Semlith

Connect Claude Code to Semlith

How to connect Claude Code to Semlith over MCP, the command or file that adds it, and how to check the connection works.

Every stanza writes ${SEMLITH_BIN} where the binary goes, the path which semlith prints. Set up your agent client explains it and the HTTP form.

Claude Code — claude mcp add, or a committed .mcp.json in the project root. Its scopes are local, user and project, defaulting to local, so --scope user makes one registration cover every directory. --transport http points it at the running daemon; in the subprocess form the -- matters, because Claude Code reads anything starting with a dash as its own flag. The JSON below is the project file, which is committed on purpose, so semlith never writes it.

{
  "mcpServers": {
    "semlith": {
      "type": "http",
      "url": "http://127.0.0.1:7365/mcp",
      "headers": { "Authorization": "Bearer ${SEMLITH_AGENT_KEY}" }
    }
  }
}
claude mcp add --scope user --transport http semlith http://127.0.0.1:7365/mcp --header "Authorization: Bearer ${SEMLITH_AGENT_KEY}"

Or as a subprocess, which needs no key. To replace an existing entry, remove it first: remove takes the same scope flag, and without one it deletes from whichever scope it finds the name in.

claude mcp remove --scope user semlith
claude mcp add --scope user semlith -- "${SEMLITH_BIN}" mcp

semlith setup also writes two hook entries into ~/.claude/settings.json. The PreToolUse one fires before a Bash grep, rg, find, cat, sed -n, head, tail or awk, a Read, a Grep or a Glob inside a folder semlith indexes, and adds one line naming a semlith call that answers the same question (semlith_search {query: …}, semlith_impact {name: …}, semlith_read {target: …}, semlith_files {tree: true}). It stays quiet outside indexed folders, on commands that search nothing, and after three lines in a session. The PostToolUse one records that a session has called semlith. Both sit beside any other hooks, and semlith setup --no-hooks removes both and leaves the rest of the file as it was.

The default mode never blocks. semlith setup --hook-mode gate refuses raw lookups until the session has made one semlith call, at most twice, then only nudges; --hook-mode hard always refuses grep, rg and find in an indexed folder. --strict is kept as the name for gate.

Gate exists because, on code, an agent with Grep reaches for Grep. On 50 held-out code questions with Opus 5.5, no wording of the instructions, tool descriptions or soft hook moved it (0 to 5 of 50 sessions called semlith). Under gate, about 45 of 50 did, with two more correct answers and about 12 % more cost per session (bench/scorecard/README.md). It stays opt-in. On documents it is the other way round: 127 of 127 sessions called semlith unforced (#189).

~/.claude/settings.json
{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash|Read|Grep|Glob",
        "hooks": [{ "type": "command", "command": "${SEMLITH_BIN} hook" }]
      }
    ],
    "PostToolUse": [
      {
        "matcher": "mcp__.*semlith.*",
        "hooks": [{ "type": "command", "command": "${SEMLITH_BIN} hook" }]
      }
    ]
  }
}

It also links the semlith Agent Skill into the directory Claude Code reads user skills from:

~/.claude/skills
semlith

It sets "alwaysLoad": true on the user-scope server entry in ~/.claude.json, so the semlith tools are in context from the first turn rather than behind ToolSearch. claude mcp add has no flag for it, so the entry is upgraded in place, backed up beside itself first. Other clients load an MCP server’s tools when they connect and need no equivalent.

It writes a read-only research subagent, ~/.claude/agents/semlith-explorer.md, whose tools are the semlith tools plus a bounded Read for files semlith does not index, and which Claude chooses over Explore for code research in an indexed folder. semlith setup --no-agents removes it.

semlith doctor reports a missing alwaysLoad, the hook’s mode, the research agent, and a per-project disable: disabledMcpServers or disabledMcpjsonServers naming semlith for the directory you run it from, which the client’s /mcp toggle writes and which makes the server silently absent there. semlith doctor --fix clears that one entry for the current directory and leaves the rest of ~/.claude.json as it was. Only --fix touches it; setup never does, because the disable was your choice in that project.