Register with a client
The release installer does not edit client configuration automatically. After
installing Kivgraph, run the integration commands without --target to detect
the coding agents present on this machine and select one or more of them:
kivgraph mcp install --scope userkivgraph skill install --scope userNeither command initialises Kivgraph nor indexes any repository. The skill command is documented separately in Agent Skill.
Client integrations run on Linux and macOS only. On any other operating system the command fails instead of guessing a path.
The selector
Section titled “The selector”Kivgraph checks each client’s known local configuration or installation roots and marks the agents it detected.
| Key | Action |
|---|---|
↑ / ↓, or j / k | Move |
space | Toggle an agent |
a | Select all |
n | Select none |
Enter | Confirm |
q or Esc | Cancel |
Detected agents start selected. If none is detected, the selector starts with no
agents selected, and confirming with an empty selection is refused. It respects
NO_COLOR and emits no ANSI when the output is redirected. When neither the
output nor standard input is a terminal, the selector refuses to run and tells
you to pass --target. Use --target for scripted, non-interactive
installation.
Supported clients
Section titled “Supported clients”Five targets are supported. ~ is the user’s home directory; the project scope
resolves against the current working directory.
| Client | --target value | Config file | Format | Where the entry goes |
|---|---|---|---|---|
| Claude Code | claude-code | ~/.claude.json (user scope) | JSON | mcpServers.kivgraph |
| Claude Code | claude-code | .mcp.json in the project directory (project scope) | JSON | mcpServers.kivgraph |
| Claude Desktop | claude-desktop | ~/Library/Application Support/Claude/claude_desktop_config.json on macOS, ~/.config/Claude/claude_desktop_config.json on Linux; user scope only | JSON | mcpServers.kivgraph |
| Codex | codex | ~/.codex/config.toml (user scope) | TOML | [mcp_servers.kivgraph] |
| Codex | codex | .codex/config.toml in the project directory (project scope) | TOML | [mcp_servers.kivgraph] |
| OpenCode | opencode | ~/.config/opencode/opencode.json (user scope) | JSON | mcp.kivgraph |
| OpenCode | opencode | opencode.json in the project directory (project scope) | JSON | mcp.kivgraph |
| Oh My Pi | oh-my-pi | ~/.omp/agent/mcp.json (user scope) | JSON | mcpServers.kivgraph |
| Oh My Pi | oh-my-pi | .omp/mcp.json in the project directory (project scope) | JSON | mcpServers.kivgraph |
Claude Desktop supports the user scope only; asking for --scope project
fails. It is also the one target with no local skill target, so it is absent
from the skill selector.
What gets written
Section titled “What gets written”In every case the server is named kivgraph, and command is the absolute
path of the Kivgraph executable that ran the install command. The examples
below use /usr/local/bin/kivgraph; your path is whatever the running binary
resolves to.
Kivgraph adds only its own entry. Existing servers, keys and top-level settings in the file are preserved. JSON files are re-encoded with two-space indentation.
Claude Code
Section titled “Claude Code”Written to ~/.claude.json in the user scope and to .mcp.json in the project
directory in the project scope.
{ "mcpServers": { "kivgraph": { "command": "/usr/local/bin/kivgraph", "args": ["serve"] } }}Claude Desktop
Section titled “Claude Desktop”Same shape as Claude Code. The file lives at
~/Library/Application Support/Claude/claude_desktop_config.json on macOS and
~/.config/Claude/claude_desktop_config.json on Linux.
{ "mcpServers": { "kivgraph": { "command": "/usr/local/bin/kivgraph", "args": ["serve"] } }}Appended to ~/.codex/config.toml in the user scope, or to
.codex/config.toml in the project directory in the project scope. The table is
appended at the end of the file; the rest of the TOML is untouched.
[mcp_servers.kivgraph]command = "/usr/local/bin/kivgraph"args = ["serve"]OpenCode
Section titled “OpenCode”Written to ~/.config/opencode/opencode.json in the user scope and to
opencode.json in the project directory in the project scope. OpenCode’s
document shape differs: the section key is mcp, command is an array holding
the executable and its arguments, and the entry carries type and enabled.
{ "mcp": { "kivgraph": { "type": "local", "command": ["/usr/local/bin/kivgraph", "serve"], "enabled": true } }}Oh My Pi
Section titled “Oh My Pi”Written to ~/.omp/agent/mcp.json in the user scope and to .omp/mcp.json in
the project directory in the project scope.
{ "mcpServers": { "kivgraph": { "command": "/usr/local/bin/kivgraph", "args": ["serve"] } }}One process for many clients
Section titled “One process for many clients”kivgraph mcp install registers a client against one daemon by default: it
writes a url entry, not a command. Every client shares that process instead
of spawning a serve of its own.
kivgraph mcp install --target claude-codeThat installs the daemon’s supervisor if it is missing, waits for the endpoint,
and reports both. What it saves, measured on a workspace of 108.737 symbols in
benchmarks/daemon-cost: at eight clients, 61 MB against 328 when they are
asking questions, and 11 against 80 when they are not. The crossover is
around one client, so with a single editor open it is a coin flip; from the
second it is not close.
--stdio is the way out, and it writes exactly what the previous default wrote:
kivgraph mcp install --target claude-code --stdioThree conditions write the stdio entry on their own, and each says so:
--scope project, because a url entry carries a token and that file gets
committed; a platform with no supported supervisor, because the daemon would
have no owner there; and a machine with no configuration yet, because there is
no state directory to point at. Passing --daemon explicitly refuses instead of
falling back, which is the point of passing it.
Reinstalling replaces the entry it finds, so switching transports leaves one
registration and not two. An entry naming a different kivgraph install still
needs --force: that one belongs to another installation.
daemon install gives the daemon an owner: a launchd agent on macOS, a systemd
user unit on Linux. Both start it with your session and bring it back if it dies,
which is what makes a url entry safe to depend on — a command entry is owned
by the client that spawns it, but a url pointing at a daemon nobody restarts
takes every client down at once. kivgraph daemon status says whether one is
installed and where its unit lives, and kivgraph daemon remove takes it out.
The unit is per state directory, so two configurations can hold two supervised
daemons without either replacing the other. Nothing supervises a daemon you
start by hand with kivgraph daemon &; it dies with the shell that launched it.
The url and its token come from ~/.local/state/kivgraph/daemon.json, mode
0600. HTTP is the door that matters: no MCP client configuration dials a unix
socket — it takes an executable or a url.
The daemon binds loopback. --allow-remote is required to bind anywhere else,
because the answers carry repository paths, file paths and symbol names.
--scope user is the default. It writes into the client’s own configuration
under your home directory, so the registration applies to every project you open
with that agent.
--scope project writes into a file inside the current working directory, so
the registration travels with the repository and applies only there. Claude
Desktop has no project-scoped configuration file and rejects this scope.
Safety
Section titled “Safety”- The file is parsed as JSON or TOML before it is modified. A file that does not
parse, a top-level value that is not an object, or a section (
mcpServers,mcp,mcp_servers) that is not an object or table, is an error and the file is left alone. - A destination that is a symlink is refused, as is a destination that exists but is not a regular file.
- Writes are atomic: the new content goes to a temporary file in the same
directory with mode
0600, is synced, and is then renamed over the destination. Missing parent directories are created with mode0700. - Before a replacement or a removal, the previous content is copied to a backup
next to the file, with the suffix
.kivgraph.bakappended to the full filename, for example~/.claude.json.kivgraph.bak. An existing backup is kept as it is, so the backup always holds the state from before the first Kivgraph write. A backup path that is a symlink or not a regular file is refused. - An entry named
kivgraphthat does not match what Kivgraph writes is reported asincompatibleand stops the command with an error.--forceis required to replace or remove it. - An entry that already matches is reported as
managedand the file is not rewritten. --dry-runreports the plan aswould-installorwould-removeand writes nothing.
Inspect and remove
Section titled “Inspect and remove”Both status and remove require --target; there is no selector for them.
kivgraph mcp status --target claude-code --scope userkivgraph mcp remove --target claude-code --scope userstatus reads the file and reports absent, managed or incompatible
together with the path it inspected, and changes nothing.
remove withdraws only Kivgraph’s own entry; every other server and setting in
the client configuration is left as it was. The file itself is never deleted. If
the entry is not there, the command reports absent and does nothing.
After registering
Section titled “After registering”The client launches kivgraph serve itself and speaks MCP over stdio. serve
opens no HTTP port; the graph viewer is a separate opt-in command.
With no published generation, serve still completes the handshake. It exposes
only index_project, and its instructions tell the agent to run
kivgraph index --full and restart the server. Nothing is broken: there is
simply no graph to answer from yet.
serve also writes the default configuration when none exists, and continues,
because a client spawns the server itself and exiting because nobody ran init
reads as a crash. That default registers no repository and indexes nothing. An
existing configuration that cannot be read is a failure and is never
overwritten.
Next: Quickstart to build the first graph, or Troubleshooting if the client reports no tools.