Contents
Back to blog

Claude Code in Action: A Practical Map for Working With AI Coding Agents

4,997 words25 min read

A practical learning guide from Anthropic's Claude Code in Action course, rewritten into an operating model for context, planning, GitHub review, MCP, hooks, SDK usage, and feedback-driven AI coding workflows.

Dynamic poster preview for this learning guide.

Claude Code in Action: A Practical Map for Working With AI Coding Agents

I finished Anthropic's Claude Code in Action course, and the main lesson is not "AI writes code now."

The deeper lesson is this:

AI coding works best when you treat it as a disciplined development workflow, not as a magic code generator.

Claude Code is powerful because it can inspect a repository, read files, run commands, edit code, use tools, and integrate with external systems. But that power only becomes useful when you control the context, define the task boundary, review the diff, and add feedback loops.

This post is my public learning guide. It is not a transcript of the course, and it does not reproduce the official quiz. Instead, it turns the course into a practical map of the ideas I want to remember and reuse.

1. The Course Frame: From Prompting To Workflow

Figure 01 - The Course Frame: From Prompting To Workflow

Figure 1: The Course Frame: From Prompting To Workflow

The course starts by reframing Claude Code as a development partner inside a workflow.

A normal chatbot waits for text and returns text. A coding assistant has a richer loop:

  1. Receive a task.

  2. Inspect the codebase.

  3. Build a plan.

  4. Edit files or run commands.

  5. Read the result.

  6. Ask for approval, revise, or continue.

That means the user is not just "asking for code." The user is designing the operating conditions around the coding agent.

For me, the key shift is:

The skill is not prompting. The skill is scoping, context design, review, and feedback.

2. What A Coding Assistant Actually Is

Figure 02 - What A Coding Assistant Actually Is

Figure 2: What A Coding Assistant Actually Is

A coding assistant is a language model wrapped in tools.

The model itself only sees text. It cannot magically read a repository or run tests. The surrounding application gives it tool access:

  • read files

  • search code

  • edit files

  • execute shell commands

  • inspect browser output

  • interact with GitHub

The assistant alternates between reasoning and tool use. Good work depends on whether the tool loop gives it enough environmental feedback to act safely.

This is why "agent" is not the important word. The important word is tool loop.

3. Seeing Claude Code In Action

Figure 03 - Seeing Claude Code In Action

Figure 3: Seeing Claude Code In Action

The demos show Claude Code acting less like autocomplete and more like another engineer in the development loop.

It can analyze performance issues, run benchmarks, inspect profiling output, iterate on code changes, and integrate with browser automation through MCP. It can also run in GitHub workflows and review pull requests.

The pattern behind these demos is consistent:

  • Claude Code needs a clear goal.

  • It gathers context before acting.

  • It creates a plan or todo list.

  • It changes the environment.

  • It checks the result.

  • The human reviews the final judgment.

That is the minimum loop I want to teach in my own Claude Code course.

4. Setup: Treat The Repo As The Real Context

Figure 04 - Setup: Treat The Repo As The Real Context

Figure 4: Setup: Treat The Repo As The Real Context

Setup matters because Claude Code works best when it can understand the actual project, not an abstract description of the project.

The basic flow is:

  1. Open the project locally.

  2. Start Claude Code from the terminal.

  3. Let it inspect the repository.

  4. Create or update project memory.

  5. Keep important architecture and style notes close to the repo.

The important command-level idea is that project instructions should be durable. A project memory file such as CLAUDE.md becomes the stable context Claude can reuse instead of rediscovering every convention.

Practical commands and references:

  • Start an interactive session with claude.

  • Use /init in the first session to generate a starter CLAUDE.md.

  • Use /memory to inspect and refine memory files later.

  • Keep team-level project instructions in ./CLAUDE.md or ./.claude/CLAUDE.md.

  • Keep personal local preferences in ./CLAUDE.local.md.

  • Official references: CLI reference, slash commands, memory and CLAUDE.md.

5. Project Setup: Give Claude A Safe First Task

Figure 05 - Project Setup: Give Claude A Safe First Task

Figure 5: Project Setup: Give Claude A Safe First Task

The first task should not be "build the whole product."

A good first task is a bounded setup or verification task:

  • read the README

  • identify install steps

  • check package manager

  • run tests

  • report missing environment variables

  • summarize architecture

