A local-first AI dev agent for your terminal. Provider-agnostic, cost-aware, and self-improving. Your codebase stays on your machine; your prompts and traces don’t leave it.
$ uv run metis chat .
metis> help me debug src/parser.py # uses your default model (sonnet)
metis> @haiku summarize what you just did # route one turn to a cheaper model
metis> /cost # per-turn USD breakdown
metis> /model haiku # sticky switch for the rest of the session
:material-rocket-launch: Quick start{ .md-button .md-button–primary } :material-book-open: Project overview{ .md-button } :material-source-branch: GitHub{ .md-button }
=== “:material-swap-horizontal: Provider-agnostic”
One canonical message format. Three adapters — Anthropic, OpenAI,
OpenRouter. Switch models mid-session and tool-use round-trips just work.
Adding a provider is writing an adapter, not refactoring the system.
```bash
metis> @opus design a refactor strategy
metis> @sonnet implement the first step
metis> @haiku write the test fixtures
```
=== “:material-notebook-edit: Bounded memory you can git-diff”
`MEMORY.md` (~2 KB) and `USER.md` (~1.5 KB) per workspace, agent-curated.
Plain Markdown on disk under `<workspace>/.metis/`. Soft cap emits an
eviction signal; hard cap rejects the write so the agent has to consolidate.
Edit, version, and sync via git.
```text
.metis/
├── MEMORY.md # workspace memory (agent-curated)
├── USER.md # user preferences
├── routing.yaml # optional per-workspace routing rules
└── trust.yaml # tool-confirmation policy
```
=== “:material-routes: Explainable routing”
Per-message `@alias` → sticky `/model` → workspace yaml rules → learned
patterns → workspace default → global default. Every turn emits one
`route.decided` event with the full seven-slot chain trace. No silent
overrides.
```yaml
# .metis/routing.yaml
rules:
- when: { tool_only: true }
choose: haiku
- when: { content_type: code, files_touched_gte: 3 }
choose: sonnet
```
=== “:material-currency-usd: Cost in real time”
Per-turn input/output/cached tokens computed in Decimal USD (not
provider-rounded floats), versioned so historical traces can be re-priced.
Per-key, per-user, per-team rollups via `/analytics/cost`.
```text
metis> /cost
turn 1 sonnet $0.0023 (3,420 in / 412 out)
turn 2 haiku $0.0001 ( 18 in / 64 out)
session total: $0.0024
```
Two-minute path from clone to first chat. Requires Python 3.13 and uv.
git clone https://github.com/david-2814/metis && cd metis
uv sync # resolves the workspace
echo "ANTHROPIC_API_KEY=sk-ant-..." > .env # or OPENAI / OPENROUTER
uv run metis chat . # start chatting
Sanity-check the loop against the real API in under a minute (~$0.015 with haiku):
uv run python scripts/smoke.py --model haiku
Prefer a TUI? uv run metis tui . opens the Textual app over the same loop.
Want a server? uv run metis serve . --port 8421 exposes HTTP + WebSocket.
This site is built from the docs/
tree in the repo with mkdocs-material.
Four top-level sections in the nav:
Every page on this site has an Edit this page and View source action in the top-right. Both point at the exact file backing the page on GitHub. Spec edits go through a PR; the change log lives at specs/CHANGES.md.
Phase 1 + Phase 2 + Phase 2.5 + Phase 3 shipped. Wave 16 reached the GA launch milestone for the first paid cohort. 1841 tests passing.
Validated cost-savings headline: delegation at 8.3% – 26.1% better cost-per-quality (19.9% midpoint) across three independent A3 runs on the fan-out workload. Slot-4 model selection is a proof-of-mechanism from §A3-rev3; the task-domain wedge is deferred post-GA. See savings demo for the full evidence.
# One-shot preview with mkdocs-material installed on demand:
uv run --with mkdocs-material mkdocs serve
# Or via Docker (mirrors the gateway shape; serves on 127.0.0.1:8423):
docker compose --profile docs up docs
Both bind loopback-only by default. The site is pure-static once built
(mkdocs build writes to site/), so any static host works for production.