← Back to Blog

Run /init First: How Claude Code Maps an Existing Project Before It Changes a Line

Run /init First: How Claude Code Maps an Existing Project Before It Changes a Line

There is a small habit that separates a smooth Claude Code session on an old project from a frustrating one, and almost nobody does it on the first day. You open the repo, you start asking for changes, and the model starts guessing. It guesses the build command. It guesses where the API handlers live. It guesses whether you use npm or pnpm. Sometimes it guesses right. Often it does not, and you spend the next hour correcting things you would have happily explained once.

The fix is one command. Before you ask for a single edit, run /init. It reads the project and writes down what it found, so every session after that one starts informed instead of blind. I picked this up early in the Anthropic Claude Fundamentals course, filed it under "obvious in hindsight," and it has quietly improved every project I have opened since.

Here is what /init does, why running it on an existing project pays off more than on a brand new one, and the handful of moves that sit next to it: the # shortcut, the @ file mention, plan mode, thinking modes, knowing when to fan work out to subagents, when to clear or compact the context, managing the context window as a project grows, connecting outside tools with MCP, and extending Claude Code yourself with hooks and your own slash commands.

What /init actually does

/init is a slash command you run inside Claude Code. It scans your codebase, the file layout, the package manifest, the build and test scripts, the CI config, the way your existing code is organized, and it writes a starter CLAUDE.md file at the root of the project. You run it right in the session:

/init

That file matters because of one detail most people miss: if a CLAUDE.md exists in your project, Claude Code reads it automatically at the start of every session. You do not paste it. You do not remind the model it is there. It is simply in context from the first message onward. So /init turns reading your project once into a memory the model keeps for good.

If a CLAUDE.md already exists, /init does not bulldoze it. It looks at what you have and suggests additions for things it noticed that your file did not mention. You can run it again later as the project grows and let it surface what changed.

Why this matters more on a project you inherited

On a greenfield project there is almost nothing to remember yet. You and the model are building the conventions together as you go, so the value of writing them down on day one is small.

An existing project is the opposite. It is full of decisions that are invisible in the code itself:

  • The build command that is not the obvious one. Maybe tests run with npm run test:unit, not npm test, and the difference matters.
  • The reason a file lives in src/api/handlers/ instead of src/api/, and the rule that new handlers follow the same path.
  • The deploy steps a human would explain on your first day, like "lint runs on commit" or "never push straight to the main branch."
  • The framework quirk that trips up every newcomer, like a monorepo that uses one package manager everywhere or a service that has to be running before the tests will pass.
  • The known rough edges, like the one test that is flaky and the setup that has to happen in a specific order.

None of that is in the source. A model reading the files cold cannot infer most of it. Capture it once with /init, refine it for a few minutes, and from then on the project context is locked in. Skip it, and you will re-explain the same five things on the third commit of every session.

Deliberate memory beats re-scanning every session

This is worth being clear about, because Claude Code can explore a codebase on its own. Ask it to make a change and it will go read the files it thinks it needs. So why bother with /init at all?

Because on-demand scanning is throwaway work. It happens fresh in every session, it costs tokens every time, and it only ever looks at the slice of the project the current task points at. The model that read your auth code this morning does not remember it this afternoon. And nothing about an ad hoc read captures the things that are not in the files, the conventions and the reasons and the gotchas above.

A CLAUDE.md is the opposite of throwaway. You write it once, it loads every session, and it is curated rather than rediscovered. You decide what goes in it. You can correct it when it is wrong, commit it so your teammates inherit the exact same context, and trim it when it drifts. Deliberate memory you control will always beat a fresh guess the model has to redo from zero each time.

Letting the model auto-scan is fine for a quick, one-off question. For anything you will come back to, a written memory is cheaper, more consistent, and more correct.

The generated file is a first draft, not the final word

The most common mistake is running /init, glancing at the output, and treating it as done. The generated file is a draft. It is a good draft, but it is built from what a scan can see, which means it tends to list things that are already obvious from the code and miss the things that are not.

Spend five minutes improving it. A CLAUDE.md earns its keep when it is:

  • Short. Aim to keep it tight, on the order of a couple hundred lines at most. Every line is context the model carries, and a bloated file is one it follows less reliably.
  • Specific and checkable. Write "run the test suite before committing," not "test your changes." Write "indent with two spaces," not "format code nicely." Vague instructions get interpreted, and interpretation is where it goes sideways.
  • Focused on the non-obvious. Drop the line that lists every script in your package manifest. Keep the line that explains which one to actually use and why.
  • Free of contradictions. If your personal memory says one thing and the project file says another, the model has to pick, and it may pick wrong. Read it as a whole and resolve the conflicts.

Grow the memory as you go with

You will not think of everything at init time. The good news is you do not have to. While you are working, the fastest way to add something to memory is to start a line with #.

Start a line with #, type the thing worth remembering, and Claude Code saves it into a memory file. It asks you which file to put it in, so you can send a project-wide convention to the shared CLAUDE.md, keep a personal note in your own user memory, or drop it in a local project file that stays off version control.

The point is that memory is not something you set once at init. /init seeds the file, and # grows it in the moment you discover something, which is exactly when you are most likely to capture it accurately. A few generalized examples of lines worth adding mid-session:

# always run the test suite before committing, not just the changed file
# api handlers live in src/api/handlers, one file per route
# use the project package manager for installs, never plain npm

Each of those is the kind of thing you would otherwise repeat out loud every few sessions. Saved once, it is just there.

Pull in one-off context with @

The # shortcut is for things you want to keep. The @ mention is for the reverse: context you need right now and do not need to persist.

Type @ in a prompt and Claude Code lets you point at a file or a folder by path, and pulls it into the conversation. Mention a file and its contents come in. Mention a directory and you get a listing of what is inside. You can reference more than one in a single prompt, which is what makes it useful for comparisons. Some examples, with placeholder paths:

Explain how sessions are validated in @src/api/handlers/auth.js
Compare the logging in @src/lib/logger.js and @src/middleware/errors.js
What is the structure of @src/components and how is it organized?

The mental model is clean once you separate the two. /init writes the baseline memory. # grows that memory over time. @ is for the file you want in front of the model for this question only, the context you do not want cluttering your permanent file.

Where memory lives, and what to commit

Claude Code reads memory from a few places, broadest first, and stacks them together:

  • Your user file, in your home .claude folder, which applies to every project you open.
  • The project file, the CLAUDE.md at the repo root that /init writes, shared with anyone who clones the repo.
  • A local file for personal, project-specific notes you do not want to share, like a scratch URL or test data. Add it to your ignore file so it stays off version control.

The simple rule: commit the project CLAUDE.md so your team inherits the same context, and keep anything personal or machine-specific in the local file instead. You can list and open any of these files anytime with the /memory command.

Plan mode: see the approach before any edits land

/init shows the model how the project is laid out. Plan mode decides what to do with it without touching anything yet.

In plan mode, Claude Code reads, searches, runs read-only commands, and even runs your tests to understand them, but it makes no edits. It comes back with a proposed plan, and only after you approve does it start changing files. You enter it by cycling the permission modes with Shift+Tab, or you can launch a session straight into it with the --permission-mode plan flag. When the plan is ready you choose how it proceeds, from reviewing every edit to letting it run.

In practice you start a session in plan mode and describe the change, and it plans without writing anything:

claude --permission-mode plan
Plan how to add rate limiting to every endpoint under src/api, and make no edits yet

Reach for plan mode when:

  • You are working in a large or unfamiliar part of the codebase and want to see the approach before any edits land.
  • The change spans several files and you would rather catch a wrong assumption in a plan than in a diff.
  • It is a risky refactor or a migration, where seeing the full scope up front is the whole game.

Skip it for the small, well understood change you have already diagnosed. There is no need to plan a one line fix you can read in your sleep. On an existing project the pairing is natural: /init first so the model knows the territory, then plan mode for the actual change so it proposes before it touches.

Dial thinking up when it pays, and off when it does not

Plan mode decides what to do. Thinking decides how hard the model works on the decision.

Thinking is the reasoning Claude runs through before it answers. On the current models it is adaptive, so the model spends more of it on a hard step and skips it on an easy one. You set the ceiling with the effort level. Run /effort and you can move between low, medium, high, xhigh, and max, with high as the sensible default. Higher means more reasoning per turn, slower replies, and a bigger token bill. Lower means fast and cheap.

For a single hard question you do not have to change the whole session. Drop the word ultrathink into that one message and Claude Code gives that turn a deeper reasoning pass. That is the one keyword the tool treats specially now, so if an older guide told you to type "think hard" or "megathink," those are just ordinary words today.

