Files
skill-repo/CLAUDE.md
T
2026-08-04 14:24:21 +00:00

6.7 KiB
Raw Blame History

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

What this repo is

skill-repo: a private collection of tool-neutral Agent Skills (SKILL.md + scripts/), currently two plugins for Claude Code:

  • git-manager — routes all git operations through one wrapper script (skills/git-manager/scripts/git_cmd.sh) so multi-repo work never needs cd or shell chaining (&&, ;, |), which is what breaks Bash permission whitelisting.
  • obsidian-vault-kb — turns an Obsidian vault into a searchable knowledge base via three wrapper scripts (vault_index.sh, vault_search.sh, vault_backlinks.sh).

There is no build, lint, or test tooling in this repo — it's shell scripts plus Markdown/JSON, exercised by running the wrapper scripts directly (e.g. skills/git-manager/scripts/git_cmd.sh status --repo <name>) or by installing the plugin in Claude Code and running its /plugin:setup command.

If you're operating from the skills local checkout wrapper

If this repo is checked out at <workspace>/repo/ with a sibling <workspace>/.claude/ holding local, un-versioned Claude Code settings (that's the standard local layout for this repo), the working directory Claude Code starts in is <workspace>, one level above this repo root — use the git-manager skill for all git operations (status, commit, push, etc.), not raw git/cd, registered there with --repo skills pointing at this directory. Raw git -C <workspace>/repo ... or cd <workspace>/repo && git ... works mechanically but bypasses the whitelisted wrapper that setup is built around.

Architecture: skills/ vs vendor/

The repo (see ARCHITECTURE.md) deliberately splits tool-neutral skill content from host-tool-specific plumbing:

.
├── skills/<name>/                       # canonical, tool-neutral — SKILL.md, scripts/, references/
└── vendor/claude-code/plugins/<name>/   # Claude Code-specific adapter
    ├── .claude-plugin/plugin.json
    ├── skills/<name> -> ../../../../../skills/<name>   (symlink, not a copy)
    ├── commands/setup.md                # -> /<name>:setup
    ├── permissions-whitelist.template.json
    └── hooks/                           # git-manager only, currently
  • skills/<name>/ is the only place skill content lives. It assumes nothing about the host tool: config is read from ~/.agent-skills/<name>/config.json, never a Claude-specific path, so the same SKILL.md works unmodified in other Agent-Skills-compatible tools.
  • vendor/claude-code/plugins/<name>/ holds everything Claude Code-specific: plugin manifest, Bash(...) permission whitelist, the /setup slash command, and (for git-manager) PreToolUse hooks. Its skills/<name> is a symlink back into the top-level skills/ dir — never a duplicated copy that can drift.
  • .claude-plugin/marketplace.json lists both plugins and must live at the repo root (Claude Code convention, not vendor/claude-code/).

Adding a third host tool (e.g. Codex) means adding a new vendor/<tool>/ tree symlinked back to the same skills/<name>/, without touching skill content.

The permission-whitelisting philosophy (applies to every plugin here)

This is the design constraint that shapes almost every file in this repo — worth understanding before editing any wrapper script, setup.sh, or permissions-whitelist.template.json:

  • Never whitelist a generic command. No Bash(git:*), Bash(find:*), Bash(cd:*). Each plugin whitelists exactly one (or a few) wrapper script(s), pinned by exact absolute path. The wrapper enforces its own scope (allowed subcommands, vault boundaries) — the whitelist entry just says "this specific, self-limiting script may run without asking."
  • Wrapper scripts never accept a raw filesystem path from the caller. They resolve everything (repo path, vault path) from a config file at ~/.agent-skills/<name>/config.json by name. This is what makes whitelisting the script by path safe — it can't be pointed at an arbitrary directory.
  • Setup copies scripts to a stable, self-owned location before writing any permission rule~/.agent-skills/<name>/bin/, never Claude Code's internal plugin cache path (~/.claude/plugins/cache/.../<version>/), which changes on every plugin version bump. This is why each setup.sh does "copy scripts → write permissions → write config" in that order, and why permission rules are written in tilde form (~/...), matching the literal unexpanded command text Claude Code matches against — not the resolved $HOME path.
  • Nothing destructive is silently whitelisted. Config-file writes (registering a new repo/vault) and anything outside the fixed subcommand/action allowlist always fall through to a normal confirmation prompt.
  • Optional PreToolUse hooks are advisory, never blocking. They only ever emit permissionDecision: "ask" (never "deny", never "allow") — see force-ask-on-chaining.sh and force-ask-on-raw-git.sh in vendor/claude-code/plugins/git-manager/hooks/. If jq is missing they fail open (no output) rather than block every Bash call.

Adding a new skill

Documented in full in ARCHITECTURE.md; short version:

  1. skills/<new-name>/ with SKILL.md (+ scripts//references/ as needed). Config path: ~/.agent-skills/<new-name>/config.json.
  2. vendor/claude-code/plugins/<new-name>/ with .claude-plugin/plugin.json, a skills/<new-name> symlink back to the top-level skill dir, and — if the skill needs restricted shell access — commands/setup.md plus permissions-whitelist.template.json following the existing plugins' pattern (wrapper scripts that resolve scope from config, whitelisted only by exact absolute path).
  3. Add an entry to .claude-plugin/marketplace.json.
  4. Bump version in both the plugin's plugin.json and its marketplace.json entry on any update.

Gotchas specific to this repo

  • Symlinks (vendor/.../skills/<name> -> ../../../../../skills/<name>) assume POSIX; this repo doesn't try to be Windows-checkout-friendly.
  • permissions-whitelist.template.json files are reference/documentation only — the actual rules are generated and written by each plugin's scripts/setup.sh, not read from the template at runtime.
  • git-manager's wrapper deliberately rejects stash, merge, rebase, reset, and arbitrary git config — these can rewrite/discard history or working-tree state irreversibly. Raw git remains a valid, visible fallback for those (nudged, not blocked, by force-ask-on-raw-git.sh if that hook is installed).