Tutorials / Native Mac IDE / Reduce permission prompts
📝 Written ● Intermediate Updated 2026-05-19

Reduce permission prompts by allowlisting safe commands

Every time you click "approve" on ls, cat, or git status, you're paying a 3-second tax. Multiply by 50 prompts a day. The fix is a one-shot scan: LingCode reads your past transcripts, finds the safe commands you keep approving, and builds you a personalized allowlist.

Why "default safe" still feels noisy

0

LingCode prompts before every Bash command for one good reason: it can't tell ls from rm -rf ahead of time without asking. The default has to be paranoid or someone, somewhere, loses their work.

But after a week of real use, the prompts you've actually answered yes to are a small, repetitive set:

  • Inspect files: ls, cat, head, tail, file, stat.
  • Inspect git: git status, git diff, git log, git show, git branch.
  • Inspect builds: npm test, npm run lint, cargo check, swift build.
  • Inspect environment: which, node --version, echo $PATH.

None of those mutate state. None of them deserve a prompt. The discipline of writing them all out by hand is what nobody does — so this tutorial replaces the discipline with a scan.

What gets scanned

1

LingCode stores conversation transcripts locally on disk — each session is a JSON file under ~/.claude/projects/, namespaced by working directory. Inside each transcript, every tool call is recorded with its exact arguments and whether the user approved it.

The scan looks at:

  • Bash tool calls that were approved.
  • MCP server tool calls that were approved (read-only ones — list, get, read, describe — are typical safe candidates).
  • Frequency — commands seen more than a handful of times get prioritized; one-offs get ignored.

It does not touch your code or any sensitive content — only the metadata of tool calls and their approvals.

The scan is read-only by default. It reads transcripts, proposes a diff, and waits for your approval. Nothing lands in settings.json until you say so.

Run the scan

2

In the chat panel, ask LingCode:

Scan my recent transcripts for repeated safe Bash and MCP tool
calls. Build me a prioritized allowlist for this project's
.claude/settings.json. Show me the proposed diff before applying.

LingCode walks the transcripts in ~/.claude/projects/, counts approvals per command, classifies each into a safe category (read-only, build-check, env-inspection) or a "needs human judgment" category (anything that writes to disk, network, or system state), and proposes additions to permissions.allow.

The output looks roughly like this:

Found 47 unique approved Bash patterns across 23 sessions.
Categorizing:
  - read-only: 19 patterns, 312 total approvals
  - build/test: 8 patterns, 94 approvals
  - env inspection: 6 patterns, 41 approvals
  - judgment call: 14 patterns (NOT proposing)

Top 12 by frequency:
  Bash(ls:*)             ........ 87 approvals
  Bash(git status:*)     ........ 54 approvals
  Bash(cat:*)            ........ 41 approvals
  Bash(git diff:*)       ........ 38 approvals
  Bash(npm test:*)       ........ 22 approvals
  ...

Proposed diff for <repo>/.claude/settings.json:
+   "Bash(ls:*)",
+   "Bash(cat:*)",
+   "Bash(head:*)",
...

Review the proposal — what to keep, what to cut

3

Don't blindly accept the diff. Read it as a code review. Three checks:

  • Is the glob too loose? Bash(git:*) matches git status but also git push --force. Prefer the narrower form, e.g. Bash(git status:*), Bash(git diff:*), Bash(git log:*) as separate entries.
  • Does any entry write or network? The scan tries to keep these out, but if you spot curl, wget, npm install, git push, or anything with redirects, strip it. Approve those manually so you keep noticing them.
  • Is it project-specific or universal? Bash(ls:*) belongs in the user file (~/.claude/settings.json) so every project benefits. Bash(./scripts/build.sh:*) belongs in the project file. The scan defaults to the project file — move entries up as you go.
Network commands deserve a second look. Even something innocent like curl https://example.com can be weaponized if the URL was assembled at runtime. The scan filters these by default; if you see one in the proposed list, it's because LingCode wasn't sure — err on the side of "leave it prompting."

Apply the diff

4

Once the proposal looks right, tell LingCode:

Apply the cleaned-up allowlist to .claude/settings.json. Show the
final file when done.

LingCode writes the file with the new entries appended (it does not remove existing entries) and prints the result. The file hot-reloads — your next session benefits immediately.

If you don't already have .claude/settings.json at the project root, LingCode creates it with the standard skeleton. If you want the rules to live in your user-wide file instead, say so explicitly: "apply to ~/.claude/settings.json instead of the project file."

Confirm fewer prompts

5

The honest test isn't "did the file save" — it's "do I get fewer prompts in the next session." Open a new chat in the same repo and ask LingCode to do something that would have prompted before:

Show me the most recently modified files in src/ and tell me
what they likely do.

If your allowlist took effect, LingCode runs ls, stat, cat, and friends without any approval dialogs. If a prompt still appears, the most common cause is a pattern mismatch between what's in the allowlist and what LingCode wants to run — see Customize permissions and env vars for the glob syntax in detail.

Re-run the scan periodically

6

Your workflow drifts. New tools enter rotation, old ones fall away. Re-running the scan every couple of weeks keeps the allowlist matching reality:

Re-scan transcripts since <date of last scan> and propose
additions to .claude/settings.json. Don't touch existing entries.

The scan is incremental-friendly — give it a date floor and it only counts approvals after that point. This is how you avoid the allowlist quietly accumulating a year of stale entries.

What the scan deliberately won't propose

7
  • Destructive shell verbsrm, mv, dd, shutdown, kill -9 (even if you've approved them before).
  • Privilege escalation — anything starting with sudo or doas.
  • Package installsnpm install, pip install, brew install, cargo install. These mutate global state and pull arbitrary code.
  • Network writesgit push, scp, rsync to remotes, curl -X POST.
  • Shell-piping installerscurl ... | sh patterns. These should be approved by hand every single time.

The scan errs on the side of leaving these prompting. If you want one of them in the allowlist anyway, add it manually — but write the glob narrowly.

Use this in LingCode

8

The whole workflow — scan, classify, propose, review, apply, re-run — is packaged as a skill. Drop it into your skills folder and ask LingCode for "reduce my permission prompts" or "build me an allowlist" to invoke it:

---
name: fewer-permission-prompts
description: Use to reduce permission-prompt fatigue. Scans Claude Code session transcripts for common read-only Bash and MCP tool calls (ls, cat, grep, git status, find, etc.), then adds a prioritized allowlist to project .claude/settings.json. Triggers: 'too many permission prompts', 'allowlist commands', 'stop asking permission', 'auto-approve safe commands', 'reduce prompts', 'allow X command'. Actions: scan transcripts, classify SAFE-READ vs JUDGMENT, append to permissions.allow, save the 3-second tax on every ls. Hard exclude: rm, sudo, package installs, network writes.
---

Reduce LingCode permission prompts by analyzing past transcripts and
proposing a personalized allowlist.

Steps:
1. Walk ~/.claude/projects/<cwd>/ JSON transcripts (or the
   user-specified directory if asked). Count approved Bash and MCP
   tool calls per pattern. If a date floor was given, only count
   approvals after it.

2. Classify each pattern:
   - SAFE-READ: inspection-only verbs (ls, cat, head, tail, file,
     stat, pwd, which, git status, git diff, git log, git show, git
     branch, cargo check, swift build, npm test, npm run lint, npx
     tsc --noEmit, node --version, env, echo).
   - JUDGMENT: anything writing to disk, network, or system state.
     Do NOT propose these — leave them prompting.

3. Sort SAFE-READ by frequency. Drop one-offs (≤2 approvals).
   Convert exact commands to prefix-glob "Bash(<verb>:*)" only
   when the verb is universally safe; otherwise keep the literal.

4. Default target is <repo>/.claude/settings.json. Universal
   patterns (ls, cat, git status, git diff) can be hoisted to
   ~/.claude/settings.json — note this as an option in the diff.

5. Show the diff first. Never modify settings.json until the user
   approves. Preserve existing entries; only append.

6. After applying, suggest re-running the scan in 2 weeks with a
   date floor of today.

Hard exclusions — never propose: rm, mv, dd, shutdown, kill, sudo,
doas, npm install, pip install, brew install, cargo install, git
push, scp, rsync to remotes, curl -X POST, curl|sh patterns.

Save as ~/.lingcode/skills/fewer-permission-prompts/SKILL.md — see Install a skill for the exact location and how skills get discovered.

Get LingCode →

What's next