Skip to content

Configuration Guide ​

Rnix uses a layered configuration system with YAML files, agent definitions, and skill definitions. Run rnix init to bootstrap the configuration environment.


Configuration Model ​

Rnix configuration has three independent dimensions:

1. Config Layering (XDG-style) ​

YAML config files (providers.yaml, config.yaml, web-search.yaml) follow a global + project two-tier model:

TierLocationPurpose
Global~/.config/rnix/ (or $XDG_CONFIG_HOME/rnix/)User-wide defaults
Project<project>/.rnix/Project-specific overrides

YAML files deep-merge: project values override global values.

2. Skill Storage (agentskills.io 2×2 model) ​

Skills follow the agentskills.io specification's dual-scope × dual-namespace model. Rnix implements two namespaces per scope:

Native Namespace (Rnix)Agents Namespace (agentskills.io)
Project scope<project>/.rnix/skills/<project>/.agents/skills/
User scope~/.config/rnix/skills/~/.agents/skills/
  • Native namespace (.rnix/skills/, ~/.config/rnix/skills/): Rnix-specific skills, highest priority within each scope
  • Agents namespace (.agents/skills/, ~/.agents/skills/): Follows the agentskills.io cross-tool standard — skills placed here are visible to Cursor, OpenCode, Windsurf, and other compatible tools

Priority: project/native > project/agents > user/native > user/agents. See Skill Packages for the full resolution model.

3. Data Directory (sessions & history) ​

Runtime artifacts — reasoning steps, checkpoints, events.jsonl, and resumable history — are not stored next to your config. They live in a single global data directory, resolved in this order:

PrioritySourceResulting path
1RNIX_DATA_DIRthe value, as-is
2XDG_DATA_HOME$XDG_DATA_HOME/rnix
3(default)~/.local/share/rnix

Under the data directory, every project gets its own subtree in a project registry, keyed by a deterministic, human-readable ID:

<data-dir>/
└── projects/
    ├── my-api-3f9a1c2b/         ← <sanitized-basename>-<hash8>
    │   └── steps/
    │       └── <uuid>/          ← events.jsonl, proc-info.json, checkpoints
    └── another-repo-7c4e0d11/
        └── steps/

The ID is <sanitized-basename>-<hash8>, where hash8 is the first 4 bytes of sha256(absolute-project-path). The hash keeps two projects that share a basename (e.g. two different api/ folders) from colliding, while the basename keeps the directory readable. Centralizing data this way lets rnix ps -a, rnix record, rnix replay, and rnix resume enumerate history across every project from one root, and lets garbage collection apply retention_days / max_entries globally.

Older releases stored session data in a cwd-relative <project>/.rnix/data/steps/. That location is superseded by the global data directory — .rnix/ now holds only config, state, and skills.

Directory Structure ​

~/.config/rnix/                  ← Global config (created by rnix init)
├── providers.yaml
├── config.yaml
├── web-search.yaml
├── agents/                      ← Global agent definitions
│   └── code-analyst/
│       ├── agent.yaml
│       └── instructions.md
└── skills/                      ← User skills (native namespace)
    └── code-analysis/
        └── SKILL.md

~/.agents/skills/                ← User skills (agents namespace, agentskills.io standard)
└── web-research/                ←   Shared with Cursor, OpenCode, etc.
    └── SKILL.md

<project>/.rnix/                  ← Project config (created by rnix init)
├── providers.yaml
├── config.yaml
├── init.yaml
├── compose.yaml
├── web-search.yaml
├── agents/                      ← Project agent definitions
├── skills/                      ← Project skills (native namespace)
└── state/                       ← Runtime state (trust marker, etc.)
                                 ← (session data lives in the global data dir — see "3. Data Directory")

<project>/.agents/skills/        ← Project skills (agents namespace, agentskills.io standard)
└── shared-util/                 ←   Shared across tools in the project
    └── SKILL.md

Note: ~/.agents/skills/ and .agents/skills/ are not created by rnix init. They are created on first use (rnix skill install --shared). This follows agentskills.io convention where the .agents/ directory belongs to the ecosystem, not any single tool.

