Add opt-in raw-git nudge hook, independent of anti-chaining hook

Forces a normal confirmation prompt (never a silent block, never a silent
allow) when Bash runs raw git instead of git_cmd.sh, worded more
insistently when the subcommand is one the wrapper already supports.
Raw git stays a valid fallback for unsupported subcommands and
unregistered repos - a hard deny would remove that fallback entirely.

Also documents in SKILL.md that repo ambiguity (which registered repo is
meant, or none at all) must be resolved by asking the user rather than
guessing - a hook only sees the literal command string, not the
conversation, so that judgment can't live in the hook itself.
This commit is contained in:
Henner M. Kruse
2026-08-04 13:58:30 +00:00
parent 47595ff160
commit 1d0b66df2e
5 changed files with 173 additions and 19 deletions
+34 -5
View File
@@ -28,11 +28,12 @@ git_cmd.sh <subcommand> [--repo <name>] [-- <git-args...>]
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
`fetch`, `remote`, `branch`, `checkout`, `add`, `commit`, `push`, `pull`,
`tag`. Anything else (`reset`, `rebase`, `stash`, `merge`, `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 can rewrite or discard history/working-tree state in ways
that are hard to reverse, so they should go through a normal confirmation
prompt rather than being auto-approved.
## Setup
@@ -56,6 +57,10 @@ This will:
silent pass-through) any time a Bash command contains shell chaining or
substitution characters (`&&`, `;`, `|`, `` ` ``, `$(...)`) — see
"The anti-chaining hook" below.
4. Ask whether you also want a second, independent hook installed: one that
forces the same kind of normal confirmation prompt any time a Bash
command runs raw `git` instead of `git_cmd.sh` — see "The raw-git nudge
hook" below.
## Usage examples
@@ -110,6 +115,30 @@ 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).
## The raw-git nudge hook
Optional, offered during `/git-manager:setup`, independent of the
anti-chaining hook above (you can install neither, either, or both). If
installed, it watches every Bash command and, when it sees raw `git` used
instead of `git_cmd.sh`, forces the normal confirmation prompt instead of
letting whitelist matching decide — the same "never silently block, never
silently allow" behavior as the anti-chaining hook.
This is deliberately **not** a hard block. Raw git stays a legitimate
fallback for subcommands `git_cmd.sh` doesn't support (`stash`, `merge`,
`rebase`, `reset`, ...) and for repos that aren't registered yet — a full
block would remove that fallback entirely. What the hook does instead is
make sure raw git is never invisible: every time it's used, it's a
confirmed, visible choice, worded more insistently when the subcommand is
one `git_cmd.sh` already supports (in which case there's rarely a good
reason to have bypassed it) and more permissively otherwise.
What this hook can't do — and isn't trying to do — is figure out from the
surrounding conversation whether raw git was actually the right call here.
It only ever sees the literal Bash command text, not the request that led
to it; that kind of judgment is the skill's own job (see `SKILL.md`), and
this hook is just the backstop for when that judgment gets skipped.
## What's deliberately *not* included
- No `Bash(git:*)` — that would also permit `git reset --hard`, `git clean