Subscribe to Newsletter

Module 4: What Claude Code Features To Use For Agentic Engineering

This module goes deeper into the tools you have as an agentic engineer. You extend an agent with hooks, skills, plugins, and MCP servers. You also run agents outside a live chat session.

Start module Module 4 of 5 · 7 lessons

4.1

How To Build Hooks on Claude Code

Hooks are user-defined shell commands that Claude Code runs at specific points in its lifecycle.

A prompt only asks the model nicely. A hook gives you deterministic control instead.

The action always happens. It does not depend on a decision by the model to comply.

Anthropic suggests that you use hooks to enforce project rules, to automate repetitive tasks, and to integrate Claude Code with your existing tools.

Watch: Hooks in Claude Code.

Build Your First Hook: A Desktop Notification

WALKTHROUGH

Goal: Get a desktop notification each time Claude Code waits on you, so you do not watch the terminal.

  1. Open ~/.claude/settings.json. Create the file if it does not exist. Add a Notification hook:
    {
      "hooks": {
        "Notification": [
          {
            "matcher": "",
            "hooks": [
              { "type": "command", "command": "osascript -e 'display notification \"Claude Code needs your input\"'" }
            ]
          }
        ]
      }
    }
  2. Run /hooks in Claude Code to confirm that Notification now appears with a hook attached.
  3. Ask Claude to do something that needs permission. Then switch away from the terminal.

Expected result: A desktop notification fires the moment Claude Code waits on you.

What Can You Automate With Hooks?

The same pattern is a JSON block tied to an event. That pattern covers most of what you want to enforce automatically:

  • Auto-format on every edit. A PostToolUse hook with an Edit|Write matcher runs Prettier on any file Claude just touched. The code format stays consistent without a request from you.
  • Block edits to protected files. A PreToolUse hook can run a script. The script checks the target path against a list (.env, package-lock.json, .git/). Then it exits with code 2 to block the edit, and it gives Claude the reason so Claude can adjust.
  • Auto-approve prompts you always allow. Scope a PermissionRequest hook to a specific tool, like ExitPlanMode. The hook returns "behavior": "allow" in its JSON output. It skips a permission dialog that you approve every time anyway.
  • Re-inject context after compaction. A SessionStart hook with a compact matcher writes text to stdout. Claude Code adds that text back into context right after it summarizes Claude's memory. Reminders like project conventions survive the reset.

Each of these examples is a hooks block that you add to a settings file. Each block has the same structure as the notification example above.

Watch: Claude Code - Getting Started with Hooks.

Understand Events, Types, and Scope Before You Customize Further

Claude Code fires an event at each lifecycle point, and dozens of events exist.

PreToolUse fires before a tool runs. PostToolUse fires after it succeeds.

Stop fires when Claude finishes its response.

Claude Code runs every hook that you register against that event in parallel.

A hook has one of four types:

  • command runs a shell script (the default).
  • http posts the event to a URL.
  • prompt sends the input to a Claude model for a single yes/no judgment call.
  • agent spawns a subagent that can read files and run commands before it decides.

Use prompt or agent hooks for decisions that need judgment rather than a fixed rule.

A matcher narrows which occurrences of an event trigger the hook.

Use Edit|Write for tool-based events. Use compact for a SessionStart that compaction triggers.

Where you register a hook sets its scope:

~/.claude/settings.json         All your projects, not shareable
.claude/settings.json           This project, shareable via the repo
.claude/settings.local.json     This project, not shareable (gitignored)
Managed policy settings         Organization-wide, admin-controlled

A hook communicates back to Claude Code through its exit code.

Code 0 means that the action proceeds normally. Code 2 blocks the action and sends your stderr message to Claude as feedback.

Any other code lets the action proceed, but it shows a warning.

For finer control than block-or-allow, a hook can print structured JSON to stdout instead.

TRY THIS IN CLAUDE CODE