Merge Rules ​

  • YAML files (providers.yaml, config.yaml, web-search.yaml): Deep merge — project overrides global
  • Agent directories (agents/): Shadow — project agent with same name completely replaces global agent
  • Skill directories (skills/): Shadow with 2×2 priority — project/native > project/agents > user/native > user/agents. Winning copy completely replaces shadowed copies.

Exception — init.yaml: The daemon is a single per-user process, so its bootstrap config is read only from the global ~/.config/rnix/init.yaml. It does not participate in the project-level merge and a project .rnix/init.yaml is never read.

Initialization ​

bash
# Create both global (~/.config/rnix/) and project (.rnix/) directories
$ rnix init
[init] created ~/.config/rnix/
[init] created .rnix/

# With MCP example configurations
$ rnix init --with-mcp-examples
[init] created ~/.config/rnix/
[init] created .rnix/
[init] added agents/playwright-demo/ with MCP Playwright config
[init] added agents/github-assistant/ with MCP GitHub config

rnix init is idempotent — it skips existing files and directories. --with-mcp-examples runs preflight checks to verify required binaries (e.g., npx) are available before creating example configs.


config.yaml — Global Configuration ​

Located at ~/.config/rnix/config.yaml (global) and optionally .rnix/config.yaml (project override).

Feature Profiles ​

Feature profiles control which emergent subsystems are active at runtime. They enable ablation experiments — selectively disabling capabilities to measure each layer's contribution to overall intelligence emergence.

There are four named presets and a custom mode for fine-grained control:

ProfileDescription
baselineFoundation only — bare LLM + VFS devices. No planning, spawning, or adaptive mechanisms.
coreFoundation + core mechanisms — planning, subprocess spawning, context compaction.
adaptiveCore + feedback loops — runtime learning, skill acquisition, path re-planning.
fullAll capabilities enabled, including immune system. Default.
customPer-flag control — any flag not explicitly listed defaults to true.

Configuration:

yaml
# .rnix/config.yaml or ~/.config/rnix/config.yaml
features:
  profile: full   # baseline | core | adaptive | full | custom
  custom:         # only used when profile is "custom"
    planning: true
    replan: false
    specialize: true
    discover_skill: true
    spawn: true
    diff_memory: false
    stem_matcher: false
    immune: true
    compaction: true

Preset Matrix:

Featurebaselinecoreadaptivefull (default)
planningfalsetruetruetrue
replanfalsefalsetruetrue
specializefalsefalsetruetrue
discover_skillfalsefalsetruetrue
spawnfalsetruetruetrue
diff_memoryfalsefalsetruetrue
stem_matcherfalsefalsetruetrue
immunefalsefalsefalsetrue
compactionfalsetruetruetrue

Environment Variable Override:

Set RNIX_FEATURE_PROFILE to override the config file setting. Valid values: baseline, core, adaptive, full, custom. Invalid values produce a warning and fall back to full.

bash
RNIX_FEATURE_PROFILE=baseline rnix "analyze this code"

Read once at daemon startup

RNIX_FEATURE_PROFILE is read once, when the daemon process starts, via its own environment. Exporting it in your shell has no effect on an already-running daemon — the CLI detects the mismatch and prints a warning to stderr. To change the profile of a live daemon, run rnix daemon stop and let the next command restart it (a CLI-autostarted daemon inherits the variable and picks it up).

Custom Mode:

When profile: custom, only the flags explicitly listed under custom: are applied. Unlisted flags default to true — custom mode is for surgical ablation, not wholesale disabling.

Inspecting the Active Profile:

Use rnix config show to display the active feature profile and flags. See CLI Reference for details.

See Feature Profiles & Ablation for how profiles map to the emergence stack.

Garbage Collection ​

yaml
gc:
  retention_days: 30      # Delete dead_at entries older than N days; 0 = disabled
  max_entries: 500        # Keep at most N history entries; 0 = disabled
  interval_seconds: 3600  # Background scan period (min 60, default 1h)
  • retention_days and max_entries are combined — hitting either triggers cleanup
  • Set both to 0 to disable the GC daemon entirely
  • Running and Suspended processes are permanently exempt