This creates trust before asking for code changes. It also gives Claude Code a chance to map the project without editing too early.

The best early win is not a feature. It is a reliable project map.

6. Adding Context Without Drowning The Agent

Figure 06 - Adding Context Without Drowning The Agent

Figure 6: Adding Context Without Drowning The Agent

Claude Code gets better when the context is relevant and worse when the context is noisy.

There are several context layers:

  • project memory shared with the repo

  • local or personal instructions

  • specific files mentioned for the current task

  • screenshots or visual references

  • current conversation history

  • permission mode and approval boundary

The trick is not to add everything. The trick is to add the smallest context that makes the task unambiguous.

Useful mental model:

If a detail changes how the agent should act, put it in context. If it is just interesting, keep it out.

One detail I originally underweighted is permission mode.

In practice, permission mode is also context. It tells Claude Code how much friction should exist between reasoning and action. The default mode keeps a human approval gate in front of edits and commands. acceptEdits lowers that friction by letting Claude create and edit files inside the working directory without asking every time. Plan mode does the opposite: it lets Claude explore and propose a path before editing source files.

That means Shift+Tab is not just a shortcut. It changes the operating conditions of the session.

My rule after revisiting this section:

Use acceptEdits when the task direction is clear and I want to review the diff afterward. Use Plan mode when the task is broad, risky, or still ambiguous.

Practical commands and references:

  • Use CLAUDE.md for durable project rules.

  • Use @path/to/file imports inside CLAUDE.md when another file should be loaded as part of memory.

  • Use /context to see what is filling the context window.

  • Press Shift+Tab in the CLI to cycle permission modes such as default, acceptEdits, and Plan mode.

  • Use claude --permission-mode acceptEdits when you want file edits auto-approved inside the working directory and will review changes afterward.

  • Use claude --permission-mode plan or /plan when Claude should inspect first and avoid editing until a plan is approved.

  • Use /compact focus on ... when a long session should preserve a specific thread of work.

  • Official references: memory and imports, permission modes, permissions, interactive mode, common workflows.

7. Making Changes: Plan For Breadth, Think For Depth

Figure 07 - Making Changes: Plan For Breadth, Think For Depth

Figure 7: Making Changes: Plan For Breadth, Think For Depth

When a task is broad, ask Claude Code to plan first.

When a task is logically difficult, give it more reasoning room.

I think of this as two different modes:

  • Planning mode handles breadth: which files, which sequence, which checks.

  • Thinking mode handles depth: tricky logic, debugging, edge cases.

Good changes also include reviewable boundaries:

  • one feature slice

  • one bug fix

  • one refactor

  • one component

  • one failing test

The smaller the slice, the easier it is to review.

Visual changes need visual context.

This is one of the most practical details from the course. If the issue is layout, spacing, color, responsive behavior, or a visible error state, a screenshot is often better than a paragraph of explanation. Claude Code can receive an image in the terminal, turn it into an [Image #N] reference, and use it as task context.

My working rule:

If I would point at the screen while explaining the bug to a teammate, I should give Claude Code a screenshot.

The important shortcut detail is slightly unintuitive on macOS: in the Claude Code terminal, image paste is usually Ctrl+V, not Cmd+V. Anthropic's docs also list Cmd+V for iTerm2 and Alt+V for Windows / WSL. If paste is unreliable, the safer fallback is to save the image and give Claude the file path.

Practical commands and references:

  • For visual work, add screenshots by drag-and-drop, clipboard paste, or an image path.

  • Paste an image into Claude Code with Ctrl+V; use Cmd+V in iTerm2 or Alt+V on Windows / WSL when that is the supported binding.

  • On macOS, capture a selected area with Shift+Command+4; add Control if you want the screenshot copied to the clipboard instead of saved to the desktop.

  • On Windows, use Windows+Shift+S to open Snipping Tool capture.

  • Use /plan before broad changes.

  • Press Shift+Tab to cycle permission modes, including Plan mode.

  • Use /diff before accepting work.

  • Use /code-review, /review, or /security-review when the change needs a second pass.

  • Official references: Claude Code image workflows, interactive mode shortcuts, custom keybindings, Apple screenshot shortcuts, Microsoft Snipping Tool, slash commands, permission modes, common workflows.

8. Controlling Context During Long Sessions

Figure 08 - Controlling Context During Long Sessions

Figure 8: Controlling Context During Long Sessions

Long AI coding sessions drift.

The course highlights several context-control moves that matter:

  • interrupt when Claude is going in the wrong direction

  • record repeated mistakes into memory

  • rewind to an earlier point when debugging gets noisy

  • compact long sessions when the useful knowledge should stay but clutter should go

  • clear the session when switching to a new task

For me, the biggest habit is interruption.

When Claude Code is wrong, do not wait politely. Stop it, correct the assumption, and make the new rule durable if the mistake is likely to repeat.

Practical commands and references:

  • Use Esc to interrupt a wrong direction.

  • Use Esc twice or /rewind to return to a better checkpoint.

  • Use /context before compacting if you need to understand what is consuming space.

  • Use /compact focus on ... to preserve the important part of a long task.

  • Use /clear when switching to an unrelated task.

  • Official references: slash commands, interactive mode, common workflows.

9. Custom Commands: Turn Repeated Work Into Slash Commands

Figure 09 - Custom Commands

Figure 9: Custom Commands

Custom commands are reusable prompts stored in the project.

They are useful when you repeatedly ask Claude Code to do the same kind of work:

  • audit a dependency

  • review a component

  • generate a test

  • explain a module

  • check security-sensitive files

  • prepare a release note

The pattern is simple:

  1. Write a markdown instruction file.

  2. Put it in the commands folder.

  3. Use a slash command to call it.

  4. Add arguments when the command needs a target file or task.

This turns a good prompt into a team workflow.

Practical commands and references:

  • Project custom commands can live in .claude/commands/.

  • Current Claude Code docs also recommend skills for richer reusable workflows: .claude/skills/<skill-name>/SKILL.md.

  • Type / inside Claude Code to discover available commands and skills.

  • Use skills when the workflow needs supporting files, examples, scripts, or deeper instructions.

  • Official reference: slash commands and skills.

10. MCP Servers: Give Claude Better Tools

Figure 10 - MCP Servers: Give Claude Better Tools

Figure 10: MCP Servers: Give Claude Better Tools

MCP servers extend what Claude Code can do.

A basic Claude Code setup can read files, edit code, and run shell commands. With MCP, Claude can connect to external capabilities such as browser automation, docs search, issue trackers, or other services.

The value is not "more tools." The value is giving Claude the exact missing feedback loop.

For example, a browser automation MCP can let Claude:

  • open the local app

  • inspect a page

  • take screenshots

  • compare visual results

  • adjust code based on what it sees

That turns UI development from blind editing into visible iteration.

Practical commands and references:

  • Add a remote MCP server with claude mcp add --transport http <name> <url>.

  • Add a stdio MCP server with claude mcp add --transport stdio <name> -- <command>.

  • List servers with claude mcp list.

  • Check and authenticate servers inside Claude Code with /mcp.

  • Official reference: MCP in Claude Code.

11. GitHub Integration: Bring The Agent Into Review

Figure 11 - GitHub Integration: Bring The Agent Into Review

Figure 11: GitHub Integration: Bring The Agent Into Review

Claude Code can also run inside GitHub workflows.

The course frames this as a way to bring AI assistance into the normal team review process:

  • mention the agent in issues or pull requests

  • let it inspect the repository state

  • let it review changes

  • let it comment on risks

  • customize workflows with project-specific instructions

The important idea is that GitHub integration should not bypass review. It should make review sharper.

The best AI review is not "looks good." It should point to risks, hidden assumptions, missing tests, security issues, and places where the implementation conflicts with project constraints.

Practical commands and references:

  • Claude Code GitHub Actions can run Claude inside GitHub workflows.

  • The useful pattern is issue or PR context -> agent review -> human merge decision.

  • Keep project standards in CLAUDE.md so the review has local rules.

  • Official reference: Claude Code GitHub Actions.

12. Hooks: Automating Guardrails Around Tool Use

Figure 12 - Hooks: Automating Guardrails Around Tool Use

Figure 12: Hooks: Automating Guardrails Around Tool Use

Hooks are commands that run before or after Claude Code uses tools.

They are powerful because they add automatic guardrails around the agent loop.

Examples:

  • block reading .env

  • run formatting after edits

  • run type checks after TypeScript changes

  • warn when sensitive files are touched

  • launch a duplicate-code review after specific directories change

Hooks are not just automation. They are policy.

The question is not "can I automate this?" The question is:

What mistake should the system prevent or surface immediately?

Practical commands and references:

  • Configure hooks through settings or the /hooks interface when available.

  • Use hooks for enforcement; use CLAUDE.md for guidance.

  • Treat every hook as arbitrary shell automation and review it carefully before enabling.

  • Official reference: hooks reference.

13. Defining Hooks: Trigger, Action, Boundary, Stop Condition

Figure 13 - Defining Hooks: Trigger, Action, Boundary, Stop Condition

Figure 13: Defining Hooks: Trigger, Action, Boundary, Stop Condition

A hook needs a clear shape:

  • trigger: which tool or file event activates it

  • action: what command runs

  • boundary: what it is allowed to inspect or change

  • feedback: what it reports back to Claude

  • stop condition: when it blocks, warns, or exits cleanly

This matters because hidden automation can make a system harder to understand.

My rule:

A hook should be boring, narrow, and inspectable.

If I cannot explain when it fires and what it does, it should not exist yet.

One detail worth making explicit is the tool name.

For tool-based hooks, the matcher is not guessing from English. It matches Claude Code's internal tool_name. That means a hook configured for Bash fires on shell commands, a hook configured for Edit|Write fires on file edits or file creation, and a hook configured for Grep fires when Claude searches file contents.

The common built-in names to know are:

Tool nameWhat it represents
ReadRead a file
Edit, MultiEditEdit an existing file
WriteCreate or overwrite a file
BashRun a shell command
GlobFind files by pattern
GrepSearch file contents
AgentSpawn a subagent
WebFetchFetch and process a web page
WebSearchSearch the web
AskUserQuestionAsk the user a structured question
ExitPlanModeLeave plan mode after a plan is accepted

The course screenshot labels the subagent tool as Task, but the current public Claude Code docs use Agent in the hooks and tools reference. That is a good reminder to treat course slides as learning material and official docs as the source of truth for exact matcher strings.

MCP tools follow a different naming pattern:

mcp__<server>__<tool>

For example, mcp__github__search_repositories targets a GitHub MCP tool, while mcp__memory__.* matches every tool exposed by a memory MCP server.

Practical commands and references:

  • A hook should define the trigger, matcher, command, allowed action, and stop behavior.

  • Match built-in tools with exact names such as Bash, Read, Edit|Write, or Grep.

  • Match MCP tools with the mcp__<server>__<tool> naming pattern.

  • Use a broad matcher only for logging or discovery; for real guardrails, keep the matcher narrow and inspect tool_input inside the hook.

  • Use ${CLAUDE_PROJECT_DIR} when a hook script should resolve paths from the project root.

  • Official references: hooks reference, tools reference, Agent SDK hooks.

14. Implementing Hooks: From Policy To Script

Figure 14 - Implementing Hooks: From Policy To Script

Figure 14: Implementing Hooks: From Policy To Script

The course uses practical examples to show how hooks receive tool-call data, inspect it, and exit with a signal.

A pre-tool hook can block an action before it happens. A post-tool hook can inspect the result and return feedback after the action.

A good hook script should:

  • parse structured input

  • check one clear rule

  • print useful feedback

  • exit predictably

  • avoid broad side effects

For example, a security hook should not be a giant security platform. It can start with one rule: do not read secret files.

Practical commands and references:

  • Hook scripts can receive structured input, inspect the tool call, then return a decision.

  • A pre-tool hook can block before the tool runs.

  • A post-tool hook can report feedback after the tool runs.

  • Official reference: hooks reference.

15. Hook Gotchas: Automation Can Hide Complexity

Figure 15 - Hook Gotchas: Automation Can Hide Complexity

Figure 15: Hook Gotchas: Automation Can Hide Complexity

Hooks are useful, but they can also create hidden behavior.

The risk is not just bugs. The risk is invisibility:

  • Claude did something because a hook told it to.

  • A file changed because a post-hook ran.

  • A command failed because a pre-hook blocked it.

  • The user forgot the hook existed.

That is why hooks need documentation and small scope.

Before adding a hook, I want to ask:

  • What failure does this catch?

  • Is the failure common enough?

  • Can a simple checklist catch it instead?

  • What happens when the hook is wrong?

  • How do I turn it off?

16. Useful Hooks: Type Checks And Duplicate Prevention

Figure 16 - Useful Hooks: Type Checks And Duplicate Prevention

Figure 16: Useful Hooks: Type Checks And Duplicate Prevention

Two useful hook patterns stand out.

The first is immediate type checking. After Claude edits TypeScript, run tsc --noEmit and feed the errors back. This helps catch broken call sites quickly.

The second is duplicate prevention. If Claude edits a critical directory, launch a separate review process that checks whether the new function or query already exists.

These hooks are valuable because they protect quality at the moment mistakes are introduced.

They are also expensive in attention and runtime, so they should be used selectively.

17. Another Useful Hook: Local Workflow Feedback

Figure 17 - Another Useful Hook: Local Workflow Feedback

Figure 17: Another Useful Hook: Local Workflow Feedback

The broader hook idea is local workflow feedback.

Whenever the agent edits something important, the system can ask:

  • did the type checker still pass?

  • did formatting change?

  • did tests break?

  • did a sensitive file get touched?

  • did the output become visually worse?

This turns Claude Code from a one-shot editor into a feedback-driven collaborator.

The best hooks are not fancy. They are small loops that keep the project honest.

18. Claude Code SDK: Put The Agent Inside Your Own Pipeline

Figure 18 - Claude Code SDK: Put The Agent Inside Your Own Pipeline

Figure 18: Claude Code SDK: Put The Agent Inside Your Own Pipeline

The SDK lets you call Claude Code programmatically.

This matters when you want Claude Code inside a larger automated workflow:

  • helper scripts

  • project audits

  • codebase reports

  • review assistants

  • migration helpers

  • internal developer tools

The default posture should be conservative. Read-only access is safer. Write access should be explicit.

My interpretation:

The terminal is for interactive collaboration. The SDK is for repeatable intelligence inside a pipeline.

Practical commands and references:

  • Use claude -p "your task" for non-interactive CLI usage.

  • The Agent SDK is available for Python and TypeScript.

  • Use explicit tool permissions such as allowed_tools / allowedTools.

  • SDK agents can load the same project features as Claude Code, including CLAUDE.md, skills, hooks, and project settings when configured to do so.

  • Official references: run Claude Code programmatically, Agent SDK overview, Claude Code features in the SDK.

19. Summary: The Operating Model I Want To Keep

Figure 19 - Summary: The Operating Model I Want To Keep

Figure 19: Summary: The Operating Model I Want To Keep

The course connects many pieces into one operating model:

  1. Give Claude Code a bounded task.

  2. Let it inspect the environment.

  3. Ask for a plan when the task is broad.

  4. Use focused context instead of dumping everything.

  5. Review changes through Git and tests.

  6. Extend capability with MCP only when a missing tool loop is obvious.

  7. Add hooks when repeated failures need automatic feedback.

  8. Use the SDK when the workflow should be repeatable.

This is the practical lesson:

AI coding agents are not a replacement for engineering judgment. They amplify judgment when the workflow is designed well.

20. Course Review Notes

Figure 20 - Course Review Knowledge Map

Figure 20: Course Review Knowledge Map

I do not recommend publishing the official course quiz as an answer key.

What I prefer to do is summarize the concepts in a way that helps me answer similar questions later. This keeps the learning useful without turning the course into a copy of the quiz.

Here is how I would summarize the key ideas from this course.

If the question is: What is a coding assistant?

A good way to answer is:

A coding assistant is a language model connected to development tools. The model reasons in text, but the surrounding tool loop lets it read files, search code, edit files, run commands, inspect browser output, and use feedback from the environment.

If the question is: Why does Claude Code need tools?

A good way to answer is:

The model itself cannot directly inspect a repo, run a test, open a browser, or change a file. Claude Code becomes useful because tools turn the model's reasoning into grounded actions, and the results of those actions come back as context.

If the question is: What is the safest mental model for using Claude Code?

A good way to answer is:

Treat Claude Code as an agent inside a controlled development workflow, not as an autonomous engineer. Give it a bounded goal, focused context, permission boundaries, verification steps, and a human review gate.

In workflow form:

scope -> context -> plan -> small change -> test -> diff review -> feedback

If the question is: Why is CLAUDE.md important?

A good way to answer is:

CLAUDE.md stores durable project context, such as architecture notes, coding conventions, commands, testing rules, and project-specific preferences. In a new repo, run /init inside Claude Code to generate a starter CLAUDE.md, then use /memory to refine it over time.

If the question is: How should context be added?

A good way to answer is:

Add the smallest context that changes how Claude should act. Durable rules belong in memory. Exact evidence belongs in mentioned files. Visual issues can use screenshots. Noisy background information should stay out unless it directly affects the task.

If the question is: When should Plan Mode be used?

A good way to answer is:

Use Plan Mode when the task is broad, touches multiple files, or requires sequencing. Planning helps Claude inspect the repo and propose an approach before editing. It is especially useful when you need to review the intended path before giving permission to change code.

If the question is: When should deeper thinking be used?

A good way to answer is:

Use deeper thinking when the task is logically difficult: debugging, tricky architecture, ambiguous edge cases, or complex reasoning. Planning handles breadth; deeper thinking handles depth. For difficult broad tasks, combine both.

If the question is: What is the difference between /compact and /clear?

A good way to answer is:

/compact summarizes a long session so useful task knowledge stays while clutter is reduced. /clear starts fresh and removes the previous conversation context. Compact when continuing the same task; clear when switching to an unrelated task.

If the question is: What are custom commands for?

A good way to answer is:

Custom commands turn repeated prompts into reusable project workflows. If I repeatedly ask Claude Code to review a component, audit a dependency, generate a test, or prepare a release note, that instruction can become a slash command stored in .claude/commands/.

If the question is: Why use MCP with Claude Code?

A good way to answer is:

MCP gives Claude Code access to external tools and feedback loops that the default repo tools do not provide. The value is not "more tools" in general; the value is the right missing capability, such as browser automation, docs lookup, issue tracking, or database inspection.

If the question is: What is the value of GitHub integration?

A good way to answer is:

GitHub integration brings Claude Code into the existing issue and pull request workflow. It can help review changes, comment on risks, suggest fixes, and respond to mentions, but it should sharpen human review rather than bypass it.

If the question is: What are hooks?

A good way to answer is:

Hooks are commands that run before or after Claude Code uses tools. A pre-tool hook can block an unsafe action before it happens. A post-tool hook can run checks or return feedback after an action, such as formatting, type checking, or duplicate-code detection.

If the question is: What makes hooks risky?

A good way to answer is:

Hooks can create hidden automation. If the trigger, allowed action, safety boundary, and stop condition are unclear, they can make the system harder to understand and control. A hook should be narrow, documented, inspectable, and easy to disable.

If the question is: What should every hook define?

A good way to answer is:

Every hook should define its trigger, action, boundary, feedback, and stop condition. In practical terms, I should know which tool call activates it, what command runs, what files or actions it can touch, what message it returns, and when it allows, warns, or blocks.

If the question is: What is a useful first hook?

A good way to answer is:

A useful first hook is a boring quality check. For a TypeScript project, a post-tool hook that runs tsc --noEmit after edits can catch broken call sites quickly and feed the errors back to Claude while the context is still fresh.

If the question is: When should the Claude Code SDK be used?

A good way to answer is:

Use the SDK when the workflow should be repeatable or embedded inside a larger pipeline. The terminal is best for interactive collaboration. The SDK is better for helper scripts, audits, migration helpers, review assistants, and hooks. Start read-only and enable write tools explicitly only when needed.

If the question is: What is the main lesson of Claude Code in Action?

A good way to answer is:

Claude Code is most useful when it is surrounded by a disciplined operating system: durable memory, focused context, small changes, verification loops, Git review, MCP for missing tools, hooks for repeated failures, and SDK usage for repeatable pipelines.

Reference:

Final Takeaway

The real skill is not knowing every Claude Code feature.

The real skill is knowing when to use each layer:

  • memory for durable context

  • files for exact evidence

  • plan mode for breadth

  • thinking for depth

  • MCP for missing tool access

  • GitHub integration for team review

  • hooks for automatic guardrails

  • SDK for repeatable pipelines

Claude Code becomes most useful when it is surrounded by a good operating system.

That is what I want my own Claude Code learning path to become: not tool worship, but a reliable way to turn ideas into reviewed, tested, shipped work.

Loading comments...