Set up Cursor AI telemetry for the ai-observability stack
Walk the user through connecting Cursor to the ai-observability stack.
The stack must already be running (docker compose up -d).
Check the platform:
~/Library/Application Support/Cursor/User/globalStorage/state.vscdb~/.config/Cursor/User/globalStorage/state.vscdbIf the DB file does not exist, tell the user Cursor doesn't appear to be installed and stop.
Store the detected DB path as CURSOR_GLOBALDB.
Store the Cursor data root (~/Library/Application Support/Cursor/User/globalStorage
or ~/.config/Cursor/User/globalStorage) as CURSOR_GLOBALDIR.
Run docker compose ps in the repo root. If is not listed as
running, run and wait for it to start.
cursor-shipperdocker compose up -d cursor-shipperRead docker-compose.yml and find the cursor-shipper volumes block. The two
host-side paths must match:
CURSOR_GLOBALDIR for the globalStorage mount~/.cursor/ai-tracking for the ai-tracking mount (same on all platforms)If the paths in the file don't match (e.g. the file still has a macOS path but
the user is on Linux), update them with the correct OS-specific paths and restart
the shipper: docker compose up -d --force-recreate cursor-shipper.
Run docker logs cursor-shipper --tail 5. Look for a line like:
Shipped — local requests: N, files: N, lines: N
If it shows an error reading the DB, the volume mount path is wrong — go back to step 3.
If it shows local requests: 0, files: 0, lines: 0, the user hasn't run any
Cursor agent sessions yet. Tell them to start a Cursor agent session and come
back.
Run:
sqlite3 "$CURSOR_GLOBALDB" "SELECT value FROM ItemTable WHERE key='cursorAuth/accessToken';" 2>/dev/null | head -c 20
If output is empty, the user is not logged in to Cursor. Remind them to sign in via Cursor → Settings → Account and then restart the shipper.
If a token is present, try the usage endpoint:
TOKEN=$(sqlite3 "$CURSOR_GLOBALDB" "SELECT value FROM ItemTable WHERE key='cursorAuth/accessToken';" 2>/dev/null)
curl -s -H "Authorization: Bearer $TOKEN" "https://api2.cursor.sh/auth/usage"
Show the response. Explain that numRequests: 0 is normal on the Free plan
(only counts premium fast requests) and that the local-activity metrics work
regardless.
Check whether ~/.cursor/mcp.json already contains an mcpproxy entry.
If not, and if MCPProxy is reachable at http://127.0.0.1:18420/mcp, offer to
add it. If the user agrees, read the existing ~/.cursor/mcp.json, add the
entry, and write it back:
{
"mcpServers": {
"mcpproxy": {
"url": "http://127.0.0.1:18420/mcp"
}
}
}
Tell the user to reload Cursor (Cmd+Shift+P → "Developer: Reload Window").
Ask the user if they want per-turn latency, model, and conversation log panels (requires cursor-otel).
If yes:
~/cursor-otel/index.mjs already exists. If not, run:
git clone https://github.com/smith/cursor-otel.git ~/cursor-otel
cd ~/cursor-otel && npm install
~/.cursor/mcp.json and add the cursor-otel server entry (without
removing existing entries):
"cursor-otel": {
"command": "node",
"args": ["/Users/USERNAME/cursor-otel/index.mjs"]
}
Use the real expanded home directory path (not ~).Cmd+Shift+P → "Developer: Reload Window")start_turn / end_turn on every turn (see README for the exact text)Tell the user to open: