Allow tag in git-manager's subcommand allowlist

Tagging a commit doesn't rewrite or discard history/working-tree state,
unlike stash/merge/rebase/reset which stay excluded as a deliberate
guardrail.
This commit is contained in:
Henner M. Kruse
2026-08-04 13:35:11 +00:00
parent 6c6fc35a1f
commit 47595ff160
3 changed files with 9 additions and 7 deletions
+7 -5
View File
@@ -1,6 +1,6 @@
--- ---
name: git-manager name: git-manager
description: Manages git operations (status, log, diff, show, fetch, remote, branch, checkout, add, commit, push, pull) across one or more git repositories — including non-code repositories such as an Obsidian vault kept under version control — through a single wrapper script instead of raw shell `git`/`cd` commands. Always use this skill instead of running `git` or `cd` directly whenever the task involves checking status, committing, pushing, pulling, or otherwise managing a git repository, especially when multiple repositories are involved in the same session (e.g. a code repo and a separate notes/vault repo). description: Manages git operations (status, log, diff, show, fetch, remote, branch, checkout, add, commit, push, pull, tag) across one or more git repositories — including non-code repositories such as an Obsidian vault kept under version control — through a single wrapper script instead of raw shell `git`/`cd` commands. Always use this skill instead of running `git` or `cd` directly whenever the task involves checking status, committing, pushing, pulling, or otherwise managing a git repository, especially when multiple repositories are involved in the same session (e.g. a code repo and a separate notes/vault repo).
--- ---
# Git Manager # Git Manager
@@ -32,8 +32,8 @@ Always use:
``` ```
- `<subcommand>` must be one of: `status`, `log`, `diff`, `show`, `fetch`, - `<subcommand>` must be one of: `status`, `log`, `diff`, `show`, `fetch`,
`remote`, `branch`, `checkout`, `add`, `commit`, `push`, `pull`. Anything `remote`, `branch`, `checkout`, `add`, `commit`, `push`, `pull`, `tag`.
else is rejected by the script itself before git runs. Anything else is rejected by the script itself before git runs.
- `--repo <name>` targets a specific pre-configured repository. The script - `--repo <name>` targets a specific pre-configured repository. The script
itself (not this skill's own logic) decides what happens if it's itself (not this skill's own logic) decides what happens if it's
omitted: with exactly one repo registered in omitted: with exactly one repo registered in
@@ -71,10 +71,12 @@ Examples:
Never call `git` directly, and never use `cd` to switch into a different Never call `git` directly, and never use `cd` to switch into a different
repo before running git — use `--repo` instead. If a task genuinely needs a repo before running git — use `--repo` instead. If a task genuinely needs a
subcommand outside the allowed list (e.g. `stash`, `merge`, `rebase`, subcommand outside the allowed list (e.g. `stash`, `merge`, `rebase`,
`reset`, `tag`), say so explicitly to the user rather than working around `reset`), say so explicitly to the user rather than working around
the restriction (e.g. via `git -C` called outside this script, or editing the restriction (e.g. via `git -C` called outside this script, or editing
`.git` internals directly) — that path isn't whitelisted and existing on `.git` internals directly) — that path isn't whitelisted and existing on
purpose as a guardrail, not an oversight. purpose as a guardrail, not an oversight. Those excluded subcommands can
rewrite or discard history/working-tree state in ways that are hard to
reverse; `tag` is allowed because tagging a commit doesn't carry that risk.
## Multi-repo setup ## Multi-repo setup
+1 -1
View File
@@ -6,7 +6,7 @@ CONFIG_FILE="$HOME/.agent-skills/git-manager/config.json"
# Subcommands this skill is allowed to run. Anything not in this list is # Subcommands this skill is allowed to run. Anything not in this list is
# rejected outright by git_cmd.sh, regardless of what the caller asks for. # rejected outright by git_cmd.sh, regardless of what the caller asks for.
ALLOWED_SUBCOMMANDS=(status log diff show fetch remote branch checkout add commit push pull) ALLOWED_SUBCOMMANDS=(status log diff show fetch remote branch checkout add commit push pull tag)
is_allowed_subcommand() { is_allowed_subcommand() {
local sub="$1" local sub="$1"
@@ -1,5 +1,5 @@
{ {
"_comment": "Reference only — setup.sh generates and writes these exact rules itself, so this file is no longer read during setup. Kept here for auditing/documentation: this is what /git-manager:setup will add to your permissions.allow, with <SKILL_DIR> substituted for the real, symlink-resolved skills/git-manager path. Exactly one Bash rule — the wrapper script itself — never a generic Bash(git:*) or anything targeting cd. The wrapper script enforces its own subcommand allowlist (status, log, diff, show, fetch, remote, branch, checkout, add, commit, push, pull) and resolves repo paths only from named entries in ~/.agent-skills/git-manager/config.json, never from the current working directory or an arbitrary caller-supplied path.", "_comment": "Reference only — setup.sh generates and writes these exact rules itself, so this file is no longer read during setup. Kept here for auditing/documentation: this is what /git-manager:setup will add to your permissions.allow, with <SKILL_DIR> substituted for the real, symlink-resolved skills/git-manager path. Exactly one Bash rule — the wrapper script itself — never a generic Bash(git:*) or anything targeting cd. The wrapper script enforces its own subcommand allowlist (status, log, diff, show, fetch, remote, branch, checkout, add, commit, push, pull, tag) and resolves repo paths only from named entries in ~/.agent-skills/git-manager/config.json, never from the current working directory or an arbitrary caller-supplied path.",
"permissions": { "permissions": {
"allow": [ "allow": [
"Bash(<SKILL_DIR>/scripts/git_cmd.sh:*)", "Bash(<SKILL_DIR>/scripts/git_cmd.sh:*)",