Skip to content

gh vibe completion

Prints a tab-completion script for gh vibe. Subcommands, per-subcommand flags, enum values (--type, --state, --shell), and open PR / issue numbers are all wired through fish’s and zsh’s completion engines.

Terminal window
gh vibe completion [--shell=<fish|zsh>]

Without --shell, the calling shell is auto-detected from $SHELL. If the detected shell is not yet wired up (e.g. bash today), the command exits 2 — pass --shell=fish or --shell=zsh explicitly to emit a snippet regardless of the host shell.

Terminal window
# persistent — installs once into fish's completions dir
gh vibe completion --shell=fish > ~/.config/fish/completions/gh-vibe.fish
# or, for the current session only
gh vibe completion --shell=fish | source

Source gh vibe completion --shell=zsh after the official GitHub CLI completion (eval "$(gh completion -s zsh)"), so the gh-vibe wrapper can capture the original _gh function before compdef-overwriting it. Reverse order leaves gh vibe completions inert (or, worse, makes gh’s own zsh completion stomp the wrapper later).

Pre-requisite: the gh-vibe wrapper delegates every non-gh vibe completion request to the saved _gh. If gh’s official zsh completion is not installed at all in your ~/.zshrc, then gh vibe … itself will still work, but gh pr <TAB>, gh repo <TAB>, and other stock gh subcommands will fall back to plain filename completion (_files). To get the full experience, always load gh’s completion first; the recommended snippets below already do this.

The first line of the emitted snippet is #compdef gh-vibe gh; zsh treats this comment specially when the file lives on $fpath, registering the function for both commands automatically.

Terminal window
# persistent — drop into a dir on $fpath, then re-run compinit
mkdir -p ~/.config/zsh/completions
gh vibe completion --shell=zsh > ~/.config/zsh/completions/_gh-vibe
# ~/.zshrc (load order matters: gh first, gh-vibe wrapper second, compinit last)
fpath=(~/.config/zsh/completions $fpath)
eval "$(gh completion -s zsh)"
autoload -U compinit && compinit
# or, current session only
eval "$(gh completion -s zsh)"
eval "$(gh vibe completion --shell=zsh)"

After that, every gh vibe ... invocation gets contextual completion (the same is true under fish):

Terminal window
gh vibe <TAB> # review issue list clean shell-setup completion
gh vibe review <TAB> # open PR numbers with titles
gh vibe issue <TAB> # open issue numbers with titles
gh vibe issue --type <TAB> # feat fix docs chore refactor test perf
gh vibe clean --state <TAB> # merged closed merged,closed

gh vibe review <TAB> and gh vibe issue <TAB> shell out to gh pr list / gh issue list and surface open items with their titles as completion descriptions. Errors (offline, non-repo directory, missing auth) are silenced — TAB simply yields no suggestions rather than spamming stderr.

Results are cached for 30 seconds in a per-repo tmpfile so back-to-back TAB presses don’t burn a gh round-trip each time. Each repo has its own cache key (derived from git rev-parse --show-toplevel), so checkouts of different repos never share suggestions. The cache filename format is shared between fish and zsh, so users who switch between shells get cache hits across both. The cache file is chmod 600’d after each write because PR / issue titles on private repos may contain sensitive context.

Even on a cache hit, each TAB still forks a few small processes (git rev-parse to find the repo toplevel, stat for the cache mtime, plus the cat of the cache file). zsh additionally uses $EPOCHSECONDS (from zsh/datetime) when available so the mtime comparison doesn’t fork date +%s on every keystroke. On modern hardware these costs are negligible, but on low-power WSL or older macOS they can be felt as a slight pause. If you want fewer gh round-trips at the cost of seeing slightly staler PR titles, set _GH_VIBE_COMPLETION_TTL — the snippet only assigns the 30-second default when the variable is unset, so exporting it before or after sourcing both work:

Terminal window
# zsh — extend the cache TTL to 5 minutes
_GH_VIBE_COMPLETION_TTL=300
eval "$(gh vibe completion --shell=zsh)"
Terminal window
# fish — same idea (before or after sourcing both work)
set -gx _GH_VIBE_COMPLETION_TTL 300
gh vibe completion --shell=fish | source
ShellStatus
fish
zsh
bash🚧 planned
pwsh (PowerShell 7+)🚧 planned

gh vibe completion --shell=bash (and the other not-yet-wired-up shells) exits 2 with an explanatory message rather than emitting nothing.

The two integrations are independent and can be loaded together:

~/.config/fish/config.fish
gh vibe shell-setup --shell=fish | source
# ~/.config/fish/completions/gh-vibe.fish (or sourced once at startup)
gh vibe completion --shell=fish | source

Each uses its own load-once sentinel (_GH_VIBE_SHELL_SETUP_LOADED vs _GH_VIBE_COMPLETION_LOADED), and the helper function namespace (__ghvibe_*) is unique to completion.

fish: remove the file from ~/.config/fish/completions/ (or the | source line from your config) and reload the shell.

zsh: remove the _gh-vibe file from your completions dir (or the eval "$(gh vibe completion --shell=zsh)" line from ~/.zshrc) and reload the shell. Stale compdef cache may need rm -f ~/.zcompdump* followed by a fresh compinit.

The cached PR / issue lookups in $TMPDIR/gh-vibe-completion-* expire on their own; deleting them manually is safe but unnecessary.

A few user-visible behaviours can’t be covered by the automated test suite because they depend on a real interactive shell. Run through these in a real terminal before cutting a release that touches completion.ts:

  • zsh, three entry points: in a zsh session with eval "$(gh completion -s zsh)" loaded first and eval "$(gh vibe completion --shell=zsh)" loaded second:
    • gh vibe <TAB> lists the six subcommands with descriptions.
    • gh vibe review <TAB> lists open PR numbers with titles (run inside a repo with at least one open PR).
    • gh-vibe <TAB> (the binary invoked directly) lists the same six subcommands.
  • zsh, flag and enum completion: in the same session, exercise the parts most likely to regress when _arguments declarations are edited:
    • gh vibe list --<TAB> lists --json, --stale, --limit, --allow-no-default-branch.
    • gh vibe clean --state <TAB> offers the three values merged, closed, merged,closed (the composite value is the one most likely to break under future refactors).
    • gh vibe completion --shell <TAB> offers every value in COMPLETION_SUPPORTED_SHELLS.
  • zsh, non-vibe gh fallthrough: in the same session, gh pr <TAB>, gh repo <TAB>, and gh issue <TAB> should still complete via gh’s own zsh completion — i.e. the wrapper must not have eaten them.
  • fish, dynamic completion: gh vibe review <TAB> and gh vibe issue <TAB> should show PR / issue numbers with titles as descriptions, in an actual repo.
  • fish, —shell enum on completion: gh vibe completion --shell <TAB> must offer every value in COMPLETION_SUPPORTED_SHELLS (regression guard for the enum diverging from the canonical list).