{"slug": "show-hn-syntra-a-terminal-first-control-plane-for-multi-model-coding", "title": "Show HN: Syntra – A terminal-first control plane for multi-model coding", "summary": "Syntra, an open-source terminal-first control plane for multi-model AI coding, has entered public beta. The tool routes coding tasks through separate planner, executor, and reviewer models, storing structured state files instead of a single chat log. It aims to give developers inspectability and control over AI model usage.", "body_md": "**Open-source control plane for coding with multiple AI models. Routes planning, execution, and review separately — with durable task state and receipts.**\n\nStop betting an entire coding task on one opaque model. Syntra is a terminal-first coordination layer that lets you inspect, override, and audit how models are used.\n\nEarly public beta:Use it, stress it, and report bugs or improvements. Expect rough edges while the core experience is hardened.\n\n*Syntra's terminal cockpit: plan, execute, review, inspect the activity trail, and see the active model route in one workspace.*\n\nYou give Syntra one coding task. It:\n\n- Picks a\n**planner** model (high intelligence) to break the task into steps. - Picks an\n**executor** model (fast/specialized for coding) to do each step. - Picks a\n**reviewer** model (good at verification) to check the result. - Stores\n`task.json`\n\n,`plan.json`\n\n,`decisions.json`\n\n,`failures.json`\n\n,`summary.json`\n\n,`cost.json`\n\n— typed state, NOT one fat chat log. - Shows the model route, reason, provider, and estimated/recorded cost.\n\nRouting starts from an editable, capability-tagged catalog. The bundled catalog is an **approximate seed snapshot**, not a guarantee of live benchmark data; inspect routes, refresh available data, override the catalog, or pin models yourself.\n\n**Syntra is TUI-first.** Just run `syntra`\n\n(no arguments) to open the full-screen cockpit —\npanels, themes, live trace, and slash commands — the recommended way to use it. If you'd\nrather script it or stay on the command line, the **full CLI is available too**:\n`syntra run \"<task>\"`\n\nfor a one-shot run, or `syntra --plain`\n\nfor a simple line session.\nMost core workflows have CLI equivalents; a few cockpit conveniences are TUI-only.\n\nPlain-English guides for everything Syntra does — what each feature is, how to use it, with examples:\n\n— the complete guide + quickstart (read this first).[docs/GUIDE.md](/AyushParkara/syntra/blob/main/docs/GUIDE.md)— common[docs/COMMANDS.md](/AyushParkara/syntra/blob/main/docs/COMMANDS.md)`syntra`\n\ncommands, with pointers to`--help`\n\nfor advanced commands.— common settings, files, and environment variables.[docs/CONFIG.md](/AyushParkara/syntra/blob/main/docs/CONFIG.md)— threat model (local-first), the security audit, and what's hardened.[docs/SECURITY.md](/AyushParkara/syntra/blob/main/docs/SECURITY.md)— maintainer checklist for GitHub Releases and PyPI.[docs/RELEASING.md](/AyushParkara/syntra/blob/main/docs/RELEASING.md)— GitHub settings needed before the public-beta announcement.[docs/REPOSITORY_SETUP.md](/AyushParkara/syntra/blob/main/docs/REPOSITORY_SETUP.md)— complete community, security, release, and support checklist for maintainers.[docs/PUBLIC_BETA_CHECKLIST.md](/AyushParkara/syntra/blob/main/docs/PUBLIC_BETA_CHECKLIST.md)— where users should ask questions, report bugs, and report security issues.[SUPPORT.md](/AyushParkara/syntra/blob/main/SUPPORT.md)**Feature guides**([docs/features/](/AyushParkara/syntra/blob/main/docs/features)):[Model selection](/AyushParkara/syntra/blob/main/docs/features/MODEL_SELECTION.md)·[Reliability & failover](/AyushParkara/syntra/blob/main/docs/features/RELIABILITY.md)·[Quality & review](/AyushParkara/syntra/blob/main/docs/features/QUALITY_AND_REVIEW.md)·[Providers, caching & MCP](/AyushParkara/syntra/blob/main/docs/features/PROVIDERS_CACHING_MCP.md)·[Tools & safety](/AyushParkara/syntra/blob/main/docs/features/TOOLS_AND_SAFETY.md)\n\nFound a bug, confusing workflow, rough edge, or missing capability? Open a **GitHub Issue** with\nthe steps and context, or a **Pull Request** to propose a fix. The highest-value beta feedback is:\n\n- a real task where routing picked the wrong model;\n- an install, provider, safety, or TUI workflow that was confusing;\n- a reproducible cost, reliability, or verification problem; or\n- a small documentation, provider, routing, safety, or benchmark contribution.\n\nRead [CONTRIBUTING.md](/AyushParkara/syntra/blob/main/CONTRIBUTING.md) before changing safety-sensitive code. Never post API keys,\nprivate provider configuration, project files, or `.syntra/`\n\ntask state in an issue.\n\n```\nuv tool install syntra\n# or: pipx install syntra\n# or: python3 -m pip install --user syntra\n```\n\nUse this after `syntra`\n\nhas been published to PyPI. Confirm the installed version with:\n\n```\nsyntra --version\ngit clone https://github.com/AyushParkara/syntra.git\ncd syntra\npython3 -m pip install -e .\n```\n\nThis is the right path for contributors and for trying the repository before a PyPI release exists.\n\n```\nsyntra\n```\n\nBare `syntra`\n\nlaunches the full-screen TUI — panels, ~20 themes, a live activity trace, a\ncommand palette (type `/`\n\n), and inline `@`\n\n-file autocomplete. This is the primary interface;\neverything below is also reachable as a CLI command if you prefer the terminal or scripting.\n\n```\nsyntra catalog\n```\n\nShows every model with intelligence index, speed, price, context window, role suitability, and capability tags. Sorted by intelligence.\n\n```\nsyntra route planner\nsyntra route executor\nsyntra route reviewer\nsyntra route executor --quality-bias 0.1   # cost-first\nsyntra route executor --quality-bias 1.0   # quality-first\nsyntra route executor --needs-long-context\n```\n\nEach call prints the picked model, the reason (with capability tags), the provider that would serve it, and the runners-up.\n\n```\nsyntra providers\n```\n\nReads `~/.config/syntra/providers.json`\n\nand lists every endpoint with whether it has a key, how many model IDs it claims to serve, and its base URL.\n\nInside the TUI, just type your task and hit enter. From the CLI, the one-shot equivalent is:\n\n```\nsyntra run \"Write a Python function that reverses a linked list, with a small test.\"\n```\n\nYou'll see live `[route]`\n\nand `[usage]`\n\nlines as planner -> executor -> reviewer runs, then a final summary with total tokens and cost. State is written to `.syntra/tasks/<task-id>/`\n\n.\n\n```\nsyntra tasks                       # list all past tasks\nsyntra task <task-id>              # inspect one task's stored state\n```\n\nProvider config lives at `~/.config/syntra/providers.json`\n\n(NEVER in this repo). The file shape:\n\n```\n{\n  \"providers\": [\n    {\n      \"name\": \"openrouter\",\n      \"display_name\": \"OpenRouter\",\n      \"base_url\": \"https://openrouter.ai/api/v1\",\n      \"api_key_env\": \"OPENROUTER_API_KEY\",\n      \"allowed_models\": [\"anthropic/claude-opus-4.7\", \"openai/gpt-5\"]\n    },\n    {\n      \"name\": \"deepseek\",\n      \"display_name\": \"DeepSeek\",\n      \"base_url\": \"https://api.deepseek.com\",\n      \"api_key\": \"YOUR_DEEPSEEK_KEY\",\n      \"allowed_models\": [\"deepseek-chat\", \"deepseek-reasoner\"]\n    }\n  ]\n}\n```\n\nRules:\n\n`api_key_env`\n\nresolves from environment at load time. Use this for keys you want in your shell config, not the JSON.`api_key`\n\naccepts the literal key, or`\"no-auth\"`\n\nfor self-hosted endpoints with no auth.`allowed_models`\n\nrestricts which model IDs this endpoint will serve. Omit for a wildcard endpoint.- Provider order is precedence order. If two endpoints can serve the same model id, the earlier one wins.\n- See\n`syntra/data/providers.example.json`\n\nfor a template covering the common providers.\n\nThe file should be `chmod 600`\n\nbecause it contains live API keys. The repo `.gitignore`\n\nblocks any `providers.json`\n\nfrom being committed.\n\nThe catalog at `syntra/data/aa_catalog.json`\n\nis the source of truth for capability-aware routing. It ships with a hand-tuned snapshot of well-known models, tagged with role/specialty metadata that the router uses to score picks. **You do not need to refresh it for Syntra to work** — the seeded data is good enough as a starting point.\n\nArtificial Analysis publishes its benchmark leaderboards publicly and offers a free, rate-limited Data API for primary benchmark, speed, and pricing metrics. To refresh supported catalog values (for example intelligence-style scores, speed, prices, and context windows), create an API key in your Artificial Analysis account and run:\n\n-\nOpen your Artificial Analysis account/API dashboard and create or copy an API key. Their free Data API has a published rate limit; consult their current API documentation for the limit and access terms.\n\n-\nExport it:\n\n`export ARTIFICIALANALYSIS_API_KEY=\"aa-...\"`\n\n-\nRefresh:\n\n```\nsyntra catalog refresh           # writes back to the configured catalog path\nsyntra catalog refresh --dry-run # see what would change without writing\n```\n\nThe refresh updates supported values for models already in the catalog. It can add models reported by the upstream source, but those new rows do not automatically gain Syntra's role/specialty tags — those remain an editorial layer under your control.\n\nIf you skip refresh forever, the seeded catalog still works. The capability *tags* matter more than the exact numbers for routing decisions.\n\n```\n.syntra/\n└── tasks/\n    └── <task-id>/\n        ├── task.json          # goal, status, timestamps\n        ├── plan.json          # steps produced by the planner\n        ├── decisions.json     # durable choices made during the run\n        ├── failures.json      # attempts that didn't work and why\n        ├── summary.json       # compressed running summary\n        ├── cost.json          # tokens + USD by role+model\n        └── events.jsonl       # append-only audit log\n```\n\nThis is the anti-compaction structure. Compaction can throw away disposable chat reasoning all it wants; the durable state lives in these files and survives across resumes.\n\n`--quality-bias 0.0 .. 1.0`\n\n— 1.0 = always pick the smartest model. 0.0 = always pick the cheapest that meets requirements. Default 0.8.`--planner <model_id>`\n\n,`--executor <model_id>`\n\n,`--reviewer <model_id>`\n\n— pin specific models, override the router.`SYNTRA_STATE_DIR`\n\n— where to put`.syntra/`\n\n. Defaults to current working directory.`SYNTRA_PROVIDERS_FILE`\n\n— override provider config path.`SYNTRA_CATALOG_PATH`\n\n— override catalog path.\n\nThe cognitive loop came first; on top of that solid base, Syntra now also has:\n\n**Agentic tool use**— read/write/edit files,`apply_patch`\n\n(multi-file atomic edit bundles), shell (sandboxed), grep/glob, git, web fetch/search, optional browser tools.**Safety layers**— command classification + Bubblewrap sandbox, an approval gate for writes/exec, sensitive-file protection, and`AGENTS.md`\n\n/`CLAUDE.md`\n\nauto-loading.**Full-screen TUI**— panels, ~20 themes (light/dark aware), live activity trace, a command palette, and inline`@`\n\n-file autocomplete.**Reliability**— multi-provider/multi-key failover, route-health memory, prompt caching, and silent-failure detection.** Quality**— a 3-lens reviewer, a verification gate, proof artifacts, Reflexion retries, and an optional review panel (PoLL).** Memory & MCP**— durable per-session memory/learnings, plus MCP tools attachable over stdio or HTTP.** Per-role reasoning control**— reasoning effort (`low|medium|high|xhigh|max|auto`\n\n) and graceful degrade when a model/key doesn't support the param.\n\n```\ngoal\n  │\n  ▼\ncatalog ─► router ─► role pick (planner)\n                │\n                ▼\n            registry ─► endpoint (provider+url+key)\n                │\n                ▼\n         provider HTTP call ─► result\n                │\n                ▼\n         step result in plan.json\n                │\n                ▼\n  (repeat for each step with executor)\n                │\n                ▼\n        reviewer pass with full plan+results\n                │\n                ▼\n       verdict + summary.json + cost.json\nsyntra/\n├── core/          the engine — routing, the planner/executor/reviewer loop, typed\n│                  task state, providers/registry, tools + sandbox + permissions,\n│                  memory, MCP, hooks, and the TUI building blocks (widgets, overlays,\n│                  themes, fuzzy matcher, edit-bundle patch parser, …)\n├── providers/     OpenAI-compatible + anthropic/gemini/responses adapters\n├── skills/        17 built-in skills (see docs/SKILLS_AND_PLUGINS.md)\n└── cli/\n    ├── main.py    the CLI surface — `run`, `route`, `catalog`, `providers`, `doctor`,\n    │              `resume`, `compare`, `tasks`, … and more\n    ├── tui2.py    the full-screen curses cockpit (bare `syntra`)\n    └── inline_tui.py  opt-in native-scrollback \"inline\" mode (`--inline`)\n```\n\nPure-Python, standard-library only — no runtime dependencies. Browse `syntra/core/`\n\nfor the full engine surface.", "url": "https://wpnews.pro/news/show-hn-syntra-a-terminal-first-control-plane-for-multi-model-coding", "canonical_source": "https://github.com/AyushParkara/syntra", "published_at": "2026-07-17 13:00:40+00:00", "updated_at": "2026-07-17 13:21:25.909697+00:00", "lang": "en", "topics": ["ai-tools", "developer-tools", "large-language-models", "ai-agents"], "entities": ["Syntra"], "alternates": {"html": "https://wpnews.pro/news/show-hn-syntra-a-terminal-first-control-plane-for-multi-model-coding", "markdown": "https://wpnews.pro/news/show-hn-syntra-a-terminal-first-control-plane-for-multi-model-coding.md", "text": "https://wpnews.pro/news/show-hn-syntra-a-terminal-first-control-plane-for-multi-model-coding.txt", "jsonld": "https://wpnews.pro/news/show-hn-syntra-a-terminal-first-control-plane-for-multi-model-coding.jsonld"}}