Project allow rules and workspace trust
permissions.allow rules and permissions.additionalDirectories entries in a project's .claude/settings.json grant capability, so Claude Code applies them only after you accept the workspace trust dialog for that folder. The dialog lists the rules and directories the folder would grant so you can review them first. deny and ask rules aren't affected, since they only restrict.
Claude Code keys and stores the trust you accept according to where you start it:
- In a repository, Claude Code keys the trust on the git repository root, so the trust covers the whole repository apart from any git repository nested inside it, such as a submodule. In a worktree, it uses the main checkout's root, as it does for saved rules.
- Outside a repository, Claude Code keys the trust on the directory you started it from, and the trust covers any subdirectory of that directory apart from a git repository nested inside it, such as a clone. Each covered subdirectory then counts as a folder whose parent you trusted.
- When you start in your home directory, Claude Code holds the trust for the current session only and doesn't write it to disk; see the additional safeguards note.
Claude Code shows the trust dialog in interactive sessions only. A claude -p run or an SDK session never shows it, and trusting a parent folder doesn't count for these rules, so What runs before you trust a folder says which repository content Claude Code still uses in each of those two situations.
When your local settings file needs trust
.claude/settings.local.json is normally your own file, so Claude Code applies its allow rules and additional directories without the trust step. When the file is tracked in git, or .claude is a symlink, Claude Code treats it as repository-supplied instead and holds its rules until you trust the folder.
Claude Code runs git to tell the two apart, and it runs git only once you've trusted the folder: you accepted the trust dialog for it or for a parent directory whose trust extends to it, or you're in a -p or SDK session, which counts as accepted. Until then, where you started Claude Code decides what happens to the file's rules:
In your configuration home: Claude Code applies that folder's
.claude/settings.local.jsonright away without running git. Your configuration home is your home directory, or a directory whose.claudesubdirectory you've set asCLAUDE_CONFIG_DIR. If thatCLAUDE_CONFIG_DIRdirectory sits inside a git repository and Claude Code keeps your local settings at the repository root instead, it holds the rules like anywhere else.Anywhere else: Claude Code holds the file's rules like project settings. Once the check has run, Claude Code applies the rules of an untracked file, or of a file in a directory outside any git repository, even though you haven't trusted that exact folder.
The configuration-home exception skips only the trust step.
~/.claude/settings.local.jsonis still local scope, so Claude Code reads it only in sessions you start in your home directory itself, not in every project. To apply permission rules across all your projects, add them to your user settings instead:~/.claude/settings.json, or$CLAUDE_CONFIG_DIR/settings.jsonwhenCLAUDE_CONFIG_DIRis set.
On versions 2.1.196 through 2.1.199, Claude Code held the file's rules in your configuration home and outside git repositories too, and printed the this workspace has not been trusted warning there. Before v2.1.207, Claude Code applied an untracked file's rules before you accepted the dialog.
What runs before you trust a folder
Each row is one kind of content a repository can supply. The columns are the two situations in which you haven't trusted the folder itself: you trusted only a parent folder, or you ran claude -p or the SDK there, which never shows the trust dialog. The parent-folder column doesn't apply inside a nested repository: in an interactive session Claude Code shows the trust dialog for it, and a claude -p or SDK run there follows the claude -p column.
| What the repository supplies | You trusted only a parent folder | claude -p or the SDK, folder never trusted |
|---|---|---|
Hooks in settings files, the env block and helper commands such as apiKeyHelper, and a project skill's hooks and allowed-tools | Used | Used. Workspace trust never gates a skill's allowed-tools in any session |
permissions.allow rules and additionalDirectories in .claude/settings.json | Not used until you accept the trust dialog, which appears again listing them | Not used. Claude Code prints a this workspace has not been trusted warning to stderr |
Frontmatter hooks in a project subagent, a project @skills-dir plugin, and extraKnownMarketplaces entries from the repository or an --add-dir directory | Not used, and no dialog is offered | Not used |
Inline mcpServers in the frontmatter of a subagent from the repository or an --add-dir directory. Before v2.1.238, Claude Code loaded these servers in both situations | Not used, and no dialog is offered | Not used |
Servers in .mcp.json, including ones the repository approves in its own settings | Claude Code asks you before connecting them. The repository's own approvals don't count | Connected without asking, approved or not. The SDK loads them only when settingSources includes project settings. claude mcp list in the same folder still reports such a server as pending |
A headersHelper on a server in .mcp.json. Before v2.1.238, Claude Code ran the helper in both situations | Not run until you accept the trust dialog, which appears again naming where the helper is declared. Claude Code connects the server with its static headers alone until then | Not run. Claude Code connects the server with its static headers alone and prints a headersHelper not run line per server to stderr |
For the rows that need this exact folder trusted, trust it by hand: set projects["<path>"].hasTrustDialogAccepted to true in ~/.claude.json, where <path> is the repository root, or the folder itself outside a repository. Claude Code prints the exact key in the debug log line for a skipped subagent hook or inline MCP server, in the stderr warning for skipped allow rules, and in the headersHelper not run line for a skipped helper.
Before you run claude -p in a repository you didn't write, decide what it may run on your machine:
- Pass
--setting-sources user, or set the SDK'ssettingSourceswithout project settings, so Claude Code reads neither the project's settings files nor its.mcp.json - Start with
--bareso Claude Code reads no hooks, skills, custom commands, subagents, plugins, or.mcp.jsonservers from the project. The project'senvblock and helpers such asawsAuthRefreshin its settings files still apply, and Claude Code readsapiKeyHelperonly from--settings - Pass
--settings '\{"disableAllHooks": true\}'to turn hooks off for that run. Setting it in your user settings alone isn't enough, because the repository's project settings take precedence over yours and can set it back tofalse - Add a
disabledMcpjsonServersentry to reject a.mcp.jsonserver by name in every session type