GUIDESEPISODES
Claude Code permissions: invite-only in 4 settings
It’s 2 AM and Claude just pushed to main. Nobody broke a rule: in auto mode, pushing to your own repository is allowed by default. Vampires only come in when invited. Claude can work the same way. Here are the four settings that make the invitation yours, each checked against Anthropic’s own docs.

01PRODUCT 1 · THE MODE DIAL
Know which mode Claude is in
Why it mattersYou can’t set a boundary for a mode you don’t know you’re in.
Here’s the 2 AM story. You asked Claude to fix a bug. It fixed it, committed, and pushed to main. You never saw a prompt. That isn’t a glitch. It’s the mode you were in.

Open the full chapterIncludes a table, a note, code
Anthropic’s docs say it plainly. From v2.1.283, auto mode is “the built-in starting permission mode for interactive terminal and VS Code sessions.” Runs started with claude -p begin in Manual instead.
Read the status bar
Press Shift+Tab to cycle modes. The status bar under the prompt shows where you are:
| Status bar | Mode | What runs without asking |
|---|---|---|
⏵⏵ auto mode on | auto | Everything, with background safety checks |
⏸ manual mode on | default (Manual) | Reads only |
⏵⏵ accept edits on | acceptEdits | Reads, file edits, and common filesystem commands |
⏸ plan mode on | plan | Reads, plus classifier-approved commands when auto mode is available |
What auto mode stops, and what it lets through
In auto mode, a second model, the classifier, reviews actions instead of you. Its default block list includes curl | bash, “production deploys and migrations” and “force push”.
Now read its default allow list. It includes “pushing to any branch of the repository you’re working in, including the default branch.” So a push to main is not, by itself, something it stops.
Want every session to start in Manual instead? The docs’ example goes in ~/.claude/settings.json. The next session shows ⏸ manual mode on.
{
"permissions": {
"defaultMode": "default"
}
}default is the config name for Manual. You can still switch to auto with Shift+Tab whenever you want.
02MAKE IT STICK
Say “don’t push”, then make it a deny rule
Why it mattersA sentence in chat can be summarized away. A rule in settings.json can’t.
Telling Claude works, for a while. The docs: “If you tell Claude “don’t push” or “wait until I review before deploying”, the classifier blocks matching actions even when the default rules would allow them.”

Open the full chapterIncludes steps, code, a note
The catch is memory. Boundaries “are not stored as rules”, and “a boundary can be lost if context compaction removes the message that stated it. For a hard guarantee, add a deny rule instead.”
Add the rule in /permissions
- Type
/permissionsin Claude Code. It lists every rule and the settings file it comes from. - Add
Bash(git push *)as a deny rule to block pushes, or as an ask rule to get a prompt before each one. - Save it to
.claude/settings.jsonto share it with your team through git, or to~/.claude/settings.jsonfor every project.
Or write it in the file yourself. This block is the docs’ own example: npm scripts and commits run without asking, and pushes are refused.
{
"permissions": {
"allow": [
"Bash(npm run *)",
"Bash(git commit *)"
],
"deny": [
"Bash(git push *)"
]
}
}Rules are checked in order: deny, then ask, then allow. The first match wins.
Two lines from the docs explain why this beats a chat message. “Deny rules block in every mode, including bypassPermissions.” And: “Permission rules are enforced by Claude Code, not by the model.”
03PRODUCT 2 · DOUBLE GARLIC
Deny .env and .env.*, not just one
Why it mattersThe key you forgot to deny is the one in .env.local.
Most people deny .env and stop there. But your keys often aren’t in .env. Next.js loads environment variables from every .env* file. Its docs add that .env*.local files “are intended to be ignored through .gitignore.” That makes .env.local the usual home of your local secrets.

Open the full chapterIncludes code, a table, a note
So deny both patterns:
{
"permissions": {
"deny": [
"Read(.env)",
"Read(.env.*)",
"Read(!.env.example)"
]
}
}The ! line must come after the rules it carves out of, in the same list. Keep real values out of .env.example.
| Rule | What it blocks |
|---|---|
Read(.env) | Any .env at or under the current folder. The docs: a bare filename matches “at any depth, so Read(.env) and Read(**/.env) are equivalent” |
Read(.env.*) | .env.local, .env.production, .env.development.local and every other .env. file |
Read(!.env.example) | Nothing. It reopens the example file, which holds names, not values |
Read(./.env) | Only the .env in the current folder, not one inside apps/web/ |
A Read deny rule also blocks the Edit and Write tools on the same path, so Claude can’t rewrite the file either.
04PRODUCT 3 · THE MOAT
Turn on /sandbox and pick auto-allow
Why it mattersWords can be rephrased. The operating system doesn’t read the command, it enforces the wall.
Permission rules match words. The sandbox is different: it’s a wall the operating system enforces around the shell commands Claude runs, and the processes they start. It covers Bash, PowerShell and Monitor commands on macOS, Linux and WSL2. On native Windows, commands run unsandboxed.

Open the full chapterIncludes steps, a table, code, a note
It’s off by default. To turn it on:
- Type
/sandboxin Claude Code. - On the Mode tab, pick auto-allow. Sandboxed commands then run without a prompt, because the wall holds them.
- Ask Claude to run
touch ~/sandbox-probe. Inside the sandbox it fails withOperation not permittedon macOS, orRead-only file systemon Linux and WSL2.
| Access | Default inside the sandbox |
|---|---|
| Writes | The working directory, a per-user temp directory, and directories you’ve added |
| Network | No direct route out. A proxy checks each host against your allowed domains, which start empty |
| Reads | Most of the machine, including ~/.ssh and ~/.aws/credentials |
| Environment variables | Inherited from Claude Code, including any secrets in it |
The panel saves your choice to .claude/settings.local.json, for this project. To turn it on for every project, put this in ~/.claude/settings.json:
{
"sandbox": {
"enabled": true
}
}Auto-allow keeps your rules in force. Deny rules still block, and an ask rule like Bash(git push *) still forces a prompt, even for sandboxed commands.
05THE FINE PRINT
The moat lets reads in: lock ~/.ssh yourself
Why it mattersA wall with an open window still needs a lock on the safe.
Here’s the line most people miss. By default, sandboxed commands can read most of the machine. The docs name ~/.ssh and ~/.aws/credentials as examples. There’s no safety net either: “There is no built-in credential deny list.” Only the files and variables you list are restricted.

Open the full chapterIncludes code, a note
So list them. This block is from the docs:
{
"sandbox": {
"enabled": true,
"credentials": {
"files": [
{ "path": "~/.aws/credentials", "mode": "deny" },
{ "path": "~/.ssh", "mode": "deny" }
],
"envVars": [
{ "name": "GITHUB_TOKEN", "mode": "deny" },
{ "name": "NPM_TOKEN", "mode": "deny" }
]
}
}
}File entries are denied for reads inside the sandbox. Variable entries are unset before each sandboxed command runs.
files: your SSH keys and cloud credentials. Add any other folder that holds a key, such as a~/.configtool login.envVars: tokens your shell exports, such asGITHUB_TOKENorNPM_TOKEN.- Any scope can add a deny entry, and no scope can remove one that another scope added.
06PRODUCT 4 · THE PEEPHOLE
Check who’s at the door with /mcp
Why it mattersEvery server you don’t use is a door you don’t need.
Every MCP server you connect is a guest with its own reach. Anthropic’s MCP page puts it in bold: “Verify you trust each server before connecting it. Servers that fetch external content can expose you to prompt injection risk.”

Open the full chapterIncludes steps, code, a note
And on its security page: Anthropic reviews connectors before adding them to its directory, “but does not security-audit or manage any MCP server.”
Look through the peephole
- Type
/mcp. It shows every connected server and its tools. - Toggle off any server you don’t use. The docs: that stops Claude Code connecting to it “without losing its configuration.”
- For the ones you keep, ask what each can reach: your files, your database, the web.
Checking .mcp.json alone isn’t enough. Servers at other scopes and claude.ai connectors live outside the repository. The security page: “reviewing .mcp.json doesn’t show every server a session can load.” /mcp shows them all.
Invite new guests the careful way
claude mcp add --transport http <name> <url>The docs’ basic syntax for a remote HTTP server.
If you share a .mcp.json with your team, keep tokens out of it. Claude Code expands environment variables, so the file holds a name and your machine holds the value:
{
"mcpServers": {
"api-server": {
"type": "http",
"url": "${API_BASE_URL:-https://api.example.com}/mcp",
"headers": {
"Authorization": "Bearer ${API_KEY}"
}
}
}
}The docs’ example. ${API_KEY} is read from your environment; ${VAR:-default} adds a fallback.
07THE ORDER FORM
The whole invite-only kit on one page
Why it mattersInvite once, on purpose. Then let Claude work.
Keep this next to your editor.

Open the full chapterIncludes a table, code, a note
| Product | Do this | What it stops | What it doesn’t |
|---|---|---|---|
| The Mode Dial | Shift+Tab, read the status bar; Bash(git push *) deny or ask | A push you didn’t ask for, in every mode | git -C . push and other spellings |
| Double Garlic | Deny Read(.env) and Read(.env.*) | Claude’s file tools reading or editing your secrets | grep -r or a script that opens the file itself |
| The Moat | /sandbox → auto-allow | Shell writes outside the project, and hosts you haven’t allowed | File tools, MCP servers and hooks |
| The Peephole | /mcp, switch off what you don’t use | Servers you forgot you connected | A trusted server that fetches hostile content |
Here is the whole kit as one settings file. Merge it with what you have; don’t replace your file.
{
"permissions": {
"deny": [
"Bash(git push *)",
"Read(.env)",
"Read(.env.*)",
"Read(!.env.example)"
]
},
"sandbox": {
"enabled": true,
"credentials": {
"files": [
{ "path": "~/.aws/credentials", "mode": "deny" },
{ "path": "~/.ssh", "mode": "deny" }
],
"envVars": [
{ "name": "GITHUB_TOKEN", "mode": "deny" }
]
}
}
}Prefer a prompt over a block for pushes? Move Bash(git push *) into an ask list instead.
Then paste the prompt at the top of this page into Claude Code. It reads your settings and MCP list, and shows you the diff before it changes anything.
THE QUICK READ
What to take away.
In one minute.
- 01
With Claude Code v2.1.283 or later, auto mode is where interactive terminal and VS Code sessions start. Press Shift+Tab to see and change it.
- 02
In auto mode a classifier model reviews actions. It blocks force push and production deploys, but “pushing to any branch of the repository you’re working in, including the default branch” is allowed by default.
- 03
Saying “don’t push” works until compaction drops the message. The docs: “For a hard guarantee, add a deny rule instead.”
- 04
Deny rules block in every mode, including
bypassPermissions. They are enforced by Claude Code, not by the model. - 05
Deny
Read(.env)andRead(.env.*). The first matches.envat any depth; the second covers.env.local, where Next.js keeps local secrets. - 06
The sandbox is off by default.
/sandboxadds an OS-level wall around shell commands. Reads stay open, so list~/.sshand~/.aws/credentialsyourself. - 07
/mcpshows every connected server. Keep the ones you trust and use, and switch off the rest.
THE TAKEAWAY, IN ONE PASTE
Paste this once. See who’s invited.
Paste this into Claude Code. It reads your settings files and MCP list, then proposes deny rules and sandbox JSON. It changes nothing until you see the diff and say yes, and it masks any token it finds.
Check my Claude Code setup before I let it work on its own. Never print a token or key: mask it. 1) Tell me which permission mode my sessions start in and whether auto mode is on. 2) Read .claude/settings.json, .claude/settings.local.json and ~/.claude/settings.json and list every allow, ask and deny rule. 3) If they are missing, propose deny rules for Bash(git push *), Read(.env) and Read(.env.*). 4) Tell me whether the sandbox is on and which credential folders (~/.ssh, ~/.aws) are listed under sandbox.credentials; propose the exact JSON. 5) List every MCP server in .mcp.json and ~/.claude.json, what each can reach, and flag any I don't use or that fetch web content. Show me the diff before you change anything.
Paste it into the agent you already build with
- Claude
- ChatGPT
- Gemini
- Cursor
- Copilot
QUESTIONS PEOPLE ASK
Good questions.
Short answers.
What permission mode does Claude Code start in?
With Claude Code v2.1.283 or later, interactive terminal and VS Code sessions start in auto mode. Runs started with claude -p start in Manual. Press Shift+Tab and read the status bar to see yours.
Can Claude Code push to main in auto mode?
Yes, by default. Anthropic’s docs list “pushing to any branch of the repository you’re working in, including the default branch” as allowed. Force push and production deploys are blocked by default.
How do I stop Claude Code from pushing?
Add Bash(git push *) as a deny rule in /permissions or in settings.json. Deny rules block in every mode. Use an ask rule instead if you want a prompt before each push.
Is telling Claude “don’t push” enough?
It works while the message is in context. The docs say such a boundary can be lost if context compaction removes it, and recommend a deny rule for a hard guarantee.
How do I stop Claude Code from reading my .env file?
Add Read(.env) and Read(.env.*) to permissions.deny. The first matches .env at any depth; the second covers .env.local and the rest. Turn on the sandbox too, because deny rules don’t stop a command like grep -r.
What does /sandbox do in Claude Code?
It turns on an OS-level wall around the shell commands Claude runs. Writes stay in your project and temp folder, and network traffic goes through a proxy that checks each host. Reads stay open, so list ~/.ssh and ~/.aws/credentials under sandbox.credentials.
Are MCP servers safe to use with Claude Code?
Only as safe as the server. The docs say to verify you trust each server, and warn that servers that fetch external content can expose you to prompt injection. Anthropic does not security-audit MCP servers. Use /mcp to switch off the ones you don’t use.
Does Aster check my Claude Code settings?
No. Aster reads your GitHub repository and flags secret keys committed in your code or shipped to the browser. Your permission mode, deny rules, sandbox and MCP servers are yours to set with this guide.
Know the mode, deny the push, double the garlic, dig the moat, check the peephole. Letting Claude ship faster means checking the code before launch: your first Aster repository audit is free, and it flags secret keys committed in your code or shipped to the browser.
Source notebook7 links
- Claude Code Docs: Choose a permission mode (auto mode, what the classifier blocks, boundaries)
- Claude Code Docs: Configure permissions (deny rules, Read and Edit patterns, Bash rule limits)
- Next.js Docs: Environment variables (.env files, .env*.local)
- Claude Code Docs: Configure the sandboxed Bash tool (/sandbox, defaults, protect credentials)
- Claude Code Docs: Connect Claude Code to tools via MCP
- Claude Code Docs: Security (MCP security)
- Claude Code Docs: Manage costs effectively (Reduce MCP server overhead)