You can also turn thinking on or off for the session with a keystroke, Alt+T on Windows and Linux or Option+T on a Mac, and set your preferred default in /config.

Here is what reaching for more thinking looks like, first for a whole session and then for a single message:

/effort xhigh
ultrathink: compare two caching strategies for this service and recommend one

Here is why both directions matter. Turn thinking up when the problem earns it: a bug you cannot reproduce, a design call with real trade-offs, a refactor that touches code you do not fully understand. The extra reasoning is where the better answer comes from, and it is cheap insurance against a confident wrong one. Turn it down for the routine: renaming a variable, fixing a typo, applying a change you have already worked out yourself. You pay for every thinking token whether or not it helped, so spending it on a single line fix is overhead and slower for no reason.

Plan mode and thinking are at their best together, and this is the part most people miss. Plan mode writes nothing, so it is the cheapest place in the whole session to spend reasoning. When you are about to plan a change that worries you a little, turn thinking up, or add ultrathink, and let it reason through the approach while nothing is at stake. Read the plan. Approve it. Then for the mechanical work of typing the edits, drop the effort back down or leave plan mode. Spend your reasoning budget where the decision lives, not where the keystrokes are.

Fan out subagents when the work is wide

A subagent is a separate worker with its own clean context. Claude Code can hand a self-contained piece of work to one and get back just the result, instead of filling your main conversation with every file it read and every log line it produced.

The reason to fan several of them out at once is width. When a task breaks into pieces that do not depend on each other, they can run in parallel, each in its own context, and only the summaries come back to you. Good candidates:

  • Independent research across separate parts of the system, for example mapping the auth layer, the data model, and the public API at the same time.
  • The same kind of pass repeated across many files, like reviewing a dozen modules against the same checklist.
  • Anything that produces a wall of output you do not want in your main thread, like a long test run where you only care about the failures.

You ask for it in plain language, for example:

Explore the auth layer, the data model, and the public API in parallel, one subagent each, then summarize how they fit together

Keep it inline instead when the steps are sequential, when one piece needs the output of another, or when you are iterating tightly and want to stay in the loop on each turn.

Plan mode and fan-out compose well on a big job. Plan first, so you understand the full shape and can see which pieces are actually independent. Approve. Then fan the independent pieces out in parallel and let the model stitch the results back together. The plan tells you what can run side by side, and the subagents do it without drowning your context.

Clear and compact: reset the context, keep the memory

The conversation you are having with Claude Code is not the same thing as the memory it keeps. The conversation is the running thread of messages, file reads, and command output. It fills up. When it does, you have two commands, and the difference between them is continuity.

/clear starts a fresh conversation with an empty context. The old thread is not destroyed, it is parked where you can pull it back with /resume, and you can name it as you clear so it is easy to find later. Reach for /clear when you finish one task and move to an unrelated one. The leftover context from the last job does nothing for the next one except cost tokens and muddy the model's focus.

/compact keeps you in the same conversation but squeezes it down. It summarizes everything so far into a tighter form, so you get room back without losing the thread, and you can point it at what matters with a focus note, for example /compact focus on the payment refactor. Reach for compact in the middle of one long task when the context is filling up but you still want the model to remember the shape of what you have been doing.

Claude Code also does this for you. As the context window gets close to full it compacts on its own, trimming old command output first and then summarizing, so you rarely have to babysit it.

The commands themselves are short:

/clear
/clear billing-bug
/compact
/compact focus on the auth work

Here is the part that ties back to the start of this post. When you /clear, or when a compaction runs, your CLAUDE.md does not go anywhere. It is not part of the conversation, it is a file the tool re-reads from disk every time, so it is right there in the fresh context while the old chatter is gone. That is the whole argument for writing it down. Conversation is cheap and disposable. The memory you put in CLAUDE.md is what carries across every clear, every compact, and every new session. If you ever notice that an instruction from early in a long session got lost after a compaction, that is the signal it belonged in CLAUDE.md in the first place. You can even add a short "Compact Instructions" section to your CLAUDE.md to tell the tool what to hold onto when it summarizes.

The context window, and what actually costs you

There is a knob worth understanding before you point Claude Code at a large project. The conversation has a maximum size, the context window. The current models give you a 1M token window; the smallest tier, Haiku, is 200K. There is no 2M window on any Claude model today, so 1M is the ceiling.

You pick the window by picking the model. In Claude Code the 1M variant shows up with a [1m] tag, and you switch with /model or set a default in /config. Two things are easy to get wrong here. First, on the current models the big window is not a premium tier: a prompt with 900,000 tokens in it bills at the same per token rate as a tiny one. The old surcharge for going past 200K is gone for these models. Second, and this is the part that bites, a bigger window does not make tokens free. You pay for every token you load, on every turn, because the model re-reads the whole conversation each time it answers.

That second point is the whole game on a large project. Say the codebase is around two million tokens of source. It does not fit in the window at all, so you were never going to load it whole. What you load is a working slice, and if you re-send a fat slice every turn, the bill is that slice times the number of turns.

This is where prompt caching earns its keep, and Claude Code does it for you. The stable front of the conversation, your CLAUDE.md, the system prompt, the context already in play, gets cached, and on later turns it is billed at roughly a tenth of the normal input rate instead of full price. Here is the saving on one slice, at Sonnet 4.6 input rates of $3 per million tokens:

  • Keep 200,000 tokens of context in front of the model and re-send it uncached every turn: about $0.60 a turn, so roughly $18 across a 30 turn session for that slice alone.
  • Let Claude Code cache it instead: about $0.75 to write it once, then about $0.06 a turn to reuse it. The same 30 turn session lands near $2.49.

That is around an 85% cut on the repeated context, and it happens automatically. What you control is whether the cache stays warm. It gets thrown away and rewritten when you switch models mid task, change the effort level, connect or disconnect an MCP server, or compact. So the practical advice is small: pick your model and effort at the start of a task and stay put, load a big file once and let it sit in cache rather than pasting it again, and save /compact for the breaks between tasks rather than the middle of one. Spend the window on what the task needs, and let caching carry the part that does not change.

Putting it together on day one

When you open a project you have not worked in before, the whole sequence takes a few minutes:

  1. Run /init and let it draft the CLAUDE.md.
  2. Read the draft, cut the obvious, and add the non-obvious conventions a scan could never see.
  3. Use plan mode for your first real change, and turn thinking up while it plans so the approach is well reasoned before any edits land. Drop the effort back down for the mechanical work.
  4. As you learn things, capture them with #, and pull one-off files in with @.
  5. On a wide task, fan the independent pieces out to subagents.
  6. When you switch to an unrelated task, run /clear to start fresh; mid-task, run /compact to free up room without losing the thread.

If staring at a blank memory file is the part that stops you, that is a solved problem too. I built a CLAUDE.md Generator that takes a few answers about your stack and conventions and hands back a structured starting file you can drop in and refine. It is the same idea as /init, just from the other direction when you want to think it through before you run anything. If you are building a whole solo operation around tools like this, the foundations-first mindset is the spine of The $97 Launch, which is about standing up a real project on a tiny budget without skipping the setup that saves you later.

Going further: connect outside tools with MCP

Everything above lives inside your project. MCP, the Model Context Protocol, is how you give Claude Code reach beyond it. An MCP server is a small connector that exposes an outside tool or data source, an issue tracker, a database, a monitoring dashboard, your docs, and Claude Code can then read from it and act on it instead of you copying things back and forth by hand.

Adding one is a single command. A local connector that runs as a process on your machine looks like this:

claude mcp add <name> -- <command to start the server>

A remote connector that lives at a URL looks like this:

claude mcp add --transport http <name> <url>

If the service needs a key, pass it as a header, for example --header "Authorization: Bearer YOUR_TOKEN", and for anything that uses a login, the in-session /mcp command walks you through authorizing it. By default a server you add is private to you on the current project. Add --scope project and the config is written to a .mcp.json file at the repo root, which you commit so your whole team gets the same connector. Add --scope user and it follows you across every project.

Once it is added, claude mcp list shows what is connected, and inside a session /mcp shows the same and lets you authorize or reconnect. From there you just ask. If you have connected an issue tracker, you might say look at issue 482 and tell me which files it touches, and Claude pulls the issue itself instead of waiting for you to paste it.

You do not have to invent these. There is a large catalog of ready-made servers. The official MCP Registry at registry.modelcontextprotocol.io is the searchable directory of public servers, and the reference servers maintained by the protocol's own team live at github.com/modelcontextprotocol/servers. Each server's page gives you the exact claude mcp add line to paste, so connecting one is usually copy, paste, authorize, done.

Pre and post hooks: when a rule has to hold every time

A line in CLAUDE.md is a request. The model reads it and usually follows it, but usually is not always. When a rule truly has to hold every single time, you want a hook. Hooks are your own shell commands that Claude Code runs automatically at set moments, and because they are code rather than guidance, they run whether the model would have thought to or not.

The two you will reach for most are the pre and post tool hooks. A PreToolUse hook runs just before Claude uses a tool, and it can stop the action cold. A PostToolUse hook runs right after a tool succeeds, which is where the cleanup and the checks go.

They live in your settings.json, either the user one in your home .claude folder, the project one at .claude/settings.json that you commit for the whole team, or a local one you keep out of version control, and you can set them up interactively with the /hooks command. A hook entry matches on the tool name and runs a command. Here is a pair that blocks edits to protected files and formats every file Claude writes:

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "/path/to/protect-files.sh" }
        ]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Edit|Write",
        "hooks": [
          { "type": "command", "command": "jq -r '.tool_input.file_path' | xargs your-formatter" }
        ]
      }
    ]
  }
}

Claude Code hands each hook a small JSON payload on standard input, including the tool name and its arguments, so the pre hook can look at exactly what is about to happen. The blocker script is tiny: read the path, and if it is off limits, print a reason and exit with code 2, which stops the tool and sends your message back to Claude.

file=$(jq -r '.tool_input.file_path')
case "$file" in
  *.env|*/secrets/*) echo "Refusing to edit a protected file" >&2; exit 2 ;;
esac

That is the whole point of the split. Use a PreToolUse hook to refuse what must never happen, blocking edits to secrets, catching a destructive shell command before it runs, or holding the line on a convention. Use a PostToolUse hook to make the good things automatic, formatting on every edit, running your linter or test suite after changes, or writing an audit line for each tool call. A convention you merely prefer can stay in CLAUDE.md. A rule you cannot afford to have skipped belongs in a hook.

Make your own slash commands

/init, /clear, and /compact are built in. You can add your own. A custom slash command is just a Markdown file: drop audit-deps.md into .claude/commands/ in your project and it becomes /audit-deps, available to everyone who clones the repo. Put the same file in ~/.claude/commands/ instead and it follows you across every project.

The body of the file is the prompt that runs when you type the command. A small frontmatter block at the top is optional; the useful keys are description (what shows in the menu) and argument-hint (what the command expects). Whatever you type after the command name lands in $ARGUMENTS, so the command can take input. Here is the generalized version of that file:

---
description: Check a dependency and flag anything risky
argument-hint: [package name]
---
Look at the dependency $ARGUMENTS in this project. Report its current version, whether a newer one exists, any known advisories, and whether anything else here still pins an old version of it.

Run it with /audit-deps some-package and $ARGUMENTS becomes some-package. The point is the same as a CLAUDE.md line: anything you catch yourself typing into Claude Code over and over, a review checklist, a release step, a standard refactor, becomes a one word command you and your team can reuse. Claude Code's richer skills system extends the same folder idea for longer workflows, but a plain command file covers most repeatable prompts.

Related reading

Fact-check notes and sources

Written from my own hands-on use of Claude Code. Mentions of Claude Code and Anthropic are nominative; this site is independent, and no affiliation or endorsement is implied.

← Back to Blog

Accessibility Options

Text Size
High Contrast
Reduce Motion
Reading Guide
Link Highlighting
Accessibility Statement

J.A. Watte is committed to ensuring digital accessibility for people with disabilities. This site conforms to WCAG 2.1 and 2.2 Level AA guidelines.

Measures Taken

  • Semantic HTML with proper heading hierarchy
  • ARIA labels and roles for interactive components
  • Color contrast ratios meeting WCAG AA (4.5:1)
  • Full keyboard navigation support
  • Skip navigation link
  • Visible focus indicators (3:1 contrast)
  • 44px minimum touch/click targets
  • Dark/light theme with system preference detection
  • Responsive design for all devices
  • Reduced motion support (CSS + toggle)
  • Text size customization (14px–20px)
  • Print stylesheet

Feedback

Contact: jwatte.com/contact

Full Accessibility StatementPrivacy Policy

Last updated: April 2026