Rethinking Claude Code Best Practices — Lydia Hallie, Anthropic
Loading slides…
Read the talk
Rethinking Claude Code Best Practices
Lydia Hallie follows a Claude Code session from manual approvals to hours of unattended work. A staging push, a test runner and a login migration show where a stronger model helps and which decisions still belong in permissions, the operating system or a test.
From a talk by Lydia Hallie
At a glance
Ideas worth remembering
Keep the unreferenced legacy dependency in
CLAUDE.md. Revisit directions the model can infer from the repository when auditing instructions and skills after an upgrade.Match the control to when the risk occurs. A deny rule stops a matching direct file read before execution. A sandbox can stop a dependency from opening that file inside an approved test run.
Choose a check that distinguishes the intended behavior from a plausible wrong result. For the login migration, exercise an existing session. To make a failing test block task completion, have the hook return exit code
2.
From correcting one session to managing dozens
Earlier in the year, a Claude Code session often stopped before the job was done. The developer was there to nudge it along, correct a decision and add another emphatic reminder to CLAUDE.md. Before auto mode, the choice was to approve commands by hand or accept the risk of skipping permissions. Lydia Hallie, who works on Claude Code at Anthropic, remembers doing this for one or two sessions at a time.
By the time of the talk, developers at Anthropic were running dozens of sessions concurrently. A session could work for hours, check its own results and even coordinate other sessions. Hallie puts the volume in perspective with a company-wide count of about 2,500 changes a day in May and more than 30,000 a day in September. At that scale, who catches a mistake while the developer is looking at another session?
Hallie rebuilds one of the earlier sessions by changing two defaults. She moves it from Opus 4.5 to Opus 5.5, which needs fewer mid-session corrections because it can infer more from the request and the codebase. She also switches manual permissions to auto mode, which Anthropic began making the default in August. The model takes on more of the steering, and auto mode handles routine approvals. Two questions remain. What can an approved action affect? How will anyone know whether the finished code does the right thing?
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Keep the project knowledge Claude cannot discover
An instruction that helped an older model can become a distraction. Hallie describes newer models following emphatic reminders off track, making extra tool calls and producing a worse result. Her editing question for CLAUDE.md is whether the instruction tells Claude something it could reasonably miss by reading the project.
Suppose a service still depends on a legacy data source that has no direct reference in the code. An engineer inspecting the repository could miss that dependency. So could Claude. Keep it in CLAUDE.md. A description of the tech stack or directions to an obvious part of the repository can usually go. Claude Code’s prompt audit checks both CLAUDE.md and the project’s skills for instructions the selected model no longer needs.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Why a staging push can stop in auto mode
Auto mode uses a separate classifier for most actions beyond reading and editing files in the project. The coding model proposes an action. The classifier can allow a familiar operation, such as running tests or installing dependencies, and block a command whose safety is uncertain.
Consider a request to ship a change to staging. The developer knows that deployment entails pushing to a separate deploy repository and would ordinarily approve the push. Auto mode starts with trust in the current folder and repository. The deploy repository falls outside that scope, so the push stops and the developer is back at the keyboard.
Where can the team record what it knows about that destination? Auto mode’s settings accept plain English naming trusted repositories, buckets and domains, along with actions to allow or reject. Those settings go to the classifier. Naming the deploy repository gives it the missing fact about this push while keeping the scope of that trust explicit.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Use reversibility to decide what needs a deny rule
In an August study Hallie cites, about 14% of people caught a clearly dangerous command. Auto mode blocked 89% of the dangerous commands in the study. That still left roughly one in ten getting through. A team that needs to prohibit a particular tool call can put a deny rule in the Claude Code harness, the software that receives tool calls and decides whether they run. The harness checks the rule first. If the call matches, it stops there, before the classifier ever sees it.
Hallie’s test is whether you could take the action back if Claude got it wrong once. You can revert a bad code change. Discarding uncommitted work may destroy the only copy. Reading a secret key can put its value into the session transcript. Those last two cases justify a rule ahead of time.
Take the project’s local environment file. Auto mode would ordinarily permit a read. Adding a deny rule for that file lets the harness stop a matching request, including a direct cat of the file. That handles the case where the proposed command identifies the file it wants to open.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
What can an approved test process read?
npm test is the sort of command a developer and auto mode would both approve. Once it starts, it executes project code and dependencies. A compromised dependency could try to read the same environment file or the developer’s SSH keys and send their contents to an unfamiliar host. All the developer saw at approval time was npm test. The dependency’s file access happens inside the running process.
Where could that second read be stopped while still letting Claude test its work? With the local shell sandbox enabled, the file restriction also goes to the operating system. The test can start. When its dependency tries to open the protected file, the operating system refuses the read. Child processes inherit the restrictions, so the same limit applies if the test launches another program.
Sandbox settings govern which files a command can read, which directories it can write to and which network hosts it can reach. Most of the local machine is still readable by default in Hallie’s setup, so protecting SSH keys takes its own rule. The scope also matters. The sandbox covers shell commands and their descendants. Claude’s own file operations, MCP servers and hooks still run outside it on the developer’s machine.
Where does each attempt to read the same file stop?
Read the diagram as text
- Direct file read. Before execution — The proposed command names the protected environment file.
- Harness blocks the call. Before execution — A matching deny rule ends the request before classification.
- Run npm test. Before execution — The proposed command names the test runner.
- Auto mode allows the test. Before execution — The test process can start.
- Dependency requests the file. During execution — The attempted read occurs inside the running test.
- Operating system refuses the read. During execution — The sandbox applies the file restriction to the process.
- Direct file read → Harness blocks the call: Matches the deny rule.
- Run npm test → Auto mode allows the test: Recognized test command.
- Auto mode allows the test → Dependency requests the file: Test executes dependency code.
- Dependency requests the file → Operating system refuses the read: Attempts to open the protected file.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Give the whole session a fresh machine
A cloud session gets its own machine with a fresh copy of the repository. It keeps running when the developer closes the laptop. In Hallie’s example, the local environment file, SSH keys and GitHub token were never in Git, so none arrive with the checkout. Even a tool outside the shell sandbox would find no local copy of those secrets there.
If the session discovers it needs an API key, it can flag the missing credential. The developer can supply a network secret so the session can use the key without sending its value to the model. Network access has a separate setting. The defaults Hallie describes include package registries and GitHub. Reaching another host requires adding its domain to the environment.
Disposing of the machine leaves a pushed commit in its remote repository and a message sent through a connector with its recipient. Hallie keeps auto mode enabled and commits the project’s deny rules to the repository. Each fresh checkout brings those rules along, so checks on outgoing actions can still catch a force push or a secret in a commit.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Does the API migration keep existing users signed in?
An isolated session can still spend hours implementing the wrong behavior. Consider a request to move login to a new API. An engineer watching each change could catch an unwanted decision as it happened. An engineer coming back hours later needs a way to tell what the implementation did to the people using the old API.
What would count as migrated? Hallie gives three plausible outcomes from the same prompt. One run could move login over while leaving the old API in place. Another could switch only new logins. A third could complete the switch and log everyone out. A successful login by a new user would tell a reviewer very little about someone who was already signed in.
If existing sessions must survive, make that behavior the first pass-or-fail check. The implementation that signs everyone out fails there, sending Claude back to find another way. Other requirements may be observable through a build or a screenshot. Reviewing a few well-chosen checks takes less work than reconstructing each decision from the final diff.
The simplest place to specify the check is in the request. Describe what done looks like, ask Claude to break the work into tasks with their own tests, and ask it to show the actual output. That last request gives the returning reviewer something to inspect.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Make a failed check block completion
A prompt leaves it up to the model to run a check. For checks that must run, Claude Code provides hooks. A hook is a script the harness invokes at a specified event. The team chooses when it runs, which command it executes and what it checks.
- After a file edit. Run the linter so Claude gets feedback on the edit it just made.
- When Claude tries to complete a task. Run the tests for the code it touched. A change to authentication has to pass the authentication tests.
- When Claude tries to finish the session. Run the whole test suite so a failure elsewhere can send Claude back to fix the change.
What turns a failing test into an unfinished task? Many test tools report failure with exit code 1. In the task-completion hook Hallie describes, passing 1 through still lets Claude Code mark the task complete. The hook script needs to translate the test failure into exit code 2. That tells the harness to block completion and sends Claude back to fix the problem.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Give every pull request the same checks
Once one session can work unattended, a developer can start several. Each cloud session has its own machine and checkout, which saves the developer from managing local worktrees to keep concurrent edits apart. Starting each session personally and reviewing each result is a reasonable stopping point. The developer still chooses which work to start and when to accept it.
The pull request gives those independent sessions a common checkpoint. Continuous integration (CI) runs the same checks on every PR, regardless of how the originating session was configured or which tests Claude ran along the way. With CI autofix enabled, Claude can see a failed check and go back to fix the change. The reviewer can spend that time on decisions the checks leave open.
For selected changes, GitHub’s merge-when-ready option can merge the PR once its checks pass. Hallie’s team bases that choice on risk. Every PR first gets a Claude review from a session with fresh context. A separate group of agents double-checks each bug it reports. A small documentation or copy edit can proceed on green automated checks alone. An ordinary product change may need one human reviewer, and a risky change may need two.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Let one session coordinate the others
Who keeps track when eight sessions come back with results? Hallie finds that much context switching difficult. In Claude Code Projects, in beta at the time of the talk, the developer gives one main session the job. That session acts as an orchestrator. It splits the job into tasks, starts a separate session or thread for each task, tracks what comes back and verifies the results. The developer has one conversation to follow.
Projects lets the developer choose the models for those two roles independently. Hallie gives Fable as an example for the main session, where the job is deciding what to do and judging the work that comes back. An incomplete result goes back to its thread for revision until it passes. Opus 5.5 is her example for the threads that write the code. Projects also manages context automatically, taking over decisions about when to compact or clear a session.
Hallie’s suggested first experiment is one task considerably bigger than you usually give Claude. Check that CI catches the failures you care about. Configure the cloud environment’s network access, secrets and setup scripts, then start the session and see where it needs you again. In the staging example, the push waits for a decision about which repository to trust. In the login example, the session-preservation check fails and sends Claude back to revise the migration. One calls for project knowledge from the developer. The other is a correction the session can make while the developer is away.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Full transcript
Loading transcript…