Until a few months ago, most of us used AI tools the same way. It didn’t matter which one. You open the box, write a request and hope for the best. There wasn’t that much to configure on each tool, and even then, only power users with the highest tier plans bothered to touch them. For everyone else, the settings menu was more or less decorative, and the defaults remained well, defaults. The tool behaved the same on every project, for every person, every time, and the only factor that differentiated you from someone else was the quality of the query you would feed the tool.
After playing with Claude Code for a few months, I began to wander around in settings that I had previously ignored for months. I started by digging through Claude Code’s own documentation Through the structure of Boris Chernythen through community building and I kept going. Thanks to all this digging, there are a few settings I change every time I start a new project.
Permissions come first every time
Decide how much yarn to give
Every Claude Code project you work on is different. You might have a project that you open every day and run a certain skill where you hit enter over and over again, confirming the same handful of commands that you’ve confirmed a hundred times. On the other hand, you may have another project that you don’t want Claude to work on without checking with you first. These two projects cannot share a permission configuration, so the first thing I do is set the permission rules for that specific project.
The first arm I reach for is permission mode. This is what decides how Claude behaves before I write a rule, and Claude Code sends a few of them. You can set the project’s default with defaultMode in the project’s .claude/settings.json file, or simply switch between them mid-session with Shift+Tab.
The default mode is exactly what it sounds like: Claude first asks if you want to use each tool, then remembers your answer. It’s all good and it’s usually where I start for a new project that I don’t know well yet. But “first time asking” does a lot of quiet work in that sentence, because the first time suggestions pile up quickly on a project I’ve edited a hundred times in a row.
At this point I switch to acceptEdits. It accepts file edits and common filesystem commands you’d approve on autopilot anyway (mkdir, touch, mv, cp) as long as they’re in my working directory. I spend most of my time in this mode when I believe in what Claude is doing.
When I do the opposite and touch a codebase I don’t yet understand, I switch to Plan mode. In plan mode, Claude reads files and runs read-only commands to explore, but it won’t touch your source files. It just tells you what to do. I regularly use this on unfamiliar projects because it allows me to follow Claude’s reasoning and catch a wrong turn when there is a paragraph of text instead of a bad commit.
Even if you refer to them less often, there are a few more modes worth knowing about. A newer automatic mode, which automatically validates tool calls but first performs security checks in the background to verify that the action is actually what you requested, is currently in research preview. There’s dontAsk, which reverses the logic and automatically denies anything you haven’t pre-approved. And then there’s bypassPermissions, which does what the name promises and manages everything without asking.
Claude Code rules of negation are actually what enforce the boundary
Saying no and meaning it
Whenever I wanted to keep Claude Code away from a particular file or command, I just said so in my own command or command. The CLAUDE.md file I created for that project. While it worked most of the time, it often decided not to work, and I couldn’t understand why a rule I clearly wrote was being ignored.
What I later realized is that the instruction in your command or in CLAUDE.md only formulates what Claude is trying to do. It doesn’t change what the Claude Code will actually allow you to do. If you’re wondering “what about the permission modes you just mentioned”, they are broad by design. They change how often clod asks before acting, which is not the same as making a particular file or command permanently inaccessible. This is where the rules of speech come from.
Deny rules live in the same permissions block in .claude/settings.json as your allow rules, and they do what they say: they stop Claude from using a certain tool or touching a certain path. The reason they are valid is because of how the Claude Code evaluates the rules. First it checks the denial, then it asks, then it allows, and the first match is won. This command is the whole point. A deny rule cannot carry exceptions, meaning that if you deny something, a disallow rule anywhere, at any parameter level, can silently override it.
Actually what I put in there is completely project dependent, so it’s not a one time but every repo setting. The first access to anything with secrets is a rule to keep Claude away from environment files — Read(.env) blocks reading any .env in or below the current directory, so credentials don’t end up in the context in the first place. On a project that I never want Claude to push to a shared branch, Bash(git push *) in the deny list says it can run all day, but the push always stops me.
The right model really depends on what you do
Stop sending Opus to do Haiku’s work
A while back I did an audit of my Claude Code usage. I’ve found that the reason I’m going through my limits incredibly fast is because I’m using the Opus for almost every mission I throw at it, including those that don’t need anything close to that much firepower.
Claude Code lets you choose between four models (Fable, Opus, Sonnet, and Haiku), and the reason they all exist is because they sit at different points on the same continuum between how capable a model is and how much time and money it costs you to run it. While the “money” doesn’t technically affect you if you use a Claude Code through a subscription, it translates directly into how quickly you burn through your usage limits. Once I started tailoring the model to the job at hand instead of going with the heaviest option, things became faster and cheaper in terms of how much of my usage I got out of it without noticeable degradation.
Haiku is fast, cheap, and great for simple tasks, and it’s perfect for mechanical work like renaming things, making small adjustments, and work where you don’t need a model to sit and think about. Sonnet is the everyday coding model and where I spend most of my time on a normal project now. Opus is where you want it to think more before you act, to achieve complex considerations, confusing errors, and architectural decisions. And then there is the fairy tale, which The newest and most capable model in Claude Code. It’s built for long autonomous sessions where it explores and checks its work more than smaller models before moving on. While the Fable is incredibly powerful, it’s also the most expensive model to run, so it burns through use noticeably faster than the others.
Switching between them is so simple that it becomes a habit for each project rather than a one-time decision. You can run /model in the middle of a session to open the selector, or you can type the /model sonnet to go directly there, and in recent versions this option remains the default for new sessions as well. There’s also a neat hybrid called opusplan that uses Opus when you’re in plan mode and automatically drops into Sonnet once you switch to actually writing code. It’s a great way to get Opus’ thinking for planning without paying Opus’s rate for the entire session.
Then he thinks how hard it is
How hard is it to think about?
The second dial, and the one I’ve overlooked for far too long, is effort level. Where the model decides how capable reasoning is, the level of effort decides how much occurs at any given step, and it ranges from low to medium, high, and x high to maximum.
Lower effort is faster and cheaper for simple tasks, while higher effort gives you deeper reasoning for the really difficult ones. The default is high, which is fine for most coding tasks, and the mistake is often to leave it high when the task doesn’t need it. There’s no point in turning on overthinking icons on something small, especially since maxing out can start to overthink and show diminishing returns, so it’s worth testing before committing to it. You set it with /effort and the current level appears next to the spinner so you can see at a glance what you’re up to.
If you don’t want to switch to a session-wide setting for one hard request, there’s a shortcut I use all the time: drop the word ultrathink anywhere in your message and Claude Code will think deeper just for that turn without changing your effort setting for everything else. It’s the perfect vehicle for one angry question in an otherwise routine session. However, it’s worth noting that only ultrathink triggers this, so typing “think more” or “think more” does nothing but fill your command.
These are just a few of the settings I change from one project to the next and are where I would tell everyone to start. The features will always depend on what you’re working on, so it’s worth revisiting rather than setting them once. Get into the habit of adapting them to each project and Claude Code stops guessing and starts feeling like it actually knows your repo.






