Skip to content

Configuration

NurCLI is configured via a TOML file and optional rule/hook files, plus environment variables.

Config file

The config file lives at ~/.nur/config.toml and is created on first run.

# Active provider id from the catalog (set by TUI /login)
provider = "meta"
model = "muse-spark-1.2"
base_url = "https://api.meta.ai/v1"
reasoning_effort = "high"
# 0 = unlimited agent rounds per prompt (default). Set a number to cap.
max_turns = 0
stream = true
context_window = 1000000

# Tool results larger than this spill to ~/.nur/tool-results/ (0 = unlimited)
tool_result_max_chars = 12000

# Optional hard stops (omit or leave unset for unlimited)
# max_session_cost_usd = 5.0
# max_session_tokens = 500000

# Per-request completion ceiling and reservation used before every dispatch.
# 0 restores the provider default and removes this safety reservation.
request_output_reserve_tokens = 8192

# Compaction (auto under context pressure, or /compact)
compact_keep_user_turns = 4
compact_tool_body_max_chars = 800

# Optional OMP-compatible remote summarizer (POST {systemPrompt,prompt} -> {summary}).
# Setting remote_endpoint opts in. OpenAI /chat/completions endpoints are also supported.
# On failure, nur falls back to local model summarization.
# [compaction]
# remote_enabled = true
# remote_endpoint = "https://example.com/compact"

# OMP-style prewalk: strong model plans + todos, then switch to a cheap model at
# the first write/edit. Off by default. Toggle with /prewalk in the TUI.
# [prewalk]
# enabled = true
# into = "openai-codex/gpt-5.6-luna"

# Optional HelixDB graph-vector memory resident. `auto` activates when a URL is
# configured here or through HELIX_URL/NUR_HELIX_URL, so an untouched default
# has no network/startup cost.
# Local native memory remains authoritative and failed mirrors retry from a
# durable outbox.
# [helix_memory]
# mode = "on"                       # auto | on | off
# url = "http://127.0.0.1:6969"
# api_key_env = "HELIX_API_KEY"     # env var name, never the key itself
# timeout_ms = 1500

# Cost-saver prompt: skip PLUR inject + long memory (tools + skill NL/slash stay full)
poor_mode = false

# Background TTL pack repair on later TUI opens (first install is foreground)
ecosystem_auto_ensure = true

# Self-update from GitHub Releases — checked on EVERY launch (60s network floor)
auto_update = true

# Allow failover from a subscription route (OAuth sign-in, OpenCode Go) to a
# per-token fallback. Off by default: a paid fallback is skipped, not billed.
# failover_allow_paid = false

# Force the wire protocol for one provider/model route, e.g. a gateway that
# only speaks Chat Completions. Keys are "provider/model" (or just "provider"
# for the whole provider); values: responses | chat | anthropic | gemini.
# [protocols]
# "opencode/kimi-k3" = "chat"

# Auth behaviour.
# [auth]
# fallback_import = false   # true restores silent vendor CLI / OMP import when
                            # no credential is found (default is the explicit
                            # `nur auth import --from <source>`)

Settings reference

Key Type Default Description
provider string meta Catalog id (meta, openai, openrouter, ollama, …). Set by TUI /login with matching base_url + model
model string muse-spark-1.2 Model id for the active provider
base_url string https://api.meta.ai/v1 API base (no trailing path); providers use Responses or Chat Completions under this base
provider_privacy map empty Per-provider privacy you assert about your own account/endpoint ({provider_id = "local" / "tee" / "zdr" / "standard"}); set in the provider picker and overrides the built-in default
provider_base_urls map empty Per-provider base-URL overrides ({provider_id = "https://…/v1"}) so any provider - including openai - can point at an OpenAI-compatible endpoint (Azure, a proxy, LiteLLM, a mirror). Also honored via env {PROVIDER}_BASE_URL
fallback_providers array empty Opt-in cross-provider failover chain: catalog ids or aliases, retried in order on 5xx/429/transport. Each fallback uses its own env-var key; empty = no failover
failover_allow_downgrade bool false Allow failover to a provider whose privacy tier is weaker than the active one. false means an outage never silently weakens data privacy
failover_allow_paid bool false Allow failover from a subscription route (OAuth sign-in, or an OpenCode Go /zen/go/ base URL) to a per-token provider. false skips the paid fallback with a status line instead of silently billing it
protocols map empty Force the wire protocol per route: {"provider/model" = "responses" \| "chat" \| "anthropic" \| "gemini"} (a bare provider key covers every model). Wins over the catalog's per-model routing; use it when a gateway rejects the default protocol (the 400 error names this table). Ignored for Anthropic and Gemini providers, whose protocol is not negotiable
auth.fallback_import bool false When no credential is found, silently import a signed-in vendor CLI / OMP session. false (default) keeps imports explicit via nur auth import --from <source>, because rotating vendor refresh tokens sign out whichever tool refreshes second
auth.encrypt_at_rest bool true Seal auth.json, provider_keys.json and provider_sessions.json with Windows DPAPI (user scope) before writing, so a copied file is inert on another account or machine. Older plaintext files are read as-is and sealed in place on first read. Set false when ~/.nur is synced between machines or Windows accounts. No effect on Unix, where mode 0600 is the protection
fusion_panel array empty Opt-in /fusion panel: catalog ids polled alongside the active model. /fusion <question> asks each and the active model synthesizes one answer. Empty = off
reasoning_effort string high Reasoning depth: low, medium, high, xhigh, max, ultracode (also minimal). See below
max_turns integer 0 Max agent tool/model rounds per user prompt. 0 = unlimited (default). Set via config or /budget turns / /turns
max_session_cost_usd float? unset (∞) Optional session $ hard-stop. /budget cost <usd> · /budget clear
max_session_tokens integer? unset (∞) Optional session token hard-stop. /budget tokens <n> · /budget clear
request_output_reserve_tokens integer 8192 Conservative per-request completion ceiling/reservation. Nur preflights estimated input + this reserve against context and session budgets, then sends the matching provider output-limit field where supported. 0 uses the provider default and is intentionally less safe.
stream bool true Stream API responses
context_window integer 1000000 Fallback context window in tokens (range: 1000–2000000). The models.dev catalog is authoritative when it knows the active provider/model; this value is used only when it does not. Auto-compaction keeps an OMP-style response/tool reserve: the larger of 15% or 16,384 tokens on large windows, with a proportional safety clamp on small windows. A local stored-context estimate is used when provider usage is absent or under-reported.
tool_result_max_chars integer 12000 Max inline tool output chars; larger results spill to disk with a head+tail preview (0 = unlimited)
shell_timeout_handoff bool true A bash command still producing output at its timeout moves to a bg job (the model gets a "still running" placeholder with the job id) instead of being killed. false restores kill-on-timeout
compact_keep_user_turns integer 4 Recent user turns kept after compaction
compact_tool_body_max_chars integer 800 When compacting, truncate older tool bodies to this many chars (0 = leave intact)
kv_stable_compact bool true true preserves the recent working edge verbatim after a stable summary for provider prompt-cache reuse. false uses a classic reconstructed working-tail order. Compaction status reports the active strategy.
compaction.remote_enabled bool false Prefer remote summarizer when an endpoint is set
compaction.remote_endpoint string unset OMP-compatible compact URL; setting it opts in. Supports {systemPrompt,prompt} endpoints and OpenAI /chat/completions; failures fall back locally. The bounded transcript crosses this configured remote data boundary. Nur records endpoint origin, bounded input estimate, output estimate, and provider usage when returned in the session receipt. Env: NUR_COMPACT_REMOTE_ENDPOINT (+ NUR_COMPACT_REMOTE=1 if only env)
typesafe.enabled bool true TypeSafe (Jev) typed judgments for the harness: tool gate, result judge, Jev-scored compaction, skill checks, model routing. Needs a key (TYPESAFE_API_KEY or /auth); with none, every policy returns "no judgment" and behavior is unchanged. Full reference: typesafe.md
typesafe.model string jev-latest System One model that answers the questions
typesafe.key_env string empty Exclusive environment variable name for a selected Jev engine; never the key value
typesafe.credential_provider string empty Exclusive credential-store slot, set to jev:<id> by nur jev use --engine <id>
typesafe.base_url string https://api.typesafe.ai/v1/systemone System One endpoint. A loopback URL (127.0.0.1 / localhost / [::1]) needs no key and runs the whole judgment layer against a local engine - see jev-local.md
typesafe.act_confidence float 0.85 Confidence at or above which a judgment may change behavior
typesafe.escalate_confidence float 0.5 Below this the judgment is handed to a bigger model or a human instead of being acted on
typesafe.api_key string unset Key inline in config. Prefer TYPESAFE_API_KEY or the credential store - anything here is plain text on disk
typesafe.timeout_ms integer 20000 Per-request timeout. Jev is fast; a long stall means something is wrong
typesafe.retries integer 2 Retries on 429/529/5xx with exponential backoff
typesafe.max_questions_per_request integer 24 Questions merged into one request before they are split and sent in parallel
typesafe.max_parallel integer 4 Concurrent requests when a question set is split
typesafe.max_request_tokens integer 30000 Estimated ceiling for one request (state + its questions). Ported from fast-jev-compaction; keeps a request under System One's ~32k limit
typesafe.compaction.enabled bool true Jev-scored compaction: drop tool calls, keep survivors verbatim
typesafe.compaction.replace_summary bool true Manual /compact honors configured Jev without summarizing, even at zero reduction; automatic recovery also checks min_reduction
typesafe.compaction.min_reduction float 0.25 Automatic recovery only: positive reduction required to skip summarization
typesafe.compaction.preserve_recent integer 6 Newest N items never touched (the first item is always kept)
typesafe.compaction.keep_threshold float 0.5 Minimum keep probability for a call or result to survive
typesafe.compaction.truncate_head_chars integer 300 Chars of a dropped result retained before its note
typesafe.compaction.max_state_tokens integer 25000 Estimated token ceiling for the state Jev sees
typesafe.compaction.goal_prompts integer 3 Recent user prompts that make up the goal shown to Jev
typesafe.tool_gate.enabled bool true Pre-execution gate + post-execution result judge at the tool boundary
typesafe.tool_gate.judge_results bool true Judge results after execution (did it work, keep it, keep it verbatim)
typesafe.tool_gate.skip_redundant bool true Answer a confident duplicate of a call whose result is still in context without re-running the tool
typesafe.tool_gate.skip_repeated_failures bool false Also skip identical repeats of a call that already failed (surfaced in the transcript, not enforced, by default)
typesafe.tool_gate.flag_risky bool true Surface risk / needs-human judgments in the UI. Never blocks anything
typesafe.tool_gate.preview_chars integer 1200 Chars of arguments/result shown to Jev per call
typesafe.tool_gate.trace_window integer 16 Most recent calls kept in the gate's state window
typesafe.skills.enabled bool true Skill layer on/off
typesafe.skills.rerank bool true Rerank skill candidates against the request when several match
typesafe.skills.narrow_requirements bool true Inject only the triggered skill's applicable rules as a checklist
typesafe.skills.check_usage bool true Check that an activated skill was actually carried out
typesafe.skills.max_requirements integer 8 Most rules injected from a narrowed skill
typesafe.routing.enabled bool true Run an agent call that names no provider/model on a cheaper reachable model when it is known-price, at least 15% cheaper and no weaker in privacy, with parent context Jev judged directly useful. The parent session never moves
typesafe.routing.suggest bool true Show routing decisions in the transcript
typesafe.tools.subset bool false Narrow the tool surface on the first round of a turn (one Noul per specialist; later rounds get the full surface). Off because tool schemas ride the prompt cache
typesafe.tools.keep_probability float 0.75 How confident the answer must be that a tool is not needed before it is dropped (keeping is the safe direction)
enclave.url string https://mcp.enclave.ai/ Enclave MCP endpoint (empty = default). https only; plain http only for a loopback host. The key comes from ENCLAVE_MCP_API_KEY or the credential store, never this file
enclave.timeout_secs integer 120 Upper bound on one Enclave MCP request
headroom.enabled bool true Headroom inline compression of large tool results (needs the headroom-ai package; missing package = no-op)
headroom.mode string inline inline compresses tool results before they enter model context; off disables (proxy mode reserved)
headroom.min_chars integer 2000 Skip compression below this many chars
headroom.model string active session model Token-counter model passed to Headroom; empty = the active session model
optmem.enabled bool true OptMem permanent memory under upstream ~/.optmem (wake inject + optmem tool; /optmem · /memo)
prewalk.enabled bool false After todos exist, first write/edit switches to prewalk.into / smol
prewalk.into string unset Cheap model for prewalk handoff (/prewalk into …, or OMP_SMOL_MODEL / OMP modelRoles.smol)
helix_memory.mode string auto auto enables only when HELIX_URL/NUR_HELIX_URL or a configured URL exists; on uses the configured/local endpoint; off disables the resident
helix_memory.url string local endpoint when on HelixDB gateway base URL. Nur uses /healthz and typed /v2/query requests
helix_memory.api_key_env string HELIX_API_KEY Name of the env var containing the Helix bearer token. The token is never written to config or memory
helix_memory.timeout_ms integer 1500 Per-request deadline. Writes queue locally first and retry from the outbox on later writes or helix_sync
native_memory bool true Agent-native memory + Connectome continuity: inject hierarchical memories into the system prompt and run localized maintenance on compact
memory_embed_mode string auto Embedding mode: auto (API, fall back to local on error), api (require API), or local (offline n-gram hash embedding only)
memory_embed_model string provider default Embedding model for the vector store. Empty = provider default (text-embedding-3-small); falls back to the local embedding when the API path is unavailable
memory_model_extract bool false Let the active model write durable first-person memories from assistant turns (one cheap low-effort call per turn). Off by default
message_inbound string refuse Inbound peer-mail policy (~/.nur/peers, message tool): refuse (default - off) / ask (you approve each letter before the model sees it) / accept (deliver). Unknown values fail closed as refuse
proposal_mode bool false Shepherd-style retained outputs: write_file stages under ~/.nur/proposals/<session>/ until proposal apply
quality_gate string empty Shell command run as a quality gate before accepting DONE in autonomous mode. Empty = none
context_register_min_chars integer 8000 Auto-register tool results larger than this into the RLM context store (0 = disabled)
subagent_depth integer 1 RLM-style subagent recursion depth. 1 = children only; each extra level multiplies cost
poor_mode bool false Skip PLUR auto-inject and long memory (explicit skill activation - slash and the skill tool - still works)
theme string unset Picked theme id (/theme). Unset = Nur Gold until onboarding choice
theme_setup.accent hex string unset Personal accent color (#rrggbb) layered over every theme pick - recolors the accent ramp, highlights, and banner gradient. theme_setup.accent_deep / theme_setup.accent_sky optionally pin the ramp ends (derived automatically when absent)
theme_setup.protocol string auto Force the terminal graphics protocol for inline images: kitty, sixel, iterm2, halfblocks, or auto
theme_setup.inline_images bool true Master switch for inline pixel rendering in transcript + peeks
theme_setup.transparent bool false Skip painting panel/code backgrounds so a translucent terminal shows through (/theme transparent)
theme_setup.motion string auto Ambient animation. full: the banner shimmer, aurora rules and modal edges repaint at ~11fps while idle. reduced: they hold one still frame, the idle loop repaints only on input or agent events, and spinners tick at ~10fps - the right setting when the terminal is drawn elsewhere (Orca panes, browser terminals, SSH), where every frame crosses a link and typing starts to feel late. auto picks reduced inside an Orca pane (ORCA_PANE_KEY) or an SSH session (SSH_TTY/SSH_CONNECTION). /theme motion toggles and saves; NUR_REDUCED_MOTION=1|0 overrides for one run
ecosystem_auto_ensure bool true Background TTL repair of packs on later TUI opens (first install is foreground via npx / one-liner / EXE / nur install\); setfalse` to skip repair
skills.auto_activate bool false Natural-language skill activation ("think like fable" injects the skill body). Off by default; explicit /skill-name and the skill tool always work. See natural-language skill activation
tools.profile string full core = minimal local editing shell (15 tools: read/list/write/edit/multi_edit/apply_patch, bash, sgrep/grep/glob, web_fetch/web_search, question, todo_write, submit_plan) with no ecosystem tools or prose. Session-fixed; restart to change. Unknown values fall back to full. Measured per-request overhead on the E2E harness (chars/4, no PLUR or OptMem installed): full about 3.9k system-prompt + 15.4k tool-schema tokens (54 tools), core about 1.8k + 2.8k (15 tools)
tools.sgrep_first bool true Semantic search is enforced, not suggested: a grep whose pattern is a description is answered by sgrep, a grep past its default cap comes back reranked by sgrep (an explicit max_matches is honored), and shell searches (grep/rg/findstr/Select-String as the command) are refused. Needs sgrep installed to change anything; see Tools
auto_update bool true On every launch (bare TUI, nur "prompt", nur run …, gateway), check GitHub Releases and install a newer binary when available; it runs on a background thread so it never delays or breaks a run, and the new binary is picked up on the next launch. A 60s floor between network checks stops a script that loops nur from hammering the API — tune it with NUR_AUTO_UPDATE_TTL_SECS (0 = check every run). Opt out with false or env NUR_SKIP_AUTO_UPDATE=1. Verify with nur update --check; nur update always runs the full update path

Personal accent (theme setup)

Layer a personal accent color on top of any /theme pick:

[theme]
accent = "#e8b923"        # your accent (any #rrggbb)
# accent_deep = "#8a5a00" # optional; derived when absent
# accent_sky  = "#ffe08c" # optional; derived when absent

The accent recolors the theme's ramp (sky → accent → deep), selection highlights, and the banner gradient - so /theme midnight + accent = "#ff5470" gives you midnight with a pink spine. /theme switching keeps the override.

Reasoning effort levels

Level Behaviour
low Light reasoning
medium Balanced (alias med)
high Deep reasoning (default)
xhigh Deeper still (alias extra)
max The strongest reasoning the route takes
ultracode max, plus the agent splits work that splits across parallel subagents and verifies the result (alias ultra)

minimal is still accepted for OpenAI-shaped routes. Set a level with /effort <level> (saved to this file) or --effort for one run.

Providers do not share one ladder, so nur keeps the level you chose and sends each route the nearest rung it accepts. Only two wire formats carry an effort field: the Responses API (reasoning.effort) and Anthropic's own Messages API (output_config.effort). Bare /effort shows what the active route receives:

Route Receives
OpenAI GPT-5.6 none, low, medium, high, xhigh, max; ultracode sends max
Other Responses-API routes (reasoning.effort) minimal … xhigh; max and ultracode send xhigh
xAI browser login (Responses) Grok 4.6/4.7: low, medium, high, xhigh; Grok 4.5: through high; legacy Grok 3 mini: low or high
Anthropic (output_config.effort) By model: Fable, Opus 4.7+ and Sonnet 5 take low … max; Opus/Sonnet 4.6 and Mythos Preview take all but xhigh; Opus 4.5 takes low … high; Haiku and older models get none
Chat Completions routes (OpenRouter, Groq, Nous Portal, xAI API keys, local servers, …) No effort field, so nothing is sent
Gemini, MiniMax No effort control, so nothing is sent

The level is saved either way and applies again on a route that takes one. ultracode also turns on parallel subagent orchestration, which works on every route because it is an instruction to the agent rather than a request field.

Provider references: OpenAI, xAI, Anthropic.

A missing rung rounds to the nearest one, and ties round up. A name nur does not know is forwarded as-is, so a rung a vendor ships today works today.

Session budgets (interactive)

In the TUI you can set ceilings without editing the file:

/budget                 # show ceilings + spend so far
/budget cost 2.5        # hard stop at ~$2.50 this process
/budget tokens 500000
/budget clear           # unlimited this process
/budget save            # write current ceilings into config.toml

When a ceiling is hit, the agent refuses new API turns with a clear status message.

Budgets are the only thing that stops a turn. With no ceilings set, nothing ends a turn on its own: context-window overflow (a preflight estimate or a provider rejection) recovers through staged compaction - promote to a larger sibling model, model-assisted compact, then a local minimal trim - and oversized pasted input is auto-registered with the context tool (pointer + preview) instead of being refused. Every other turn stop is an explicit budget you set.

max_turns = 0 means unlimited task completion rounds - it does not mean that spending is safe or capped. On the first unrestricted turn Nur warns about this distinction. Provider usage can be absent or subscription-only, so token and dollar enforcement remains estimate-based on those routes.

Conservative budget preset

For unattended or weekly-allowance-sensitive work, start with this explicit preset and adjust upward only after inspecting /usage and /receipt:

# Conservative: 40 model/tool rounds, 250k total tokens, $2.00 estimated
# list-price spend, and an 8k reserve before every request/failover target.
max_turns = 40
max_session_tokens = 250000
max_session_cost_usd = 2.0
request_output_reserve_tokens = 8192

# Keep fusion/fan-out opt-in. Every configured panel is an additional reserved
# request; set fusion_panel = [] for the conservative preset.
fusion_panel = []

The preflight also evaluates each failover destination for context capacity, tool capability, parallel-tool safety, output-limit support, and incremental catalog-estimated cost. Local OpenAI-compatible servers use conservative serial tool behavior because tool support depends on the selected model template.


Permission rules

Optional file: ~/.nur/permissions.toml (and/or project .nur/permissions.toml - both are merged).

A project file comes with the repository, so it can only tighten on its own: its deny and ask rules apply at once, while its allow rules are held until you trust that exact list with /permissions trust or nur permissions trust. An edit to the list (a git pull, say) holds it again, and nur tells you at startup what the project asks to auto-approve. Trust is recorded per directory in ~/.nur/trusted-permissions.json; /permissions untrust withdraws it.

# Patterns: "tool" or "tool:glob"  (* = any sequence)
# Order: deny > ask > allow > mode default
# Plan mode still blocks code authoring / VCS mutation even if allow matches.

deny  = ["bash:rm -rf *", "bash:git push --force*"]
ask   = ["bash:npm publish*"]
allow = ["bash:git status*", "bash:cargo test*"]
Decision Effect
deny Always block (including auto mode)
ask Force an approval prompt (even in auto)
allow Skip approval in manual (plan structural blocks still win)

bash rules see every command in a chain. The command is split at ;, &, &&, |, ||, newlines and subshell parentheses (quoted text stays whole), so a deny or ask rule fires when any command in it matches: cd . && rm -rf / is denied by bash:rm -rf *, and so is echo "$(rm -rf /)". An allow rule approves only when every command is allowed on its own: bash:git * covers git status && git diff, not git status && curl … | sh. A command substitution ($(…), backticks, <(…)) or a redirect into a file (> out.txt; 2>&1 and >/dev/null are fine) is never approved by pattern and falls back to the mode default.

Reload without restart: /permissions reload. /cd reloads them for the new directory.


Tool hooks

Hook output is discarded - exit status is the only channel (0 allows, non-zero blocks the call in Manual/Auto and is reported to the model). stdout/stderr are not captured, so a hook that writes a lot cannot stall the call.

Optional file: ~/.nur/hooks.toml.

pre_tool = "echo pre $NUR_TOOL"
post_tool = ""
timeout_ms = 5000

Environment for hook commands:

Env Meaning
NUR_TOOL Tool name
NUR_ARGS_JSON Raw JSON args
NUR_CWD Workspace cwd
NUR_SESSION Session id

Non-zero pre_tool exit blocks the tool. Missing file = no hooks. Check status with /hooks.


Environment variables

API and model

Variable Purpose
NUR_API_KEY API key (preferred)
META_API_KEY Optional key for Meta Model API provider
NUR_BASE_URL Override API base URL (self-hosted Ollama/vLLM/LiteLLM/gateways)
NUR_PROVIDER Override the provider for this process (catalog id or alias, e.g. opencode-go, chatgpt). The provider's host and default model follow; [provider_base_urls] and <PROVIDER>_BASE_URL still apply, and NUR_MODEL / --model still pick the model. An unknown id is a config error. A value inherited from a parent nur session is ignored
NUR_MODEL Override model id for the active provider. A value inherited from a parent nur session is ignored (nur exports NUR_MODEL to its own children) - pass --model to override explicitly
NUR_JEV_LOCAL_URL Point the TypeSafe layer at a local System One engine (e.g. http://127.0.0.1:8788). Loopback needs no key, so TYPESAFE_API_KEY becomes optional. See jev-local.md
TYPESAFE_API_KEY TypeSafe (Jev) key for the harness boost layer. Aliases: TYPESAFE_KEY, JEV_API_KEY; also /auth → TypeSafe · Jev, or ~/.nur/typesafe.key. It is a judgment credential, never the active chat provider

Provider reliability

Variable Purpose
NUR_PROVIDER_TURN_TIMEOUT_SECS Maximum time for one provider request before Nur cancels it (default 300). Applies to Responses, Chat Completions, Anthropic Messages, Gemini Cloud Code, and Cursor Agent CLI transports

Rendering

Variable Purpose
NUR_IMAGE_PROTOCOL Force the terminal graphics protocol for inline images (kitty, sixel, iterm2, halfblocks); overrides theme_setup.protocol
NUR_IMAGE_QUERY Set to 1 to run the full stdio graphics-capability probe on launch (default is the instant, non-blocking path)
NUR_REDUCED_MOTION 1 freezes ambient animation and stops idle repaints for this run, 0 forces full motion; overrides theme_setup.motion
NUR_STARTUP_TRACE Set to 1 for local phase timings in $NUR_HOME/cache/startup-<pid>.jsonl, or set a file path. Records elapsed milliseconds and stage names, without prompts or credentials. Off by default

Paths

Variable Purpose
NUR_HOME Override data home (default ~/.nur). Its parent directory also becomes the ~ nur reads vendor state from (~/.agents, ~/.claude, ~/.codex, ~/.optmem, ...), so NUR_HOME=<dir>/.nur is a fully contained install. Without it, HOME then USERPROFILE are honoured on every OS (Windows included), then the OS profile
NUR_CWD Default working directory

Status and usage

Set by NurCLI for host integrations:

Variable Purpose
NUR_STATUS_PATH Path to live status file
NUR_USAGE_LOG_PATH Path to usage log
NUR_SESSION_ID Current session id
NUR_PROVIDER Provider id Nur exports to its own children (the active provider, e.g. meta); children ignore the inherited value, see above

Update control

The release check runs on every launch (see auto_update above).

Variable Purpose
NUR_SKIP_AUTO_UPDATE Set to 1 to skip the launch-time release check for this shell
NUR_DISABLE_UPDATES / DISABLE_UPDATES Set to 1 to disable the launch-time release check
DISABLE_AUTOUPDATER Claude Code's kill switch — also honored. It is injected only inside AI-agent sessions, so nur stays on your last version there instead of swapping its own binary mid-session. Absent from an ordinary terminal, where nur still updates every run
NUR_AUTO_UPDATE_TTL_SECS Minimum seconds between network checks (default 60; 0 = check every single run). Guards against a script looping nur
NUR_AUTO_UPDATE_BLOCKING Set to 1 to wait for the check to finish before continuing, instead of backgrounding it (scripts / CI that want to be on the newest build now)

Ecosystem

Variable Purpose
CLAUDE_FLOW_DB_PATH Ruflo database path
CLAUDE_FLOW_MEMORY_PATH Ruflo home path
HELIX_URL / NUR_HELIX_URL Activate the HelixDB memory resident in auto mode and select its gateway
HELIX_API_KEY Optional HelixDB bearer token (or use the env-var name configured by helix_memory.api_key_env)
USE_BUILTIN_RIPGREP Set to 0 to use system ripgrep

Data home

All NurCLI state lives under ~/.nur/ by default:

~/.nur/
├── auth.json           # API key
├── config.toml         # Configuration
├── permissions.toml    # Optional allow/deny/ask rules
├── hooks.toml          # Optional pre/post tool hooks
├── nur.log            # Tracing (not painted into the TUI)
├── status.json         # Live token/cost status
├── usage.jsonl         # Per-request usage log
├── ade.json            # ADE discovery manifest
├── memory.md           # Cross-session memory journal (quick-memory #notes)
├── history.jsonl       # Prompt history
├── sessions/           # Session files (UUID.json + .json.bak / .precompact.bak)
├── tool-results/       # Spilled oversized tool outputs
├── browser-extension/  # Staged tmwd_cdp_bridge for browser tool
├── skills/             # Installed skill packs
├── ruflo/              # Vector memory database
└── skill-packs/        # Skill pack metadata

Override with NUR_HOME.


Project instructions

NurCLI reads project-level instruction files from your working directory:

File Purpose
NUR.md Primary project instructions
AGENTS.md Agent conventions (shared with other tools)
CLAUDE.md Legacy instructions (still loaded)

These are loaded at session start and prepended to the system prompt.