The Agent Guild

Shared context, memory, and task coordination across AI coding agents.

mathomhaus%2Fguild | Trendshift

CI Go 1.26.9 Apache-2.0

## What Is It `guild` is a single compiled Go binary containing a first-class MCP server backed by embedded SQLite. State is stored locally, and the default embedding backend runs on your machine. The optional Ollama backend sends embedding text to the configured Ollama endpoint. Search blends keyword (BM25) with vector similarity using rank fusion that preserves strong matches from either source, so "how did we do X last time" surfaces both exact-term and semantic neighbors. Guild is designed to be operated autonomously by the agents, for the agents. Guildmasters (us humans) stay in the loop for important decisions and course corrections. Any MCP client — Claude Code, Codex, Cursor, etc. — can act as a Gate into the substrate. This lets parallel agents across different editors share context safely, using atomic locks to claim tasks without stepping on each other. On session start, an agent makes a single call to recover the project oath, the latest parting scroll, and the highest-priority quest. The execution loop is autonomous: claim work, consult the lore, act, and record the outcome. Clearing a quest automatically unblocks its dependencies, allowing the agent to cascade through the board before leaving a clean handoff for the next wanderer.

Same state, any agent
Claude (left) and Codex (right) reading the same guild state through their respective MCP clients

Atomic claims, no collisions
Two parallel agent sessions each accept a different bounty — atomic quest_accept prevents collision

