GAIA
Generative AI Interface for Agents. Specialist agents for Claude Code and OpenCode, with a memory that outlives the session and a consent gate on everything that changes state.

What it is and why it exists
Gaia is a plugin for two terminal AI hosts, Claude Code and OpenCode. You talk to one agent, and it holds the conversation; it never edits a file or runs a general command itself. For each piece of work it sends out a specialist that lives for one turn inside its own field -- application code, infrastructure as code, a cluster's desired state, a live system, planning, or Gaia itself -- and that specialist comes back with a contract: what it looked at, what it changed, how it checked the result, and how the turn ended. What a turn learns is kept in a database on your machine, so the next session starts from what the last one found instead of from zero. And every command any agent tries to run is classified before it runs: reads pass, changes wait for your yes, and a short list of irreversible commands never runs at all.
The four belong together. A conversation that forgets makes you re-explain the project every day; a specialist that reports in prose makes you trust a story instead of a record; an agent that can change your cluster without asking makes you supervise every keystroke. Gaia keeps the conversation in one place, the work in specialists, the record in contracts, and the risk behind a gate.
you
│ asks, in your words
▼
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ the one who holds the │◄──────│ memory that outlives the │
│ conversation │recalls│ session │
└──────────────┬───────────────┘ └──────────────▲───────────────┘
│ sends out one turn │ what stays
▼ │
┌──────────────────────────────┐ ┌──────────────┴───────────────┐
│ a specialist, born for this │──────►│ a contract: what it found, │
│ turn inside its own field │closes │ what it changed, how it ended│
└──────────────┬───────────────┘ on └──────────────────────────────┘
│ every command
▼
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ a gate: reads pass, changes │──────►│ your repository, cluster or │
│ wait for your yes │ once │ account │
└──────────────────────────────┘you say└──────────────────────────────┘
yes
The same boxes with their real names: the one who holds the conversation is the orchestrator, agents/gaia-orchestrator.md, the identity settings.json activates. The specialists are the other eight agent files in agents/. The contract is a row in ~/.gaia/gaia.db that the specialist writes through gaia contract while it works and closes with gaia contract finalize. Memory is the same database, read and curated through gaia memory. The gate is the tier classifier in hooks/modules/security/tiers.py: T0 reads, T1 validation and T2 dry-runs run freely; a T3 mutation stops with an approval_id you answer in the host's dialog (gaia approvals); a blocked command has no approval path at all.
What it can do for you
Ask the orchestrator "what is Gaia?" or "what can you do for me?" and it explains the picture above and offers this table. Each row names the skill or agent that answers it; every one exists under skills/ or agents/.
| You want to... | What answers |
|---|
| Change or investigate code, infrastructure, a cluster's desired state, or a live system | A specialist: developer, platform-architect, gitops-operator, cloud-troubleshooter |
| Understand something -- a system, a process, what happened, why it failed | technical-explanation |
| A README, a runbook, a PR body, a report or a CHANGELOG entry | technical-writing |
| A message or an email for someone else, sent in the user's name | ghostwriting |
| A ticket or an issue | ticket-writing |
| A blog post | blog-writing |
| A diagram deck -- an architecture map, a timeline, a flow, a comparison | deck-builder |
| Capture a feature before planning it | brief-spec |
| Plan it -- decompose it into verifiable tasks | gaia-planner (a skill and the agent of the same name) |
| A review of a module, a branch or a PR | code-review |
| Audit a Gaia component, live-check an area of Gaia, release it, verify the install | gaia-audit, gaia-check, gaia-release, gaia-verify, through the gaia-system agent |
| Look at repositories for something Gaia could take | gaia-research |
| Reflect on the session, or compact it | session-reflection |
| A reminder, or something offered routinely | reminders, recorded with gaia notifications add; nothing runs unattended, what is due waits for the next session |
| See or act on pending approvals | pending-approvals |
| Triage the mailbox, or connect a Google account | gmail-triage, gws-setup |
| Remember, find or curate what Gaia knows | memory |
| See what a session, an agent or a plan cost in tokens, or how a brief changed | gaia usage show --plan N or --session ID, and gaia brief history <slug>, which the orchestrator reads itself; the transcripts are loaded first with gaia usage ingest, run by gaia-operator |
Coming from 5.4? The behaviour changes you will meet -- declared workspaces, reminders in place of gaia schedule, append-only memory, signed package runners, the new approval questions and more -- are listed in CHANGELOG.md, Upgrading from 5.4.
Flow
One turn, from your prompt to the answer:
1. You write a prompt in Claude Code or OpenCode.
2. The orchestrator matches it against the surface_routing table (seeded from
each agent's routing: frontmatter) and dispatches one specialist.
3. The dispatch is validated and its contract row born; the specialist is
handed that contract, its CLI lane, and what Gaia already knows about it.
On Claude Code that is hooks/pre_tool_use.py and hooks/subagent_start.py;
on OpenCode, opencode/bridge.py prepends the same kernel to the Task
prompt, with the specialist's skills listed by name.
4. The specialist works. Every command passes the tier classifier:
T0-T2 run; T3 is denied with an approval_id, the request is phrased with
gaia approvals request-set, and the orchestrator asks you with the
question gaia approvals question prints -- the host's own permission
prompt is never the route, the orchestrator's own commands included;
a blocked command is refused with nothing to approve.
5. The specialist fills its row as it goes (gaia contract set/add/fill) and
closes it (gaia contract finalize); the SubagentStop gate validates the
row and records the episode in ~/.gaia/gaia.db -- hooks/subagent_stop.py
on Claude Code, the child session's session.idle on OpenCode.
6. The orchestrator reads the row, not the message, and answers you.
Gaia interacts with three things outside itself: the host, which loads the hooks -- from hooks/hooks.json on the Claude Code plugin, from .claude/settings.local.json on the npm package, through opencode/plugin.ts on OpenCode, which forwards the same lifecycle (session start on the first user message, each message, tool calls, a child's start and stop, compaction, session end) to opencode/bridge.py -- only Claude Code's TaskCompleted hook, a logging passthrough, has no OpenCode counterpart; the ~/.gaia/ directory, where the database, evidence and logs live (gaia paths prints the resolved locations); and your repositories, which a specialist touches through its own git worktree (gaia worktree) and only mutates past the gate.
Requirements
- One host: Claude Code >= 2.1.295 (the floor declared in
.claude-plugin/plugin.json) or OpenCode. No OpenCode floor is declared or checked; the plugin was measured on OpenCode 1.18.32, which runs subagents in the background only with OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true in its environment (INSTALL.md, Surface 3).
- Python >= 3.12 on
PATH (the engines in package.json); the CLI and the hooks are Python. On the plugin the hooks start through hooks/launch.sh, which needs sh and takes the first of python3, python or py -3 that is really Python 3, so the python.org Windows install, which has no python3, works too.
- Node.js >= 18 and npm or pnpm, only for the package channels below.
- git, for the per-turn worktrees.
- Nothing is installed behind your back: there is no
postinstall, and the database is created lazily on the first gaia command (_ensure_db_bootstrapped in bin/gaia).
How it is used
Gaia reaches your host through one of three channels. The folder you install in is where the host loads Gaia; it is not a workspace until you declare one (see Workspaces, groups and projects).
| Channel | Host | What you install | Where gaia runs from |
|---|
| Plugin | Claude Code | gaia@gaia-marketplace, from this repository | the plugin's own bin/gaia, run by the orchestrator |
| Package | Claude Code | @jaguilar87/gaia from npm, then gaia install --channel npm | node_modules/.bin/gaia, or ~/.local/bin with --path |
| OpenCode | OpenCode | the same package, then gaia install --channel opencode | as for the package |
gaia install and gaia dev take the channel with --channel; there is no default and no all. The package channel and the plugin exclude each other in one Claude Code install folder, since each registers Gaia's hooks: gaia install --channel npm refuses while the folder's settings enable a gaia@... plugin and names claude plugin uninstall <plugin> --scope <scope>, and gaia dev --channel plugin refuses while the package's hooks are registered in .claude/settings.local.json and names gaia uninstall --workspace <folder>, with --channel npm when OpenCode is recorded beside it (channel_conflict in bin/cli/install.py). OpenCode joins either and is removed on its own with gaia uninstall --channel opencode; npm and the plugin share .claude/, so uninstalling either takes back the Claude Code entries. gaia update re-wires the channels gaia install recorded in .claude/gaia-manifest.json. gaia doctor names the channel it finds.
Plugin. In Claude Code:
/plugin marketplace add metraton/gaia
/plugin install gaia@gaia-marketplace # terminal: claude plugin install gaia@gaia-marketplace
That is the whole install, and it does not put gaia on your terminal's PATH. The first session merges Gaia's permission set into .claude/settings.local.json, and asks for /reload-plugins (or a restart); when the folder lies outside every declared workspace, the session says so and names the command that declares one. Auto-update is off for third-party marketplaces; take a new release with claude plugin marketplace update gaia-marketplace, then claude plugin update gaia@gaia-marketplace and a restart.
Package and OpenCode. From the folder you install in: