The first thing an agent does with a brain is orient: which project is this, what's the current status, what's open. In the first version of LLMBrain that took three calls — get_project, then get_doc for the status doc, then list_issues — and before any of them, the agent had to figure out which project this repo maps to. Four decisions before the actual work starts, each one a chance to skip a step or guess wrong.
Watching real sessions made the fix obvious: orientation isn't four questions, it's one — where were we? So now it's one tool, start_session, and the answer comes back whole: the project card, the full status doc, open issues, the roadmap, and docs_health flags for anything stale. One round trip, everything an agent needs to start working, nothing it has to remember to ask for.
The repo is the address
The subtler half of the problem is identity. An agent sitting in a fresh clone doesn't know your project slug — but it always knows its own git remote. So start_session accepts a remote URL as readily as a ref:
start_session("llmbrain") → the project
start_session("https://github.com/ghalex/llmbrain.git") → the same project
Remote URLs get normalized — SSH and HTTPS spellings of the same repo resolve to the same key — so the agent can pass whatever git remote get-url origin returns and stop thinking about it. The repo becomes the address; the human never has to introduce the project again.
The hook that said too much
Claude Code fires a SessionStart hook, and the obvious move is to print the brain's briefing right into the session. That's what the first version did — and it backfired in a way worth recording.
The hook printed roughly 80% of what start_session returns. So from the agent's point of view, calling the tool was redundant: the interesting content was already in context, and the call became a step it could rationally skip. But the hook output was a static snapshot rendered at session start — skip the call and you also skip marking the session, the freshest state, everything the tool call actually anchors.
The fix was to make the hook brief on purpose. It renders a few lines — project name, one-line description, a pointer at what's open — and explicitly withholds the rest, saying so: none of it is repeated here, deliberately. This line is a pointer, not the briefing.
If the trigger contains the payload, the payload stops being fetched. A hook should make the agent curious, not satisfied.
The same renderer produces both from one source — briefs are rendered per audience, so the hook's teaser and the tool's full payload can't drift apart. They're the same document at two zoom levels.
Bootstrap is the product
It's tempting to file session start as plumbing. For an agent-first product it's the opposite: the bootstrap is the front door, and every token and every decision it demands is friction applied at the exact moment the agent is deciding whether the brain is worth consulting at all. One call, one argument the agent already possesses, one response shaped for a context window — that's the whole design, and every piece of it came from watching an agent take a shortcut we'd accidentally paved.