Agents
Rendered from knowledge/exobrain/agents.md — the text an agent reads.
An exobrain serves any AI coding agent — Claude Code, OpenClaw, Codex, others added later. Content is written universally by default; agent-specific bits are isolated so they never bleed into another agent’s context. This file describes that isolation.
For the skill-loading side of the same machinery, see skills.md.
Supported agents
Section titled “Supported agents”| Agent | CLI | Marker (in repo) | Per-user config dir |
|---|---|---|---|
| Claude Code | claude |
.claude/CLAUDE.md |
~/.claude/ |
| OpenClaw | openclaw |
.openclaw |
~/.openclaw/workspace/ |
| Codex | codex |
.codex |
~/.codex/ |
A marker is the agent’s generated surface (or a file beside it), and its presence means “this agent is wired here — keep it maintained.” Connecting is the human act; from then on the post-merge git hook re-links each agent whose marker exists and silently skips the rest. Disconnecting an agent is removing its marker.
Every marker is therefore a gitignored file the connector generates, never a committed path like the .claude/ directory — that ships in every clone for its settings.json, so it proves the clone rather than the choice. connect-agent.sh and exobrain-healthcheck.sh test the same three paths.
Universal-by-default
Section titled “Universal-by-default”Specs, skills, and docs are written so the same content works for every agent — “the agent reads SKILL.md”, not “Claude reads SKILL.md.” The universal AGENTS.md names no primitives; the per-agent sidecars translate. When a skill genuinely depends on one agent’s runtime, mark it agent: "<name>" in skills.json; the opposite-shaped skipAgents: [...] excludes specific agents. See skills.md § Agent filtering.
Per-scope sidecars
Section titled “Per-scope sidecars”At any scope (the repo root, a group/person/host, or a standalone scope like seed/), three sidecar filenames are recognized alongside AGENTS.md: CLAUDE.md, CODEX.md, OPENCLAW.md. Each loads only when connect-agent.sh runs for that agent. Use them for tooling-primitive names (“use Edit, not Bash sed”), MCP registration commands, and per-agent quirks. Content that applies under all agents goes in the universal AGENTS.md at the same scope — never duplicated into each sidecar.
Per-scope script suffix
Section titled “Per-scope script suffix”Scripts that depend on a specific agent’s runtime use a <name>.<agent>.sh suffix. Universal scripts have no suffix. The invoker picks the right variant; connect-agent.sh doesn’t manage these paths.
Non-interference — enforced
Section titled “Non-interference — enforced”Isolation is enforced at link and fetch time, not by convention:
- The Codex connector writes its context and skills inside the checkout and leaves personal Codex home files and symlinks untouched.
- The linker skips
CLAUDE.md/OPENCLAW.mdsidecars when injecting for Codex. - The fetcher skips external entries tagged for another agent.
- The generated
optional-skills.mdexcludes any skill not visible to the running agent.
The rule: any agent-specific artifact must be invisible to other agents. If it isn’t, the agent filter is the bug.
Per-agent injection surface
Section titled “Per-agent injection surface”Each agent pulls auto-loaded specs into its prompt differently; the content is identical across agents.
| Agent | Connected-scope specs | Generated indexes |
|---|---|---|
| Claude Code | .claude/CLAUDE.md @-imports .claude/connected-scopes.md — a manifest of @-imports to each connected scope’s live source AGENTS.md/sidecar (by reference, not copied) |
The same CLAUDE.md @-imports .claude/optional-skills.md, .claude/tools-index.md, .claude/knowledge-index.md |
| Codex | The whole composition is written to an in-repo, gitignored AGENTS.override.md, read natively — it outranks AGENTS.md at the same directory level |
Inlined in AGENTS.override.md |
| OpenClaw | Inlined into USER.md via a marker block (<!-- BEGIN exobrain --> … <!-- END exobrain -->) |
Inlined in the same block |
All three deliver the same content — each connected scope’s specs (shallow→deep) plus the generated indexes — differing in delivery and in how the global scope (root AGENTS.md) arrives. Claude @-imports a manifest pointing at the live source files, so a scope edit shows up without a recompose, and lets the checked-in root CLAUDE.md load the global scope; OpenClaw and Codex get the global scope inlined: OpenClaw’s sessions start in its own workspace, whose AGENTS.md is the runtime’s conventions file, so the connector copies the root AGENTS.md into the USER.md marker block; Codex’s AGENTS.override.md replaces AGENTS.md, so the file must be self-contained.
connect-agent.sh end-to-end
Section titled “connect-agent.sh end-to-end”A single run:
- Resolve config — establish
connected_scopes+ thepersonid from one of four sources, in precedence order: explicit flags (--handle/--host/--scope/--guest) > existing/parent.exobrain.json> the interactive wizard > guest. Identity is name-matched (handle/hostname → a scope by leaf name); the wizard offers a checkbox menu of connectable scopes with person + host pre-checked. - Resolve the skills registry — walk every
skills.jsonin priority order into a plan. - Link always-tier skills — symlink each into the agent’s skills dir as
<name>.<scope-owner>/. Most agents read it from their context surface (.claude/skills,~/.openclaw/workspace/skills); Codex scans a repo-local.agents/skills, so its skills link there — out of the global~/.codex, scoped to this repo. OpenClaw honors a workspace skill symlink only when its target root is trusted in its config — step 8 keeps that list current. - Fetch external skills — route to
skills/(always) orskills-optional/(optional). - Generate the indexes —
optional-skills.md(optional-tier skills),tools-index.md(visible tool docs),knowledge-index.md(domains + their summaries, then a section per mount —mounts.md). - Compose + inject — deliver each connected scope’s
AGENTS.md(+ agent sidecar, shallow→deep) and the generated indexes. Claude writes.claude/connected-scopes.md— a manifest of@-imports to the live source specs — and a.claude/CLAUDE.mdthat@-imports that manifest plus each index; Codex writes the self-contained in-repoAGENTS.override.md(root scope and root sidecar inlined, since it replacesAGENTS.md); OpenClaw inlines the same specs and indexes into aUSER.mdmarker block, with the rootAGENTS.mdand its root sidecar prepended, and gets a second marker block in its workspace.gitignore— the runtime writes raw capture intomemory/(a near-verbatim transcript per session reset, plus the dreaming sweep’s corpus and candidate logs), and a workspace with a remote would otherwise publish all of it permanently. Files already tracked need untracking by hand; the run says so. - Install the git hooks — rewritten on every run,
--relinkincluded, so a template change reaches a checkout that connected long ago. What each hook runs:machinery.md§ Git hooks. - Reconcile the OpenClaw runtime config (openclaw only) — through
openclaw config set: the real parent dir of every linked skill joinsskills.load.allowSymlinkTargets,skill_workshopjoinstools.deny,skills.workshop.autonomous.modebecomesoff(rootOPENCLAW.md§ Skills are exobrain files), the bootstrap budgets (agents.defaults.bootstrapMaxChars/bootstrapTotalMaxChars) are raised to floors that hold the injectedUSER.md— past the per-file budget its tail, the knowledge index, is silently dropped — andmemory.search.extraPathsgains this checkout’sknowledge/and each listed mounted domain, so the runtime’s semantic recall reaches the domains and not only its own memory files. The paths are positive per-depth globs, since the indexer cannot exclude a path segment and a domain’s_raw//_meta/must stay out; indexing sends the matched files to the runtime’s configured embedding provider. Lists are unioned, so entries the human added stay, and a larger budget stays; nothing is written when the config already matches; a missing CLI is reported and the connect carries on.OPENCLAW_BINoverrides the binary. - Reconcile the scheduled jobs (openclaw only) — run
scripts/openclaw-cron-sync.py --scopes <the connected chain>, so thecrons.jsonregistries of the connected scopes are what the runtime’s scheduler runs. Skipped when no scope in the chain carries acrons.json— a checkout that declares no jobs never touches the scheduler, so a relink that resolved no scopes cannot empty it — and from a linked worktree; a missing CLI or a failed sync is reported and the connect carries on. - Run scope hooks — a connected scope extends the connect with setup of its own. Each scope in the chain carrying an executable
scripts/connect-agent.sh(every agent) orscripts/connect-agent.<agent>.sh(that agent alone) gets it run, shallow→deep, as<hook> <agent> <target-dir> <scope-dir>; both run when both exist, universal first. The global scope is skipped — itsscripts/connect-agent.shis the connector. A hook that fails is reported and the connect carries on.
--relink repeats steps 2–10 without prompting and writes neither marker nor config (a --relink for an unmarked agent exits before any of this; --relink with no agent named runs it once per marked agent, and takes no other flag); --configure re-resolves identity (the wizard, or the identity flags); --wire-sandbox runs steps 2–6 and stops before hooks, the OpenClaw config, and scope hooks — real wiring for a throwaway copy (a test sandbox, a CI checkout), so a wire-sandboxed checkout counts as connected for claude. For openclaw the mode refuses to run unless OPENCLAW_WORKSPACE is set, so the real home workspace is never the implicit target — the guard checks that the variable is set, not where it points, so point it at a throwaway dir.
Adding a new agent
Section titled “Adding a new agent”To support a fourth agent: pick a marker and a target dir, add a link/inject branch in connect-agent.sh (symlink-and-import or marker-block shape), recognize its <AGENT>.md sidecar, add it to the agent filter, and document its runtime quirks in the root <AGENT>.md. The agent-specific bits extend without touching the universal layer. Test: connect each agent in turn on a fresh clone, confirm none sees another’s content.
Worktree context
Section titled “Worktree context”create-worktree.sh calls link-worktree-context.sh <main> <worktree> to inherit the generated markdown and Claude’s per-machine .claude/settings.local.json (permission allowlists, gitignored), and to create real Codex skill directories with individual skill links. In-tree skill links prefer the worktree’s own source, so a branch’s skill edits are what the agent loads there; fetched skills use the main checkout’s cache when the worktree has no copy. Existing destination files are preserved, and re-running the helper repairs missing links in an existing worktree. Mounts resolve through the main checkout (mounts.md).
Wiring Codex inside a worktree replaces the inherited AGENTS.override.md symlink with a local composition and leaves the main checkout’s file untouched. The healthcheck checks Codex’s context and resolved always-tier skills in the active checkout; connection markers and trunk freshness come from the main checkout.