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?

0:100:38
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

0:00 · section reference included

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.

3:143:24
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

3:14 · section reference included

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.

4:124:14
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

4:12 · section reference included

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.

5:475:49
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

5:32 · section reference included

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?

Direct file readBefore execution — The proposed command names the protected environment file.
Harness blocks the callBefore execution — A matching deny rule ends the request before classification.
Run npm testBefore execution — The proposed command names the test runner.
Auto mode allows the testBefore execution — The test process can start.
Dependency requests the fileDuring execution — The attempted read occurs inside the running test.
Operating system refuses the readDuring execution — The sandbox applies the file restriction to the process.
A direct read names the file before execution. In the test path, the filename becomes relevant only after the dependency runs, when the operating system can enforce the restriction.
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.
7:187:23
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

7:16 · section reference included

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.

9:269:28
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

9:26 · section reference included

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.

10:5010:52
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

10:47 · section reference included

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.

12:2112:23
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

12:21 · section reference included

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.

13:2513:27
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

13:25 · section reference included

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.

15:2015:21
Suggest correction

This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.

15:10 · section reference included

Transcript download
Full transcript

Loading transcript…