Configuration
Omnodex keeps its configuration in your Omnodex home: ~/.omnodex/ by default, C:\Users\<you>\.omnodex\ on native Windows, or the directory set in OMNODEX_HOME. Each file below is optional; create only the ones you need.
| File | Purpose |
|---|---|
config.json | Dashboard roots and machine label |
omnodex-config.json | Where hooks find their handlers (source installs), extra workspace roots, and enforcement settings |
omnodex-proxy.json | MCP proxy upstream servers |
stream-config.json | Hosted dashboard connection, written by omnodex connect |
config.json
Section titled “config.json”{ "dashboard": { "roots": ["/mnt/c/Users/<you>/.omnodex"] }, "machine": { "label": "Work Laptop" }}dashboard.roots
Section titled “dashboard.roots”Type: string[]
Default: []
Additional Omnodex home directories the local dashboard reads. The dashboard’s own home is always included, so list only the extra ones. Paths that do not exist are skipped.
Use this to see several hosts in one dashboard, for example native Windows and WSL on the same machine. See Windows and WSL. For one-off use, pass omnodex dashboard --roots <path> instead.
machine.label
Section titled “machine.label”Type: string
Default: (none)
A readable name for this host, shown in the hosted dashboard’s machine selector. Without it, the dashboard shows the machine’s random ID. The label is encrypted under the stream secret before it leaves the machine, so only your dashboard can read it, and it is display only: storage uses the ID.
omnodex-config.json
Section titled “omnodex-config.json”Tells hook launchers where the hook handlers of your Omnodex build are, and optionally which extra folders count as part of your workspace. shim_paths is required for source installs; an npm install does not need it, because the launchers find the npm package on their own.
{ "shim_paths": { "claude-code": "/path/to/omnodex/packages/hooks-provider/dist/bin/claude-hook-shim.js", "codex": "/path/to/omnodex/packages/codex-provider/dist/bin/codex-hook-shim.js", "antigravity": "/path/to/omnodex/packages/antigravity-provider/dist/bin/antigravity-hook-shim.js" }}Use absolute paths in the host’s path style, with escaped backslashes on Windows. An entry is used only if the file exists. See Installation.
workspace_roots
Section titled “workspace_roots”Risk detection flags writes outside a session’s workspace. The workspace is the folder the session started in and its current folder, the git repositories those belong to (including every worktree of the same repository), and any folders you list here. Add folders your agents are meant to write to across projects, such as a shared notes folder:
{ "shim_paths": { "claude-code": "/path/to/omnodex/packages/hooks-provider/dist/bin/claude-hook-shim.js" }, "workspace_roots": ["~/notes", "/srv/shared-docs"]}A leading ~ is your home folder. Your home folder itself and the filesystem root are never treated as a workspace, even when a session starts there.
enforcement
Section titled “enforcement”Whether Omnodex acts on tool calls, and what it does with findings. Set the mode with omnodex enforce and policy entries with omnodex policy. See Shadow Mode and Guardrails for how they combine.
| Key | Value |
|---|---|
mode | monitor (default), shadow or guardrails (Pro; without the guardrails module it records as shadow) |
on_error | allow (default): a call Omnodex cannot check goes ahead. block: it is stopped |
policy | List of policy entries: { "id", "match": { "rule_id" | "category" | "severity", "target"?, "project"? }, "effect": { "verdict"?: "deny" | "confirm" | "allow", "severity"?, "mute"? }, "note"?, "created_at"? }. target is one of { "path" }, { "destination" }, { "command_prefix" }, { "credential" }, { "tool", "server"? } or { "access": "read" | "write", "path" } |
rules | Rule ID to verdict: deny, confirm or alert_only |
severity_defaults | Severity (LOW, MEDIUM, HIGH, CRITICAL) to verdict, for rules without their own |
exceptions | List of { "rule_id", "kind": "allow" | "mute", "target"?, "note"? }; target is one of { "path" }, { "destination" } or { "command_prefix" } |
projects | Project folder to its own rules, severity_defaults and exceptions |
{ "enforcement": { "mode": "shadow", "policy": [ { "id": "p-1a2b3c4d", "match": { "rule_id": "RULE_SENSITIVE_PATH_READ" }, "effect": { "verdict": "deny" } }, { "id": "p-5e6f7a8b", "match": { "rule_id": "RULE_SENSITIVE_PATH_READ", "target": { "path": "~/work/app/.env.example" } }, "effect": { "verdict": "allow" } } ] }}rules, severity_defaults, exceptions and projects are the older form of the same settings; they keep working and omnodex policy list shows them as entries. An entry Omnodex cannot read is skipped on its own, so a typo never switches the rest off. A repository can also carry .omnodex/config.json with an enforcement section; only its rules, severity_defaults and tightening policy entries are read, and only where they are stricter than yours.
MCP proxy configuration
Section titled “MCP proxy configuration”omnodex-proxy.json lists the upstream MCP servers the proxy routes. The proxy reads it from --config <path> if given, otherwise from the Omnodex home.
{ "version": 1, "redact_parameters": false, "upstream_servers": [ { "name": "filesystem", "transport": "stdio", "command": "npx", "args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/project"] }, { "name": "github", "transport": "stdio", "command": "npx", "args": ["-y", "@modelcontextprotocol/server-github"], "env": { "GITHUB_TOKEN": "${GITHUB_TOKEN}" }, "redact_parameters": true } ], "upstream_connection": { "discovery_window_ms": 15000, "discovery_window_uncached_ms": 45000 }}| Field | Type | Default | Description |
|---|---|---|---|
version | 1 | required | Config schema version |
redact_parameters | boolean | false | Replace every parameter value with [REDACTED] in the event log. Parameter names are kept. |
proxy_bin | string | (none) | Source installs: path to your build’s proxy script, for the Cowork, Codex, and Antigravity plugin launchers. Not needed for an npm install, which the launchers find on their own, or when a client starts the proxy directly with node and --config. |
upstream_servers | array | [] | Upstream servers to route. May be empty: the proxy still serves its built-in omnodex_* tools. |
upstream_servers[].name | string | required | Identifier, used as the tool name prefix |
upstream_servers[].transport | "stdio" | required | Only stdio is supported |
upstream_servers[].command | string | required | Executable to start. Use an absolute path for desktop apps. |
upstream_servers[].args | string[] | [] | Arguments for the command |
upstream_servers[].env | object | (none) | Environment variables for the upstream. Values can reference the proxy’s environment as ${VAR}. |
upstream_servers[].cwd | string | proxy’s directory | Working directory for the upstream |
upstream_servers[].name_override | string | (none) | Prefix to use instead of name |
upstream_servers[].redact_parameters | boolean | inherits top level | Per-server redaction |
upstream_connection.discovery_window_ms | number | 15000 | Normal discovery ceiling from proxy start. Cached tools are listed immediately; failed first attempts do not wait for retries. |
upstream_connection.discovery_window_uncached_ms | number | 45000 | First-list ceiling for upstreams without a cached tool list, counted from proxy start. Added in omnodex 0.10.0. See Sizing the discovery window. |
upstream_connection.connect_timeout_ms | number | 30000 | Independent timeout for each connection step: initialization, then tool listing |
upstream_connection.retry_initial_delay_ms | number | 1000 | Delay before the first retry of a failed upstream. Doubles on each retry. |
upstream_connection.retry_give_up_delay_ms | number | 180000 | Retries stop once the next delay would reach this. With the defaults that is 9 attempts over about 4 minutes. |
Tools from each upstream are exposed as <prefix>__<tool>, for example filesystem__read_file. Keep secrets out of this file: put them in environment variables and reference them with ${VAR}.
How upstreams connect
Section titled “How upstreams connect”The proxy answers your agent straight away and connects upstream servers in the background, each one independently. A slow or broken upstream does not stop the others, and does not stop the built-in omnodex_* tools. A failed upstream is retried with a delay that doubles each time, until the next delay would reach retry_give_up_delay_ms; after that it stays failed. Ask your agent to call omnodex_status to see each upstream’s state, last error and next retry, or to call it with retry_failed: true to retry the failed ones immediately.
The proxy remembers each upstream’s tool list between runs, so from the second run on an upstream’s tools are listed straight away, even while it is still starting. If your agent calls one of those tools before the upstream is ready, the call waits for it. The lists are kept in proxy-tool-cache/ in your Omnodex home, hold tool definitions only (names, descriptions and parameters, never environment values or credentials), and are safe to delete. Changing an upstream’s entry in this file starts it fresh.
Sizing the discovery window
Section titled “Sizing the discovery window”Most agent clients read the tool list once, when they start the proxy. Claude Code acts on the MCP tools/list_changed notification and picks up an upstream that connects later in the session. ChatGPT Desktop, Codex CLI and Cowork do not. The proxy covers this by listing the tools it remembers from earlier runs, so the window matters only the first time an upstream runs, or after you change its entry. An upstream that connects after the discovery window is missing until the agent app restarts, even though omnodex_status shows it connected. In Cowork, opening a new task is not enough: fully quit and reopen the app. After a restart its tools are listed at once.
Starting with omnodex 0.10.0, discovery_window_uncached_ms gives an upstream without cached tools up to 45 seconds from proxy start. Cached tools need no wait, and a failed first attempt ends its wait without waiting for a retry. Before 0.10.0, discovery_window_ms bounded uncached discovery too, with a 15-second default.
Set discovery_window_uncached_ms above the time your slowest upstream needs on its first run. The wait ends as soon as every first attempt has settled, so this is a ceiling, not a delay you always pay. Both discovery settings accept zero or a positive integer in milliseconds.
{ "upstream_connection": { "discovery_window_uncached_ms": 60000 }}How long upstreams take:
- A local server started from an installed binary: well under a second.
- A first run of
npx -yoruvx, which downloads the package: several seconds, and longer on a slow network. Later runs are faster because the package is cached. - A server that signs in over the network at startup: as long as that call takes.
To check yours, ask your agent to call omnodex_status after the first tool list arrives. If an uncached upstream was still connecting when that list was sent, the proxy writes one stderr warning naming it, and status keeps restart guidance even after it connects. Restart the app once it is connected to use its tools. A client that explicitly requests a fresh list can pick them up without restarting; that clears the warning for tools it receives.
Raising it costs nothing while upstreams are healthy. It costs time only when one is slow or hanging: the first tool listing can block for up to the window. Your agent still starts, because the proxy answers the MCP handshake immediately.
Lowering it gets a first run’s tool listing sooner, at the risk of omitting a new, slow upstream until the app restarts. Use a low value when every upstream is a fast local process, or when you would rather start with fewer tools than wait.
connect_timeout_ms is independent and remains 30000 ms per connection step by default. Raising the discovery window does not raise that timeout. If an attempt fails first, discovery does not wait for its retries; if it is still connecting when the window closes, its tools are missing from the first list.
Test a new upstream by running the proxy yourself before adding it to a desktop app: omnodex-mcp-proxy --config <path> for an npm install, or node <proxy_bin> --config <path> for a source install.
MCP proxy with Claude Code
Section titled “MCP proxy with Claude Code”To add the proxy to a project, put it in the project’s .mcp.json. The proxy script is <global node_modules>/omnodex/bin/omnodex-mcp-proxy.js for an npm install (npm root -g prints the folder), or <repo>/packages/mcp-proxy/dist/bin/omnodex-mcp-proxy.js for a source install:
{ "mcpServers": { "omnodex": { "command": "/absolute/path/to/node", "args": [ "/usr/local/lib/node_modules/omnodex/bin/omnodex-mcp-proxy.js", "--config", "/home/<you>/.omnodex/omnodex-proxy.json" ], "alwaysLoad": true } }}alwaysLoad is optional. Claude Code defers MCP tools until a tool search finds them; with alwaysLoad, the Omnodex tools are available from the start of the session.
stream-config.json
Section titled “stream-config.json”Written by omnodex connect. Holds the hosted dashboard connection for this host.
{ "stream_secret": "word1 word2 word3 word4 word5 word6", "passphrase": "word1 word2 word3 word4 word5 word6", "api_url": "https://api.omnodex.com", "api_token": "omx_..."}| Field | Description |
|---|---|
stream_secret | The stream secret that encrypts this stream’s events. Generated as six random words on first connect. |
passphrase | The same value under its older name, kept so earlier versions of Omnodex on this machine still find it |
api_url | Omnodex cloud API endpoint |
api_token | Connection token for this stream. Replaced automatically when the stream’s owner rotates it. |
OMNODEX_API_TOKEN and OMNODEX_STREAM_SECRET take precedence over the values in this file. The file contains credentials; do not commit or share it.
Two other files in the Omnodex home belong to this connection. stream-verifier.json remembers the last check of this machine’s secret against the stream’s, so the check runs once per token and secret. pause-state.json holds any pause in effect. Neither holds a secret.
Automatic sync settings
Section titled “Automatic sync settings”A connected host refreshes the hosted dashboard’s encrypted blob on its own. See Automatic sync for what runs where. These optional fields in the same file tune it; the defaults suit almost everyone.
| Field | Type | Default | Description |
|---|---|---|---|
auto_sync | boolean | true | Set to false to turn automatic sync off. omnodex sync still works by hand. |
auto_sync_min_interval_seconds | number | 60 | Shortest gap between two syncs. Stops back-to-back sessions each starting one. |
auto_sync_interval_seconds | number | 900 | How often a running MCP proxy syncs. Values under 30 are ignored. Does not apply to hook platforms, which sync when a session ends. |
OMNODEX_AUTO_SYNC=0 in the environment turns automatic sync off without editing the file.
Environment variables
Section titled “Environment variables”| Variable | Description |
|---|---|
OMNODEX_HOME | Omnodex home directory (default ~/.omnodex) |
OMNODEX_API_TOKEN | API token for cloud features |
OMNODEX_STREAM_SECRET | Stream secret (OMNODEX_SYNC_PASSPHRASE still works) |
OMNODEX_AUTO_SYNC | Set to 0 to turn automatic sync off on this host |
OMNODEX_POLICY_PULL | Set to 0 to stop pulling the account’s finding policy on this host |
OMNODEX_DEBUG | Set to 1 for detailed hook launcher logging in launcher.log |
OMNODEX_NO_UPDATE_CHECK | Set to 1 to disable the background update check |
Desktop apps such as Cowork do not always pass user environment variables to the MCP servers they start. Use the config files above for anything a desktop app needs.
File locations
Section titled “File locations”$OMNODEX_HOME/ config.json Dashboard roots, machine label omnodex-config.json Hook handler locations account-policy.json Your account's finding policy, as last pulled; do not edit omnodex-proxy.json MCP proxy configuration stream-config.json Hosted dashboard connection machine-id.json This machine's random ID for the hosted dashboard installations.json Projects where hooks are installed auto-sync-state.json Last automatic sync: time, blob, error auto-sync.lock Held while a sync runs; ignored after 10 minutes streaming-key-cache.json Cached streaming key, so each push skips the KDF monitoring-heartbeat.json Last monitoring status report sent to the hosted service known-secrets.json Hashes of secrets seen in calls, never the values; never synced known-secrets.key Random key for those hashes event-log/ index.jsonl Session index sessions/<id>.jsonl Per-session event log (append-only) traces.db SQLite read model (derived, safe to delete) bin/ Hook launchers launcher.log Launcher failuresDefault paths by platform
Section titled “Default paths by platform”~/.omnodex/ (for example /Users/you/.omnodex/), used by every agent on the Mac.
~/.omnodex/ (for example /home/you/.omnodex/), used by every agent on the machine.
C:\Users\<you>\.omnodex\ for agents running natively on Windows, including Cowork and ChatGPT Desktop.
WSL has its own home, /home/<you>/.omnodex/, used by agents you run inside WSL. See Windows and WSL.
Next steps
Section titled “Next steps”- CLI Commands - Command reference
- Event Schema - Event data format