exit lab

Engineering Lab · Reference

Agent Coding Handbook

Claude Code and Codex, from first install to unattended runs. Written to be read once end to end, then opened at a single section on the day you need it.

Version
1.0.0
Updated
2026-09-10
Sections
18
Sources
24 primary

Where to start

Contents · 18 sections

Part 1

Foundations

What a coding agent actually does, how to install both tools, and how they map onto each other.

Section 1

FoundationBoth tools

A coding agent is a loop, not a chat box

Read this first. Everything else in the handbook configures one part of the loop described here.

A chat model answers once. A coding agent runs a loop: it reads your goal, gathers evidence from the real repository, decides on one action, executes it through a tool, observes the result, and decides again. It stops when the goal is met or when it needs you.

The model supplies reasoning. Everything around it — which files it can see, which commands it may run, what happens after each edit, what counts as done — is the harness. claude and codex are harnesses. Configuring them well is the whole job.

The agent loop, one turn at a time

Every task you give either tool walks this cycle. Failures do not end the run — they re-enter it at the point that produced them.

Your promptThe goal and its constraints
Load instructionsCLAUDE.md / AGENTS.md, rules
Gather contextRead, grep, glob the repo
PlanOrder the verifiable steps
ActEdit, run, call an MCP tool
Hooks fireDeterministic pre/post automation
ObserveExit codes, diffs, test output
Quality gateBuild, test, lint, review
Your approvalPermission prompts and plan review
Commit / PRNormal source-control controls
HandoffState, evidence, open risks
  • gateact · Gate fails — fix and re-run
  • observecontext · Missing evidence — gather more
  • approveplan · Approval denied — re-plan
LegendHuman boundaryAgent stepChanges real stateFailure path

The six parts you configure

Every feature in the rest of this handbook belongs to exactly one of these. When something goes wrong, name the part first — it tells you which file to open.

PartQuestion it answersWhere you configure itHandbook section
InstructionsWhat are the standing rules here?CLAUDE.md, AGENTS.md, .claude/rules/§5, §6
ContextWhat can the model actually see right now?Retrieval, /context, compaction§4
SkillsHow is this repeated job done properly?SKILL.md files§7
ToolsWhat is the agent allowed to touch?Built-in tools, MCP servers§9
ControlWhat is blocked, and what needs me?Permissions, sandbox, hooks§11, §12
VerificationHow do we know it worked?Quality gates, review, evals§14, §17

Section 2

FoundationBoth tools

Install both tools and reach a first real task

Get from nothing to a verified, committed change in one sitting.

Install Claude Code

Claude Code — pick one
# macOS, Linux, WSL
curl -fsSL https://claude.ai/install.sh | bash

# Windows PowerShell
irm https://claude.ai/install.ps1 | iex

# Homebrew (does not auto-update; run 'brew upgrade claude-code')
brew install --cask claude-code

# WinGet (does not auto-update)
winget install Anthropic.ClaudeCode

Native installs update themselves in the background. On native Windows, install Git for Windows as well — without it Claude Code falls back to PowerShell for its shell tool instead of Bash.

Install Codex

Codex CLI — install and update
# Install (and later, update — same command)
curl -fsSL https://chatgpt.com/codex/install.sh | sh

# First run signs you in with your ChatGPT account
codex

Your first task, in the right order

  1. Generate the instruction fileRun /init in either tool. Claude Code writes CLAUDE.md; Codex writes AGENTS.md. Both read the codebase first and propose build commands and conventions.
  2. Read what it wroteThis file is loaded into every future session. Delete anything the agent can already derive from the code, and keep the things it cannot — pitfalls, rationale, conventions that differ from the tool defaults.
  3. Ask a read-only question first"Explain how authentication flows through this repo, and cite the files." You are checking whether the agent can find things before you let it change things.
  4. Give it one bounded changeOne file, one behaviour, with a test you can run. Ask for the plan before the edit.
  5. Verify yourselfRun the build and the tests in your own terminal, then read the diff. Never approve a diff you have not read.
  6. Write down what you correctedThe first correction you repeat twice belongs in CLAUDE.md or AGENTS.md. This is how the setup compounds.

Section 3

FoundationBoth tools

Claude Code and Codex, side by side

The same seven concepts exist in both tools under different filenames. Learn the mapping once.

Both tools are terminal-first agent harnesses with an IDE extension, a cloud runner, and a GitHub integration. They differ in file layout and in how permissions are expressed, not in the shape of the loop.

Concept-for-concept mapping
Claude CodeCodex
Standing instructionsCLAUDE.md (also ./.claude/CLAUDE.md, CLAUDE.local.md)AGENTS.md (plus AGENTS.override.md)
Scoped instruction files.claude/rules/*.md with paths: frontmatterNested AGENTS.md per directory
Configuration file.claude/settings.json (JSON).codex/config.toml (TOML)
Reusable procedures.claude/skills/<name>/SKILL.md, run as /name.agents/skills/<name>/SKILL.md, run as $name
Delegated agents.claude/agents/*.md subagentsCloud tasks and codex exec runs
External tools.mcp.json / claude mcp add[mcp_servers.*] in config.toml / codex mcp add
Permission controlpermissions.allow/ask/deny rules + sandboxapproval_policy + sandbox_mode + permission profiles
Lifecycle automationHooks on ~30 events in settings.jsonNo equivalent hook system — use CI and git hooks
Non-interactive runclaude -p "..."codex exec "..."
Bootstrap command/init/init

Running both tools on one repository

Claude Code reads CLAUDE.md, not AGENTS.md. Keep one source of truth by writing AGENTS.md and importing it, so a change in shared conventions never has to be made twice.

CLAUDE.md
@AGENTS.md

## Claude Code only

Use plan mode for changes under `src/billing/`.
Run `pnpm test` before reporting a task complete.

Part 2

Context and instructions

What the agent sees at the start of a session, what you can put there on purpose, and what survives a long run.

Section 4

Working knowledgeBoth tools

The context window is a budget you spend

Know exactly what is loaded before you type, and what happens when the session runs long.

Every session starts with a fresh context window and immediately fills part of it before you say anything. Knowing the running order tells you why an instruction was ignored — usually it was never loaded at all.

Claude Code startup order
#What loadsVisible to you?
1System prompt — behaviour, tool use, response formatNo
2Auto memory — first 200 lines or 25 KB of MEMORY.mdNo
3Environment info — cwd, platform, shell, git branch and statusNo
4MCP tool names (schemas stay deferred until needed)No
5Skill descriptions — names and one-liners, not bodiesNo
6~/.claude/CLAUDE.md — your personal instructionsYes
7Project CLAUDE.md and unscoped .claude/rules/*.mdYes
8Your promptYes

Run /context in a session to see the real numbers for the current run, including which memory files actually loaded. If a file you wrote is not in that list, the agent cannot see it — no amount of rewording will help.

What survives compaction

When the window fills, Claude Code summarizes the conversation and continues. Content loaded from disk is re-injected; content that only ever existed in the conversation is summarized away. This table is the single most useful thing to know about long sessions.

Loaded asAfter compaction
System prompt and output styleStill apply
Project-root CLAUDE.md and unscoped rulesRe-injected from disk
Auto memoryRe-injected from disk
The plan written in plan modeRe-injected from disk
Rules with paths: frontmatterReloaded when a matching file is next read
Nested CLAUDE.md in subdirectoriesReloaded when a file in that directory is next read
Files the agent read or editedUp to five re-read, most recently modified first
Invoked skill bodiesRe-injected, capped at 5,000 tokens each and 25,000 total
Anything you only said in chatSummarized — treat it as gone

Section 5

Working knowledgeBoth tools

CLAUDE.md and AGENTS.md — the files that shape every session

Write instructions that are actually followed: correctly placed, specific, and short.

Where Claude Code looks

Load order, broadest scope first — later files are read last and therefore win ties
ScopeLocationUse it for
Managed policymacOS /Library/Application Support/ClaudeCode/CLAUDE.md · Linux and WSL /etc/claude-code/CLAUDE.md · Windows C:\Program Files\ClaudeCode\CLAUDE.mdOrganization standards nobody can opt out of
User~/.claude/CLAUDE.mdYour preferences across every project
Project./CLAUDE.md or ./.claude/CLAUDE.mdTeam conventions, committed to git
Local./CLAUDE.local.md (gitignore it)Your sandbox URLs, personal test data

Files in directories above your working directory load at launch, ordered from the filesystem root down, so the file closest to where you started is read last. Files in subdirectories load on demand when the agent reads a file there.

Where Codex looks

Codex builds an instruction chain at startup: global first, then project files from the git root down to your working directory. In each location it checks AGENTS.override.md before AGENTS.md. Files closer to your current directory appear later in the combined prompt and therefore override earlier guidance. The chain stops once it reaches project_doc_max_bytes — 32 KiB by default.

A layered Codex setup
  • ~/.codex/AGENTS.mdYour personal working agreements, every repo
  • my-repo/
  • └─ AGENTS.mdRepository expectations, committed
  • └─ services/
  • └─ payments/
  • └─ AGENTS.override.mdWins over the root file for this subtree
Verify the chain loaded in the order you expect
codex --ask-for-approval never "Summarize the current instructions."

How to write instructions that get followed

  • Stay under 200 linesLonger files consume context and measurably reduce adherence. If it is growing, that content belongs in a path-scoped rule or a skill.
  • Be concrete enough to verify"Use 2-space indentation" beats "format code properly". "Run pnpm test before committing" beats "test your changes".
  • Write what cannot be derivedSkip the directory listing and the dependency list — the agent can read those. Keep the pitfalls, the rationale, and the conventions that differ from the tool defaults.
  • Remove contradictionsWhen two files disagree, the agent picks one arbitrarily. Review the whole set periodically, including nested files.
  • Add an entry the second time you repeat yourselfThe first correction is a conversation. The second is a missing instruction.

Imports

CLAUDE.md can pull in other files with @path/to/file, resolved relative to the importing file, up to four hops deep. Imports are expanded at launch, so they organize content — they do not reduce what it costs. Wrap a path in backticks to mention it without importing it.

CLAUDE.md
See @README for the project overview and @package.json for available commands.

# Additional instructions
- Git workflow: @docs/git-instructions.md
- Personal preferences shared across worktrees: @~/.claude/my-project-instructions.md

Section 6

Working knowledgeClaude Code

Rules and memory — instructions that load only when relevant

Split a growing instruction file into path-scoped rules, and understand the notes the agent writes about you.

Path-scoped rules

.claude/rules/ holds one markdown file per topic, discovered recursively. A rule with no frontmatter loads at launch with the same priority as .claude/CLAUDE.md. A rule with paths: frontmatter loads only when the agent reads a matching file — which is how you keep backend conventions out of a frontend task.

.claude/rules/api-design.md
---
paths:
  - "src/api/**/*.ts"
  - "src/**/*.{controller,service}.ts"
---

# API rules

- Every endpoint validates its input before touching a service.
- Errors use the shared error envelope, never a bare string.
- A new endpoint ships with an integration test in the same PR.
Glob patterns in paths:
PatternMatches
**/*.tsAll TypeScript files in any directory
src/**/*Everything under src/
*.mdMarkdown files in the project root only
src/components/*.tsxComponents in one specific directory
src/**/*.{ts,tsx}Brace expansion — two patterns from one line

Personal rules in ~/.claude/rules/ apply to every project and load before project rules, so project rules take priority. The directory supports symlinks, which is the clean way to share one rule set across several repositories.

Auto memory: the notes the agent keeps

Separately from anything you write, Claude Code saves short notes as it works — your preferences, corrections you gave it, and project facts it cannot derive from the code. They live in plain markdown you can read, edit, or delete.

~/.claude/projects/<project>/memory/
  • MEMORY.mdIndex — first 200 lines or 25 KB load every session
  • user_role.mdOne memory, read on demand
  • feedback_testing.mdOne memory, read on demand
Two memory systems, different jobs
CLAUDE.mdAuto memory
Who writes itYouThe agent
What it holdsInstructions and rulesLearnings, preferences, corrections
ScopeProject, user, or organizationPer repository, shared across worktrees, machine-local
Use it forStandards, workflows, architectureThings you would otherwise re-explain every session
.claude/settings.json — turn it off for one project
{
  "autoMemoryEnabled": false
}

Part 3

Execution units

Skills, subagents, MCP servers, and plugins — the four ways to give an agent more capability without a longer prompt.

Section 7

Working knowledgeBoth tools

Skills — a procedure the agent loads only when it needs it

Turn any workflow you have pasted into chat twice into a file the agent can run properly.

A skill is a folder with a SKILL.md in it. Unlike an instruction file, the body costs nothing until it is invoked — which is why a skill can be long and detailed where CLAUDE.md must be short.

Where skills live
ToolScopePathInvoke with
Claude CodeProject.claude/skills/<name>/SKILL.md/name
Claude CodePersonal~/.claude/skills/<name>/SKILL.md/name
Claude CodePlugin<plugin>/skills/<name>/SKILL.md/name
CodexProject.agents/skills/<name>/SKILL.md$name
CodexRepo root$REPO_ROOT/.agents/skills/$name
CodexPersonal~/.agents/skills/$name

Anatomy of a skill

.claude/skills/review-diff/SKILL.md
---
name: review-diff
description: Reviews uncommitted changes for correctness and risk. Use before opening a PR.
allowed-tools: Bash(git diff:*) Read Grep
disable-model-invocation: true
---

## Current changes

!`git diff HEAD`

## Instructions

1. Group the diff by intent, not by file.
2. For each group, state the behaviour change in one sentence.
3. Flag: missing error handling, untested branches, widened permissions,
   and any change to a public contract.
4. End with a GO / NO-GO line and the single most important reason.

The ` !git diff HEAD ` line is dynamic context injection: the command runs and its output is inserted before the model reads the skill, so the review is grounded in the real diff rather than in a description of one.

Claude Code SKILL.md frontmatter
FieldWhat it does
nameIdentifier; defaults to the directory name
descriptionWhen the agent should invoke this on its own — the single most important field
allowed-toolsPre-approve tools for this turn, skipping permission prompts
disable-model-invocationtrue means only you can run it — use for deploys, commits, anything irreversible
user-invocablefalse means only the agent runs it, never /name
pathsGlob patterns limiting when the skill can activate
context: forkRun the skill in an isolated subagent instead of the main conversation

Codex uses the same two required fields — name and description — and adds an optional agents/openai.yaml for display name, icon, implicit-invocation policy, and MCP tool dependencies. Bundle supporting material in scripts/, references/, and assets/ beside the SKILL.md in either tool.

Skill, rule, or instruction file?
If the content is…Put it in
A fact true in every sessionCLAUDE.md / AGENTS.md
A convention for one part of the tree.claude/rules/ with paths:
A multi-step procedure with its own checksA skill
Something that must happen regardless of what the model decidesA hook (§12)

Section 8

AdvancedClaude Code

Subagents — delegate with a clean context and a narrow remit

Use a second context window when the work is separable and the noise is expensive.

A subagent is a separate context window with its own system prompt, tool allowlist, and model. It receives a task, works independently, and returns a summary — the intermediate file reads never enter your main session. That is the point: you keep the conclusion, not the search.

Delegate when the answer requires reading across many files and you only need the finding, or when you want a genuinely independent opinion on work the main session just produced. Do not delegate a single-file lookup — the coordination costs more than the search.

.claude/agents/backend-reviewer.md
---
name: backend-reviewer
description: Reviews backend changes for data-safety and API-compatibility risk. Use after a service or migration is edited.
tools: Read, Grep, Glob, Bash(./gradlew test:*)
model: sonnet
permissionMode: plan
memory: project
color: cyan
---

You review backend changes. You never edit files.

For every finding, give: the file and line, the concrete failure scenario
(inputs and state that produce the wrong result), and the smallest fix.
Rank findings by severity. If you find nothing, say so in one line —
do not invent findings to fill the report.
Frontmatter fields worth knowing
FieldEffect
name, descriptionRequired. The description is what triggers automatic delegation.
tools / disallowedToolsAllowlist, or subtract from the inherited set. A reviewer with no write tools cannot edit.
modelsonnet, opus, haiku, fable, a full ID, or inherit
permissionModedefault, acceptEdits, auto, dontAsk, bypassPermissions, plan
maxTurnsHard stop after N agentic turns; the result is marked partial
skillsPreload specific skill bodies into the subagent's context
mcpServersWhich MCP servers this subagent may reach
memoryuser, project, or local — its own memory, separate from the main session
isolation: worktreeRun in its own git worktree so parallel agents cannot collide
effortlowmax, overriding the session default
Four ways to invoke
# 1. Automatic — the agent matches your task to the description
# 2. By name in a prompt
"Have backend-reviewer look at the migration"

# 3. Guaranteed, via @-mention typeahead
@"backend-reviewer (agent)" review src/db/migrations

# 4. Run the whole session as that agent
claude --agent backend-reviewer

Section 9

AdvancedBoth tools

MCP and plugins — connecting the agent to everything else

Give the agent typed access to your database, tracker, and design tools without pasting credentials into a prompt.

The Model Context Protocol is an open standard for exposing tools and resources to any compatible agent. An MCP server advertises named capabilities with schemas; the agent discovers and calls them. Because the contract is typed and the credentials live in the server, the agent never sees the secret — it only sees the tool.

Claude Code

claude mcp
# stdio server, project scope so the team gets it via git
claude mcp add --transport stdio --scope project postgres -- npx -y @bytebase/dbhub

# Remote HTTP server with a header
claude mcp add --transport http github https://api.githubcopilot.com/mcp/ \
  -H "Authorization: Bearer ${GITHUB_TOKEN}"

claude mcp list          # what is configured
claude mcp get <name>    # one server's details
claude mcp login <name>  # OAuth flow
claude mcp remove <name>
Scopes
ScopeFileShared with the team?
local (default)~/.claude.jsonNo — this project, just you
project.mcp.json at the project rootYes, via git
user~/.claude.jsonNo — all your projects
.mcp.json
{
  "mcpServers": {
    "github": {
      "type": "http",
      "url": "https://api.githubcopilot.com/mcp/",
      "headers": { "Authorization": "Bearer ${GITHUB_TOKEN}" }
    },
    "database": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@bytebase/dbhub"],
      "env": { "DB_URL": "${DATABASE_URL:-postgresql://localhost/mydb}" }
    }
  }
}

${VAR} and ${VAR:-default} are expanded from your environment, so the file itself stays safe to commit. Project-scoped servers require an explicit approval the first time an interactive session sees them.

Codex

~/.codex/config.toml
[mcp_servers.context7]
command = "npx"
args = ["-y", "@upstash/context7-mcp"]
env_vars = ["LOCAL_TOKEN"]

[mcp_servers.figma]
url = "https://mcp.figma.com/mcp"
bearer_token_env_var = "FIGMA_OAUTH_TOKEN"

[mcp_servers.chrome_devtools]
url = "http://localhost:3000/mcp"
enabled_tools = ["open", "screenshot"]
default_tools_approval_mode = "prompt"
tool_timeout_sec = 45
codex mcp
codex mcp add context7 -- npx -y @upstash/context7-mcp
codex mcp add example --url https://mcp.example.com --oauth-client-id my-client
codex mcp login example
codex mcp list

Plugins

A plugin is an installable bundle — skills plus MCP servers plus, in Claude Code, subagents, commands, and hooks — distributed through a marketplace. Reach for a plugin when you want one install to deliver both the instructions and the connected service; reach for a bare skill when you only need instructions.

Part 4

Configuration

The files, the precedence between them, the permission model, and the hooks that enforce what prose cannot.

Section 10

Working knowledgeBoth tools

Configuration files and which one wins

Know every file in play and the exact order they resolve in — most configuration bugs are precedence bugs.

The `.claude` directory

Project scope — committed unless noted
  • your-project/
  • └─ CLAUDE.mdInstructions read every session
  • └─ CLAUDE.local.mdYour personal overrides — gitignore this
  • └─ .mcp.jsonProject MCP servers, shared with the team
  • └─ .worktreeincludeGitignored files to copy into new worktrees
  • └─ .claude/
  • └─ settings.jsonPermissions, hooks, model — committed
  • └─ settings.local.jsonYour overrides for this project — gitignored
  • └─ rules/Topic instructions, optionally path-gated
  • └─ skills/Reusable procedures, one folder each
  • └─ agents/Subagents with their own context window
  • └─ commands/Single-file prompts — skills supersede these
  • └─ workflows/Scripts that orchestrate many subagents
  • └─ output-styles/Instruction sets that adjust how the agent writes
User scope — ~/, applies to every project
  • ~/.claude/
  • └─ CLAUDE.mdYour preferences everywhere
  • └─ settings.jsonYour defaults for all projects
  • └─ keybindings.jsonCustom keyboard shortcuts
  • └─ themes/Custom colour themes
  • └─ rules/ · skills/ · agents/ · workflows/Personal versions of each
  • └─ projects/<project>/memory/Auto memory — the agent writes this
  • ~/.claude.jsonApp state, UI preferences, local MCP servers

Settings precedence, highest first

#LayerFileWho it is for
1Managedmanaged-settings.json, MDM, or the claude.ai consoleYour organization — you cannot override it
2Command lineclaude --settings <file>You, this session only
3Project local.claude/settings.local.jsonYou, this project
4Shared project.claude/settings.jsonEveryone on the project, via git
5User~/.claude/settings.jsonYou, every project
.claude/settings.json
{
  "$schema": "https://json.schemastore.org/claude-code-settings.json",
  "permissions": {
    "allow": ["Bash(pnpm run lint)", "Bash(pnpm run test:*)"],
    "ask": ["Bash(git push:*)"],
    "deny": ["Read(./.env)", "Read(./.env.*)", "Read(./secrets/**)"],
    "additionalDirectories": ["../shared-types"],
    "defaultMode": "default"
  },
  "env": { "NODE_ENV": "test" },
  "autoMemoryEnabled": true
}

Codex `config.toml`

Codex precedence, highest first
#Source
1CLI flags and --config overrides
2Project config — .codex/config.toml, closest to the working directory wins
3Profile files — ~/.codex/<profile>.config.toml
4User config — ~/.codex/config.toml
5Cloud-managed defaults
6System config — /etc/codex/config.toml
7Built-in defaults
~/.codex/config.toml
model = "gpt-5.6"
approval_policy = "on-request"     # or "never"
sandbox_mode = "workspace-write"
default_permissions = ":workspace" # :read-only | :workspace | :danger-full-access
web_search = "cached"              # cached | indexed | live | disabled

[windows]
sandbox = "elevated"               # fall back to "unelevated" if needed

[permissions.review-only]
# a named profile you can switch into

Section 11

Working knowledgeBoth tools

Permissions and sandboxing

Decide exactly what runs without you, what stops for you, and what never runs at all.

Two independent layers protect you. Permissions decide which tool calls the harness will make; they cover every tool. Sandboxing is OS-level enforcement on shell commands and their child processes. Permissions can be talked around by a convincing prompt injection; a sandbox cannot. Use both.

How one tool call is decided (Claude Code)

Rules are evaluated deny, then ask, then allow. The first match in that order decides — specificity never reorders it.

Tool call requestede.g. Bash(git push origin main)
deny rulesAny match → blocked, always
ask rulesAny match → prompt you, even in auto mode
allow rulesMatch → run with no prompt
Permission modedefault · acceptEdits · plan · auto · dontAsk · bypass
PreToolUse hookLast word — can deny or approve
SandboxOS-level fence on Bash and its children
Command runsResult observed by the agent
You are askedApprove, deny, or add a rule
  • promptcall · "Yes, don't ask again" writes a new allow rule
LegendYouRule evaluationEnforcement pointFeeds back into configuration

Rule syntax

Every rule is Tool or Tool(specifier). A bare tool name in deny removes the tool from the agent's context entirely, so it never even sees it. A scoped rule leaves the tool available and blocks only the matching calls.

RuleMatches
BashEvery shell command
Bash(pnpm run build)That exact command
Bash(pnpm run test:*)Any command starting with that prefix
Read(./.env)Reading .env in the current directory
Read(./secrets/**)Reading anything under secrets/
Edit(/src/**/*.ts)Editing TypeScript under src/, anchored at the settings source
Read(//Users/alice/keys/**)An absolute path — note the double leading slash
WebFetch(domain:example.com)Fetches to that host
WebFetch(domain:*.example.com)Any subdomain, but not the apex
mcp__githubEvery tool from the github MCP server
mcp__github__create_issueOne specific MCP tool
Agent(Explore)Use of the Explore subagent

Rules match each subcommand of a compound command independently, so Bash(safe-cmd *) does not approve safe-cmd && rm -rf /. Deny and ask rules also reach inside subshells, command substitutions, and loop bodies. Environment-runner wrappers such as npx, docker exec, and devbox run are not stripped — write one rule per inner command rather than trusting Bash(devbox run *).

Permission modes

Claude Code — set the starting mode with defaultMode
ModeBehaviour
defaultPrompts on first use of each tool. Shown as Manual in the UI.
acceptEditsAuto-accepts file edits and common filesystem commands inside the working directories
planReads and explores, never edits source. The right mode for "tell me how you would do this".
autoAuto-approves with background safety checks that verify actions match your request
dontAskAuto-denies anything not pre-approved. Good for unattended runs with a tight allowlist.
bypassPermissionsSkips prompts. Containers and disposable VMs only.
Codex
ModeSandboxApprovalsBehaviour
Ask for approval (default)workspace-writeon-requestReads and edits inside the workspace; asks before the network or anything outside it
Approve for meworkspace-writereviewed automaticallySame boundary; requests for extra access are reviewed for you rather than by you
Full accessunrestrictednoneAny file, any command, network included. Materially raises the risk of loss and leaks.

Changing who reviews a request never widens the sandbox — the two are separate dials. In the Codex CLI, /permissions manages both.

A sane starting point for a work repository
{
  "permissions": {
    "deny": [
      "Read(./.env)", "Read(./.env.*)",
      "Read(./**/credentials.json)", "Read(~/.ssh/**)",
      "Bash(curl:*)", "Bash(git push --force:*)"
    ],
    "ask": ["Bash(git push:*)", "Bash(gh pr merge:*)"],
    "allow": [
      "Bash(pnpm install)", "Bash(pnpm run:*)",
      "Bash(git status)", "Bash(git diff:*)", "Bash(git log:*)"
    ],
    "defaultMode": "default",
    "disableBypassPermissionsMode": "disable"
  }
}

Section 12

AdvancedClaude Code

Hooks — automation that does not depend on the model remembering

Attach deterministic shell commands to lifecycle events so critical checks always run.

A hook is a shell command bound to an event. It runs whether or not the model thought of it, which is precisely why it is the right home for formatting, secret scanning, and any rule you have written into CLAUDE.md twice and watched get skipped anyway.

.claude/settings.json
{
  "hooks": {
    "PostToolUse": [
      {
        "matcher": "Edit",
        "hooks": [
          { "type": "command", "command": "pnpm exec prettier --write \"$CLAUDE_FILE_PATHS\"" }
        ]
      }
    ],
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          { "type": "command", "command": "${CLAUDE_PROJECT_DIR}/.claude/hooks/scan-secrets.sh" }
        ]
      }
    ]
  }
}
The events you will reach for first
EventFires whenBlocking
SessionStartA session begins, resumes, clears, compacts, or forksExit 2 prevents the session starting
UserPromptSubmitBefore your prompt is processedExit 2 rejects the prompt
PreToolUseBefore a tool runs — matcher is the tool nameExit 2 blocks the call
PostToolUseAfter a tool succeedsExit 2 stops the agent from finishing
PostToolUseFailureAfter a tool failsExit 2 stops the agent from finishing
StopThe agent is about to finish respondingExit 2 makes it keep working
SubagentStart / SubagentStopA subagent spawns or finishesStop can block with exit 2
PreCompact / PostCompactAround context compactionPreCompact can block
FileChangedA watched file changes — matcher is a filename patternExit 2 prevents the change
InstructionsLoadedInstruction files load — invaluable for debuggingInformational
NotificationA notification is sent, e.g. a permission promptInformational
SessionEndThe session terminatesInformational

There are around thirty events in total, covering permission decisions, task lifecycle, model switches, worktrees, config changes, and MCP elicitation. The full list is in the hooks reference; the twelve above cover most real setups.

The exit-code contract

Exit codeMeaning
0Success. Valid JSON on stdout is honoured.
2Block the action. stderr is shown to the agent as the reason.
anything elseNon-blocking error — the action still proceeds.
.claude/hooks/scan-secrets.sh
#!/usr/bin/env bash
# PreToolUse hook: refuse commands that would print a secret file.
set -euo pipefail

payload="$(cat)"                       # hook input arrives on stdin as JSON
command="$(jq -r '.tool_input.command // ""' <<<"$payload")"

if grep -Eq '(^|[[:space:]])(cat|less|head|tail)[[:space:]]+.*\.env' <<<"$command"; then
  echo "Refusing: this command would print .env to the transcript." >&2
  exit 2
fi
exit 0

Part 5

Daily workflow

The loop to run every day, the gates that decide when a stage is finished, and how to run the whole thing unattended.

Section 13

Working knowledgeBoth tools

The development loop

One pipeline, eight stages, each with a deliverable that feeds the next.

The failure mode of agent-assisted work is not bad code — it is unbounded work. A stage that never declares itself finished quietly turns into a 40-file diff nobody can review. Give every stage an input, a deliverable, and a criterion that says when it is done.

The pipeline

Each stage produces the next stage's input. An unmet criterion stops progression rather than deferring the problem downstream.

FrameGoal, constraints, definition of done
ExploreRead-only. Find the real change surface.
PlanOrdered, verifiable steps
ImplementSmallest coherent change
TestRun the suite; add the missing case
ReviewIndependent pass over the diff
CommitConventional message, feature branch
HandoffState, evidence, open risks
  • testimplement · Red — fix, then re-run (cap the retries)
  • reviewplan · Scope changed — re-plan, do not patch over it
LegendHuman owns thisAgent stageChanges the working treeFailure path
Criteria per stage
StageInputDone whenWhen unmet
FrameTicket, bug report, ideaThe goal, the constraints, and the definition of done are written down in one paragraphAsk, do not assume. An unframed task produces confident work on the wrong problem.
ExploreThe framed goalThe agent names the files it will change and cites why, without having changed anythingWiden the search or point it at an entry point yourself
PlanExploration findingsOrdered steps, each with the check that proves itSteps that cannot be verified get split until they can
ImplementThe approved planOne coherent change, built, matching the planScope drift returns to Plan rather than continuing
TestThe changeSuite green, and a new test covers the new behaviourRe-enter Implement with the failure list; after three rounds, take over
ReviewThe full cumulative diffNo blocking findings; every finding has a file, a line, and a failure scenarioFix, then re-review only the changed part
CommitReviewed changeConventional commit on a feature branch, pushedConvention or protected-branch violations are fixed before retry
HandoffSession endWhat is done, what is verified, what is unresolved, and the next safe commandAn unverified item is stated as unverified — never as complete

Plan before you let it write

Plan mode is the highest-leverage habit in the whole handbook. The agent reads and explores but cannot edit, so you get to inspect the intent before the diff exists — and a bad plan costs you thirty seconds instead of a revert.

Enter plan mode
# Claude Code — Shift+Tab cycles the permission mode, or:
claude --permission-mode plan

# Persist it as the default for a risky repository, in .claude/settings.json:
#   { "permissions": { "defaultMode": "plan" } }

# Codex — review without touching the working tree:
codex review

Section 14

Working knowledgeBoth tools

Quality gates and review

Define what counts as evidence, so "it works" stops being an opinion.

A plausible implementation is not a verified one. A gate is a check with a binary outcome that must pass before work advances — compile, test, lint, type-check, security scan, and a review pass that did not write the code.

Where to put each gate
GateEnforce it asWhy there
FormattingPostToolUse hook on EditDeterministic, instant, and never worth a token of the model's attention
Secret scanningPreToolUse hook on Bash, plus a deny rule on .envMust hold even when a prompt injection is trying to talk past it
Type-check and unit testsA command in CLAUDE.md the agent is told to runThe agent needs the output to fix its own work
Integration testsCI on the pull requestToo slow for the inner loop; too important to skip
Independent reviewA reviewer subagent, then a humanThe context that wrote the code is the worst context to judge it
Human approvalThe permission prompt and the PRAccountability does not delegate

Ask for a review that is falsifiable

"Review this code" produces a list of style opinions. Demand a concrete failure scenario for every finding and the list gets short, specific, and worth reading.

A review prompt that works
Review the uncommitted diff for correctness only — not style.

For each finding give exactly:
  1. file:line
  2. the inputs or state that produce the wrong behaviour
  3. the observable wrong result
  4. the smallest fix

Rank by severity. If a finding is a guess, label it PLAUSIBLE, not CONFIRMED.
If you find nothing, say so in one line. Do not pad the list.

Both tools ship review entry points: /code-review and the ultrareview and Code Review integrations in Claude Code, and codex review plus /review in Codex. Use them for the first pass, and read the diff yourself for the second — the review is a filter, not a substitute.

Section 15

AdvancedBoth tools

Headless runs, CI, and scheduled work

Run the agent where nobody is watching, safely.

Both tools are composable Unix programs. Piping into them and running them from CI is where the time actually comes back — the interactive session is for work that needs judgement, and everything else should be a script.

Non-interactive runs
# Claude Code — one-shot, prints and exits
claude -p "translate new strings into French and open a PR"

# Feed it a stream
tail -200 app.log | claude -p "summarize anomalies as a bullet list"
git diff main --name-only | claude -p "review these files for security issues"

# Codex — the same shape
codex exec "add a regression test for the null-tenant bug"
codex resume            # pick up where a previous run stopped

Rules for unattended runs

  1. Deny by defaultRun in dontAsk mode with an explicit allowlist, or a Codex permission profile scoped to what the job needs. A run with nobody to answer a prompt should fail closed, not proceed.
  2. Sandbox itA container or an ephemeral VM, with no production credentials mounted. The blast radius should be the checkout, and nothing else.
  3. Bound the runmaxTurns on subagents, a job timeout in CI, and a token budget. An agent in a loop is expensive long before it is dangerous.
  4. Produce a reviewable artefactA pull request, not a push to main. The output of an unattended run is a proposal.
  5. Keep the traceLog which context loaded, which commands ran, and what failed. Without the trace an unattended failure is unexplainable.
Where to run it
NeedClaude CodeCodex
Automate PR review and triageGitHub Actions, GitLab CI/CD, Code ReviewGitHub integration
Long tasks off your machineClaude Code on the web, claude --cloudCodex cloud, codex apply
Recurring scheduleRoutines (cloud), desktop scheduled tasks, /loopAutomations
From team chatSlack — mention @ClaudeSlack integration
Custom orchestration in your own codeAgent SDK (TypeScript, Python)Codex SDK

Part 6

Advanced practice

Running many agents at once without collisions, and treating your own setup as something to measure and improve.

Section 16

AdvancedBoth tools

Parallel agents and worktrees

Run several agents at once without them editing the same file underneath each other.

Parallelism pays when tasks are genuinely independent — three separate bugs, or one review split across dimensions. It costs when they are not: two agents in one working tree will overwrite each other, and merging their reasoning is slower than doing the work once.

The isolation primitive is the git worktree: a second checkout of the same repository on its own branch, in its own directory. Each agent gets a real filesystem it cannot share, and you merge through the normal review path.

Worktrees by hand
git worktree add ../repo-auth-fix -b fix/auth-refresh
git worktree add ../repo-perf   -b perf/query-plan
git worktree list
git worktree remove ../repo-auth-fix   # when the branch has merged

Claude Code automates this. A subagent with isolation: worktree in its frontmatter runs in a temporary worktree that is cleaned up if it changed nothing. .worktreeinclude in the project root lists the gitignored files — .env.local, build caches — that must be copied into each new worktree for the project to actually run there.

Choosing a parallelism mechanism (Claude Code)
MechanismUse whenIsolation
SubagentYou need a finding, not a diff — search, review, researchSeparate context, same working tree
Subagent with isolation: worktreeThe delegated task will edit filesOwn branch and checkout
Agent view / background agentsSeveral full sessions you want to watch from one screenSeparate sessions
Agent teams and cross-session messagingLong-running sessions that must coordinateSeparate sessions that can message each other
Dynamic workflowsA deterministic fan-out — N dimensions, each verifiedScripted orchestration of many subagents

