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.
  1. .claude/rules/api-endpoints.mdpaths: BookTracker.Api/Endpoints/**/*.cs
  2. .claude/rules/data-access.mdpaths: BookTracker.Data/**/*.cs (parameterized queries only, async EF methods, migrations live in BookTracker.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.md showing the canonical endpoint shape to mirror.
  • Test by auto-matchdon'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

  • /memory shows the path-scoped rule loading only on a matching file
  • add-api-endpoint is a folder with a SKILL.md, and it auto-applied
  • The PreToolUse hook 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 PreToolUse skill-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.