Prelude

After using Claude Code daily for over six months, not for experiments or demos but for real production work (building features, reviewing pull requests, debugging infrastructure, writing documentation, refactoring entire modules), it has become the tool that opens first thing in the morning and closes last before switching off.

What follows is not theory. This is the actual setup, the actual configuration files, the actual daily routine refined through hundreds of sessions. Some of it came from the documentation. Most of it came from doing things wrong first.

The difference between a developer who finds Claude Code "interesting" and one who finds it indispensable comes down to configuration. The defaults are sensible, but they are generic. Once you tune Claude Code to your project, your team, and your habits, the productivity shift is substantial. Not because the AI gets smarter, but because you stop fighting friction you did not need to have.

This guide assumes you already have Claude Code installed and have run it at least a few times. If you are looking for a getting-started tutorial, the official documentation is the right starting point. What follows is everything that comes after "getting started."

The Problem

Most developers install Claude Code, run it a few times, get impressive results on simple tasks, then gradually stop using it for anything complex. The pattern is predictable. Sessions get long and unfocused, and Claude starts forgetting context from earlier in the conversation.

The AI makes changes that break project conventions. Permission prompts slow everything down. Costs spiral on long sessions because the wrong model is running for the wrong task.

These are not limitations of the tool. They are configuration problems. Every one of them has a solution that takes minutes to set up and saves hours over the following weeks.

The deeper issue is that Claude Code is not just a chat interface bolted onto an editor. It is a development environment with its own configuration language, its own permission system, its own context management, and its own workflow conventions. Using it without configuring it is like using VS Code without installing extensions or customising keybindings. It works, but you are leaving most of the value on the table.

Many developers spend their first month in that state. Then a dedicated weekend going through every setting, every command, every configuration option changes everything. The guide you are reading is the distilled version of that process, plus everything learned since.

The Journey

Your CLAUDE.md is Your Most Important File

The single most impactful thing you can do for Claude Code productivity is write a good CLAUDE.md file. This file lives in your project root and acts as persistent context that Claude reads at the start of every session. Think of it as a briefing document for a contractor you are onboarding. You want it concise, specific, and focused on decisions rather than descriptions.

Here is what belongs in a CLAUDE.md file.

Build and run commands. Claude needs to know how to build your project, run tests, start services, and verify changes. Do not make it guess. Be explicit.

## Quick Start

- Build: `just build`
- Test: `cargo test --workspace`
- Start: `just start`
- Lint: `npm run lint`

Architecture rules that Claude would otherwise violate. If your project has conventions that differ from common patterns, state them. Claude will follow widespread conventions by default, so you only need to document where your project diverges.

## Critical Rules

1. CSS files go in `storage/files/css/`, never in `extensions/*/assets/css/`
2. The `core/` directory is read-only. It is a git submodule.
3. All Rust code lives in `extensions/`. No Rust in `services/`.
4. Brand name is always lowercase: "systemprompt.io"

What to leave out. Do not put your entire README in CLAUDE.md. Do not describe what every file does. Do not paste in API documentation. Every token in CLAUDE.md costs context space, and context space is finite.

Claude can read your source files directly when it needs implementation details. What it cannot infer on its own are your team's decisions, your naming conventions, and your deployment constraints.

The mistake that appears most often is CLAUDE.md files that are thousands of lines long, full of information Claude could get by reading the actual code. A good CLAUDE.md is under 200 lines. The one for systemprompt.io is around 80 lines, and it covers build commands, critical rules, directory structure, CSS conventions, and debugging workflows. That is everything Claude needs to work in the project without making mistakes it would otherwise make.

The hierarchy matters. Claude Code reads CLAUDE.md files from multiple locations in a specific order. The project root CLAUDE.md loads first. Then any CLAUDE.md in parent directories. Then ~/.claude/CLAUDE.md for user-level instructions. If you work across multiple projects that share conventions, put the shared rules in your user-level file and keep project-specific rules in the project file. For monorepo setups where this hierarchy becomes especially important, see our guide on CLAUDE.md in monorepos.

One effective pattern is structuring the file with the most critical rules first. Claude gives more weight to content it encounters early in its context. Put your "never do this" rules at the top, your build commands next, and any nice-to-have guidance at the bottom.

The Settings File Every Repository Should Have

Beyond CLAUDE.md, the .claude/settings.json file controls Claude Code's actual behaviour. This is where you configure permissions, allowed commands, and tool access. Every repository you work in regularly should have one.

Here is a minimal settings file that eliminates the most common friction points.

{
  "permissions": {
    "allow": [
      "Bash(git status)",
      "Bash(git diff*)",
      "Bash(git log*)",
      "Bash(cargo build*)",
      "Bash(cargo test*)",
      "Bash(npm run lint*)",
      "Bash(just *)",
      "Read",
      "Glob",
      "Grep"
    ],
    "deny": [
      "Bash(git push --force*)",
      "Bash(rm -rf*)",
      "Bash(docker rm*)"
    ]
  }
}

The allow list is what saves you from clicking "approve" hundreds of times per session. Every command pattern in this list executes without prompting. The deny list is your safety net for commands that should never run automatically, regardless of context.

The patterns support wildcards. Bash(git diff*) matches git diff, git diff --staged, git diff HEAD~3, and any other git diff variant. Bash(just *) matches any target in your Justfile. This means you can approve broad categories of safe commands without listing every possible invocation.

We also recommend adding tool-specific permissions. Read, Glob, and Grep in the allow list mean Claude can search and read your codebase without asking permission for each file. This alone reduces session friction significantly, because Claude's most common actions are reading files and searching for patterns.

For team projects, commit this file to the repository. Everyone on the team gets the same baseline permissions. Individual developers can then add personal overrides in ~/.claude/settings.json for commands specific to their workflow.

The full settings reference documents every option available. The permissions system is the one you will use most.

Choosing the Right Model for the Right Task

Claude Code supports multiple models, and choosing the right one for each task is one of the easiest ways to manage both cost and quality. Not every task needs the most powerful model.

Opus is the default and the most capable. Use it for complex refactoring, multi-file changes, architectural decisions, debugging subtle issues, and any task where you need Claude to reason deeply about your codebase. It is the most expensive option, but for tasks where getting it right the first time matters, it pays for itself.

Sonnet is faster and cheaper. It excels at routine tasks like writing tests for existing code, generating boilerplate, formatting changes, and simple bug fixes where the problem is already identified. The quality difference from Opus is noticeable on complex tasks but negligible on straightforward ones. In my experience, Sonnet handles the majority of typical daily development needs.

Haiku is the lightweight option. It is best for quick questions, simple lookups, and tasks where you are essentially using Claude as a fast search engine over your codebase. "What file contains the database migration for users?" or "Show me every place this function is called." Haiku answers these in seconds at minimal cost.

You can switch models mid-session using the /model command. A typical workflow is to start a session in Sonnet for routine work, switch to Opus when hitting something complex, then switch back to Sonnet or Haiku when the hard part is done.

The cost dimension matters. Frontier models cost significantly more per token than lighter-weight alternatives. Check the Anthropic pricing page for current rates, as these change over time. If your team runs hundreds of Claude Code sessions per day, model selection becomes a genuine budget consideration. The right approach is not to always use the cheapest model. It is to use the most expensive model only when the task justifies it. For a deeper look at managing costs, see our guide on Claude Code cost optimisation.

Your ideal model split will depend on the kind of work you do. In my experience, most developers end up routing the bulk of their tokens through Sonnet, reserving Opus for complex reasoning tasks and using Haiku for quick lookups. If you spend most of your day debugging production issues, you will lean more heavily on Opus. If you spend most of your day writing tests and documentation, Sonnet and Haiku will cover it.

PR Reviews with Claude Code

This is one of the most surprisingly effective workflows. Using Claude Code for pull request reviews often starts almost by accident, and it quickly becomes one of the most consistent use cases.

The simplest approach is to check out the PR branch and ask Claude to review it.

git checkout feature/new-dashboard
claude

Then, inside the session, ask Claude to compare against main.

Review the changes in this branch compared to main. Focus on correctness,
potential bugs, and adherence to our project conventions.

Claude will run git diff main...HEAD, read through the changes, and give you a structured review. What makes this better than reading the diff yourself is that Claude reads the surrounding code too. It does not just review the diff in isolation. It checks whether the changes are consistent with the rest of the codebase.

For a more targeted review, you can pipe the diff directly.

git diff main...HEAD | claude --print "Review this diff for bugs, security
issues, and style violations."

The --print flag runs Claude in non-interactive mode. It reads the input, produces a response, and exits. This is perfect for CI pipelines or quick reviews where you do not need a full interactive session.

A shell alias makes this even faster to use multiple times a day.

alias pr-review='git diff main...HEAD | claude --print "Review this diff.
Focus on bugs, security issues, missing error handling, and deviations
from the patterns in CLAUDE.md."'

For larger PRs, the interactive approach works better because you can ask follow-up questions. "What happens if this database call fails?" or "Is this new function consistent with how we handle errors in the rest of the module?" These follow-ups are where Claude Code adds the most value, because it can search the codebase to answer them.

One particularly valuable pattern is asking Claude to suggest test cases for the PR changes. After reviewing the diff, ask "What test cases would cover the edge cases in these changes?" Claude will identify the boundary conditions and generate test code that is already adapted to your project's test framework and conventions.

Five Settings That Save Hours

After months of configuration tweaking, five specific settings stand out as the ones that save the most time.

1. Extended auto-allow patterns. The default permission set is conservative. Adding your project's specific build tools, test runners, and deployment commands to the allow list eliminates the biggest source of friction.

{
  "permissions": {
    "allow": [
      "Bash(cargo test*)",
      "Bash(cargo clippy*)",
      "Bash(just *)",
      "Bash(npm run *)",
      "Bash(systemprompt *)"
    ]
  }
}

Every command you add here is one fewer approval click per session. Over a full day of development, this adds up to hundreds of saved interruptions.

2. Deny patterns for destructive commands. The inverse of auto-allow. Explicitly denying commands you never want Claude to run automatically means you can be more liberal with your allow patterns without worrying about edge cases.

{
  "permissions": {
    "deny": [
      "Bash(git push --force*)",
      "Bash(git reset --hard*)",
      "Bash(rm -rf *)",
      "Bash(*DROP TABLE*)",
      "Bash(*DROP DATABASE*)"
    ]
  }
}

3. Additional directories. If your project spans multiple repositories or directories, configure them in settings so Claude has full visibility without you manually adding them each session.

{
  "additionalDirectories": [
    "/var/www/html/core",
    "/var/www/html/shared-libs"
  ]
}

4. Environment-specific configuration. Different environments can have different settings. Your local development settings might allow broad command execution, while your CI settings restrict Claude to read-only operations.

5. Compact threshold awareness. This is not a setting you configure, but a behaviour you learn. When your session context gets long, Claude's responses degrade. The /compact command summarises the conversation history and frees context space.

Run it roughly every 30-40 messages, or whenever Claude starts to forget things mentioned earlier. This keeps sessions productive. More on this in the context management section.

Debugging Like You Mean It

The debugging workflow is where Claude Code earns its place in the daily toolkit most convincingly. The traditional debugging cycle is: read logs, form a hypothesis, find the relevant code, trace the execution path, test the fix. Claude Code compresses this cycle dramatically because it can do the searching and tracing steps faster than any human.

A productive debugging workflow looks like this.

Start a fresh session. Debugging works better with a clean context because you want Claude focused on the problem, not distracted by whatever you were working on before.

claude

Describe the symptom, not your theory about the cause. "The dashboard page returns a 500 error when I filter by date range" is better than "I think the SQL query in dashboard.rs is wrong." Let Claude form its own hypothesis after reading the code.

Claude will typically start by searching for relevant files, reading the error handling code, and tracing the execution path from the HTTP handler down to the database query. This is where having Read, Grep, and Glob in your auto-allow list pays off. Claude might read twenty files during a debugging session, and you do not want to approve each one manually.

Once Claude identifies a likely cause, ask it to verify before fixing. "Can you confirm this is the issue by showing me what the SQL query produces with a date range that spans midnight?" Verification before fixing saves you from the frustrating cycle of applying a fix, discovering it was wrong, reverting, and trying again.

For production debugging, combine Claude Code with your logging tools.

systemprompt infra logs view --level error --since 1h | claude --print \
  "Analyse these error logs. Identify the most frequent errors and
  suggest likely root causes based on the codebase."

This pipes your recent error logs directly into Claude with codebase context. Claude can correlate the log messages with your actual source code, which is something log analysis tools cannot do.

For tracing specific requests through the system, a multi-step approach works well.

systemprompt infra logs audit <request-id> --full

Then paste the output into Claude and ask it to trace the request through the codebase, identifying where it failed and why. The combination of the request trace and codebase access means Claude can usually pinpoint the exact line of code responsible.

The Commands You Should Know

Claude Code has a set of slash commands that control the session itself. Most developers discover /help and stop there. Here are the ones worth using regularly.

/help shows the available commands. Run it once to familiarise yourself. The specific commands available may vary by version, so /help is always the definitive reference.

/compact is the most important command for long sessions. It summarises the conversation history and compresses the context. Run this proactively, not just when Claude starts forgetting things. A good rule of thumb is to compact after every major task within a session. Finished a feature? Compact. Fixed a bug? Compact. About to switch to a different area of the codebase? Compact.

/model lets you switch between models mid-session. This is how you move between Opus, Sonnet, and Haiku without starting a new session.

/mcp shows the status of connected MCP servers. If you have extended Claude Code with MCP servers for additional capabilities, this command tells you which ones are connected and healthy.

/add-dir adds another directory to the session's scope. Equivalent to starting Claude Code with --add-dir, but usable mid-session. This is especially useful when a debugging trail leads into a dependency or shared library that lives in a different directory.

/add-dir /var/www/html/core

These commands are session-level controls. They do not modify your configuration files or persist between sessions. Think of them as the control panel for your current working session. Run /help to see the full list for your version, as new commands are added regularly.

Working with Multiple Directories

Real projects rarely live in a single directory. You might have a monorepo with multiple packages, or a set of related repositories that reference each other, or a project that depends on a local library you are also developing.

Claude Code handles this through the --add-dir flag at startup and the /add-dir command during a session.

claude --add-dir /var/www/html/core --add-dir /var/www/html/shared-libs

This gives Claude read access to all three directories (the working directory plus the two additional ones). When Claude searches for files or reads code, it searches across all of them. This is essential for debugging issues that cross repository boundaries.

For directories you always want included, add them to your settings file.

{
  "additionalDirectories": [
    "/var/www/html/core",
    "/var/www/html/shared-libs"
  ]
}

With this configuration, every session in the project automatically includes these directories without you specifying them on the command line.

One thing to be aware of is that additional directories increase context pressure. Claude needs to process more files, more search results, and more code when additional directories are in scope. If you add a massive monorepo as an additional directory, you might find that context fills up faster and you need to compact more frequently. Be selective. Add directories you actually need, not every directory that might be tangentially relevant.

For enterprise setups with managed settings, administrators can configure additional directories at the organisation level. This ensures that every developer on the team has visibility into shared libraries and internal packages by default.

Context Management and Session Discipline

Context management is the skill that separates productive Claude Code users from frustrated ones. The context window is large but finite. Every message you send, every file Claude reads, every command output adds to it. When the context fills up, Claude starts losing track of earlier conversation, and the quality of responses degrades.

The first rule is to start fresh sessions for unrelated tasks. If you just finished a feature and want to review a PR, start a new session. The feature context is noise for the PR review, and the review context will be noise for whatever comes next. A typical productive day involves four to six separate Claude Code sessions, each focused on a single task or closely related set of tasks.

The second rule is to compact proactively. Do not wait for Claude to start forgetting. The /compact command preserves the essential information from your conversation while freeing context space. Compact after every significant milestone within a session.

The third rule is to keep prompts focused. A prompt like "refactor this module, also fix the bug in the login handler, and while you're at it update the README" produces worse results than three separate, focused prompts. Claude works best when it can concentrate on one thing at a time.

The fourth rule is to let Claude read files instead of pasting them. When you paste a 500-line file into the chat, that content occupies context space for the entire session. When Claude reads a file using its tools, it can process the file and retain only the relevant parts. The file content still uses context, but Claude manages it more efficiently than a raw paste.

When you do need to continue a long session, look for signs of context fatigue. Claude repeating questions you already answered, forgetting constraints you stated earlier, or producing code that ignores patterns established earlier in the session. Any of these signals means it is time to compact or start fresh.

What a Typical Day Might Look Like

Here is an illustrative example of how these workflows fit together across a full day. Your actual day will vary, but this gives a sense of the rhythm.

Morning: PR reviews. Open a terminal and start Claude Code in the main project directory. If there are PRs from teammates, check them out and run through the review workflow described earlier. Two or three PR reviews might take about thirty minutes total, including follow-up questions and testing suggestions.

Mid-morning: feature work. Start a fresh session for the day's main task. Describe the feature at a high level, referencing the existing patterns in the codebase. Claude reads the existing code, the database schema, the template files, and proposes an approach. Iterate on the design for a few messages, then let Claude start implementing while you review each change.

This is where model selection matters. Use Opus for the initial design discussion and complex logic. Once the architecture is settled and Claude is writing straightforward handler code and templates, switch to Sonnet for the implementation work.

After lunch: debugging. Something is broken. Start a fresh session dedicated to the problem and describe the symptom clearly. Let Claude trace through the code to find the root cause. Verify the fix before applying it. Fresh sessions with focused context make debugging significantly faster.

Afternoon: documentation and cleanup. Switch to Sonnet for writing documentation and cleaning up code from the morning's feature work. Adding inline comments, updating configuration files. This is routine work where Sonnet performs well and costs less.

Late afternoon: automation. If time allows, work on hooks and automation to improve the workflow itself. Setting up a new PostToolUse hook to auto-run tests when Claude modifies certain files. Adding a new MCP server for a tool the team has been requesting. These meta-improvements compound over time.

Throughout the day, five or six separate sessions might start and close. Each one is focused on a specific task, compacting within sessions when they run long, switching models based on task complexity. None of this is dramatic. It is the accumulated result of configuring the tool to fit how you actually work.

Common Pitfalls and Troubleshooting

Even with good configuration, a few issues come up regularly.

Invalid settings.json syntax. If Claude Code ignores your settings, the most common cause is a JSON syntax error. A trailing comma, a missing bracket, or an unquoted string will silently break the file. Run your settings through a JSON validator or open it in an editor with JSON linting before assuming the settings are not working.

CLAUDE.md is too large. If your CLAUDE.md exceeds a few hundred lines, it consumes a significant portion of your context window before you even start working. Keep it under 200 lines. If you find yourself adding more, move the extra detail into documentation files that Claude can read on demand.

Context fills up unexpectedly. If Claude starts forgetting instructions or producing inconsistent output mid-session, context pressure is the likely cause. Run /compact to reclaim space. If that is not enough, start a fresh session. Adding many directories with --add-dir or pasting large blocks of text accelerates context usage.

Configuration changes do not take effect. Changes to .claude/settings.json apply to new sessions, not the current one. If you edit the file mid-session, start a new session to pick up the changes.

Claude keeps asking for permission. If you have set up allow patterns but Claude still prompts for approval, check that your patterns match exactly. Bash(cargo test*) matches cargo test --workspace but not cd src && cargo test. Patterns match the entire command string, so commands with cd prefixes or pipes need their own patterns.

The Lesson

The lesson from six months of daily Claude Code use is simple. Configuration is leverage.

Every minute spent writing a CLAUDE.md, tuning a settings.json, and learning the commands pays back substantially in daily productivity. The developers who try Claude Code and abandon it almost always skip the configuration step. They used the defaults, hit friction, and concluded the tool was not ready. The tool was ready. Their setup was not.

The specific takeaways, in order of impact.

Write a concise, specific CLAUDE.md. Under ~500 lines. Focus on rules Claude would otherwise violate, not descriptions of what the code does. This single file eliminates the majority of "Claude did the wrong thing" moments.

Configure your permissions. Auto-allow safe commands. Auto-deny dangerous ones. This eliminates the majority of "Claude is slow because I keep clicking approve" moments.

Use the right model for the right task. Opus for complex reasoning. Sonnet for routine development. Haiku for quick lookups. This manages costs without sacrificing quality where it matters.

Start fresh sessions for unrelated tasks. Compact proactively within long sessions. These two habits maintain response quality throughout the day.

Learn the slash commands. /compact, /model, /mcp, and /add-dir are the ones you will use most. They give you real-time control over the session without leaving the conversation. Run /help to see the full list for your version.

Build your debugging workflow around Claude Code's ability to search and read code. Describe symptoms, let Claude trace the cause, verify before fixing. This consistently produces faster and more accurate debugging than the traditional manual approach.

None of this is complicated. None of it requires deep technical knowledge. It requires spending an hour or two on setup and then paying attention to what works and what does not over the following weeks.

Conclusion

Claude Code is not a tool you install and forget. It is a tool you configure, adapt, and refine. The configuration surface is not large. A CLAUDE.md file, a settings.json file, a handful of slash commands, and an awareness of model selection and context management. That is the entire surface area.

But within that surface area, the difference between a default setup and a tuned setup is enormous. It is the difference between a tool that occasionally helps and a tool that fundamentally changes how you work.

If you are just starting out, begin with CLAUDE.md and settings.json. Get those right and you will immediately see the difference. Then add hooks for automation, explore MCP servers for extended capabilities, and if you are managing a team, look into enterprise managed settings for consistent configuration across your organisation.

The full settings reference documents every option available. But you do not need to read it all at once. Start with what this guide covers, use it for a week, and then go deeper into the areas where you want more control.

The best productivity tool is the one you have configured to match how you actually work. Claude Code gives you the configuration surface to do exactly that. The rest is just daily practice.