# From plan to working code with Claude Code

URL: https://developertoolkit.ai/en/claude-code/build/implementation/
Description: Turn an approved plan into committed code with Claude Code: commit-sized slices, hook-enforced gates, evidence per slice and clean resumes across sessions.

Claude Code turns an approved plan into working code through a slice loop: ground the session in the plan and the existing code, split the plan into commit-sized slices, implement one slice at a time behind hooks that lint every edit and refuse to stop on failing tests, check each slice's evidence, and commit it before the next one starts.

This page is for developers who hold an approved plan and have to ship it, and for tech leads who decide which gates every slice must pass. The situation: the plan touches 12 files across the schema, a service, routes and the UI. You ask Claude Code to "implement the plan", and 40 minutes later you face a 900-line diff that ignores your error-handling pattern, edits a test to make it pass, and cannot be reviewed.

If the plan does not exist yet, write it first with [feature planning in Claude Code](/en/claude-code/plan/feature-planning/). If this is your first feature with Claude Code, start with [build your first feature](/en/claude-code/quick-start/development-workflow/), which walks one ticket end to end. This page is the loop for longer implementations. Working in another tool? The Cursor version of multi-file, test-first implementation is in [Cursor agent and chat workflows](/en/cursor-ide/build/agent-chat/).

## What you'll walk away with from the plan-to-code loop

- A two-hook setup that makes "the tests pass" a fact Claude Code cannot skip.
- Four copy-paste prompts: the pattern brief, the slice list, the slice implementation, and the evidence report.
- A rule for what you read per slice, and what you trust to tests and gates instead.
- A resume routine that picks up a three-day implementation without re-explaining it.
- Recovery steps for the six ways this loop usually breaks.

## How does the plan-to-code loop work in Claude Code?

Every slice goes through the same five steps. The plan is the contract, the slice is the unit of work, and the commit is the checkpoint you can return to.

| Step | Claude Code does | You check | Evidence |
| --- | --- | --- | --- |
| Ground | Reads the plan and two or three files that show your patterns | The pattern brief matches how your team writes code | A short brief in the conversation |
| Slice | Splits the plan into slices, each with a file list and a "done when" line | Order, size, and that every acceptance criterion lands in some slice | A slice list saved in the plan file |
| Implement | Writes one slice, including its tests | Nothing yet: the gates run first | Hook output: lint and tests |
| Verify | Reports test output, `git diff --stat` and deviations from the plan | Test names, the file list, public interfaces | The evidence report |
| Commit | Commits the slice with a message that names the slice | The message and a green suite | One commit per slice |

Order the slices by dependency: types and schemas, then the data layer, then services, then routes, then the UI. Each layer then compiles against something that already exists. Tracing dependencies and running cross-cutting renames are covered in [multi-file workflows](/en/claude-code/build/multi-file-workflows/).

## Set up the gates before the first slice

Gates are what let you stop reading every line. Two [hooks](/en/claude-code/automate/hooks-automation/) do most of the work: a `PostToolUse` hook that formats and lints each edited file, and a `Stop` hook that runs the test suite and blocks the turn from ending while it fails. The hooks page has both scripts, `format-and-lint.sh` and `tests-before-stop.sh`, with fixture tests. Register them in the project's `.claude/settings.json`:

```json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/format-and-lint.sh", "args": [], "timeout": 60 }]
      }
    ],
    "Stop": [
      { "hooks": [{ "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/tests-before-stop.sh", "args": [], "timeout": 300 }] }
    ]
  }
}
```

A `PostToolUse` hook receives the event as JSON on stdin and reads the edited path from `.tool_input.file_path`; there is no `$FILE_PATH` variable. To feed a lint error back to Claude, the script writes it to stderr and exits with code 2. Exit code 1 only shows a "hook error" notice, and the work continues. Open `/hooks` in a session to confirm that both hooks loaded.

Keep the type checker out of the per-edit hook. Running `tsc --noEmit` after every edit costs seconds per file on a large project, and mid-slice the types are often broken on purpose. Run it in the `Stop` hook or in the evidence step instead.

Then start a named session so you can find it again later:

```bash
# Terminal, from the repository root
claude -n org-management
```

With Claude Code v2.1.283 or later (both release channels on 2026-10-12), interactive terminal sessions start in auto mode, so a classifier approves most commands without asking you. Add `deny` or `ask` rules for anything a checkpoint cannot undo, such as `Bash(git push *)` and migration commands against shared databases. See [error recovery](/en/claude-code/quick-start/error-recovery/) for what `/rewind` does and does not restore.

## Ground the session in the plan and the code

Context from the planning session does not carry into a new one, and a plan names files without showing how they are written. Ask for a pattern brief before any edit. The brief is short enough to check in one minute, and it becomes the reference you point back to when the code drifts.

**Copy-paste prompt: pattern brief before implementing**

```text
Read docs/plans/org-management.md, then read these files:
- src/services/user.service.ts
- src/routes/user.routes.ts
- src/schemas/user.schema.ts
- tests/services/user.service.test.ts

Do not edit anything. Write a pattern brief of at most 15 bullets:
naming, error handling (which error class, how it maps to HTTP),
validation (where Zod schemas live and where .parse() is called),
transaction handling, logging, and how tests build fixtures.
Quote the file and line for each bullet. If two files disagree on
a pattern, say so and ask me which one wins.
```

Correct the brief if it is wrong. Correcting one bullet here costs less than correcting the same pattern in eight files later. If the brief contradicts your `CLAUDE.md`, fix the `CLAUDE.md` too; see [the memory system](/en/claude-code/build/memory-system/).

## Turn the plan into commit-sized slices

A slice is the largest change that still passes the whole suite on its own and that you can judge from its evidence. In practice that means one layer of one feature, touching roughly three to six files. The "done when" line for each slice has to be something a test or a command can prove, which is easiest when the plan already carries [executable acceptance criteria](/en/workflows/plan/acceptance-criteria/).

**Copy-paste prompt: slice the plan**

```text
Using the plan and the pattern brief, split the work into slices.
For each slice give:
1. A name that works as a commit subject (under 72 characters)
2. The exact files it creates or modifies
3. Which acceptance criteria from the plan it satisfies
4. "Done when": the test file(s) and command that prove it
5. Anything it depends on from an earlier slice

Rules: every slice must leave the full test suite green. No slice
touches more than 6 files. Order by dependency: types and schemas,
data layer, services, routes, UI. Every acceptance criterion must
appear in exactly one slice. Append the list to
docs/plans/org-management.md under "## Slices" and stop.
```

Review the slice list as you would review a pull request description. Look for a criterion that no slice claims, a slice that touches files outside the plan, and a "done when" line that says "works correctly" instead of naming a test. For a risky slice, such as a migration or an authorization change, run `/plan` (or press `Shift+Tab` until plan mode is on) and approve a file-by-file plan for that slice alone before any edit.

## Implement one slice at a time

Name the slice, restate its boundary, and say what Claude must not touch. The boundary is what keeps the diff reviewable.

**Copy-paste prompt: implement one slice**

```text
Implement slice 2 from docs/plans/org-management.md
("Add organization service with CRUD operations").

- Follow the pattern brief. Where the brief is silent, copy
  user.service.ts rather than inventing a new pattern.
- Write the tests in tests/services/org.service.test.ts first and
  run them to show they fail, then implement until they pass.
- Touch only the files the slice lists. If you need another file,
  stop and tell me why before editing it.
- Do not edit existing tests or test fixtures. If an existing test
  fails, report it; do not change it.
- Do not start slice 3.
```

From v2.1.280, the default model is Claude Opus 5.5, and it runs at `medium` effort in Claude Code. When a slice keeps failing on the same logic, raise effort with `/effort high` before you consider another model; the [models hub](/en/ecosystem/models/) explains when switching is worth it.

## How do you verify a slice without reading every line?

The `Stop` hook has already proved that the suite is green. What is left is to check that the right things are green and that the change stayed inside its boundary. Ask for the evidence in one message, and read that message instead of the diff.

**Copy-paste prompt: evidence report for a slice**

```text
Before I commit slice 2, give me an evidence report:
1. The exact test command you ran and its summary line
2. The names of the new tests, grouped by acceptance criterion
3. Output of: git diff --stat
4. Any file changed that the slice did not list, and why
5. Any change to an exported function signature or a type
6. Any deviation from the plan or the pattern brief
7. Run the type checker and paste its last 10 lines
Do not fix anything in this turn. Only report.
```

Read these parts yourself, because tests cannot judge them:

- **The test names and assertions.** A test called `creates organization` that asserts only `expect(result).toBeDefined()` proves nothing. Check that each acceptance criterion has a test that would fail if the behaviour broke. See [how to protect the oracle](/en/workflows/test/protect-the-oracle/).
- **The file list against the slice.** An unexpected file is the cheapest signal of drift.
- **Public interfaces.** Exported signatures, API responses and schema changes outlive the slice, so read them in full.

For a second opinion without spending your attention, run the bundled `/code-review` skill on the uncommitted diff. It reviews in a fresh context, so it does not share the implementing conversation's assumptions. You still decide what to accept. The developer signs off each slice on this evidence. The pull request reviewer signs off the whole change on the collected evidence of all slices, as described in [the evidence bundle](/en/workflows/ship/evidence-bundle/).

## Commit each slice as a checkpoint

Commit as soon as a slice's evidence is clean. A commit per slice gives `git bisect` something to work with and gives the reviewer a story to follow. It also gives you a floor to fall back to that survives the session.

```text
The evidence is clean. Commit slice 2 with the slice name as the
subject line and a body listing the acceptance criteria it covers.
Then mark slice 2 as done in docs/plans/org-management.md.
```

