blockReadsOutsideWorkingDirectories: why setting it to false does nothing (2026)
permissions.blockReadsOutsideWorkingDirectories blocks reads outside your working directories in every permission mode, including bypassPermissions. Writing false does not turn it off, because the key is a logical OR across all settings sources. Plus the 53-hour macOS defect window, dated from the npm registry.
Updated on September 4, 2026
On this page
Quick Answer (September 2026). permissions.blockReadsOutsideWorkingDirectories is a boolean that makes Claude Code's Read, Grep, Glob and LSP tools refuse any path outside the session's working directories, in every permission mode including bypassPermissions. It needs Claude Code v2.1.257 or later. The part that surprises people: writing false in your own settings does not turn it off. The setting is a one-way latch across settings sources, so if any file your session loads sets true, the block applies and a false elsewhere is treated the same as leaving it unset. To switch it off you have to find and remove the true.
Everything below is sourced from Anthropic's own settings reference, its sandboxing guide, the
anthropics/claude-code changelog, and the npm registry's publish timestamps. Versions and dates are pinned to artifacts I read directly rather than to a release blog.
What the setting actually does
From the Claude Code settings reference, the block stops Claude from reading paths outside the session's working directories with the Read, Grep, Glob and LSP tools.
"Working directories" is a specific list, not a vibe. It means:
- the current working directory,
- directories added with
--add-diror/add-dir, - directories in
permissions.additionalDirectories.
Anything else is outside, including your home directory.
{
"permissions": {
"blockReadsOutsideWorkingDirectories": true
}
}
There is also a path by which the value arrives without you typing it. In auto mode, Claude Code shows a one-time prompt before the first file read outside the working directories, and if you choose to block, Claude Code writes true into your settings for you. A lot of people who go looking for this key later did not add it by hand.
1. false is not an off switch
This is the single most useful thing to know about the setting, and it inverts how nearly every other settings key behaves.
The reference states the semantics plainly. Scope is any file, and:
Settings reference, verbatim: "If any settings source sets true, the block applies."
and for the value itself:
Settings reference, verbatim: "false: the same as unset; a true in any other settings file still blocks"
So the effective value is not "whichever file wins precedence". It is a logical OR across every settings source the session loads: user, project, local and managed. One true anywhere latches it on, and there is no value you can write in a higher-precedence file to unlatch it. Putting "blockReadsOutsideWorkingDirectories": false in your user settings to override a project's true does nothing at all, silently.
The fix is subtractive, not corrective. You have to locate the source that sets true and remove it or change it to unset. Check, in order: ~/.claude/settings.json, the project's .claude/settings.json, .claude/settings.local.json, and any managed settings your organisation pushes.
The contrast that shows this is deliberate
It would be easy to read the OR behaviour as an oversight. It is not, and the same documentation page proves it by handling a sibling setting differently.
useAutoModeDuringPlan has the identical monotonic-OR wording ("a false in any of these files still turns it off"), but its scope is deliberately narrowed:
Settings reference, verbatim: "Scope: User, local, or managed. A repository can't turn it off for you."
Project scope is simply excluded, so a repo you clone cannot reach that setting. blockReadsOutsideWorkingDirectories is documented as scope any file, project scope included. The two designs sit a few hundred words apart on one page and the page never draws the comparison.
The honest reading is that this is a fail-safe choice: for a read-restricting control, a repository being able to tighten your session is defensible, and being unable to loosen it is the point. But the practical consequence is real, and it is the direction people do not expect: a repository can turn this on for you, and you cannot turn it back off from your user settings.
One bound worth stating rather than dramatising. The reference notes that entries in a project's .claude/settings.json take effect only after you accept the workspace trust dialog for that folder. So this is not something an arbitrary clone does behind your back; it is something you consent to in the same motion as trusting the repo, which is exactly when nobody is reading carefully.
2. Permission mode does not apply to it
The block runs "in every permission mode including bypassPermissions". That is worth saying twice, because the mental model most people carry is that bypassPermissions is the master switch that lifts everything.
It is not the master switch here. Running with --dangerously-skip-permissions does not lift this block. If you are debugging a read failure and your first instinct is to escalate the permission mode, you will escalate all the way to the least safe mode available and still see the same refusal.
There is a second-order effect on shell commands too. A Bash command that reads a matching path through a file command Claude Code recognises, such as cat, prompts you even in auto mode and in bypassPermissions mode. So the workaround of "just have it cat the file instead" does not silently succeed either; it surfaces as an approval prompt in a mode where you had stopped expecting prompts. If you want the wider picture of how the modes relate, our walkthrough of Claude Code plan mode covers the mode ladder in detail.
3. What stays readable
The block is not total, and knowing the carve-outs saves a lot of confused debugging.
Files Claude Code itself needs stay readable, specifically your skills, plugins, rules, agents, commands and the CLAUDE.md memory file under ~/.claude/. So turning the block on does not break your own customisations, even though they live outside the working directory.
When the sandbox is on, the block reaches further than the four tools. It also denies sandboxed commands read access to home directories and mounted-volume roots outside the working directories. A retry that needs approval to run outside the sandbox prompts you even in bypassPermissions mode.
And the one that catches people: files a tool reads from your home directory, such as ~/.gitconfig, are denied along with everything else. The documented escape hatch is to re-open a specific path with the sandbox.filesystem.allowRead setting rather than to disable the block.
4. The 53-hour macOS window, dated from the registry
The setting is new, and it already shipped with a defect on macOS. Rather than take a release post's word for the timing, here are the publish timestamps straight from the npm registry for
@anthropic-ai/claude-code:
Scroll to see more
| version | published (UTC) | what happened |
|---|---|---|
| 2.1.257 | 2026-09-01T17:15:33Z | setting added |
| 2.1.258 | 2026-09-01T22:25:07Z | unrelated macOS 12 launch fix |
| 2.1.259 | 2026-09-02T21:21:42Z | unrelated |
| 2.1.260 | 2026-09-03T22:32:02Z | macOS defect fixed |
The 2.1.260 entry in the changelog reads:
Changelog, verbatim: "Fixed permissions.blockReadsOutsideWorkingDirectories on macOS hiding the user's git config from sandboxed git and hiding a worktree-isolated sub-agent's own checkout"
So the exposure window was 2026-09-01T17:15Z to 2026-09-03T22:32Z, about 53 hours. Two things broke inside it, both on macOS only:
- Sandboxed
git lost sight of the user's git config. Not the Read tool being denied
~/.gitconfig, which is intended, but thegitbinary running inside the sandbox not seeing its own configuration. Identity, aliases and per-user settings go missing, so git behaves like a fresh install. - A worktree-isolated sub-agent could not read its own checkout. This is the sharper one. The whole premise of worktree isolation is that the sub-agent gets its own checkout to work in; if the block treated that checkout as "outside", the sub-agent was locked out of the only directory it was supposed to touch. Our guide to Claude Code subagents covers how that isolation is meant to work.
If you enabled this setting on macOS between those timestamps and something git-shaped or subagent-shaped went strange, that is very likely what you hit, and upgrading past 2.1.260 is the fix.
5. The docs and the changelog look like they disagree. They do not.
Reading the two sources side by side produces an apparent contradiction that is worth resolving, because the next person to look will re-derive it.
- The settings reference says files read from your home directory, such as
~/.gitconfig, are denied. Stated as intended behaviour. - The changelog calls hiding git config from sandboxed git a bug, and fixes it.
Both are true, because they have different subjects. The denial that is intended is the Read tool (and Grep, Glob, LSP) refusing to read ~/.gitconfig as a file, on your behalf, at Claude's request. The behaviour that was a bug is the sandbox hiding that file from the git binary itself, so git could not configure itself while running a command you already approved.
One is a policy about what Claude may read. The other was an accident about what a tool needs to function. If you only skim, they read as a conflict.
6. Check whether you even have the setting
Before you spend time on any of this: a large number of installs cannot use this setting at all.
The npm dist-tags for the package currently read latest: 2.1.260 and stable: 2.1.236. The setting requires 2.1.257 or later, and 2.1.236 predates it. So anyone tracking the stable channel does not have the key, cannot enable it, and equally cannot be latched into it by a repository.
claude --version
npm view @anthropic-ai/claude-code dist-tags
If you are below 2.1.257, the key is inert and any true sitting in a settings file is doing nothing yet. It will start working the moment you upgrade, which is its own small surprise.
How to turn it on deliberately
If you want the block, set it in user settings rather than in a project, so it travels with you rather than depending on which repo you are in:
{
"permissions": {
"blockReadsOutsideWorkingDirectories": true,
"additionalDirectories": ["../shared-docs/"]
}
}
Then widen deliberately. additionalDirectories is the right lever, because a directory listed there becomes a working directory and is therefore no longer outside the block. Reach for sandbox.filesystem.allowRead only for specific files that a sandboxed command needs, such as a credentials helper path.
How to debug it when a read fails
A short checklist, in the order that resolves fastest:
- Check the version.
claude --version. Below 2.1.257 the setting is not the cause. - Do not escalate the permission mode. It will not help, and
bypassPermissionsis a bad place to end up by accident. - Find every
true. Grep all four settings scopes. Remember that your ownfalseis not an override. - Ask whether the path should just be a working directory.
/add-dirfor the session, oradditionalDirectoriesto persist it. - On macOS, if it is git or a worktree subagent, check you are past 2.1.260.
The setting is a good control and worth turning on for most work. The trap is not the block itself, it is assuming it behaves like the settings keys around it.
Verified against Claude Code 2.1.260, published 2026-09-03T22:32:02Z. Version claims are pinned to npm registry timestamps and to the anthropics/claude-code changelog, read on 4 September 2026.
Written by
Ren OkabeRen Okabe builds and debugs LLM agent systems, with a focus on LangGraph orchestration, evals, and production reliability.
Frequently asked questions
Does setting blockReadsOutsideWorkingDirectories to false turn it off?
No. Claude Code evaluates this key as a logical OR across every settings source the session loads (user, project, local and managed). Anthropic's settings reference states that if any settings source sets true, the block applies, and that false is the same as unset. So a false in your user settings does not override a true in a project's .claude/settings.json. To switch the block off you have to find the file that sets true and remove it.
Does bypassPermissions mode bypass this block?
No. The block applies in every permission mode, including bypassPermissions, so running with --dangerously-skip-permissions does not lift it. A Bash command that reads a blocked path through a recognised file command such as cat will also prompt you for approval, even in auto mode and bypassPermissions mode.
Which Claude Code version added blockReadsOutsideWorkingDirectories?
Version 2.1.257, published to npm at 2026-09-01T17:15:33Z. The documentation states the key requires v2.1.257 or later. Note that the npm stable dist-tag currently points at 2.1.236, which predates the setting, so installs tracking the stable channel do not have the key at all.
Why can Claude still read my CLAUDE.md and skills when the block is on?
Those are a documented carve-out. Files Claude Code itself needs stay readable, specifically your skills, plugins, rules, agents, commands and the CLAUDE.md memory file under ~/.claude/, even though they sit outside the working directory. Turning the block on does not disable your own customisations.
Why did git or a worktree subagent break on macOS after I enabled this?
That was a defect present between Claude Code 2.1.257 (published 2026-09-01T17:15:33Z) and 2.1.260 (published 2026-09-03T22:32:02Z), a window of about 53 hours. On macOS the setting hid the user's git config from sandboxed git and hid a worktree-isolated sub-agent's own checkout. Upgrading to 2.1.260 or later fixes it.
How do I let Claude read a directory outside the working directory without disabling the block?
Add the directory to permissions.additionalDirectories, or use --add-dir or /add-dir for a single session. A directory added that way becomes one of the session's working directories, so it is no longer outside the block. For a specific file that a sandboxed command needs, such as a credentials path, use sandbox.filesystem.allowRead instead of turning the block off.
Related tutorials
Claude Code Plan Mode: How It Actually Gates Your Edits (2026)
Plan mode is not a read-only state. It is a rule at step 4 of a six-step permission evaluation, which is why allow rules stop applying while you plan and why a session with bypass permissions can edit anyway. The CLI keystrokes, the settings, the Agent SDK equivalent, and a plan-then-execute pipeline in Python and TypeScript. August 2026.
Claude Code Subagents: How to Create, Scope, and Nest Them (2026)
The /agents creation wizard was removed in Claude Code v2.1.198, so almost every guide still ranking for this topic teaches a flow that no longer exists. Here is the current way to write, scope, invoke, and cap Claude Code subagents, with a version number on every claim. August 2026.
TodoWrite No Longer Available: Claude Code's 2.1.233 Tool Gate (2026)
"TodoWrite no longer available" is not a bug. Claude Code v2.1.233 drops the five task-tracking tools on Sonnet 5 and newer unless you opt in. The gate follows the session, not the model, and the SDK opt-in line behaves differently in TypeScript and Python (2026).