File Discovery and Merging
runok loads configuration from up to four layers, merging them in a defined order. This allows you to set organization-wide defaults globally while overriding specific settings per project. For sharing configuration across repositories, see Extends (Presets).
Configuration File Locations
Section titled “Configuration File Locations”runok searches for configuration files in two scopes:
| Scope | Path | Purpose |
|---|---|---|
| Global | $XDG_CONFIG_HOME/runok/runok.yml | User-wide defaults |
| Project | ./runok.yml (working directory) | Project-specific rules |
When XDG_CONFIG_HOME is not set, the global config directory defaults to ~/.config/runok/. See Environment Variables for details.
In each scope, an optional local override file is also loaded:
| Scope | Override Path | Purpose |
|---|---|---|
| Global | $XDG_CONFIG_HOME/runok/runok.local.yml | Personal tweaks |
| Project | ./runok.local.yml (working directory) | Personal project overrides |
File Extension Priority
Section titled “File Extension Priority”When both .yml and .yaml extensions exist, .yml takes priority:
runok.yml(preferred)runok.yaml(fallback)
This applies to both the main configuration file and the local override file in each scope.
Merge Order
Section titled “Merge Order”Configuration layers are merged bottom-to-top, with later layers taking higher priority:
| Priority | Layer | Path |
|---|---|---|
| 1 (low) | Global config | $XDG_CONFIG_HOME/runok/runok.yml |
| 2 | Global local override | $XDG_CONFIG_HOME/runok/runok.local.yml |
| 3 | Project config | ./runok.yml |
| 4 (high) | Project local override | ./runok.local.yml |
After merging all four layers, the resulting configuration is validated.
Merge Semantics
Section titled “Merge Semantics”Different fields use different merge strategies:
| Field | Strategy | Behavior |
|---|---|---|
extends | Append | Lists are concatenated. |
rules | Append | Rules from all layers are concatenated in order. |
defaults.action | Override | Higher-priority layer wins. |
defaults.sandbox | Override | Higher-priority layer wins. |
definitions.paths | Per-key append | Values for each key are concatenated (deduplicated). |
definitions.sandbox | Per-key override | Higher-priority layer replaces the entire preset. |
definitions.wrappers | Append | Lists are concatenated. |
definitions.commands | Append | Lists are concatenated. |
Example
Section titled “Example”Given a global config:
rules: - allow: 'git *'
definitions: paths: secrets: - ~/.sshAnd a project config:
rules: - allow: 'cargo build *' - deny: 'rm -rf /'
definitions: paths: secrets: - ~/.aws/credentialsThe merged result is:
rules: # global rules come first, then project rules - allow: 'git *' - allow: 'cargo build *' - deny: 'rm -rf /'
definitions: paths: secrets: # values are merged per-key - ~/.ssh - ~/.aws/credentialsValidation
Section titled “Validation”After merging, runok validates the final configuration:
- Each rule must have exactly one of
deny,allow, orask. denyrules must not have asandboxattribute.sandboxvalues must reference names defined indefinitions.sandbox.<path:name>references infs.denymust resolve to entries indefinitions.paths.<path:name>references are not allowed insidedefinitions.pathsvalues.
All validation errors are collected and reported together so you can fix every issue in a single pass.
Related
Section titled “Related”- Configuration Schema — Full reference for
runok.ymlfields. - Extends (Presets) — Inherit configuration from other files or repositories.