Skip to content

The branch-management command line (#1725) - #1727

Merged
suleimansh merged 2 commits into
mainfrom
1725-branch-management-cli
Aug 27, 2026
Merged

The branch-management command line (#1725)#1727
suleimansh merged 2 commits into
mainfrom
1725-branch-management-cli

Conversation

@suleimansh

Copy link
Copy Markdown
Contributor

Step 2 of #1725: the package's operations as a command line, and the daemon puts it on every agent's PATH. Step 1 was #1726.

The command

branch-management, the package's bin, over the same functions the daemon calls:

command does
create <id> [--base <ref>] checkout on a fresh tf-agent-<id>, dependencies linked in, branches/ links refreshed
attach <id> <branch> checkout for a continued agent on an existing branch
name <name> renames this checkout's branch to tf-<name>; prints the name it got
status [path] branch, clean?, on the remote?
list [--sizes] every checkout under .the-framework/branches/
remove <id> [--no-push] the reclaim rule; links refreshed after
prune [--no-push] remove for every checkout; reports removed and kept-with-reason

Contract: one JSON document on stdout; a refusal ({ ok: false, reason }) or a git failure also puts one line on stderr and exits 1; a command that cannot be read gets the usage and exits 2. The project is the checkout whose .the-framework/branches/ the working directory is under, else the checkout itself — so the commands name the same project from inside an agent's checkout, and a project that is itself a linked worktree keeps its own checkouts. Outside a repo: not-a-repo.

name is new logic, not a lift, and the framework's session-name handler now uses it too (renameAgentBranch is gone): a rename of the current branch (no second branch, nothing to clean up later), refused unless the branch is one The Framework minted (an agent in the user's checkout can never rename main) and unless the name is not one of ours (data, agent-…), suffixed -2, -3, … when taken locally or on the remote, a no-op when asked again for the name the checkout already carries, and a rename lost to a sibling's race takes the next suffix.

One consequence in reclaim: a branch renamed after it was pushed still tracks its old remote name; that copy is the branch's own and no longer counts as "another name holds it", so such a branch is pushed under its new name instead of deleted.

createCheckout / attachCheckout are the one sequence (worktree, dependencies linked, links refreshed) behind both the daemon's allocation and the CLI.

The daemon

childEnv puts the package's bin/ first on the spawned agent's PATH (CLI_BIN_DIR, resolved beside dist/ so the same path holds installed). The driver spawns claude with process.env, so the agent's shell inherits it. This covers every agent the daemon starts on its machine; an actions or web run executes elsewhere and gets no PATH — step 3's SKILL.md has to say so, or those targets need their own install.

Tests

  • Package: cli.test.ts, 22 tests against real git — every command, the ids, the suffix rules, reserved names, a linked-worktree project, refusals, usage, a git failure, and the executable run by name from CLI_BIN_DIR; a rename-race unit test; a reclaim test for the renamed-after-push case.
  • Framework: a stub agent records the PATH it was spawned with; the test asserts the bin dir comes first and runs branch-management list through that PATH, which reports the checkout the daemon allocated.
  • Guards broken on purpose (the PATH prepend, the suffix loop, the link refresh after remove): each test went red.

Package 113, framework 1553 + 864, dashboard tsc clean, pnpm build ok. The package's test script builds dist/ first, because the executable test runs the real shim.

Not a user-facing feature yet

FEATURES-SPEC.md is unchanged on purpose: nothing tells the agent or the user the command exists. It becomes a feature with step 3's SKILL.md. Also deliberate: the CLI does not know whether an agent is running or what its handoff allows — remove/prune are for the caller who knows (the plan's rule); SKILL.md should hand the agent name and status only.

Not in this PR

Step 3 (SKILL.md, dropping setSessionName / set-session-name, the prompt's branch step) waits for the answer to #1725's second question. Windows: an extensionless bin/branch-management and a PATH key are POSIX assumptions, like the rest of the daemon.

🤖 curated · Fable 5, effort high

Step 2 of #1725: the package's operations as a CLI for the agent's shell —
create, attach, name, status, list, remove, prune — JSON on stdout, the
reason on stderr, exit 1 for a refusal and 2 for a usage error. The daemon
puts the package's bin directory first on every spawned agent's PATH.
Naming is a rename of the checkout's branch (tf-agent-<id> -> tf-<name>),
refused for a branch The Framework did not mint, suffixed when taken.
… a renamed branch's own upstream

- The framework's session-name handler names the branch by the package's
  rule (nameBranch); renameAgentBranch is gone.
- The project is the checkout whose .the-framework/branches/ the cwd is
  under, not git's common dir: a project that is itself a linked worktree
  keeps its own checkouts.
- `name`: reserved names (data, agent-…) refused; asking again for the name
  the checkout already carries (suffixed or pushed) is a no-op; a rename lost
  to a sibling's race takes the next suffix.
- reclaim: a branch's tracked upstream is its own copy — a branch renamed
  after a push is pushed under its new name, never read as empty.
- createCheckout/attachCheckout: one sequence for the daemon and the CLI.
- CLI: prototype keys are not commands; id checked before the project is
  looked for; prune reconciles once; only git's 'not a git repository' reads
  as not-a-repo.
- SPEC wording: the PATH is for agents the daemon starts on its machine.
@suleimansh
suleimansh merged commit 9b96d44 into main Aug 27, 2026
2 checks passed
@suleimansh
suleimansh deleted the 1725-branch-management-cli branch August 27, 2026 18:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant