Home › Study guides › CCDV-F › Domain 3 › Lesson 3.1
CCDV-F · Domain 3 · 3.1% of the exam · Lesson 3.1 · 22 min read
Operating Claude Code: from /init to headless runs
How Claude Code is set up and run: /init and the CLAUDE.md hierarchy, rules, commands, skills, subagents, memory, settings.json and headless mode.
Written against skill 3.1 of the official CCDV-F exam guide (Version 1.0, effective July 2026). An independent resource, not affiliated with Anthropic; the practice questions are written from scratch.
3.1.1 Why Claude Code knows nothing about a project on day one
Dario, a back-end developer, has just started contributing to Pebblecart, an open-source e-commerce platform written in TypeScript. He clones the repository, starts Claude Code, Anthropic's coding agent for the terminal, code editors, desktop and browser, and asks it to fix a coupon bug. Within ten minutes it has run npm install in a project that uses pnpm, and stored a discount as a decimal where Pebblecart keeps money in integer cents. It has also poured four thousand lines of test output into the conversation, and opened his .env file, which holds his payment-sandbox keys, to check a setting.
Nothing is wrong with the model. Every Claude Code session starts with a fresh context window, the working memory that holds everything Claude can see in one conversation. Claude can read the code, but not the choices the maintainers made. Think of a skilled contractor on a building site with no drawings: competent work, guessed details. The maintainers' knowledge has to be written where Claude Code reads it, and their limits kept where Claude Code enforces them.
That place is a small set of files, mostly in a .claude/ folder inside the repository and a matching one in your home directory. They hold Claude Code's core components. CLAUDE.md files and rules are instructions you write, and agent memory is notes Claude writes for itself. Commands and skills package repeatable work you start by name, subagents are helpers with their own context window, and settings.json holds configuration Claude Code enforces. Around them sit the ways you run it: interactive sessions you can resume, and headless mode for scripts and continuous integration (CI).
Dario's first session, before and after setup
No project setup
npm installthe project uses pnpm.envto check a settingProject set up
test-runner subagentreturns a short summary.envwhatever Claude decides3.1.2 Initialising a repository: /init and the CLAUDE.md hierarchy
Here is the question behind most setup mistakes: where does an instruction go so that the right people's sessions see it, and nobody else's? The answer is the CLAUDE.md hierarchy, and it starts with initialising the repository.
Dario runs /init, a built-in command that analyses the codebase and writes a starter CLAUDE.md with the build commands, test commands and conventions it detects. If a CLAUDE.md already exists, /init suggests improvements instead of overwriting it. Dario then deletes what Claude could work out from the code and adds what it could not: use pnpm, money is integer cents, never edit migrations/generated/. Anthropic suggests keeping each file under about 200 lines, because every line costs context in every session and long files are followed less reliably.
| Level | File | Who gets it |
|---|---|---|
| Managed policy | A system path such as /etc/claude-code/CLAUDE.md on Linux |
Everyone on machines the organisation manages; it cannot be excluded |
| User | ~/.claude/CLAUDE.md |
You, in every project on this machine |
| Project | ./CLAUDE.md or ./.claude/CLAUDE.md |
Everyone who clones the repository |
| Local | ./CLAUDE.local.md, added to .gitignore |
You, in this project only |
| Subdirectory | src/checkout/CLAUDE.md |
Any session that reads files in that folder |
Memorise the user, project and local rows; recognise the managed one. Dario's "use pnpm" goes in the project file. His local database URL goes in CLAUDE.local.md, where it never reaches Maren, the maintainer who reviews his work.
At launch, Claude Code reads CLAUDE.md and CLAUDE.local.md from the directory you start in and every directory above it. It concatenates them rather than letting one override another, broadest first, so the most specific file is read last. Think of a company handbook, a team page and a sticky note on your monitor: you read all three, and none replaces the others. Subdirectory files load only when Claude reads files there, and if two files contradict each other, Claude may follow either. /memory opens the files, and /context shows which ones loaded.
Larger projects split instructions into topic files under .claude/rules/. A rule without front matter loads at launch, like the project CLAUDE.md. A rule with a paths list loads only when Claude reads a matching file. Here is Dario's checkout rule; the paths list keeps it out of context while he works on the storefront.
---
paths:
- "src/checkout/**/*.ts"
---
# Checkout rules
- Store every money amount as integer cents (`amountCents`), never a decimal.
- Round only for display, with `formatMoney()`.
- Every payment-provider change needs a test in `tests/checkout/`.
3.1.3 Commands and skills: repeatable work on demand
Dario types the same fifteen-line prompt every time he triages an issue, and the maintainers keep a checklist, a code template and a validation script for adding a payment provider. Pasting all of that by hand is slow, easy to get wrong, and leaves every developer with a slightly different version. Anything you start by typing / is a slash command, and there are three kinds.
Built-in commands are coded into Claude Code and control the session itself: /init, /memory, /context, /compact, /clear, /resume, /permissions and more. A custom command is a Markdown file whose body is the prompt and whose file name becomes the command. A skill is a folder holding a SKILL.md plus any templates, scripts or reference files the procedure needs.
| Kind | Where it lives | What it is for |
|---|---|---|
| Built-in command | Inside Claude Code: /init, /compact, /resume and the rest |
Controlling the session, its memory and its settings |
| Custom command | .claude/commands/triage-issue.md for the team, ~/.claude/commands/ for you |
One prompt you start by name: /triage-issue 412 |
| Skill | .claude/skills/add-payment-provider/ for the team, ~/.claude/skills/ for you |
A procedure with supporting files; you start it by name, or Claude loads it when its description fits the task |
The location decides the audience: a command or skill in the repository's .claude/ folder reaches everyone who clones it, while one in your home folder stays yours. Custom commands have been merged into skills, so .claude/commands/deploy.md and .claude/skills/deploy/SKILL.md both create /deploy; the skill form adds a folder for supporting files. Unlike CLAUDE.md, a skill costs almost nothing until it is used: only its description sits in context, and the body loads when the skill runs. A workflow with side effects, such as a release, should set disable-model-invocation: true, so only a person can start it.
Here is the skill Dario and Maren add to the project. Look at the description, which tells Claude when to use it, and at $ARGUMENTS, which receives whatever follows the command name. ${CLAUDE_SKILL_DIR} points to the skill's own folder, where the template and the script live.
---
name: add-payment-provider
description: Adds a payment provider to Pebblecart checkout. Use when asked to integrate a new payment service.
---
Add the payment provider $ARGUMENTS:
1. Copy `${CLAUDE_SKILL_DIR}/template/provider.ts` into `src/checkout/providers/`.
2. Implement authorize, capture and refund with amounts in integer cents.
3. Run `${CLAUDE_SKILL_DIR}/scripts/check-provider.sh $ARGUMENTS` and fix every error it reports.
4. Add tests under `tests/checkout/`, then summarise what changed.
3.1.4 Subagents and agent memory: work that happens elsewhere
Remember the four thousand lines of test output. Everything in the conversation stays in the context window, costs tokens (the units a model reads and bills by) on every later turn, and crowds out Dario's instructions. The fix is to run the tests somewhere else.
A subagent is a specialised assistant defined in a Markdown file under .claude/agents/ for the team or ~/.claude/agents/ for you. Its front matter needs a name and a description and can limit its tools or choose a model. The body becomes its system prompt, the standing instructions it works from. Claude delegates when a task matches the description, or when you name the subagent. It works in its own context window with its own tools and permissions, and only its final summary comes back. Picture an assistant who reads three hundred archive boxes and returns with one page.
Here is Dario's test runner. Look at tools, which limits what it can do, model, which puts routine work on a cheaper model, and memory, covered below.
---
name: test-runner
description: Runs the Pebblecart test suite and reports failures. Use proactively after code changes.
tools: Bash, Read
model: haiku
memory: project
---
You run tests for Pebblecart. Run `pnpm test`, or the test file you are given.
Return only: how many tests passed and failed, each failing test's name, file
and first error line, and your best guess at the cause.
Check your memory for known flaky tests first, and record any new ones.
Where the test output goes
Main conversation
coupon.tstest-runner subagent
pnpm testreads 4,000 lines of outputAgent memory is what Claude writes for itself. Auto memory, on by default, holds Claude's notes on your corrections, your preferences and project facts it cannot derive from the code, in ~/.claude/projects/<project>/memory/. Its index file, MEMORY.md, loads at the start of every session (the first 200 lines or 25KB). It is machine-local, so Maren never sees Dario's. Ask Claude to "remember that the API tests need Redis" and it writes auto memory; ask it to "add this to CLAUDE.md" and it edits the shared file.
A subagent can keep a memory of its own through the memory field, scoped to user, project or local. With project, the notes live in .claude/agent-memory/test-runner/ inside the repository, so the test runner's list of flaky tests can travel with the code to the rest of the team.
3.1.5 What Claude Code enforces: settings.json and permission modes
Dario adds "never read .env files" to CLAUDE.md and feels safe. He should not. CLAUDE.md reaches Claude as a user message placed after Claude Code's own system prompt, and Claude tries to follow it, but nothing guarantees it. An instruction is a "staff only" sign on a door; a deny rule is the lock. What MUST hold goes in settings.json, which the Claude Code client enforces whatever Claude decides.
Settings hold permission rules, environment variables, hooks, the default model and more. They live at four levels: your user file ~/.claude/settings.json, the shared project file .claude/settings.json, your own .claude/settings.local.json (kept out of git) and managed settings from your organisation. When a key is set in several places, the highest level wins: managed, then command-line flags, then local, shared project and user. List keys such as permissions.allow merge across files instead.
Here is the shared .claude/settings.json Maren adds to the project. Look at the three permission lists: Claude Code checks deny first, then ask, then allow, and the first match decides, so no allow rule can carve an exception out of a deny rule.
{
"permissions": {
"allow": ["Bash(pnpm test *)", "Bash(pnpm lint *)"],
"ask": ["Bash(git push *)"],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Bash(pnpm db:reset *)"
]
},
"env": {
"PEBBLECART_ENV": "development"
}
}
Rules refine a baseline called the permission mode, which you cycle with Shift+Tab or set at launch with --permission-mode.
| Mode | What runs without asking | Use it for |
|---|---|---|
default (shown as Manual) |
Reads only | Reviewing every action yourself |
acceptEdits |
Reads, file edits and common filesystem commands | Iterating on code you are reviewing |
plan |
Reads; edits wait until you approve a plan | Exploring before changing anything |
auto |
Everything, with a classifier checking risky actions | Long tasks where you trust the direction |
dontAsk |
Reads and pre-approved tools; everything else is denied | Locked-down CI and scripts |
bypassPermissions |
Everything | Isolated containers and virtual machines only |
Memorise auto, dontAsk and bypassPermissions, the modes that matter when nobody is watching; recognise the rest.
In auto mode, a separate classifier model reviews actions before they run and blocks anything that goes beyond your request, targets infrastructure it does not recognise or looks driven by hostile content. Reads and file edits inside the project are approved without that review. Current releases start interactive terminal sessions in auto mode where it is available, while claude -p runs start in Manual. Deny rules still block in every mode, and Anthropic warns that auto mode reduces prompts without guaranteeing safety.
3.1.6 Sessions, headless runs and streaming output
How does Dario pick up yesterday's work, and how does Pebblecart run Claude Code with nobody at the keyboard?
A session is a saved conversation tied to a project directory. claude --continue reopens the latest one in the current directory, and claude --resume opens a picker or takes a session name or ID. Inside a session, /resume does the same. Resuming brings back the full history, tool calls included. For a long session, /clear starts a new conversation with empty context, and /compact summarises the one so far to free space.
Headless mode runs Claude Code without the chat interface; the docs also call it non-interactive mode. Add -p (short for --print) and a prompt, and Claude Code runs the same agent loop, prints the result and exits with 0 on success. Unless you add --bare, a -p run loads the same project context as an interactive one, and custom commands work inside the prompt. What is missing is a person to approve anything. A -p run starts in Manual mode and denies whatever would have prompted, so you pre-approve exactly what the job needs.
The --output-format flag chooses text (the default), json (one object with the result, session ID and cost) or stream-json, the streaming mode. Used with --verbose, as the docs show it, stream-json writes one JSON event per line as the run progresses and ends with a result message; --include-partial-messages adds the text token by token. Input can stream too: with --input-format stream-json, a program feeds messages to a long-running process.
Here is the job Pebblecart runs whenever someone opens an issue. Look at three lines: --permission-mode dontAsk with a single command allowed on the command line, --max-turns as a safety cap, and --output-format stream-json, which puts each step in the job log as it happens.
# Runs when an issue is opened; the CI system sets ISSUE_NUMBER
claude -p "/triage-issue $ISSUE_NUMBER" \
--permission-mode dontAsk \
--allowedTools "Bash(gh issue view *)" \
--max-turns 15 \
--output-format stream-json --verbose \
| tee /dev/stderr \
| jq -r 'select(.type == "result") | .result' > triage.md
One headless run in CI
claude -p "/triage-issue 412"loads CLAUDE.md, the command, settingsgh issue view; the rest is deniedresult messagefinal text, cost, session ID3.1.7 The exam traps
Almost every mistake here puts configuration at the wrong level or in the wrong kind of file.
- ✗ Writing a must-never rule only in CLAUDE.md. ✓ Add a deny rule to the project's
.claude/settings.json. Settings are enforced; CLAUDE.md is only context, and auto mode's classifier is no guarantee either. - ✗ Putting team guidance where only one machine reads it:
~/.claude/CLAUDE.md,CLAUDE.local.mdor auto memory. ✓ Put it in the project CLAUDE.md or.claude/rules/, which every clone reads, and keep personal files for personal preferences. - ✗ Growing CLAUDE.md into a manual of every procedure. ✓ Keep it short: move procedures into skills, which load when used, and area-specific guidance into path-scoped rules.
- ✗ Letting Claude start a workflow with side effects on its own. ✓ Set
disable-model-invocation: trueon a release or deploy skill, so only a person can start it. - ✗ Running noisy work, such as the full test suite, in the main conversation. ✓ Delegate it to a subagent that returns a summary.
- ✗ Running Claude Code in CI interactively, or with every check skipped on a shared runner. ✓ Use
claude -pindontAskmode with an exact--allowedToolslist and stream-json for progress; keepbypassPermissionsfor isolated containers.
3.1.8 Put it together: set up a repository and break it
You now have every piece, from the first /init to a headless run with streamed output. The fastest way to feel the line between context and enforcement is to watch Claude Code ignore an instruction and obey a setting.
Neighbouring skills build on this setup. Configuration management (2.6) keeps these files versioned and consistent across developers and environments. Plugins (2.5) package commands, skills, subagents and hooks for other repositories. Hooks as safety controls (7.3) turn a must-never rule into code that runs before every tool call.
Key takeaways
- ✓ Claude Code starts every session with a fresh context window; its behaviour in a project comes from files that say what to know, what to do and what is allowed.
- ✓
/initdrafts a project CLAUDE.md; CLAUDE.md files stack from managed to user to project to local, add up rather than override, and.claude/rules/can scope instructions to paths. - ✓ Built-in commands control the session; custom commands and skills package repeatable work, with skills adding supporting files, loading only when used and, for side effects, taking
disable-model-invocation: true. - ✓ Subagents run noisy or restricted work in their own context window and return a summary; auto memory is Claude's own machine-local notes, and subagents can keep their own.
- ✓ settings.json is enforced: permission rules are checked deny, then ask, then allow, and the permission mode sets the baseline, with auto mode handing approval to a classifier.
- ✓ Sessions resume with
--continueor--resume; headlessclaude -pruns unattended with pre-approved tools andtext,jsonorstream-jsonoutput.
Check your understanding
4 questions written for this lesson, then one from the CCDV-F question bank on the same topic. Every answer option is explained, including the ones you did not pick. Nothing is stored.
6 CCDV-F questions on Domain 3, free
Every question in the bank is tagged to a domain, so you can drill 6 questions on Claude Code alone, or sit the full 53-question timed simulator.
Open the CCDV-F question bank → Back to Domain 3 →
The question bank is free. It asks for an account only because the quiz engine has to store answers to score them and show which domains are weak. The questions on this page need nothing.