Goal: Add a guardrail hook that blocks Claude edits to a file that you consider off-limits.

  1. In a real project, pick a file that Claude must never edit directly (e.g. .env or a lockfile).
  2. Ask Claude Code: "Write a PreToolUse hook script that blocks edits to <your file> and explains why in the error message."
  3. Register the hook in .claude/settings.json with a PreToolUse event and an Edit|Write matcher.
  4. Ask Claude to edit that file directly. Confirm that the hook blocks the edit and shows your reason.

Expected result: Claude Code refuses the edit and shows your custom reason. Claude then adjusts its approach and does not retry the same blocked edit.

Watch: 5 Claude Code Hooks That Save Me Hours Every Day.
4.2

How To Build Skills In Claude Code

A skill is a SKILL.md file with instructions that Claude adds to its toolkit.

Claude loads a skill automatically when it is relevant. You can also invoke the skill directly with /skill-name.

Anthropic suggests that you create a skill when you paste the same instructions, checklist, or multi-step procedure into chat again and again.

Anthropic also suggests a skill when a section of your instructions file grows into a procedure rather than a fact.

Unlike always-loaded instructions, a skill's body loads into context only when Claude actually uses it.

Reference material sits there almost free until you need it.

Watch: What are skills?

Build Your First Skill: Summarize Uncommitted Changes

WALKTHROUGH

Goal: Create a skill that summarizes your git diff and flags anything risky, on demand or automatically.

  1. Create the skill directory:
    mkdir -p ~/.claude/skills/summarize-changes
  2. Save this to ~/.claude/skills/summarize-changes/SKILL.md:
    ---
    description: Summarizes uncommitted changes and flags anything risky. Use when asked what changed.
    ---
    
    ## Current changes
    
    !`git diff HEAD`
    
    ## Instructions
    
    Summarize the changes above in two or three bullet points, then list any risky changes.
  3. Open a git project with uncommitted changes. Then start Claude Code.
  4. Ask "What did I change?" and let Claude invoke the skill automatically. Or run /summarize-changes directly.

Expected result: Claude responds with a short summary of your edit and a list of risks. The !git diff HEAD line runs before Claude sees the skill. The instructions arrive with your actual diff already inline, and Claude does not go look for it.

Shape What the Skill Loads and Who Can Trigger It

Two kinds of content call for different setups.

  • Reference content (conventions, style guides, domain knowledge) runs inline so Claude can use it alongside the conversation.
  • Task content is a specific procedure, such as a deploy or a commit. You often want to trigger it yourself rather than leave it to Claude's judgment.

A handful of frontmatter fields control that:

description                     Recommended. What the skill does and when to use it;
                                this is what Claude reads to decide whether to load it.
disable-model-invocation: true  Only you can invoke the skill (e.g. /deploy). Use for
                                anything with side effects you want to control the timing of.
user-invocable: false           Only Claude can invoke the skill. Use for background
                                knowledge that isn't a meaningful action for a person to trigger.
allowed-tools                   Tools Claude can use without an approval prompt while
                                this skill is active, e.g. Bash(git add *) Bash(git commit *).
arguments                       Named positional arguments, available in the skill body
                                as $ARGUMENTS, $ARGUMENTS[0], or the shorthand $0, $1.

Keep the SKILL.md body concise.

Once Claude loads the body, it stays in the conversation for the rest of the session. Every line is a recurring token cost, so state what to do and not why.

Control Where a Skill Applies

Where you save a skill determines who can use it:

~/.claude/skills/<name>/SKILL.md        Personal: all your projects
.claude/skills/<name>/SKILL.md         Project: this project only
<plugin>/skills/<name>/SKILL.md        Plugin: wherever that plugin is enabled

For anything beyond the main procedure, add supporting files in the same directory. Use a reference doc, example outputs, or a helper script.

Link to those files from SKILL.md.

Claude loads those files only when the skill's instructions point to them. The core file stays focused.

Watch: Master 95% of Claude Code Skills in 28 Minutes.
TRY THIS IN CLAUDE CODE

Goal: Take a task that you ask Claude to do from scratch each time. Turn it into a reusable skill that you trigger.

  1. Pick a multi-step task that you repeat often (e.g. "stage and commit my changes following our commit message format").
  2. Create the skill directory and SKILL.md. Write the steps as numbered instructions.
  3. Add disable-model-invocation: true so the skill runs only when you type its name. Claude does not trigger it on its own judgment.
  4. Add an arguments field if the task needs input, such as a commit scope. Reference that field in the body with $ARGUMENTS.
  5. Run the skill by name. Confirm that it does exactly what the manual version did.

Expected result: A working /skill-name command that performs your repeated task end to end, only when you invoke it.

4.3

How To Connect MCP Servers To Claude Code

Claude Code can reach hundreds of external tools and data sources through the Model Context Protocol, an open standard for AI-tool integrations.

Connect a server when you copy data into chat from another tool. An issue tracker or a monitoring dashboard is one example.

Claude then reads and acts on that system directly, and it does not work from what you paste.

Watch: Claude Code MCP: How to Add MCP Servers (Complete Guide).

Connect Your First Server: A Hosted HTTP Server

WALKTHROUGH

Goal: Connect to a hosted MCP server end to end and confirm Claude can use it.

  1. In your terminal (not inside a Claude Code session), register the server:
    claude mcp add --transport http claude-code-docs https://code.claude.com/docs/mcp
  2. Check its connection status:
    claude mcp list
  3. Start a session. Then ask Claude to use the server by name: Use the claude-code-docs server to look up what MCP_TIMEOUT does.
  4. Approve the permission prompt the first time Claude calls the new tool.

Expected result: claude mcp list shows ✓ Connected. Claude's answer includes a tool call with the claude-code-docs server name on its label. That label confirms that the answer came from the server rather than Claude's built-in knowledge.

When you finish your experiment, remove the server with claude mcp remove claude-code-docs.

Each connected server loads its tool names and instructions into every session. Remove the servers that you do not use to keep that space free.

Connect a Local Server for Tools That Need Your Machine

A hosted server runs at a URL. A local stdio server runs as a program that Claude Code starts on your machine.

Use a local server for tools that need local resources, such as a browser, a filesystem, or a database socket.

The Playwright MCP server is a good one to try, because it needs no account:

claude mcp add playwright -- npx -y @playwright/mcp@latest

Everything after -- is the command that Claude Code runs to start the server.

Check the connection the same way with claude mcp list. Then give Claude a task that needs the browser: "Use playwright to open https://example.com and tell me the page title."

A browser window opens, and you watch it work.

Connect a Server That Needs Sign-In

Hosted services like Sentry, Linear, and Notion run their MCP servers behind OAuth.

Add the server's URL. Claude Code then prompts you to authenticate in your browser the first time you use it:

claude mcp add --transport http sentry https://mcp.sentry.dev/mcp

After you add the server, claude mcp list shows ! Needs authentication.

Open the /mcp panel. Select the server, and choose Authenticate.

Your browser opens to the service's sign-in page. After you approve, the server's status changes to connected.

Services that authenticate with a static token instead pass it directly: --header "Authorization: Bearer <token>".

Control Who Can Use a Server

Where you register a server controls its scope:

local (default)   ~/.claude.json, this project only, private to you
project           .mcp.json in the project root, shared via version control
user              ~/.claude.json, all your projects, private to you

You fix a server's scope when you add it. To change the scope, remove the entry and add it again with --scope project or --scope user.

Commit .mcp.json to share a server with your team. The first time a teammate opens the project, Claude Code prompts them to approve the server before it connects.

TRY THIS IN CLAUDE CODE

Goal: Connect a real external tool you actually use and complete one task through it.

  1. Pick a service that you use and that has a hosted MCP server, such as GitHub, Sentry, or Notion. Check the Anthropic Directory if you are not sure which one.
  2. Register it with claude mcp add --transport http <name> <url>. Add an auth header, or complete the OAuth sign-in as needed.
  3. Confirm that it shows ✓ Connected with claude mcp list.
  4. Ask Claude to do one real, specific task through the server. For GitHub, use "Review PR # and suggest improvements". For Sentry, use "What are the most common errors in the last 24 hours?"

Expected result: Claude's response contains a tool call with your server's name. The answer comes from your actual data in that service, and not from Claude's general knowledge.

4.4

How To Build Plugins In Claude Code

Everything in this module so far (skills, hooks, MCP servers) lives loose in your .claude/ directory, personal to you and this project.

A plugin bundles any combination of them into one self-contained folder that you can version, share with your team, or publish for the community.

According to Claude Code, standalone .claude/ configuration is still the right call for personal workflows and quick experiments.

Use a plugin when you want to share functionality or reuse it across projects. Use a plugin also to version and update it as a unit.

Watch: Claude Code Plugins Explained In 7 Minutes.

Build Your First Plugin

WALKTHROUGH

Goal: Package a skill as a working plugin and run it locally.

1. mkdir my-first-plugin
2. mkdir my-first-plugin/.claude-plugin
3. Create my-first-plugin/.claude-plugin/plugin.json:
   {
     "name": "my-first-plugin",
     "description": "A greeting plugin to learn the basics",
     "version": "1.0.0"
   }
4. mkdir -p my-first-plugin/skills/hello
5. Create my-first-plugin/skills/hello/SKILL.md:
   ---
   description: Greet the user with a friendly message
   disable-model-invocation: true
   ---
   Greet the user warmly and ask how you can help them today.
6. claude --plugin-dir ./my-first-plugin
7. Run /my-first-plugin:hello inside the session

Expected result: Claude greets you. /help lists the skill under the plugin's namespace in Custom commands. Plugin skills always carry a namespace (/my-first-plugin:hello), so two plugins can ship a skill with the same name and not collide.

While you iterate, edit SKILL.md. Then run /reload-plugins to pick up changes without a restart of the session.

Grow the Plugin: More Components, One Folder

A plugin is not limited to one skill.

Add sibling directories at the plugin root, and Claude Code picks them up automatically. Put nothing inside .claude-plugin/, which holds only plugin.json:

my-plugin/
├── .claude-plugin/plugin.json
├── skills/<name>/SKILL.md      # skills (Section 4.2)
├── agents/                     # subagents (Module 3)
├── hooks/hooks.json            # hooks (Section 4.1)
├── .mcp.json                   # MCP servers (Section 4.3)
├── .lsp.json                   # language servers for code intelligence
└── settings.json               # default settings applied when enabled

Hooks and MCP servers use the exact formats from earlier in this module. A plugin's hooks/hooks.json is the same JSON that you put in settings.json, and it applies only to the plugin.

There is one difference. Hook and MCP commands can reference ${CLAUDE_PLUGIN_ROOT}, an environment variable that points at the plugin's own directory.

A hook can then call a script that ships inside the plugin instead of a hardcoded path.

Watch: Claude Code Plugins Tutorial: Install & Build Your Own.

Install and Manage Plugins from a Marketplace

A marketplace is a catalog of plugins that someone else built. It comes as a marketplace.json in a GitHub repo, another git host, or a plain URL.

When you add a marketplace, you only register the catalog. The installation is a separate step.

An app store works the same way: when you add it, you do not download every app in it.

/plugin marketplace add anthropics/claude-code        # register a catalog
/plugin                                               # browse, install, manage: opens an interactive panel
/plugin install commit-commands@claude-code-plugins   # install by name, or do it from the Discover tab
/reload-plugins                                       # activate without restarting

Anthropic maintains two marketplaces:

  • claude-plugins-official, a curated set that Claude Code registers automatically on first launch.
  • claude-community, where third-party submissions land after an automated safety check. You add this marketplace manually with /plugin marketplace add anthropics/claude-plugins-community.

