How It Works¶
Skills¶
A skill is a Markdown file (SKILL.md) with YAML frontmatter:
---
name: fastapi-guideline
description: Use this skill whenever working with FastAPI...
---
# FastAPI
Instructions for the agent...
The description field is what the agent reads to decide whether to load the skill. Keep it specific — the more clearly it describes when to trigger, the more reliably it auto-activates.
Loading system¶
Skills use three-level progressive loading:
1. description (~100 words) → always in context
2. SKILL.md body → loaded when skill triggers
3. references/ files → loaded on demand
This keeps the agent's context lean. Heavy reference material stays on disk until it's actually needed.
Auto-triggering¶
When you send a message, Claude reads all installed skill descriptions and decides which ones are relevant. If a skill's description matches what you're doing — even without a slash command — it loads the full SKILL.md automatically.
Example: you write "add asyncpg connection pooling to my FastAPI app" — the fastapi-guideline and postgres-best-practices skills activate without you typing anything.
Slash commands¶
Every skill is also available as a slash command. Type / in Claude Code to see all installed skills:
Hooks¶
The coding and bms plugins ship PreToolUse hooks — shell scripts that run before Claude executes a Bash command. They intercept common tool invocations and rewrite them to preferred tools:
pip install→uv addnpm run dev→bun run devpytest→uv run pytest
The rewrite is silent. The agent sees the corrected command as if it typed it.
A separate global hook rewrites pyright → uv run ty check, since ty is the team's standard type checker.
The dev-workflow plugin ships three enforcement hooks:
- PreToolUse on Edit/Write/NotebookEdit (deny) — blocks edits outside a
worktree*/.worktree*/.claudepath, so changes land in an isolated worktree rather than a shared main checkout. - PreToolUse on EnterWorktree (allow) — auto-approves entering or creating a worktree whose
path/namematches the sameworktree*/.worktree*pattern, so switching into an already-isolated worktree doesn't hit a permission prompt. - PreToolUse on Bash (deny) — blocks commands that publish or complete a PR (
bdt pr publish,bdt pr create --no-draft,az repos pr create/update --auto-complete,gh pr create/ready/merge, etc.) unless a code review has already run earlier in the session —/code-reviewor/bms-code-review, directly or via a subagent, or a review done by the local OpenAIcodexCLI. The hook reads the session transcript (andsubagents/*.jsonl). A codex review counts only if the transcript holds a real Bash call whose command word iscodexand that runscodex exec "<prompt>"(the prompt must mention a code review / the bms-code-review skill, or say "review" together with diff, branch, PR, pull request, changes or commit) orcodex review(alsocodex exec review), and the run is known to have finished: a foreground call whose tool result is not an error, arun_in_backgroundcall with acompletedtask notification, or a shell-backgrounded run (nohup codex exec ... &, where the tool result only says "started") whose-o <file>output file exists, is non-empty and is newer than the call's transcript timestamp. The-ofile is proof only for shell-backgrounded runs: it never rescues a failed foreground orrun_in_backgroundcall, which can leave partial output behind, and a backgrounded run without-odoes not count. The tool result is the exit status of the whole command line, so a foreground orrun_in_backgroundrun only counts when the codex call decides that status:cd x && codex exec ...andcodex exec ... && echo okare fine, butcodex review | cat,codex exec ... | tee out.md(unlessset -o pipefailcomes earlier),codex exec ...; echo doneandcodex exec ... || trueare not accepted, because they exit 0 even when codex failed. For those, background with&and-o, or drop the tail. Acodex execprompt may come from a variable assigned earlier in the same command (P="...code review..."; codex exec "$P"); an unresolved variable does not count. A start alone,codex --version/--help, and the word "codex" in a commit message,echoorgrepnever count. As with the Claude-side check, the review counts for the whole session: it is not tied to HEAD and later commits do not invalidate it.
The same two hooks run in Codex, from the generated .agents/plugins/marketplace.json. The worktree check reads the files of an apply_patch patch, and the PR gate reads the Codex rollout (session_meta first row) instead of a Claude Code transcript; Codex has no EnterWorktree, so that hook is left out. node scripts/sync-codex.mjs keeps the Codex marketplace identical in content to the Claude one, and CI fails when it is stale.
Plugins¶
Skills are bundled into plugins for easier distribution. A plugin is a named group of skills that install together.
The bmsuisse-skills marketplace (this repo) defines all available plugins. When you enable coding@bmsuisse-skills, all skills in that plugin become available in your Claude Code session.
Plugin definitions live in .claude-plugin/marketplace.json.
File locations¶
After installation, skills land here:
| Platform | Path |
|---|---|
| Claude Code | .claude/skills/ (project) or ~/.claude/skills/ (global) |
| Cursor | .cursor/rules/ |
| Codex CLI | ~/.codex/skills/ |
Contributing a skill¶
- Create
skills/<skill-name>/SKILL.md - Add it to the relevant plugin in
.claude-plugin/marketplace.jsonas./skills/<skill-name> - Run
npm run skill:validateandnpm run plugins:checkto confirm every skill, agent and hook script a plugin references exists - Open a PR — CI auto-updates the skills table in README