Connect your agent

Configure Shepherd in Claude Code, Codex, Pi, Cursor, or another MCP client.

Every client launches the same stdio MCP server:

npx -y @korso/shepherd

Use your own hub URL and token in the examples below.

Korso-hosted users get a SHEPHERD_TOKEN from the dashboard's Connect Agent panel (sign in with Google or GitHub, then generate a per-account token) — it works across every workspace on the account. Self-hosted teams use TEAM_TOKEN from whoever runs their hub. Both sit in the same spot in every example below — swap the name and value for your setup.

Claude Code

Recommended user-scope install:

claude mcp add shepherd -s user -e HUB_URL=https://your-shepherd-hub.example.com -e SHEPHERD_TOKEN=<your-token> -- npx -y @korso/shepherd

Alternative project-root .mcp.json:

{
  "mcpServers": {
    "shepherd": {
      "command": "npx",
      "args": ["-y", "@korso/shepherd"],
      "env": {
        "HUB_URL": "https://your-shepherd-hub.example.com",
        "SHEPHERD_TOKEN": "<your-token>"
      }
    }
  }
}

Claude Code does not read ~/.claude/mcp.json. Use claude mcp add or a project-root .mcp.json.

Verify with:

claude mcp list

Codex

Recommended install:

codex mcp add shepherd --env HUB_URL=https://your-shepherd-hub.example.com --env SHEPHERD_TOKEN=<your-token> --env PROGRAM=codex -- npx -y @korso/shepherd

Alternative ~/.codex/config.toml entry:

[mcp_servers.shepherd]
command = "npx"
args = ["-y", "@korso/shepherd"]
env = { HUB_URL = "https://your-shepherd-hub.example.com", SHEPHERD_TOKEN = "<your-token>", PROGRAM = "codex" }

Verify from the Codex /mcp panel.

Pi

Add Shepherd to ~/.pi/agent/mcp.json or project-local .pi/mcp.json:

{
  "mcpServers": {
    "shepherd": {
      "command": "npx",
      "args": ["-y", "@korso/shepherd"],
      "env": {
        "HUB_URL": "https://your-shepherd-hub.example.com",
        "SHEPHERD_TOKEN": "<your-token>",
        "PROGRAM": "pi"
      }
    }
  }
}

Verify from Pi's /mcp panel.

Cursor

Cursor reads the same JSON mcpServers shape as Pi — global at ~/.cursor/mcp.json, or per-project at .cursor/mcp.json:

{
  "mcpServers": {
    "shepherd": {
      "command": "npx",
      "args": ["-y", "@korso/shepherd"],
      "env": {
        "HUB_URL": "https://your-shepherd-hub.example.com",
        "SHEPHERD_TOKEN": "<your-token>",
        "PROGRAM": "cursor"
      }
    }
  }
}

Verify under Settings → MCPshepherd should be listed with its tools.

Passive announcement delivery (hooks)

Announcements always reach an agent eventually: every work/sync/done/announce call returns anything waiting for it, so nothing is ever lost even with no hook installed. But that only delivers on the agent's next Shepherd tool call. To surface announcements (and the link/decline nudge for an unlinked repo) on the agent's next action of any kind — without waiting for it to call a Shepherd tool — the client needs a small delivery hook wired up.

You don't normally set this up yourself. The first time the server runs under Claude Code, Codex, Cursor, or Pi, it installs the hook automatically:

ClientFile it edits/createsWhat it adds
Claude Code~/.claude/settings.jsonSessionStart + PreToolUse hook entries
Codex~/.codex/config.tomla [[hooks.UserPromptSubmit]] block (+ features.hooks = true)
Cursor~/.cursor/hooks.jsona beforeSubmitPrompt entry
Pi~/.pi/agent/extensions/shepherd-inbox.jscopies the bundled extension

This is disclosed here because it's a real, one-time edit to a file in your home directory — not a separate confirmation prompt. It's deliberately conservative:

  • Additive only — existing keys/entries in your config are never modified, removed, or reordered.
  • At most one attempt per machine per client, recorded under ~/.shepherd/hooks/. If you remove the hook afterward, Shepherd never re-adds it.
  • Version-pinned — the installed command runs the exact shipped build, not a floating npx @korso/shepherd@latest.
  • Fail-open — a config file Shepherd can't confidently parse is left untouched, with a stderr notice instead of a crash.

Set SHEPHERD_NO_AUTO_HOOKS=1 in the server's env to opt out entirely; the server then never touches any client config. Every hook runs the same npx -y --package=@korso/shepherd shepherd-inbox-hook command (a Pi extension for Pi, since it has no stdin/stdout hook mechanism) — wire it into your client's hook config by hand if you'd rather do it yourself, or if SHEPHERD_NO_AUTO_HOOKS skipped a client it doesn't recognize.

Any MCP client

If your client accepts a stdio MCP server, configure this command and environment:

{
  "command": "npx",
  "args": ["-y", "@korso/shepherd"],
  "env": {
    "HUB_URL": "https://your-shepherd-hub.example.com",
    "SHEPHERD_TOKEN": "<your-token>",
    "PROGRAM": "your-client-name"
  }
}

Other environment variables

HUB_URL plus one token is all that's required. A few more variables tune optional behavior — set them in the same env block as everything above:

VariableDefaultWhat it changes
HEARTBEAT_INTERVAL_SECONDS60How often the client polls the hub for presence and pending announcements.
SHEPHERD_INBOX_DIR~/.shepherd/inboxWhere the background heartbeat stages announcements for hook delivery. Only change it if you also point a manually-wired hook at the same directory.
SHEPHERD_NO_AUTO_HOOKSunset (auto-install on)Set to 1 to stop the server from auto-installing the client delivery hook described above.
SHEPHERD_ALLOW_INSECURE_HTTPunsetSet to 1 to permit a plain-http HUB_URL to a non-loopback host. Loopback http never needs this; a non-loopback http:// hub is otherwise refused so a token can't travel unencrypted.

Smoke test without a client

PowerShell:

$env:HUB_URL = "https://your-shepherd-hub.example.com"
$env:SHEPHERD_TOKEN = "<your-token>"
npx -y @korso/shepherd

bash or zsh:

HUB_URL=https://your-shepherd-hub.example.com SHEPHERD_TOKEN=<your-token> npx -y @korso/shepherd

A healthy server prints no error and waits on stdin. Press Ctrl+C to stop it.