Skip to content

[F9] nous clean --orphaned to remove stale nous-exp-* worktrees and branches #254

@sriumcp

Description

@sriumcp

Problem

When a nous run is killed mid-iteration (e.g., via pkill after a nous stop that didn't fire fast enough), the experiment worktree at <target_repo>/.nous-experiments/iter-N-<id>/ and its associated branch nous-exp-iter-N-<id> are left behind. nous didn't clean them up because it didn't get to run its own teardown.

The user must manually run:

git -C <target_repo> worktree remove --force .nous-experiments/<id>
git -C <target_repo> branch -D nous-exp-<id>

Across many iterations / multiple killed runs, these orphans accumulate.

Desired behavior

A new command:

nous clean --orphaned [--target-repo <path>]

That:

  1. Detects worktrees under <target_repo>/.nous-experiments/ matching the iter-* pattern.
  2. For each: looks up the corresponding nous run state (e.g., is the run_id still active in ~/.nous/state/?).
  3. If the run is dead/aborted/completed and the worktree is not actively in use, removes it (with --force) and deletes the matching branch.
  4. Prints a summary of what was removed.

Variants:

nous clean --campaign <run_id>     # remove worktrees specific to one campaign
nous clean --dry-run               # show what would be removed without doing it

Could also be invoked automatically at the start of nous run for the same run_id, removing any orphans from prior aborted runs of that same campaign.

Suggested implementation sketch

  1. Add a clean subcommand to orchestrator/cli.py.
  2. Walk <target_repo>/.nous-experiments/, list git worktree list --porcelain, intersect with branches matching nous-exp-*.
  3. For each candidate, check whether the originating run is dead (state file missing or marked completed/aborted).
  4. Remove via git worktree remove --force <path> and git branch -D <branch>.
  5. Add --dry-run, --campaign <id>, and --target-repo <path> flags.
  6. Document in nous --help output.

Acceptance criteria

  • nous clean --orphaned removes worktrees and branches for completed/aborted runs.
  • --dry-run prints what would be removed without acting.
  • --campaign <id> scopes cleanup to a single campaign.
  • Tests cover (a) clean run with no orphans (no-op), (b) clean run with one orphan (removed), (c) active worktree (NOT removed).
  • Friction report F9 row in the tracking issue checks off.

Severity

LOW — workaround is two git commands, but accumulates over time.

Source

friction-report.md F9, paper-memorytime-mirage campaign (2026-05).


Part of friction-report tracking issue #245.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestfriction-reportFrom external campaign-author friction reports

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions