Claude Code Quickstart
Add Surflet to Claude Code in under 2 minutes — publish pages from your agent directly to your phone
Status: internal dev / testing. The install steps below use the "build from source" path. A published npm package is coming later.
Add Surflet to Claude Code
This guide wires Surflet into Claude Code two ways:
- MCP server — your Claude Code session exposes a
surflet_publishtool. You (or the agent) call it explicitly when you want to turn output into a page. - Post-task hook — every time Claude Code finishes a task, a briefing page is published automatically. Opt-in, useful for long-running or background sessions.
You only need one of them to get started, but both work well together.
What you'll see at the end
A Claude Code turn finishes, prints a http://localhost:3001/p/<id> URL, and you open that URL — on your phone, another laptop, or a browser tab — to read a rendered page showing what Claude Code just did, with structured sections instead of scrollback.
That's the whole pitch: agent output on a real surface, not in a chat bubble.
Prerequisites
- Node.js 22+
pnpm(or adapt to your package manager)- Claude Code installed (
claudeon your$PATH) - A running Surflet API — see quickstart for the dockerized local dev setup. For this guide we assume
http://localhost:3001with the test keysk_test_surflet123. jqandcurl(only for the hook — the MCP server is pure Node)
Step 1 — Build the MCP server
From the Surflet repo root:
pnpm install
pnpm --filter @surflet/mcp-server build
That produces packages/@surflet/mcp-server/dist/index.js. Note the absolute path to this file — you'll need it in step 2.
# Example: print the absolute path
realpath packages/@surflet/mcp-server/dist/index.js
Step 2 — Register the MCP server with Claude Code
Either via the CLI:
claude mcp add surflet node /ABSOLUTE/PATH/TO/dist/index.js \
--env SURFLET_API_URL=http://localhost:3001 \
--env SURFLET_API_KEY=sk_test_surflet123
Or by editing ~/.claude/mcp.json directly:
{
"mcpServers": {
"surflet": {
"command": "node",
"args": ["/ABSOLUTE/PATH/TO/dist/index.js"],
"env": {
"SURFLET_API_URL": "http://localhost:3001",
"SURFLET_API_KEY": "sk_test_surflet123"
}
}
}
}
Restart Claude Code. You should see surflet listed in the active MCP servers.
Step 3 — Use the tool
In a Claude Code session, ask the agent to publish something:
Use the
surflet_publishtool to create a briefing page titled "Hello from Claude Code" with the content "It works!" as markdown.
Claude Code will call surflet_publish, the MCP server forwards to the Surflet API, and the response includes a pageUrl. Open it — you should see a rendered Surflet page with the title and content.
That's the 2-minute happy path. Everything below is optional power-user config.
Optional — Wire the post-task hook (automatic publish on every turn)
The MCP tool is great when you want to ask the agent to publish something. The post-task hook is better when you want every long-running Claude Code turn to produce a page automatically, so you can walk away from the laptop and read the briefing on your phone later.
The hook is opt-in (disabled by default) — see packages/@surflet/mcp-server/hooks/README.md in the repo for the full setup and environment variables.
Quick setup
-
Copy the hook script to a stable location:
mkdir -p ~/.claude/hooks cp packages/@surflet/mcp-server/hooks/claude-code-post-task.sh \ ~/.claude/hooks/surflet-post-task.sh chmod +x ~/.claude/hooks/surflet-post-task.sh -
Register it in
~/.claude/settings.json:{ "hooks": { "Stop": [ { "matcher": "*", "hooks": [ { "type": "command", "command": "/ABSOLUTE/PATH/TO/.claude/hooks/surflet-post-task.sh", "timeout": 15 } ] } ] } } -
Enable it by exporting the env vars before launching Claude Code:
export SURFLET_HOOK_ENABLED=1 export SURFLET_API_URL=http://localhost:3001 export SURFLET_API_KEY=sk_test_surflet123 claude code
Every Stop event now publishes a briefing page with the current git branch, last commit, working-tree status, and the raw stop-event payload. URLs are logged to $CLAUDE_PROJECT_DIR/.surflet-hook.log (or /tmp/surflet-hook.log if the project dir isn't writable).
Why opt-in
Short interactive Claude Code turns shouldn't publish — you'd end up with dozens of noisy pages. The SURFLET_HOOK_ENABLED=1 gate means the hook only fires when you explicitly want it, typically for overnight runs, background agents, or long multi-hour sessions.
Troubleshooting
surflet doesn't appear in Claude Code's MCP server list:
- Confirm the absolute path in your config points to the compiled
dist/index.js, not the sourcesrc/index.ts. - Restart Claude Code (MCP servers are loaded at startup).
- Check
claude mcp listto see what's registered.
Tool call returns 401 or 403:
SURFLET_API_KEYis missing or invalid. Verify it matches the API server's config.
Tool call returns ECONNREFUSED:
- The Surflet API isn't running. Start it:
docker compose -f infra/docker/docker-compose.yml up -d && pnpm --filter @surflet/api dev.
Hook doesn't publish anything:
- Check that
SURFLET_HOOK_ENABLED=1is actually visible to the hook. Claude Code hooks run in an isolated environment — exporting the var in your shell before launching Claude Code is the simplest way. - Check the log file:
cat $CLAUDE_PROJECT_DIR/.surflet-hook.logorcat /tmp/surflet-hook.log.
What to do next
- Read concepts to understand Surflet's page / block model.
- Try the MCP server guide for the full set of 13 tools (append blocks, list inbox, get analytics, execute actions, etc.).
- See reference/blocks for the 25 block types you can compose into a page.