Checkpoints and commits do different jobs. `/rewind` (or `Esc` twice on an empty prompt) restores code and conversation to an earlier prompt within the session, which is right for a bad turn in the middle of a slice. Checkpoints track only Claude's file-editing tools, not files changed by shell commands such as a code generator, so a commit is the only reliable undo for a finished slice.

## Run independent slices in parallel

Slices with no dependency between them, such as the organization settings UI and the audit log exporter, can run at the same time. Claude Code offers two ways:

- **Subagents** run inside your session, report back to it, and run in the background by default. Use them for work that shares a working tree and does not edit the same files, such as writing tests for slice 3 while you review slice 2. See [custom subagents](/en/claude-code/automate/custom-subagents/).
- **Worktrees** give each session its own checkout and branch. Start one with `claude -w org-audit-export`. Use them when two slices would otherwise edit the same files or run conflicting migrations.

For a mechanical change that splits into many identical units, such as moving 20 routes to a new error type, the bundled `/batch` skill does the fan-out for you: it decomposes the change into 5 to 30 units and runs each in a background subagent with its own worktree. Codex users get the same lane-per-worktree pattern from [Codex multi-agent workflows](/en/codex/automate/multi-agent-workflows/).

Parallel slices still pass the same gates. The hooks in `.claude/settings.json` are committed, so every worktree gets them.

## Resume the implementation in a new session

A long implementation spans several sessions, and the conversation is the least reliable place to keep its state. Keep the state in the plan file and in git, so a new session can rebuild it in one prompt.

At the end of a session, ask Claude to write the status into the plan: slices done with their commit hashes, the next slice, decisions made during implementation, and open questions. The next day, run `claude --resume org-management`, which opens the session picker filtered to that name, or start a clean session and ground it again:

**Copy-paste prompt: resume an implementation**

```text
Read docs/plans/org-management.md, including "## Slices" and the
status notes, and run: git log --oneline -15
Tell me which slices are committed, which slice is next, and any
open question the notes record. Re-read the pattern brief files
before you edit anything. Do not start implementing until I confirm
the next slice.
```

When the context fills in the middle of a slice, run `/compact Keep the slice list, the pattern brief and the current slice's progress; drop the exploration`. Between slices, a fresh session with the resume prompt is usually cleaner than compacting. To rename a session that you started without `-n`, run `/rename org-management`.

## What breaks when you turn a plan into code with Claude Code?

**The code works but does not look like the rest of the codebase.** The pattern brief was skipped or is too vague. Recovery: `/rewind` to the prompt before the slice, correct the brief with the file and line that shows the right pattern, and rerun the slice prompt.

**A test was changed to make the suite pass.** The `Stop` hook is satisfied, but the evidence report shows a modified file under `tests/` that the slice did not list. Recovery: restore the test with `git restore tests/<file>`, then ask Claude to explain why the original assertion fails. To make this impossible rather than detected, add a permission rule such as `Edit(/tests/**)` to `ask` or `deny` during implementation slices. The leading slash anchors the pattern to the project root in project settings; without it, the path is matched relative to the directory the session started in.

**The plan turns out to be wrong in the middle of a slice.** Claude finds a constraint the plan missed and starts working around it. Recovery: "Stop. Describe what the plan did not account for and propose a change to the plan and the slice list. Do not edit code." Update the plan file first, then continue. A silent workaround becomes a surprise in review.

**Every slice is green, but the feature does not work end to end.** The slices were tested in isolation only. Recovery: add one slice whose only job is an integration or end-to-end test of the main user path, and run it after the route slice. See [testing with Claude Code](/en/claude-code/test/testing/).

**The Stop hook loops or makes every turn slow.** The suite takes minutes, or a flaky test fails at random. Recovery: scope the hook to the affected package or test pattern during implementation, and run the full suite in the evidence step and in CI. Quarantine a flaky test in a separate commit instead of letting Claude retry until it passes. Make sure `tests-before-stop.sh` exits 0 when the input's `stop_hook_active` is true, so a second failure hands control back to you instead of looping.

**A slice grows past its file list.** The slice was too big, or a shared type had to change. Recovery: stop, commit nothing, and ask Claude to split the remaining work into two slices. If a shared module changed, run the full suite before you continue, and note the module in the plan as one that needs the full suite.

## Where to go next after the implementation

- [Test generation and TDD with Claude Code](/en/claude-code/test/testing/) — Lock the test file, run red-green-refactor, and prove the suite catches bugs.
- [Automated code reviews with Claude Code](/en/claude-code/ship/review-automation/) — Pre-commit checks, pull request analysis and quality gates that run before a human reviews.
- [Goal workflows with /goal](/en/claude-code/automate/goal-workflows/) — Let Claude Code run a slice list unattended, with a finish line an evaluator can judge.
- [CLI debugging workflow](/en/claude-code/test/debugging/) — Trace a failure that shows up during implementation from the terminal.
