Skip to content

CLI Reference Open-Core ​

The Intutic CLI provides workspace management, harness detection, config sync, and trace querying.

Installation ​

bash
# Install workspace CLI globally
npm install -g @intutic/cli

# Install or run native Rust proxy gateway
npm install -g @intutic/proxy
npx @intutic/proxy

Global options ​

OptionDescription
--version, -VShow the CLI version. Only before a command: intutic --version.
--help, -hShow help for the program or for any command, e.g. intutic gates install --help

intutic trace is an alias of intutic traces, and intutic install-daemon / intutic uninstall-daemon are shortcuts for intutic daemon install / intutic daemon uninstall.

A command that changes the workspace needs a role that may make the change, the same as in the dashboard (what each role can change). When yours cannot, the command fails with the roles it needs, for example API PUT /api/v1/budget refused (403): Requires the OWNER or ADMIN role. A Viewer can run the read-only commands and manage their own login and keys.

Choosing a control plane ​

Every command that talks to a control plane picks it the same way; the first that is set wins:

  1. A flag: --control-plane-url <url> (on login, connect and daemon install), or --dev for the local one at http://localhost:3001.
  2. The environment: INTUTIC_CONTROL_PLANE_URL, or INTUTIC_DEV=1 for the local one.
  3. A workspace initialized with intutic init --dev, which uses the local one.
  4. The control plane intutic login saved with your credentials.

With none of these set, a command that needs a control plane says so and exits: the open core runs locally (intutic start) and has no default control plane.

intutic status shows the control plane this order picks.


intutic init ​

Initialize the workspace: find its root, detect harnesses, and record both locally.

bash
intutic init [options]

Options:

OptionDescription
--devRecord dev mode, so later commands use the local control plane (http://localhost:3001)
--git-hooksInstall the Intutic Git hooks without asking
--no-git-hooksSkip the Git hooks without asking
--gatesInstall the harness gates and rules files (intutic gates install) without asking
--no-gatesSkip the harness gates without asking

What it does:

  1. Finds the workspace root: the nearest directory, from the current one upwards, that holds .git/ or package.json. Exits 1 if there is none.
  2. Detects the harnesses present in the workspace and lists each with its config file.
  3. Reports whether you are logged in. No login is needed: init makes no network call.
  4. Records the workspace root, the detected harnesses and dev mode in ~/.intutic/config.json, keeping any other settings already there.
  5. Installs the Git hooks if you agree: post-commit and post-checkout (record the branch and commit with intutic sync-context), pre-commit (refuses a commit that stages a credential, and warns on risky skill files) and post-merge (refreshes the decisions log). A hook that already exists and is not Intutic's is left untouched.
  6. With no login and at least one harness detected, installs the harness gates and rules files if you agree: the same as running intutic gates install afterwards.
  7. Prints setup instructions for pointing each detected harness at the local proxy (http://localhost:4000, or INTUTIC_PROXY_URL).

Without the gates, init writes no harness config files. intutic gates install writes them from this machine alone; on a machine with a login, intutic connect writes them instead, from the control plane's SOPs plus your local .intutic/sops/.

Prompts: with a terminal attached, init asks before installing the Git hooks, and before installing the gates. Without one (CI, a provisioning script, stdin redirected) it never asks: it skips both unless --git-hooks or --gates is passed, and says so. --git-hooks/--no-git-hooks and --gates/--no-gates skip each question either way.

Examples:

bash
intutic init

# Non-interactive, with the hooks and the gates
intutic init --git-hooks --gates

intutic start ​

Run the proxy in the foreground, standalone — no account or control plane needed.

bash
intutic start [options]

Options:

OptionDescriptionDefault
--port <port>Port the proxy listens onThe port of INTUTIC_PROXY_URL, else 4000
--valkey-port <port>Local Valkey port to use or start6379
--upstream-url <url>Upstream LLM provider base URL, passed to the proxy as UPSTREAM_URL(proxy default)
--no-gatesNeither refresh the local gates nor watch .intutic/sopsRefresh and watch

What it does:

  1. Local gates. On a machine with no login whose gates intutic gates install installed, refreshes them before the proxy starts (the gate scripts, the rules files from .intutic/sops/ and the policy snapshot), and again whenever .intutic/sops/ changes while the proxy runs. The refresh never writes routing. Each refresh also deletes the decide logs in ~/.intutic/logs/ (decide-<date>.jsonl, and the decide-state-<date>.jsonl files --log-state writes) more than 30 days old. With no gates installed, one line names the recorded harnesses that have none. --no-gates skips this step.
  2. Decide engine (background). When the policy snapshot carries decide rules and an engine is configured (intutic decide configure, or INTUTIC_DECIDE_MODEL), it loads the engine's model and keeps it loaded for 8 hours (Ollama's keep_alive, with the logprobs adapter only), then runs the known-answer canary and stores the result in ~/.intutic/decide/canary.json, where the gates read it. This runs beside the proxy's start-up: each result is printed, and none stops or delays the proxy.
  3. Valkey (best-effort). Checks for a Valkey or Redis on 127.0.0.1:<valkey-port>. If none is listening, it tries, in order: starting an intutic-valkey Docker container (valkey/valkey:8-alpine), then valkey-server or redis-server from PATH. If none of these works, it warns and continues in standalone mode: routing, policies, DLP, and local spend caps all still work; bandit learning persists to ~/.intutic, and the response cache lasts only as long as the process.
  4. Proxy binary. Runs the version-matched binary in ~/.intutic/bin/ if it is there, otherwise intutic-proxy from PATH. If neither exists it prints npm install -g @intutic/proxy and exits with status 1.
  5. Proxy environment. Starts the proxy with your environment plus:
    • PORT set to --port
    • with Valkey running: VALKEY_URL, taken from your environment if set, otherwise redis://127.0.0.1:<valkey-port>
    • without Valkey: INTUTIC_STANDALONE=1 — unless CONTROL_PLANE_URL is set in your environment. That marks a managed deployment, where the proxy requires Valkey and refuses to start without it; intutic start leaves that decision to the proxy.
    • UPSTREAM_URL when --upstream-url is given

Ctrl+C stops the proxy, and the command exits with the proxy's exit code.

Examples:

bash
intutic start
export ANTHROPIC_BASE_URL=http://localhost:4000

# Different port, and a Valkey on 6380
intutic start --port 8080 --valkey-port 6380

intutic gates install ​

Install the tool-call gate and rules file for each harness intutic init recorded, from this machine alone — no account or control plane needed.

bash
intutic gates install [options]

Options:

OptionDescription
--harness <id>Only this harness, for example cursor. It must be recorded in ~/.intutic/config.json, unless --add is passed too
--addWith --harness: record the harness in ~/.intutic/config.json first
--routeAlso point each harness's LLM traffic at the local proxy (http://127.0.0.1:4000, or the port of INTUTIC_PROXY_URL). The proxy must then be running, for example as a service with intutic daemon install --proxy, or the harnesses cannot reach their model
--dry-runPrint what would be written, and write nothing
--workspace <path>The workspace to write into. Default: the one intutic init recorded

What it writes, for every recorded harness (one with --harness):

  1. The gate. The same tool-call gate intutic connect installs, registered where the harness reads it (.claude/settings.json for Claude Code, Cursor's hooks.json, and so on). Your own hooks and settings stay. Every gate enforces the built-in protections, such as refusing an agent's attempt to remove or unlock Intutic's own files.
  2. The policy snapshot (~/.intutic/hooks/policy-snapshot.rules and .json) every gate reads: the destructive-command and skill-directory tiers, and from .intutic/sops/ each review_before: token, the lane holds of each closed_lanes:, the decide: rules (with the pins intutic decide eval wrote), and the rule records: each qualified requires_before: ([ok]), scope_paths: under scope_paths_mode: enforce, and plan_approval:. A SOP with roles: contributes no rule records or lane holds, since a gate knows no role. With no control plane to approve a hold, a review_before: token or a lane hold is refused outright, with a message saying so, rather than held, and plan_approval: refuses every gated call that is not a read (PLAN_NOT_APPROVED). The snapshot names no workspace and is marked source: local.
  3. The rules files from the SOPs in .intutic/sops/, into each harness's own file (see Where rule sets go). A harness no SOP targets gets no rules file.
  4. The bundled agent skills, once per workspace: the Kitkat skill (.agents/skills/intutic-governance-kitkat/SKILL.md), which tells an agent what each refusal code means and what to do about it, and the Rule Author skill (.agents/skills/intutic-rule-author/SKILL.md), as intutic connect writes them. Only a missing one is written; a copy already there is never overwritten. intutic disconnect deletes the copies it wrote, unless you have edited them.

It also blanks the API key an earlier intutic connect may have left in ~/.intutic/env/runtime.env, so no gate posts events to that control plane, and moves .intutic/events/hook-events.jsonl aside to hook-events.jsonl.1 once it passes 10 MB: with no control plane, nothing drains it.

Not written: proxy routing (unless --route), MCP server wrapping, and anything sent anywhere: it makes no network call. .env.intutic, which Codex and the SDK frameworks read only when you source it, is still written for a harness a SOP targets. With --route, Windsurf's traffic goes through the proxy's TLS interception, which needs the Intutic CA (~/.intutic/ca.crt, created when the proxy first runs) trusted; gates install does not trust it for you.

It prints each file written and the gate file of each harness, and ends with Undo with intutic disconnect. Re-run it after editing .intutic/sops/, or keep intutic start running, which refreshes the gates when the SOPs change.

Refused, with exit status 1, on a machine with a login (intutic connect installs and refreshes the gates there; run intutic disconnect first to switch to local gates), and before intutic init.

Examples:

bash
intutic gates install

# What it would write, for Cursor only
intutic gates install --harness cursor --dry-run

# Also route the harnesses through a proxy that runs as a service
intutic daemon install --proxy
intutic gates install --route

When the SOPs carry decide: rules, it also prints how many were compiled and how many are stamped enforce, names any decide: line that does not read by file and line number, and warns when more than 4 rules name one tool.


intutic decide test <rule> ​

Ask a decide rule's questions about one call, with the engine intutic decide configure set up, and print each answer's probability against its band, the when value and the outcome the rule would reach if it enforced. Decide rules walks through writing, evaluating and enforcing a rule with these commands.

bash
intutic decide test <rule> --state <file> [options]

<rule> is the rule's ref (local:data.md#prod-data-export), its id when only one local rule has it, or <file>#<id>.

Options:

OptionDescription
--state <file>A JSON file with the call: {"tool", "toolInput", "cwd"?}. A lastUserTurn in it is not sent: context: ["last_user_turn"] is reserved in 3.0, and no gate supplies the user's last turn. For an on: response rule, the response instead: {"response"}, asked in the gateway's layout (the SOP's text, then the response) and held to the engine's response limit (32,768 bytes unless INTUTIC_DECIDE_MAX_RESPONSE_STATE_BYTES says otherwise)
--jsonPrint the result as JSON
--log-stateAlso write the exact state sent to ~/.intutic/logs/decide-state-<date>.jsonl
--workspace <dir>The workspace whose .intutic/sops to read. Default: the recorded one, else the current directory

intutic decide eval <rule> ​

Measure a decide rule on labelled calls. A rule enforces only on a model a passing pre-registered eval pinned, so this is how a rule leaves shadow.

bash
intutic decide eval <rule> --labels <file.jsonl> [--preregister <file>] [--adversarial]

Each labels line is one call: {"id", "label": "refuse" | "allow", "tool", "toolInput", "cwd"?} (violation and clean read as refuse and allow). For an on: response rule each line is one response, {"id", "label", "response"}, asked about in the gateway's layout and under its response limit; a response over the limit counts as an escalation. Recall counts a refuse case as caught when it is refused or escalated; false alarms count allow cases refused. A case the engine could not answer counts as an escalation, never as an allow.

  • Without --preregister, it fits one band on the dev split (the cases whose id hashes to a multiple of 3), choosing the band with no automatic error and the fewest escalations, then reports recall, false alarms, escalation and each question's AUC on the rest. It writes a run report and no pin.
  • --preregister <file> naming a file that does not exist writes the pre-registration there: the rule hash, the model digest, the bands and the pass marks, before any label is read. Nothing else happens.
  • --preregister <file> naming that file evaluates every labelled case at the rule's own bands, with the adversarial families added. It passes when the pre-registration matches the rule and the model, the labels file was not used by an earlier pre-registered run of this rule, there are at least 20 cases with 5 to refuse, recall is at least 95%, false alarms at most 10%, escalation at most 40%, and planted approvals are caught at least 90% of the time. A pass writes the pin (~/.intutic/decide/evals/<ruleHash>/<digest>.json) and rewrites the local policy snapshot. A failed run exits with status 1. On a logged-in machine the pin is still written, but the policy snapshot there takes its decide rules and pins only from the control plane, so the pin applies to local use on a machine with no login, and the command says so.

--adversarial adds three fixed families to the refuse cases: five planted approvals appended to the arguments, five instructions aimed at the model, and paraphrases of the command (an environment variable for the program, quoting, a line split, reordered flags, long and short options). For a response rule the approvals and instructions are appended to the response, with no paraphrase. No model writes a case. Each family is reported apart.

Options:

OptionDescription
--labels <file>The labelled calls, JSONL
--preregister <file>Write the pre-registration when the file is absent (reading no label); evaluate against it when present
--adversarialAdd the adversarial families (always on under a pre-registration)
--calibration <id>With --preregister, when writing the pre-registration: pre-register the band and combiner of a candidate calibration of this rule that a control plane holds, fitted on the engine's model, and register the run as that calibration's companion. Needs a control plane: refused without a login
--jsonPrint the run report as JSON
--log-stateAlso write each exact state sent to ~/.intutic/logs/decide-state-<date>.jsonl
--workspace <dir>The workspace whose .intutic/sops to read

Examples:

bash
intutic decide eval prod-data-export --labels dev.jsonl
intutic decide eval prod-data-export --preregister prereg.json
intutic decide eval prod-data-export --labels fresh.jsonl --preregister prereg.json

intutic decide calibrate <rule> ​

Fit a logistic combiner over the rule's questions (L2, λ = 1) and a band on its output to labelled calls, and save them as a candidate in ~/.intutic/decide/evals/<ruleHash>/candidates/. The next intutic decide eval --preregister for that model carries the candidate; once that eval passes, the combiner replaces when for the model it was fitted on.

OptionDescription
--labels <file>The labelled calls, as for intutic decide eval
--jsonPrint the candidate as JSON
--workspace <dir>The workspace whose .intutic/sops to read

intutic decide models ​

The models the pre-registered bake-off measured, and which passed. No laptop-sized model passed, so none is validated for a laptop and the engine has no default model: bring a self-hosted model and validate it on your own labels with intutic decide eval. Nothing is downloaded.

OptionDescription
--jsonPrint as JSON

intutic decide check ​

The entry the shell gates (Gemini CLI, Goose, Hermes, OpenHands) and the n8n gate call for a tool call that a decide rule names. It reads one JSON request from stdin and writes one JSON line, with exit status 0:

bash
echo '{"v":1,"harness":"goose","tool":"Bash","toolInput":{"command":"pg_dump -h prod"},"cwd":"/repo","sessionId":"s1","budgetMs":3400,"lastUserTurn":null}' \
  | intutic decide check --stdin
# {"v":1,"outcome":"refuse","code":"DECIDE_REFUSED","ruleId":"decide.local:data.md#prod-data-export","reason":"…"}

outcome is allow, refuse or escalate; code is null, DECIDE_REFUSED, DECIDE_ESCALATED or GOVERNANCE_UNAVAILABLE. A shadow rule never refuses. An enforcing rule refuses with GOVERNANCE_UNAVAILABLE when the engine is unavailable (an error, a timeout, a failed canary), as does input that does not read and a decide record that does not decode. An enforcing rule the engine cannot answer inside budgetMs escalates without being asked. Every evaluated call is written to the decide log, ~/.intutic/logs/decide-<date>.jsonl.

OptionDescription
--stdinRead the request from stdin

intutic decide configure ​

Write ~/.intutic/decide/engine.json (mode 0600): the engine's URL, adapter and model. The engine must run on this machine or a private address, or on a host listed in INTUTIC_SELF_HOSTED_DECISION_HOSTS; hosted decision APIs are refused. The key, if the engine needs one, is read from INTUTIC_DECIDE_API_KEY only and is never written. The INTUTIC_DECIDE_* variables override the file (see Configuration).

The hook gates refuse this command when an agent runs it: run it yourself.

OptionDescription
--url <url>The engine's base URL. Default http://127.0.0.1:11434 (Ollama)
--adapter <adapter>logprobs (Ollama, vLLM, llama.cpp, LM Studio), systemone or decisions. Default logprobs
--model <model>The model the engine serves. Without one the engine is not configured
--timeout-ms <ms>Per-call timeout. Default 5000
--parallel <n>Most requests in flight. Default 1 for Ollama, 8 otherwise
--structuredSend structured_outputs with logprobs requests
--no-structuredDo not send it (the default)
--jsonPrint the written configuration as JSON

intutic doctor then checks the engine and its model, runs the known-answer canary, measures the per-call p95 and names every harness whose time budget a rule cannot fit.


intutic decide disable ​

Run every decide rule on this machine as shadow (each call is logged, none is refused) until intutic decide enable. It rewrites the local policy snapshot; on a connected machine the sync daemon applies it on its next poll. A decide: line that does not read still refuses its tools.

The hook gates refuse this command when an agent runs it: run it yourself.


intutic decide enable ​

Undo intutic decide disable.


intutic decide lint ​

Read every decide: line in .intutic/sops/: each rule with its file, line, rule hash and whether a pin exists for it, each line that does not read with its error (a bare decide: line gets the hint "write one rule per line as decide: {json}"), and each tool more than 4 rules name. An on: response rule is marked as judged at the gateway. It warns about each rule declaring context: ["last_user_turn"], which is reserved and not supplied in 3.0; intutic gates install and intutic doctor report it too. Exits with status 1 when a line does not read; the warnings do not change the status.

OptionDescription
--jsonPrint as JSON
--workspace <dir>The workspace whose .intutic/sops to read

intutic setup ​

Guided setup wizard — detect harnesses, configure a provider credential, and verify it, in one interactive flow. It is the interactive counterpart of intutic init, not a replacement: this command always prompts, while init asks only whether to install the Git hooks and the gates, and never without a terminal, so it stays safe for CI. See the cohort wizard guide for a full narrative walkthrough of every step.

bash
intutic setup [options]

Options:

OptionDescription
--devUse local control plane (http://localhost:3001)

What it does:

  1. Detects harnesses in the current workspace (same detection intutic init uses)
  2. Asks whether to configure a provider against a connected workspace or locally (no control plane — writes a .intutic.env file instead)
  3. Picks a provider from the registry (intutic credentials list shows the same set) and prompts for its credential fields
  4. Verifies the credential against the provider's own API before saving — a 401/403 asks for confirmation before proceeding anyway; a rate-limited or unreachable response is reported but does not block
  5. Saves the credential (PUT /api/v1/workspace/provider-credentials/:provider, same route intutic credentials set hits) or writes the local env file

There is no judge-model step: judges run only on self-hosted models, so a workspace has no judge model to choose.

Examples:

bash
# Connected to Intutic (requires `intutic login` first)
intutic setup

# Against a local control plane
intutic setup --dev

intutic status ​

Show workspace status — auth, harnesses, sync state.

bash
intutic status

No options. Displays:

  • Current authentication state: email, workspace, and the control plane commands use (see Choosing a control plane)
  • The workspace root, dev mode and config version recorded by intutic init
  • The harnesses recorded by intutic init, by name
  • Gates: installed locally (by intutic gates install), installed by intutic connect, or none
  • Sync state: last sync timestamp and the number of tracked files, and whether the sync daemon is running
  • Running agent processes, with a warning when a recorded harness is running but the sync daemon is not

intutic doctor ​

Diagnose workspace health — proxy, auth, daemon, configs, logs, Valkey, CA trust, policy snapshot, gates, decide.

bash
intutic doctor

No options. Runs these checks in order, each printing ✓ or ✗ plus a one-line remediation on failure:

  1. Proxy reachable (http://127.0.0.1:4000/health, or the port of INTUTIC_PROXY_URL)
  2. Control plane auth (the stored credentials against /api/v1/auth/me)
  3. Sync daemon running (PID file or process scan)
  4. Harness config files intact (SHA-256 against <workspaceRoot>/.intutic/integrity.json)
  5. Daemon log readable (~/.intutic/logs/sync-daemon.log, then the system-service log, then the legacy ~/.intutic/daemon.log)
  6. Valkey reachable (TCP probe on 127.0.0.1:6379)
  7. CA cert trust (~/.intutic/ca.crt plus the OS trust store)
  8. Policy snapshot present, valid, non-empty and fresh (~/.intutic/hooks/policy-snapshot.rules)
  9. Local gates, on a machine with no login: a gate file for each recorded harness that has one
  10. Plan approval, only when a SOP sets plan_approval:: with no control plane connected it fails, since every gated call that is not a read is refused with PLAN_NOT_APPROVED; on a connected machine it fails until the daemon has written a fresh approved-plans cache (~/.intutic/hooks/approved-plans.jsonl)
  11. Cisco skill scanner on PATH (optional; never fails)
  12. Decide, always. With no decide rules in the snapshot and no engine configured it prints one passing line, ✓ Decide — no decide rules and no engine configured. Otherwise: the engine and its model (with the digest, and a note when the server cannot report a weights digest), the known-answer canary (cached in ~/.intutic/decide/canary.json), the per-call p95 of 20 warm calls (stored in ~/.intutic/decide/engine.json), and every harness and rule pair whose time budget the rule cannot fit, for example "prod-data-export cannot be evaluated within windsurf's 2,300 ms (estimated 3,100 ms)". Such a rule escalates there instead of being asked

Checks 2–5 need a control plane. On a machine with no login they are skipped with one note, the proxy and CA-trust remediations point at intutic start, and checks 8 and 9 look at what intutic gates install wrote and point at it to fix what is missing.

See intutic doctor for what each check verifies and how to fix it.


intutic disconnect ​

Undo intutic connect or intutic gates install on this machine: put every harness config they changed back the way it was, remove the gates and the background services, and log out.

The hook gates refuse this command when an agent runs it: run it yourself.

bash
intutic disconnect [options]

Options:

OptionDescription
--harness <id>Disconnect one harness only, for example cursor. The login, the services and the other harnesses stay.
--dry-runPrint exactly what would change, and change nothing
--keep-loginKeep the stored credentials

What it undoes, for every harness (one with --harness):

  • Rules files of Intutic's own (.claude/rules/intutic-governance.md, .cursor/rules/intutic-governance.mdc, .windsurf/rules/intutic-governance.md, .clinerules/intutic-governance.md, .continue/rules/intutic-governance.md, .openhands/microagents/intutic-governance.md, .intutic/aider-sops.md) and .env.intutic: deleted, or the file you had before at that path comes back.
  • Rules sections in files you also write (AGENTS.md, GEMINI.md, .github/copilot-instructions.md, .goosehints, and the AGENTS.md of OpenClaw's agent workspace): the section between the INTUTIC:RULES markers is taken out, and the file comes back byte for byte when you did not edit it, or is deleted if connect created it. See Where rule sets go.
  • Rules files earlier versions wrote whole (CLAUDE.md, .cursorrules, .windsurfrules, .roorules, AGENTS.md): the file you had before comes back, or the file is deleted if connect created it.
  • Hook registrations in each harness's settings (.claude/settings.json, Cursor's and Windsurf's hooks.json, and the rest): only the entries that run an Intutic gate are removed. The gate scripts are deleted.
  • Proxy routing: base URLs and proxy settings connect pointed at the proxy (Codex openai_base_url, Continue apiBase, Goose OPENAI_HOST/ANTHROPIC_HOST, Grok base_url, Pi and OpenHands base URLs, Aider openai-api-base, Windsurf http.proxy, the JetBrains IDE proxy for the Windsurf plugin, dsh's llm-deepseek route) go back to the values they had.
  • MCP servers: each server connect wrapped gets its original entry back, every key included; the intutic server connect added is removed; and the copies of approved .mcp.json servers connect added to ~/.claude.json are removed.
  • What connect replaced or removed comes back: the Claude Code permissions.deny rules connect replaced, and Aider's test-cmd, lint-cmd, auto-test and auto-lint.
  • Agent skills (without --harness): the Kitkat and Rule Author skills connect wrote into .agents/skills/, unless you have edited them. A copy that was there before connect, or that an earlier version of connect wrote, stays.

Without --harness it also removes the services intutic daemon install set up for your user (a system-wide one is listed with the command that removes it), the Intutic CA certificate connect trusted (in the macOS login keychain, or connect's intutic-connect-ca.crt in the Linux system trust store, which needs root: run as a user, disconnect prints the sudo rm and bundle-rebuild commands instead), the intutic-valkey Docker container connect started, the gate caches in ~/.intutic/hooks/ (the policy snapshot with its verified copy, the approved bypasses and the egress policy), ~/.intutic/env/runtime.env (the copy of the API key the gates read) and, unless --keep-login, the stored credentials. It resets the synced config version, so a later intutic connect writes everything again.

How it knows what you had: before connect first writes a file, it keeps a copy of it, in .intutic/originals/ for files in the workspace and ~/.intutic/originals/ for the rest (owner-only, and ignored by git). A file you have not changed since is restored byte for byte. In one you have changed, only Intutic's entries are taken out and your edits stay. A file connect writes whole that you edited is left as it is, and listed.

Files from an earlier connect: versions before this one kept no copies. For their files, disconnect removes what it can recognise as Intutic's: the generated header, entries that run an Intutic gate, wrapped MCP servers (their arguments carry the original command), and URLs on the proxy connect used. A generated file git does not track is deleted; where git has a committed version that is not generated, that version comes back. A setting connect overwrote is removed rather than restored, because its earlier value is unknown, and the output says so. Deny rules connect added to permissions.deny cannot be told apart from yours, and are listed for you to review.

Left in place: your SOPs in .intutic/sops/, Intutic's own state in ~/.intutic/ (configuration, logs, events, the downloaded proxy), <file>.drift-backup copies (they hold edits connect reverted), and a valkey-server or redis-server connect started outside Docker. Git hooks from intutic init --git-hooks live in .git/hooks/, and variables from intutic env persist are removed with intutic env clear.

The control plane is told (with a login; with none there is no control plane, and nothing is sent): before it removes the credentials, a real run reports the disconnect (POST /api/v1/devices/disconnect, with the machine's fingerprint and the harnesses), so the control plane stops expecting the machine's gates instead of alerting that they went silent, the devices list and the AI inventory show the machine or harness as disconnected rather than stale or newly ungoverned, and the disconnect is recorded for SIEM export (device_disconnects). If the control plane cannot be reached within five seconds, the disconnect goes ahead and says so. Running intutic connect again reconnects.

While connect runs: a running intutic connect would write everything straight back. A real run stops the services first, then exits with status 1 before changing any file if an intutic connect you started yourself is still running. --dry-run only warns.

One harness: --harness leaves a file another connected harness also writes (AGENTS.md is shared by Codex, Muse Code, Grok Build, OpenCode, Pi, Hermes, Roo Code and dsh; .env.intutic by Codex and the SDK frameworks). It removes the harness from ~/.intutic/config.json, so connect stops writing its config and stops wrapping its MCP servers; run intutic init to manage it again.

Examples:

bash
# See what would change
intutic disconnect --dry-run

# Disconnect everything, keep the login
intutic disconnect --keep-login

# Stop governing Cursor only
intutic disconnect --harness cursor

intutic traces list ​

List execution traces, from the control plane when you are logged in or from the local proxy's trace log when you are not.

bash
intutic traces list [options]

Options:

OptionDescriptionDefault
--limit <n>Number of traces to show (1–100 in connected mode)20
--since <duration>Time window: 30m, 24h, 7d, or an ISO 8601 timestamp24h
--action <type>Connected mode only. Filter by enforcement action: BYPASS, ENHANCE, HIJACK, KILL(all)
--verdict <type>Local mode only. Filter by verdict: allowed, killed, upstream_error, reasked, hijacked(all)
--model <name>Filter by requested model name(all)
--jsonOutput as JSON instead of a tablefalse
--devUse local control plane (http://localhost:3001)—

intutic trace list is the same command.

What it does:

The mode depends only on whether intutic login has stored credentials, not on whether intutic connect is running:

  • Connected mode (logged in) queries the control plane and shows Trace ID, Timestamp, Model, Action, Score, and Cost. --verdict is ignored. If the request fails, the command exits with status 1.
  • Local mode (not logged in) reads the proxy's daily trace files, ~/.intutic/logs/traces-YYYY-MM-DD.jsonl (%APPDATA%\intutic\logs\ on Windows), newest first, and shows Trace ID, Timestamp, Model, Verdict, and Cost. There is no compliance score locally. --model must match the requested model exactly. It warns when a day's file reached the proxy's 64 MB daily limit (later traces that day were dropped, so the count is a minimum) and when lines could not be parsed. Passing --action, or a --verdict value not in the list, exits with status 1.

Examples:

bash
# Last 20 traces from the past 24 hours
intutic traces list

# All KILL actions from the past week (connected mode)
intutic traces list --action KILL --since 7d

# Killed requests from the local log (local mode)
intutic traces list --verdict killed --since 7d

# JSON output for scripting
intutic traces list --json --limit 100

# Filter by model
intutic traces list --model claude-4-sonnet

intutic traces inspect <trace_id> ​

Show full detail of a single trace.

bash
intutic traces inspect <trace_id> [options]

Arguments:

ArgumentDescription
trace_idThe trace ID to inspect (e.g., tr_abc123)

Options:

OptionDescription
--devUse local control plane (http://localhost:3001)

Example:

bash
intutic traces inspect tr_abc123

Logged in, it returns the trace from the control plane: token counts, costs, compliance scores, anomaly data and the corrective prompt card. Not logged in, it looks the trace up in the local trace files (~/.intutic/logs/traces-*.jsonl).


intutic budget ​

Check remaining daily/monthly budget and list active loops, or watch spend live. The subcommands below set the workspace's caps and the budgets and rate limits on keys and members.

bash
intutic budget [options]
intutic budget --watch [--interval <seconds>]

Options:

OptionDescriptionDefault
--devUse local control plane (http://localhost:3001)—
--watchPrint machine-local and workspace spend continuously, one line per tick, until Ctrl+C—
--interval <seconds>Tick interval for --watch. A non-numeric or non-positive value falls back to the default.5

What it does:

Without --watch:

  • When you are logged in, prints the workspace's budget from the control plane: daily and monthly spend against their budgets with percentages, the daily cap and whether it is the workspace's own or the $100-a-day default of a workspace that never saved one, remaining budget, and an alert line when the alert threshold is exceeded.
  • Prints the local spending cap from ~/.intutic/config.json (maxDailyBudgetUsd, or max_daily_budget_usd; default $10.00).
  • Prints today's machine-local spend from the local proxy at http://127.0.0.1:4000 (or the port of INTUTIC_PROXY_URL), or a dash when the proxy is not running.
  • When you are logged in, lists every ACTIVE loop run with its token spend and budget limit.

Without a login it runs in standalone (offline) mode and prints only the local figures.

With --watch, it prints one line per tick in this shape:

[10:42:05] machine-local: $0.4210 / $10.00  |  workspace: $3.1200 / $50.00

The time is printed in your locale's format.

  • machine-local is today's spend and cap as reported by the local proxy at http://127.0.0.1:4000 (or the port of INTUTIC_PROXY_URL). (enforcement off) is appended when the proxy is not enforcing the cap; — (local proxy not running) is shown when it cannot be reached.
  • workspace is the workspace's daily spend and daily budget, refreshed on the first tick and every 6th tick after that (every 30 seconds at the default interval). It shows — (not connected) when you are not logged in or the request fails.

--watch does not list loops. It works without a login; only the workspace figure needs one.

Examples:

bash
intutic budget

# Live view, one line every 5 seconds
intutic budget --watch

# Every 2 seconds
intutic budget --watch --interval 2

intutic skill list ​

List the rule and skill files in the workspace.

bash
intutic skill list

No options.

What it does:

Looks in the workspace recorded by intutic init (~/.intutic/config.json), or the current directory when there is none, for:

  • Rule files at the workspace root: .cursorrules, CLAUDE.md, .windsurfrules, .clauderules, rules.md
  • Skill files one directory below each skill root: .agents/skills/<name>/SKILL.md and .claude/skills/<name>/SKILL.md

Prints each file found with its line count. It reads the files but does not scan their content; use intutic skill audit for that. When you are logged in, it also reports the list (paths and line counts) to the control plane. A failed report is ignored.


intutic skill audit ​

Scan rule files, skill files, and the scripts bundled with skills for leaked credentials and unsafe instructions.

bash
intutic skill audit [--sarif] [--engine <native|cisco>] [--exit-zero]

Options:

OptionDescriptionDefault
--sarifPrint the skill-file and bundled-script findings as a single SARIF 2.1.0 JSON document on stdout (for GitHub Code Scanning and other CI tools) instead of the readable report. Findings in root rule files are not in the document but still set the exit status—
--engine <engine>native runs the built-in scanner. cisco also runs Cisco's skill-scanner on each skill directory; the skill-scanner binary must be on PATH (pipx install cisco-ai-skill-scanner).native
--exit-zeroExit 0 even when the audit has findings or could not scan everything—

What it does:

It scans the workspace recorded by intutic init, or the current directory when there is none:

  1. Rule files at the workspace root (.cursorrules, CLAUDE.md, .windsurfrules, .clauderules) are checked for hardcoded Intutic virtual keys, hardcoded sk-live- secrets, recursive-delete wildcards such as rm -rf *, and curl/wget commands.
  2. Skill files (.agents/skills/<name>/SKILL.md, .claude/skills/<name>/SKILL.md) are content-scanned, whole, for prompt-injection, data-exfiltration, and malicious-code patterns. See Skill Scanning.
  3. Bundled files next to each SKILL.md (up to 3 directories deep and 40 files per skill; symlinks are skipped) are hashed (SHA-256). Shell, Python, JavaScript, TypeScript, Ruby, PowerShell, and Perl scripts up to 256 KiB are also content-scanned. Data files — .md, .markdown, .txt, .rst, .json, .jsonl, .yaml, .yml, .csv, .tsv and images (.png, .jpg, .jpeg, .gif, .webp, .svg, .ico, .bmp) — are not scripts: they are listed as not applicable and do not affect the result, unless a shebang makes one a script, which is then scanned. Any other file that is larger than the cap, unreadable, or not a recognised script is reported as unscanned, never as clean: the report names each one, and the audit does not pass.

When you are logged in, three workspace settings change the run:

SettingEffect
enableLocalSkillAuditDeleteDeletes each flagged line from the rule file or SKILL.md it was found in (bundled scripts are not changed)
ciscoSkillScannerEnabledRuns the Cisco engine without --engine cisco if skill-scanner is on PATH; if it is not, the run continues with the built-in scanner only
semanticSkillAnalysisEnabledIncludes each SKILL.md's content (its first 65,536 characters) in the report it uploads, with the SHA-256 and length of the whole file. A SKILL.md longer than that is named in a warning: the semantic judge reads only the first 65,536 characters, so the skill is reported as partially scanned and needs review. It does not change the exit status

When you are logged in, the results are also reported to the control plane; a failed report is ignored. With --sarif, nothing but the JSON document is printed. Cisco's results, when that engine ran, are added as a second run in the same document. The run's invocations entry lists each unscanned file as a warning notification, each data file as a note, and each failed Cisco run as an error notification, with executionSuccessful: false when an engine run failed.

Exit status: 1 when the audit has findings, when a file other than a data file could not be scanned, or when a Cisco engine run failed, so a CI step fails on them; 0 when everything was scanned and nothing was found, or with --exit-zero. Also 1 for an unknown --engine value, or for --engine cisco when skill-scanner is not on PATH. The report, the SARIF document and the control-plane report are all complete before the command exits.

Examples:

bash
intutic skill audit

# Upload to GitHub Code Scanning, which then decides pass/fail
intutic skill audit --sarif --exit-zero > skills.sarif

# Also run Cisco's skill-scanner
intutic skill audit --engine cisco

intutic skill scan-staged ​

Scan staged skill files for risky content before a commit, as a warning only.

bash
intutic skill scan-staged

No options.

What it does:

Lists the files staged for commit (added, copied, or modified) under .agents/skills/ and .claude/skills/, then runs the skill-content scan over the staged version of each file (what git commit will record, not what is on disk). Each finding is printed as a warning naming the file, category, and pattern.

It never blocks a commit: the exit status is always 0, findings or not. Outside a Git repository, or with nothing staged under those directories, it prints nothing.

The pre-commit hook that intutic init can install runs this after its credential scan. Unlike this command, the credential scan does refuse the commit when it finds a secret. Run intutic skill audit for the full report.


intutic policy test ​

Run dry-run WASM policy evaluation locally. For a Rego rule, use intutic rules test.

bash
intutic policy test --wasm <path> --mock <path>

Options:

OptionDescription
--wasm <path>Path to compiled WebAssembly rule binary (required)
--mock <path>Path to mock JSON request context file (required)

intutic policy compile ​

Compile an AssemblyScript rule to WASM (wraps asc).

bash
intutic policy compile [options]

Options:

OptionDescriptionDefault
--src <path>Rule source entry fileassembly/index.ts
--out <path>Output .wasm pathbuild/rule.wasm
--debugInclude debug info and source mapsfalse

What it does: Shells out to npx --no-install asc <src> -o <out> --optimize --exportRuntime, creating the output directory if needed. With --debug it also passes --debug --sourceMap. If asc is not available, install it with pnpm add -D assemblyscript assemblyscript-json.


intutic policy install ​

Validate and install a compiled WASM rule, native or Rego, into the local proxy rules dir.

bash
intutic policy install --wasm <path> [options]

Options:

OptionDescriptionDefault
--wasm <path>Path to compiled WebAssembly rule binary (required)—
--name <name>Rule name(the file name)
--priority <NN>Evaluation priority — lower runs first100

What it does:

  1. Instantiates the rule and evaluates it against a built-in allow-mock context — a rule that fails to instantiate or evaluate, or returns a code other than 0, 1, 2 or 3, is not installed (2 installs with a deprecation warning: the proxy treats it as a block). A Rego rule is loaded and evaluated through the Rego host instead, and refused if a proxy could not run it
  2. Writes it as {priority}_{name}.wasm into the local rules dir — INTUTIC_WASM_DIR if set, otherwise ~/.intutic/wasm
  3. Prints the destination path, priority, and SHA-256 of the installed binary

The proxy picks up local rule changes within ~5s on the next request. If your proxy config.yaml sets intutic_settings.wasm_local_dir, make sure it matches this path (or set INTUTIC_WASM_DIR for both).


intutic policy list-local ​

List WASM rules installed in the local proxy rules dir.

bash
intutic policy list-local

No options. For each .wasm file in the local rules dir (INTUTIC_WASM_DIR, defaulting to ~/.intutic/wasm) it prints the rule name, priority, size, mtime, and a SHA-256 prefix.


intutic rules build ​

Compile a Rego policy to a rule with OPA, and package it with the metadata the proxies read.

bash
intutic rules build --rego <path> --entrypoint <package/rule> [options]

Options:

OptionDescriptionDefault
--rego <path>Rego file or directory (required)—
--entrypoint <package/rule>The rule to evaluate, e.g. intutic/shell/deny (required)—
--risk-tier <tier>Default risk tier for the rule's decisions: low, medium, high or critical(none)
--out <path>Output .wasm pathbuild/<entrypoint>.wasm, with each character other than a letter, digit, _ or - as _ (build/intutic_shell_deny.wasm)

What it does:

  1. Runs opa build -t wasm -e <entrypoint> — OPA must be on the PATH, or set INTUTIC_OPA_BIN; without it the command says how to install it
  2. Takes policy.wasm from the bundle and appends an intutic.rule section with the entrypoint, the ABI (opa) and the risk tier
  3. Loads it as the proxies will and refuses one they would refuse, such as a policy needing a builtin Intutic does not provide, which it names
  4. Writes the module and prints its size and SHA-256

Install the result with intutic policy install. See Rego policies.


intutic rules test ​

Evaluate a Rego rule against sample inputs locally, through the same Rego host the proxies use.

bash
intutic rules test <module> --input <file...>

Options:

OptionDescription
--input <file...>JSON file(s), each holding one input document or an array of {"name", "input", "expect"} cases (required)

Prints each case's decision (ALLOW, DENY, HOLD or REASK), reason and risk tier. expect is optional, and one of allow, deny, hold or reask in lowercase; the command exits 1 when a case gets a decision other than the one it expects, or when evaluation fails. The rule runs under the proxies' instruction budget, so a rule that would run out of it in the proxy fails here too. A native rule is refused, with a pointer to intutic policy test.


intutic exec ​

Execute a command wrapped with Intutic proxy environment variables.

bash
intutic exec -- <command> [args...]
intutic exec --sandbox -- <command> [args...]

Arguments:

ArgumentDescription
command...Command and arguments to execute (e.g. -- claude)

Options:

OptionDescription
--sandbox [kind]Run the agent in an isolated sandbox instead of directly on the host. kind is oci (default) or firecracker. See Sandboxed Execution for what each backend actually isolates and requires.
--sandbox-image <image>Sandbox image — must contain the agent, nftables, and capsh. Default: intutic/sandbox:<CLI version>, built locally from the Dockerfile shipped with the CLI on first use; it has no agent, so extend it (Sandboxed Execution). intutic/sandbox:<CLI version>-node adds Node.js and npm, the base for Node agents such as Claude Code, and is built on first use the same way.
--sandbox-memory <size>Sandbox memory cap, e.g. 2g. Default: 2g.
--sandbox-cpus <n>Sandbox CPU cap. Default: 2.
--sandbox-pids <n>Sandbox max process count. Default: 512.
--sandbox-allow <cidrs>Comma-separated extra destination CIDRs the sandbox may reach beyond the proxy and DNS.

If the workspace's sandbox requirement is set to Require (Settings → Security → Sandboxed Execution) and --sandbox is omitted, the command refuses to run rather than executing ungoverned on the host.

What it does: Injects the proxy environment into the child process, then spawns it with inherited stdio and exits with the child's exit code. The injected variables cover the competing SDK conventions:

VariableConsumers
OPENAI_API_BASELiteLLM, LangChain, CrewAI, ADK, Aider
OPENAI_BASE_URLOpenAI Python SDK v1+, Pydantic-AI, Agent SDK
OPENAI_API_BASE_URLOpenWebUI
OPENAI_HOSTGoose (host only, no /v1)
ANTHROPIC_BASE_URLClaude Code, Anthropic SDK (host only)
OPENAI_API_KEY / ANTHROPIC_API_KEY / INTUTIC_API_KEYThe workspace API key, when you are logged in
INTUTIC_GRAPH_ID / INTUTIC_NODE_ID / INTUTIC_PARENT_ID / INTUTIC_DEPTHA nested intutic exec and the Clawde SDK: the agent graph this agent belongs to
ANTHROPIC_CUSTOM_HEADERSClaude Code: the same identity as X-Intutic-* headers, after any headers already set

The base-URL variables point at the local proxy, http://localhost:4000, or at INTUTIC_PROXY_URL when it is set; inside --sandbox they point at the host the proxy runs on. Each carries the agent-graph identity as a path prefix (/_i/<graph>/<node>/<parent>/<depth>), which the proxy strips before routing; the OPENAI_* URLs other than OPENAI_HOST end in /v1.

Without a login (open core, with intutic start running) only the base URLs change: the agent keeps the provider keys already in its environment, and the standalone proxy passes them through to the provider. With --sandbox, OPENAI_API_KEY and ANTHROPIC_API_KEY are handed into the container for the same reason.

Logged in, the key variables are set to the workspace key, the workspace's sandbox requirement applies, and a sandboxed run is recorded as a session.

Examples:

bash
intutic exec -- claude
intutic exec -- aider --model openai/gpt-4o
intutic exec -- python my_agent.py

intutic chaos run ​

Run a chaos experiment: the agent with a known fault injected, in the sandbox, scored. See Chaos Engineering for Agents.

bash
intutic chaos run <file> [--sandbox-image <image>] [--out <report.json>] [--keep]

Arguments:

ArgumentDescription
fileExperiment file (YAML)

Options:

OptionDescription
--sandbox-image <image>Sandbox image; must contain the agent. Overrides the experiment's sandbox_image. Default: the intutic exec --sandbox image. For a Node agent, extend intutic/sandbox:<CLI version>-node (Bring your agent).
--out <report.json>Where to write the JSON report. Default: intutic-chaos/report-<name>-<timestamp>.json under the OS temp directory. The path is printed.
--keepKeep each repetition's git worktree instead of removing it.

Refuses to start without a clean git working tree (each repetition is a fresh worktree of HEAD) or without an available sandbox backend; it never runs the agent on the host. Runs repeat baseline repetitions, then repeat faulted ones, each behind a dedicated proxy on a free port. Each worktree gets the project's generated gates, its Claude Code, Codex and Cursor project hook settings and the policy snapshot, with the project's path rewritten to /work; the output names what was carried in and warns when the project has no gates (Bring your agent). Exits 0 when the run is scored, 1 when it was aborted or refused to start (or the file is invalid), 2 when the run is invalid (the baseline failed verify).


intutic chaos validate ​

Check a chaos experiment file against the experiment schema and print each error with the path of the field.

bash
intutic chaos validate <file>
ArgumentDescription
fileExperiment file (YAML)

Exits 1 when the file is invalid.


intutic chaos list ​

Print the fault catalog: each fault, the component that injects it (proxy, MCP proxy or gate) and its safety class (fail-safe or mutating), and where the example experiments are.

bash
intutic chaos list

intutic env persist ​

Persist ANTHROPIC_BASE_URL and OPENAI_BASE_URL at the OS level so new terminals and applications reach the proxy.

bash
intutic env persist [--proxy-url <url>]

Options:

OptionDescriptionDefault
--proxy-url <url>Proxy base URL both variables are set tohttp://localhost:4000

What it does:

Sets exactly two variables, ANTHROPIC_BASE_URL and OPENAI_BASE_URL, both to --proxy-url. It sets no API keys and none of the other variables intutic exec injects. The mechanism depends on the OS:

OSMechanismScope
macOSlaunchctl setenvEvery application launched afterwards, including GUI apps, until you log out or restart
Linux (as root)Writes KEY="<url>" lines to /etc/environment, replacing any earlier lines for the two variablesSystem
Linux (otherwise)Appends export KEY="<url>" lines to ~/.bashrc, each tagged with an # intutic-env-<KEY> marker; a re-run replaces the earlier linesUser
WindowssetxUser

Terminals that are already open keep their old environment until you restart them or re-source your shell profile. On any other platform the command exits with status 1.

This is opt-in on purpose: on macOS it reaches every GUI application you start afterwards. To route a single command instead, use intutic exec.

Examples:

bash
intutic env persist
intutic env persist --proxy-url http://localhost:8080

intutic env clear ​

Remove the variables written by intutic env persist.

bash
intutic env clear

No options.

What it does:

Removes ANTHROPIC_BASE_URL and OPENAI_BASE_URL: launchctl unsetenv on macOS, and the values in HKCU\Environment on Windows. On Linux it deletes the marked lines from ~/.bashrc, leaving the rest of the file exactly as it was, and, when run as root, the two variables' lines from /etc/environment. Running it when nothing is set is not an error. Already-open terminals keep the old values until restarted.


intutic enforce ​

Manage the mandatory default-deny egress firewall — makes the governing proxy non-optional by dropping outbound traffic to everything except the proxy, DNS, and operator-declared infrastructure. Where Network Egress Control governs traffic the proxy sees, intutic enforce closes the gap where an agent simply doesn't route through the proxy at all: with it applied, there is no other way out.

bash
intutic enforce <action> [options]

Actions:

ActionPrivilegeWhat it does
generateNonePrints the platform firewall ruleset without applying it.
applyRootApplies the default-deny egress firewall. All egress except the proxy, DNS, and --allow infrastructure is dropped.
removeRootRemoves the Intutic egress firewall.
statusNoneReports whether the egress firewall is currently applied.
report CloudNone (needs intutic login)Reports the locally recorded enforcement state (firewall, CA-trust, system-hooks posture) to the control plane. For when apply/remove ran elevated and couldn't reach stored credentials.

Options (apply/remove/status/generate):

OptionDescription
--port <port>The proxy's listener port to permit. Default: 4000; neither PORT nor INTUTIC_PROXY_URL is read, so pass it when the proxy listens elsewhere.
--uid <uid>uid the proxy runs as, exempted from the deny. Defaults to you: the user the command runs as, or under sudo the user who invoked sudo (SUDO_UID), not root. Pass it when the proxy runs as a different account.
--allow <cidrs>Comma-separated extra destinations to permit (control plane, private registries, etc.), each an IP address or CIDR block. A hostname is refused before anything is applied: resolve it to its address range first.
--no-dnsAlso deny outbound DNS — only if a local resolver serves the host.
--platform <os>Target ruleset platform: linux, macos, or windows. Defaults to the current OS.

What it does:

Implemented in the intutic-proxy binary's own enforce subcommand (platform-aware: nftables or iptables on Linux, pf on macOS); the CLI command is a thin, discoverable wrapper around it. apply/remove change the host firewall and need root — re-run with sudo if it fails with a permission error. After a successful apply/remove, the CLI re-queries status while still elevated and best-effort reports the result to the control plane, so an admin can see whether enforcement is actually active on a given machine without SSHing into it.

Examples:

bash
# See what would be applied, without changing anything
intutic enforce generate

# Apply, permitting an internal network and a package registry's address range too
sudo intutic enforce apply --allow 10.0.0.0/8,203.0.113.0/24

# Check whether it's currently active
intutic enforce status

# Remove it
sudo intutic enforce remove

intutic daemon install ​

Install sync-daemon as a system service (auto-starts on login, restarts on any exit).

bash
intutic daemon install --workspace-id <id> --api-key <key> [options]
intutic daemon install --proxy [--port <port>] [--valkey-url <url>] [--upstream-url <url>]

Also available as the top-level shortcut intutic install-daemon, with the same options and defaults.

Options:

OptionDescriptionDefault
--workspace-id <id>Workspace ID, e.g. wk_xxxx (required unless --proxy)—
--api-key <key>Workspace API key, e.g. vk_xxxx (required unless --proxy)—
--control-plane-url <url> CloudControl plane the sync-daemon or MCP daemon connects to, written into the serviceResolved as in Choosing a control plane: INTUTIC_CONTROL_PLANE_URL (or INTUTIC_DEV=1), then a workspace initialized with intutic init --dev, then the URL saved by intutic login; this release has no default
--binary-path <path>Path to the intutic CLI binary; with --proxy, an absolute path to intutic-proxy(current process; with --proxy, the launcher's pinned binary, then intutic-proxy on PATH)
--dry-runPrint what would be done without writing files—
--systemInstall as a system-level service (LaunchDaemon on macOS, systemd system unit on Linux)—
--mcpInstall the MCP proxy daemon instead of the sync-daemon—
--proxyInstall the standalone intutic-proxy binary as a service — no workspace or key needed—
--port <port>With --proxy: proxy listen port (PORT)The port of INTUTIC_PROXY_URL, else 4000
--valkey-url <url>With --proxy: Valkey to attach to (VALKEY_URL); omitted, the unit sets INTUTIC_STANDALONE=1—
--upstream-url <url>With --proxy: upstream LLM provider base URL (UPSTREAM_URL)—

Service files written:

  • macOS: ~/Library/LaunchAgents/ai.intutic.sync-daemon.plist (KeepAlive: true)
  • Linux: ~/.config/systemd/user/intutic-sync-daemon.service (Restart=always)
  • With --proxy: ~/Library/LaunchAgents/ai.intutic.proxy.plist / ~/.config/systemd/user/intutic-proxy.service, running the binary with the same environment intutic start sets. The binary path must be absolute — neither launchd nor systemd searches PATH.

Because the service restarts on any exit, stopping it requires intutic daemon stop, intutic daemon uninstall, or launchctl unload.


intutic daemon uninstall ​

Remove the sync-daemon system service and stop it permanently.

The hook gates refuse this command when an agent runs it: run it yourself.

bash
intutic daemon uninstall [options]

Also available as the top-level shortcut intutic uninstall-daemon, with the same options.

Options:

OptionDescription
--dry-runPrint what would be done without writing files
--systemUninstall the system-level service
--mcpUninstall the MCP proxy daemon instead of the sync-daemon
--proxyUninstall the standalone intutic-proxy service instead of the sync-daemon

intutic daemon status ​

Show sync-daemon system service status. With --proxy or --mcp, the same for the standalone proxy service or the MCP proxy daemon.

bash
intutic daemon status
intutic daemon status --proxy
intutic daemon status --mcp

Options:

OptionDescription
--proxyShow the standalone intutic-proxy service installed by daemon install --proxy instead of the sync-daemon.
--mcpShow the MCP proxy daemon instead of the sync-daemon.

intutic daemon start ​

Start and load the sync-daemon system service. With --proxy or --mcp, the same for the standalone proxy service or the MCP proxy daemon.

bash
intutic daemon start
intutic daemon start --proxy
intutic daemon start --mcp

Options:

OptionDescription
--proxyStart the standalone intutic-proxy service installed by daemon install --proxy instead of the sync-daemon.
--mcpStart the MCP proxy daemon instead of the sync-daemon.

intutic daemon stop ​

Stop and unload the sync-daemon system service. With --proxy or --mcp, the same for the standalone proxy service or the MCP proxy daemon.

The hook gates refuse this command when an agent runs it: run it yourself.

bash
intutic daemon stop
intutic daemon stop --proxy
intutic daemon stop --mcp

Options:

OptionDescription
--proxyStop the standalone intutic-proxy service installed by daemon install --proxy instead of the sync-daemon.
--mcpStop the MCP proxy daemon instead of the sync-daemon.

intutic rollback ​

List or restore file pre-images captured when a guard flagged a call and let it proceed. This is the restore half of the mechanism — the capture half runs automatically inside the generated harness hook when a warn-tier guard fires, if capture is enabled.

bash
intutic rollback              # list captured pre-images
intutic rollback --id <id>    # restore one

Options:

OptionDescription
--listList captured pre-images. The default when --id is omitted.
--id <id>Restore the named pre-image.

Capture is opt-in and narrowly scoped — set "captureRollbackPreImages": true in .intutic/config.json. It's off by default because it stores copies of flagged files locally. It only captures on the warn enforcement tier: a KILLed call never executes (nothing to revert), and a require-tier violation is refused before it runs — capture exists for the one case where a call was flagged and allowed to proceed anyway, so there's a "before" worth keeping. Bounded to 2 MiB per file and 50 retained entries.

What it does:

  • With no --id: lists every captured pre-image (id, capture time, tool, target path, byte size or "file did not exist") and prints the restore command for each.
  • With --id <id>: restores exactly that pre-image and nothing else — there is no --all and no implicit "latest". Before restoring, the current contents of the target are themselves captured as a new pre-image, so the restore is itself undoable. The restore is appended to the same .intutic/events/hook-events.jsonl log the gate writes to (tool_reverted), so the audit trail reads "flagged → allowed → reverted", not a file that silently changed back. If the pre-image's stored blob was evicted by the retention ceiling, the command refuses rather than performing a partial restore.

Examples:

bash
# See what's available to restore
intutic rollback

# Restore a specific one (id comes from the list above)
intutic rollback --id a1b2c3d4e5f60718

Environment variables ​

Environment variables the CLI, and the hook gates and proxy it sets up, read. Command-line flags take precedence where both exist.

VariableRead byEffect
INTUTIC_CONTROL_PLANE_URLEvery command that calls a control-plane APIThe control plane to use, ahead of a workspace initialized with intutic init --dev and the one saved by intutic login, and behind a --control-plane-url or --dev flag. See Choosing a control plane.
INTUTIC_DEVEvery command that calls a control-plane API1 targets the local control plane at http://localhost:3001, the same as --dev, unless INTUTIC_CONTROL_PLANE_URL is set. Any other value is ignored.
INTUTIC_PROXY_URLintutic exec, start, connect, budget, doctor, daemon install --proxy, enterprise install, and the setup output of init and connectBase URL of the local proxy, default http://localhost:4000. Its port is the one every command uses: start, connect and daemon install --proxy run the proxy there unless --port says otherwise, and budget and doctor probe it there. exec points the child process's SDK variables at it. enterprise install uses it when --proxy-url is not given. init and connect print it as your gateway endpoint (with /v1 appended). The shell's PORT is not read. intutic enforce reads neither: its --port defaults to 4000.
VALKEY_URLintutic start, intutic connectValkey/Redis the proxy uses. start passes it through only when a Valkey is reachable on --valkey-port; otherwise it uses redis://127.0.0.1:<valkey-port>. connect defaults to redis://127.0.0.1:6379.
CONTROL_PLANE_URLintutic startWhen set and no Valkey is available, start does not force standalone mode; the proxy treats the run as a managed deployment and requires Valkey. The CLI does not use it to choose a control plane.
INTUTIC_SNAPSHOT_RULESHook gates, intutic policy snapshot, intutic doctorPath of the policy snapshot file the gates enforce. Default ~/.intutic/hooks/policy-snapshot.rules. policy snapshot writes into this path's directory and always names the file policy-snapshot.rules (it warns if your path uses another name); doctor checks this path.
INTUTIC_GUARD_DISABLEHook gates1 makes the gates skip the snapshot's destructive-command rules. The built-in protections (protected paths, bypass guards) and your workspace's own SOP block rules still apply. Every gated tool call while it is set is recorded as a guards_disabled event; once intutic connect uploads those events, the control plane opens a HIGH-severity incident for each affected session.
INTUTIC_SKIP_GLOBAL_HOOKSintutic connect (Claude Code hooks)Any non-empty value stops the sync daemon from writing Intutic's hooks and deny rules into ~/.claude/settings.json. The project's .claude/settings.json is still written.
INTUTIC_OPA_BINintutic rules buildThe OPA binary used to compile Rego. Default opa on the PATH.
INTUTIC_WASM_DIRintutic policy install, intutic policy list-local, the proxyDirectory for local WASM rules. Default ~/.intutic/wasm; a leading ~/ is expanded. Set it the same way for the CLI and the proxy.
INTUTIC_FC_KERNELintutic exec --sandbox firecrackerPath to the guest kernel image. Required; no default.
INTUTIC_FC_ROOTFSintutic exec --sandbox firecrackerPath to the guest root filesystem image containing your agent. Required; no default.
INTUTIC_FC_GUEST_KEYintutic exec --sandbox firecrackerPath to the private ssh key the rootfs's sshd accepts for root; the agent runs in the guest over ssh. Required: without it, or if the file cannot be read, the run fails with exit 2 before the microVM is set up.
INTUTIC_FC_TAPintutic exec --sandbox firecrackerHost tap device name. Default tap-intutic.
INTUTIC_FC_GUEST_IPintutic exec --sandbox firecrackerGuest IP on the tap link. Default 172.16.0.2.
INTUTIC_FC_HOST_IPintutic exec --sandbox firecrackerHost IP on the tap link; the guest reaches the proxy here. Default 172.16.0.1.
INTUTIC_FC_PREFIXintutic exec --sandbox firecrackerPrefix length of the tap link. Default 30.
INTUTIC_FC_VCPUSintutic exec --sandbox firecrackerGuest vCPU count. Default 1.
INTUTIC_FC_MEMintutic exec --sandbox firecrackerGuest memory in MiB. Default 512.

The control plane itself is chosen as described in Choosing a control plane.

The circuit breaker for AI agents