Learn/Claude Academy: Learn the productsguide

Claude Code in action

Context control, custom commands, hooks, headless runs, GitHub integration and plugins.

Series Claude Academy: Learn the products Part 1 of 7
  1. Claude Code in action
  2. Introduction to Model Context Protocol
  3. Model Context Protocol: Advanced topics
  4. Introduction to subagents
  5. Introduction to agent skills
  6. The AI-native SDLC playbook
  7. Deploying Claude Enterprise with confidence

A walkthrough of the Claude Academy course Claude Code in action (Learn the products track, 9 lessons + quiz, about 1 hour). Each lesson is summarised with my own tables and examples; take the course for the full lessons. All the courses are listed in the Claude Academy course index.

Note: Built from the public lesson text. The settings.json hook wiring, the example hook script, and the plugin layout tree were added from the Claude Code docs and should be checked against the lessons and current docs.

Prerequisites / Audience

  • Developers who already use Claude Code for single prompts and want longer, less supervised, team-wide workflows.
  • Basic Git and command-line familiarity.

Objectives (4 themes)

  1. Steer the work: plan mode, directed compaction, rewind, /goal and /loop.
  2. Configure Claude: a lean CLAUDE.md, skills, permission modes, hooks.
  3. Automate repeat work: routines, headless mode (-p), Code Review and the GitHub Action.
  4. Verify and share: verify unsupervised runs, gate on tests with hooks, package plugins.

Module 1 — Steer the work

Lesson 1: Steering long sessions

The two habits: scope the work before Claude starts, then steer it while it runs.

  • Plan mode: Claude researches without editing source files and hands you a plan. Read it, don’t skim it. Iterating on a plan is much faster than cleaning up after a bad run.
  • Directed compaction: /compact summarizes the conversation and replaces the old messages with the summary. Add instructions after the command so the summary keeps what matters:
    /compact Focus on the --version flag implementation
  • Rewind: every user prompt creates a checkpoint. Double-tap Esc on an empty prompt to open the rewind menu.
Rewind option Effect
Restore code and conversation Roll back both
Restore conversation Chat only
Restore code Files only
Summarize from here Compress everything after the checkpoint (e.g. a side conversation)
Summarize up to here Compress everything before it (e.g. a long setup phase)
  • Autonomous runs:
    • /goal <condition> sets a completion condition. Claude keeps working across turns until a fast evaluator confirms it. /goal clear cancels it. ⚠️ The evaluator reads only the transcript, so the condition must be checkable from Claude’s output (e.g. test results).
      /goal all tests in src/billing pass, and the type checker reports zero errors
    • Loop runs a prompt on an interval (fixed or self-paced), e.g. to poll CI or a deploy. Press Esc to stop a self-paced loop while it waits. A fixed-interval loop runs until you cancel it or 7 days pass.
  • Worktrees for parallel sessions: each session gets its own file tree, so sessions can’t clobber each other. Clean worktrees are auto-removed when the session exits. A .worktreeinclude file at the repo root lists git-ignored files (e.g. .env) to copy into each worktree.

Module 2 — Configure Claude

Lesson 2: A CLAUDE.md that follows

  • CLAUDE.md is guidance, not enforced configuration. Every line competes for attention, so the leaner the file, the more of it Claude follows.
  • Hard rules belong in hooks. For example, “never push to main” should be a PreToolUse hook that blocks the action, not a CLAUDE.md line.
Location Purpose
Managed policy Org-level file controlled by the platform team. Can’t be excluded
User Your preferences across all projects
Project Shared with the team, checked into the repo
Local Git-ignored. Your personal notes for this repo (e.g. branch-specific architecture decisions)

All four load together at launch and stack.

  • Imports help organize, but they don’t reduce context: imported files are expanded inline at launch.
    @.claude/conventions/code-style.md
    @.claude/conventions/testing.md
    @.claude/conventions/workflow.md
  • Phrasing rules that stick:
    • Specific and checkable: ❌ “Follow best practices for API routes” → ✅ “Put new API routes in src/api/handlers, one per file.”
    • Name the replacement: ❌ “Don’t use default exports” → ✅ “Use named exports, not default exports.”
    • Emphasis is a budget: save “IMPORTANT” / “YOU MUST” for the 2–3 rules that really hurt when broken.
  • Keep revising it: treat each wrong behavior as a bug report against CLAUDE.md (“add that to the CLAUDE.md file”). If you can’t justify a line, delete it.