You browse both from the same /plugin panel:

  • Discover lists everything from every marketplace that you added.
  • Installed lets you enable, disable, or remove what you have.
  • Errors shows anything that failed to load.

Choose an installation scope when you install.

Use user for all your projects. Use project to share with collaborators via .claude/settings.json.

Use local for this repository and you alone.

Careful: plugins execute arbitrary code with your user privileges, so install only the ones that you trust. Anthropic does not vet what an MCP server or hook script actually does, even in the official marketplace.

Share What You Built

When you want to share your plugin:

1. Write a README.md with install and usage instructions
2. Pick a versioning strategy: set "version" in plugin.json, or rely on the git commit SHA
3. claude plugin validate ./my-plugin --strict   # catch schema issues before anyone installs it
4. Have a teammate test it before wider distribution
5. Create your own marketplace.json to distribute privately, or submit to
   the community marketplace via claude.ai or platform.claude.com/plugins/submit
TRY THIS IN CLAUDE CODE

Goal: Take a skill, a hook, or an MCP server that you built in this module. Turn it into a real plugin that you can install.

  1. Pick a skill, a hook, or an MCP server that you set up earlier in this module. Or invent a small one.
  2. Package it as a plugin. Create .claude-plugin/plugin.json. Then move the component into the matching directory (skills/, hooks/, or .mcp.json).
  3. Load it with claude --plugin-dir ./your-plugin. Confirm that it works the same as the unpackaged version.
  4. Add a second component to the same plugin, such as a hook next to your skill. Confirm that both load after /reload-plugins.
  5. Run claude plugin validate ./your-plugin --strict. Fix anything that it flags.

Expected result: One plugin folder bundles two or more components. It loads cleanly with --plugin-dir and passes strict validation, and you can hand it to a teammate or check it into a repo.

The Code: Your daily unfair advantage in software engineering.

Join 350,000+ software engineers, tech leads, and CTOs who start their morning with The Code.

Subscribe to Newsletter
4.5

How To Run Scripts And Schedules On Claude Code

So far, every task in this guide ran inside a session that you watch.

Claude Code can also run headlessly. It runs as one command in a script, a CI job, or a pipeline, with no one at the keyboard.

It can also run again and again, and it checks back on something without a new prompt from you each time.

Both use the same engine, the Agent SDK, that powers the interactive tool.

Run a One-Off Prompt Non-Interactively

Add -p (or --print) to any claude command. The command then runs non-interactively, and it does not open a session:

claude -p "Find and fix the bug in auth.py" --allowedTools "Read,Edit,Bash"

Claude Code exits with code 0 on success and non-zero on failure. A script can branch on the result.

All the CLI options that you use interactively work here too. Use --allowedTools to auto-approve specific tools.

Or use a permission mode like --permission-mode acceptEdits. It sets a baseline for the whole run instead of a list of tools one by one.

Add --bare for scripted and CI calls. It skips auto-discovery of hooks, skills, plugins, auto memory, and CLAUDE.md.

The run then behaves identically on every machine, whatever the configuration of that machine:

claude --bare -p "Summarize README.md" --allowedTools "Read"

Bare mode does not read your subscription login. Set ANTHROPIC_API_KEY in the environment first.

Anthropic notes that --bare is the recommended mode for scripted and SDK calls. It becomes the default for -p in a future release.

Non-interactive mode reads stdin. You can pipe data in like any command-line tool:

cat build-error.txt | claude -p 'concisely explain the root cause of this build failure'

Get Output You Can Parse

By default -p prints plain text. Two other formats make the result usable by other code:

--output-format json          # result, session ID, and cost as one JSON object
--output-format stream-json   # newline-delimited JSON, one event per token, for real-time consumers

Pair --output-format json with --json-schema to constrain the result to a schema that you define.

Then pull the parsed value out of structured_output with a tool like jq:

claude -p "Extract the main function names from auth.py" \
  --output-format json \
  --json-schema '{"type":"object","properties":{"functions":{"type":"array"}}}' \
  | jq '.structured_output'
TRY THIS IN CLAUDE CODE

Goal: Wire Claude into a real script-driven check, with output that your script can act on.

  1. Pick a repeatable check in your project. Use a lint pass, a typo scan on a diff, or a summary of a log file.
  2. Write a one-line script that pipes the relevant input into claude -p. Scope --allowedTools to only what the task needs.
  3. Add --output-format json. Confirm that you can pull total_cost_usd and the result text out with jq.
  4. Run the script twice: once against input that must pass, and once against input that must fail. Confirm that the exit code differs.

Expected result: A script that you can drop into a package.json script or a CI step. It has a predictable exit code, and your automation parses its JSON result without a scrape of plain text.

Run a Prompt Repeatedly with /loop

/loop re-runs a prompt on an interval inside a session that stays open.

Use it to poll a deployment, to watch a PR, or to check back on a long build.

What you give it changes how it behaves:

/loop 5m check if the deployment finished and tell me what happened   # fixed interval
/loop check whether CI passed and address any review comments        # Claude picks the interval each time
/loop                                                                # runs a built-in maintenance prompt, or your loop.md

When you omit the interval, Claude chooses a delay between one minute and one hour, based on what it observes.

Claude waits a short time while something is active, and longer once things go quiet. Claude prints the delay and its reason after each iteration.

Write your own default to replace the built-in maintenance prompt of the bare /loop.

Use .claude/loop.md at the project level, or ~/.claude/loop.md at the user level for any project without its own:

.claude/loop.md
Check the 'release/next' PR. If CI is red, pull the failing job log,
diagnose, and push a minimal fix. If new review comments have arrived,
address each one and resolve the thread. If everything is green and
quiet, say so in one line.

Press Esc to stop a loop while it waits between iterations.

A loop also ends automatically 7 days after you start it. Claude can end it earlier when Claude decides that the task is done.

For a single reminder rather than a recurring check, ask in plain language. You need no /loop:

remind me at 3pm to push the release branch
in 45 minutes, check whether the integration tests passed

See more on The Ultimate Guide to Loop Engineering.

Choose the Right Scheduling Mechanism

/loop has the scope of one session. It stops the moment you close the terminal, and a fresh conversation clears it.

When you resume with --resume or --continue, anything unexpired comes back.

Three other options exist for automation that must survive independently of any open session:

Routines          Anthropic-managed cloud infrastructure, runs without your machine on
GitHub Actions    A `schedule` trigger in your CI pipeline
Desktop tasks     Runs locally on your machine, persists across restarts
  • Use cloud tasks when the work must run reliably without anyone's laptop.
  • Use Desktop tasks when the job needs local files and tools, but must outlive a single session.
  • Use /loop for a quick poll while you work.
4.6

How To Set Up Goal And Make Claude Code Work Towards It

You saw earlier that /loop re-runs a prompt on a timer.

/goal is different. Instead of a schedule, you give Claude a condition.

Claude then takes turns on its own until that condition is verifiably true. You send no new prompt, and you tune no interval.

Use it for substantial work with a checkable end state.

One example is a migration of a module to a new API, until every call site compiles and tests pass.

Another example is a labeled issue backlog that Claude works through until the queue is empty.

Watch: Claude Code Just Dropped /Goal. (Master it in 8 Minutes).

Set a Goal and Let Claude Work Until It's Met

Run /goal with the condition that you want to satisfy:

/goal all tests in test/auth pass and the lint step is clean

This starts a turn immediately, and it uses the condition itself as the directive.

After each turn, a small fast model reads the condition against what Claude put in the conversation. The model answers yes or no with a short reason.

On no, Claude takes another turn and uses that reason as guidance.

On yes, the goal clears, and Claude Code records an achieved entry in the transcript.

Only one goal can be active per session. A new goal replaces the old one.

While a goal is active, a /goal active indicator shows how long it ran. Run /goal with no arguments at any time to check the status:

condition
how long it has been running
how many turns have been evaluated
current token spend
the evaluator's most recent reason

Write a Condition the Evaluator Can Actually Check

The evaluator does not run commands or read files on its own.

It only judges what Claude's own output already put in the conversation. A condition must be something that Claude can demonstrably produce.

"All tests in test/auth pass" works because Claude runs the tests and the result lands in the transcript for the evaluator to read.

A condition that holds up across many turns usually has three parts:

One measurable end state: a test result, a build exit code, a file count, an empty queue
A stated check: how Claude should prove it, e.g. "npm test exits 0" or "git status is clean"
Constraints that matter: anything that must not change on the way, e.g. "no other test file is modified"

Add a turn clause or a time clause to the condition itself to bound how long a goal runs. For example, "stop after 20 turns."

Claude reports progress against that clause each turn, and the evaluator judges it from the conversation. Conditions can run up to 4,000 characters.

Pair with Auto Mode for Unattended Runs

A goal does not change permissions on its own.

In the default permission mode, Claude still stops to ask before any tool call that your settings do not already allow.

That stop defeats the point, because you want to walk away.

Pair /goal with auto mode to approve tool calls automatically. Every turn of the goal then runs without you at the keyboard.

Clear or Resume a Goal

/goal clear   # remove an active goal before its condition is met

stop, off, reset, none, and cancel all work as aliases for clear. A fresh conversation with /clear also removes any active goal.

Suppose that a session ends while a goal is still active. When you resume it with --resume or --continue, the condition comes back.

The turn count, the timer, and the token-spend baseline all reset on resume.

A goal that Claude already achieved, or that you cleared before the session ended, does not come back.

Choose Between /goal, /loop, and a Stop Hook

Three approaches keep a session alive between prompts. Each one starts its next turn on a different trigger:

/goal       next turn starts when the previous one finishes; stops when a model confirms the condition
/loop       next turn starts on a time interval; stops when you stop it or Claude decides the work is done
Stop hook   next turn starts when the previous one finishes; stops when your own script or prompt decides

Under the hood, a /goal is really a prompt-based Stop hook with the scope of one session.

It fires the same evaluator logic, but it is a one-line shortcut instead of an entry in a settings file.

Write a real Stop hook when you need evaluation logic more custom than a plain-language condition.

Write a real Stop hook also when the same check must apply across every session, and not only this one.

TRY THIS IN CLAUDE CODE

Goal: Run a real multi-step task to completion with no new prompt from you.

  1. Pick a task with a checkable end state in your project. For example, fix every failing test in a directory. Or migrate the callers of a small function to a new signature, or clear a labeled set of TODOs.
  2. Write a condition with all three parts: a measurable end state, a stated check, and any constraint that must hold. Add a turn-count bound like "stop after 15 turns."
  3. Set the goal with /goal <your condition>. Then turn on auto mode so the goal runs unattended. Approve the permission mode change.
  4. Run /goal with no arguments partway through to check turns spent and the evaluator's latest reason.
  5. Let it run to completion. Then read the achieved entry in the transcript.

Expected result: Claude takes multiple turns on its own, and the status check shows real progress mid-run. The goal clears itself once the condition is genuinely true, and you send no follow-up prompt.

4.7

How To Share Claude Code Session As An Artifact

Some output is easier to look at than to read line by line.

Examples are an annotated diff, a dashboard from data that the session pulled, and several design options side by side.

An artifact turns that output into a live, interactive web page. Claude publishes the page from your session to a private URL on claude.ai.

The output does not stay as scrollback in the terminal.

Watch: Artifacts in Claude Code: share your work as it happens.

Create and Update an Artifact

Claude may publish an artifact on its own when the output suits a page.

