v0.2.0
Released on 2026-03-15. Full changelog
Highlights
Section titled “Highlights”Breaking: * inside quotes is now treated as a glob pattern (#157)
Section titled “Breaking: * inside quotes is now treated as a glob pattern (#157)”Previously, "*" in a pattern was treated as a literal asterisk. Starting with v0.2.0, * inside quotes is treated as a glob wildcard, matching the same way as an unquoted *. To match a literal * character, use the \* escape sequence.
What should I do?
If your rules use "*" intending to match a literal asterisk, update them to use \*:
# Before (v0.1.x): matched a literal * characterrules: - allow: 'echo "*"'
# After (v0.2.0): use \* to match a literal * characterrules: - allow: 'echo \*'If your rules use "*" intending it as a wildcard (matching any arguments), no changes are needed — it now works as you’d expect.
See Wildcards for details.
runok test subcommand (#204)
Section titled “runok test subcommand (#204)”A new runok test subcommand lets you write test cases for your rules and verify they behave as intended. Test cases can be defined in two ways.
Inline tests attach directly to a rule:
rules: - allow: 'git status' tests: - allow: 'git status' - allow: 'git status --short'
- deny: 'git push -f|--force *' tests: - deny: 'git push --force origin main'Top-level tests validate across multiple rules:
tests: cases: - allow: 'git push origin main' - deny: 'git push --force origin main'$ runok test -c runok.ymlPASS: git status => allowPASS: git status --short => allowPASS: git push --force origin main => deny3 passed, 0 failed, 3 totalGlobal config is excluded during test execution to guarantee reproducible results.
See runok test for details.
Typed variable definitions with <var:name> placeholder (#201, #208)
Section titled “Typed variable definitions with <var:name> placeholder (#201, #208)”Rules can now define typed variables using definitions.vars and reference them with <var:name> in patterns. Variables support per-value types for more precise matching, and can also be used in command position:
definitions: vars: branch: values: - main - develop - 'feature/*'
rules: - allow: 'git checkout <var:branch>'See Placeholders and Configuration Schema for details.
Audit subcommand (#103, #200, #207)
Section titled “Audit subcommand (#103, #200, #207)”The new runok audit subcommand provides logging and inspection of command evaluation results. It displays results in a table format with colors, making it easy to review how rules evaluate commands across your configuration.
Use --dir to filter audit results by directory.
See runok audit for details.
New Features
Section titled “New Features”runok update-presets command (#197)
Section titled “runok update-presets command (#197)”A new command to refresh and upgrade cached remote presets. It detects version tag precision (@v1, @v1.0, @v1.0.0) and automatically finds the latest compatible version. For branch references, it shows SHA changes; for version tag upgrades, it displays a config file diff.
$ runok update-presetsSee runok update-presets for details.
redirects and pipe variables in when clauses (#203)
Section titled “redirects and pipe variables in when clauses (#203)”Two new context variables are available in when expressions for conditional rule evaluation based on shell I/O:
redirects: list of redirect operators present in the command (e.g.,>,>>,2>&1)pipe: the command’s position in a pipeline (stdin,stdout, or empty)
rules: # Block piping curl output to sh - deny: 'sh' when: 'pipe.stdin'See when clause for details.
Fused short flag pattern matching (#205)
Section titled “Fused short flag pattern matching (#205)”Fused short flags like -n3 (where the flag and value are joined without a space) are now matched by FlagWithValue patterns. This allows patterns like [-n *] to match both git tag -n 3 and git tag -n3:
rules: # Matches: git tag -n3, git tag -n 3, git tag -n100 - allow: 'git tag [-n *] *'Only flags declared as value-bearing in the pattern are split, so -rf (combined boolean flags) is not incorrectly separated.
See Matching Behavior for details.
Bug Fixes
Section titled “Bug Fixes”Unknown flags now rejected in exec/check (#202)
Section titled “Unknown flags now rejected in exec/check (#202)”Unknown flags before -- in exec/check subcommands were silently absorbed and the command exited with code 0. They are now properly rejected with an error message:
# Before: silently ignored, exit 0runok check --unknown-flag -- git status
# After: error message, non-zero exitrunok check --unknown-flag -- git status # → error: unknown flag '--unknown-flag'exec --dry-run removed (#216)
Section titled “exec --dry-run removed (#216)”The runok exec --dry-run option has been removed. Use runok check instead, which provides the same functionality:
# Beforerunok exec --dry-run -- git status
# Afterrunok check -- git status<cmd> placeholder no longer captures flag-starting tokens (#206)
Section titled “<cmd> placeholder no longer captures flag-starting tokens (#206)”The <cmd> placeholder in wrapper patterns was incorrectly capturing token sequences starting with -, causing explicitly allowed commands to be downgraded to ask:
definitions: wrappers: - 'command <cmd>'rules: - allow: 'command -v|-V *'# Before: <cmd> captured [-v, a], inner "-v a" matched no rules → askcommand -v git # → ask (wrong)
# After: <cmd> skips flag-starting sequences, direct rule applies → allowcommand -v git # → allow (correct)