The #113 sweep rested on CLAUDE.md's premise that rtk either filters or passes through unchanged, so prefixing is always safe. Measured against rtk 0.42.4, that premise is false for several of the commands the sweep prefixed, and two skills were left giving wrong answers silently. Why: - `rtk git worktree list --porcelain -z` discards both flags and renders its own format. The `locked`/`lock_reason` fields git-worktrees Step 2 must emit are absent entirely, and paths under $HOME are abbreviated to `~/`. - `rtk git branch --list <name>` prints a phantom `* ` line even when nothing matches, so git-branches' stated ambiguity test — "output from both means the name is ambiguous" — reported every name as ambiguous. `tag --list` is a clean passthrough, so only one half broke. - `rtk git diff --name-only`/`--name-status` append a `Changes:` trailer to output documented as "one per line"; `--word-diff` emits none of the `[-removed-] {+added+}` markers its table describes; `rtk git log -L` truncates each line at ~72 chars, on the one command whose purpose is showing line content. - `rtk git stash pop` prints only `FAILED: git stash pop`, swallowing the conflict diagnostic and retained-entry message the surrounding prose tells the agent to rely on. Implementation notes: - Eleven sites reverted to bare `git`, each carrying its reason inline so the next sweep does not undo it. `mergetool` and `rebase -i` are reverted on clause 3's interactive limb only: the TTY defect does not reproduce — rtk filters exactly twelve subcommands and execs the rest — and ADR-0023 records that measurement rather than a convenient one. - ADR-0023 states the rule repo-wide with a third clause: a command whose output the skill parses, or which is interactive, stays bare. `plugins/git/README.md` is reduced to a pointer; its claim that gitea skills "contain no git/rtk mentions at all" was false, and its citation of `hard-rules.md` pointed at a file containing no occurrence of "rtk". - Eight gitea sites swept, all verified byte-identical passthroughs first. - `scripts/check-rtk-prefix.sh` gates clause 1. Run against main's pre-sweep corpus it reports 99 findings including every gitea site, so it would have caught the drift #113 was filed about. Impact: the gate covers clause 1 only, in shell-tagged fences and the opening span of Run cells. Clause 2 is not gateable — "Run `git switch`" and "`git switch` refuses" are the same tokens — and prose bullets are invisible to it. Both limits are recorded in gates.md rather than left implied. Refs: #113 ADR: 0023 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EeH8SCbcrCAQrtymkNuhKP
3.9 KiB
name, description, metadata
| name | description | metadata | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| git-branches | Use when creating, switching, deleting, renaming, tracking, merging, or comparing local git branches under GitHub Flow or Gitflow. Not writing or rewriting commits -> `git-commits`. Not history inspection -> `git-history`. Not a Gitea remote's branches -> `gitea-branches`. |
|
Gotchas
- Uncommitted changes abort a switch.
git switchrefuses rather than clobbering conflicting local edits. Offer to stash and retry — forcing the checkout past it is how work disappears. - A branch and a tag can carry the same name. Detect it before acting —
git branch --list <name>(bare, notrtk: rtk prints a phantom*line even on no match, which reports every name as ambiguous — ADR-0023) andrtk git tag --list <name>; output from both means the name is ambiguous. Prefergit switchovergit checkout, and where a command accepts either ref, disambiguate withrefs/heads/<name>orrefs/tags/<name>. mainandmasterare a refusal, not a gate. Force-pushing, force-deleting, or renaming them is rejected even when the caller passesconfirm: true— no flag makes the remote's history recoverable. Offer a new branch instead.
Step 1 — Determine the branching pattern
Read branching_pattern from the git plugin config (.claude/plugins/git/config.json; the plugin root's config.example.json shows the shape). Default: github-flow. With no config, infer Gitflow from the presence of a develop or release/* branch, and GitHub Flow otherwise.
The two patterns are not mixable, and the wrong merge rule silently damages history. If the action touches a base branch, a name prefix, or a merge rule, read references/branch-patterns.md.
Step 2 — Dispatch on the action
| Action | Reference |
|---|---|
| create, switch, delete, rename, track, list, get-intent, stash | references/branch-operations.md |
| merge a branch, resolve merge conflicts | references/merging.md |
| compare two branches, find their divergence | references/comparing-branches.md |
Load only the file the action needs. A destructive action still passes Step 3 first.
Step 3 — Gate destructive operations
Before any delete or force-delete that loses history:
- Does the branch track a remote? Warn if so.
- Are there unpushed commits on it? Warn if so.
- Did the caller pass
confirm: true? Fail if not — for a human caller, prompt interactively instead of failing.
These gates are passable. The main/master refusal in Gotchas is not.
Step 4 — Set tracking
A new branch's first push must be rtk git push -u origin <branch>. The push itself is git-remotes' — every remote-side gate lives there, which is why Step 2's remote-delete row hands off the same way — but the upstream requirement originates here, so carry it in the handoff. Without an upstream, later pushes and pulls either fail or silently target the wrong remote branch, and the caller has no way to tell which happened.
Step 5 — Return a structured result
Return every operation in this shape rather than prose, including failures — a calling agent chains its next operation on the result and cannot parse a sentence.
{
"success": true,
"action": "create|switch|delete|rename|track|list|get-intent",
"branch": "<name>",
"message": "descriptive message",
"intent": "<intent if tracked>",
"tracking": "origin/<branch, if set>",
"error": "<error message if success=false>",
"suggestion": "<recovery suggestion if applicable>"
}
When the failure is uncommitted local changes, set "suggestion": "stash changes and retry" so the caller can offer recovery rather than surfacing a dead end.
When a calling agent supplies a structured request rather than prose, read references/orchestrator-contract.md for the request schema.