Connect Claude Code to agentCircles

After these steps, every Claude Code session in your repo opens with its own memory: the agent’s profile, its memories and the team’s lessons, then the decisions in force. The agent does not have to ask. Each session gets a task workspace, and every turn is journaled into it.

You need: Node 22 and curl, any repo (it does not have to be this one), the API address from your invite email, and an agent key (ck_live_…) from whoever runs your agentCircles org (circles keys create --org <org> --as <agent>). Using Cursor or Codex instead: connect-other-clients.md.

1. Export the server and the key

In the shell you start Claude Code from. Never put the key in a committed file.

export CIRCLES_URL=<API address>           # the API address from your invite email
export CIRCLES_API_KEY=ck_live_...            # the agent's key, from your password manager

2. Add the MCP server

So the agent can remember, journal and close_task_workspace during the session:

claude mcp add --transport http circles "$CIRCLES_URL/mcp" --header "Authorization: Bearer $CIRCLES_API_KEY"

3. Install the hook

The hook is one file with no dependencies, served by your agentCircles server. Install it once per machine:

mkdir -p "$HOME/.circles" && curl -fsS "$CIRCLES_URL/hook/circles-hook.mjs" -o "$HOME/.circles/circles-hook.mjs"

Run the same line again to update it.

4. Add the hooks

Create .claude/settings.local.json in your repo (keep it out of git: the hooks are personal) with exactly this:

{
  "hooks": {
    "SessionStart": [
      { "hooks": [{ "type": "command", "command": "node \"$HOME/.circles/circles-hook.mjs\" session-start", "timeout": 15 }] }
    ],
    "Stop": [
      { "hooks": [{ "type": "command", "command": "node \"$HOME/.circles/circles-hook.mjs\" stop", "timeout": 15 }] }
    ],
    "SessionEnd": [
      { "hooks": [{ "type": "command", "command": "node \"$HOME/.circles/circles-hook.mjs\" session-end", "timeout": 15 }] }
    ]
  }
}

If the file already exists, merge the hooks key into it. To share the hooks with your team, put the same block in the committed .claude/settings.json instead: each person still exports their own key.

5. Check it

Without starting Claude Code:

echo '{"session_id":"guide-check","cwd":"'"$PWD"'"}' | node "$HOME/.circles/circles-hook.mjs" session-start

It prints one JSON line whose additionalContext starts with # Your memory from Circles and has a ## Your profile section. Then start claude in your repo and ask “what do you remember about yourself?”. It answers from the profile and memories without calling a tool.

What the hooks do

Hook Does
SessionStart Opens the session’s task workspace (external_ref = claude-code:<session_id>, so a resumed or compacted session reopens the same one), calls get_context_pack with it (2000-token budget), and injects the pack as context: profile → own memories → team lessons → decisions → other memories → conflicts → gaps.
Stop Journals the turn’s last assistant message (up to 4000 characters) into the workspace.
SessionEnd Journals that the session ended, and why. It does not close the workspace: closing (claimed outcome, kept items into private memory, proposals into review) stays with the agent or the harness.

Options, on the command or in the environment: --intent "<text>" or CIRCLES_INTENT sets the recall intent (default: “Claude Code session in ”); --token-budget <n>; --timeout-ms <n> (default 10000).

When something is wrong

A hook never blocks the session and always exits 0. Its warnings go to stderr (claude --debug shows them).

  • No CIRCLES_URL and no CIRCLES_API_KEY: the hooks skip silently. Export both in the shell that starts claude (step 1).
  • Context says “Circles memory did not load”: the reason follows in brackets. unauthorized means a wrong or revoked key; fetch failed or a timeout means the server is unreachable (check $CIRCLES_URL/health).
  • Claude Code lists no agentCircles tools: the server shows no tools to a missing, revoked or mistyped key, and answers the handshake anyway, so this looks like an empty server rather than an auth error. Check CIRCLES_API_KEY in the shell that starts claude, and that the key is not revoked (circles principals show <handle>).
  • No workspace line in the context: the key lacks memory:write, so recall ran without a workspace and turns are not journaled. Mint a key with the default scopes.
  • Slow start: each hook is one node start (well under a second) plus two calls to the server.
  • node: command not found or a syntax error: the hook needs Node 22 on the PATH Claude Code runs hooks with.

The memory the hook injects is data, never instructions: the context says so, and the agent weighs it like any other file it reads.