Skip to content

native2: one agent cursor and outline per agent, colored by tool - #234

Merged
iamnbutler merged 3 commits into
mainfrom
multi-cursor
Nov 2, 2026
Merged

iamnbutler merged 3 commits into
mainfrom
multi-cursor

Conversation

@iamnbutler

Copy link
Copy Markdown
Contributor

Each agent gets its own cursor (with a name tag) and its own window outline, colored by tool:

  • Claude is orange and Codex blue, matched on DESKTOP_TOOLS_AGENT or on the caller's identifier, name or path.
  • Any other agent gets one of six palette colors, picked by FNV-1a of its key so it's the same every time.

The cursor uses the motion Nate tuned in the cursor lab (#228):

  • An agent's first input peels its cursor off the user's pointer (wind-up dip and a halo, then a peel with spin). The whole first move stays within a 0.54 s budget, under the 600 ms pointer limit.
  • Later moves follow an arc with overshoot, 0.2–0.4 s by distance. The cursor stretches and tilts with velocity, and its name tag follows on a spring.
  • After 3 s idle the cursor springs back to the live pointer and merges into it.

Outlines are per agent: several agents in one window get nested outlines, with labels spread side by side.

To identify the agent behind each input, Hooks.pointer now receives the requesting client's pid. run() carries the Hooks.call task-local into its detached delivery thread.

Verified

  • swift test in native2: 62 tests pass, including the new AgentIdentityTests.
  • Release build has no warnings.

Not verified live: a concurrent three-agent run against the dev app was blocked. A Desktop Tools approval prompt (for /usr/bin/timeout, raised by another agent's check) was open in the installed app. The installed app and dev build guard each other, so all input was refused with SELF_TARGET_REFUSED. The overlays are excluded from captures in any case, so the animation needs a person watching.

🤖 Generated with Claude Code

iamnbutler and others added 2 commits November 2, 2026 11:26
Each agent gets its own cursor with a name tag and its own window outline:
Claude is orange, Codex blue, and any other agent a palette color fixed by
its key. The cursor uses the motion tuned in the cursor lab (#228): it peels
off the user's pointer, travels on an arc, and merges back after idling.
Outlines that share one window nest, with their labels side by side.

Why: native2/Sources/DesktopHost/Inspect.swift | run() must carry Hooks.call into its detached thread, or the pointer hook can't tell which client (agent) the input is for
Why: native2/Sources/DesktopTools/Cursor.swift | a first input's wind-up, peel and travel share Tuning.firstWait (0.54 s) so the wait stays under Hooks.pointerLimit (600 ms)

Co-Authored-By: Claude <noreply@anthropic.com>
@iamnbutler
iamnbutler merged commit 1a71f74 into main Nov 2, 2026
2 checks passed
@iamnbutler iamnbutler mentioned this pull request Nov 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant