Filter to read-only. Keep only commands that don't mutate state. Examples of read-only: ls, cat, pwd, git status, git log, git diff, git show, git branch, rg, grep, find, head, tail, wc, file, which, echo, date, gh pr view, gh pr list, gh pr diff, gh issue view, gh issue list, gh run list, gh run view, gh api (GET), bun run typecheck, bun run lint, bun run test (for tests that don't mutate), docker ps, docker logs, kubectl get, kubectl describe, ps, top, df, du, env, printenv, any MCP tool with read/get/list/search/view in its name.
Drop anything that writes, deletes, renames, pushes, merges, installs, or runs a build/test that has side effects. When in doubt, leave it out.
Never allowlist a pattern that grants arbitrary code execution. A wildcard rule for any of these (e.g. Bash(python3:*)) is equivalent to allowing arbitrary code execution. This list is not exhaustive — apply the same rule to anything in the same category:
- Interpreters:
python/python3, node, bun, deno, ruby, perl, php, lua, etc.
- Shells:
bash, sh, zsh, fish, eval, exec, ssh, etc.
- Package runners:
npx, bunx, uvx, uv run, etc.
- Task-runner wildcards:
npm run *, yarn run *, pnpm run *, bun run *, make *, just *, cargo run *, go run *, etc. — an exact Bash(bun run typecheck) is fine, Bash(bun run *) is not
gh api *, docker run/exec, kubectl exec, sudo, and similar
Drop commands Claude Code already auto-allows. These don't need an allowlist entry — they never prompt. If you see any of these in the transcripts, skip them; don't suggest them to the user.
- Always auto-allowed (any args):
cal, uptime, cat, head, tail, wc, stat, strings, hexdump, od, nl, id, uname, free, df, du, locale, groups, nproc, basename, dirname, realpath, cut, paste, tr, column, tac, rev, fold, expand, unexpand, fmt, comm, cmp, numfmt, readlink, diff, true, false, sleep, which, type, expr, test, getconf, seq, tsort, pr, echo, printf, ls, cd, find.
- Auto-allowed with zero args only:
pwd, whoami, alias.
- Auto-allowed exact forms:
claude -h, claude --help, node -v, node --version, python --version, python3 --version, ip addr.
- Auto-allowed with safe flags only (validated):
xargs, file, sed (read-only expressions), sort, man, help, netstat, ps, base64, grep, egrep, fgrep, sha256sum, sha1sum, md5sum, tree, date, hostname, info, lsof, pgrep, tput, ss, fd, fdfind, aki, rg, jq, uniq, history, arch, ifconfig, pyright.
- All git read-only subcommands:
git status, git log, git diff, git show, git blame, git branch, git tag, git remote, git ls-files, git ls-remote, git config --get, git rev-parse, git describe, git stash list, git reflog, git shortlog, git cat-file, git for-each-ref, git worktree list, etc.
- All gh read-only subcommands:
gh pr view, gh pr list, gh pr diff, gh pr checks, gh pr status, gh issue view, gh issue list, gh issue status, gh run view, gh run list, gh workflow list, gh workflow view, gh repo view, gh release view, gh release list, gh api (GET), gh auth status, etc.
- Docker read-only subcommands:
docker ps, docker images, docker logs, docker inspect.
Source of truth: src/tools/BashTool/readOnlyValidation.ts (READONLY_COMMANDS, READONLY_NOARGS, READONLY_EXACT, COMMAND_ALLOWLIST) and src/utils/shell/readOnlyCommandValidation.ts (GIT_READ_ONLY_COMMANDS, GH_READ_ONLY_COMMANDS, DOCKER_READ_ONLY_COMMANDS, RIPGREP_READ_ONLY_COMMANDS, PYRIGHT_READ_ONLY_COMMANDS). If the user is in this repo and you're unsure whether a command is covered, grep these files rather than guessing.