123 lines
5.0 KiB
Markdown
123 lines
5.0 KiB
Markdown
# 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`:
|
|
|
|
```bash
|
|
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
|
|
|
|
```bash
|
|
# 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`:
|
|
|
|
```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.
|