- Rust 73.4%
- TypeScript 25.3%
- Shell 0.6%
- Dockerfile 0.2%
- PLpgSQL 0.2%
- Other 0.1%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| .anima | ||
| .claude | ||
| .design-sync | ||
| .forgejo | ||
| .solstice | ||
| anima-pwa | ||
| crates | ||
| deploy | ||
| docs | ||
| images/anima-runner-vm | ||
| node_modules/.vite/vitest/da39a3ee5e6b4b0d3255bfef95601890afd80709 | ||
| proto/anima/v1 | ||
| scripts | ||
| .dockerignore | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| CONTEXT.md | ||
| DEPLOY_NOTES.md | ||
| docker-compose.runner.yml | ||
| docker-compose.yml | ||
| Dockerfile | ||
| Dockerfile.runner | ||
| IMPLEMENTATION_SUMMARY.md | ||
| LICENSE | ||
| main.pen | ||
| projectbrief.txt | ||
| rca-d1-d2-agent-diff-pollution.md | ||
| README.md | ||
Anima
Anima is a command centre for AI-driven software development. A human defines a unit of work precisely; AI coding agents implement it as tightly-scoped vertical slices. The quality comes from the plan, not from the implementer's exploration.
It is not a chat wrapper and not an autonomous "do my project" agent. It is the scheduling, review and bookkeeping layer around agent sessions: what gets dispatched, to which agent, with what prompt, under what budget, and what has to be true before the work moves on.
- Licence: MPL-2.0
- Canonical repository: https://code.aopc.cloud/toasterson/Anima
- Status: v0.1.1, pre-release and self-hosted. First commit 11 April 2026; ~1300 commits since. Anima runs its own development — most merges in the log are agent sessions dispatched by the system on its own repository.
The model
Six nouns carry the whole system. They are defined once, in
CONTEXT.md, and the code uses no synonyms for them.
| Term | Meaning |
|---|---|
| Plan | The human-defined intent and its decomposition. The Define-side anchor. |
| Slice | The 1:1 execution wrapper for a Plan; the operator's monitoring surface. |
| Work Item | One small vertical slice of implementation — a thin path through the layers. Carries its own forcing prompt. |
| Workflow | A reusable ordered set of Phases, attached to the Define side, the Implement side, or both. |
| Phase | One step in a Workflow, carrying the prompt that drives it. |
| Phase kind | Who acts: Agent (an ACP session, consumes a slot), Human (opens a thread message and waits), Machine (triggers CI). |
Three design decisions are worth calling out, because they are what make the loop safe to leave running:
Forcing prompts. A Work Item is not handed to an agent as a title. It carries a prompt
assembled from the Plan plus the Phase's own prompt, so the agent's context is constructed
rather than discovered. anima-ai is the assembler.
Graph versioning. A Work Item is pinned on entry to an immutable revision of the phase
graph. Rewiring a workflow never moves in-flight items — they finish on their version, new
items start on the current one. This is what lets an operator edit the flow while work is
running, and what lets per-(item, phase) counters survive the rewire.
Bounded redispatch. Phases have exit bars and a loop guard, so an item that cannot pass its own gate strands visibly instead of burning tokens in a cycle. Agent lanes carry quotas; a lane that is failing is backed off rather than probed.
The reasoning behind these is recorded as 37 ADRs in docs/adr/, starting at
0001 — plan/slice one-to-one.
Agents are pluggable — Anima is not tied to a vendor
Agent sessions are hosted over the Agent Client Protocol (ACP) on stdio, one
subprocess per slot. The executors are configuration, not code: claude-code,
gemini-cli, codex, opencode and ollama-cloud lanes are all driven through the same
path, and the runner never spawns containers of its own — the server assigns work to
advertised slots.
The separate anima-ai service, used for prompt assembly and summarisation rather than
for coding, addresses three configurable tiers (MINIMAL, STANDARD, REASONING), each
with its own base URL, key and model name. Pointing a tier at a local or self-hosted
endpoint is an environment variable, not a patch.
Architecture
A Rust workspace of twelve crates, a gRPC/Protobuf API, PostgreSQL, and a React PWA speaking Connect-Web to the same schema.
| Crate | Role |
|---|---|
anima-core |
Domain types, auth, RBAC, the diff gate |
anima-proto |
Generated types for 27 .proto service and message files |
anima-db |
SQLx repositories and 100 ordered migrations |
anima-server |
The gRPC service surface, plus an MCP endpoint exposing Anima's own tool catalogue |
anima-ai |
Forcing-prompt assembly and the tiered model client |
anima-runner |
Static stateful ACP runner; advertises slots, hosts agent subprocesses over stdio |
anima-forgejo |
Forgejo REST client — pull requests and repository metadata |
anima-git |
A VcsClient trait with a shell-out git implementation |
anima-solstice |
Dispatch and log retrieval against the Solstice CI system |
anima-mq |
RabbitMQ topology for the execution and streaming fabrics |
anima-bridge |
Diagnostic CLI for inspecting work item state |
anima-anthropic |
Thin Messages API client. Not a workspace member — present in-tree, unwired. |
Cross-cutting: tokio, tonic 0.13 for gRPC and gRPC-Web, sqlx 0.8 against
PostgreSQL 18, lapin for AMQP, axum, and OpenTelemetry 0.31 for OTLP traces and
metrics. The PWA is React 19 with @connectrpc/connect-query, TanStack Query, Tailwind
and Vite, tested with Vitest and Testing Library.
Running the development stack
docker compose up --build postgres anima-server
That brings up PostgreSQL 18 — migrations run on server start — and anima-server, with
gRPC on 50051 and the MCP endpoint on 50054.
Known gap: docker-compose.yml also declares anima-ai and anima-mail, and neither
builds. The current multi-stage Dockerfile defines only anima-server and
anima-runner targets, and there is no anima-mail crate in the tree at all — mailbox
support lives inside anima-core, anima-db and anima-server rather than in a separate
service. Name the services explicitly, as above, to skip both. anima-ai is a normal
workspace member and builds with cargo build -p anima-ai.
The compose file ships development-only defaults (BOOTSTRAP_ADMIN_PASSWORD: admin,
literal service tokens, postgres://anima:anima@postgres/anima). Change all of them before
exposing anything. The model tiers need MINIMAL_API_URL / MINIMAL_API_KEY and their
STANDARD_ and REASONING_ counterparts in the environment.
The runner is deliberately not in that compose file. It is a long-lived process that
dials out to the server's RunnerService and needs the agent CLIs on its own PATH — see
Dockerfile.runner and
docker-compose.runner.yml. The PWA in
anima-pwa/ is a normal Vite app (npm install && npm run dev).
Licensing, dependencies and IP boundaries
- Anima itself is MPL-2.0 (
LICENSE) — file-level copyleft. You can link it into a larger work under other terms; modifications to Anima's own files stay MPL. - All dependencies are third-party upstream packages pulled from crates.io and npm at
their published versions, under their own licences (predominantly MIT/Apache-2.0). None
are vendored-and-modified;
Cargo.lockandpackage-lock.jsonpin the exact set. - No proprietary code, datasets or model weights are included, and none are required to build. Anima trains nothing and ships no weights.
- Model providers are external services reached over their public APIs. Anima holds no
provider credentials of its own; keys are supplied by the operator through the
environment. ACP agents (
claude-code,gemini-cli,codex,opencode) are separately installed third-party programs under their own licences and terms — Anima executes them, does not redistribute them, and does not depend on any single one. - Anima's own outputs — plans, prompts, work items, generated diffs — belong to the operator. Nothing is transmitted to the project's authors; there is no telemetry callback, and the OpenTelemetry exporter points wherever the operator configures it.