Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2026 wine-fall

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ murmur is always on the air. It finds a topic and chats with you on its own, pla

Existing tools are either "voice-control Claude to write code" or message-driven assistants. Nobody occupies the **proactive + emotional companionship + voice radio** combination. That gap is murmur.

> Open-source and non-commercial — but **not self-contained**. Three things come off the network — the brain is a Claude session, the music streams in, and the voice is [fish-speech](https://github.com/fishaudio/fish-speech) by [@fishaudio](https://github.com/fishaudio), reached over a hosted endpoint — and a fourth if you hand it a listening catalogue to find songs in. What runs on your machine is everything murmur itself owns — program logic, keyboard I/O, memory, persona, and audio mixing. A local TTS is a noted want, not current code.
> Open-source (MIT) — but **not self-contained**. The main three come off the network — the brain is a Claude session, the music streams in, and the voice is [fish-speech](https://github.com/fishaudio/fish-speech) by [@fishaudio](https://github.com/fishaudio), reached over a hosted endpoint — and a fourth if you hand it a listening catalogue to find songs in. What runs on your machine is everything murmur itself owns — program logic, keyboard I/O, memory, persona, and audio mixing. A local TTS is a noted want, not current code.

## Core experience

Expand Down Expand Up @@ -45,7 +45,7 @@ Two processes. A Node.js (TypeScript) **engine** owns the program and the audio;
- **TypeScript on the Claude Agent SDK** — the brain harness is the heart of the product, and `@anthropic-ai/claude-agent-sdk` is the first-class surface for it (the Python implementation served as the behavior oracle for the rewrite — GitHub issue #54). The mixer is a Web Audio graph on `node-web-audio-api`; local TTS models are deferred, so no Python/MLX runtime is needed.
- **Brain = a harnessed agent (Claude today), subscription auth** — reuses your local Claude Code OAuth credentials; no `ANTHROPIC_API_KEY` needed. Every model sits behind a seam (`Brain`, `VoiceProvider`, `MusicProvider`) so swaps are adapter/config changes; a second brain backend (Codex SDK) is a recorded direction.
- **Keyboard in, voice out** — no ASR this round; ASR is solved and not the value-add. The hard part is making the AI *sound human*, and that's the focus.
- **Two-phase model strategy** — experiment now with the best available models (private, personal use); adopt paid/properly-licensed models at distribution.
- **murmur ships no model** — the brain is your own Claude session and the voice is an endpoint you point it at, so each model's terms stay between you and that model's author, never redistributed by murmur. See [License](#license).

See [`DESIGN.md`](specs/DESIGN.md) for the full master spec and rationale.

Expand Down Expand Up @@ -135,4 +135,17 @@ The voice is [fish-speech](https://github.com/fishaudio/fish-speech) by [@fishau

## License

Open-source, non-commercial. Distributed models are chosen/licensed at distribution time (see the two-phase strategy in `specs/DESIGN.md` §3.7).
murmur's own code is **MIT** — see [`LICENSE`](LICENSE).

**Third-party services.** murmur ships no model weights; it calls services that carry their own terms, and complying with them is yours:

- **Brain** — your own Claude session, under your own Anthropic subscription.
- **Voice** — the default endpoint serves [fish-speech](https://github.com/fishaudio/fish-speech), whose model carries the [Fish Audio Research License](https://github.com/fishaudio/fish-speech/blob/main/LICENSE) (research and non-commercial use free; commercial use by separate license). Whoever operates the endpoint you point at may add service terms of their own — read both; murmur is not a party to either.
- **Music** — retrieval runs through `yt-dlp` on your machine, against whatever source you point it at.

And these, only on the paths that need them:

- **A package registry** — a packaged first boot runs `bun install` for the TUI; without it murmur falls back to the plain front-end.
- **`raw.githubusercontent.com`** — downloading a built-in voice preset's reference clip (cached and hash-pinned after the first fetch).
- **[Last.fm](https://www.last.fm/api), or the catalogue you point `MURMUR_LISTENING_URL` at** — only with a listening key set.
- **`registry.npmjs.org`** — the version check behind `/update`.
10 changes: 5 additions & 5 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>murmur — a whole radio station, for an audience of one</title>
<meta name="description" content="A local-first companion radio with an agent for a brain. It talks on its own, plays music, repairs its own setup by talking, and hands your replies to an agent. Open-source, non-commercial.">
<meta name="description" content="A local-first companion radio with an agent for a brain. It talks on its own, plays music, repairs its own setup by talking, and hands your replies to an agent. Open-source, MIT-licensed.">
<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='14' fill='%23282828'/%3E%3Ctext x='30' y='46' font-family='monospace' font-size='36' text-anchor='middle' fill='%23d4be98'%3Em%3C/text%3E%3Cpath d='M46 30q5-2 7-7M44 20q3-3 3-7' stroke='%23d8a657' stroke-width='4.5' fill='none' stroke-linecap='round'/%3E%3C/svg%3E">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
Expand Down Expand Up @@ -301,7 +301,7 @@ <h1 data-en="A whole radio station, for an audience of one." data-zh="一整座
<span class="p">$</span> cd murmur &amp;&amp; make dev <span class="c" data-en="# the radio comes on the air" data-zh="# 电台就开播了"># the radio comes on the air</span></code></pre>
<p class="hero-meta">
<span data-en="local-first" data-zh="本地优先">local-first</span>
<span data-en="open-source, non-commercial" data-zh="开源 · 非商业">open-source, non-commercial</span>
<span data-en="open-source, MIT" data-zh="开源 · MIT">open-source, MIT</span>
<span data-en="keyboard in, voice out" data-zh="键盘输入 · 语音输出">keyboard in, voice out</span>
</p>
</div>
Expand Down Expand Up @@ -388,8 +388,8 @@ <h3 data-en="Three network calls, total" data-zh="只有三条对外连接">Thre
</div>
<div class="fact">
<h3 data-en="Accepted by ear" data-zh="用耳朵验收">Accepted by ear</h3>
<p data-en="Open-source and non-commercial, with a hard bar: if it doesn’t sound human, it isn’t done. The remaining work is listening."
data-zh="开源、非商业,验收标准只有一条:听起来不像人,就不算完成。剩下的活儿是听。">Open-source and non-commercial, with a hard bar: if it doesn’t sound human, it isn’t done. The remaining work is listening.</p>
<p data-en="Open-source under MIT, with a hard bar: if it doesn’t sound human, it isn’t done. The remaining work is listening."
data-zh="MIT 开源,验收标准只有一条:听起来不像人,就不算完成。剩下的活儿是听。">Open-source under MIT, with a hard bar: if it doesn’t sound human, it isn’t done. The remaining work is listening.</p>
</div>
</div>
</div>
Expand Down Expand Up @@ -417,7 +417,7 @@ <h2 data-en="On the air today" data-zh="今天就能开播">On the air today</h2

<footer>
<div class="wrap foot">
<span data-en="murmur — open-source, non-commercial" data-zh="murmur —— 开源 · 非商业">murmur — open-source, non-commercial</span>
<span data-en="murmur — open-source, MIT" data-zh="murmur —— 开源 · MIT">murmur — open-source, MIT</span>
<span><a href="https://github.com/wine-fall/murmur">github.com/wine-fall/murmur</a></span>
</div>
</footer>
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "murmur-radio",
"version": "0.2.1",
"description": "A companion radio, always on the air — Claude for a brain, a fish-speech voice, keyboard-driven replies.",
"license": "SEE LICENSE IN README.md",
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/wine-fall/murmur.git"
Expand Down
Loading
Loading