#7576·superset

Cursor agent identity/resume: residual gaps after the SUPERSET_HOOK_HARNESS fix

Author: FinndersenCreated Sep 15, 2026Updated Sep 16, 2026

Summary

  • Terminal agent bindings record agent_id = "claude" for cursor-agent sessions, while storing Cursor's real session id.
  • Reopening the workspace therefore runs claude --permission-mode auto --model sonnet --resume <cursor-session-uuid>, which fails with No conversation found with session ID: .... The Cursor session can never be resumed.
  • Happens for every Cursor CLI session. Across my two org databases, all 79 terminal_agent_bindings rows say claude and zero say cursor-agent, yet 4 of 6 stored session ids are genuine Cursor sessions (they exist under ~/.cursor/projects/*/agent-transcripts/<id>/ and ~/.cursor/chats/*/<id>/, and not under ~/.claude/projects).
  • Likely the same root cause as #5259 (Cursor Agent "Task complete" notification on every model turn) — different symptom, same mechanism.

Steps to reproduce

  1. Create a workspace using the Cursor Agent (cursor-agent) preset.
  2. Let the agent run at least one turn.
  3. Quit Superset, reopen it, and reopen that workspace's terminal.

Expected

Resume uses the cursor-agent config, i.e. cursor-agent --resume <id>.

Actual

Resume uses Claude's config with Cursor's session id, and fails immediately.

Cause

cursor-agent loads Claude Code's hook config in addition to its own — it resolves claudeUserConfigPath = ~/.claude/settings.json (plus project .claude/settings.json / settings.local.json) alongside ~/.cursor/hooks.json, parses them with parseClaudeConfig, and runs them.

Superset's managed Claude hook command hardcodes the agent id as an env prefix:

[ -n "$SUPERSET_HOME_DIR" ] && [ -x "$SUPERSET_HOME_DIR/hooks/notify.sh" ] && SUPERSET_AGENT_ID=claude "$SUPERSET_HOME_DIR/hooks/notify.sh" || true

That prefix overrides the correct SUPERSET_AGENT_ID=cursor-agent exported by Superset's own cursor-agent wrapper. Verified: the live cursor-agent process has SUPERSET_AGENT_ID=cursor-agent in its environment, and its terminal id matches a binding row that says claude.

So notify.sh POSTs {agentId: "claude", sessionId: "<cursor session id>"}. Server-side recordEvent does nextAgentId = agentId ?? existing?.agentId (last write wins), and Claude's PostToolUse hook fires on every tool call, so claude is continuously re-asserted for the lifetime of the session.

The two hook sets are not deduplicated, because dedupeClaudeHooksAgainstCursorHooks keys on exact command string plus event name — cursor-hook.sh … and notify.sh differ, and the event names differ too (beforeSubmitPrompt vs UserPromptSubmit).

Suggested fixes

  • In getManagedNotifyHookCommand, use SUPERSET_AGENT_ID=${SUPERSET_AGENT_ID:-claude} so the wrapper's value wins when another Claude-config-compatible agent executes the hook.
  • Better: treat the launch preset as authoritative for the binding's agent_id. It is already known at terminal creation time (bindResumedSession records agentId: presetId), so a foreign agent's hook should not be able to overwrite it.
  • Possibly also guard the resume builder: if the stored session id does not belong to the resolved agent, prefer starting fresh over emitting a command that cannot succeed.

Separate, smaller bug

cursor-hook.sh's fallback identity detection checks $CURSOR_AGENT / $CURSOR_CLI:

if [ -n "$CURSOR_AGENT" ] || [ -n "$CURSOR_CLI" ]; then AGENT_ID="cursor-agent"; else AGENT_ID="cursor-composer"; fi

cursor-agent 2026.09.10 sets neither; it sets CURSOR_INVOKED_AS=cursor-agent. So whenever SUPERSET_AGENT_ID is absent, a CLI session is mislabelled as cursor-composer (which is not in BUILTIN_AGENT_IDS at all).

Environment

Superset 1.26.0, macOS Darwin arm64, cursor-agent 2026.09.10-fd3934a