You can also ask for one directly. Name the feature, or describe the visual output that you want:

Make an artifact that walks through this PR with the diff annotated inline.
Build a dashboard artifact of last week's deploy failures by service and keep it updated as you investigate.

Claude writes the page to an HTML or Markdown file in your project. Then Claude publishes it.

Claude Code asks for permission before it publishes a new artifact. It does not prompt again when it republishes one that you already approved.

After Claude publishes the page, it prints the URL, and your browser opens to the page.

Press Ctrl+] at any time to reopen the most recent artifact from the terminal.

To update an artifact, ask Claude to revise it. Or let a long-running task republish the page as it makes progress.

Anyone with the page open sees the update in place.

To update an artifact from a different session, give Claude the URL and ask for a revision. Without the URL, a new session always creates a new artifact instead.

Share What You Built

Only you can see a new artifact.

Open it in your browser. Then use the Share control in the page header to change that:

Within your organization   grant access to specific people or everyone (Team, Enterprise)
Publicly                   share a link anyone on the internet can open, no sign-in required

The people that you share with are viewers by default. They see each version that you publish, but they cannot change the page.

On Team and Enterprise plans, you can also make someone an editor in the share dialog.

That editor gives Claude the artifact's URL from their own session and publishes new versions.

What You Can Build

An artifact is a single HTML page. Anything that HTML, CSS, and inline JavaScript can express is in scope.

These patterns come up most:

Walk through a change:      render a diff or design change with annotations beside the relevant lines
Compare alternatives:       lay out several variants of a layout, API shape, or plan on one page
Tune with interactive controls: sliders, toggles, or inputs bound to whatever you're adjusting
Bring the result back:      add an export control that produces text you can paste into the terminal
Track work in progress:     keep a checklist or timeline current while a long task runs

Know the Constraints

An artifact is one self-contained page with no backend. It runs under a strict content security policy:

No external requests   scripts, styles, fonts, and images from other hosts are blocked;
                       connector calls are the one exception, made through claude.ai itself
No backend             can't store form input or authenticate viewers; its only path to
                       outside data is calling MCP connectors
Single page            relative links don't resolve; multi-section content uses in-page anchors
File types             must publish as .html, .htm, or .md
Size limit             the rendered page must be 16 MiB or smaller

Artifacts require a Pro, Max, Team, or Enterprise plan. They also require a session that you sign in with /login.

When your setup misses a requirement, Claude writes a local HTML file, or Claude says that it cannot publish.

TRY THIS IN CLAUDE CODE

Goal: Turn a piece of real session output into a shareable artifact.

  1. Pick something from your project that is easier to see than to read. Use a recent diff, a set of test results, or a small dataset in your codebase.
  2. Ask Claude to build an artifact from it. Name the visual format that you want: an annotated walkthrough, a dashboard, or a comparison layout.
  3. Approve the publish prompt. Confirm that the page opens with Ctrl+].
  4. Ask Claude to revise the page, for example to add a section or to change the layout. Confirm that the update appears in place at the same URL.
  5. Open the Share control. Set it to a scope that you actually use, either within your organization or a public link.

Expected result: A live URL that you can hand to a teammate right now. It shows real output from your session, and it updates in place the next time you ask Claude to revise it.

END OF MODULE 4

By this point you should have:

  • Added a hook that enforces a rule deterministically, and a skill that packages a repeated task into a reusable command.
  • Connected a real MCP server and completed a task on that service's own data.
  • Packaged multiple components into a plugin, installed one from a marketplace, and shared your own.
  • Wired Claude into a script-driven check with parseable output, and set up a schedule that checks back with no new prompt from you.
  • Run a real multi-step task to completion unattended with /goal, and published a live artifact from your session.

You now have the full feature set that Claude Code offers a single agent.

You know how to extend it with hooks, skills, MCP, and plugins. You also know how to run it when you do not watch: scripts, schedules, goals, and artifacts to show for the work.