Skip to content

Commit 4f0e520

Browse files
asanmateuclaude
andcommitted
feat: audio modes and built-in presets
Add 6 configurable audio modes (podcast, briefing, lecture, storyteller, study-buddy, calm) that control the persona and structure used when rewriting summaries for spoken playback. Ship 7 built-in presets (morning-brief, commute-catch-up, deep-study, exam-prep, bedtime-read, story-mode, team-debrief) with curated audio/style/tone/voice combos. Rename "profiles" to "presets" in all user-facing surfaces while keeping --profile and /profile as hidden aliases for backward compatibility. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7be20ff commit 4f0e520

25 files changed

+915
-100
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ coverage/
66
.DS_Store
77
.env
88
.env.*
9+
claude_notes/

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Added
1111

12+
- Audio modes: six personas for spoken summaries — podcast, briefing, lecture, storyteller, study-buddy, calm
13+
- `--audio-mode` CLI flag and `tldr config set audio-mode` command
14+
- Built-in presets: morning-brief, commute-catch-up, deep-study, exam-prep, bedtime-read, story-mode, team-debrief
15+
- `--preset` CLI flag and `tldr preset` command (list, create, delete, use, edit)
1216
- Chat export: press `Ctrl+s` in chat view to save the conversation as `chat.md` in the session directory; auto-saves on every subsequent message
1317

1418
### Changed
1519

20+
- Renamed "profiles" to "presets" in CLI and docs (`--profile` and `tldr profile` still work as aliases)
21+
- Audio rewriting uses template-driven prompts instead of hardcoded podcast persona
1622
- Chat view: role labels changed from "You"/"AI" to ``/`` symbols, messages wrapped in bordered card, consistent spacing between messages
1723

1824
## [2.1.0] - 2026-02-21

CLAUDE.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,15 @@ When cutting a release, collect all `[Unreleased]` entries into a new version he
1515

1616
1. **Update CHANGELOG.md** — Add entries under `[Unreleased]` for any user-facing change (Added, Fixed, Changed, Removed)
1717
2. **Write tests** — New features and bug fixes must have corresponding tests in `src/__tests__/`. Do not test external libraries or vendor APIs.
18-
3. **Update documentation**If behavior changes, update the relevant docs in `docs/` and `README.md`
18+
3. **Update documentation**After each feature, review `docs/` and `README.md` to ensure they reflect the current state of the product. Keep docs concise and non-redundant: prefer linking to the relevant `docs/` page over duplicating content in the README. The README should be a clean overview with a quick-start, not a full reference. A demo GIF placeholder lives at the top of the README — do not remove it.
1919
4. **Clean up obsolete code** — Remove dead references, unused types, stale docs entries. Don't leave commented-out code or backward-compat shims for removed features.
2020
5. **Run checks before finishing**:
2121
- `bun run test` — all tests pass
2222
- `bun run typecheck` — no type errors
2323
- `bun run check` — lint and format pass
24-
6. Always keep tldr-desktop in sync, especially when inserting breaking changes and new features.
25-
7. Keep code clean, if possible better than you found it.
24+
6. **Test strategy**:
25+
- **Unit tests**: Pure functions, constants, validation. Every new type/constant/exported function.
26+
- **Integration tests**: Config resolution flows, save/load round-trips with temp filesystem.
27+
- **App-level tests**: UI behavior via ink-testing-library — keybindings, state transitions, rendered output.
28+
7. Always keep tldr-desktop in sync, especially when inserting breaking changes and new features. After each session that introduces breaking changes, new features, or UI-affecting changes, add an entry to `claude_notes/desktop-sync-tracker.md` describing what tldr-desktop needs to catch up on.
29+
8. Keep code clean, if possible better than you found it.

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ I had a pile of to-reads growing at work and it was overwhelming — not because
2222

2323
## Audio
2424

25-
Summaries aren't just read aloud. They're **rewritten as podcast-style scripts** adapted to your cognitive profile. ADHD mode leads with hooks. Dyslexia mode uses short punchy sentences. The result sounds like a brief podcast, not a screen reader.
25+
Summaries aren't just read aloud. They're **rewritten as spoken scripts** using a configurable audio mode — podcast, briefing, lecture, storyteller, study-buddy, or calm. Each mode has a distinct persona and delivery style. The script also adapts to your cognitive traits and tone. The result sounds natural, not robotic.
2626

27-
Press **`a`** to listen. Press **`w`** to save the audio alongside your summary. Free with Edge TTS by default, or switch to OpenAI TTS for higher quality. See the [Audio guide](docs/audio.md) for voices, save-with-audio, and provider options.
27+
Press **`a`** to listen. Press **`w`** to save the audio alongside your summary. Use built-in presets like `morning-brief` or `bedtime-read` for curated listening experiences. Free with Edge TTS by default, or switch to OpenAI TTS for higher quality. See the [Audio guide](docs/audio.md) for modes, voices, and provider options.
2828

2929
---
3030

@@ -62,10 +62,10 @@ Type `/` in interactive mode to access commands like `/history`, `/setup`, `/con
6262

6363
1. You give it something to read (a URL, file, or text)
6464
2. It extracts the content automatically
65-
3. Claude generates a structured, learning-focused summary
65+
3. Your AI provider generates a structured, learning-focused summary
6666
4. The summary is saved to `~/Documents/tldr/`
6767

68-
Summaries use short sentences, bullet points, bold key terms, and put the most important information first. This isn't just formatting — it's based on how people with dyslexia and ADHD process information.
68+
Summaries use short sentences, bullet points, bold key terms, and put the most important information first. This isn't just formatting — it's designed around cognitive accessibility research to work better for all types of readers.
6969

7070
---
7171

@@ -81,7 +81,7 @@ tldr --model sonnet "https://..." # Use a different model
8181

8282
Choose from three color themes (coral, ocean, forest) and auto dark/light mode during setup, or change later with `tldr config set theme`.
8383

84-
You can set up profiles for different contexts (work, study, casual) with different tones, styles, and cognitive trait settings.
84+
Use built-in presets (morning-brief, deep-study, bedtime-read, etc.) or create your own for different contexts with different tones, styles, audio modes, and cognitive trait settings.
8585

8686
See the [Configuration guide](docs/configuration.md) for details.
8787

@@ -99,7 +99,7 @@ Cognitive accessibility is the point, not a feature. Every summary is optimised
9999
| **ESL** | Common words only, jargon defined inline |
100100
| **Visual thinker** | Hierarchical layout, grouped ideas, numbered steps |
101101

102-
Traits stack. Enable multiple with `tldr profile edit`.
102+
Traits stack. Enable multiple with `tldr preset edit`.
103103

104104
---
105105

@@ -112,9 +112,9 @@ By default tldr uses Claude Code (`claude-code`). You can also use the Anthropic
112112
## Documentation
113113

114114
- [Installation](docs/installation.md) — Homebrew, standalone binaries, prerequisites
115-
- [Configuration](docs/configuration.md) — settings, profiles, tones, summary styles
115+
- [Configuration](docs/configuration.md) — settings, presets, tones, summary styles, audio modes
116116
- [Providers](docs/providers.md) — Claude Code, Anthropic API, Gemini, xAI, Ollama, Codex, and OpenAI-compatible setup
117-
- [Audio](docs/audio.md) — listening to summaries, voices, save with audio
117+
- [Audio](docs/audio.md)audio modes, listening to summaries, voices, save with audio
118118

119119
---
120120

docs/audio.md

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,38 @@
11
# Audio
22

3-
Summaries aren't just read aloud. They're **rewritten as podcast-style audio scripts** by the same AI provider you use for summarizing. The script adapts to your cognitive traits and tone setting. The result sounds like a brief podcast, not a screen reader.
3+
Summaries aren't just read aloud. They're **rewritten as audio scripts** by the same AI provider you use for summarizing, using a configurable **audio mode** that controls the persona and structure. The script adapts to your cognitive traits and tone setting. The result sounds like a natural spoken piece, not a screen reader.
44

55
## How audio works
66

77
Three things happen when you press `a`:
88

99
1. Your **summary** is sent to the AI provider (same one used for summarizing).
10-
2. The AI **rewrites it as a spoken script** — conversational, with hooks and natural transitions.
10+
2. The AI **rewrites it as a spoken script** using your chosen **audio mode** — each mode has a distinct persona, structure, and delivery style.
1111
3. The script is sent to a **TTS voice** (Edge TTS or OpenAI) for synthesis and playback.
1212

13-
The rewrite adapts to your **cognitive traits**:
13+
### Audio modes
14+
15+
Audio modes control how the script is structured and delivered:
16+
17+
| Mode | Persona | Best for |
18+
|------|---------|----------|
19+
| **podcast** (default) | Conversational host with hooks and transitions | General listening |
20+
| **briefing** | Analyst delivering concise, numbered facts | Daily catch-ups |
21+
| **lecture** | Patient teacher building understanding progressively | Deep learning |
22+
| **storyteller** | Narrator weaving a compelling narrative | Story-driven content |
23+
| **study-buddy** | Study partner with quizzes and mnemonics | Exam prep, retention |
24+
| **calm** | Gentle, soothing narrator | Relaxed / bedtime listening |
25+
26+
```bash
27+
tldr config set audio-mode briefing # Change default
28+
tldr --audio-mode lecture "https://..." # Override for one run
29+
```
30+
31+
Built-in presets bundle an audio mode with matching style, tone, and voice settings — see [Presets](configuration.md#presets).
32+
33+
### Cognitive traits
34+
35+
The rewrite also adapts to your **cognitive traits**. These work with any audio mode:
1436

1537
| Trait | How the audio script changes |
1638
|-------|------------------------------|
@@ -20,7 +42,7 @@ The rewrite adapts to your **cognitive traits**:
2042
| **ESL** | Common vocabulary. Specialized terms explained inline. |
2143
| **Visual thinker** | Spatial language. Word pictures. Narrative structure. |
2244

23-
Your **tone** setting also shapes the script (casual, professional, academic, eli5).
45+
Traits stack — enable multiple with `tldr preset edit`. Your **tone** setting (casual, professional, academic, eli5) also shapes the script.
2446

2547
This costs one extra API call, which is why it sounds natural instead of robotic.
2648

@@ -63,7 +85,7 @@ tldr config set tts-provider openai
6385
tldr config set tts-provider edge-tts # back to default
6486
```
6587

