@plazmodium/odin
v0.6.3-beta
Published
Odin MCP runtime server for the 11-phase workflow
Maintainers
Readme
Odin Runtime
A single-install MCP server that gives your AI coding agent an 11-phase development workflow with built-in quality gates, skill resolution, review checks, learnings, and release archival.
Quick Start
1. Install
Preferred published-package flow:
npx -y @plazmodium/odin init --project-root /path/to/your/project --tool opencode --write-mcpMaintainer repo-checkout flow:
cd runtime
npm install
npm run build2. Bootstrap your project
# Published-package MCP command snippets
npx -y @plazmodium/odin init --project-root /path/to/your/project --tool amp --write-mcp
npx -y @plazmodium/odin init --project-root /path/to/your/project --tool opencode --write-mcp
# Source-checkout snippets while working on Odin from this repo
npm run init:project -- --project-root /path/to/your/project --tool amp --distribution source --write-mcp
npm run init:project -- --project-root /path/to/your/project --tool codex --distribution source --write-mcpThis creates:
.odin/config.yaml— runtime configuration (commit this).odin/skills/— project-local skill overrides (commit this).env.example— required environment variables (commit this)- Your harness config file (
opencode.json,.mcp.json, or.codex/config.toml, depending on tool)
Important: Odin bootstraps with runtime.mode: in_memory by default so MCP wiring can work without external services. Switch .odin/config.yaml to runtime.mode: supabase when you are ready for persistent workflow state.
If you are developing Odin from this repo, use the repo-checkout --distribution source flow shown above.
If you are the maintainer preparing that publish, use ../docs/guides/NPM-PUBLISH.md.
Manual MCP wiring
If you do not want Odin to write your harness config for you, add the MCP server manually.
For Claude Code / Amp:
{
"mcpServers": {
"odin": {
"command": "npx",
"args": ["-y", "@plazmodium/odin", "mcp"],
"env": {
"ODIN_PROJECT_ROOT": "/absolute/path/to/your/project"
}
}
}
}For OpenCode:
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"odin": {
"type": "local",
"command": [
"npx",
"-y",
"@plazmodium/odin",
"mcp"
],
"enabled": true,
"environment": {
"ODIN_PROJECT_ROOT": "/absolute/path/to/your/project"
}
}
}
}For Codex:
[mcp_servers.odin]
command = "npx"
args = ["-y", "@plazmodium/odin", "mcp"]
env = { ODIN_PROJECT_ROOT = "/absolute/path/to/your/project" }For Cursor, use the same command, args, and env values in the MCP Servers settings UI.
3. Add your database credentials
cp .env.example .env
# Edit .env with your database credentialsUse the project root .env or .env.local file that lives next to opencode.json / .mcp.json / .odin/. Odin does not read env files from nested app directories.
Runtime config is loaded once at server startup. If you change .env, .env.local, or .odin/config.yaml, restart the Odin MCP server before retrying tools.
Odin uses two database paths today:
Direct PostgreSQL (any provider — Neon, Railway, self-hosted, local Supabase Postgres, etc.) for
odin.apply_migrations:DATABASE_URL=postgresql://user:password@host:5432/dbnameSupabase runtime + management API for full persistent Odin workflow state plus archival:
SUPABASE_URL=https://your-project.supabase.co SUPABASE_SECRET_KEY=your-secret-key SUPABASE_ACCESS_TOKEN=your-management-api-access-token
DATABASE_URL takes priority inside odin.apply_migrations. It does not replace Supabase-backed workflow state for the main runtime.
4. Start using Odin
Recommended feature-start flow:
npx -y @plazmodium/odin start-feature \
--project-root /path/to/your/project \
--id AUTH-001 \
--name "Login" \
--complexity-level 2 \
--severity ROUTINE \
--author "Jane Doe" \
--dev-initials jdThis command creates or switches to the feature branch first, then calls odin.start_feature so the runtime record matches the real git workspace.
Your AI agent now has these tools available:
| Tool | Purpose |
|------|---------|
| odin.start_feature | Record a feature in the workflow after the branch already exists |
| odin.get_next_phase | Ask "what should happen next?" |
| odin.pick_next_autonomous_phase | Let Ralph Loop pick the next safe feature/phase and return prepared context |
| odin.prepare_phase_context | Get the full working bundle for a phase, including harness execution guidance |
| odin.get_development_eval_status | Inspect focused development-eval state for a feature |
| odin.record_phase_artifact | Register a phase output (PRD, spec, tasks, etc.) |
| odin.submit_claim | Submit a watched-agent claim for policy and watcher verification |
| odin.record_commit | Persist git commit metadata for a feature |
| odin.record_pr | Persist pull request metadata for dashboard/git tracking and return the current automation snapshot |
| odin.record_merge | Persist that a human merged the feature PR and return the current automation snapshot |
| odin.record_release_handoff | Close the active Release invocation after PR handoff while keeping the feature in phase 9 |
| odin.record_release_handoff_failure | Close the active Release invocation after a failed PR handoff attempt so Ralph Loop can retry later |
| odin.record_release_closeout_failure | Close the active Release invocation after a failed release closeout attempt so Ralph Loop can retry later |
| odin.record_quality_gate | Persist an explicit workflow quality gate decision |
| odin.record_supervisor_event | Persist Ralph Loop tick/no-op/failure/completion events for operator visibility |
| odin.record_eval_plan | Persist a structured Architect eval_plan artifact |
| odin.record_eval_run | Persist a structured Reviewer/Integrator eval_run artifact |
| odin.record_phase_result | Record phase completion, blocking, or rework |
| odin.run_review_checks | Run security/review scans via Semgrep |
| odin.run_policy_checks | Run deterministic policy checks for submitted claims |
| odin.verify_design | Run formal design verification (TLA+ model checking) on a .machine.ts DSL file |
| odin.capture_learning | Capture a reusable learning with semantic domain matching |
| odin.get_skill_proposal_queue | Inspect repeated unresolved learning topics that may warrant a generated skill draft |
| odin.get_skill_proposals | List drafted, approved, rejected, or published skill proposal records |
| odin.record_skill_proposal_draft | Persist a drafted generated-skill proposal and run deterministic validation |
| odin.record_skill_proposal_decision | Approve or reject a drafted skill proposal |
| odin.publish_skill_proposal | Publish an approved skill proposal into .odin/skills/generated/ |
| odin.sync_skill_proposal_candidates | Persist the current deterministic proposal queue for later review/approval workflows |
| odin.get_feature_status | Inspect feature state with workflow details, invocation coverage, and the current automation snapshot |
| odin.verify_claims | Check claim verification status |
| odin.get_claims_needing_review | List claims waiting for watcher review |
| odin.record_watcher_review | Record the watcher verdict for an escalated claim |
| odin.archive_feature_release | Archive release artifacts to Supabase Storage |
| odin.explore_knowledge | Explore knowledge clusters, cross-domain bridges, and domain stats |
| odin.apply_migrations | Apply pending database migrations (auto-detects existing schema) |
Dashboard
@plazmodium/odin ships the MCP runtime only. It does not bundle the Next.js dashboard.
If you want the dashboard UI for feature health, learnings, claims, and eval visibility, use the full Odin repository and run the dashboard app from dashboard/.
The dashboard is a separate app and is not included in the npm tarball.
Configuration
Odin uses two files:
.odin/config.yaml (committed) — project-level config with env var interpolation:
runtime:
mode: in_memory # quick-start mode; switch to "supabase" for persistent workflow state
database:
url: ${DATABASE_URL} # used by odin.apply_migrations for direct PostgreSQL
supabase:
url: ${SUPABASE_URL}
secret_key: ${SUPABASE_SECRET_KEY}
skills:
paths:
- .odin/skills
auto_detect: true
review:
provider: semgrep
automation:
mode: guarded
allowed_base_branches: []
require_green_checks: true
require_clean_policy_checks: true
require_no_open_blockers: true
require_watched_claims_verified: true
paused: false
kill_switch: false
merge_strategy: squash
formal_verification:
provider: none # set to "tla-precheck" after installing Java 17+ and `npm install -D tla-precheck`
timeout_seconds: 120
archive:
provider: none.env (uncommitted) — secret values:
# Option A: Direct PostgreSQL for odin.apply_migrations
DATABASE_URL=postgresql://user:password@host:5432/dbname
# Option B: Supabase runtime + management API
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SECRET_KEY=your-secret-key
SUPABASE_ACCESS_TOKEN=your-management-api-access-tokenRuntime Modes
supabase— Full persistent workflow state backed by Supabase. RequiresSUPABASE_URLandSUPABASE_SECRET_KEY. Enablearchive.provider: supabasewhen you want release archival too.in_memory— Zero-dependency smoke-test mode. State is lost when the process exits. Useful for testing MCP wiring and prompt flow before provisioning Supabase.
Note on
DATABASE_URL: today it powersodin.apply_migrations, including local PostgreSQL or local Supabase Postgres access. The main Odin workflow runtime still uses the Supabase workflow-state adapter whenruntime.mode: supabase.
Automation Modes
guarded— default; humans remain the PR creation/review/merge boundaryauto_pr— opt-in; autonomous PR recording is allowed only on allowlisted base branches with clean blockers/gates/policy checksauto_merge— reserved for future use and intentionally unsupported today; runtime startup fails fast if configured
Notes:
allowed_base_branches: []is intentionally deny-by-default for autonomous PR actionspaused: truetemporarily stops autonomous actions without changing the configured modekill_switch: truehard-stops autonomous actions until a human re-enables themodin.prepare_phase_contextincludes anautomationblock so agents/orchestrators can inspect the effective policy and blocking reasons before attempting PR actionsodin.get_feature_statusalso returns the currentautomationsnapshot and invocation-coverage summaries for out-of-band orchestration checks or release status readsodin.pick_next_autonomous_phasegives a queue-safe read path for Ralph Loop style orchestration without inventing a second workflow engine inside the runtimeodin.record_release_handofflets an external loop runner archive/create/record a PR, then close the active Release invocation cleanly while waiting for human mergeodin.record_supervisor_eventlets an external loop runner publish operational state intoaudit_logwithout coupling itself directly to Supabaseodin.record_prandodin.record_mergereturn the currentautomationsnapshot with the recorded metadata so orchestrators can keep policy state alongside persisted PR/merge facts- PR creation and merge execution still happen outside the runtime via git/GitHub tooling, so the trusted enforcement boundary in this release is the orchestrator consulting
context.automationbefore it acts; the record tools persist facts after the external action happens - after a merge is recorded,
odin.record_phase_result({ phase: '9', outcome: 'completed', next_phase: '10' })now uses the runtime-owned completion flow instead of a raw status flip
Harness Execution Modes
Odin phase agents are logical phase roles, not runtime-owned worker processes.
context.agent.nameis the canonical Odin phase role for the selected phasecontext.execution.phase_role_namerepeats that canonical role explicitlycontext.execution.acting_agent_nameis the resolved acting label used for invocation tracking in the current run
If a harness spawns a child agent, that child is acting as the current Odin phase role. The runtime still does not launch or supervise that child itself.
odin.prepare_phase_context(...) now returns an execution block with:
supported_modes- currentlyinlineandsubagentrecommended_mode- guidance only; not enforcementexecution_policy- whether inline execution is allowed, distinct sessions are preferred, or distinct sessions are requiredprompt_realization_policy- whether using the canonical Odin phase prompt bundle is optional, preferred, or requiredchild_state_strategy- whether the harness should prefer directodin.*calls from the child when available or have the child return intent to the parent sessionresponse_style- whether internal execution chatter should staynormalor useterse_executionphase_prompt_manifest- the canonical manifest describing the shared context, phase definition, resolved skills, prompt sections, and dynamic context bundle used for strict phase-prompt realization attestationprompt_sections- the fields the harness should keep in the active prompt
context.agent.constraints already includes context.development_evals.harness_prompt_block. Keep the dedicated eval block visible if you want a separate eval section, but do not append both verbatim or the same instructions will appear twice.
Canonical harness flow:
1. Call odin.prepare_phase_context({ feature_id, phase, agent_name }).
2. Build the prompt from:
- context.agent.name
- context.agent.role_summary
- context.agent.constraints
- context.automation
- context.verification
- context.workflow
- context.artifacts
- context.skills.resolved
- context.learnings
3. Choose execution mode:
- inline: parent session performs the phase work directly
- subagent: parent session spawns a child that acts as the current Odin phase role
4. Record the actual mode with `odin.register_phase_execution(...)` when you want auditable phase ownership.
5. If the child is meant to count as a strict Odin phase-agent run, register prompt realization with `odin.register_phase_realization(...)` using the returned `phase_prompt_manifest`.
6. Record artifacts, claims, checks, and gates through odin.* tools as work happens.
7. Close the phase with odin.record_phase_result(...).If the child agent cannot call odin.* directly, keep the same flow but have the child return a clear State Changes Required section and the parent session performs those calls on the child's behalf. When proxying, pass context.execution.acting_agent_name through to tool fields such as agent_name and created_by so attribution and invocation tracking stay aligned with the prepared phase context.
Execution attestation rules:
- invocation open/close telemetry is not proof of distinct-session execution
odin.register_phase_execution(...)records the harness-attested actual mode plus supervisor/worker session linkageodin.register_phase_realization(...)records whether the child was launched from the canonical Odin phase prompt bundleodin.record_phase_result(...)may warn or reject based onexecution_policyodin.record_phase_result(...)may also warn or reject based onprompt_realization_policyodin.get_feature_status(...)exposes expected vs actual vs proven execution state for auditing
response_style is a bounded internal execution hint, not a global constitution change:
- use it for harness/child operational chatter and short execution summaries
- do not silently apply it to direct user chat by default
- do not use it as a reason to rewrite durable human-facing artifacts like PRDs, specs, tasks, docs, changelogs, or release notes into compressed prose
Optional: TLA+ Design Verification
odin.verify_design is optional and stays disabled while formal_verification.provider is none.
Install it in the target project Odin runs against, not in the runtime package:
# In your target project root
npm install -D tla-precheckRequirements and setup:
- Install Java 17+ locally for the TLC model checker
- Install
tla-precheckas a dev dependency in the target project so Odin can resolve it fromnode_modules/.bin - Enable it in
.odin/config.yaml
formal_verification:
provider: tla-precheck
timeout_seconds: 120Typical usage:
- Create a state-machine file such as
specs/BILLING-001/subscription.machine.ts - Ask Odin to run
odin.verify_designwith that relativemachine_path - Review the result in Architect/Guardian before implementation
If Java or tla-precheck is missing, Odin returns an UNAVAILABLE / NOT_CONFIGURED result for design verification instead of enabling it silently.
Development Evals
Odin also supports a lightweight Development Evals workflow track:
- Architect records
eval_planviaodin.record_eval_plan(orodin.record_phase_artifact) - Guardian records
eval_readinessviaodin.record_quality_gate - Reviewer records
eval_runviaodin.record_eval_run(orodin.record_phase_artifact) - Integrator may append a later
eval_runviaodin.record_eval_runwhen runtime verification materially changes the result
These artifacts are surfaced in odin.prepare_phase_context and odin.get_feature_status.
When Development Evals are relevant, odin.prepare_phase_context returns a richer development_evals block with:
expected_artifacts— which eval artifact(s) this phase is expected to produce nowexpected_gate— which eval gate this phase is expected to decide nowstatus_summary— current eval state the harness should keep visibleharness_prompt_block— phase-specific prompt lines the harness should append verbatim to the active agent prompt
Recommended harness behavior:
1. Call odin.prepare_phase_context(...)
2. Build the agent prompt from:
- context.agent.name
- context.agent.role_summary
- context.agent.constraints
3. Choose inline vs subagent execution using context.execution.recommended_mode as guidance
4. If the child cannot call odin.* directly, proxy the required state changes from the parent session and pass `context.execution.acting_agent_name` through to `agent_name` / `created_by`
5. Keep context.development_evals.status_summary visible to the operator
6. Do not treat eval instructions as a replacement for formal verification, Semgrep, tests, runtime checks, or watcher checksCanonical eval-aware orchestration snippet:
When orchestrating Odin phases:
1. Call odin.prepare_phase_context({ feature_id, phase, agent_name }).
2. Build the active agent prompt from:
- context.agent.name
- context.agent.role_summary
- context.agent.constraints
3. Use context.execution.recommended_mode as the default inline/subagent choice, but keep Release strongly parent-session controlled.
4. If the child cannot call odin.* directly, have it return state-change intent and let the parent session proxy those calls with `context.execution.acting_agent_name` as the relevant `agent_name` / `created_by` value.
5. Use odin.get_development_eval_status({ feature_id }) when you need focused eval state.
6. Record eval artifacts/gates with odin.record_eval_plan, odin.record_eval_run, and odin.record_quality_gate.
7. Never let Development Evals override odin.verify_design, odin.run_review_checks, tests, runtime verification, or watcher checks.If the harness wants a focused eval-only read path instead of parsing odin.get_feature_status, call:
odin.get_development_eval_status({ feature_id: "FEAT-001" })This returns the current Development Eval mode, latest eval_plan, latest eval_run, open eval_readiness gate (if any), and recent eval artifact history.
Important: Development Evals are additive. They do not replace odin.verify_design, odin.run_review_checks, Builder/Integrator test verification, or watched-claim verification.
Project-Local Skills
Drop skill files into .odin/skills/ to override or extend built-in skills:
.odin/skills/
my-framework/
SKILL.mdOdin resolves project-local skills with higher precedence than built-in skills when names match.
Approved generated skills publish into .odin/skills/generated/ so they are visible to the normal project-local skill resolver without mutating Odin's packaged built-ins.
Memory Palace: Semantic Learning Propagation
Odin's learning system uses semantic domain matching to automatically route learnings to the right knowledge targets (skills, agent definitions, AGENTS.md).
How it works
- Capture with tags: When calling
odin.capture_learning, agents providedomain_tags— conceptual keywords describing what the learning is about (e.g.,["nextjs", "fetch-cache", "supabase"]) - Domain matching: The runtime matches tags against a knowledge domain registry derived from skill frontmatter. Each skill's
name,compatible_with,depends_on,category, anddescriptiongenerate keyword tiers (strong + weak) - Auto-targeting: Matches passing both gates (≥ 1 strong keyword hit AND ≥ 0.60 relevance) are auto-declared as propagation targets. Weaker matches are returned as suggestions
- Cross-feature corridors:
odin.prepare_phase_contextretrieves related learnings from other features that share propagation targets, with tag intersection fallback - Resonance ranking: Related learnings are ranked by domain density, corroboration (same-category learnings from different features), and recency — never modifying
confidence_score - Proposal surfacing: Repeated unresolved tags can be inspected via
odin.get_skill_proposal_queueto identify candidate topics for governed skill drafting - Proposal persistence:
odin.sync_skill_proposal_candidatessnapshots the current candidate queue into workflow state so later approval/draft flows and dashboard surfaces can build on stable relational state - Governed skill workflow: draft generation, approval, and publish happen through
odin.record_skill_proposal_draft,odin.record_skill_proposal_decision, andodin.publish_skill_proposalrather than automatic built-in self-modification
Exploration
Use odin.explore_knowledge to inspect knowledge clusters:
- Learnings grouped by domain
- Cross-domain bridges (learnings appearing in multiple domains)
- Domain density stats
- Unmatched tags (tags that matched zero domains)
Adding a domain
Adding a new skill with proper frontmatter (name, description, category, compatible_with, depends_on) automatically creates a new knowledge domain — zero configuration, zero migration.
Development
npm run type-check # Check types without emitting
npm run build # Compile TypeScript to dist/
npm test # Run tests
npm start # Start the MCP server (stdio)
npm run dev # Watch modeArchitecture
Odin presents one MCP server (odin) to your AI agent. Internally it uses adapter seams for different concerns:
- WorkflowStateAdapter — Supabase-backed feature/phase state
- SqlExecutor — Provider-agnostic SQL execution (direct PostgreSQL or Supabase Management API)
- ArchiveAdapter — Supabase Storage for release archives (direct upload, no Edge Function needed)
- ReviewAdapter — Semgrep for security/code review
- FormalVerificationAdapter — TLA+ model checking via tla-precheck (opt-in)
- SkillAdapter — Filesystem-based skill resolution (built-in + project-local)
Providers are internal implementation details — your agent only sees odin.* tools.
Requirements
- Node.js >= 18
- PostgreSQL database — any provider: Supabase, Neon, Railway, self-hosted, etc. (for
supabaseruntime mode) - Semgrep (optional, for review checks — falls back to Docker if local binary not found)
- Java 17+ and tla-precheck (optional, for formal design verification — install as a devDependency in your target project)
