hubagenticai

Tutorials Beginner · 5/8

Claude Code from zero: an agentic coding workflow, step by step

Install Claude Code, learn the core loop, and build up to a disciplined agentic workflow: CLAUDE.md, plan mode, custom skills, hooks, and MCP servers.

updated 2026-10-08 ⏱ 50 min

Agentic coding tools reward workflow discipline far more than prompt cleverness. This tutorial sets up Claude Code and then focuses on the habits that separate “autocomplete with extra steps” from an agent that does real work while you review it. Most of these habits carry over to other coding agents too (Codex CLI, Gemini CLI, Cursor and others), because the building blocks (an instructions file, skills, MCP) are now shared conventions.

Step 1 — Install and authenticate

The recommended install is the native installer. It has no Node.js dependency and updates itself in the background:

# macOS, Linux, WSL
curl -fsSL https://claude.ai/install.sh | bash
# Windows PowerShell
irm https://claude.ai/install.ps1 | iex

Other routes, if your machine policy prefers a package manager: brew install --cask claude-code (Homebrew), winget install Anthropic.ClaudeCode (Windows), signed apt/dnf/apk repositories (Linux), or npm install -g @anthropic-ai/claude-code. The npm route needs Node.js 22 or later. Homebrew, WinGet and the Linux repos don’t auto-update, so upgrade them yourself.

Open a new terminal and check the install:

claude --version     # prints e.g. "2.1.287 (Claude Code)"
claude doctor        # read-only health check of the install and settings

Then start it inside your project:

cd your-project
claude

The first run opens a browser to log in. If you use an API key instead, set ANTHROPIC_API_KEY before starting and approve it when asked. Inside the session, /status shows the version, model, and account you’re on.

Step 2 — Give the agent a memory: CLAUDE.md

Claude Code reads CLAUDE.md from your project root at the start of every session. This is the highest-leverage file in the whole workflow. Run /init to have Claude draft one from your codebase, then cut it down. A good one is short and factual:

# CLAUDE.md

## Project
Payment reconciliation service. Python 3.12, FastAPI, PostgreSQL.

## Commands
- Test: `pytest -q`
- Lint: `ruff check .`
- Run locally: `make dev`

## Conventions
- Type hints everywhere; mypy must pass.
- Never touch `migrations/` by hand.

Rule of thumb: anything you’d tell a new teammate on day one belongs here. Anything you’d tell them once, in one specific situation, does not (that’s a skill, Step 6).

Already have an AGENTS.md? Claude Code reads a repository’s AGENTS.md as its project instructions when there is no CLAUDE.md, so a repo set up for other coding agents works as is. If you keep both, Claude reads only CLAUDE.md by default. Put @AGENTS.md inside your CLAUDE.md to import one into the other and keep a single source of truth.

Step 3 — The core loop: plan first, then execute

For any non-trivial task, don’t let the agent code immediately. Press Shift+Tab to cycle the permission mode (Manual → accept edits → plan) until the indicator shows plan mode, or type /plan followed by the task. In plan mode Claude reads and proposes but doesn’t edit. Read the plan it produces. You are reviewing the approach while it’s still cheap to change. Then approve, and let it execute against the plan.

The habit that matters: review at the plan level and the diff level, not keystroke level. You’re a tech lead now, not a typist. If a change goes wrong, /rewind rolls the conversation and the code back to an earlier checkpoint.

Step 4 — Let it verify its own work

An agent that can run your tests can check itself. End tasks with an explicit verification instruction:

Implement the fix, then run pytest -q and iterate until green.

This single habit converts “plausible-looking code” into “code that passed the suite before you ever read it.”

Step 5 — Extend it with an MCP server

Claude Code speaks MCP natively. Connect any server. Everything after -- is the command that starts it, so use absolute paths (and the venv’s own Python):

claude mcp add hello-mcp -- /full/path/to/.venv/bin/python /full/path/to/server.py
claude mcp list
hello-mcp: /full/path/to/.venv/bin/python /full/path/to/server.py - ✔ Connected

That’s the server from our first MCP server tutorial; we ran it here with mcp 2.3.0. By default the server is registered for you, in this project only (--scope local). Use --scope project to write it to a .mcp.json file your team commits. Claude Code asks each person to approve project-scoped servers on first use, so claude mcp list shows them as “Pending approval” until someone starts claude and says yes. Use --scope user to make a server available in all your projects.

You don’t pay for idle servers: by default Claude Code uses tool search. Only tool names load at session start, and full tool definitions load when Claude needs them. Adding servers costs little context. (The MCP vs. CLI comparison measures what that saves.)

Step 6 — Teach it a repeatable task with a custom skill

