Claude app chat setup
Register the seam mcp-proxy bridge in claude_desktop_config.json, restart the app, and run the session loop explicitly - a chat has no hooks and no cwd.
On this page
The Claude desktop app hosts two different Seamless surfaces, and they are wired differently:
- Code sessions inside the app are real Claude Code - they share
~/.claude, so the hooks, MCP registration, and skills from your Claude Code setup apply unchanged. See the code surface inside the Claude app. - Chat conversations are this page: a plain MCP client with no hooks,
wired through
claude_desktop_config.json. Seamless treats it as its own install target, namedclaude-desktop.
If you came here from chat work that isn't code - a legal matter, a deal, a manuscript - Seamless in the Claude app shows what that looks like in plain terms. This page is the technical setup behind it.
No hooks means no ambient layer
Everything the hooks deliver on the code surface is absent in a chat. There is
no <seam-briefing> at conversation start, no per-prompt <seam-recall>, no
findings harvest when the conversation ends, no plan capture - and no
CLAUDE.md, so none of your standing agent guidance is in context either. The
chat surface installs no skills.
What a chat gets instead is the full MCP tool surface, which means the model has
to run the loop itself - the same explicit loop as any
hand-integrated agent: session_start to bind
and fetch the briefing, recall before guessing, durable writes for what should
outlive the conversation, session_end to leave findings. The MCP handshake's
server instructions give the model that baseline workflow, but nothing forces
it - if a conversation never calls session_start, Seamless never hears about
it. Nor is a chat bound to a session the way a Claude Code agent is: that
automatic binding joins an agent's tool
calls to the session its SessionStart hook opened, and a chat has no such hook.
Register the bridge
seamlessd install-hooks --client claude-desktop
This is the same registration the interactive installer offers as menu entry
[2] Claude app (chat) - answers are comma lists, so 1,2 wires Claude Code
and the chat surface together, and all includes the chat surface on the
platforms that can host it (the Claude app ships for macOS and Windows; on
Linux all deliberately excludes it).
There is no management CLI for the app, so registration is a direct, merge-preserving edit of the app's config file:
macOS
The file is ~/Library/Application Support/Claude/claude_desktop_config.json.
Windows
The file is %APPDATA%\Claude\claude_desktop_config.json.
Linux
The Claude app does not ship for Linux, so there is no chat surface to register on this machine - the code-session and CLI setup on Claude Code setup is the whole story there.
--desktop-config PATH overrides the location.
The edit adds one stdio entry under mcpServers - the reserved name
seamless, launching seam mcp-proxy --config <absolute seamless.yaml> - and
touches nothing else. Foreign entries round-trip byte-for-byte (other servers'
entries may hold credentials in env), the original file is backed up once
before the first change, and the write is verified by re-reading the file. No
secret lands in the app's config: the bridge reads the bearer key from
Seamless's 0600 config at connect time, the same policy as every other
registration (see why MCP goes through a bridge).
Then restart the app. It reads the config only at startup; the installer prints the same notice.
Two sharp edges, stated rather than discovered:
--client claude-desktop --mcp=falseis an error. The chat surface has no hooks and no skills, so skipping MCP leaves nothing to install.- A foreign entry already holding the reserved
seamlessname is never overwritten - the installer refuses and names the manual fix.
Registering by hand
In the app: Settings > Developer > Edit Config, then add under
mcpServers:
"seamless": {
"command": "/abs/path/seam",
"args": ["mcp-proxy", "--config", "/abs/path/seamless.yaml"]
}
Use the absolute installed seam and config paths, save, and restart the app.
This is also the repair path whenever the automatic edit refuses to run.
Scope discipline in a chat
A chat conversation has no working directory, and cwd is how every other surface resolves scope. Three things worth knowing before the first durable write - the two failure modes are quiet, and neither is reliably a rejection:
- Bind with
project. When the conversation is about a project, have Claude callsession_start project=<slug>- or pass the repo's absolute path ascwd, which resolves through the repo map. Either buys the full project briefing and correctly scoped unscoped calls on that connection. An unknown slug creates the project, and the result'swarningsays so. The binding lives in the daemon's memory, so after a reconnect (a daemon or app restart) callsession_startagain. - A
session_startwith neitherprojectnorcwdbinds the global scope. The response's scope line warns, but every later unscoped durable write then lands global silently - nothing at write time flags it. - Skipping
session_startis not a reliable way to fail closed. An unscoped durable write with no bound session falls back to the sole active ambient session. The chat'sseam mcp-proxynames the process that launched it (the app), so that fallback skips sessions owned by other agents' processes - a Claude Code or Codex session on a currentseam- and the write is refused as ambiguous. A session started by an olderseamcarries no process stamp and is still a candidate, though: then the chat's write lands in that session's project, stamped with its provenance.
The discipline that avoids both: have the chat pass a project (or a real
cwd) at session_start, or pass project: explicitly on every durable
write. Use project: global only when global is the point. The full precedence
chain is in Projects & scope.
Uninstall
seamlessd uninstall (default --client all) removes the chat-surface entry
along with everything else; --client claude-desktop limits the client step
to this entry alone, though uninstall always removes the service and binaries
too - it un-installs the program, not one client. Removal deletes only the
reserved seamless entry - every other key, including a now-empty
mcpServers, stays exactly as found - and prints the same restart notice,
since the app also loads config at startup only. To drop just this entry and
keep Seamless, edit the config by hand:
Add or remove one client.
Verify
seamlessd doctor
Look for the claude desktop mcp line. Not registered is an info line, not
a warning - the chat surface is an explicit opt-in, so doctor never nags you
into it. An exact registration reports OK with one honest caveat: whether the
running app has actually loaded it is unverifiable, because the app reads the
config at startup and exposes no way to ask. If you registered and did not
restart, doctor cannot tell - the restart is on you.
The live evidence behind what this page claims - protocol handshake, in-app tool calls, and the scope gotchas above - is recorded in the Claude app compatibility matrix.