How to Set Up Claude Code Permissions for Junior Developers
To set up Claude Code permissions for junior developers, create a .claude/settings.json file in your project root with a permissions object containing allow and deny arrays. List safe commands like test runners in the allow array, and list anything that must never execute — secrets files, package installs, deploy scripts — in the deny array. Because deny rules fire first and block unconditionally, this gives you a reliable safety net even when a junior developer is pairing with Claude in an unfamiliar codebase.
What Problem Do Claude Code Permissions Solve for Junior Developers?
Without a permissions configuration, every file write and shell command Claude attempts requires a manual approval click. That friction is manageable for an experienced developer who knows what to expect, but it creates two opposite problems for junior developers: either they approve everything reflexively (defeating the safety check) or they get overwhelmed and stop using Claude at all.
The permissions system solves this by letting a team lead define safe corridors in advance. Claude can move quickly inside those corridors — running linters, executing tests, reading source files — while genuinely dangerous operations like reading .env files or calling external APIs are caught automatically before execution, with no decision required from the junior developer in the moment.
As the Claude Code security documentation describes it, the system evaluates rules in a strict hierarchy: deny rules fire first and block unconditionally, then allow rules grant silent auto-approval, and anything not matched either prompts the user or is blocked depending on the active permission mode.
How Do You Create the Permissions File?
The configuration lives in a JSON file. There are two locations:
- Project-level:
.claude/settings.jsonin your repository root — checked into version control so every team member gets the same rules automatically. - Global-level:
~/.claude/settings.jsonon the developer's machine — useful for personal defaults like always blocking reads of SSH or cloud credential files regardless of project.
Project-level rules take precedence over global ones. For a junior developer onboarding scenario, the project-level file is the right place to start because it travels with the repo and requires no per-machine setup.
Inside the file, add a permissions object with allow and deny arrays. Each entry is a tool-name string, optionally with a parenthesized argument pattern. For example, Bash(npm run test) allows that exact command, while Read(./.env) denies reads of the environment file.
What Does a Real Junior-Developer Config Look Like?
Here is a practical starting configuration for a JavaScript project where you want Claude to run tests and linting but block access to secrets and prevent dependency changes:
{
"permissions": {
"allow": [
"Bash(npm run lint)",
"Bash(npm run test *)",
"Bash(npm run build)"
],
"deny": [
"Read(./.env)",
"Read(./.env.*)",
"Read(./secrets/**)",
"Bash(npm install)",
"Bash(npm install *)",
"Bash(npm uninstall *)"
]
}
}
With this config in place, Claude will run npm run test button.test.js automatically without prompting, report the failing tests, fix the code, and re-run — all without interruption. If Claude ever attempts npm install lodash, it is blocked and informs the developer that package installation requires manual approval. If it tries to read .env, it is blocked silently.
How Do Permission Modes Change the Overall Behavior?
Beyond individual allow/deny rules, Claude Code has session-wide permission modes that set the overall posture:
| Mode | What it does | Best for junior devs when… |
|---|---|---|
default |
Asks before most tool uses | Exploratory sessions where the junior dev should stay aware of each action |
acceptEdits |
Silently approves file reads/writes; still prompts for shell commands | Large refactors where file changes are expected but shell access needs oversight |
dontAsk |
Prevents all tool execution — read-only analysis only | Code review or architecture exploration with zero risk of changes |
bypassPermissions |
Silently approves everything (deny rules still apply) | Isolated CI containers only — not appropriate for junior dev workstations |
For most junior developer scenarios, the combination of default mode plus explicit allow/deny rules in settings.json is the right starting point. The mode can be set via the CLI or toggled interactively during a session.
How Do You Audit What Rules Are Actually Active?
Because global and project settings merge together, it is easy to end up with a combined rule set that surprises you. Run /permissions in the Claude Code terminal to view the active merged rule set and audit what is currently allowed or blocked. This is especially useful when onboarding a new developer — have them run it at the start of a session to confirm the project rules loaded correctly.
The Claude Code settings documentation explains that URL allowlists and environment variable allowlists merge additively across global and project settings, while permission allow/deny rules follow a precedence hierarchy where project-level rules take priority.
What Are the Most Common Mistakes When Setting Up Permissions?
Wildcard patterns don't match the way you expect
The asterisk in a rule like Bash(npm *) matches a single argument segment — it does not capture all npm subcommands universally. For maximum reliability, list each permitted command explicitly: Bash(npm run lint), Bash(npm run test *), Bash(npm run build) rather than relying on a single wildcard rule. Also note that spacing matters: Bash(ls *) requires a space before an argument, so a command like lsof would not match it.
Assuming deny rules don't apply in bypassPermissions mode
Deny rules are enforced even in bypassPermissions mode — if a deny rule matches, the tool is blocked. This is actually good news for junior developer setups: even if someone accidentally enables a more permissive mode, your deny rules for secrets files remain in effect.
Symlink bypass assumptions
The permission system evaluates both the symlink path and the physical target path. For a deny rule, either path matching is sufficient to trigger a block — so secrets files are protected even through symlinks. For an allow rule, both paths must match. This means you cannot grant access to a symlink and assume the real file is also covered.
Using the wrong flag in headless pipelines
If your team uses CI pipelines, be aware that one common flag triggers an interactive consent dialog on first run — a headless pipeline without a terminal will freeze indefinitely waiting for that confirmation. Use --permission-mode dontAsk or --permission-mode bypassPermissions in CI pipelines instead, as these suppress the consent dialog entirely.
When Should You Use Project-Level vs. Global Settings?
Use project-level .claude/settings.json rules when permissions should be specific to one repository and checked into version control for team consistency. This is the right choice for junior developer onboarding because the rules travel with the repo — no per-machine configuration required, and a team lead can update the rules in a single commit that applies to everyone.
Use global ~/.claude/settings.json for personal defaults that apply across all projects — for example, always blocking reads of SSH keys or cloud credential directories regardless of which project is open. Encourage junior developers to set a global deny rule for their credentials directories as a baseline habit.
Is There an Enterprise Option for Organization-Wide Rules?
For larger teams, Claude Code supports organization-wide permission ceilings configured in Organization Settings. Individual role grants cannot exceed those ceilings, which means a security team can enforce hard limits — for example, blocking SSH-based deploy commands across the entire organization — while still allowing product engineers to freely use tools like the GitHub CLI for pull requests. This is described in the enterprise deployment documentation.
Step-by-Step: Setting Up Permissions for a New Junior Developer
- Create
.claude/settings.jsonin your project root if it does not already exist. - Add a
permissionsobject containingallowanddenyarrays. Each entry is a tool-name string, optionally with a parenthesized argument pattern — for example,Bash(npm run test *). - Put anything that must never execute in the
denyarray first. Deny rules take precedence over allow rules unconditionally. - Add allow rules for the specific commands Claude should run without prompting — test runners, linters, build scripts.
- Commit the file to version control so every developer who clones the repo gets the same rules automatically.
- Have the junior developer run
/permissionsin the Claude Code terminal at the start of their first session to verify the merged rule set looks correct. - For read-only code review sessions, start Claude Code with
--permission-mode dontAskto make it impossible for Claude to modify any files.
This setup gives junior developers the productivity benefits of Claude Code automation immediately, while the team lead retains control over which operations are permitted — without requiring the junior developer to make security judgment calls in the moment.
Frequently asked questions
Where does the Claude Code permissions file go?
Create .claude/settings.json in your project root for project-specific rules that apply to everyone who checks out the repository. For personal defaults across all projects, use ~/.claude/settings.json. Project-level rules take precedence over global ones.
Do deny rules apply even in bypassPermissions mode?
Yes. Deny rules are enforced even in bypassPermissions mode — if a deny rule matches, the tool is blocked unconditionally. This means your secrets-file deny rules remain in effect regardless of which permission mode is active.
How do I let Claude run tests but block package installs?
Add allow rules for your specific test and lint commands (e.g., Bash(npm run test *)) and deny rules for install and uninstall commands (e.g., Bash(npm install *)) in your .claude/settings.json permissions object. Claude will run tests silently but be blocked from changing dependencies.
What permission mode is safest for a junior developer reviewing unfamiliar code?
Use --permission-mode dontAsk for read-only analysis. In this mode Claude can read and reason about files but cannot write, edit, or run any command, making accidental changes impossible.
How do I verify which permission rules are actually active?
Run /permissions in the Claude Code terminal to view the active merged rule set showing what is currently allowed or blocked, including rules merged from both global and project settings files.
Can wildcard rules cover all npm subcommands at once?
Not reliably. The asterisk in a pattern like Bash(npm *) matches a single argument segment, not all subcommands universally. For reliability, list each permitted command explicitly rather than relying on a single broad wildcard rule.
Permissions & tool allowlists is one of 85 features in Claude Master — the independent, always-current manual with worked examples, the pitfalls, and the workflows that make Claude pay.
Get Claude Master — founding price →Independent product. Not affiliated with or endorsed by Anthropic. "Claude" is a trademark of Anthropic, used here only to describe the subject of this guide.