A skill is a folder with a SKILL.md file: a short description Claude always sees, plus instructions it loads only when needed. Create .claude/skills/changelog-entry/SKILL.md:

---
name: changelog-entry
description: Write a one-line CHANGELOG entry for the current uncommitted changes. Use when the user asks for a changelog entry or release note.
disable-model-invocation: true
allowed-tools: Bash(git diff *) Bash(git status *)
---

Write ONE changelog line for the uncommitted changes in this repo.

1. Run `git status --short` and `git diff` to see what changed.
2. Output a single line in the form `- <type>: <what changed, for a user>`,
   where <type> is one of feat, fix, docs, chore.
3. Do not edit any files.

Run it by typing /changelog-entry in a session. The folder name becomes the command. We ran it on the demo project and got:

- feat: Add MCP server demo with add tool

What the frontmatter does:

  • description is what Claude reads to decide when a skill is relevant. Write it as “what it does + when to use it”.
  • disable-model-invocation: true means only you can trigger it. Remove it and Claude may load the skill on its own when a request matches the description.
  • allowed-tools pre-approves the read-only git commands the skill needs, so you aren’t prompted each time.

Two things worth knowing. First, custom slash commands and skills are now the same thing: an older .claude/commands/deploy.md file still works, but new work should be a skill. Second, SKILL.md follows the open Agent Skills format, which other coding agents also read. The Agent Skills tutorial covers writing skills that travel between tools.

Step 7 — Add a guard that can’t be talked out of it: a hook

Your CLAUDE.md says “never touch migrations/ by hand”. That is an instruction, and the model can forget instructions. A hook is a script Claude Code runs on an event, outside the model. Create .claude/hooks/protect-migrations.py:

#!/usr/bin/env python3
"""PreToolUse hook: block any edit or write under migrations/."""
import json, sys

event = json.load(sys.stdin)
path = event.get("tool_input", {}).get("file_path", "")
if "/migrations/" in path or path.startswith("migrations/"):
    print("migrations/ is generated. Create a migration with `make migration`.",
          file=sys.stderr)
    sys.exit(2)   # exit 2 = block the tool call and show stderr to Claude
sys.exit(0)

Make it executable (chmod +x), then register it in .claude/settings.json:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          {
            "type": "command",
            "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/protect-migrations.py"
          }
        ]
      }
    ]
  }
}

When we asked Claude to create migrations/001_init.sql, the write was blocked and Claude reported the hook’s message back verbatim. Use exit code 2 to block. Exit 1 is treated as a non-blocking error, and the action goes ahead. Run /hooks in a session to see what’s registered.

Two more building blocks, briefly. Subagents (Markdown files in .claude/agents/) run a task in their own context window and return only a summary, which keeps big searches out of your main session. Plugins (/plugin) bundle skills, hooks, subagents and MCP servers so a team can install one package instead of copying folders. When to reach for which: skills vs. tools vs. hooks vs. subagents.

Troubleshooting

claude: command not found right after installing

The native installer puts the launcher in ~/.local/bin. Open a new terminal; if it’s still missing, add ~/.local/bin to your PATH. claude doctor then confirms the install.

npm prints EBADENGINE during install

The npm package declares Node.js 22+. On older Node it warns but still installs, because it downloads a native binary. Upgrade Node or use the native installer instead. Never use sudo npm install -g.

An MCP server shows “Pending approval” in claude mcp list

It was added with —scope project (a .mcp.json file). Start claude in that folder and approve it. We hit this when testing; local-scope servers don’t need the approval step.

The hook runs but doesn’t block anything

Check the exit code: only exit 2 blocks. An unhandled Python exception exits with 1, which Claude Code treats as a non-blocking error. Test the script by piping a fake event into it. This should print the message and then 2:

echo '{"tool_input":{"file_path":"migrations/x.sql"}}' | .claude/hooks/protect-migrations.py; echo $?
The agent keeps “fixing” things you didn’t ask about

Scope creep is a prompting problem. Add “Do not change anything outside src/billing/” style constraints to the task, and put standing boundaries (“never edit generated files”) in CLAUDE.md, or in a hook if it must never happen.

Long session starts giving worse answers

Context windows fill up. /context shows what is using the space. Use /compact at natural breakpoints, or /clear between unrelated tasks: a fresh session with a good CLAUDE.md beats a bloated one.

Where to go next

The same plan-then-delegate habit, written as code, is the orchestrator and sub-agents pattern. To give Claude Code tools for your own systems, see wrap a REST API in MCP.

newsletter

One practical agentic-AI guide in your inbox. No news, no hype.

Tutorials and decision frameworks as they ship. Unsubscribe anytime.

Quick Jump: