Developer productivity and operational enablement — reference
Developer productivity and operational enablement — reference
A decision-table companion. Each table names a decision, the documented input that settles it, and the claim it does not license.
1. Where a setting lands (LO1.S1)
| Scope | Who it affects | Use it for |
|---|---|---|
User (~/.claude/settings.json) | You, in every project on this machine | Personal preferences and your own permission rules |
Shared project (.claude/settings.json) | Everyone working in the folder — in a git repository, commit it so teammates get it | Team permissions, hooks, plugins, project environment |
Project local (.claude/settings.local.json) | You, in this one project only | Personal overrides, and testing before you share |
| Managed | Everyone the organization deploys it to | Security policy and compliance requirements |
⚠ Installing Claude Code creates no settings file. Any file you find came from you, your team, or your organization.
Precedence, highest first
| Level | Notes |
|---|---|
| Managed settings | Nothing you set overrides them; a key passed with --settings does not either |
| Command line arguments | One session |
| Project local | Your personal file for this project |
| Shared project | What your team committed |
| User | Your personal file everywhere |
⚠ Environment variables are not a level in this stack. When a behaviour has both a shell variable and a settings key, which one applies is decided per pair, not by level.
⚠ Two documented cases run against the stack: a handful of security-sensitive keys honour the stricter value from a lower level over a managed value, and the permissive permissions.defaultMode values do not take effect from project or local settings at all.
How values combine
| Kind of key | Rule |
|---|---|
A list key, such as permissions.allow | The lists combine, so each file adds entries without removing another file's |
An ordered chain, such as fallbackModel | Position carries meaning, so the whole value comes from the highest file that defines it |
| A tool server entry | The entire entry from the highest-precedence scope; fields are never merged across scopes |
2. Sharing with a team (LO1.S2, LO1.S3)
| Goal | Where it goes |
|---|---|
| The same for everyone who clones | The committed shared project file |
| A personal exception | That developer's project local file, which needs no commit |
| Non-negotiable | Managed settings |
⚠ Hook entries merge across settings levels rather than replacing each other, and disableAllHooks cannot switch off a managed hook from outside managed settings.
⚠ Command hooks execute shell commands with your full user permissions. Review and test them before adding them.
Tool server scopes
| Scope | Loads in | Shared | Stored in |
|---|---|---|---|
| Local (the default) | Current project only | No | The home directory configuration |
| Project | Current project only | Yes, via version control, after each teammate approves it | A file at the project root |
| User | All your projects | No | The home directory configuration |
⚠ Two different things are called "local scope." A local-scoped tool server lives in the home directory configuration; general local settings live in the project directory. The documentation calls the collision out itself.
Sharing without sharing secrets: the shared server file supports environment variable expansion, offered so teams can share configurations while keeping machine-specific paths and sensitive values like API keys out of the file. Committing it is not the last step: Claude Code prompts for approval in interactive sessions before using a project-scoped server.
3. Asked for, or guaranteed (LO2.S1, LO2.S2)
| Mechanism | What it gives you |
|---|---|
| Instruction files | Context, not enforced configuration. Delivered as a user message after the system prompt, with no guarantee of strict compliance |
| A hook | A shell command at a fixed lifecycle event, which applies regardless of what Claude decides to do |
⚠ When it must run at a specific point — before every commit, after each file edit — write it as a hook. Making the instruction more specific improves consistency and does not make it enforcement.
Choose the cadence
| Cadence | Events |
|---|---|
| Once per session | SessionStart, SessionEnd |
| Once per turn | UserPromptSubmit, Stop, StopFailure |
| On every tool call | PreToolUse, PostToolUse |
⚠ An async hook cannot block or control behaviour: decision fields have no effect, because the action they would have controlled has already completed. A check that must stop something runs synchronously on an event that can block — PreToolUse blocks the tool call; PostToolUse is documented as unable to block, because the tool already ran.
4. Running it unattended (LO2.S3)
| Mode | What the repository's content does |
|---|---|
-p without --bare | Its committed hooks run and its tool servers connect — in a folder you have never trusted |
-p --bare | Neither is read at all |
⚠ A print session shows no workspace trust dialog and no per-server approval prompt. Before scripting it over a repository you did not write: review its settings files, start with --bare, or turn hooks off for that run with disableAllHooks.
Bare mode skips auto-discovery of hooks, skills, custom commands, subagents, plugins, tool servers, auto memory and the instructions file, which is why it is documented for CI and scripts that need the same result on every machine. It also never reads OAuth credentials or the keychain, so supply an API key in the environment or an apiKeyHelper in the --settings JSON. Amazon Bedrock, Google Cloud's Agent Platform and Microsoft Foundry keep reading their own provider credentials as usual.
The GitHub Action
| Input | Mode |
|---|---|
No prompt | Interactive: Claude waits for the trigger phrase and answers in a comment |
A prompt | Automation: Claude runs unattended, and results appear in the workflow run log by default |
The gates differ by event. Write access is checked on issue and pull request events, and events that no user authors, such as a schedule trigger, skip that check. The human-actor check applies on every event: a bot actor is rejected unless listed in allowed_bots, which keeps bots from triggering Claude in a loop.
5. Reading it back (LO3.S1, LO3.S2)
| Symptom | First reading |
|---|---|
| A setting is ignored | /status, to see which settings files the session actually loaded |
| None of your settings apply | Settings files are strict JSON — a // comment or a trailing comma is a Settings Error at the next start |
| A standing rule is not followed | /context, and the Memory files list; if a file is missing there, Claude cannot see it |
| A hook did nothing | The debug log: which hooks matched, their exit codes, and full stdout and stderr |
⚠ The --debug flag does not print to the terminal. Write the log to a path you name with --debug-file, or read it under the home directory keyed by session. For matching detail specifically, set CLAUDE_CODE_DEBUG_LOG_LEVEL=verbose.
What a hook's exit code says, and to whom
| Exit | What reaches Claude | What reaches the transcript |
|---|---|---|
0 | Nothing from stderr | Nothing; stderr goes to the debug log only |
2, on an event that can block | The blocking reason | The block, which JSON cannot override |
2, on an event that cannot block | The failure, e.g. PostToolUse shows stderr to Claude | Nothing blocked; the tool already ran |
| Anything else, for most events, with plain-text or empty stdout | Nothing | A <hook name> hook error notice with the first line of stderr |
⚠ A hook that exits 0 after printing a warning has warned nobody. To surface a warning to Claude from a PostToolUse or PostToolUseFailure hook, exit 2 instead; it works even though the tool already ran.
Why it worked for the author
| Session | Hooks from a settings file |
|---|---|
| Interactive, folder not yet trusted | Held back, including from your own user file |
| Interactive, folder trusted | Run |
-p or SDK | Run regardless; no dialog is ever shown |
⚠ Do not explain a hook with the local-file exemption. An allow rule in an untracked project local file skips the trust step the committed file requires — but that exemption covers permission allow rules, and the hooks documentation says hooks are held back from every settings file, the author's own included. The author's folder is simply trusted already, possibly through a parent directory whose trust extends to it, and the teammate's fresh clone is not.