Skip to content

docs(license): MIT — the model's terms were never murmur's to carry - #206

Merged
wine-fall merged 2 commits into
mainfrom
zachg-0904--mit-license
Sep 4, 2026
Merged

docs(license): MIT — the model's terms were never murmur's to carry#206
wine-fall merged 2 commits into
mainfrom
zachg-0904--mit-license

Conversation

@wine-fall

Copy link
Copy Markdown
Owner

murmur had no LICENSE file at all, and called itself "open-source, non-commercial" in the README, the master spec, and five strings on the landing page. This lands MIT and untangles where that "non-commercial" came from.

The restriction was the model's, not murmur's

It was inherited from the voice. fish-speech is under the Fish Audio Research License (research and non-commercial free, commercial by separate license), and DESIGN.md §3.7's two-phase strategy deferred "what we're allowed to ship" to some future distribution date.

But murmur redistributes none of those materials. It speaks HTTP to an endpoint the listener points it at; the tarball carries no weights and no model code, only the client. No model license reaches a source tree that embodies none of it.

So the label protected nothing — every commercially interesting piece is already gated by its own author's terms — while costing what an OSI license actually buys: awesome-lists, package indexes, and every reader who checks the badge before they clone.

The tense was stale too: §3.7 described distribution as future work, while murmur has been on npm since 0.2.1.

What changed

LICENSE new, MIT, at the root so GitHub detects it
package.json "SEE LICENSE IN README.md" → the SPDX id "MIT"
README.md a real ## License plus Third-party services, naming every outbound hop and pointing at its terms
specs/DESIGN.md §3.7 rewritten present-tense as murmur ships no model; §2, §3.1, §3.5 and the appendix follow
docs/index.html five stale "non-commercial" strings, both data-en and data-zh

Disclosure replaces the restriction. That only works if it is complete, so Third-party services lists all seven hops the code actually makes — the brain, the voice endpoint and yt-dlp, plus the four conditional ones: a package registry (ensureTuiDeps, whose failure degrades the TUI to plain), raw.githubusercontent.com (presetClip), Last.fm or a configured catalogue (HostedListening), and registry.npmjs.org (latestVersion, behind /update).

Test

test/package.test.ts only asserted expect(pkg.license).toBeDefined() — which "SEE LICENSE IN README.md" satisfied, so it was watching nothing. Written failing first, it now pins the SPDX id, the root file, and its content. npm pack --dry-run confirms LICENSE ships (npm notice 1.1kB LICENSE) despite not being in the files array — npm always packs it.

Gates

pnpm test 1412 passed · typecheck 0 · oxlint 0 · source-language passed (125 files)

Peer review (codex gpt-5.6-sol, xhigh): 3 findings, 3 applied, 0 dismissed.

  1. P1 — §3.7 pronounced on who a model's license binds at the far end of an endpoint. Redistributing nothing establishes that no model license reaches murmur's source; it does not establish whether the model license or the operator's service terms govern an API caller. murmur is not a party to that agreement and should not characterise it. Scoped back to what is established, pointing at the terms instead of summarising them.
  2. P2 — the service list had three entries and the code makes seven. Verified each against src/ and completed it.
  3. P2 — §3.1 still claimed Claude and music were "the only two network hops" on the line after the one this branch edited, the architecture diagram repeated it, and §2 still said "fully-local". All false once the voice is an endpoint. Corrected.

Not legal advice. The choice of MIT over AGPL-3.0 was the repo owner's, made explicitly.

AI coding brief

Original request. The user was promoting murmur overseas and had gained 2 stars. Traffic data showed the 小红书/X posts had driven no GitHub referrals at all, and the diagnosis surfaced two blockers ahead of any new channel: no demo, and a license that reads as non-commercial. The user had the demo. They asked how to decide the license, then chose MIT once the trade-off was laid out.

Manual interventions. One real decision point, put to the user rather than defaulted: MIT (maximise adoption) vs AGPL-3.0 (still OSI, but blocks SaaS resale) vs PolyForm Noncommercial (keep NC, but stop calling it open source). They chose MIT. Two scope calls made without asking: docs/index.html was not in the brief but carries the same claim to anyone arriving from Hacker News, so leaving it would have defeated the change; and the stale "two network hops" claims were out of scope until codex pointed out they sit on the line adjacent to one this branch already edited.

