# Labs — Module 4: Extending AI Intelligence > Four short labs that ship one of each extension type (skill, MCP, > hook) and a triage exercise that prevents you from building the > wrong kind. Each fits in a single focused block; the whole set is > ~70 minutes. | Lab | Title | Time | Maps to | |-----|--------------------------------------------------|--------|----------------------------------| | 4.1 | Ship one minimal skill | 20 min | §4.2 Skills | | 4.2 | Install one read-only MCP server | 20 min | §4.3 Model Context Protocol | | 4.3 | Wire two hooks (lint + secret-scan) | 15 min | §4.4 Hooks | | 4.4 | Triage 5 capabilities with the decision rubric | 15 min | §4.5 Skill vs MCP vs Hook | --- ## Lab 4.1 — Ship one minimal skill ### Objective Promote one repetitive procedure into a `SKILL.md` the agent loads on demand and follows. ### Time 20 minutes. ### Real-world scenarios - **A — Release process.** Cut version, update changelog, tag, push tag. STOP before publishing. - **B — On-call handoff.** Incidents-still-open, follow-ups, recent pages, blockers for next shift. - **C — Scaffold a new microservice.** Copy template, rename, regenerate IDs, register in platform catalog. ### Setup ```bash mkdir -p .claude/skills/<name> ``` ### Steps 1. Write `.claude/skills/<name>/SKILL.md` with frontmatter (`name`, `description` listing trigger phrases) and a body of ≤10 numbered steps. Include at least one explicit STOP point. 2. Fresh session. Use one of the trigger phrases. Confirm the skill loads. 3. Negative test: use an *off-topic* phrase. Confirm the skill does **not** load. ### Deliverable `.claude/skills/<name>/SKILL.md` committed + `labs/notes/4.1-skill.md` with the trigger phrases and a transcript snippet showing the skill loading. ### Success criteria - The skill loads on the trigger phrase, in a fresh session. - The negative test doesn't load it. If it does, narrow the description. ### Reflection - Which step needed the most clarifying detail to keep the agent on rails? That's where your tribal knowledge lived. ### Stretch - Add a supporting file (template, fixture, script) next to `SKILL.md` and reference it from the body. --- ## Lab 4.2 — Install one read-only MCP server ### Objective Give the agent first-class access to one external system without shelling out. Read-only — mutations belong in Module 6. ### Time 20 minutes. ### Real-world scenarios - **A — Staging Postgres.** Read-only credential. Agent can answer "what's the schema for `orders`?" without you pasting `\d+`. - **B — Linear / Jira.** Agent reads your assigned issues and recent comments. Cuts the standup-prep ritual. - **C — Feature-flag service.** Read-only flag state per env. Pays off during outages and code review. ### Setup ```bash mkdir -p .claude && touch .claude/mcp.json ``` ### Steps 1. Pick an off-the-shelf server matching your scenario. Register it in `.claude/mcp.json` using `${ENV_VAR}` references (no inline secrets): ```jsonc { "mcpServers": { "<name>": { "command": "npx", "args": ["-y", "<package>", "<scoped-conn-string>"], "env": { "TOKEN": "${TOKEN}" } } } } ``` 2. `claude /mcp`. Confirm the server is listed and reports its tool count. 3. Use it. Prompt the agent in plan mode with a question only the new server can answer. Watch it invoke the MCP tool. ### Deliverable `.claude/mcp.json` committed (no inline secrets) + `labs/notes/4.2-mcp.md` with the server, credential scope, and one example prompt the agent now answers without you. ### Success criteria - The agent answered a real question via MCP — not by guessing. - The credential cannot mutate (confirmed by attempting it). ### Reflection - What did you used to bridge by pasting data into chat that's now one tool call away? ### Stretch - Add a second MCP server. Prompt with a question that joins their outputs ("for each open Linear issue tagged `database`, summarize the affected table"). --- ## Lab 4.3 — Wire two hooks (lint + secret-scan) ### Objective Move two repetitive enforcement tasks from prompts to deterministic hooks. Verify each fires. ### Time 15 minutes. ### Real-world scenarios - **A — TS team.** PostToolUse on Edit: `pnpm lint --fix`. Plus a secret-scanner. - **B — Python team.** PostToolUse on Edit: `ruff check --fix`. Plus a secret-scanner. - **C — Infrastructure.** PostToolUse on `*.tf` edits: `terraform fmt && terraform validate`. Plus a secret-scanner. ### Setup `mkdir -p scripts && touch scripts/check-secrets.sh && chmod +x scripts/*.sh`. ### Steps 1. Write `scripts/check-secrets.sh` using the §4.4 template (AWS key, OpenAI/Anthropic key, GitHub PAT, RSA header). Exit 2 on match. 2. Register two hooks in `.claude/settings.json`: ```jsonc "hooks": { "PostToolUse": [{ "matcher": "Edit|Write|MultiEdit", "hooks": [ { "type": "command", "command": "<your formatter>" }, { "type": "command", "command": "scripts/check-secrets.sh" } ] }] } ``` 3. Trigger each: have the agent make a bad-format edit (lint hook fires) and another with a fake `sk-...` string (secret hook blocks). Capture the surfaced messages. ### Deliverable Hooks committed + `labs/notes/4.3-hooks.md` with the firing transcripts. ### Success criteria - Both hooks fire on the intended events. - The secret hook **blocks** (exit 2) with a *useful stderr message* — not silently. ### Reflection - Which `AGENTS.md` rule could you now delete because a hook enforces it? ### Stretch - Add a Stop hook that appends one-line session summaries to `.claude/sessions.log`. --- ## Lab 4.4 — Triage 5 capabilities with the decision rubric ### Objective Decide where each wished-for capability belongs before any code is written: Skill / MCP / Hook / `AGENTS.md`. ### Time 15 minutes. ### Real-world scenarios If you don't have 5 of your own, pick from: - **A — Backend.** Query staging DB. Run data-quality SQL on migrations. Snake_case columns. Walk-through for new tenant. - **B — Frontend.** Screenshot every PR's changed pages. Block inline styles. Tokens design system not Tailwind. Read Figma. - **C — Compliance fintech.** Refuse `pii/` commits without reviewer tag. Look up customers (redacted). No `JSON.parse` on untrusted input. ### Setup Open `labs/notes/4.4-rubric.md` with columns: `# | Capability | Home | Why`. ### Steps 1. List **5 capabilities** you want. 2. Per row, pick a home: Skill (procedure the model decides when to invoke), MCP (data/tool needed mid-task), Hook (deterministic on an event), `AGENTS.md` (standing fact every session). 3. Write the *why* in one sentence each. ### Deliverable The 5-row table + 3 "next sprint" picks (one of each type ideally), plus a "not yet" list with reasons. ### Success criteria - At least 3 of the 4 homes appear in the table. - Every *why* is specific (not "useful"). ### Reflection - Which row was hardest to place? That row likely composes — see the SQL-on-migration example in §4.5. ### Stretch - Convert the rubric into a backlog. Each shipped row's PR description references the row. --- ## Wrap-up In the repo (committed): `.claude/skills/<name>/`, `.claude/mcp.json`, hooks in `.claude/settings.json`, `scripts/check-secrets.sh`. In `labs/notes/`: `4.1` through `4.4`. Your CLI is now a platform. Module 5 gives it memory. **Next:** [Labs — Module 5: Memory Orchestration](05-memory-orchestration-labs.md)