For You Who Wasted Your Day Pressing Enter in Claude Code
5 minutes of permission setup eliminates the Accept hell. Stop babysitting your AI agent.
Introduction
If you've used Claude Code, you've been here before.
Claude is cranking out code, making great progress — then it stops. "Do you want to allow this command?" You press Enter. It stops again. "Do you want to allow this file edit?" Enter again. You step away to grab coffee, come back, and Claude is frozen on a permission prompt. The entire time you were gone, Claude did absolutely nothing.
After this happens enough times, you end up choosing between two extremes:
- Sit in front of the monitor pressing Enter — Watch Claude work and hit Accept every time it asks. You can't do anything else.
- Use
--dangerously-skip-permissions— Skip all permission checks. Convenient, but the name literally starts with "dangerously."
There's a middle ground. Set up your permissions properly.
Why Does Claude Code Keep Asking?
Claude Code manages permissions at the tool level. Reading files, editing files, running bash commands — each is a separate tool call, and by default, most tool calls require user approval.
It's a safety feature, but the result is Claude asking "Can I do this?" for every single action.
The key insight: If you pre-approve safe operations, Claude never needs to ask.
Understanding Permission Files
Claude Code permissions are managed in three locations:
| File Location | Scope | Git Shared |
|---|---|---|
~/.claude/settings.json | All projects (global) | ❌ |
.claude/settings.json | Current project | ✅ (team shareable) |
.claude/settings.local.json | Current project (personal) | ❌ |
Priority order: .local.json > .claude/settings.json > ~/. More specific settings win.
The basic structure:
{
"permissions": {
"allow": [],
"deny": []
}
}Items in allow execute without prompts. Items in deny are completely blocked. Deny always takes priority. Anything not in either list triggers a prompt.
Escape Accept Hell in 5 Minutes
Step 1: Allow All Read Tools
Reading files is safe. It doesn't change anything.
{
"permissions": {
"allow": [
"Read",
"Glob",
"Grep"
]
}
}This alone makes a noticeable difference. Claude exploring your codebase no longer triggers constant prompts.
Step 2: Allow Write Tools
File modifications are also mostly safe if you're using Git. You can always revert.
{
"permissions": {
"allow": [
"Read",
"Glob",
"Grep",
"Edit",
"Write"
]
}
}At this point, all file read/write prompts are gone. But the real bottleneck is next.
Step 3: Allow Safe Bash Commands
Bash commands support wildcard pattern matching with *. This is where it gets powerful.
{
"permissions": {
"allow": [
"Read",
"Glob",
"Grep",
"Edit",
"Write",
"Bash(git status *)",
"Bash(git diff *)",
"Bash(git log *)",
"Bash(git add *)",
"Bash(git commit *)",
"Bash(npm test *)",
"Bash(npm run lint *)",
"Bash(npm run build *)",
"Bash(npx prettier *)",
"Bash(ls *)",
"Bash(pwd)"
],
"deny": [
"Bash(rm -rf *)",
"Bash(git push --force *)"
]
}
}With this setup, Claude can read, edit, run git operations, execute tests, and build — all without a single Accept prompt.
Note: When
*follows a space (likeBash(ls *)), it enforces a word boundary.Bash(ls *)matchesls -labut NOTlsof. Without the space,Bash(ls*)matches both.
Project-Specific Configurations
Different projects use different tools. Put project-specific settings in .claude/settings.json at the project root.
Spring/Gradle Project
{
"permissions": {
"allow": [
"Read", "Glob", "Grep", "Edit", "Write",
"Bash(./gradlew build *)",
"Bash(./gradlew test *)",
"Bash(./gradlew spotlessApply *)",
"Bash(./gradlew detekt *)",
"Bash(git *)"
],
"deny": [
"Bash(./gradlew publish *)",
"Bash(rm -rf *)"
]
}
}Next.js Project
{
"permissions": {
"allow": [
"Read", "Glob", "Grep", "Edit", "Write",
"Bash(npm run *)",
"Bash(npx *)",
"Bash(git *)"
],
"deny": [
"Bash(npm publish *)",
"Bash(rm -rf *)"
]
}
}Python Project
{
"permissions": {
"allow": [
"Read", "Glob", "Grep", "Edit", "Write",
"Bash(python -m pytest *)",
"Bash(python *)",
"Bash(pip install *)",
"Bash(ruff check *)",
"Bash(ruff format *)",
"Bash(git *)"
],
"deny": [
"Bash(rm -rf *)"
]
}
}Share With Your Team for Maximum Impact
.claude/settings.json can be committed to Git. When the whole team uses the same permission settings:
- No individual setup needed for each team member
- Dangerous commands are blocked at the team level
- New team members can use Claude efficiently from day one
Personal additions go in .claude/settings.local.json. Add this file to .gitignore to keep it private.
Don't Use --dangerously-skip-permissions
It's tempting. "Why not just allow everything?"
Don't. Here's why:
- Claude makes mistakes. Commands like
rm -rfandgit push --forcecan cause serious damage with a single slip. - Hallucinations. Claude occasionally fabricates commands or operates on wrong paths.
- No audit trail. You lose the ability to review what's being executed.
Proper permission setup gives you nearly identical convenience without --dangerously-skip-permissions. The only difference is whether it stops on dangerous commands or doesn't stop at all.
The Claude Code developer Boris himself doesn't use Skip Permissions. He uses permission settings instead.
Still Getting Accept Prompts?
If you've set things up and still see frequent prompts, check the pattern.
See which commands Claude stops on. If they're safe, add them to your allow list. Repeat this 2-3 times and Accept prompts virtually disappear from your daily workflow.
Tip: When Claude requests permission, selecting "Always allow" automatically adds it to your settings file. But managing the settings file directly is cleaner and more precise.
Wrapping Up
Here's the summary:
- If you're spending your day pressing Enter in Claude Code, your permissions aren't configured.
- Add to
allowin order: read tools → write tools → safe bash commands. - Set up
.claude/settings.jsonper project and share it with your team. - Don't use
--dangerously-skip-permissions.
Five minutes of setup eliminates the Enter key waiting game. You no longer need to sit in front of your monitor babysitting Claude. While Claude works, you can actually do something else.