When a coding agent reads or edits a file you have on the canvas, Forkshop draws an outline around the affected tile in the agent's color. Multiple agents working at once each get their own color and stack. Read activity gets a slower-breathing pulse than edit activity.

How an agent talks to Forkshop

The protocol is one HTTP endpoint and one SSE stream:

  • POST /api/forkshop/agent-activity — the producer side. An agent emits one POST per tool call.

    {
      "agent": "claude-code",
      "agentLabel": "Claude",
      "sessionId": "<string>",
      "file": "<repo-relative path>",
      "action": "read" | "edit" | "create" | "delete",
      "ts": 1716000000000
    }
    
  • GET /api/forkshop/agent-activity/stream — the consumer side. The canvas opens an EventSource; the engine streams activity events with the current set of active files. A keepalive comment fires every 15 seconds. Entries age out after a few seconds of silence.

Both routes are dev-only — production returns 403.

Per-agent colors

The engine picks colors from an 8-slot OKLCH palette. The mapping is deterministic per agent name: start the same agent twice and you'll see the same color. Slot 0 (orange) is reserved for claude-code so Claude lands on a known color.

When two agents work at once on different files, you see two colors on the canvas. When they touch the same file, the most recent agent wins the outline.

The agent color flows through every surface that reflects activity: the iframe outline on the canvas, the badge above each tile, and the sidebar — the activity dot and trailing filename next to a page, block, or primitive entry are tinted with whichever agent most recently edited it. So a Claude edit lights up the sidebar row in orange; a second agent on a different file paints its own row in its own color.

Claude Code producer

Pass --install-claude-pack to forkshop init (or set FORKSHOP_INSTALL_CLAUDE_PACK=1) to install the producer pack for Claude Code:

  • .claude/hooks/forkshop-post-tool-use.sh — a bash hook that watches Read, Write, Edit, and MultiEdit tool calls and POSTs the activity to your dev server.
  • .claude/settings.json — the hook is merged into the PostToolUse array idempotently.

The hook only matches changes to .ts, .tsx, .mdx, and .css files.

Other producers

Any agent runtime can produce activity by hitting the POST endpoint with the shape above. A producer is small — typically a hook that observes the agent's tool calls and converts each to one POST.

Block outlines in page iframes

When an agent edits a page file, the engine propagates an outline into any page-view iframe to highlight which block was touched. This requires each block component to have data-forkshop-block="<slug>" on its outermost element — without it the engine can't identify the block inside the iframe:

export function HeroBlock(props: HeroBlockProps) {
  return (
    <section data-forkshop-block="hero">
      {/* ... */}
    </section>
  )
}

The setup skill adds this attribute for you when it detects block components. Check that existing blocks have it if outlines aren't showing in page-view iframes.

Static / seeded activity

AgentActivityProvider accepts two props for seeding activity without opening the live SSE stream — useful for static showcases or marketing demos:

<AgentActivityProvider
  fileMap={fileMap}
  initialActivity={[/* pre-built ActivityEntry objects */]}
  subscribeToStream={false}  // skip the SSE connection
>
  {children}
</AgentActivityProvider>

Entries in initialActivity age out after ~5 seconds by default. Set pinned: true on an entry to prevent it from expiring.

Disabling

Remove the hook script (or its entry in .claude/settings.json) and the activity stream stops feeding. The canvas falls back to no outlines. Nothing else changes.