Retro. The useful move was reading fish-speech's actual LICENSE instead of reasoning from the phrase "non-commercial" — that is what separated the model's terms from murmur's and made the whole change obvious. The correction worth carrying forward is codex's P1: having been careful to tell the user "this is the ordinary reading, not legal advice," the spec text was then written more confidently than that. A doc should not out-claim the reasoning that produced it. Grepping the codebase for outbound fetch before drafting the disclosure list, rather than after review, would have saved the second round.

🤖 Generated with Claude Code

https://claude.ai/code/session_01P6pPTjtKyjcz4rbDKBPVNe

wine-fall and others added 2 commits September 4, 2026 14:11
murmur called itself "open-source, non-commercial" and shipped no LICENSE
file at all. The non-commercial half was inherited from the voice model:
fish-speech is under the Fish Audio Research License, and DESIGN §3.7's
two-phase strategy deferred "what we're allowed to ship" to distribution.

But murmur redistributes none of those materials — it speaks HTTP to an
endpoint the listener points it at. A model's license binds whoever reaches
the model; it does not reach a client that embodies none of it. So the NC
label protected nothing (every commercially interesting piece is already
gated by its own author's terms) while costing an OSI license's whole
distribution surface: awesome-lists, package indexes, and any reader who
checks the badge before they clone.

The tense was also stale. §3.7 described distribution as future work while
murmur has been on npm since 0.2.1.

- LICENSE at the root, MIT, so GitHub detects it
- package.json: "SEE LICENSE IN README.md" -> the SPDX id "MIT"
- README grows a Third-party services section naming what each hop is
  under: the listener's Claude session, fish-speech's research license,
  yt-dlp for music. Disclosure replaces the restriction.
- DESIGN §3.7 rewritten present-tense as "murmur ships no model", with
  §§2/3.1/3.5 and the appendix following it
- docs/index.html: five stale "non-commercial" strings, both languages

The manifest test tightens with it: license was only asserted defined, which
"SEE LICENSE IN README.md" satisfied. It now pins the SPDX id and the file
npm packs (LICENSE ships regardless of the files array — verified against
npm pack).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P6pPTjtKyjcz4rbDKBPVNe
Peer review (codex gpt-5.6-sol) findings, all three verified against the
code and applied:

- The §3.7 text pronounced on who a model's license binds at the far end of
  an endpoint. Redistributing nothing establishes that no model license
  reaches murmur's source; it does not establish whether the model license
  or the operator's service terms govern an API caller. murmur is not a
  party to that agreement and should not characterise it — it now says what
  it knows and points at the terms.
- Third-party services listed three hops and the code makes seven:
  ensureTuiDeps reaches a package registry on a packaged first boot (a miss
  degrades the TUI to plain), presetClip reaches raw.githubusercontent.com,
  HostedListening reaches Last.fm, and latestVersion reaches
  registry.npmjs.org behind /update. Disclosure replacing a restriction has
  to be complete or it is worse than what it replaced.
- §3.1 still claimed Claude and music were "the only two network hops" on
  the line after the one this branch edited, the diagram repeated it, and
  §2 still said "fully-local" — all false once the voice is an endpoint.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01P6pPTjtKyjcz4rbDKBPVNe
@wine-fall
wine-fall force-pushed the zachg-0904--mit-license branch from 7b68ec4 to 2f75205 Compare September 4, 2026 06:11
@wine-fall
wine-fall merged commit 2ebe70f into main Sep 4, 2026
3 checks passed
@wine-fall
wine-fall deleted the zachg-0904--mit-license branch September 4, 2026 06:13
@zach-guo-opus

Copy link
Copy Markdown

Hosting the README demo video here so it has a permanent URL — GitHub's CSP media-src only allows the attachment CDN, so a release asset or a committed file cannot play inline.

murmur-demo.mp4

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants