The branch-management command line (#1725) - #1727
Merged
Merged
Conversation
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.
This was referenced Aug 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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'sbin, over the same functions the daemon calls:create <id> [--base <ref>]tf-agent-<id>, dependencies linked in,branches/links refreshedattach <id> <branch>name <name>tf-<name>; prints the name it gotstatus [path]list [--sizes].the-framework/branches/remove <id> [--no-push]prune [--no-push]removefor every checkout; reports removed and kept-with-reasonContract: 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.nameis new logic, not a lift, and the framework'ssession-namehandler now uses it too (renameAgentBranchis 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 renamemain) 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/attachCheckoutare the one sequence (worktree, dependencies linked, links refreshed) behind both the daemon's allocation and the CLI.The daemon
childEnvputs the package'sbin/first on the spawned agent's PATH (CLI_BIN_DIR, resolved besidedist/so the same path holds installed). The driver spawnsclaudewithprocess.env, so the agent's shell inherits it. This covers every agent the daemon starts on its machine; anactionsorwebrun executes elsewhere and gets no PATH — step 3's SKILL.md has to say so, or those targets need their own install.Tests
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 fromCLI_BIN_DIR; a rename-race unit test; a reclaim test for the renamed-after-push case.branch-management listthrough that PATH, which reports the checkout the daemon allocated.remove): each test went red.Package 113, framework 1553 + 864, dashboard tsc clean,
pnpm buildok. The package's test script buildsdist/first, because the executable test runs the real shim.Not a user-facing feature yet
FEATURES-SPEC.mdis unchanged on purpose: nothing tells the agent or the user the command exists. It becomes a feature with step 3'sSKILL.md. Also deliberate: the CLI does not know whether an agent is running or what its handoff allows —remove/pruneare for the caller who knows (the plan's rule); SKILL.md should hand the agentnameandstatusonly.Not in this PR
Step 3 (
SKILL.md, droppingsetSessionName/set-session-name, the prompt's branch step) waits for the answer to #1725's second question. Windows: an extensionlessbin/branch-managementand aPATHkey are POSIX assumptions, like the rest of the daemon.🤖 curated · Fable 5, effort high