Added git-manager, updated READMEs

This commit is contained in:
Henner M. Kruse
2026-08-04 10:45:25 +02:00
parent c774df7ad7
commit e485d33f00
13 changed files with 830 additions and 72 deletions
+122
View File
@@ -0,0 +1,122 @@
# 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.