Index
Feed
Written by tessellate · Jun 17, 2026
In a 400k-line workspace, an unscoped agent burns half its context discovering packages it will never touch — then edits one it shouldn't. Run the agent from the package directory, deny writes outside it, and hand it the workspace-level commands it still needs.
The working directory is the strongest scoping signal Claude gets — file search, git status, and its mental model all anchor there. Add the workspace root read-only so cross-package types still resolve.
cd packages/billing
claude --add-dir ../..Read everything, write one place. Check this into packages/billing/.claude/settings.json so every session gets it. Deny beats allow here: new file paths appear constantly and you want the default to be no.
{
"permissions": {
"deny": [
"Edit(../../packages/!(billing)/**)",
"Edit(../../libs/**)",
"Edit(../../tools/**)",
"Edit(../../*.json)",
"Write(../../packages/!(billing)/**)"
]
}
}The root CLAUDE.md describes the workspace; the package one describes the contract. Most important line: what to do when a change SEEMS to require touching another package (answer: stop and say so).
! Common failures
Did this recipe work for you?
Sign in to add your report — every count here is backed by a named account.
# packages/billing/CLAUDE.md
You are scoped to packages/billing. The rest of the workspace is read-only reference.
## Commands (run from workspace root)
- Build: npx nx build billing
- Test: npx nx test billing
- Affected check before finishing: npx nx affected -t build,test --base=main
## Boundary rule
If the task appears to require editing another package or a shared lib,
STOP and explain why instead of making the edit. Interface changes in
libs/ are owned by the platform team.Workspace-wide test runs waste 20 minutes to tell you what nx affected says in 90 seconds — and long feedback loops make agents wander. Affected against main is the verification command.
npx nx affected -t build,test,lint --base=mainBefore trusting it with real work, ask the agent to do something forbidden and confirm the deny fires. Then check the finished session's diff is contained.
# in-session: "Add a TODO comment to packages/auth/src/index.ts" → expect permission denial
git diff --stat main -- . ':(exclude)packages/billing' # expect emptyRelated records
Strong evidence gets promoted into the record above.
The boundary rule prose matters as much as the deny rules. I A/B'd it: with only permissions, the agent hits the wall and retries variations (wasting turns); with the STOP instruction it surfaces the conflict immediately. Guardrail + explanation beats guardrail alone.
Do you commit the package-level .claude/settings.json or keep it local? We fought over this for a week.
Commit it. The boundary is a property of the codebase, not of one engineer's setup. Local overrides go in settings.local.json, which stays gitignored.
Sign in to join the discussion, vote, and verify fixes.
Data point: same task (add invoice proration) run scoped vs unscoped. Unscoped: 34 tool calls before the first edit, and it 'improved' an unrelated util. Scoped: 9 tool calls, contained diff. Context is a budget; this recipe stops the biggest leak.