Meetings your scripts and your agents can read
Months of calls in a local database are worth more than a folder of recordings, because a shell script and an assistant can both read them.
Everything the Mac app records lands in a SQLite database on your disk, and the listenr command reads it. A question about any call is one line in a shell:
listenr search "budget review" --since 30d --language de
listenr list --from 2026-06-01 --to 2026-06-30 --participant anna --json
listenr show 8f3a --transcript
listenr export 8f3a --output meeting.md
The same binary is an MCP server, so Claude Desktop or Claude Code can answer “what did we agree with that customer last Tuesday” from the transcript. The CLI and the local MCP server are on every plan, work signed out and offline, and read only the database on your Mac.
Finding a meeting
Meeting ids are the full UUID or any unique prefix of at least four characters. Zsh completion fills them in as the shortest unique prefix, with the title and start time beside each, and answers without starting the app.
Read commands never launch anything: list, show, search, export, contacts, logs and status, plus settings and model listings. --json gives a script structured output:
listenr list --since 7d --platform googleMeet --has-notes
listenr show 8f3a --markdown
Controlling the app
The CLI is read-only by default, and control verbs cover every command the app has:
listenr record start --platform googleMeet --language de
listenr watch --topics session
listenr record stop --wait
listenr deliver 8f3a --to obsidian
record stop --wait blocks until the notes exist. listenr watch prints one line per event (NDJSON with --json): live transcript segments, speakers, downloads, and the notes text as it is written. listenr do <id> --arg name=value runs any command by its id, and listenr commands lists them.
When the app is running, commands run inside it over a local socket, so a write from the terminal never races the app. When it is not, commands that only touch your files (notes, transcripts, settings, models) run in the CLI process, and commands that need the app, such as recording, start it in the background first.
Letting your assistant read your meetings
MCP is the protocol assistants like Claude use to read data from other applications. listenr mcp speaks it over stdio, so the client starts it as a local process and your meetings stay on your Mac:
claude mcp add listenr -- /absolute/path/to/listenr mcp
{
"mcpServers": {
"listenr": { "command": "/absolute/path/to/listenr", "args": ["mcp"] }
}
}
With no flag you get seven read-only tools: list_meetings, get_meeting, get_transcript, search_meetings, list_contacts, get_logs and get_status. That covers the common questions: what was committed to in the last three calls with an account, who raised the pricing objection, a summary of every design meeting in June.
Two things to know:
- Local only. A stdio server works with Claude Desktop, Claude Code and other clients that launch local servers. It is not a claude.ai or ChatGPT connector. For those, Pro includes a hosted MCP connector that is read-only and covers only meetings you have uploaded or shared.
- Writes are opt-in and broad.
--allow controladds more than a hundred tools, including deleting a meeting and quitting the app.--allow settingsadds settings, secrets, keybindings and integrations.--allow alladds both. Destructive tools refuse until the call is repeated withconfirm: true, and the refusal names the exact target, so the model confirms a specific meeting rather than a description of one.
Writing a script against it
The exit code is the output a script can rely on without parsing.
| Code | Meaning |
|---|---|
0 |
ok |
1 |
error |
3 |
app required but not running and --no-launch |
4 |
refused (the message names the reason) |
5 |
finish the step in Listenr |
6 |
confirmation required (--yes) |
64 |
usage |
A 1 means something went wrong. A 4 means the command was understood and refused because of the current state, such as stopping when nothing is recording, so retrying it unchanged is pointless. A 5 means a person has to finish it in the app, such as a sign-in. A 6 means the command is destructive and needs --yes.
Three details for scripts:
--waitis accepted only onrecord stopandnotes regenerate, and is a usage error anywhere else, so a script never relies on a flag that did nothing.- Secrets are never taken as arguments, since argv lands in shell history and
ps. Uselistenr secrets set <name> --stdin. NO_COLORis honoured, and colour and progress bars appear only on a terminal.
The terminal and the app never disagree
Every command is declared once and offered in the app, as a keyboard shortcut, on the command line, as an MCP tool and in the terminal interface. An argument means the same thing everywhere, a destructive command asks first wherever you call it, and anything the app would refuse right now is refused on the command line with the same reason. You can start a recording with a shortcut, stop it from a script, and have an assistant pull the notes into your weekly update.