66-
You can also change the TTS provider in the profile editor (`tldr profile edit` / `/config`).
88+
You can also change the TTS provider in the preset editor (`tldr preset edit` / `/config`).
6789

6890
### TTS Model
6991

@@ -117,8 +139,8 @@ When you switch TTS providers, the voice automatically resets to the new provide
117139
## Speed, Pitch & Volume
118140

119141
```bash
120-
# Set via profile editor
121-
tldr profile edit
142+
# Set via preset editor
143+
tldr preset edit
122144

123145
# Or via CLI
124146
tldr config set tts-speed 1.25 # 25% faster

docs/configuration.md

Lines changed: 55 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Settings are stored at `~/.tldr/settings.json`. Run `tldr config` to see your current settings.
44

5-
Most settings are easier to change interactively with `tldr profile edit` or `/config` in interactive mode. The CLI commands below are for when you know exactly what you want.
5+
Most settings are easier to change interactively with `tldr preset edit` or `/config` in interactive mode. The CLI commands below are for when you know exactly what you want.
66

77
## Summary
88

@@ -43,13 +43,33 @@ tldr --style quick "https://example.com/article"
4343

4444
| Key | Values | Example |
4545
|-----|--------|---------|
46+
| `audio-mode` | `podcast`, `briefing`, `lecture`, `storyteller`, `study-buddy`, `calm` | `tldr config set audio-mode briefing` |
4647
| `tts-provider` | `edge-tts`, `openai` | `tldr config set tts-provider openai` |
4748
| `tts-model` | Any OpenAI TTS model ID | `tldr config set tts-model tts-1-hd` |
4849
| `voice` | TTS voice name | `tldr config set voice en-US-GuyNeural` |
4950
| `tts-speed` | Positive number | `tldr config set tts-speed 1.25` |
5051
| `pitch` | `low`, `default`, `high` | `tldr config set pitch high` |
5152
| `volume` | `quiet`, `normal`, `loud` | `tldr config set volume loud` |
52-
> **Note:** Pitch and Volume only apply to Edge TTS. They are not supported by OpenAI TTS and will be hidden in the profile editor when OpenAI is selected.
53+
> **Note:** Pitch and Volume only apply to Edge TTS. They are not supported by OpenAI TTS and will be hidden in the preset editor when OpenAI is selected.
54+
55+
### Audio Modes
56+
57+
Audio modes control the persona and structure used when rewriting summaries for spoken playback.
58+
59+
| Mode | Persona | Best for |
60+
|------|---------|----------|
61+
| **podcast** (default) | Conversational podcast host | General listening |
62+
| **briefing** | Concise analyst | Quick daily catch-ups |
63+
| **lecture** | Patient teacher | Deep learning sessions |
64+
| **storyteller** | Compelling narrator | Narrative-driven content |
65+
| **study-buddy** | Smart study partner | Exam prep and retention |
66+
| **calm** | Gentle, soothing narrator | Relaxed listening |
67+
68+
Override for a single run:
69+
70+
```bash
71+
tldr --audio-mode briefing "https://example.com/article"
72+
```
5373

5474
See the [Audio guide](audio.md) for workflow details, voice personalities, and save-with-audio behavior.
5575

@@ -66,30 +86,46 @@ Three appearance modes: **auto** (detects system setting, default), **dark**, **
6686

6787
## Global Settings
6888

69-
These are top-level settings, not profile-specific. They are not available in the interactive profile editor.
89+
These are top-level settings, not preset-specific. They are not available in the interactive preset editor.
7090

7191
| Key | Values | Example |
7292
|-----|--------|---------|
7393
| `apiKey` | Your API key | `tldr config set apiKey sk-ant-...` |
7494
| `baseUrl` | Custom API endpoint | `tldr config set baseUrl https://proxy.example.com` |
7595
| `maxTokens` | Number | `tldr config set maxTokens 2048` |
7696
| `output-dir` | Path | `tldr config set output-dir ~/summaries` |
77-
| `activeProfile` | Profile name | `tldr config set activeProfile work` |
97+
| `activeProfile` | Preset name | `tldr config set activeProfile work` |
98+
99+
## Presets
100+
101+
Presets let you save different settings for different contexts. tldr ships with 7 built-in presets you can use out of the box or clone and customise.
102+
103+
### Built-in Presets
104+
105+
| Preset | Audio Mode | Style | Tone | Speed | Voice |
106+
|--------|-----------|-------|------|-------|-------|
107+
| **morning-brief** | briefing | quick | professional | 1.15x | Guy |
108+
| **commute-catch-up** | podcast | standard | casual | 1.0x | Jenny |
109+
| **deep-study** | lecture | study-notes | academic | 0.9x | Aria |
110+
| **exam-prep** | study-buddy | study-notes | casual | 0.95x | Jenny |
111+
| **bedtime-read** | calm | standard | casual | 0.85x | Sonia |
112+
| **story-mode** | storyteller | detailed | casual | 1.0x | Guy |
113+
| **team-debrief** | briefing | standard | professional | 1.0x | Jenny |
78114

79-
## Profiles
115+
Built-in presets are read-only. To customise one, create a preset with the same name — the built-in settings are used as a starting point.
80116

81-
Profiles let you save different settings for different contexts (work, study, casual).
117+
### Managing Presets
82118

83119
```bash
84-
tldr profile list # List profiles (* = active)
85-
tldr profile create work # Create a new profile
86-
tldr profile use work # Switch active profile
87-
tldr profile edit work # Edit profile settings (interactive)
88-
tldr profile delete work # Delete a profile
89-
tldr --profile work <url> # Use a profile for one run
120+
tldr preset list # List presets (* = active)
121+
tldr preset create work # Create a new preset
122+
tldr preset use work # Switch active preset
123+
tldr preset edit work # Edit preset settings (interactive)
124+
tldr preset delete work # Delete a preset
125+
tldr --preset morning-brief <url> # Use a preset for one run
90126
```
91127

92-
In interactive mode, type `/profile` to switch profiles without leaving the TUI.
128+
In interactive mode, type `/preset` to switch presets without leaving the TUI.
93129

94130
## Interactive Commands
95131

@@ -99,9 +135,9 @@ In interactive mode, type `/` to access commands:
99135
|---------|-------------|
100136
| `/history` | Browse and resume past sessions |
101137
| `/setup` | Re-run the first-time setup wizard |
102-
| `/config` | Edit current profile settings |
138+
| `/config` | Edit current preset settings |
103139
| `/theme` | Change color theme |
104-
| `/profile` | Switch between profiles |
140+
| `/preset` | Switch between presets |
105141
| `/help` | Show shortcuts and commands |
106142
| `/quit` | Exit the app |
107143

@@ -127,7 +163,7 @@ When no `styleModels` are configured, all styles default to Opus.
127163

128164
## Model Selection
129165

130-
The interactive profile editor (`tldr profile edit` / `/config`) uses a free-text input for the model field. Type any model ID supported by your provider — for example `gpt-4o` for OpenAI, `gemini-2.5-flash` for Gemini, or `llama3.3` for Ollama.
166+
The interactive preset editor (`tldr preset edit` / `/config`) uses a free-text input for the model field. Type any model ID supported by your provider — for example `gpt-4o` for OpenAI, `gemini-2.5-flash` for Gemini, or `llama3.3` for Ollama.
131167

132168
### Anthropic Aliases
133169

@@ -161,9 +197,9 @@ Environment variables override file settings:
161197

162198
Settings are resolved in this order (first wins):
163199

164-
1. CLI flags (`--model`, `--style`, `--profile`, `--provider`)
200+
1. CLI flags (`--model`, `--style`, `--preset`, `--provider`, `--audio-mode`)
165201
2. Environment variables
166-
3. Profile settings in `settings.json`
202+
3. Preset/profile settings in `settings.json`
167203
4. Built-in defaults
168204

169205
## Defaults
@@ -173,6 +209,7 @@ Settings are resolved in this order (first wins):
173209
| Provider | `claude-code` (Claude Code) |
174210
| Summary style | `standard` |
175211
| Model | Opus (`claude-opus-4-6`) |
212+
| Audio mode | `podcast` |
176213
| Cognitive traits | `dyslexia` |
177214
| Tone | `casual` |
178215
| Voice | `en-US-JennyNeural` |

src/App.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ export function App({ initialInput, showConfig, editProfile, overrides }: AppPro
325325
setConfigMode("edit");
326326
setState("config");
327327
break;
328+
case "preset":
328329
case "profile":
329330
(async () => {
330331
const profileList = await listProfiles();

src/__tests__/app.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ const TEST_CONFIG: Config = {
139139
outputDir: "/tmp/tldr-test",
140140
ttsProvider: "edge-tts",
141141
ttsModel: "tts-1",
142+
audioMode: "podcast" as const,
142143
};
143144

144145
const TEST_EXTRACTION: ExtractionResult = {

src/__tests__/chat.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ function makeTestConfig(overrides?: Partial<ResolvedConfig>): Config {
4848
outputDir: "/tmp/tldr-output",
4949
ttsProvider: "edge-tts" as const,
5050
ttsModel: "tts-1",
51+
audioMode: "podcast" as const,
5152
...overrides,
5253
};
5354
}

src/__tests__/commands.test.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,16 @@ describe("matchCommands", () => {
4242
expect(names).toContain("help");
4343
});
4444

45-
it("matches /profile command", () => {
45+
it("matches /preset command (and /profile as alias)", () => {
4646
const result = matchCommands("/pr");
4747
expect(result).toHaveLength(1);
48-
expect(result[0]?.name).toBe("profile");
48+
expect(result[0]?.name).toBe("preset");
49+
});
50+
51+
it("matches /profile alias to /preset", () => {
52+
const result = matchCommands("/profile");
53+
expect(result).toHaveLength(1);
54+
expect(result[0]?.name).toBe("preset");
4955
});
5056
});
5157

0 commit comments

Comments
 (0)