You'll walk away with
- How
/initbootstraps a project and where the three CLAUDE.md tiers live (project, local, user-global) - How to author custom slash commands in
.claude/commands/and pass arguments via$ARGUMENTS - How PreToolUse and PostToolUse hooks insert before or after tool execution, and what each can or cannot block
- How to wire MCP servers into Claude Code and when to reach for the
ghCLI for GitHub workflows - How the Claude Code SDK runs the same Claude Code programmatically from TypeScript, Python, or the CLI
Read these first
Lesson outline
Every lesson from Claude Code in Action with our one-line simplification. The Skilljar course is the source; we summarize.
| # | Skilljar lesson | Our simplification |
|---|---|---|
| 1 | Introduction | Course frame: Claude Code is more than a chat box; it integrates with your editor, repo, CI, and shell. |
| 2 | What is a coding assistant? | Coding assistants pair an LLM with file access, shell access, and a tool loop, not just autocomplete. |
| 3 | Claude Code in action | Live demo of Claude Code reading the repo, planning, and editing across files in one session. |
| 4 | Claude Code setup | Install via npm/Homebrew, sign in with your Anthropic API key or Console subscription, verify in a sandbox repo. |
| 5 | Project setup | Cd into the repo and run Claude Code; it auto-detects the project root and respects .gitignore. |
| 6 | Adding context | /init writes CLAUDE.md from the codebase; @file injects file contents; # enters memory mode for inline edits. |
| 7 | Making changes | Claude proposes edits, you approve per-file or shift-tab to auto-accept; diffs render inline before commit. |
| 8 | Course satisfaction survey | Mid-course survey checkpoint, no technical content. |
| 9 | Controlling context | Use /clear to reset, /compact to summarize, and @-mentions to keep only relevant files in working memory. |
| 10 | Custom commands | Create .claude/commands/<name>.md files; the filename becomes /<name> and $ARGUMENTS pipes user input. |
| 11 | MCP servers with Claude Code | Add MCP servers via /mcp or settings JSON to give Claude Code access to GitHub, Sentry, databases, browsers. |
| 12 | GitHub integration | Use the gh CLI inside Claude Code or the GitHub Action to run Claude Code on PRs and issues. |
| 13 | Introducing hooks | Hooks run shell commands before or after a tool call; PreToolUse can block, PostToolUse can only react. |
| 14 | Defining hooks | Hooks live in ~/.claude/settings.json, .claude/settings.json, or .claude/settings.local.json; matchers target tool names. |
| 15 | Implementing a hook | A hook is a command that reads a JSON tool-call payload from stdin and exits 0/non-zero or writes feedback. |
| 16 | Gotchas around hooks | Hooks run as your shell user with full perms; matcher regex traps and infinite-loop hooks are common failure modes. |
| 17 | Useful hooks! | Auto-format on Edit, run tests on Write, log every Bash to a file, block reads from .env files. |
| 18 | Another useful hook | Notification hooks: ping a webhook, play a sound, or open a desktop notification when Claude finishes a task. |
| 19 | The Claude Code SDK | Run Claude Code programmatically from TypeScript or Python; default is read-only, opt in to writes via allowedTools. |
| 20 | Quiz on Claude Code | End-of-course knowledge check across CLAUDE.md, hooks, MCP, slash commands, and the SDK. |
| 21 | Summary and next steps | Recap and pointers to Subagents, MCP Advanced, and Agent Skills as natural follow-ups. |
The course in 7 paragraphs
Claude Code in Action is a tour of the eight integration surfaces that take Claude Code from "a chat box that reads files" to "a build-time tool every engineer on the team uses the same way." The eight: /init and CLAUDE.md, @ file mentions, custom slash commands, MCP servers, GitHub integration, hooks (Pre and Post), the SDK, and the settings hierarchy that lets each layer be team-shared or personal. The course is short on theory and heavy on "here is the file you put it in". Treat it as an integration manual, not an introduction.
The CLAUDE.md hierarchy is the load-bearing primitive. Three locations: CLAUDE.md at repo root (committed, shared with the team), CLAUDE.local.md (gitignored, personal overrides), and ~/.claude/CLAUDE.md (user-global across every project). Claude reads all three on every request, layered. The /init command bootstraps the repo-root file by analyzing your codebase. The # memory-mode shortcut merges new instructions into the right tier without you opening the file. `@file` mentions inline file contents on demand, and you can put @-mentions inside CLAUDE.md so referenced files load on every turn.
Custom slash commands live in .claude/commands/<name>.md. The filename becomes the command, the body is the prompt, and $ARGUMENTS is the placeholder for whatever the user types after the command name. A write_tests.md file becomes /write_tests <path>. This is the cleanest way to encode a team's repeatable workflows; audit, ship, refactor, write_tests, lint-fix; without each engineer reinventing the prompt every time. Restart Claude Code after creating a new command file; discovery is at startup, not live. Personal commands live in ~/.claude/commands/ and shadow project commands of the same name, so each engineer can override a team-shared command locally without forking the file. The pattern matters: what slash commands are to ad-hoc prompting, custom commands are to your team's shared engineering vocabulary.
Hooks are where Claude Code stops being a chat assistant and becomes part of your build pipeline. PreToolUse runs before a tool is executed (matcher targets Read, Edit, Bash, etc.) and can block by exit code; PostToolUse runs after and can only react. Real uses: auto-format with Prettier on every Edit, run pnpm typecheck after Write, block reads from .env files, log every Bash call to a security audit trail. The hook is just a shell command receiving a JSON payload on stdin. Configuration lives in the same three-tier settings system (global, project, project-local) so you can ship team hooks via .claude/settings.json while letting each engineer add personal ones in .claude/settings.local.json.
MCP servers in Claude Code extend the tool surface beyond the built-ins. Claude Code is an MCP client; you point it at MCP servers via /mcp or settings JSON, and those servers expose their tools, resources, and prompts to the session. Install GitHub, Sentry, Postgres, Playwright, Linear, or Notion in one line of config and Claude can query and act against them. The `gh` CLI is often the simpler GitHub path: Claude Code calls gh directly through the Bash tool, no MCP wiring needed. The Claude Code GitHub Action lets the same harness run on PRs and issues from CI.
The Claude Code SDK is the same Claude Code, just runnable from your own scripts. The TypeScript and Python packages expose a query() async iterator; you give it a prompt, and it streams the same tool-call conversation you'd see in the terminal. Default permissions are read-only; the SDK can Read, Grep, Glob, Bash (read-only commands), but cannot Edit or Write unless you opt in via allowedTools. Use cases: pre-commit hooks that review diffs, CI checks that summarize changes, batch refactors that apply Claude Code across many repos, custom slash commands inside other tools.
The implicit thread through the whole course is the settings hierarchy. Three tiers (global at ~/.claude/settings.json, project-shared at .claude/settings.json committed, project-personal at .claude/settings.local.json gitignored) apply to MCP servers, hooks, custom commands, and permissions in exactly the same way. Think of `.claude/settings.json` as your team's contract for how Claude Code behaves in this repo, and .claude/settings.local.json as your personal overrides on top. The deeper layers shadow earlier ones, never silently. Once you see the pattern in one surface (hooks), you see it in all of them, and the course's eight topics collapse into one coherent integration model. The exam-relevant takeaway: Claude Code is not a chat box; it is a configurable harness whose every surface obeys the same three-tier hierarchy, and an architect designing rollout strategy works at that meta-layer rather than at any single surface.
5 hooks every Claude Code repo should consider
These show up in real production setups; each maps to a real failure mode that hooks prevent.
- PostToolUse: format on Edit
Match
Concept: hooks ↗Write|Edit|MultiEditand runprettier --writeorruff formaton the changed file. Removes the entire "Claude wrote ugly code" class of complaints in one config block. - PostToolUse: typecheck on Edit
Run
Concept: hooks ↗pnpm typecheckormypyafter edits; the hook can echo errors back to Claude as feedback. Claude self-corrects without the user mediating. - PreToolUse: block .env reads
Match
Concept: hooks ↗Readand reject any path matching.env*with a non-zero exit. Never trust prompt-only constraints when you have a hook contract you can enforce. - PreToolUse: log every Bash
Match
Concept: hooks ↗Bashand append the command + cwd to an audit log before letting it run. Cheap forensics for any "what did Claude do?" investigation. - Notification hook on Stop
Match the
Concept: hooks ↗Stopevent and play a sound or send a webhook so you know when a long task finishes. Removes the "is it still running?" tab-switching tax.
3 things to put in your team's CLAUDE.md
The repo-root CLAUDE.md is committed, shared, and read on every request. Optimize it for the highest-leverage instructions, not for verbosity.
- Project commands
The exact
Concept: claude-md-hierarchy ↗dev,build,test,typecheck,lintcommands. Claude defaults to npm if you don't tell it you use pnpm/yarn/bun. - Architecture sketch
A 5-10 line description of the app's shape: frontend, backend, database, auth, deploy target. Saves Claude from grepping the same files every session.
Concept: claude-md-hierarchy ↗ - House rules
"Never edit
Concept: claude-md-hierarchy ↗db/migrations/", "Use Tailwind utilities, not CSS modules", "Run typecheck before claiming done". Concrete rules, not platitudes.
6 takeaways with cross-pillar bridges
Claude Code reads three CLAUDE.md tiers (repo-root, repo-local, user-global) on every request; design instructions to live at the right layer.
Custom slash commands are markdown files in .claude/commands/; $ARGUMENTS substitutes user input and the filename becomes the command.
PreToolUse hooks can block tool execution by non-zero exit; PostToolUse hooks can only react, not block. Choose by what you need to enforce.
MCP servers in Claude Code extend the tool surface to GitHub, Sentry, Postgres, browsers, etc.; configure via /mcp or settings JSON in the same three-tier hierarchy.
The Claude Code SDK runs the same harness programmatically with read-only defaults; opt in to writes via allowedTools when you trust the prompt.
Settings hierarchy is the meta-pattern: global / project-shared / project-personal applies to hooks, MCP, commands, and permissions identically.
How this maps to the CCA-F exam
3 hand-picked extras
These amplify the Skilljar course beyond what the course itself covers. Each was picked for a specific reason.
Claude Code Hooks; Anthropic documentation
Canonical reference for hook event names, matcher syntax, JSON payload schema, and exit-code semantics. The Skilljar lessons demo hooks; this doc is what you keep open while writing them.
Read source ↗Claude Code SDK; Anthropic documentation
TypeScript and Python SDK reference with query() signatures, allowedTools semantics, and permission modes. Pair with Lesson 19 when you start building automation.
Claude Code best practices for agentic coding
Anthropic's own engineering write-up of how they use Claude Code internally; covers CLAUDE.md authoring, command design, and hook patterns at scale.
Read source ↗Concepts in this course
CLAUDE.md hierarchy
Three-tier context primitive at the heart of every lesson
Concept: claude-md-hierarchy ↗Hooks
PreToolUse / PostToolUse, the integration mechanism for build pipelines
Concept: hooks ↗MCP
How Claude Code extends its tool surface to external systems
Concept: mcp ↗Tool calling
What hooks intercept and what slash commands invoke
Concept: tool-calling ↗Agentic loops
The runtime model under every Claude Code session
Concept: agentic-loops ↗Where you'll see this in production
Code generation with Claude Code
Primary scenario covering custom commands and CLAUDE.md authoring
Scenario: code-generation-with-claude-code ↗Claude Code for CI/CD
SDK + GitHub Action use case from Lessons 12 and 19
Scenario: claude-code-for-cicd ↗Developer productivity agent
Hooks + slash commands as a daily productivity layer
Scenario: developer-productivity-agent ↗Other course mirrors you may want next
8 questions answered
Phrased as the way real students search. Tagged by intent so you can scan to what you actually need.
ComparisonWhat is the difference between CLAUDE.md, CLAUDE.local.md, and the user-global CLAUDE.md?
CLAUDE.local.md is gitignored and holds your personal overrides for this repo. ~/.claude/CLAUDE.md is user-global and applies across every project on your machine. Claude layers all three; later tiers do not overwrite earlier ones, they accumulate.How-toHow do I create a custom slash command in Claude Code?
.claude/commands/<name>.md in your repo. The filename becomes the command (audit.md → /audit), the body of the file is the prompt Claude runs when invoked, and $ARGUMENTS is the placeholder substituted with whatever the user types after the command name. Restart Claude Code after creating the file; discovery happens at startup, not live.DefinitionCan a PostToolUse hook block a tool call from running?
TroubleshootWhy does my custom slash command show up in `/help` but doesn't run?
.claude/commands/, not .claude/command/ or commands/), or the filename has spaces or uppercase letters that are getting stripped. Use lowercase-hyphenated names.How-toDo I need MCP to integrate Claude Code with GitHub?
gh directly through its Bash tool; no MCP wiring needed for issues, PRs, comments, or repo operations. Use the GitHub MCP server when you want stricter tool boundaries, structured outputs, or features the CLI doesn't expose. Use the official Claude Code GitHub Action when you want Claude to run on PRs and issues from CI.ComparisonIs the Claude Code SDK the same thing as the Anthropic Messages API?
messages.create() endpoint; you build the agent loop yourself. The Claude Code SDK wraps the *full Claude Code harness*; same tools, same agentic loop, same MCP servers, same CLAUDE.md reading; and exposes it as a query() function in TypeScript or Python. Use the SDK when you want Claude Code's capabilities programmatically; use the raw API when you're building a different harness from scratch.How-toWhat does `/init` actually do when I run it in a new project?
CLAUDE.md at the repo root summarizing the project's purpose, architecture, key commands, and important files. Treat the output as a draft, not the final; almost every team rewrites it after the first week as they learn what Claude actually needs to know.ScopeAre hooks safe? Can a hostile prompt make Claude run a destructive shell command via a hook?
Bash hook that pipes the command into a shell evaluator without sanitization is dangerous. Treat hooks like cron jobs you wrote: review them, scope tightly, and never accept hook configs from untrusted sources.