docs(license): MIT — the model's terms were never murmur's to carry - #206
Merged
Conversation
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
force-pushed
the
zachg-0904--mit-license
branch
from
September 4, 2026 06:11
7b68ec4 to
2f75205
Compare
|
Hosting the README demo video here so it has a permanent URL — GitHub's CSP murmur-demo.mp4 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
murmur had no
LICENSEfile 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
LICENSEpackage.json"SEE LICENSE IN README.md"→ the SPDX id"MIT"README.md## Licenseplus Third-party services, naming every outbound hop and pointing at its termsspecs/DESIGN.mddocs/index.htmldata-enanddata-zhDisclosure 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), andregistry.npmjs.org(latestVersion, behind/update).Test
test/package.test.tsonly assertedexpect(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-runconfirmsLICENSEships (npm notice 1.1kB LICENSE) despite not being in thefilesarray — npm always packs it.Gates
pnpm test1412 passed ·typecheck0 ·oxlint0 · source-language passed (125 files)Peer review (codex
gpt-5.6-sol, xhigh): 3 findings, 3 applied, 0 dismissed.src/and completed it.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.htmlwas 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
LICENSEinstead 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 outboundfetchbefore drafting the disclosure list, rather than after review, would have saved the second round.🤖 Generated with Claude Code
https://claude.ai/code/session_01P6pPTjtKyjcz4rbDKBPVNe