Skip to content

Add bash and zsh completions - #60

Open
leogdion wants to merge 1 commit into
release-1.0.3from
51-completions
Open

Add bash and zsh completions#60
leogdion wants to merge 1 commit into
release-1.0.3from
51-completions

Conversation

@leogdion

@leogdion leogdion commented Aug 21, 2026

Copy link
Copy Markdown
Member

Adds bash and zsh completions for git trees.

The dispatch naming (most likely thing to review wrong)

The tool installs on PATH as git-trees and is invoked as git trees. Two
different shells resolve that subcommand two different ways, and both names are
load-bearing:

  • bash — bash-completion's git driver does
    local completion_func="_git_${command//-/_}", so git trees dispatches to a
    function named _git_trees (underscores, not dashes). Verified against
    /Library/Developer/CommandLineTools/usr/share/git-core/git-completion.bash:3830.
  • zsh_git does _call_function ret _git-$words[1], so git trees
    dispatches to a file named _git-trees (dashes) found on fpath.

Renaming either one silently disables completion with no error, so both files
carry a comment explaining why the name cannot change, and the README says so
too.

Each file also wires up direct invocation of the standalone git-trees binary
(complete -F in bash, the #compdef git-trees tag in zsh), so completion
works whether the user types git trees or git-trees.

What is completed

Subcommands at position 1 (init root add track list ls rm clean sync prune help), then each subcommand's own flags:

command flags
init --host --dir
root --agents
add --print-path --no-push
track --no-push
list / ls --json
rm --apply
clean --merged --gone --apply
sync --pull --ff-only --rebase
prune --dry-run

rm completes branch and worktree names derived from git itself
(git for-each-ref refs/heads plus git worktree list --porcelain), never a
hardcoded list. Worktree directory names are branch names slugged /-, so
the two sets overlap heavily and both files dedupe. The bare container root
(trees-bare.git) is filtered out — git lists it as a worktree but it is not a
removable target.

Every git call is silenced and short-circuited: completing outside a repository
returns an empty list rather than erroring or hanging in the user's prompt.
There is a smoke assertion for exactly that.

sync / prune anticipate sibling PRs

sync [worktree] [--pull] [--ff-only|--rebase] and prune [--dry-run] are
being added concurrently in #50 and #55. They are included here so the
completions are correct for the release as a whole. This PR merges after those
two, so it may need a rebase on release-1.0.3 first — the completions
themselves need no change either way, since they do not read anything out of
git-trees at runtime.

Verified

bash -n on all four bash files, shellcheck -s bash on all four,
zsh -n completions/_git-trees, and tests/smoke.sh ./git-trees all pass
clean.

Beyond the linters, the bash completion was exercised for real: sourcing
bash-completion's git script plus this file into a non-interactive bash,
confirming _git_trees is defined, and driving COMP_WORDS/COMP_CWORD
through it. Every row of the table above was checked, plus the empty-and-quiet
behavior outside a repo. Those probes are now part of tests/smoke.sh so they
run in CI on both runners.

For zsh, zsh -n passes and a compinit load test confirms the dispatch wiring
resolves: with completions/ on fpath, _comps[git-trees] resolves to
_git-trees and the function autoloads, defining its helpers and running its
_arguments specs. Full interactive match capture was not possible in this
environment — zsh/zpty here does not deliver keystrokes to ZLE (a trivial
control-key-bound widget never fires), and _arguments refuses to run outside a
real completion context. That limitation is the sandbox's, not the file's, and
is called out rather than glossed over.

Why the zsh file is excluded from CI linting

completions/git-trees.bash is added to both the bash -n and shellcheck
steps. completions/_git-trees is added to neither, deliberately: #compdef,
_arguments, ${(f)...} and friends are zsh syntax that is not valid bash, and
including it would fail both steps. It is covered by zsh -n locally and by the
smoke test asserting install.sh places it byte-identical to the source.

Install and docs

install.sh copies both files to ~/.config/git-trees/completions/ following
the existing AGENTS.md.template shape — a secondary artifact with a
no-overwrite guard — then prints where each landed and the one line needed to
activate it. A user who edits an installed copy keeps it across reinstalls;
there are smoke assertions for both the install and the guard. Every existing
install.sh behavior is preserved, and the edit is additive and tightly scoped so
it should merge cleanly with the curl | bash bootstrap work in #54.

README.md gains a ### Shell completions subsection under ## Install
covering both shells, including what to do manually if you installed via the
curl path rather than install.sh.

Closes #51

🤖 Generated with Claude Code


Release coordination (v1.0.3)

One of five PRs into release-1.0.3 (#56 prune, #58 sync, #60 completions, #59 curl install, #57 Homebrew). All five are green on CI (smoke on Linux + macOS).

Suggested merge order: #56#58#60#59#57. This PR merges cleanly against every other branch.

⚠️ Verification gap: zsh is structurally verified only

The bash completion is fully exercised — sourced against the system git-completion.bash, with real COMPREPLY output confirmed for every subcommand and flag set. The zsh side is not. zsh -n passes and compinit resolves the dispatch (_comps[git-trees]_git-trees), but no actual tab-completion was ever driven through it: that needs real ZLE, and zsh/zpty in the sandbox would not deliver keystrokes to it. Please tab-test git trees <TAB> in a real zsh before merging.

Also note this PR anticipates #58 and #56: sync and prune are already in both completion files with their flags. If either of those PRs changes a flag name before merging, these lists need to follow.

Note: CodeRabbit skipped all five — "reviews are disabled for this base branch." These have not had automated review; that would come when release-1.0.3 merges to main.

The CHANGELOG is deliberately excluded from every PR — it needs the merged PR URLs, so it lands as one commit on release-1.0.3 before tagging v1.0.3.

Adds completions/git-trees.bash and completions/_git-trees covering every
subcommand and its own flags, with branch and worktree names derived from git
for `rm`.

The filenames and function names are load-bearing. bash-completion's git driver
dispatches `git <cmd>` to `_git_<cmd>` with dashes turned into underscores, so
`git trees` requires a function named `_git_trees`. zsh's `_git` dispatches via
`_call_function ret _git-$words[1]`, so it requires a file named `_git-trees`
on fpath. Both files also wire up the standalone `git-trees` binary.

install.sh copies both files to ~/.config/git-trees/completions/ using the same
no-overwrite guard already used for AGENTS.md.template, and prints the
activation line for each shell.

CI gains completions/git-trees.bash in both the `bash -n` and `shellcheck`
steps. completions/_git-trees is deliberately excluded from both: `#compdef`
and `_arguments` are zsh syntax and are not valid bash.

Closes #51

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 666f82e1-6271-4e97-9c4f-6b8087fd48d8

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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