Add agentic-ai/Claude/ — bypassPermissions + PreToolUse safety hooks - #17
Conversation
Sets up version-controlled Claude Code config: bypassPermissions for frictionless operation, guarded by PreToolUse hooks that block dangerous Bash patterns (rm -rf root/home, dd to device, piped sh execution, force-push to main) and writes to sensitive paths (~/.ssh, ~/.aws, ~/.gnupg, /etc, etc.). install.sh wires everything into ~/.claude/ via symlinks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Other implementable tips from the article on Claude Code settingsWe built Tip 3 (bypassPermissions + hook validation). Here's what else is worth doing, roughly in priority order: Tip 4 — PostToolUse: auto-run tests after edits ⭐Configure a Would add Tip 6 — Hierarchical rules structure ⭐Already stubbed in the planned directory structure as Would add Tip 5 — Stop hook: session-end drift checkA Would add Tip 8 — Self-activating agents via rulesDefine trigger conditions in a rules file so Claude auto-invokes agents without being asked: complex features → planner, code changes → code-reviewer, bug fixes → tdd-guide. Reduces the need to remember which agent to ask for. Would live in Already covered / lower priority
One gap in our current Tip 3 implementationThe article's
|
…erarchy, agent triggers + gap fix Gap fix (Tip 3): - validate-bash.sh now blocks `sudo` (escalation must be explicit) and `git add -A`/`--all`/`.` (bulk staging can silently include secrets). Fixed regex to `(^|[^[:alnum:]_])sudo` so semicolon- and &&-prefixed sudo is also caught. Tip 4 — PostToolUse shellcheck: - hooks/post-edit-shellcheck.sh runs `shellcheck --severity=error` on any edited .sh file; exits 2 (blocking) if errors found. Skips gracefully when shellcheck is not installed. - Registered in settings.json under PostToolUse for Write|Edit|MultiEdit. Tip 5 — Stop drift check: - hooks/driftcheck.sh validates all git-tracked .sh files at session end: flags shebang/execute-bit inconsistency (has one but not the other). Library files (no shebang, not executable) are intentionally skipped. - Registered in settings.json under Stop. Tip 6 — Hierarchical rules structure: - rules/common/general.md: language-agnostic coding principles - rules/bash/style.md: bash scripting conventions - install.sh symlinks rules/ into ~/.claude/rules/ so @imports resolve Tip 8 — Self-activating agents: - rules/common/agents.md: when to proactively use Plan, Explore, /review, /security-review, and /verify without being asked. - CLAUDE.md @-imports all three rules files as user-level instructions. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
settings.json: - sandbox.enabled = true (bubblewrap on Linux, Seatbelt on macOS) - denyRead for ~/.ssh, ~/.aws, ~/.gnupg, ~/.config/gh - allowUnsandboxedCommands = false (disables escape hatch) Sandbox enforces filesystem + network isolation at the kernel level for all Bash subprocesses, replacing the need for regex-based path checks in validate-write.sh for the Bash tool surface. validate-write.sh is kept for Write/Edit/MultiEdit tools which are not sandboxed. setup-linux-sandbox.sh: - Installs the bwrap AppArmor profile required on Ubuntu 24.04+ and reloads AppArmor. Idempotent. No-ops on non-Ubuntu or if AppArmor is not present. install.sh: - Warns if Ubuntu is detected and the bwrap profile is missing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Make hook scripts and setup-linux-sandbox.sh executable so hooks fire. Remove ~/.gnupg from sandbox denyRead — passphrase-less keys make the restriction redundant, and it blocked autonomous GPG-signed commits. Add skipDangerousModePermissionPrompt. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Review notes — includes uncommitted Uncommitted change:
|
Add ~/.gnupg to allowWrite so GPG can create temp files for signing commits. Add ~/.config/gh to allowWrite so gh auth login can persist tokens. Both were missing from the sandbox allowWrite list. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…AN.md
- All four hook scripts: add set -euo pipefail + trap 'exit 2' ERR so
unexpected failures (jq missing, unbound var) fail-closed instead of
silently passing
- validate-bash.sh: remove unnecessary cat | jq subshell; jq reads stdin
directly
- driftcheck.sh: guard read -r first_line with || first_line= so empty
files don't trip set -e
- README: correct denyRead docs (only ~/.ssh and ~/.aws are blocked);
add Security tradeoffs section documenting the gh/GPG read-access model
- PLAN.md: add detailed roadmap covering GPG socket verification,
1Password credential pre-resolution, Railguard evaluation, network
allowlist, per-project sandbox overrides, and hook hardening
References & future workLogging the resources that informed the current sandbox design and what's next. Full detail in Sources reviewed
Near-term items added to PLAN.md
|
seccomp BPF blocks AF_UNIX on Linux (issue #44180), making GPG commit signing and SSH agent unusable inside the sandbox. Disabling bwrap for now; hooks remain the primary safety layer. denyRead/allowWrite config preserved for re-enablement when #44180 ships. - settings.json: sandbox.enabled false - PLAN.md: sandbox decision + per-device key decision in Done; item 1 reframed as re-enable trigger; item 2 updated to GH_TOKEN/deferred; Docker and NVIDIA container approaches evaluated and ruled out for personal dev workflows requiring GPG/SSH - README.md: activation simplified, sandbox section updated, security model section rewritten Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…le path Captures everything investigated about the Linux bwrap sandbox: - Core blocker (seccomp BPF, #44180) and what it breaks - Every workaround evaluated and why each fails - Current security model without the sandbox - Step-by-step re-enable checklist for when #44180 ships - Docker and NVIDIA approaches with findings - enableWeakerNestedSandbox note for future container use Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Final summary — what this PR delivers and the sandbox decisionWhat's in the branch
Sandbox: disabled, and why
Every workaround was evaluated and ruled out:
Upstream blocker: #44180 — Linux: add Re-enable triggerWhen #44180 ships, flip git commit --allow-empty -S -m "sandbox gpg test" # must sign
git push # must push via SSH
gh api user # must return GitHub userIf those pass without errors or prompts, the sandbox is viable. At that point also move Current security model (without sandbox)Hooks are the primary guardrail. Claude runs as your user — same surface as any terminal session. The gaps relative to sandbox-enabled: Bash-level shell redirects to system paths aren't blocked, and Full writeup with re-enable checklist, all evaluated workarounds, and upstream issue table: |
… system paths validate-write.sh only covers Write/Edit/MultiEdit tools; a Bash redirect bypasses it entirely. The new pattern closes that gap for the shell-redirect case without touching the filesystem hook. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
settings.json: - Add denyWrite [/etc /usr /boot /sys /proc] to sandbox filesystem config. No live effect while sandbox.enabled is false; staged for when #44180 ships. install.sh: - Prompt for GH_TOKEN at install time (read -s to suppress echo). - When provided, write ~/.claude/settings.json as a generated file with env.GH_TOKEN merged in via jq env-var injection (not --arg) so the token never appears in jq's argv / /proc/*/cmdline. - When not provided, keep the symlink behaviour unchanged. PLAN.md: - Move items 2 (GH_TOKEN) and 5 (denyWrite) to Done. - Renumber remaining near-term and longer-term items. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
GH_TOKEN is now managed via env or gh CLI auth rather than being merged into settings.json at install time. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Current status of affected filesAll hooks confirmed working in a live test session on macOS (2026-05-22):
Sandbox is disabled ( Potential improvements (from PLAN.md)Near-term
Longer-term
|
…nk loop Railguard evaluation (PLAN.md item 2): reviewed source at v0.4.0. Hook layer is strictly better than validate-bash.sh — adds evasion detection (Tier 1–3), memory guard, per-edit rollback, audit trail, self-protection. Railguard-shell on Linux breaks GPG/SSH same as #44180 (bwrap --tmpfs /tmp + --tmpfs ~/.gnupg wipes SSH agent sockets and GPG keyring). Recommendation: adopt hook layer, skip railguard-shell; integration steps documented. install.sh: ln -sf on an existing dir-symlink follows the link and creates a nested symlink inside the target directory. Re-running install.sh was creating agentic-ai/Claude/rules/rules → rules (self-loop). Fix: rm -f the old symlink before relinking. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Install railguard alongside existing hooks (validate-bash.sh, validate-write.sh, post-edit-shellcheck.sh, driftcheck.sh). CLAUDE_CODE_SHELL intentionally unset to avoid bwrap/AF_UNIX conflict (same root cause as #44180) — hook layer only. - railguard.yaml: custom blocks for privilege-escalation and git-add-bulk; ~/.gnupg and ~/.config/gh excluded from denied_paths (required for GPG signing and gh CLI); ~/.claude and /tmp in allowed_paths for memory writes - settings.json: railguard PreToolUse/PostToolUse/SessionStart hooks merged alongside existing hooks using absolute ~/.cargo/bin/railguard path - install.sh: symlinks railguard.yaml to ~/.railguard.yaml (global policy) - .gitignore: exclude .railguard/ (per-session traces and snapshots) - PLAN.md: mark item 2 complete with integration notes Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ite/denyRead Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rd duplicates Heredoc bodies (commit message text) were triggering the escalation and bulk-staging blocks because the hook matched against the full command string. Policy checks now use FIRST_LINE; destructive-pattern checks keep full-string matching. The matching custom blocks in railguard.yaml removed — validate-bash.sh owns these patterns with correct scoping. Railguard retains its built-in detection layer (encoding, memory guard, path fence, audit trail). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…behaviors Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ter patterns Extends the piped-execution block (curl/wget) to cover python, ruby, node, and perl alongside sh/bash. Adds two-grep AND checks for inline interpreter flags combined with dangerous exec calls; scoped to FIRST_LINE to avoid the same heredoc false-positive that affected the sudo/git-add checks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Runs the project test suite after source file edits. Auto-detects cargo/go/pytest/npm/make; .claude/test-cmd in the project root overrides. 60s timeout with elapsed timing always reported. Warns Claude on failure or timeout (exit 2, non-imperative message); silent exit 0 on pass or when no test suite is found. Skips non-source extensions (md, yaml, json, etc.). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…S rationale Move validate-bash hardening and post-test-runner hook to Done. Remove GH_TOKEN (GitHub-only PAT doesn't fit a provider-agnostic workflow that requires GPG signing and SSH agent across GitHub, Bitbucket, and Forgejo). Update #44180 blocker description to reflect the multi-VCS dependency. Fix item 3 header (decision already made). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Final state — reference for after mergeThis PR establishes the full What's running
railguard-shell (bwrap) is intentionally not activated — same AF_UNIX blocker as the built-in sandbox. Blocked on upstreamBoth remaining items block on the same root cause: #44180 — seccomp BPF unconditionally blocks AF_UNIX sockets on Linux, killing
Known railguard behaviors to expect
|
Summary
Adds
agentic-ai/Claude/as a version-controlled source of truth for~/.claude/config. Installs viabash agentic-ai/Claude/install.sh(idempotent, symlink-based).What's included
Core config
settings.json—bypassPermissions(no prompts), hooks wired up, sandbox config withdenyRead/denyWrite/allowWritestaged for when the upstream AF_UNIX blocker ships,advisorModel: opusCLAUDE.md—@-imports hierarchical rules fromrules/rules/common/general.md— coding style rules applied globallyrules/common/agents.md— when to auto-spawn Plan/Explore/review/security-review agentsrules/bash/style.md— bash scripting conventionsHooks
PreToolUse
validate-bash.shblocks:ddto device nodes,mkfs~/.ssh,~/.aws,~/.gnupg,~/.config/gh,/etc,/usr,/boot,/sys,/proc)curl/wget | sh/python/ruby/node/perlpipe executionpython -c+os.system/subprocess,node -e+child_process/execSync,perl -e+system(/exec()main/mastersudoescalationgit add -A / --all / .bulk stagingAll policy checks that can match heredoc commit message bodies are scoped to
$FIRST_LINEto prevent false positives.PreToolUse
validate-write.shblocks Write/Edit/MultiEdit to the same sensitive paths.PostToolUse
post-edit-shellcheck.shrunsshellcheckon any.shfile after it's written or edited.PostToolUse
post-test-runner.shruns the project's test suite after every Write/Edit on source files. Discovery order:.claude/test-cmdoverride →cargo test/go test ./.../pytest/npm test/make test. 60s timeout; warns on failure, silent on pass.Stop
driftcheck.shcompares the installed~/.claude/against the repo source at end of session and warns if they've drifted.Railguard v0.5.1
Hook layer integrated; railguard-shell (bwrap) skipped — same AF_UNIX blocker as the built-in sandbox. Adds: encoding/obfuscation detection (Tier 1), behavioral evasion detection (Tier 3), memory write classification, per-edit rollback, structured audit trail, self-protection rules.
railguard.yamlsymlinked to~/.railguard.yamlfor global coverage.Sandbox (disabled — upstream blocker)
setup-linux-sandbox.sh+SANDBOX.mddocument the bubblewrap sandbox config. Currently disabled (sandbox.enabled: false) because seccomp BPF unconditionally blocksAF_UNIXsockets (#44180), which kills GPG commit signing and SSH agent — both required for a provider-agnostic workflow across GitHub, Bitbucket, and Forgejo. The filesystem config is in place and ready to re-enable when #44180 ships.install.sh
settings.json,CLAUDE.md,rules/,railguard.yaml, and allhooks/*.shinto~/.claude/Activation
🤖 Generated with Claude Code