Skip to Content
Cardinal UIAgent OutcomesInstall: Cursor plugin

Install the Cursor plugin

The cardinal-cursor-plugin puts your Cursor sessions on the Agent Outcomes dashboard, matching the Claude Code and Codex CLI plugins:

  • Telemetry — your Cursor sessions stream to Cardinal, attributed to engineer, branch, PR, and initiative, with per-tool activity and subagent lifecycle events.
  • MCP tools — a managed cardinal MCP server entry in ~/.cursor/mcp.json, exposing whichever tools your org has integrations for. Pass --telemetry-only to skip this side.

Sessions in a git repo receive the initiative branch-naming convention at start, and org spend-limit policies are enforced in-session — quiet context at notify, a visible block at block. Cursor’s beforeSubmitPrompt hook has no allow-with-message channel, so warn falls back to notify (agent-only) by default; set CARDINAL_CURSOR_STRICT_WARN=1 in your environment to escalate warn to a hard block instead.

Reach out to support@cardinalhq.io for support or to ask questions not answered in our documentation.

Requirements

  • Cursor with hooks (v1) support.
  • Python 3.11+ on your PATH.
  • A Cardinal account on app.cardinalhq.io, or a self-hosted Cardinal UI your operator has prepared (see Connect AI clients).

1. Install

Cursor doesn’t have a plugin marketplace, so the install is a git clone + run:

git clone https://github.com/cardinalhq/cardinal-cursor-plugin.git ~/workspace/cardinal-cursor-plugin

2. Connect

python3 ~/workspace/cardinal-cursor-plugin/plugins/cardinal-cursor-plugin/scripts/cardinal-connect

The connect script prints a URL like https://app.cardinalhq.io/connect?code=ABCD-EFGH. Open it in your browser, sign in if you aren’t already, pick the org to connect, and click Approve. The plugin picks up your consent within a few seconds and writes:

FileWhat gets written
~/.cursor/mcp.jsonA managed mcpServers.cardinal entry (tagged cardinalManaged: true).
~/.cursor/hooks.jsonManaged Cardinal hook entries for sessionStart, beforeSubmitPrompt, postToolUse, preCompact, stop, and subagentStop.
~/.cursor/cardinal.jsonNon-secret connection state for status/disconnect.
~/.cursor/cardinal-secrets.jsonYour minted keys, written mode 0600.

For self-hosted Cardinal UI, add --host:

python3 scripts/cardinal-connect --host https://ui.example.internal

Then restart Cursor so it reloads the MCP and hook configuration.

3. Verify

python3 scripts/cardinal-status

You’ll see the connected org, both endpoints, key prefixes, and a reachability probe against each side. Run a session in any git repo and it appears on the Outcomes dashboard within a few minutes.

Cloud agents

Cursor cloud agents do not load ~/.cursor/hooks.json or ~/.cursor/mcp.json — cloud VMs have no access to your home directory. To send Cardinal telemetry from cloud-agent runs, install the plugin at the project level from inside your repo:

cd path/to/your/repo python3 /path/to/plugins/cardinal-cursor-plugin/scripts/cardinal-connect --project

This additionally writes .cursor/mcp.json and .cursor/hooks.json at the repo root. Commit both files so cloud agents pick them up. Cursor cloud agents don’t run sessionStart (per Cursor’s hooks docs ), so the initiative-convention prompt and the decision-capture instructions don’t reach them. beforeSubmitPrompt, postToolUse, subagentStop, preCompact, and stop do run, so the spend gate and tool-level telemetry work there. PR lookups need gh signed in inside the cloud VM.

Variants

python3 scripts/cardinal-connect --telemetry-only # Outcomes dashboard only; skip the MCP tools python3 scripts/cardinal-connect --rotate # Mint fresh keys, overwrite an existing connection python3 scripts/cardinal-connect --project # Also install at .cursor/ for cloud-agent coverage python3 scripts/cardinal-connect --host https://… # Point at a self-hosted Cardinal UI python3 scripts/cardinal-connect --dry-run # Walk the consent flow, write nothing

