Lab 2 — Steer Your Workflow
Summary — what this page covers The revised hands-on lab for Section 2. Attendees split their CLAUDE.md into path-scoped rules, build a real skill folder, add a guardrail hook that blocks destructive commands, and wrap it all into a minimal plugin — all committed under
.claude/. This replaces the old "slash commands + single-file skill + hook" lab.
Duration: 55 min · Deliverable: a .claude/ directory (rules + skill folder + guardrail hook + plugin manifest), committed
Keep the Steering Reference Card open — it has the decision table and copy-paste starters for everything below. If you get stuck, working versions of every file ship in the repo under
.claude/.
Part A — Split CLAUDE.md into Rules (12 min)
Goal: move the conventions you put in your Lab 1 CLAUDE.md into focused, path-scoped rules, and trim the root CLAUDE.md back to a map (facts, commands, architecture).
mkdir -p .claude/rules
Create two path-scoped rules. A rule is Markdown with a paths: glob in its frontmatter:
---
paths:
- "BookTracker.Api/Endpoints/**/*.cs"
---
# API endpoint conventions
- Keep endpoints thin — business logic lives in Core services.
- Accept and return DTOs, never EF entities.
- Async all the way; thread the CancellationToken through.
.claude/rules/api-endpoints.md—paths:BookTracker.Api/Endpoints/**/*.cs.claude/rules/data-access.md—paths:BookTracker.Data/**/*.cs(parameterized queries only, async EF methods, migrations live inBookTracker.Data)
Now delete those same conventions from CLAUDE.md so they live in exactly one place.
Verify: run /memory to see what's loaded. Open a file under BookTracker.Api/Endpoints/ and
confirm the api-endpoints rule loads; note that it does not load when you're working
elsewhere. (Recall the Section 2 gotcha: path-scoped rules load on read, not create.)
Part B — Build a skill folder (18 min)
Goal: a reusable procedure for adding an endpoint — the kind of multi-step task that belongs in a skill, not CLAUDE.md.
mkdir -p .claude/skills/add-api-endpoint/references
Write SKILL.md. The description is the trigger, written for the model — phrase it the way a
user would ask, so Claude auto-matches it:
---
name: add-api-endpoint
description: Use when adding a new HTTP endpoint to BookTracker.Api — creating the route,
handler, request/response DTOs, and wiring it into the Minimal API. Triggers on requests like
"add an endpoint", "expose a new route", "create a GET/POST for ...".
---
# Add an API endpoint
## Procedure
1. Read `references/endpoint-pattern.md` and an existing endpoint to match the house style.
2. Define request/response DTOs in `BookTracker.Core/Dtos`.
3. Add the handler and map the route in `BookTracker.Api`.
4. Build, then add a test mirroring `BookTracker.Tests`.
## Gotchas
- Never return an EF entity — map to a DTO.
- Validate inputs before touching the data layer.
- (Add the non-obvious traps you hit — this section is the high-value part.)
- Add a short
references/endpoint-pattern.mdshowing the canonical endpoint shape to mirror. - Test by auto-match — don't name the skill, just describe the work:
Add a GET /books/{id}/reviews endpoint returning reviews sorted by date.Watch Claude pick up the skill from its description.
Part C — A guardrail hook (15 min)
Goal: a deterministic block on destructive commands — the thing a CLAUDE.md "never do X" line cannot reliably enforce.
Create .claude/hooks/block-destructive.sh. A PreToolUse hook receives the tool call as JSON on
stdin; exit 2 to block and write the reason to stderr so Claude sees it:
#!/usr/bin/env bash
# PreToolUse (Bash) guardrail: block destructive commands.
input=$(cat)
cmd=$(echo "$input" | jq -r '.tool_input.command // empty')
if echo "$cmd" | grep -Eiq 'rm[[:space:]]+-rf|DROP[[:space:]]+TABLE|git[[:space:]]+push.*--force'; then
echo "Blocked by guardrail: destructive command pattern detected." >&2
exit 2
fi
exit 0
chmod +x .claude/hooks/block-destructive.sh
Register the guardrail (PreToolUse on Bash) and a build hook (PostToolUse on edits) in
.claude/settings.json:
{
"hooks": {
"PreToolUse": [
{ "matcher": "Bash", "hooks": [
{ "type": "command", "command": ".claude/hooks/block-destructive.sh" }
]}
],
"PostToolUse": [
{ "matcher": "Edit|Write", "hooks": [
{ "type": "command", "command": "dotnet build" }
]}
]
}
}
Test it: start a fresh session (so settings reload), ask Claude to run a destructive command,
and watch it get blocked with the reason. Then make a real edit and watch the build hook fire
— if the build breaks, Claude sees the failure and self-corrects. (The hook script uses jq; it's
preinstalled in WSL2/macOS dev setups — install it if missing.)
Part D — Package as a plugin (10 min)
Goal: bundle the rules, skill, and hooks so a teammate gets your whole setup in one install.
Add .claude/plugins/booktracker-kit/plugin.json with the plugin metadata; the skill, rules, and
hooks are discovered by convention:
{
"name": "booktracker-kit",
"version": "0.1.0",
"description": "BookTracker steering kit: API/data rules, the add-api-endpoint skill, and a destructive-command guardrail."
}
Commit everything:
git add .claude
git commit -m "feat: steer Claude Code — rules, skill, guardrail hook, plugin"
Checkpoint
-
/memoryshows the path-scoped rule loading only on a matching file -
add-api-endpointis a folder with aSKILL.md, and it auto-applied - The
PreToolUsehook blocked a destructive command (exit 2) and Claude saw why - The build hook fired on write and Claude self-corrected a failure
- Everything under
.claude/committed, including the plugin manifest
Starter artifacts: working versions of every file above ship in the repo under
.claude/(skill folder, subagent, rules,settings.json, hook script, plugin manifest). Attendees can reference them if they get stuck.
Bonus — The Team Plugin
No time pressure. Promote booktracker-kit into a publishable team plugin:
- A marketplace entry so teammates can install it by name.
- A full rule set covering every project area (not just endpoints and data access).
- Three skill folders (e.g. add-endpoint, write-tests, review-PR).
- A
PreToolUseskill-usage logging hook that records which skills actually fire — the same pattern teams use to find skills that under-trigger and need a better description.