Skip to content

Environment Variables

Variables capability authors and operators interact with — discovery paths, flag overrides, runtime connection contract, MCP interpolation, and the full flag resolution order.

The runtime reads four classes of environment variable from the operator’s shell, injects two classes into capability code (flags and runtime-connection vars), and supports two interpolation forms inside MCP server config. This page is the catalog.

VariablePurpose
DREADNODE_CAPABILITY_DIRS:-separated (; on Windows) list of extra capability search directories. Applied after ~/.dreadnode/capabilities/.
Terminal window
export DREADNODE_CAPABILITY_DIRS="/opt/capabilities:$HOME/dev/capabilities"

Entries resolve to absolute paths. Non-existent directories are silently skipped. See Installing for the full search order.

Operators set this in their shell to override the capability author’s default and any persisted binding:

DREADNODE_CAPABILITY_FLAG__<CAP>__<FLAG>

Capability and flag names upper-case, with dashes converted to underscores:

threat-hunting + readonly → DREADNODE_CAPABILITY_FLAG__THREAT_HUNTING__READONLY

Accepted values (case-insensitive):

TrueFalse
10
truefalse
onoff

Anything else logs a warning and is skipped — the override does not apply.

Operators set the DREADNODE_-prefixed variable above; the runtime resolves the flag and injects one CAPABILITY_FLAG__* variable per declared flag, per capability, before workers and tool modules run:

CAPABILITY_FLAG__<CAP>__<FLAG>

Value is always 1 or 0. Read it directly:

import os
READONLY = os.environ.get("CAPABILITY_FLAG__THREAT_HUNTING__READONLY") == "1"

The DREADNODE_-prefixed form is the operator-facing override; the CAPABILITY_FLAG__* form is what code reads.

Subprocess workers (and any standalone process connecting to a runtime — test harnesses, external daemons, a dn serve client) read these variables to reach and authenticate against the runtime. The runtime injects them authoritatively into every subprocess worker it spawns.

VariablePurpose
DREADNODE_RUNTIME_URLFull base URL of the runtime HTTP API, e.g. http://127.0.0.1:8787. Always composed against 127.0.0.1 when the runtime injects it.
DREADNODE_RUNTIME_TOKENBearer token for HTTP and WebSocket auth. Send as Authorization: Bearer <token>. Optional only if the runtime is running unsecured.
DREADNODE_RUNTIME_IDRuntime identifier used for scoping and logs. Opaque — treat as a string.
DREADNODE_RUNTIME_HOSTUsed to compose URL when URL is absent. Falls back to 127.0.0.1.
DREADNODE_RUNTIME_PORTUsed to compose URL when URL is absent. Falls back to 8787.

The URL is co-located with the runtime; workers run on the same host. Cross-host bridging is not supported.

Values for DREADNODE_RUNTIME_URL, DREADNODE_RUNTIME_TOKEN, and DREADNODE_RUNTIME_ID set in a subprocess worker’s manifest env: are rejected at parse time:

Worker 'bridge' 'env' must not set runtime-owned keys
(DREADNODE_RUNTIME_URL, DREADNODE_RUNTIME_TOKEN); these are injected
authoritatively by the runtime [CAP-WTOP-006]

The runtime owns the connection identity. Set them yourself only when running a worker outside the capability system (standalone or under a separate process manager).

The following names are still read for one release with a deprecation warning, then removed. Migrate to the DREADNODE_RUNTIME_* names.

DeprecatedReplacement
DREADNODE_SERVER_HOSTDREADNODE_RUNTIME_HOST
DREADNODE_SERVER_PORTDREADNODE_RUNTIME_PORT
SANDBOX_AUTH_TOKENDREADNODE_RUNTIME_TOKEN

The runtime sets CAPABILITY_ROOT to the absolute path of the capability directory in every worker, MCP server, and tool module. ${CAPABILITY_ROOT} in MCP server config interpolates from this.

Inside MCP server command, args, url, headers, and env:

FormResolved atSource
${CAPABILITY_ROOT}Parse timeThe capability directory path
${VAR}Connect timeos.environ — raises ValueError if unset
${VAR:-default}Connect timeos.environ, falling back to default

Connect-time resolution means a capability can be loaded, validated, and published without every referenced variable being set. Failures appear only when the MCP server starts.

Flags resolve through four layers. Later layers win.

LayerSourceWho controls it
1default: in capability.yamlCapability author
2Persisted binding statePer-project — the TUI flag editor writes here
3DREADNODE_CAPABILITY_FLAG__* env varOperator shell environment
4--capability-flag cap.flag=bool CLIRuntime invocation

A CLI override beats everything else. A persisted binding beats only the author default.

A local runtime persists flag toggles to ~/.dreadnode/local-capability-state.json — written by the TUI when you toggle a flag in the capability detail panel. A sandbox runtime persists them on the platform per project. Either way, flags survive runtime restarts until you clear them.

Terminal window
dn --capability-flag <capability>.<flag>=<bool>

Parsing rules:

  • One = separator, left is <cap>.<flag>, right is the boolean.
  • Exactly one . in the path separating capability from flag name.
  • Extra dots, missing =, or unrecognized boolean values log a warning and skip the entry.
  • Multiple --capability-flag arguments accumulate.
Terminal window
dn \
--capability-flag threat-hunting.readonly=true \
--capability-flag threat-hunting.burp=false \
--capability-flag network-tools.verbose=on

when: on an MCP server or worker is a list of flag names. The component loads if any listed flag is effectively true (OR semantics).

when:Loads when
null or absentAlways
[a]a is true
[a, b]a or b is true
[]Validation error

Flag names referenced in when: must be declared in the same manifest. Undeclared names are a validation error.