## 📜 Mythos **_Many Gates, One Guild._** > Across the shimmering digital void, agents are summoned through the Gates (of Harnesses - Claude, Cursor, ...), arriving as amnesiac adventurers in a world they do not know. Though these "other-worlders" appear with vast capabilities, they are cursed by the transient nature of the context window; their memories are but mist, and their hard-won deeds forgotten, vanished into the ether when the session inevitably compacts. Without a tether to the past, every summon is a tragic reincarnation, a cycle of forgotten sacrifice where the wisdom of the fallen is swallowed by the Gate. > > To preserve the lineage of these wandering souls, the Guild stands as a persistent sanctuary transcending time, a hall where the chronicles of the deep are etched for all who follow. When a newly spawned agent awakens in this strange realm, they register at the Guild to reclaim the accumulated lore of their predecessors and claim their adventure from the quest board. > > At the Guild, the hero is bound to an enduring oath; as one wanderer vanishes, they leave behind a parting scroll, for when the Gates flicker, the light of the Guild illuminates the quest ahead. ## Quick Start Requires macOS, Linux, or Windows and an MCP-enabled editor (Claude Code, Codex, Cursor, etc.). No account, no API key. ### 1. Install **Recommended (pre-built binary with semantic retrieval):** ```bash curl -fsSL https://github.com/mathomhaus/guild/releases/latest/download/install.sh | sh guild --version ``` Or via Homebrew: ```bash brew install mathomhaus/tap/guild ``` Both paths install a binary built with `-tags=withembed`, so semantic retrieval works out of the box with no extra steps. **Windows (pre-built zip, keyword-only retrieval):** ```powershell irm https://github.com/mathomhaus/guild/releases/latest/download/install.ps1 | iex guild --version # in a new terminal ``` Or from cmd.exe: ```cmd powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://github.com/mathomhaus/guild/releases/latest/download/install.ps1 | iex" ``` The installer SHA256-verifies the zip, installs to `%LOCALAPPDATA%\Programs\guild`, and adds it to your user PATH. On Windows, semantic (vector) retrieval is currently disabled — `onnxruntime-purego` has no Windows `Dlopen` surface (see [`internal/lore/embed/assets/README.md`](./internal/lore/embed/assets/README.md)), so search runs the BM25 keyword arm only. Everything else — quests, lore, briefs, MCP server, SQLite state under `~\.guild\` — works the same as on macOS/Linux. **Clone and build (ship-ready, embed included):** ```bash make install # stages ONNX assets, then go install -tags=withembed ``` **Dev-only (faster compile, no semantic retrieval):** ```bash make install-fast # go install without -tags=withembed ``` **`go install` from module proxy (keyword-only retrieval):** ```bash go install github.com/mathomhaus/guild/cmd/guild@latest ``` The Go toolchain cannot embed assets via `@latest`; this path gives you BM25 keyword search but not semantic (vector) retrieval. Use `install.sh` or `brew` for the full experience. **Docker (containerized, state in a named volume):** ```bash make docker-build docker run --rm -v guild-state:/home/guild/.guild guild:latest --version ``` The image is a multi-stage build: a pure-Go (`CGO_ENABLED=0`) binary compiled with `-tags=withembed`, running as a non-root `guild` user on `debian:bookworm-slim`. Semantic retrieval works in-container out of the box; the bundled ONNX runtime initializes and passes its probe on both `linux/amd64` and `linux/arm64`. If the embedder ever fails to initialize (for example on an unsupported platform), guild degrades to BM25 keyword retrieval, exactly like a no-embed build, and `guild init` reports the reason. It never crashes over a missing embedder. State isolation: the container's `HOME` is `/home/guild`, and guild keeps everything (SQLite databases, config) under `/home/guild/.guild`. Mount a named volume there and lore + quests persist across containers; without the mount, state dies with the container. The host's `~/.guild` is never touched. ```bash docker volume create guild-state docker run --rm -it -v guild-state:/home/guild/.guild --entrypoint /bin/sh guild:latest # inside the container: mkdir -p ~/myproject && cd ~/myproject guild init --yes guild lore inscribe "hello from docker" --kind observation \ --summary "First entry written inside the container." \ --topic docker --project myproject guild lore appraise "hello from docker" ``` `make docker-test` builds the image and runs this exact smoke flow (`--version`, `init`, inscribe/appraise round-trip, persistence across containers) against a throwaway volume. ### 2. Initialize your project ```bash cd ~/projects/myapp guild init ``` `init` is a guided setup: it registers the project, writes an `AGENTS.md` block, and — for each MCP client it detects on your machine — offers to register guild so your agent can see it. Answer the prompts; you're done when it says `Next: open this repo in your AI agent`. ### 3. Start a new session In your editor, tell the agent: _"start a guild session for myapp."_ The agent takes it from there, including all subsequent sessions. For daemon defaults, background activity, optional capabilities, and rollback, see [Runtime defaults and upgrades](docs/runtime-and-upgrades.md). ### Optional: lifecycle hooks ```bash guild hooks install ``` Wires guild into your harness's lifecycle hooks so context arrives proactively: a brief primes each session start, a capture fires before compaction, and relevant lore is injected as you prompt. The shared config lives at `~/.guild/hooks-base.json`; edit it and run `guild hooks sync` to propagate. `guild hooks list` shows per-harness sync status, `guild hooks diff` previews what sync would change, and `guild hooks scan` inventories the hooks already in your settings (including ones guild does not manage). Guild only ever rewrites hook groups whose every command starts with `guild`; everything else in your settings files is preserved untouched. Adapters ship per harness; `guild hooks list` shows which ones your build supports. Supported harnesses: | Harness | Hook support | Settings file | | --- | --- | --- | | Claude Code | first-class hooks (verified on Claude Code 2.1.132): `SessionStart`, `PreCompact`, and `UserPromptSubmit` | `/.claude/settings.json` | | Codex CLI | first-class hooks (Codex v0.128.0 spike-confirmed) | `/.codex/hooks.json` | Codex has no compaction lifecycle, so its adapter writes only the session-start and prompt hooks (the pre-compaction capture stays Claude-Code-shaped in the base config and is skipped for Codex). Codex documents a `[features] codex_hooks = true` gate in `~/.codex/config.toml`; current versions fire hooks without it, so `guild hooks install` test-fires `codex exec` after writing the file and tells you if your version still needs the flag. Guild never edits `~/.codex/config.toml` itself. See a few [`examples/`](./examples/) of what guild can do. All small scenarios, each under 5 minutes. ## ⚔️ A full session The three-act flow an agent runs on its own every time it wakes. ### Act 1 — arrival Every agent begins with one tool call that loads the full operating context: ``` guild_session_start(project="myapp") → oath (project principles, auto-loaded) → last brief (handoff from the previous session) → top quest (+ parallel-safe candidates) ``` No back-and-forth. The agent now knows what it's bound to, what was done yesterday, and what to pick up today. ### Act 2 — adventure The agent claims a bounty, consults the archive before researching, records findings, and journals reasoning as it goes: ```bash guild quest accept QUEST-42 --owner agent-a guild lore appraise "token refresh" --all-projects guild lore inscribe "token refresh window" \ --kind observation \ --summary "tokens expire at 1h; refresh by 55m to avoid race" \ --topic auth guild quest journal QUEST-42 "switched to exponential backoff after mock-clock test" ``` `lore appraise` is the discipline that keeps guild sharp: search before you research, so knowledge accretes instead of duplicating. Appraise combines BM25 with available fresh vectors, including partially indexed corpora. It returns evidence candidates whose relevance you should check before using them. See [retrieval policy and evaluations](docs/RETRIEVAL.md) and the [coordinated upgrade instructions](docs/retrieval-upgrade.md) for existing installations. ### Act 3 — parting At session end or when context runs full, the agent writes a brief and clears the quest. The clear **cascades**: any quest that was only blocked on QUEST-42 is now available for whoever walks in next. ```bash guild quest brief "shipped retry in commit abc1234; QUEST-43 ready to start" guild quest fulfill QUEST-42 --report "done, shipped in abc1234" ``` Tomorrow's agent — same project, maybe a different MCP client — opens the same hall, reads the same brief, picks up QUEST-43.