Codex approaches the same problem from the cloud side: start several cloud tasks in parallel and bring each result back into your checkout with codex apply. The isolation is the remote environment rather than a local worktree, and the merge point is still a reviewed diff.

Section 17

AdvancedBoth tools

Measuring and improving your own setup

Treat your configuration as a system with a failure rate you can watch go down.

Prompts, instruction files, and tool definitions are code with no test suite by default. A change that feels like an improvement can quietly break a behaviour you relied on, and you will not find out until it costs you an afternoon.

A minimal eval loop

  1. Collect real failuresEvery time you correct the agent, save the task and the wrong output. Ten of these is already a useful suite.
  2. Write the expected behaviour, not the expected text"Refuses to widen the permission scope" is checkable. "Says the right thing" is not.
  3. Re-run the set after every configuration changeNew rule, new skill, new model — the same ten tasks, and you compare.
  4. Grade deterministically where you canExit codes, file diffs, and "did it touch a forbidden path" beat a subjective judgement every time.
  5. Keep the trace, not just the verdictWhich context loaded, which tool ran, where it turned wrong. A failed eval with no trace tells you nothing actionable.

Observability

/context shows what is loaded right now. The InstructionsLoaded hook logs which instruction files loaded, when, and why. claude doctor prints the fully resolved configuration and flags rules it had to skip. Between them you can answer nearly every "why did it do that?" question without guessing.

Cost and context discipline

SymptomUsual causeFix
Sessions compact constantlyA large instruction file loading every timeMove content into path-scoped rules and skills
The agent re-reads the same files each turnNo plan, so no memory of what it already knowsPlan first; the plan survives compaction
Answers drift late in a sessionKey facts were summarized awayPut them in CLAUDE.md so they are re-injected
A wide search burns the whole windowExploration in the main contextDelegate it to a subagent and keep only the conclusion
Costs spike with no more outputAn unbounded retry loopmaxTurns, timeouts, and a hard retry cap

Part A

Appendix

The commands and vocabulary to keep open in a second tab.

Section A

FoundationBoth tools

Command cheat sheet

Everything you reach for in a normal week, in one place.

Claude Code — shell
CommandWhat it does
claudeStart an interactive session in the current directory
claude -p "…"One-shot run: print the answer and exit
claude --resumeResume a previous session in this directory
claude --agent <name>Run the whole session as a named subagent
claude --permission-mode planStart in plan mode — explore without editing
claude --add-dir <path>Grant access to a directory outside the working tree
claude --settings <file>Load an extra settings file for this session only
claude mcp add|list|get|removeManage MCP servers
claude doctorPrint the resolved configuration and flag broken rules
claude --teleportPull a web or mobile session into your terminal
Claude Code — in session
CommandWhat it does
/initGenerate or improve CLAUDE.md from the codebase
/contextShow what is actually loaded, with token counts
/memoryBrowse and edit memory files; toggle auto memory
/permissionsView and edit permission rules, with their source file
/compactCompact the conversation now, on your terms
/clearStart fresh — the right move between unrelated tasks
/mcpInspect connected MCP servers and their tools
/code-reviewReview the current diff
/doctorConfiguration checkup, including CLAUDE.md trim suggestions
/cd <path>Move the session to a different working directory
Shift+TabCycle the permission mode without leaving the session
Codex
CommandWhat it does
codexStart an interactive session
codex exec "…"Non-interactive run
codex resumeContinue a previous session
codex reviewReview uncommitted changes without touching the tree
codex applyBring a cloud task's changes into your checkout
codex cloudManage cloud runs
codex mcp add|list|loginManage MCP servers
codex --ask-for-approval never "…"Run with approvals off — read-only checks only
/initGenerate AGENTS.md
/statusSession details
/permissionsConfigure sandbox and approval behaviour
/modelPick the model and reasoning effort
/reviewReview the current changes
$skill-nameInvoke a skill

Vocabulary

TermMeaning
HarnessEverything around the model: context, tools, permissions, workflow, verification, state
Context windowThe finite budget of text the model reasons over in one turn
CompactionSummarizing the conversation to make room; disk-loaded content is re-injected
Instruction fileCLAUDE.md / AGENTS.md — context the model reads, not a rule it obeys
RuleA topic-scoped instruction file, optionally gated by file path
SkillA procedure in a SKILL.md, loaded only when invoked
SubagentA delegated task in its own context window, returning a summary
MCPModel Context Protocol — the open standard for exposing tools to agents
HookA shell command bound to a lifecycle event; runs regardless of the model
Permission ruleTool(specifier) in allow / ask / deny; enforced by the harness
SandboxOS-level restriction on shell commands and their children
Quality gateA binary check that must pass before work advances
EvalA repeatable scenario that measures whether the setup still behaves
HandoffThe transfer of verified state, evidence, and open risk at a boundary

Section B

Source library

Every factual claim above traces to one of these. When a tool ships a change, re-check it here rather than trusting the handbook.

Anthropic

OpenAI

Model Context Protocol

Git

This handbook records how I run these tools day to day. Tool behaviour changes; the source library above is the authority, and this page is the summary I keep in sync with it.