Lesson 3: Verification skills

  • Build a verification skill first. It removes the dependency on you remembering to ask for checks. When its description matches (e.g. a refactor just finished), it:
    1. Runs the test suite
    2. Reads the diff
    3. Checks that no test was weakened to make things pass
    4. Reports pass/fail with evidence
  • “Done” means the gates were run and observed, with results stated explicitly. “The diff looks right” is not done.
  • Keep SKILL.md lean. Put depth in reference.md (read on demand) and tooling in scripts like check.sh, which are executed, not loaded into context.
  • Rule of thumb: if you’ve typed the same multi-step instruction twice, make it a skill.
Surface Owns
CLAUDE.md Always-on conventions (naming, file locations)
Skill Task-specific procedures and reference material
Hook Rules Claude must not be able to skip (code that runs, not instructions)
---
name: verify-change
description: Verifies a finished code change. Use after any refactor, feature, or bug fix before reporting done.
---
1. Run `scripts/check.sh` (do not read it) and capture the output.
2. Run `git diff` and confirm no test assertions were removed or loosened.
3. Report PASS/FAIL with the command output as evidence.

Lesson 4: Permission modes

Mode Behavior
Manual Reads run without prompting. Everything else asks
Accept edits Reads, file edits, and common filesystem bash run freely. You review after the fact
Plan Researches and proposes without editing. With auto available, the classifier approves exploration commands
Auto Accepts everything, with a separate classifier model reviewing most actions first
Don’t ask Reads inside working dirs plus pre-approved tools. Anything that would prompt is auto-denied (for CI and unattended runs)
Bypass permissions Skips all checks (= --dangerously-skip-permissions). Only in an isolated container or VM
  • Shift+Tab cycles manual → accept edits → plan → auto. The status bar shows the current mode.
  • The auto classifier guards intent. It blocks production deploys and migrations, force-pushes, piping downloaded code into a shell, sending sensitive data to external endpoints, and irreversibly destroying pre-existing files. It allows local edits, lockfile installs, reads, and pushes to your own branch.
  • ⚠️ The classifier doesn’t check correctness. Broken auth code isn’t “dangerous”, so it passes. Pair auto mode with a Stop hook that runs tests: auto guards intent before actions, and the hook guards correctness after.

Lesson 5: Hooks

  • A hook is deterministic code at a fixed point in the loop. It turns “Claude usually listens” into “Claude can’t skip it”. There are about 30 events. The key ones:
Event Use
PreToolUse Before a tool call. The enforcement primitive (can block or rewrite)
PostToolUse After a successful call. Auto-format / lint
Stop / SubagentStop When Claude (or a subagent) wants to end its turn. Refuse if not done
PreCompact / PostCompact Around compaction
InstructionsLoaded When CLAUDE.md or a rule file loads. Audit what reached context
SessionStart Prime the environment. Use the startup source for fresh starts only
  • 💡 To re-inject context after compaction, use SessionStart with the compact matcher, not PostCompact.
  • PreToolUse JSON output (print it to stdout and exit 0). permissionDecision is allow | deny | ask (plus defer, for -p runs only):
    {
      "hookSpecificOutput": {
        "hookEventName": "PreToolUse",
        "permissionDecision": "deny",
        "permissionDecisionReason": "...",
        "updatedInput": { "command": "..." }
      }
    }
    • updatedInput rewrites the call (e.g. redact sk_live_… and still run the command). It replaces the whole input object, so echo back any unchanged fields.
Exit code Meaning
0 Success. JSON on stdout is parsed. Plain text is added to context only for SessionStart / UserPromptSubmit / UserPromptExpansion
2 Blocking error. stderr is fed back to Claude (can even block Stop)
other (incl. 1) Non-blocking. stderr is logged and the action proceeds ⚠️
  • PostToolUse blocking comes too late to stop the call, but it can feed text back. Notification and SessionStart ignore blocking.
// .claude/settings.json (wiring per Claude Code docs)
{
  "hooks": {
    "PreToolUse": [
      { "matcher": "Bash", "hooks": [{ "type": "command", "command": ".claude/hooks/guard-bash.sh" }] }
    ],
    "Stop": [
      { "hooks": [{ "type": "command", "command": ".claude/hooks/run-tests.sh" }] }
    ],
    "SessionStart": [
      { "matcher": "compact", "hooks": [{ "type": "command", "command": ".claude/hooks/recap-files.sh" }] }
    ]
  }
}
# run-tests.sh: Stop hook that refuses to end the turn on failure
out=$(npm test 2>&1) || { echo "$out" | tail -50 >&2; exit 2; }

Module 3 — Automate repeat work

Lesson 6: Routines and headless

The options form a spectrum: Routines (Anthropic infra, build nothing) → headless -p → --bare → Agent SDK (inside your app).

  • Routine = prompt + repo + connectors + trigger, run in the cloud on Anthropic’s infrastructure.
    • Triggers: cron schedule, HTTP POST to its API endpoint, or a GitHub event (e.g. a new PR).
    • Create one at claude.ai/code/routines, or with /schedule daily dependency audit at 9am.
    • Limits: it’s a research preview. Recurring runs are at most hourly. Runs start from a fresh clone of the default branch and push to a claude/ branch (PR-triggered runs start at the PR head). Use GitHub branch protection or rulesets to restrict pushes.
  • Headless (non-interactive) mode: claude -p "..." runs one-shot, reads stdin, writes stdout. It still loads hooks, skills, plugins, MCP servers, and CLAUDE.md.
    claude -p "Extract the exported function names from src/core/style.js" \
      --output-format json \
      --json-schema '{"type":"object","properties":{"functions":{"type":"array","items":{"type":"string"}}},"required":["functions"]}' \
      | jq '.structured_output.functions'
    claude --resume "$(jq -r .session_id plan.json)"   # multi-step: resume a saved session
  • --bare: skips auto-discovery of hooks, skills, plugins, MCP, and CLAUDE.md. You get Bash, Read, and Edit plus anything passed via --settings / --mcp-config. Startup is reproducible and faster. Needs ANTHROPIC_API_KEY (no subscription login).
  • Agent SDK (TS/Python): a query() function that takes a prompt plus options (allowedTools, system prompt, permission mode). You iterate over the streamed messages.
  • Decision guide: start with routines. Use -p when the job needs your pipeline, --bare for identical CI setups, and the SDK when the work belongs inside your product.

Lesson 7: GitHub Actions and Code Review

Code Review (managed) GitHub Action (DIY)
Hosting Anthropic Your GitHub runners
Setup Org Owner: admin settings → Allow code review → install the Claude GitHub app → pick repos /install-github-app (needs repo admin; sets the API key secret)
Triggers PR opened / every push / @claude review comment PR or issue comments, cron, any GitHub event
Output Inline, severity-tagged, deduped and ranked comments, plus a summary table in the check run Commits, comments, logs
Limits Never approves/blocks, never pushes fixes. Team and Enterprise plans Whatever you configure
  • Code Review looks at the diff against the full codebase. To check a fix locally before pushing, run /code-review (add --fix to apply its findings to your working tree).
  • Action inputs: anthropic_api_key (or claude_code_oauth_token / workload identity federation), github_token (optional override), trigger_phrase (default @claude), use_bedrock / use_vertex / use_foundry, prompt (set it to run automatically without a mention), claude_args.
# .github/workflows/claude.yaml (core step); job needs permissions: id-token: write
- uses: anthropics/claude-code-action@v1
  with:
    anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
    trigger_phrase: "@claude"
    claude_args: "--max-turns 5 --model claude-sonnet-5"
  • Scheduled rollups: use a cron trigger plus prompt, and read the result in the run log (a scheduled run doesn’t post a comment). Add workflow_dispatch to allow manual runs.
  • claude_args tuning: --max-turns caps the loop, use a non-prompting permission mode for unattended jobs, and give minimal allowed tools (read-only for reports).

Module 4 — Verify and share

Lesson 8: Trust it — verifying unsupervised runs

  • The less you watched, the more you verify.
  • Run unattended work in auto mode, not bypass. The classifier still catches dangerous actions, but it never judges correctness.
  • Start with the diff, not the summary. Run /code-review and then read git diff yourself. Check the files in the plan, then look for anything outside it.
  • Make tests a gate, not a promise: a Stop hook runs tests and refuses to end on failure, and a PostToolUse hook lints and type-checks after each edit. Exit 2 feeds failures back so Claude fixes them on its own.
  • Verify headless runs by their JSON result and exit code.
  • Get a cold second opinion: a fresh session or subagent with no memory of the build catches what the author rationalized away.

Lesson 9: Plugins

  • A plugin is one installable unit bundling skills, subagents, hooks, MCP configs, LSP servers, monitors, themes, and a slice of settings.
    /plugin install github@claude-plugins-official
    /plugin marketplace add your-org/claude-plugins
    /reload-plugins            # --force if it warns about re-reading the conversation
  • ⚠️ Read before you install. Plugins run code with your privileges, and their hooks fire on every matching call (e.g. a Stop hook that calls a network endpoint). Being listed on a marketplace doesn’t make a plugin trusted. The official marketplace is curated separately from community submissions.
  • Components run alongside yours: hooks stack. Skills, agents, and commands are namespaced (/plugin-name:skill). A plugin’s settings.json honors only the agent and subagent status-line keys, and the agent key promotes a plugin subagent to the main thread, changing default behavior.
  • Packaging your own uses the same .claude shape:
    my-plugin/
    ├── .claude-plugin/plugin.json   # optional manifest
    ├── skills/<skill>/SKILL.md
    ├── agents/<agent>.md
    ├── hooks/hooks.json
    └── .mcp.json
    { "name": "svg-splitter-review", "version": "0.1.0",
      "description": "Reviews the SVG Splitter repo", "author": { "name": "Lewis Menelaws" } }
    • name is the only required manifest field and sets the namespace. Version the plugin like any other dependency.

Quick-Review Flashcards

  1. Q: How do you steer what /compact keeps? → A: Add instructions after it, e.g. /compact Focus on the --version flag implementation.
  2. Q: How do you open the rewind menu? → A: Double-tap Esc on an empty prompt.
  3. Q: What’s the key constraint on /goal conditions? → A: The evaluator only reads the transcript, so “done” must be visible in Claude’s output.
  4. Q: What is .worktreeinclude for? → A: Listing git-ignored files (like .env) to copy into each worktree.
  5. Q: Do CLAUDE.md @imports save context? → A: No. They’re expanded inline at launch and only help organization.
  6. Q: Where does “never push to main” belong? → A: In a PreToolUse hook, not CLAUDE.md.
  7. Q: What does the auto-mode classifier check? → A: Intent and danger, not correctness. Pair it with a Stop hook that runs tests.
  8. Q: Which exit code blocks, and which surprisingly doesn’t? → A: 2 blocks. 1 is non-blocking.
  9. Q: How do you re-inject context after compaction? → A: A SessionStart hook with the compact matcher.
  10. Q: What are routines’ limits? → A: Research preview, at most hourly, fresh clone of the default branch, pushes to a claude/ branch.
  11. Q: What does --bare skip, and what does it need? → A: It skips hooks, skills, plugins, MCP, and CLAUDE.md discovery. It needs ANTHROPIC_API_KEY.
  12. Q: Can managed Code Review approve or push fixes? → A: No. It only posts findings.

Practice Ideas

  • Plan a multi-file refactor in plan mode, edit the plan, then run it with /goal "<tests pass + typecheck clean>".
  • Audit your CLAUDE.md: delete vague lines, rewrite rules to be checkable and to name replacements, and move hard rules to hooks.
  • Write a verify-change skill with a check.sh, commit it to .claude/skills, and confirm it fires after a refactor.
  • Add a PreToolUse Bash hook that redacts sk_live_ tokens via updatedInput, plus a Stop hook that exits 2 on failing tests.
  • Create a routine with /schedule for a daily dependency audit. Separately, script a claude -p --output-format json --json-schema extraction.
  • Install the GitHub Action with /install-github-app and try an @claude comment workflow and a cron rollup.
  • Package your .claude setup as a plugin with a plugin.json and install it from a private marketplace.