# 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](11-steering-reference-card.md) 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).

```bash
mkdir -p .claude/rules
```

Create two path-scoped rules. A rule is Markdown with a `paths:` glob in its frontmatter:

```markdown
---
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.md` — `paths:` `BookTracker.Api/Endpoints/**/*.cs`
2. `.claude/rules/data-access.md` — `paths:` `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.

```bash
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:

```markdown
---
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-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:

```bash
#!/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
```

```bash
chmod +x .claude/hooks/block-destructive.sh
```

Register the guardrail (`PreToolUse` on Bash) **and** a build hook (`PostToolUse` on edits) in
`.claude/settings.json`:

```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:

```json
{
  "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:

```bash
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.
