Why runok?
Even with allow rules configured, Claude Code asks for confirmation in cases like these:
# Claude adds a comment before the command -- no longer matches your allow rule
)
# Claude chains commands with && -- same problem
&& && )
runok parses commands with tree-sitter-bash, so comments, compound commands (&&, |, ;), and wrapper commands (sudo, bash -c, xargs) are all handled correctly. Each sub-command is evaluated independently against your rules.
Features
Flexible command parsing
tree-sitter-bashAST parsing -- comments, pipes,&&,;are understood, not treated as opaque stringssudo,bash -c,xargsare recursively unwrapped so rules apply to the inner command
Flexible rule configuration
- Wildcards, flag alternation (
-f|--force), optional groups, argument-order-independent matching - Conditional
whenclauses with CEL expressions for environment-aware decisions - OS-level sandboxing (macOS Seatbelt / Linux Landlock) for file and network restrictions
And more -- preset sharing, denial feedback, extension protocol
Quick start
Install
Pre-built binaries are also available on GitHub Releases. See Installation for details.
Configure
Create ~/.config/runok/runok.yml:
rules:
- allow: 'git status'
- allow: 'git diff *'
- allow: 'git log *'
- ask: 'git push *'
- deny: 'git push -f|--force *'
message: 'Force push is not allowed'
defaults:
action: ask
Integrate with Claude Code
Add runok as a PreToolUse hook in .claude/settings.json:
See Claude Code Integration for sandbox setup and advanced configuration.
Verify
Full Documentation
See runok.fohte.net
Feedback
Feature requests and bug reports are welcome on GitHub Issues.