CLI tool
phodal/routa avatar
phodal/routa

Routa puts a contract on every Kanban lane so coding agents stop agreeing with themselves

Workspace-first multi-agent coordination platform for AI development, with shared Specs, Kanban orchestration, and MCP/ACP/ A2A support across web and desktop.

1,820 stars253 forksTypeScriptMIT

At a glance

What is it?
A TypeScript coordination platform where five board lanes each enforce a different prompt and evidence contract, backed by one Next.js web app and one Axum desktop server that share an API contract.
Who is it for?
Routa's real contribution is not the board and not the agent runtime, it is the refusal to let a downstream lane trust the upstream lane's own account of what happened. Todo reparses what Backlog wrote, Dev refuses to code until the story is executable, Review checks each acceptance criterion independently and will send a card backwards over a dirty git state.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 56 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 8, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Why a board instead of a chat transcript

The repository description calls Routa a workspace-first multi-agent coordination platform for AI development, and the opening line of the README states the motivation more plainly: it keeps goals, tasks, sessions, traces, evidence, and review state visible on a board instead of burying them inside a single chat thread.

That one sentence is the whole design argument. Agent tooling tends to hand you a transcript, and a transcript is a poor place to hold state once work outlasts a single turn. Which files changed, which tests ran, what was blocked and why, these are exactly the facts that scroll away. Putting them on a card turns them into something a second process can read.

The README is explicit that the board is not a reporting layer bolted on after the fact. It says the board is both the planning surface and the coordination bus, which is a stronger claim: the automation reads and writes the same cards a human reads. The five columns are Backlog, Todo, Dev, Review, and Done, and the diagram in the README shows how a single natural-language request travels across them.

text
 Backlog              Todo              Dev               Review            Done
 Backlog Refiner  ->  Todo Orchestrator -> Dev Crafter -> Review Guard -> Done Reporter

A sixth role, Blocked Resolver, sits off to the side of that flow. Its job is to write the blocker down and route the card back to the correct lane, rather than letting the problem stay implicit in a conversation.

Every lane is told to distrust the lane before it

The interesting mechanism is not the columns, it is what each column's prompt is instructed to do with the card it receives. The README's lane contract table gives each lane a specialist, a prompt obligation, an artifact written to the card, and a condition for moving on. The through-line is repeated verification.

Backlog Refiner is told to clarify scope and not to code, and it cannot move a card forward until the card contains exactly one canonical YAML story block with a problem statement, acceptance criteria, constraints, dependencies, out-of-scope items, and INVEST checks. Todo Orchestrator then distrusts that card: it reparses the YAML, rejects weak or malformed stories, and appends an execution plan, a key files and entry points list, a dependency plan, and risk notes.

Dev Crafter distrusts the plan a third time. It refuses to code unless the story is executable, implements only the scoped change, runs verification, commits, keeps git clean, and appends Dev Evidence listing changed files, work summary, tests run, per-acceptance-criterion verification, and caveats.

Review Guard is the strictest lane because it inherits the most accumulated optimism. It does not accept Dev's self-assessment; it checks each acceptance criterion independently, rejects missing evidence, rejects scope creep, rejects a dirty git state, and rejects broken lint or type checks. Only an APPROVED verdict moves the card to Done, where Done Reporter treats the column as terminal and leaves a completion record behind.

The practical consequence for a reader evaluating this project is that the cost is not the agents, it is the repeated re-derivation. The same acceptance criteria get parsed three times on the way from a sentence to a commit. That is the tradeoff the project is making deliberately.

The delivery gate is three stacked deciders, not one reviewer

Routa separates delivery approval into a distinct diagram from the lane flow, and it splits the decision into three questions asked by three different components. The README describes the gate as a stacked decision path rather than a single reviewer persona.

Harness Monitor answers what happened. It surfaces traces, changed files, commands, git state, and attribution. Entrix Fitness answers what should be true, enforcing hard gates, evidence requirements, and file budget or policy checks. Gate Specialist answers the only question that matters for moving a card, whether acceptance criteria are actually satisfied, and routes to Done, back to Dev, or to a human.

The split is useful because the three failure modes are different. An agent that produced no trace needs monitoring, an agent that produced a trace with no tests needs Fitness, and an agent that ran everything and still missed the actual requirement needs the specialist. A single reviewer prompt tends to collapse into the last of those, because it has no mechanical source of truth to check against.

The name Entrix also shows up in the Rust workspace, where `crates/entrix` is one of ten members alongside `crates/routa-server`, `crates/routa-cli`, `crates/routa-rpc`, `crates/harness-monitor`, and `crates/feature-trace`. So the gate is not only a prompt: at least two of the three roles have dedicated Rust crates behind them, which is the sort of detail that tells you the architecture diagram reflects shipped code rather than intent.

One contract, two runtimes that have to agree

The README is upfront that the implementation is intentionally dual-backend, and it stresses that this is not two separate products. Web is Next.js pages and route handlers in `src/`. Desktop is a Tauri shell in `apps/desktop/` backed by the Axum server in `crates/routa-server/`. Both runtimes are required to preserve the same workspace, session, task, trace, codebase, worktree, and review semantics, and the file that defines those semantics is `api-contract.yaml` at the repository root.

That contract file is the load-bearing artifact in this design. Everything else is an implementation of it in one language runtime or the other, and the list of concepts it has to cover is long enough that drift is a real risk: workspace, session, task, trace, codebase, worktree, review.

The integration surface is broader still. The README lists ACP, MCP, A2A, AG-UI, A2UI, REST, and SSE. Seven names covering agent-to-agent protocol, Model Context Protocol, agent-to-agent, two UI streaming protocols, plain REST, and server-sent events. The package keywords track the same set, listing agents, kanban, multi-agent, tauri, nextjs, rust, mcp, and acp.

