Files
skill-repo/vendor/claude-code/plugins/git-manager

git-manager

Run git commands across one or more repositories — your code, an Obsidian vault kept under version control, whatever else — without Claude Code needing to cd into a directory or chain shell commands together. That matters because chained commands (cd path && git ..., git add && git commit && git push) are exactly what breaks Bash permission whitelists: either the whole chain needs separate approval every time, or — depending on the Claude Code version — a chain can slip through on a rule that was only meant to cover one piece of it. This plugin sidesteps the problem instead of fighting it: there's simply never a reason to cd or chain.

What it does

All git operations go through a single script, git_cmd.sh:

git_cmd.sh <subcommand> [--repo <name>] [-- <git-args...>]
  • No cd needed. Omit --repo and it operates on whatever git repository your current working directory is in — which, in a normal Claude Code session, is already the right repo. Use --repo <name> to target a different, pre-registered repository (e.g. your notes vault) without leaving your current directory.
  • No chaining needed. Each git operation is its own call to the script. Want to add, commit, and push? That's three separate calls, not one chained command — which is exactly what keeps every single one of them covered by the whitelist.
  • A fixed set of allowed subcommands: status, log, diff, show, fetch, remote, branch, checkout, add, commit, push, pull. Anything else (reset, rebase, filter-branch, arbitrary git config, ...) is rejected by the script itself, before git ever runs — not because those operations are inherently dangerous, but because they're consequential enough that they should go through a normal confirmation prompt rather than being auto-approved.

Setup

After installing the plugin:

/git-manager:setup

This will:

  1. Ask you (optionally) to register named repositories — useful if you work with more than one repo in the same session, e.g. a code repo plus a separate Obsidian vault repo. Skip this if you're fine relying on the default (current working directory).
  2. Add exactly one entry to your Claude Code permissions: Bash(<path-to-git_cmd.sh>:*) — nothing broader.
  3. Ask whether you want an additional safety net installed: a hook that forces a normal confirmation prompt (not a silent block, not a silent pass-through) any time a Bash command contains shell chaining or substitution characters (&&, ;, |, `, $(...)) — see "The anti-chaining hook" below.

Usage examples

# Current repo (no --repo needed)
git_cmd.sh status
git_cmd.sh log -- --oneline -10
git_cmd.sh add -- -A
git_cmd.sh commit -- -m "Update notes"
git_cmd.sh push -- origin main

# A different, pre-registered repo — still no cd
git_cmd.sh status --repo homelab-notes
git_cmd.sh push --repo homelab-notes -- origin main

Everything after -- is passed to git as literal arguments (not re-parsed by a shell), so quoting in commit messages etc. is safe.

Registering repositories

Repositories are looked up by name in ~/.agent-skills/git-manager/config.json:

{
  "repos": [
    {"name": "homelab-notes", "path": "/absolute/path/to/vault"},
    {"name": "dwh-pipeline", "path": "/absolute/path/to/repo"}
  ]
}

This file is entirely optional. Without any entries, --repo simply isn't available and every call operates on the current directory. Add entries any time by asking Claude to register a new repo, or by editing the file directly — writing to this file is never in the permissions whitelist, so you'll always see (and can decline) that change.

The anti-chaining hook

Optional, offered during /git-manager:setup. If installed, it watches every Bash command Claude Code is about to run (not just git ones) and, if the command contains a chaining or substitution operator, forces the normal permission prompt instead of letting whitelist matching decide. It never silently blocks anything and never silently approves anything — worst case, you get one extra confirmation prompt you didn't strictly need; best case, it catches a chained command before it runs unreviewed.

With git_cmd.sh in place, chained commands involving git shouldn't come up in the first place — this hook is a backstop for the rare cases they do anyway (or for other tools/skills in your setup that aren't as careful about it).

What's deliberately not included

  • No Bash(git:*) — that would also permit git reset --hard, git clean -fdx, git filter-branch, etc.
  • No Bash(cd:*) — removed as a category, not just discouraged.
  • No auto-approved writes to the config file — registering a repo is always a visible, confirmed step.
  • push --force is technically reachable (it's just push with extra args) since it's a normal, if consequential, part of a git workflow — it isn't specially gated beyond the normal push approval.