See Process Resume for GC CLI usage.

Raw Capture ​

Rnix records the raw request and response of every LLM call — the HTTP body for API drivers, and the full command invocation plus output for CLI drivers — so you can verify exactly what was sent (prompts, reasoning_effort, thinking_budget, temperature, …). Captures are enabled by default.

yaml
raw_capture:
  enabled: true            # default true; set false to disable raw logging globally
  max_output_bytes: 4194304  # per-record truncation limit (default 4 MB)
FieldDefaultDescription
enabledtrueMaster switch; false stops all processes from writing raw.jsonl
max_output_bytes4194304 (4 MB)Any single request/response field larger than this is truncated in place (per-record, not per-field); the record is marked truncated: true

Behavior:

  • Each successful reasonStep appends one NDJSON line to <data-dir>/.../steps/<uuid>/raw.jsonl, alongside steps.jsonl / events.jsonl. The file is created lazily — a driver that never produces a capture leaves no empty file.
  • Failed calls are captured too, tagged with outcome: "error" and the error text, so the request that failed is still recoverable.
  • Credentials are automatically redacted before writing — authorization headers, API keys, and matching argv flags become non-reversible redacted(len=…,prefix=…,sha256=…) fingerprints. Reasoning-effort and model flags keep their real values.
  • raw.jsonl lives in the process's step directory and is cleaned up by the same GC retention_days / max_entries policy; Running and Suspended processes are exempt.
  • Raw capture is an orthogonal kernel-level setting — independent of the features profile, so a baseline profile does not turn it off.

Captures are queryable after the fact via rnix strace <pid> --raw, the Dashboard inspector's Raw I/O view, and the get_raw_capture IPC method. See Debugging › Raw LLM I/O.


providers.yaml — LLM Providers ​

This file defines available LLM providers. Located at ~/.config/rnix/providers.yaml (global) and optionally .rnix/providers.yaml (project override).

yaml
version: "1"
default_provider: deepseek

providers:
  - name: claude
    driver: claude-cli
    default_model: haiku

  - name: cursor
    driver: cursor-cli
    command: agent              # CLI binary name (default: "agent")

  - name: groq
    driver: openai-compat
    base_url: https://api.groq.com/openai/v1
    default_model: llama-3.3-70b-versatile
    api_key_env: GROQ_API_KEY

  - name: ollama
    driver: openai-compat
    base_url: http://localhost:11434/v1
    default_model: llama3

  - name: deepseek
    driver: openai-compat
    base_url: https://api.deepseek.com/v1
    default_model: deepseek-chat
    api_key_env: DEEPSEEK_API_KEY

Fields ​

FieldTypeDescription
versionstringConfig format version ("1")
default_providerstringDefault provider when none specified (default: deepseek)
providers[].namestringProvider name, maps to /dev/llm/<name>
providers[].driverstringDriver type (one of 8): claude-cli, cursor-cli, qwen-cli, codex-cli, openai-compat, openai, gemini, anthropic
providers[].commandstringCLI binary name override for CLI drivers
providers[].default_modelstringDefault model name
providers[].base_urlstringAPI base URL (for openai-compat driver)
providers[].api_key_envstringEnvironment variable name for API key
providers[].timeout_secintPer-request timeout in seconds; 0 = driver default (5 min for CLI drivers)
providers[].grace_secintCLI grace period between SIGTERM and SIGKILL; 0 = driver default (20s)
providers[].modelsmapPer-model metadata, keyed by model name: <model>: {context_window: N}. Used to derive context_budget (context_window × 0.9)

For the full set of advanced provider options (mode, max_tokens, cost_per_token, thinking_budget, reasoning_effort, extra_args, permission_mode), see LLM Providers › Advanced Provider Options.

Driver Types ​

DriverHow It WorksExamples
claude-cliInvokes Claude Code CLI (claude -p)Anthropic Claude
cursor-cliInvokes Cursor CLI (agent --print)Cursor
qwen-cliInvokes Qwen Code CLIQwen Code
codex-cliInvokes OpenAI Codex CLIOpenAI Codex
openai-compatCalls OpenAI-compatible HTTP APIOllama, Groq, DeepSeek, any OpenAI-compatible endpoint
openaiOfficial OpenAI SDKOpenAI GPT-4, GPT-4o
geminiNative Gemini APIGoogle Gemini
anthropicOfficial Anthropic SDKClaude (via API, not CLI)

Provider Resolution Priority ​

  1. --provider CLI flag (highest priority)
  2. agent.yaml → models.provider field
  3. providers.yaml → default_provider
  4. Built-in default: deepseek

Model Resolution Priority ​

  1. --model CLI flag
  2. agent.yaml → models.preferred field
  3. Provider's default_model
  4. Driver's built-in default

Reasoning Effort ​

Set reasoning_effort on a provider (or per spawn) to control discrete reasoning strength. The value is passed through to the provider verbatim. It resolves through a four-tier fallback (per-spawn → agent → provider → native default) and supersedes the legacy thinking_budget where both are set; the budget path is retained as a fallback for providers that still require it. See LLM Providers › Reasoning Effort for details and the case-sensitivity note.

API Key Management ​

API keys are referenced via environment variables — never stored directly in config files. Resolved from project .env files first, then daemon process environment.


web-search.yaml — Web Search Backends ​

Configure search backends for the /dev/web device. Located at ~/.config/rnix/web-search.yaml (global) or .rnix/web-search.yaml (project, takes priority).

yaml
version: "1"
default_backend: tavily
backends:
  - name: tavily
    driver: tavily
    api_key_env: TAVILY_API_KEY
    max_results: 5
    search_depth: basic

  - name: exa
    driver: exa
    api_key_env: EXA_API_KEY
    num_results: 5

  - name: local-searxng
    driver: searxng
    base_url: http://localhost:8888

The project file fully overrides the global file (no merging). See Web Search for backend details and quick-start options.


Environment Files (.env) ​

Rnix supports project-level .env files for managing API keys and other environment variables without polluting the daemon's process environment.

Loading Order ​

  1. .env — Base environment
  2. .env.local — Local overrides (gitignore this)
  3. .env.{RNIX_ENV} — Environment-specific (e.g., .env.production)
  4. .env.{RNIX_ENV}.local — Environment-specific local overrides

RNIX_ENV ​

The RNIX_ENV environment variable selects which environment-specific files to load. Default: development.

bash
RNIX_ENV=production rnix "deploy the service"

Project Isolation ​

Each spawn request generates an independent environment snapshot from .env files. Variables are not written to os.Setenv — different projects' environments are fully isolated, even when sharing the same daemon.


init.yaml — Bootstrap Services & Supervisors ​

Defines services and supervised agent trees that start when the daemon launches. The daemon is a single per-user process, so bootstrap is a global concern: this file is read only from ~/.config/rnix/init.yaml. A project-level .rnix/init.yaml is never read.

rnix init writes a scaffold here that defaults to an empty service list. Two top-level sections are supported: services and supervisors.

yaml
services:
  - name: skills
    type: skill_registry
    required: false
    config:
      scan_path: lib/skills

  - name: mcp
    type: mcp_manager
    required: false

supervisors:
  - name: monitors
    strategy: one_for_one
    max_restarts: 3
    max_window: 60s
    required: false
    children:
      - name: health-monitor
        intent: "Monitor system health and report anomalies"
        agent: monitor
        model: deepseek-v4-flash
        restart: permanent

Services ​

services is a list; each item is a ServiceConfig.

FieldTypeDefaultDescription
namestringRequiredDisplay name for the service
typestringRequiredRegistered service type — one of skill_registry, mcp_manager, log_aggregator
requiredboolfalsetrue = bootstrap aborts if this service fails; false = warn and continue
configmap{}Type-specific key/value options (e.g. skill_registry accepts scan_path)

mcp_manager is loaded implicitly even when omitted, so MCP servers declared in mcp.yaml are always resolvable by rnix mcp test/rnix mcp list. A user-declared mcp_manager service takes precedence over the implicit one.

Supervisors ​

supervisors is a list; each item is a SupervisorConfig describing a long-running supervised agent tree.

FieldTypeDefaultDescription
namestringRequiredDisplay name for the supervisor tree
strategystring""Restart strategy for the tree
max_restartsint0Maximum restarts within max_window
max_windowduration0Sliding window for the restart counter (e.g. 60s)
requiredboolfalsetrue = bootstrap aborts (and rolls back) on failure; false = warn and continue
children[]object[]Child processes supervised by this tree

Each entry under children is a ChildConfig:

FieldTypeDescription
namestringChild display name
intentstringIntent string for the child agent
agentstringNamed agent definition (optional; empty = generic)
modelstringModel override
providerstringProvider override
context_budgetintPer-step context window guard
restartstringChild restart policy

compose.yaml — Multi-Agent Workflows ​

Compose files define DAG-based multi-agent workflows. Located at .rnix/compose.yaml.

yaml
version: "1.0"
intent: "Code review workflow"
model: "deepseek-v4-flash"

agents:
  analyzer:
    intent: "Analyze kernel/kernel.go code quality"
    agent: "code-analyst"

  doc-gen:
    intent: "Generate improvement documentation"
    depends_on:
      analyzer: completed

  checker:
    intent: "Verify analysis and documentation quality"
    depends_on:
      doc-gen: completed

Top-Level Fields ​

FieldTypeDescription
versionstringCompose spec version (currently "1.0")
intentstringOverall workflow description
modelstringGlobal default model (agents can override)
providerstringGlobal default provider (agents can override)
reasoning_effortstringSpec-level reasoning effort default (passthrough; agents can override)
token_budgetintOverall token budget for the workflow
agentsmapAgent definitions

Agent Fields ​

FieldTypeDescription
intentstringTask description for this agent
agentstringNamed agent definition (optional)
modelstringModel override for this agent
providerstringProvider override for this agent
reasoning_effortstringReasoning effort override for this agent (passthrough)
skills[]stringSkill names to load for this agent
prioritystringScheduling priority: high, normal, low
max_tokensintPer-process token budget
timeout_msintExecution timeout in milliseconds
depends_onmapDependencies: <upstream>: completed
candidates[]stringCandidate agents for auto-selection

Running Compose Workflows ​

bash
rnix compose up          # Run the workflow
rnix compose up --json   # Run with JSON output
rnix compose down        # Stop all compose processes
rnix compose resume --node <name>  # Resume a failed DAG node

Agent Manifest — agent.yaml ​

Each agent is defined by an agent.yaml file and an instructions.md file in agents/<name>/ (global: ~/.config/rnix/agents/, project: .rnix/agents/).

yaml
name: code-analyst
description: "Code quality analysis agent"
models:
  provider: deepseek
  preferred: deepseek-v4-flash
  fallback: deepseek-v4-pro
max_steps: 20
max_tokens: 50000
skills:
  - code-analysis
  - security-scan
mcp:
  servers:
    github:
      command: "npx"
      args: ["-y", "@anthropic/mcp-github"]
      env:
        GITHUB_TOKEN: "${GITHUB_TOKEN}"
      timeout: 30s
      max_output_tokens: 4096

Fields ​

FieldTypeRequiredDescription
namestringYesUnique agent identifier
descriptionstringNoHuman-readable description
modelsobjectNoLLM model preferences
models.providerstringNoLLM provider name
models.preferredstringNoPreferred model name
models.fallbackstringNoFallback model name (same provider)
models.fallback_providerstringNoCross-provider fallback; empty = same provider
models.reasoning_effortstringNoAgent-level reasoning effort default (passthrough, no validation/case-mapping); empty = defer to provider snapshot
context_budgetintNoPer-step context window guard: max input tokens allowed in a single LLM call. When exceeded, the process self-suspends with exit code 3 (context_full) and can be resumed. 0 = auto-derive from context_window × 0.9; explicitly set values are clamped to min(budget, context_window).
ctx_sizeintNoPer-process message-history slot count (overrides the default 256)
max_stepsintNoMaximum reasoning steps. 0 = use DefaultMaxSteps (currently 0, i.e. no step-count limit).
max_tokensintNoMaximum total tokens (0 = unlimited)
max_costfloat64NoPer-process cost budget in USD (0 = unlimited)
step_timeoutstringNoPer-step timeout as a duration string, e.g. "10m" (default "5m"; "0" = disabled)
skills[]stringNoReferenced skill names
deferred_skills[]stringNoSkills loaded metadata-only; body loaded on discover_skill
tools[]stringNoAgent-level tool declaration, unioned with skill allowed-tools
planningboolNoEnable the planning capability (default true when unset)
project_docboolNoInject the project-root AGENTS.md into the system prompt (default true; set false to disable)
languagestringNoPreferred response language (e.g. Chinese, English); empty = no preference
mcpobjectNoMCP server configurations

MCP Server Config Fields ​

FieldTypeRequiredDescription
commandstringYesExecutable to launch the MCP server
args[]stringNoCommand-line arguments
envmap[string]stringNoEnvironment variables (${VAR} expansion)
timeoutdurationNoPer-server timeout (default: 30s)
max_output_tokensintNoMax tokens per tool output

Skill Definition — SKILL.md ​

Skills are defined as SKILL.md files following the agentskills.io standard. Storage uses a four-path model (project/user × native/agents namespace):

PathScopeNamespacePriority
<project>/.rnix/skills/projectnative1 (highest)
<project>/.agents/skills/projectagents2
~/.config/rnix/skills/usernative3
~/.agents/skills/useragents4 (lowest)

See Skill Packages for the full multi-scope management model.

markdown
---
name: code-analysis
description: >
  Analyze code quality, identify bugs, performance issues
  and security vulnerabilities.
allowed-tools: /dev/fs /dev/shell /dev/web
metadata:
  author: rnix
  version: "1.0"
  tags: "code, quality"
---

# Code Analysis

## When to Use
...

## Workflow
1. Read source files via /dev/fs
2. Run analysis via /dev/shell
3. Generate report

Frontmatter Fields ​

FieldTypeRequiredDescription
namestringYesUnique skill identifier
descriptionstringNoShort description (~100 tokens)
allowed-toolsstringKey fieldSpace-separated VFS device paths
metadatamapNoArbitrary key-value pairs

allowed-tools and Security ​

The allowed-tools field is the core of Rnix's permission model. A skill can only access VFS devices listed here:

DeviceCapability
/dev/fsHost filesystem read/write
/dev/shellShell command execution
/dev/llm/<provider>LLM inference
/dev/webWeb search and fetch
/mnt/mcp/*MCP server tools

When multiple skills are loaded by an agent, their allowed-tools are unioned — the agent can access any device permitted by any of its skills. Empty allowed-tools means no restrictions (can access all devices).


Environment Variables ​

VariableDescription
RNIX_ENVSelect environment for .env file loading (default: development)
RNIX_ASCIISet to 1 to force ASCII mode (disable Unicode glyphs)
RNIX_FEATURE_PROFILEFeature profile override: baseline, core, adaptive, full, custom
XDG_CONFIG_HOMEOverride global config directory (default: ~/.config)
XDG_RUNTIME_DIRUsed to determine socket path
TAVILY_API_KEYTavily search API key (auto-detected for /dev/web)
EXA_API_KEYExa search API key (auto-detected for /dev/web)
RNIX_SEARCH_URLSearXNG instance URL (auto-detected for /dev/web)

Socket Path ​

The daemon socket location follows this priority:

  1. $XDG_RUNTIME_DIR/rnix/rnix.sock (e.g., /run/user/1000/rnix/rnix.sock)
  2. /tmp/rnix-{uid}/rnix.sock (fallback)

Directory permissions: 0700 (current user only).


Released under the MIT License.