Skip to content

Matching Behavior

This page explains how runok parses commands and matches them against patterns.

runok does not rewrite or preprocess patterns. The way you write a rule is exactly how it is parsed and matched:

  • No implicit splitting or joining. Tokens are separated by spaces, and =-joined values stay as a single token.
  • Rules are self-contained. You can understand a rule’s behavior by reading it alone — definitions do not change how a pattern is parsed.
# "-Denv=prod" is a single token — matched as-is
- deny: 'java -Denv=prod *'
# Matches: java -Denv=prod -jar app.jar
# Does NOT match: java -Denv staging -jar app.jar
# "-X" and "POST" are separate tokens — matched as flag and value
- deny: 'curl -X POST *'
# Matches: curl -X POST https://example.com

When a pattern contains a flag followed by a value, runok infers that the flag takes a value argument. This inference is used when parsing the actual command to correctly associate values with their flags.

# Pattern: curl -X|--request POST *
# Inferred flag schema: -X and --request take a value
- deny: 'curl -X|--request POST *'

With this inferred schema, the command curl -X POST https://example.com is parsed as:

  • -X — flag
  • POST — value of -X
  • https://example.com — positional argument

Without this inference, POST would be treated as a positional argument rather than a flag value.

Flags inside optional groups are also included in the inferred schema:

# Both -o/--output and -X/--request are inferred as value flags
- allow: 'curl [-o|--output *] -X|--request GET *'

Flags (tokens starting with -) in patterns are matched regardless of their position in the command:

- allow: 'git push -f|--force *'
CommandResult
git push --force origin mainMatches
git push origin --force mainMatches
git push origin main --forceMatches

This applies to both standalone flags (alternation) and flag-value pairs. The matcher scans the entire command token list to find a matching flag, removes it, and continues matching the remaining tokens.

Tokens that do not start with - are matched in order:

- allow: 'git push origin main'
CommandResult
git push origin mainMatches
git push main originDoes not match

Combined short flags like -am are not split into individual flags — they are matched as a single token, exactly as written:

- deny: 'git commit -m *'
CommandResultReason
git commit -m "fix bug"Matches-m matches directly
git commit -am "fix bug"Does not match-am is a different token than -m

If you want to match -am, write it explicitly:

- deny: 'git commit -am *'

To prevent pathological patterns (such as many consecutive wildcards) from causing excessive computation, matching is limited to 10,000 steps. Patterns that exceed this limit fail to match.