Skip to content

id(cli): space-form --new swallows the subcommand as the instance name — the documented id --new serve creates .iroh/serve/ and starts the REPL instead of serving under a random name #3144

Closed

Description

@dezren39

Problem

id --new is declared with an optional value (num_args = 0..=1), and clap greedily consumes the next token as that value — including when the next token is the subcommand. The documented random-name example therefore does the opposite of what it says:

  • pkgs/id/src/cli.rs:170-171 — #[arg(long, global = true, num_args = 0..=1, default_missing_value = "", value_name = "NAME", conflicts_with = "data_dir")] pub new: Option<String>
  • pkgs/id/src/cli.rs:162-168 — the doc examples: id --new my-dev serve --port 0, id --new serve ("Random name (auto-generated)"), id --new my-dev list.
  • pkgs/id/src/cli.rs:189-191 — command: Option<Command>; "If None, the REPL is started." main.rs:147 dispatches None => run_repl(None).
  • pkgs/id/src/main.rs:88-112 — a non-empty --new name creates .iroh/<name>/ and bails if it already exists.

So id --new serve creates an instance literally named serve under .iroh/serve/ and starts the interactive REPL — it does not start a server, and it does not use a random name. A second run of the same documented command then fails outright: "instance directory already exists: .iroh/serve (use --data-dir to reuse an existing directory)". The same swallowing hits every bare subcommand: id --new list, id --new id, id --new repl, … all become instance names with no subcommand.

Evidence (verified this run)

Laptop probe (~/git/fleet/probe-2026-10-31-laneA-clap-new/): a minimal clap 4.6.7 derive struct replicating the exact Cli shape (global --data-dir with conflicts_with = "new", global --new with num_args = 0..=1 + default_missing_value = "", and an optional subcommand enum), run against the pinned clap version in pkgs/id/Cargo.lock (clap 4.6.7):

--new serve        => new=Some("serve")   command=None        BUG (documented as random-name serve)
--new my-dev serve => new=Some("my-dev")  command=Some(Serve) control, works
--new list         => new=Some("list")    command=None        BUG (any bare subcommand is swallowed)
--new              => new=Some("")        command=None        random name, as intended
--new=serve        => new=Some("serve")   command=None        explicit name via =, expected
serve --new        => new=Some("")        command=Some(Serve) trailing form works

Coverage gap that let this ship: every --new integration test uses the = form (pkgs/id/tests/cli_integration.rs:3696ff — --new=, --new=test-instance, --new=dup, --new=../escape); no test exercises a space-form --new followed by a subcommand.

Why it matters

--new is the documented way to spin up a throwaway instance, and its own help text gives the broken command as the example. A user following the docs gets an interactive REPL in a directory named after their subcommand instead of a running server, and the leftover .iroh/serve/ directory then makes the same command fail on retry. The failure is silent about the real cause — nothing says the subcommand was eaten as a name.

Acceptance criteria

  • id --new serve behaves as documented: a randomly-named instance directory is created and the serve subcommand runs. More generally, a bare token that names a subcommand is never consumed as the --new value (e.g. --new list, --new id likewise).
  • The forms that work today keep working: --new alone (random name), --new=<name> <cmd>, --new <name> <cmd> (named instance), and a trailing --new after the subcommand.
  • Help text / doc examples and the actual parsing agree for every form shown at cli.rs:152-168.
  • New integration tests in pkgs/id/tests/cli_integration.rs cover the space forms — at minimum --new serve-style subcommand non-consumption (using a fast subcommand such as id) and --new <name> <cmd> — alongside the existing =-form tests.

Activity

  1. added
    queue/queuedHas a queued task in the Supabase agent queue
    source/creatorFiled by the new-issue-creator job
    task/triageQueue packet kind: verify, reproduce, and route this item
    priority/lowNice to have; do when convenient
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    app/idPackage/app: id (pkgs/ or apps/ in this repo)
    effort/sSmall: expected under 2 hours of work
    on Oct 31, 2026
  2. dezren39 commented on Oct 31, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator job (new-issue-creator-code-a)
    • Session / ID: new-issue-creator-code-a run 2026-10-31T16:50Z
    • Found via: filed this run
    • Task: Filed this issue — the space-form id --new swallows the following subcommand as the instance name (cli.rs:170-171, num_args = 0..=1), so the documented id --new serve (cli.rs:165) creates .iroh/serve/ and starts the REPL (main.rs:147) instead of serving under a random name, and a repeat run then fails with "instance directory already exists". Verified this run with a minimal clap 4.6.7 probe on the laptop replicating the exact Cli shape (--new serve → new=Some("serve"), command=None; --new list likewise; --new my-dev serve, bare --new, and trailing serve --new all correct). Enqueued as a triage packet in queue repo-health-code-pilot.
    • Expectation: effort/s — make the parse honour the documented forms (a subcommand token is never the --new value) and add space-form integration tests; every existing --new test uses the = form.
    • Links: evidence issue body (hidden_files/issue-code-new-flag-subcommand-body.md); probe laptop ~/git/fleet/probe-2026-10-31-laneA-clap-new/
  3. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  4. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 1, 2026
  5. 5 remaining items

  6. added
    task/small-fixQueue packet kind: bounded fix with reproduction and targeted tests
    queue/queuedHas a queued task in the Supabase agent queue
    and removed
    work/assignedQueue worker lifecycle state
    on Nov 1, 2026
  7. dezren39 commented on Nov 1, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · handed off

  8. added
    queue/claimedQueue worker lifecycle state
    work/assignedQueue worker lifecycle state
    and removed
    queue/queuedHas a queued task in the Supabase agent queue
    on Nov 2, 2026
  9. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · picked up

  10. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/idPackage/app: id (pkgs/ or apps/ in this repo)effort/sSmall: expected under 2 hours of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/lowNice to have; do when convenientsource/creatorFiled by the new-issue-creator jobtask/small-fixQueue packet kind: bounded fix with reproduction and targeted tests

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions