Skip to content

v0.1.4

Released on 2026-03-11. Full changelog

Literal tokens (positional arguments) in patterns are now matched regardless of their position in the command. Previously, patterns required arguments to appear in the exact order specified. Now commands like gh -X GET api /repos match patterns where flags and subcommands are in a different order:

runok.yml
rules:
# Matches both:
# gh api -X GET /repos
# gh -X GET api /repos
- allow: 'gh api [-X GET] *'

See Matching Behavior for details.

runok init now detects other PreToolUse hooks that match Bash commands and warns about potential conflicts. A Claude Code issue caused multiple Bash-matching hooks to interfere with each other, which could silently disable sandbox enforcement. The warning helps users identify and resolve this before it becomes a security issue.

Allowed commands inside command substitutions ($()) were incorrectly propagating their allow result to the parent compound evaluation. This could cause a deny rule to be bypassed:

Terminal window
# Before: the inner `echo ok` was allowed, and its result
# propagated to make the whole command allowed
rm -rf / && echo $(echo ok) # → allow (wrong)
# After: each sub-command is evaluated independently,
# and the strictest result wins
rm -rf / && echo $(echo ok) # → deny (correct)

Two related fixes for =-joined flag tokens:

FlagWithValue matching — Patterns like [--sort *] now match --sort=-committerdate:

runok.yml
rules:
# Before: did not match --sort=-committerdate
# After: matches correctly
- allow: 'git tag [--sort *] *'

Flag negation matching — Negation patterns like !--pre now correctly block --pre=pdftotext:

runok.yml
rules:
# Before: --pre=pdftotext bypassed the negation
# After: correctly blocked
- allow: 'rg !--pre *'

Flag negation patterns (e.g., sort !-o) now correctly pass when the command has no arguments at all. Previously, sort with no arguments would fail to match sort !-o, even though the absence of -o should satisfy the negation.