This directory (~/launchapp-dev) is the root for developing the Animus ecosystem
(launchapp-dev GitHub org). It is a clone of the worktree-manager template: its MCP
server manages git worktrees and GitHub operations across many repos at once.
Two things differ from the stock template — read these first:
- Task tracking lives in the Animus portal, not here. Use the
mcp__animus__*tools (a Postgres-backed board). Do NOT use the worktree-manager's built-intask_*/req_*tools — they are superseded. See Task & Requirement Tracking below. - Repos are organized by version. Each repo has a
versions/dir (release-line checkouts) and aworktrees/dir (feature work). See Repo Layout below.
Every repo brought into the workspace lives under repos/<name>/:
repos/<name>/
.bare/ # bare clone (source of truth; never edit here)
versions/ # release-LINE checkouts — track release/* branches
0.7/ # worktree on branch release/0.7 (editable)
0.6/ # worktree on branch release/0.6
worktrees/ # FEATURE work — one dir per work branch
main/ # trunk checkout (base for new work)
<feature-slug>/ # worktree on a feature branch
versions/<version>— a worktree checked out on a release branch (release/<version>). This is where you cut/patch a specific released line. Add one with:./scripts/add-version.sh <repo> <version> [ref](defaults ref torelease/<version>, falls back to the tag).worktrees/<slug>— a worktree for feature work, created via the worktree-manager MCP (git_create_worktree). Dir name is the sanitized branch name.- Only
.bare/,versions/,worktrees/should exist under a repo.repos/is gitignored.
- Feature work:
agent/v<version>/<slug>(e.g.agent/v0.7.0/mcp-oauth-broker) orfeat/<slug>. - Release lines:
release/<version>(e.g.release/0.7). - A worktree's directory should match its version/branch so the tree is self-describing.
| Repo | Lang | Role | Current line | Release branches |
|---|---|---|---|---|
| animus-cli | Rust (20-crate ws) | AO agent orchestrator — the kernel/daemon | v0.7.0-rc.1 |
release/0.7, many release/v0.6.* |
| animus-protocol | Rust | Plugin protocol stack (SDK crates + spec) | v0.7.0-rc.2 |
release/0.7 |
| animus-launchapp | JS (server/+web/+agent/) |
The portal — Railway-deployed; backs the animus MCP |
main (rolling) |
— |
| animus-plugin-sdk-ts | TypeScript | @launchapp-dev/animus-plugin-sdk — author plugins in TS |
v0.2.x |
— (tag-based) |
| animus-web-ui | React/TS | Web UI for Animus (HTTP + GraphQL transports) | v0.1.x |
— (tag-based) |
| animus-desktop | Tauri/TS | Desktop app ("the app for AI teams", Mac v1) | v0.0.1 |
— |
The whole plugin/kernel line is converging on v0.7.x. animus-cli and animus-protocol
release together (protocol crates are git-dep'd by tag from the plugins).
Bring in more org repos anytime with the worktree-manager MCP:
git_init_repo { name: "<repo>", url: "https://github.com/launchapp-dev/<repo>.git" }.
The portal is a Postgres-backed board of "subjects" of various kinds. It is shared across the whole workspace — every member sees changes live. Prefer it over any local file.
Primary kinds: task (the work board), requirement (PRDs/specs), knowledge
(repo/entity graph), plus note, blog, ci_job, transcript, trigger_event.
Task fields: status (ready → in-progress → done), priority (p0–p3 / critical…low),
tags, task_type, risk, scope, description, dependencies, linked_requirements.
Core tools:
mcp__animus__list_kinds— discover kinds + their custom-field schema (run before creating an unfamiliar kind).mcp__animus__list_subjects { kind, status?, cursor? }— read the board (PAGINATE untilnext_cursoris null).mcp__animus__get_subject { kind, id }— one subject's full record.mcp__animus__create_subject { kind, title, body?, priority? }— add a task/requirement.mcp__animus__subject_status { kind, id, status }— move lifecycle (ready/in-progress/done).mcp__animus__update_subject { kind, id, title?/body?/priority? }— edit fields.
Convention: title tasks with the target version, e.g. "animus-cli v0.7.0: <what>"
(matches the existing board). Link a task to its requirement where one exists.
Daemon / fleet ops (also on the animus MCP): daemon_health, daemon_status,
queue_*, workflow_*, agent_*, cost_summary. Confirm before pausing/cancelling anything shared.
- Repos:
git_init_repo,git_list_repos - Worktrees (feature work):
git_create_worktree { repo, branch },git_list_worktrees,git_remove_worktree,git_worktree_status,git_sync - Commit/push:
git_commit,git_push,git_pull,git_reset - GitHub:
github_create_pr,github_list_prs,github_get_pr,github_merge_pr,github_pr_checks,github_create_issue,github_list_issues,github_add_comment
git_create_worktree writes to repos/<repo>/worktrees/<branch>. For release-line
checkouts under versions/, use scripts/add-version.sh (the MCP doesn't manage versions/).
- Plan — create/checkout a task on the board:
mcp__animus__create_subject { kind:"task", title:"animus-cli v0.7.0: <feature>", priority:"p1" }, thensubject_status → in-progresswhen you start. - Branch — feature work:
git_create_worktree { repo:"animus-cli", branch:"agent/v0.7.0/<slug>" }→ code inrepos/animus-cli/worktrees/agent-v0.7.0-<slug>/. Patching a release: work inrepos/animus-cli/versions/0.7/(add viascripts/add-version.sh). - Code / build — Rust repos:
cargo build/cargo test. JS/TS repos:pnpm install/pnpm build. - Ship —
git_commit→git_push→github_create_pr; thensubject_status → done.
The portal is Railway-deployed and backs the animus MCP. These are the rules that keep deploys
from silently breaking execution. Read this before touching a portal deploy.
- Railway auto-deploys on push to
main. Merging any PR intoanimus-launchappmain ships it live. mainis the source of truth for the deploy (the ao-cliANIMUS_VERSIONpin, the runner pin, the cutover Dockerfile + start.sh).feat/baas-cutoveris a STALE divergent branch — do NOT base deploy PRs on it (it will revert main's newer work).git_create_worktreefrequently branches off a STALE base (seen: v0.4.12). ALWAYSgit reset --hard origin/main(or origin/) right after creating a worktree and verify HEAD. Multiple agents shipped PRs on stale bases — always double-check the base.- Run
railwayCLI from the linked worktreerepos/animus-launchapp/worktrees/feat-baas-cutover.railway deployment list --jsonis flaky (malformed JSON) — text-parse:railway deployment list | grep <id> | awk -F'|' '{...}'.
docker build --platform linux/amd64 -f deploy/Dockerfile -t validate .
Gate on ALL of: install --locked → "7 verified, 0 failed" (every plugin sha matches) AND
daemon preflight → "all 5 required roles satisfied" AND EXIT=0. Catches bad pins/shas pre-prod.
deploy/DockerfileARG ANIMUS_VERSION— pins the ao-cli/daemon (e.g.v0.7.0-rc.6).animus.toml— the workflow-runner git tag..animus/plugins.lock— the runnerversion+ per-targetarchive_sha256+installed_binary_sha256. When bumping the runner: download the linux tarball,shasum -a 256the archive (must equal the.sha256sidecar) AND the inner binary; update BOTH the toml tag and the lock version+shas.
The workflow runner (animus-workflow-runner-default) is a SEPARATE release built against a pinned
ao-cli. If it lags the daemon's ao-cli line, execution breaks silently (queue entry leases →
done → NO journal_run). Rebuild the runner with its ao-cli dep repinned to the SAME rc, cut a new
runner release, then repin the portal. Failure modes seen this session (runner v0.4.20→23):
- Runner on pre-multi-kind ao-cli can't see
config_sourcein the consolidated animus-postgresplugin_kindsarray (daemon'sserves_kindpasses, runner's legacy check fails) → no run spawned. - Command-phase
{{subject_id}}must render kind-QUALIFIED (task:TASK-x,transcript:TRANSCRIPT-001) or dynamic-kind phases default totaskand fail. - Runner context-build must resolve dynamic kinds via the backend's generic
subject/get, not a per-kind capability, or dynamic-kind subjects hang beforemark-running.
- Subjects are stored BARE (
TASK-244,TRANSCRIPT-001); the qualifiedkind:idis constructed. Dynamic/custom kinds (transcript, blog, ci_job…) are served by the*catch-all backend. - Dispatch a dynamic kind with
animus queue enqueue --subject-id <kind>:<id>.--task-id/--requirement-idare being retired for--subject-id. - After every deploy, VERIFY execution: enqueue a throwaway task → a
journal_runappears → phases execute →mark-done(queryjournal_runs/journal_events).
- Live in the durable on-volume registry
/data/animus-state/state/skills-registry.v1.json(github-imported, integrity-pinned inline definitions)./app/.animus/skillsis EPHEMERAL — askill install --paththere dies on redeploy; only github-import writes the durable registry. - Sources:
phuryn/pm-skills(third-party, ~80 PM skills) + org-ownedlaunchapp-dev/animus-skills(Animus operational skills +transcript-cleanup) +launchapp-dev/animus-pack-core-skills. - An agent with
config.skills: [...]HARD-FAILS its phase if the skill isn't installed. start.shseeds the pinned org packs on boot (idempotent, non-fatal) so a volume reset doesn't lose them. The portal MCP now hasskill_*tools (list/search/info/install/create/uninstall/update).
- DB-backed in
team_agent/team_phase/team_workflow, COMPILED to the daemon's config (config-postgres). - Raw SQL edits to team_ only apply on a daemon RESTART (deploy).*
team_reloadlooks for YAML and does NOT apply DB config. To change an agent/phase LIVE without a deploy, use theteam_agent_set/team_workflow_setMCP tools (they recompile + hot-reload).team_agent_setREPLACES the profile — pass ALL fields (model, tool, mcpServers, andskillsviaextraConfig) or you drop them.
- The ao-cli daemon rewrites an
oauthMCP server into a localanimus-mcp-proxystdio command that injects the cached bearer (NOT a raw https url + Authorization header). - Deploy REQUIREMENTS: (1) the Dockerfile MUST ship
animus-mcp-proxy(+animus-hook) next toanimus— else the proxy spawn ENOENTs, the server is silently dropped, and agents get onlyanimus__*tools; (2) the device secret KEY must be DURABLE on/data(NOT regenerated each boot) — else the on-volume encrypted store (secrets.enc.v1) can't be decrypted after redeploy → all OAuth tokens wiped. After such a fix the user must re-Connect once. - The MCP UI "connected" badge should derive from token presence (
animus mcp auth-status), notteam_mcp_server.tools.
logs_tail(animus MCP) returns the BOOT window, not recent logs (log-storage-s3 query bug). For live diagnosis userailway sshinto the container: read/data/animus-state/runs/<run>/events.jsonl(agent activity + tool calls), the skills registry,animus workflow config get --json,animus skill list,animus mcp auth-status,which <binary>.- The session's cached MCP tool schemas do NOT refresh when the portal redeploys with changed tools —
verify tool changes via
plugin_list/agent_run, not the cached schema.
daemon_status→ correct version, not paused.plugin_list→ expected plugin/runner versions.- Enqueue a throwaway task →
journal_runspawns → phases execute →mark-done. - If it was an MCP/skill/team/OAuth change → verify via
agent_run/skill list/ the run behavior.
- Never edit inside
.bare/. Never commit therepos/tree (gitignored). - Match worktree dir name to its branch/version — keep the tree self-describing.
animus-launchappis a multi-part app (server/,web/,agent/), deployed on Railway; it is the service behind theanimusMCP endpoint.animus-protocolcrate version (0.1.x) is independent of its release tags (v0.7.x); trust the tag/branch for the release line, not the Cargo version.- The stock template's task/requirement workflow doc is preserved in
CLAUDE.template.md.bakfor reference, but the Animus board is the system of record.