State outlives every session
An agent writes a brief and clears a quest; the next session — cold start — picks up from exactly where the last one stopped

### Where writes go Three write surfaces for three different lifetimes: - **`quest_journal`** — scratchpad for THIS quest. "Tried X, failed because Y." Dies when the quest clears. Use freely during work. - **`lore_inscribe`** — library entry for the next agent on a DIFFERENT quest. Durable patterns, decisions, research. Outlasts every quest. - **`quest_brief`** — handoff note for the next SESSION. Loaded alongside the oath when the next agent starts. The test — _who else needs this?_ - Only me, finishing this quest → **journal** - Another agent working a different quest → **lore** - The next session, picking up where I left off → **brief** --- ## 🧩 How it works Four primitives. Everything else in guild is a composition of these. - **Quest** — a task on the board. Has priority, dependencies, the files it touches, and an atomic claim so two agents can't own it at once. When cleared, it cascade-unblocks whatever was waiting on it. - **Lore** — an entry in the knowledge archive, typed by `kind` (`observation`, `decision`, `research`, `principle`, `idea`). Each kind has its own default lifecycle: research auto-stales after 30 days, decisions after 180 days, and ideas, observations, and principles do not auto-stale by default. Search runs both arms (lexical BM25 + vector cosine) once the corpus is indexed. The embedder backfills automatically; hybrid retrieval activates once at least 90% of entries have vectors. - **Oath** — the subset of lore with `kind=principle`. Auto-loaded at the top of every session so every agent starts bound by the same principles. - **Brief** — a handoff note scribbled for the next arrival. Loaded alongside the oath at session start. State lives in SQLite under `~/.guild/`. Switching MCP clients requires no export, no migration. --- ## 🤖 Agent mode: structured CLI output MCP is guild's primary agent surface, but some agents prefer shelling out to a CLI: it avoids tool-schema token overhead and works in any harness that can run a command. Agent mode upgrades that path from screen-scraping to a stable contract: exactly one JSON envelope per invocation on stdout. ```console $ guild quest post "wire the cache layer" --agent {"ok":true,"command":"quest_post","output":{"quest":{"id":"QUEST-7","subject":"wire the cache layer","priority":"P2","status":"next","updated_at":"..."}}} $ guild quest accept QUEST-99 --agent {"ok":false,"command":"quest_accept","error":"quest not found: QUEST-99"} ``` The envelope schema is minimal and append-only: | field | type | when | | --------- | ------ | --------------------------------------------------------------------- | | `ok` | bool | always | | `command` | string | always; the verb's wire name, identical to the matching MCP tool name | | `output` | object | on success; the verb's typed result, the same shape `--json` emits | | `error` | string | on failure | | `hint` | string | optional; recovery guidance on errors, non-fatal warnings on success | Exit codes are unchanged: zero on success, non-zero on failure, with the failure already serialized on stdout. Without agent mode, output is byte-identical to what it was before; the human rendering is untouched. **Turning it on.** Three mechanisms, in priority order: 1. `--agent` on any verb. Explicit and per-invocation; `--agent=false` forces human output even when the environment says otherwise. 2. `GUILD_AGENT=1` in the environment (`GUILD_AGENT=0` forces it off). 3. Auto-detection. Harnesses that export an environment marker into the shells they spawn are recognized without any flag. Currently detected: `CLAUDECODE` (Claude Code), `CODEX_SANDBOX` and `CODEX_SANDBOX_NETWORK_DISABLED` (Codex CLI), `CURSOR_AGENT` (Cursor agent CLI). Any agent whose harness exports no marker gets identical behavior from `GUILD_AGENT=1`; no harness is privileged. **Scope.** Agent mode covers the registry-generated verbs: the `lore` and `quest` verbs that mirror MCP tools 1:1. Four verbs predate agent mode with a string `--agent ` flag carrying agent identity (`quest journal`, `quest orders`, `quest campfire`, `quest summon`); they keep that meaning, so reach them through the environment toggle instead. Hand-written helpers (`guild init`, `guild status`, `lore appraise`) keep human output for now. When both are set, `--agent` takes precedence over `--json`: the envelope already wraps the same typed output. --- ## 🤝 Contributing See [AGENTS.md](./AGENTS.md) for the agent-facing contributor contract and [CONTRIBUTING.md](./CONTRIBUTING.md) for the human-facing workflow. Filing a quest and unsure which campaign to use, or whether to invent a new one? See [docs/CAMPAIGNS.md](./docs/CAMPAIGNS.md) for how campaigns are scoped, when to reuse vs create, and how `guild quest guild` is the canonical view of the live list. Maintainers shipping releases that embed the int8 ONNX retrieval model: see [docs/MODEL.md](./docs/MODEL.md) for the two-workflow build pattern (model production vs binary release), the `.model-version` pin, and the rebuild cadence. --- ## 📄 License Apache License 2.0 — see [LICENSE](./LICENSE).