Getting attributed correctly

Sessions are attributed to an initiative by branch name: <type>/<kebab-name>, where the type prefix is one of feat, fix, refactor, infra, chore, research, or spike (for example fix/login-crash → initiative login-crash, type bugfix). Sessions on main/master/develop/trunk are treated as research/scoping work. The plugin surfaces this convention to Cursor at session start, so branches it cuts for you classify cleanly.

Pull requests and decisions

Each prompt’s branch state includes the branch’s pull request when gh is installed and signed in and a PR exists.

Decision capture is off by default. Turn it on from your own terminal:

python3 scripts/cardinal-decision on

While it’s on, Cursor’s agent is told at session start to record each material choice with cardinal-decision record …. Since Cursor 3.6 the agent’s shell commands run in a sandbox by default, so that command only checks its arguments and prints them; Cardinal’s postToolUse hook records the decision, sends it tagged with the session, repo, branch, and PR, and tells the agent the recorded id or why nothing was recorded. If the sandbox blocks the command, approve running it outside the sandbox, or add the plugin directory to additionalReadonlyPaths in your sandbox settings. python3 scripts/cardinal-decision off turns it off.

Upgrading to 0.18.0 from an earlier version? Re-run cardinal-connect so the postToolUse hook gets its longer timeout.

Storyboard associations

From version 0.21.4, the plugin tells Cursor how Cardinal’s storyboards relate to your work, and records where a storyboard was written. See Associations for the model: a storyboard is about something someone declared, or written from a checkout.

  • At session start, with Cardinal connected, the plugin gives Cursor this session’s id and shows storyboards about or written from the work in this repository, including after a merge.
  • No automatic context. Cursor’s hooks can’t rewrite a tool call before it runs, so the session-start text tells Cursor to pass the output of the plugin’s cardinal-storyboard context command as context.
  • Edited files are recorded by an afterFileEdit hook. This follows Cursor’s documented hook payload and hasn’t yet been checked against a live Cursor build, so treat the list of edited files as best-effort.
  • No lookup before an edit. That is Claude Code only.
  • Upgrading. Re-run cardinal-connect so the file-edit hook is registered.
  • Opt out. CARDINAL_STORYBOARD_SESSION_START=0 drops the session id line and the discovery block; CARDINAL_STORYBOARD_DISCOVERY=0 drops the discovery block only. CARDINAL_STORYBOARD_CONTEXT=0 has no effect on Cursor, since the plugin never fills in context there.
  • What it sends. Repository, branch, commit, pull request number and ticket key from the branch name, and (on main) recently merged pull request numbers and your recent local branch names, to your own Cardinal. Files edited are repository-relative paths, visible to members of your org and never on a public link. See Associations.

Privacy

The plugin captures tool names, command lines, and file paths so Cardinal can tell which repo and service a session worked on. The contents of your prompts are never captured. Per-model-call token counts are not currently emitted from Cursor sessions (Cursor’s transcript format for that data is undocumented; see the parity spec  for the open spike).

From version 0.19.0, the result of every tool call (Cursor’s own tools such as Shell and read_file, and any MCP server) is kept locally as storyboard evidence, in ~/.cardinal/evidence/ on your machine, with credentials scrubbed, and deleted after 14 days. Cardinal’s own tools are skipped: their results are already witnessed. A call that touches something sensitive, such as a .env file, a private key or a secret-printing command, is withheld: only a stub saying why is kept. The plugin never uploads the spool; a result leaves your machine only when you cite it in an Investigation Storyboard and the plugin’s scripts/cardinal-evidence promotes it. Re-run the connect script with --rotate after upgrading so failed calls are captured too. To opt out, set CARDINAL_EVIDENCE_CAPTURE=0 in the environment Cursor starts with, or create the file ~/.cardinal/evidence/disabled.

Disconnect

python3 scripts/cardinal-disconnect

This revokes your keys with Cardinal and removes the managed MCP entry, hooks, and local state at both ~/.cursor/ and (if you used --project) the repo root. Everything else in your Cursor config is left as it was.

Last updated on