The honest read is that a dual-runtime design buys a desktop app with local data and a web app you can host, at the cost of a translation layer that has to be maintained. Whether that cost is worth it depends on whether you need the desktop shell. If you do not, the Axum server and its five crates are optional reading.

SQLite is the default and Postgres is one flag away

The deployment story is unusually well documented for a project this young, and the comments at the top of `docker-compose.yml` state the three supported configurations directly. The default needs no external database. A bundled Postgres container is available behind a profile flag, and an external Postgres is selected by setting `DATABASE_URL` in `.env` before running compose.

bash
docker compose up
ROUTA_DB_DRIVER=postgres docker compose --profile postgres up

The application service maps port 3000, mounts a named volume at `/app/data` for the SQLite file, and carries a healthcheck that hits `http://127.0.0.1:3000/api/health` on a 30 second interval with a 30 second start period. Both the Postgres service and the schema migration service are marked `required: false`, so compose does not insist on starting them when you are on the default profile.

The `Dockerfile` explains why the image is shaped the way it is. It runs four stages off `node:22-alpine`: dependency installation with `npm ci --legacy-peer-deps` plus a retry policy and timeouts, a migrator stage that runs `npm run db:push` as the non-root `node` user, a builder stage that runs `npm run build:docker`, and a runner stage with `NODE_ENV=production`. The deps stage installs `libc6-compat python3 make g++` with the stated reason that native addons such as `better-sqlite3` need build tools.

The Docker path and the local path differ slightly and it is worth knowing which you are on. `package.json` shows `build:docker` setting `ROUTA_DESKTOP_STANDALONE=1` and then running a build script that esbuilds the SQLite TypeScript sources into the standalone chunk directory so `ROUTA_DB_DRIVER=sqlite` works at runtime. That extra compile step exists because of the container, not because of the app.

Where the version numbers and the changelog disagree

Here is the contradiction worth knowing about before you pin a dependency. `package.json` declares version 0.19.0 for the `routa-js` package, and the `[workspace.package]` block in `Cargo.toml` declares version 0.19.0 as well, so the JavaScript and Rust halves agree with each other.

The releases tell a different story about what that number means. There are three releases: v0.19.0 dated 2026-06-22 and v0.18.1 dated 2026-04-28 both consist of the line that release notes will be added manually, with v0.19.0 adding only the heading Routa Desktop v0.19.0. The third, v0.18.0 dated 2026-04-22, is a full changelog with issue numbers, covering a JIT context system, history memory snapshots, a task-adaptive harness, session transcript analysis, and new MCP tools for feature tree preload and file session summaries.

So the most recent detailed description of the software describes v0.18.0, and everything after that is a placeholder. The workable conclusion is to treat the changelog as authoritative only up to 0.18.0 and to read the current tree for anything newer. The repo does carry a `CHANGELOG.md` at the root, which is where a reader should look first, and the README points at `docs/ARCHITECTURE.md` and `docs/product-specs/FEATURE_TREE.md` for current detail rather than at the release list.

The tree is also worth reading as a signal about how the project is built. At 60 entries it is a large surface, and it contains five agent-configuration directories side by side: `.agents/`, `.augment/`, `.claude/`, `.codex/`, `.kiro/`, and `.qoder/`, alongside `AGENTS.md`, `CLAUDE.md`, and `skills-lock.json`. A project that vendors configuration for several agent tools at once is telling you something about the audience it expects. The `LICENSE` is MIT, the default branch is `main`, and the last push recorded a commit on 2026-08-13.

Editorial conclusion

Routa's real contribution is not the board and not the agent runtime, it is the refusal to let a downstream lane trust the upstream lane's own account of what happened. Todo reparses what Backlog wrote, Dev refuses to code until the story is executable, Review checks each acceptance criterion independently and will send a card backwards over a dirty git state. The dual-backend split is the part to evaluate before committing, because a Next.js route handler and an Axum handler both have to honour the same `api-contract.yaml` and a divergence there shows up as a desktop-only bug. Two things the repository does not settle: the version numbers agree across `package.json` and `Cargo.toml` at 0.19.0, but the two most recent release notes are placeholders, so the changelog cannot tell you what moved since 0.18.0. Start with `docs/ARCHITECTURE.md` and the lane contract table, then run the default SQLite profile to see the board before wiring up any agent.

Frequently asked questions

What is Routa used for in software development?

Routa is a coordination layer that puts goals, tasks, sessions, traces, evidence, and review state on a Kanban board instead of inside a chat thread. Work moves through five lanes, Backlog, Todo, Dev, Review, and Done, each backed by a different specialist prompt and a different evidence contract.

How does Routa keep an agent from marking its own work done?

It does not let a lane trust the lane before it. Dev Crafter's self-assessment is written to the card as Dev Evidence, and Review Guard then checks every acceptance criterion independently, rejecting missing evidence, scope creep, a dirty git state, or broken lint and type checks. Only an APPROVED verdict moves the card.

Do I need a database to run Routa?

No. The default profile is SQLite and needs no external database, started with `docker compose up`. Postgres is available through a compose profile using `ROUTA_DB_DRIVER=postgres docker compose --profile postgres up`, or you can point `DATABASE_URL` at an external server.

Is Routa a web app or a desktop app?

Both, deliberately. Web is Next.js pages and route handlers in `src/`, desktop is a Tauri shell in `apps/desktop/` backed by the Axum server in `crates/routa-server/`, and both are required to preserve the same semantics defined by `api-contract.yaml`.

Official sources

  1. License: MIT
  2. phodal/routa on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/phodal-routa.svg)](https://hysenlabs.com/projects/phodal-routa)