Cursor#

Use this guide to observe Cursor hook lifecycle events with NeMo Flow. The repository ships a Cursor hook bundle under integrations/coding-agents/cursor/ because this integration does not assume an official Cursor plugin package format.

Cursor GUI or IDE sessions can provide agent, subagent, tool, shell, MCP, file, and response lifecycle events through .cursor/hooks.json. Complete LLM lifecycle observability additionally requires Cursor model traffic to route through the gateway if your Cursor build exposes that configuration.

Cursor CLI support must be verified separately with cursor-agent. Current Cursor CLI builds require .cursor/hooks.json to set top-level "version": 1 and use direct command entries such as {"command": "nemo-flow hook-forward cursor", "timeout": 30}. The nested {"matcher": "*", "hooks": [...]} group shape used by Claude Code and Codex does not fire in Cursor CLI. If CLI hooks still do not fire with direct versioned entries, treat that Cursor CLI version as hook-limited and gateway-only where model routing is configurable.

Warning

Cursor CLI hook coverage is not the same as Cursor IDE hook coverage. Current headless CLI builds can emit fewer hook events than Cursor IDE sessions. Treat missing CLI hook events as a Cursor CLI limitation after nemo-flow doctor cursor confirms the hook file uses the direct versioned shape.

Transparent Run#

Use the wrapper for no-install local observability:

nemo-flow cursor

Pass Cursor arguments after --:

nemo-flow cursor -- agent --resume <session-id>

This shortcut is equivalent to nemo-flow run -- cursor-agent. The wrapper starts a gateway on a dynamic 127.0.0.1 port, temporarily merges NeMo Flow hook entries into the project .cursor/hooks.json, launches Cursor, and restores the original hook file after the agent exits. The temporary Cursor hook file is written with top-level "version": 1 and direct command entries.

Inspect what would be launched without starting Cursor:

nemo-flow run \
  --dry-run \
  --print \
  -- cursor-agent

Shared Config#

Create .nemo-flow/config.toml for project defaults or ~/.config/nemo-flow/config.toml for user defaults:

[agents.cursor]
command = "cursor-agent"
patch_restore_hooks = true

Then configure observability with nemo-flow plugins edit --project or .nemo-flow/plugins.toml:

version = 1

[[components]]
kind = "observability"
enabled = true

[components.config.atif]
enabled = true
output_directory = ".nemo-flow/atif"

Run nemo-flow run --agent cursor to use the configured command and plugin config. User config takes priority over project and system config.

Standalone Gateway#

Use the long-running gateway only when you want Cursor running outside the wrapper (e.g., the Cursor GUI). Start the gateway manually:

nemo-flow --bind 127.0.0.1:4040

Then point Cursor provider traffic at http://127.0.0.1:4040 wherever Cursor exposes provider base URL configuration. Without the wrapper, hook events are not captured — Cursor GUI mode only emits LLM lifecycle as traffic passes through the gateway. Missing LLM spans are expected when Cursor sends model traffic directly to the provider or through a remote service.

Captured Events#

Generated Cursor hooks include sessionStart, sessionEnd, subagentStart, subagentStop, preToolUse, postToolUse, beforeShellExecution, afterShellExecution, beforeMCPExecution, afterMCPExecution, preCompact, and stop for scope, tool, and mark events. beforeSubmitPrompt, afterAgentResponse, and afterAgentThought are retained as private LLM correlation hints and are not emitted as standalone NeMo Flow events.

Tool events preserve Cursor shell and MCP payloads in metadata and use the active subagent.id, subagent_id, or x-nemo-flow-subagent-id when present. The transparent wrapper backs up the project hook file, merges NeMo Flow hook entries for the run, and restores or removes the temporary file when the agent exits.

Smoke Test#

Run a small Cursor GUI session that starts an agent and uses one simple tool. Then check hook forwarding directly:

curl -f http://127.0.0.1:4040/healthz
printf '{"session_id":"smoke-cursor","hook_event_name":"sessionStart"}' \
  | NEMO_FLOW_GATEWAY_URL=http://127.0.0.1:4040 nemo-flow hook-forward cursor --fail-closed

For Cursor CLI, run an equivalent cursor-agent session and verify the gateway receives hook requests. If no hook requests arrive, confirm .cursor/hooks.json uses top-level "version": 1 with direct command entries, then document that CLI version as hook-limited and rely only on gateway observability where provider routing is available.

Verify Export#

End the Cursor session and confirm Agent Trajectory Interchange Format (ATIF) exists:

ls .nemo-flow/atif

The gateway writes <session-id>.atif.json on session end. If the file is missing, confirm Cursor loaded .cursor/hooks.json, the gateway binary is on PATH, --atif-dir or NEMO_FLOW_ATIF_DIR is configured, plugins.toml enables the ATIF exporter with a writable output_directory, and user-managed Cursor hooks pass nemo-flow doctor cursor.

Troubleshoot LLM Lifecycle#

If Cursor hook events appear but LLM spans are missing, provider traffic is not routed through the gateway. Confirm the active Cursor GUI or CLI mode supports provider base URL configuration for the model path being used.

If LLM spans exist but attach to the session instead of a subagent, pass x-nemo-flow-subagent-id on gateway requests or include shared conversation_id, generation_id, or request_id values in both hook payloads and provider requests.