-# Chorus
+# Polyphony
**A second opinion (and a third) before you ship AI-written code — using the AI subscriptions you already pay for.**
2–3 _different_ AI tools review the same change in parallel, only green-lighting when they agree. Runs on your existing Claude Pro / ChatGPT Plus / Gemini Advanced — typical review costs **$0** out of pocket.
-[](https://github.com/chorus-codes/chorus/actions/workflows/ci.yml)
-[](https://www.npmjs.com/package/chorus-codes)
+> Formerly **Chorus**. The `chorus` CLI binary, `~/.chorus/` config directory, and `chorus` MCP registration all still work — see [Compatibility](#compatibility) below.
+
+[](https://github.com/crypticpy/chorus/actions/workflows/ci.yml)
+[](https://www.npmjs.com/package/@crypticpy/polyphony)
[](./LICENSE)
[](./ROADMAP.md)
[](https://nodejs.org/)
@@ -22,7 +24,7 @@
-

+

**One AI writes. Three review. You ship only when they agree — using AI subscriptions you already pay for.**
@@ -30,7 +32,7 @@
---
-## The problem Chorus solves
+## The problem Polyphony solves
🤖 **AI coding tools are confident — and wrong about 5% of the time** in subtle ways that are hard to spot until production.
@@ -40,16 +42,16 @@ Asking GPT to review GPT's work is theatre — same training, same biases.
💸 **Multi-AI review on raw API keys gets expensive fast.**
Every diff × 3 reviewers × pay-per-token = real money. So nobody does it routinely.
-### Chorus fixes all three
+### Polyphony fixes all three
✅ **Different vendors review each other.**
Claude writes, GPT and Gemini check it. Different blind spots cover each other. Disagreement = red flag _before_ you merge.
✅ **Uses your existing AI subscriptions.**
-You're already paying for Claude Pro / ChatGPT Plus / Gemini Advanced (~$20/mo each). Chorus drives them headlessly through their CLIs — every multi-AI review costs **$0 out of pocket**, just counts against the quota you already have. Per-token API users save 10-100× vs running the same prompts directly.
+You're already paying for Claude Pro / ChatGPT Plus / Gemini Advanced (~$20/mo each). Polyphony drives them headlessly through their CLIs — every multi-AI review costs **$0 out of pocket**, just counts against the quota you already have. Per-token API users save 10-100× vs running the same prompts directly.
✅ **Local-first, zero markup.**
-Your code never reaches a new vendor. Chorus runs on your laptop, talks to the AI tools you already trust, and shuts up. Open source, Apache-2.0.
+Your code never reaches a new vendor. Polyphony runs on your laptop, talks to the AI tools you already trust, and shuts up. Open source, Apache-2.0.
That's the whole pitch.
@@ -59,23 +61,23 @@ That's the whole pitch.
🚨 **You asked Claude to write a `divide(a, b)` helper.**
It says "looks correct!" You ship. Production crashes at 2am because nobody handled `b = 0`.
-_With Chorus: GPT or Gemini would have flagged it in the review pass before you merged._
+_With Polyphony: GPT or Gemini would have flagged it in the review pass before you merged._
🔧 **You're refactoring a critical path.**
Your AI rewrote 200 lines and says it's behaviour-equivalent. You're tired and skeptical.
-_Run it through Chorus. Three different AIs all saying "yes, equivalent" lets you sleep._
+_Run it through Polyphony. Three different AIs all saying "yes, equivalent" lets you sleep._
🏗️ **Big architectural call** — queue vs polling, sync vs async, this DB vs that one.
-Write a paragraph, hit Chorus. _Three different models give you three angles you hadn't thought of._
+Write a paragraph, hit Polyphony. _Three different models give you three angles you hadn't thought of._
📝 **Reviewing a 600-line PR.**
-You're short on time. Paste the diff into Chorus. _Three reviewers spot the obvious bugs in 90 seconds. Your job becomes the 5% they couldn't catch._
+You're short on time. Paste the diff into Polyphony. _Three reviewers spot the obvious bugs in 90 seconds. Your job becomes the 5% they couldn't catch._
⚔️ **Test-driven development where neither AI cheats.**
_One AI writes tests blind to the code; another AI writes code to pass them._ Use the `red-green` template.
🐛 **Hunting a flaky bug.**
-Reproduces 1-in-20, no obvious pattern. Drop the failing test + suspect code into Chorus.
+Reproduces 1-in-20, no obvious pattern. Drop the failing test + suspect code into Polyphony.
_Each reviewer attacks the bug from a different angle — race? clock skew? off-by-one? — and you land on the cause faster than walking it alone._
---
@@ -83,11 +85,13 @@ _Each reviewer attacks the bug from a different angle — race? clock skew? off-
## Quick start
```bash
-npm i -g chorus-codes # install (no sudo — see below)
-chorus init # finds AI tools you already have, wires up MCP
-chorus start --ui # opens http://localhost:5050
+npm i -g @crypticpy/polyphony # install (no sudo — see below)
+chorus init # finds AI tools you already have, wires up MCP
+chorus start --ui # opens http://localhost:5050
```
+> The CLI binary is `chorus` (kept stable for muscle memory + existing docs). `polyphony` is also installed as an alias — both run the same code. Use whichever you like.
+
Paste a task. Hit submit. Watch the AIs argue.
> **Don't `sudo npm install -g`** if you use nvm, fnm, asdf, or any per-user
@@ -104,7 +108,7 @@ expects regardless of how you installed.
### Or drive it from any AI CLI you already use
-`chorus init` registers Chorus as an MCP server with every CLI / IDE it detects (Claude Code, Codex, Gemini CLI, Cursor, Windsurf, Kimi, OpenCode). After that, just ask the assistant in plain English:
+`chorus init` registers Polyphony as an MCP server with every CLI / IDE it detects (Claude Code, Codex, Gemini CLI, Cursor, Windsurf, Kimi, OpenCode). The MCP server is registered under the name `chorus` so existing prompts keep working. After init, just ask the assistant in plain English:
```
> Use chorus to review the staged diff against main
@@ -182,8 +186,8 @@ Pick whichever vendor you already pay for. Or skip CLIs entirely and add an Open
From inside Claude / Cursor
-
-Any AI tool that speaks MCP can trigger a Chorus run.
+
+Any AI tool that speaks MCP can trigger a Polyphony run.
|
@@ -200,7 +204,7 @@ function divide(a, b) {
}
```
-Submit to Chorus with the **Code Review** template (1 writer + 2 reviewers, both must agree to ship):
+Submit to Polyphony with the **Code Review** template (1 writer + 2 reviewers, both must agree to ship):
| Step | What happens |
| ----------------------------- | ----------------------------------------------------------- |
@@ -233,7 +237,7 @@ Make your own by dropping a YAML file in `~/.chorus/templates/`. Or duplicate on
The `audit-*` templates run in two phases:
-1. **Audit phase** — point Chorus at a repo, pick a preset (code review, architecture review, de-slopify, monolith breakdown, engineering review), and one writer produces a checklist of concrete changes. You approve the items you want.
+1. **Audit phase** — point Polyphony at a repo, pick a preset (code review, architecture review, de-slopify, monolith breakdown, engineering review), and one writer produces a checklist of concrete changes. You approve the items you want.
2. **Orchestrate phase** — approved items fan out to worker voices on per-worker git branches. Each worker gets its own slot, model, and persona. Output: an `orchestrate-manifest.json` with diff stats and per-worker status, plus Checkout / Open-PR buttons in the cockpit.
### Verify phase + TDD loop
@@ -269,7 +273,7 @@ quorum:
## Reviewer personas
-Each reviewer can wear a "hat" — a focus area Chorus prepends to their prompt:
+Each reviewer can wear a "hat" — a focus area Polyphony prepends to their prompt:
| Persona | What they look for |
| ----------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------- |
@@ -285,7 +289,7 @@ Different personas reviewing the same change = wider net.
## Why "different vendors" matters
-You can run Chorus with three Claudes. We let you. But the value drops a lot.
+You can run Polyphony with three Claudes. We let you. But the value drops a lot.
A second Claude reviewing the first Claude's work is theatre — same training, same blind spots. Mix vendors (Claude + GPT + Gemini) and you get genuinely different angles, because they were trained on different data with different biases.
@@ -303,7 +307,7 @@ A typical review = **$0** out of pocket. Counts against the quota you already ha
**Using API keys** (pay-per-use)
A typical code-review run = **$0.30 to $1.50**, depending on diff size. If reviewers disagree and retry, 2–3× worst case.
-Chorus adds **zero markup**. We don't see your tokens.
+Polyphony adds **zero markup**. We don't see your tokens.
---
@@ -325,7 +329,7 @@ Configure on first run, or anytime at _Settings → Permissions_.
## Compared to other code-review tools
-| | **Chorus** | CodeRabbit | Greptile | Cursor Review | GitHub Copilot |
+| | **Polyphony** | CodeRabbit | Greptile | Cursor Review | GitHub Copilot |
| -------------------------------------------------------------- | :-----------: | :--------: | :------: | :-----------: | :------------: |
| Multiple AI vendors review the same change | ✅ | ❌ | ❌ | ❌ | ❌ |
| Uses your existing AI subscriptions | ✅ | ❌ | ❌ | ❌ | ❌ |
@@ -333,7 +337,7 @@ Configure on first run, or anytime at _Settings → Permissions_.
| Open source (modify + self-host) | ✅ Apache-2.0 | ❌ | ❌ | ❌ | ❌ |
| Custom review patterns | ✅ | partial | ❌ | ❌ | ❌ |
-**The unique thing:** your code never goes to a new vendor. Chorus just orchestrates the AI tools you already use.
+**The unique thing:** your code never goes to a new vendor. Polyphony just orchestrates the AI tools you already use.
---
@@ -384,7 +388,7 @@ older Node + Windows combos), a self-contained crash log is written to
## Telemetry
-Chorus pings home once on startup and once every 24h. The payload is fixed:
+Polyphony pings home once on startup and once every 24h. The payload is fixed:
```json
{
@@ -433,7 +437,7 @@ Full picture in [ROADMAP.md](./ROADMAP.md).
flowchart TB
User([👤 You])
Cockpit[Cockpit
:5050 · web UI]
- Daemon[Chorus daemon
:7707 · local server]
+ Daemon[Polyphony daemon
:7707 · local server]
DB[(SQLite
~/.chorus/chorus.db)]
MCP[MCP server
for editor integrations]
@@ -447,7 +451,7 @@ flowchart TB
Daemon -->|spawn| Claude
Daemon -->|spawn| Codex
Daemon -->|spawn| Gemini
- User -.->|"call Chorus from your AI"| MCP --> Daemon
+ User -.->|"call Polyphony from your AI"| MCP --> Daemon
classDef user fill:#fef3c7,stroke:#f59e0b,color:#000
classDef chorus fill:#dbeafe,stroke:#3b82f6,color:#000
@@ -461,9 +465,9 @@ flowchart TB
- **Daemon** — small local server (port 7707) that spawns AI tools as subprocesses, parses their output, and tracks state in a SQLite database at `~/.chorus/chorus.db`.
- **Cockpit** — the web UI at port 5050 (Next.js). Templates, chats, voices, settings.
-- **MCP server** — lets _other_ AI tools (Claude Code, Cursor, etc.) call Chorus programmatically.
+- **MCP server** — lets _other_ AI tools (Claude Code, Cursor, etc.) call Polyphony programmatically.
-Each AI runs as an isolated subprocess. Chorus reads their structured output (stream-JSON), compares against the template's quorum rule, and emits a verdict. Nothing leaves your machine except the calls to the AI vendors you already use.
+Each AI runs as an isolated subprocess. Polyphony reads their structured output (stream-JSON), compares against the template's quorum rule, and emits a verdict. Nothing leaves your machine except the calls to the AI vendors you already use.
Code layout:
@@ -490,7 +494,7 @@ pnpm test # full suite
Read [`AGENTS.md`](./AGENTS.md) first — Next.js 16 has breaking changes from older versions. Coverage target on new code: 80%+.
-We dogfood: PRs to Chorus go through Chorus before merging.
+We dogfood: PRs to Polyphony go through Polyphony before merging.
See [CONTRIBUTING.md](./CONTRIBUTING.md) for the full guide.
@@ -504,6 +508,20 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) for the full guide.
---
+## Compatibility
+
+Polyphony was published as `chorus-codes` in v0.7. The v0.8 rebrand keeps everything you typed before working:
+
+- **CLI binary** — `chorus` still works. `polyphony` is installed as an alias; both run the same code.
+- **Config directory** — `~/.chorus/` is still the canonical location for `chorus.db`, templates, logs, secrets, and the install-id.
+- **MCP server** — `chorus init` still registers under the name `chorus` in your editors (Claude Code, Codex, Cursor, etc.), so any prompt that says "ask chorus to…" or any `chorus.create_chat` tool call keeps working.
+- **Env vars** — `CHORUS_TELEMETRY`, `CHORUS_DB_PATH`, `CHORUS_CODEX_HOME`, `CHORUS_LOG_LEVEL` are unchanged.
+- **GitHub repo** — still `crypticpy/chorus`. The repo name will move in a follow-up.
+
+If you're on the old `chorus-codes` npm package, switch with: `npm uninstall -g chorus-codes && npm i -g @crypticpy/polyphony`. No other change required.
+
+---
+
## License
[Apache-2.0](./LICENSE). Use it however you want, including commercially.
diff --git a/package.json b/package.json
index f6393e9..95d22b1 100644
--- a/package.json
+++ b/package.json
@@ -1,15 +1,16 @@
{
- "name": "chorus-codes",
+ "name": "@crypticpy/polyphony",
"version": "0.8.26",
- "description": "Driver-agnostic multi-LLM peer review for code decisions. Bring your own CLI; Chorus convenes 2-4 other LLMs to review the work before you ship.",
+ "description": "Driver-agnostic multi-LLM peer review for code decisions. Bring your own CLI; Polyphony convenes 2-4 other LLMs to review the work before you ship.",
"license": "Apache-2.0",
- "author": "99x Agency",
- "homepage": "https://chorus.codes",
+ "author": "crypticpy",
+ "homepage": "https://github.com/crypticpy/chorus",
"repository": {
"type": "git",
- "url": "https://github.com/chorus-codes/chorus.git"
+ "url": "https://github.com/crypticpy/chorus.git"
},
"bin": {
+ "polyphony": "./bin/chorus.mjs",
"chorus": "./bin/chorus.mjs"
},
"publishConfig": {
diff --git a/src/app/api/daemon/[...path]/route.ts b/src/app/api/daemon/[...path]/route.ts
index a4797f5..2f4cdb7 100644
--- a/src/app/api/daemon/[...path]/route.ts
+++ b/src/app/api/daemon/[...path]/route.ts
@@ -60,10 +60,9 @@ async function proxy(req: NextRequest, ctx: ProxyContext): Promise
{
// while the daemon itself only exposes the versioned shape. Exact
// segment check — `startsWith("api/v1")` would naively match
// `api/v10/...` or `api/v1foo/...` and skip prepending.
- const isPrefixed = segments === API_PREFIX || segments.startsWith(`${API_PREFIX}/`);
- const versionedSegments = isPrefixed
- ? segments
- : `${API_PREFIX}/${segments}`;
+ const isPrefixed =
+ segments === API_PREFIX || segments.startsWith(`${API_PREFIX}/`);
+ const versionedSegments = isPrefixed ? segments : `${API_PREFIX}/${segments}`;
const search = req.nextUrl.search;
const daemonUrl = await getDaemonUrl();
const target = `${daemonUrl}/${versionedSegments}${search}`;
@@ -87,8 +86,7 @@ async function proxy(req: NextRequest, ctx: ProxyContext): Promise {
// see DELETE through fetchFromDaemon. We also drop the upstream
// Content-Type for empty requests because Fastify rejects
// application/json + empty body with FST_ERR_CTP_EMPTY_JSON_BODY.
- const hasContentLength =
- Number(req.headers.get("content-length") ?? "0") > 0;
+ const hasContentLength = Number(req.headers.get("content-length") ?? "0") > 0;
const isChunked = (req.headers.get("transfer-encoding") ?? "")
.toLowerCase()
.includes("chunked");
@@ -142,7 +140,7 @@ async function proxy(req: NextRequest, ctx: ProxyContext): Promise {
error: {
code: "daemon_unreachable",
message:
- "Chorus daemon is not running on this host. Start it with `chorus start`.",
+ "Polyphony daemon is not running on this host. Start it with `chorus start`.",
},
},
{ status: 502 },
diff --git a/src/app/onboarding/page.tsx b/src/app/onboarding/page.tsx
index 2ac2c9e..078f59d 100644
--- a/src/app/onboarding/page.tsx
+++ b/src/app/onboarding/page.tsx
@@ -55,14 +55,15 @@ export default function OnboardingPage() {
// OpenCode AND the binary is installed. The user picks which
// subscription models chorus should expose as voices; persisted in
// submit.ts.
- const [opencodeModels, setOpencodeModels] = useState(
+ const [opencodeModels, setOpencodeModels] =
+ useState(null);
+ const [opencodeModelsError, setOpencodeModelsError] = useState(
null,
);
- const [opencodeModelsError, setOpencodeModelsError] = useState(null);
const [opencodeModelsLoading, setOpencodeModelsLoading] = useState(false);
- const [selectedOpencodeModels, setSelectedOpencodeModels] = useState>(
- new Set(),
- );
+ const [selectedOpencodeModels, setSelectedOpencodeModels] = useState<
+ Set
+ >(new Set());
useEffect(() => {
// `cancelled` guards every setter against unmount-during-fetch
@@ -192,8 +193,7 @@ export default function OnboardingPage() {
if (!value) {
setManualError((prev) => ({
...prev,
- [id]:
- "Enter the full path to the CLI program (e.g. /usr/local/bin/claude).",
+ [id]: "Enter the full path to the CLI program (e.g. /usr/local/bin/claude).",
}));
return;
}
@@ -264,7 +264,9 @@ export default function OnboardingPage() {
const handleSubmit = () => {
setError(null);
if (filledCount === 0) {
- setError("Pick at least one CLI or paste at least one API key to continue.");
+ setError(
+ "Pick at least one CLI or paste at least one API key to continue.",
+ );
return;
}
startTransition(async () => {
@@ -295,7 +297,7 @@ export default function OnboardingPage() {
- Chorus runs your prompt past 2–4 LLMs of different lineages and
- synthesises consensus. Pick the CLI subscriptions you already have,
- or paste API keys. You can change these later in Settings.
+ Polyphony runs your prompt past 2–4 LLMs of different lineages and
+ synthesises consensus. Pick the CLI subscriptions you already have, or
+ paste API keys. You can change these later in Settings.