Skip to content

Releases: silverstein/minutes

v0.15.0: OpenAI-compatible summaries, speaker overlays everywhere, SDK polish

27 Apr 20:59

Choose a tag to compare

Minutes 0.15.0: OpenAI-compatible summaries, speaker overlays everywhere, SDK polish

Minutes 0.15.0 plugs in OpenAI-compatible summarization so any compatible cloud or local LLM endpoint can produce meeting summaries (with API keys living in macOS Keychain, not config), propagates speaker-identity overlays cleanly across the desktop, CLI, and MCP so a confirmed name in one place is honored everywhere, ships SDK helpers for human-readable transcript rendering, adds Pi agent support, unifies palette meeting actions, and fixes a deterministic desktop crash when a configured input device is unplugged at launch.

Headline features

OpenAI-compatible summarization backend

Plug Minutes into anything that speaks OpenAI's chat-completions API. That covers the obvious cloud endpoints (OpenAI, Mistral, and the Vercel AI Gateway), and just as importantly any local server (Ollama, llama.cpp, LM Studio, vLLM, etc.). Configure once and Minutes will request structured summaries from your chosen backend automatically when meetings finish processing.

API keys are stored in macOS Keychain via minutes setup --gateway-key, not in plaintext config.toml. The HTTP path is hardened with retry, and runtime summary configuration survives upgrades cleanly so you don't lose your endpoint after cargo install --force.

To enable:

minutes setup --gateway-key   # interactive prompt for backend + key

Then update config.toml with the model and base URL you want:

[summarization]
backend = "openai_compatible"
model = "claude-sonnet-4-6"
base_url = "https://api.your-gateway.example/v1"

The Keychain entry is referenced by name, never read into the config file.

Speaker overlays propagate across surfaces

Minutes now has a sidecar overlay store at the core layer that lets every surface see the same speaker-identity edits. Confirm a speaker name once in the desktop, on the CLI, or via MCP, and that mapping is honored:

  • in every meeting view (desktop, CLI, MCP get_meeting)
  • in every report (relationship_map, track_commitments, consistency_report)
  • in every cross-meeting query

The SDK reads through the overlay layer too, so any custom UI consuming minutes-sdk automatically sees the corrected names without re-implementing the merge.

This closes the long-running "I confirmed this person on the desktop, why does the MCP still call them SPEAKER_2" feedback loop.

humanizeTranscript() SDK helper

minutes-sdk@0.15.0 exposes a new humanizeTranscript() for rendering meeting bodies with paragraph wrapping and clean speaker breaks. Useful for any UI surface that wants a richer presentation than the raw markdown body. The MCP server uses it internally for meeting previews.

Pi agent support

Inflection's Pi joins the supported clients list. Same plugin skills, same MCP tools, same filesystem corpus. No code in the agent integration is Pi-specific; it works because Pi reads the standard MCP surface and the standard ~/meetings/ markdown.

Auto-heal stale recording.device config

If your configured input device (USB mixer, Bluetooth headset, virtual loopback driver) is unplugged before launch, the desktop used to crash deterministically on Start Recording with a SIGABRT and silently relaunch via launchd, leaving the UI looking stuck. Minutes now validates the configured device on startup and falls back to the system default if the pin is missing.

The check is three-state (Available, Missing, Unknown) so transient cpal enumeration failures (CI runners, coreaudiod hiccups) never clobber a real config. The pin is only cleared when enumeration definitively returned devices and yours wasn't among them.

Mid-session disconnect (the device vanishing while the app is running) is tracked separately as #189; that case still requires either a quit-relaunch or picking a different device in Settings.

Quality of life

  • Unified palette meeting actions. The desktop command palette exposes a single, coherent meeting-action set instead of duplicate verbs scattered across surfaces.
  • MCP first-run + local-test gating. Cleaner first-run defaults; local test paths no longer trip publish-mode safety checks.
  • whisper-guard 0.2.0. The in-tree anti-hallucination toolkit shipped 0.2.0 with a clean_segments API and a pipeline-order fix used by the in-tree transcription path. Now consumable by other Rust projects via crates.io.

Bug fixes

  • Fixed a regression in summarization config that lost runtime summary state when upgrading. Hardened the upgrade path and the OpenAI-compatible HTTP surface against malformed responses.
  • Restored local gateway authentication so on-device endpoints work without round-tripping through cloud gateways.
  • Repaired CI release metadata and Windows prompt tests that drifted after recent infra changes.
  • Hardened MCP first-run gating so local tests no longer false-positive against the publish-mode safety check.
  • Eliminated an accidental beads issues.jsonl artifact from getting committed during pre-commit hook runs (multiple chore: drop accidental issues export commits).

CLI / MCP / desktop impact

  • CLI: new minutes setup --gateway-key flow for keychain-backed gateway secrets. No removed commands; no breaking flag changes.
  • MCP: server moves to 0.15.0. No tool contract changes (still 29 tools). Speaker overlay reads now flow through the new sidecar store. Hardened first-run gating.
  • Desktop: auto-heal of stale recording.device pins. Unified palette meeting actions. Speaker overlay edits from the desktop are now visible to every other surface.
  • SDK: humanizeTranscript() and overlay-aware reads in minutes-sdk@0.15.0. The minutes-sdk dep in minutes-mcp is ^0.15.0.

Migration notes

  • No breaking changes. Existing configs continue to work.
  • If you used the previous Mistral-specific summarization path, it still functions; the new openai_compatible backend is additive. The Mistral path internally now uses the same hardened HTTP code.
  • Speaker overlay history is preserved. The new sidecar store is populated lazily as you confirm speakers; nothing forces a rewrite of existing transcripts.

Install / upgrade

# CLI
brew install silverstein/tap/minutes
# or
cargo install minutes-cli

# Setup whisper model + optional gateway key
minutes setup --model tiny
minutes setup --gateway-key   # only if you want cloud or local LLM summaries

# MCP server (zero-install)
npx minutes-mcp@latest

# Claude Desktop extension (.mcpb)
# Download minutes.mcpb from this release and double-click to install.

For Claude Code plugin users, refresh and update:

/plugin marketplace update minutes
/plugin update minutes@minutes

then restart Claude Code so the new skills register.

Known issues

  • Mid-session device disconnect still hits the original SIGABRT path until the running session is restarted. Tracked as #189.
  • Windows desktop installer artifacts remain unsigned; treat them as the existing preview/advanced-user surface.
  • GitHub Actions reports Node.js 20 deprecation warnings on upstream actions; these do not affect the v0.15.0 artifacts.

v0.14.1: Regression fixes for call auto-stop and 1:1 diarization

23 Apr 23:08

Choose a tag to compare

Minutes 0.14.1: Regression fixes for call auto-stop and 1:1 diarization

What changed

  • Fixed a v0.14.0 regression where call-detection recordings could emit call_ended and then cleared before the 30s countdown finished, leaving recordings running.
  • Hardened call-end countdown terminal states so timer, cancel, and already-stopped paths own countdown_active and cannot be re-armed by a polling race.
  • Fixed hybrid source-aware diarization for 1:1 open-speaker calls: system-stem diarization can now contribute one meaningful remote speaker instead of only multi-party remote structure.
  • Cleaned release metadata so the SDK, MCP package, desktop app, CLI, manifests, MCPB bundle, and agent docs all agree on 0.14.1.

Who should care

  • Desktop users who enabled [call_detection] stop_when_call_ends = true.
  • Users on Zoom/native-call capture with open speakers or severe mic bleed, especially 1:1 calls where the remote side became UNKNOWN.
  • MCP / Claude Desktop extension users who want the patched package and bundle versions to match the CLI release.

CLI / MCP / desktop impact

  • Desktop: fixes call-end auto-stop and improves source-aware diarization behavior for native call capture.
  • CLI: no command contract changes.
  • MCP / agent integrations: no tool contract changes; minutes-sdk, minutes-mcp, and the .mcpb bundle move to 0.14.1.
  • Distribution: release metadata and package versions are refreshed for the patch release.

Breaking changes or migration notes

  • None.
  • Existing stop_when_call_ends configs continue to work. If you disabled the flag after v0.14.0, re-enable it with:
[call_detection]
stop_when_call_ends = true
  • For the diarization fix, keep source-aware/native call capture enabled and upgrade to v0.14.1; older transcripts are not rewritten.

Known issues

  • Windows desktop installer artifacts are still unsigned and should be treated as the existing preview/advanced-user surface.
  • GitHub Actions reports Node.js 20 deprecation warnings for upstream actions; these do not affect the v0.14.1 artifacts.

v0.14.0: Desktop context, video review, and a self-healing extension

23 Apr 19:25

Choose a tag to compare

Minutes 0.14.0: Desktop context, video review, and a self-healing extension

Minutes 0.14.0 promotes desktop context to a first-class MCP surface, ships a new /minutes-video-review workflow for Looms and ScreenPal recordings, splits the Apple Speech live backend from the main transcription engine with a proper fallback chain, and lands a round of call-capture reliability fixes (hybrid source-aware diarization, device-name canonicalization, Parakeet CPU fallback, native-capture loopback bypass).

Headline features

Desktop context is now a real product surface

A new local context.db captures meeting-adjacent activity (docs opened, terminals active, browser tabs) around every recording and live session. Three new MCP tools query it:

  • activity_summary: what happened in a time window (works without a transcript)
  • search_context: keyword lookups across captured context
  • get_moment: rewind to a specific timestamp

Useful even when you weren't recording. Shared Windows and Linux collectors land alongside the existing macOS path.

/minutes-video-review workflow

Drop a Loom, ScreenPal recording, bug repro clip, or local screen walkthrough and Minutes produces a durable review artifact: transcript, sampled frames, metadata, and a briefable bundle any agent can read. Available as a plugin skill and as a portable skill for Codex, Gemini, and OpenCode.

Apple Speech live backend, done right

Standalone live transcription (minutes live) now has its own backend picker, separate from the general transcription engine. Old overloaded configs migrate automatically. The scope is explicitly standalone-live-only: see docs/APPLE_SPEECH.md.

Live now falls back cleanly: Apple Speech → Parakeet → Whisper. Parakeet itself falls back to CPU when the GPU path is unavailable, so builds without Metal/CUDA still work end-to-end.

Call capture reliability

  • Hybrid source-aware diarization. When dual-source stems are available (mic + system audio), diarization keeps your local voice ownership stable and refines remote speakers from the system stem. Chunks aligned by index, not wall-clock, so long calls stay coherent.
  • Device-name canonicalization. Decorated picker labels persisted from older versions ("MacBook Pro Microphone (Built-in)", etc.) now resolve to the real CoreAudio device, so your saved recording device keeps working after upgrades.
  • Native call capture can bypass the loopback preflight when the desktop path is available, so ScreenCaptureKit-based setups don't need a loopback driver installed to record system audio.

Self-healing Claude Desktop extension

The hosted .mcpb bundle used to break every time we cut a release. The MCP server required an exact CLI version match, and the auto-installer pinned to a specific GitHub release tag. Any version skew produced scary mismatch warnings, and once a pinned tag was cleaned up or renamed, auto-install returned a 404.

Phases 1 and 2 of #183 both land in this release.

Phase 1: same-major semver compatibility.

  • CLI 0.14.0 against MCP 0.13.3, or the reverse, is now a silent compatible combination. Only cross-major skew (1.x vs 0.x) emits the upgrade message. No more warning spam.
  • Auto-install switched to GitHub's releases/latest/download/ redirect. Hosted .mcpb bundles pull the newest CLI regardless of what version they shipped with, and deleting or renaming old releases is safe.

Phase 2: capabilities feature probe.

  • New minutes capabilities --json CLI command returns a stable schema describing what the CLI build supports. Shape: { version, api_version, features: {...} }.
  • MCP server probes capabilities at boot (synchronously, so tool registration can consult it) and feature-gates the three new 0.14.0 context tools: activity_summary, search_context, get_moment. Gate is fail-closed: a CLI that cannot respond to the probe (too old, missing, or crashed) has the gated tools hidden rather than exposed and failing at call time.
  • Wire-contract version is pinned at api_version: 1. Reports from a future incompatible CLI are rejected so an old MCP cannot silently trust a new schema.
  • Consumers must treat missing feature keys as false. Adding a new feature does not bump api_version.

Phase 3 (decoupled MCP_API_VERSION vs RELEASE_VERSION surfaces) is planned for a follow-up. See #183.

Quality-of-life

  • Calendar respects [calendar] enabled=false throughout. The background poller no longer auto-launches Calendar.app. The calendar-events helper is correctly bundled into release .app builds on macOS.
  • Build reliability. Auto-recovers from stale ort-sys clang_rt paths after Xcode upgrades (the library not found that tends to follow macOS major updates). CLI and app feature flags stay in sync.
  • Setup polish. minutes setup --demo ships with aligned public metadata.

Agent surfaces

  • llms.txt enumerates the full skill catalog with CI enforcement.
  • The Claude plugin tree now emits per-skill scripts/ and references/ assets for Claude host's copy asset policy.
  • Generated agent docs (.agents/skills/, .opencode/skills/, .opencode/commands/) stay in lockstep via a compiler check.
  • Surface audits guard against silent skill, hook, and pack drift.

Install

# MCP server (zero-install)
npx minutes-mcp

# CLI
brew install silverstein/tap/minutes
# or
cargo install minutes-cli

# Then
minutes setup --model tiny     # whisper
minutes setup --parakeet       # parakeet (optional)
minutes setup --demo           # 5 bundled fixture meetings

For Claude Desktop, download minutes.mcpb from this release and double-click to install.

Claude Code plugin (0.9.0)

The plugin bumps to 0.9.0 alongside this release, with a new minutes-video-review skill and the full per-skill asset tree. Existing users, refresh with:

/plugin marketplace update minutes
/plugin update minutes@minutes

Then restart Claude Code.

Thanks

Thanks to @edwinvlieg for a first-time contribution this cycle, and to everyone in Discussions and Issues who flagged the desktop-context rough edges and the live-backend confusion that led to the Apple Speech split.

v0.13.3: Meeting-reliability fixes from the field

21 Apr 16:08

Choose a tag to compare

v0.13.3: Meeting-reliability fixes from the field

0.13.3 is a patch release focused on two bugs that showed up in real calls, plus a handful of platform and tooling fixes that make the rest of the stack easier to trust.

If you're on 0.13.0 or later you can upgrade in place. If you somehow held at 0.12.x, read v0.13.0 and v0.13.2 first; those shipped the settings, identity, call-aware recording, and mic-mute work that this release builds on.

Two meeting-reliability fixes from user reports

Both of these came from @athal7 running Minutes on Zoom calls with real hardware and writing up what actually happened. That's the loop we want.

Auto-stop actually auto-stops now

stop_when_call_ends shipped in 0.13.0 to auto-stop recordings 30 seconds after the call app quits. It worked for most users. For Andrew's setup it logged call_ended and then a state race killed the countdown before it could fire.

The fix: once the countdown is armed, the countdown thread alone owns the lifecycle. No atomics flip in the detector's poll loop can orphan it mid-tick. Same call getting re-detected mid-countdown (Zoom hiccup, back-to-back meetings, reconnect) now cancels the countdown instead of firing it in the middle of a live call. And a rejected cmd_start_recording during an active session can no longer silently kill an in-flight countdown.

Regression test locked in. If this breaks again we'll see it in CI, not in a user's log dump.

Context: issue #129.

Stem diarization has an escape hatch for open-speaker mics

If you join Zoom with Studio Display speakers, a laptop mic, or a USB desk mic sitting near the speakers, your mic acoustically picks up the other people in the call. A hardcoded 0.85 stem-correlation gate was reading that bleed as "same person on both sources" and collapsing every meeting to a single SPEAKER_0.

The gate is now configurable:

[diarization]
stem_correlation_threshold = 1.0   # disables the collapse entirely

Default stays at 0.85, so no existing setup changes. Set it to 1.0 to keep SPEAKER_1+ labels on open-speaker calls. Set it anywhere in between to tune the aggressiveness of the collapse for your room.

This is step one. A structural fix (ML fallback targets the mix or a stricter heuristic) needs telemetry on how often the collapse actually fires in the wild before we commit to a shape. For now, the config knob unblocks Andrew and anyone else on open-speaker setups.

Context: issue #157, PR #158.

Also in this release

  • Linux recording no longer segfaults on some PipeWire setups. A double host init/teardown path inside the capture plan was tripping an abort inside pipewire-sys. Fixed the lifetime so the host stays live for the duration of the session. (#160)
  • npx minutes-mcp works from npm shims now. The MCP server's entrypoint guard compared process.argv[1] to __filename as raw strings, which didn't match for npm .bin shims and /var vs /private/var path variants. It now compares canonical realpaths. OpenCode, Cursor, and npx launches connect cleanly.
  • summarize handles the auto engine in the speaker-mapping dispatch instead of erroring. (#156)
  • Recall (the multi-agent CLI launcher) got three fixes: per-agent scoping of approval-bypass flags so a Claude setting doesn't bleed into Codex or OpenCode, OpenCode agent settings support, and assistant workspaces now sync to the generated portable skill trees so agents other than Claude Code see the same helpers.
  • ./scripts/install-dev-app.sh now pre-signs nested executables (like mic_check) before the deep app sign, so Developer ID signing doesn't reject missing timestamps on subcomponents. Contributors with a local signing identity get a clean signed dev app the first time.

New

  • minutes setup --demo installs a bundled fixture corpus of two meetings so new users can see the search, graph, and summarize surfaces light up immediately without recording anything first. Useful for demos, reviewer onboarding, and "what does the MCP actually do?" moments.
  • Frontmatter gains authority and supersedes fields on Decision entries. Opt-in schema extensions for teams that want to mark one decision as overriding another. No behavior change if you don't set them.

CLI / MCP / desktop impact

  • Desktop: the call-end countdown fix lives here. If you had stop_when_call_ends = true and it was silently failing, reinstall and try again.
  • CLI: minutes setup --demo is new. Diarization threshold tunable via config.
  • MCP: minutes-mcp@0.13.3 on npm. npm-shim launch path is fixed. Bundle and tool contract unchanged from 0.13.2.
  • Shared engine: PipeWire fix and diarization threshold both live in minutes-core, so the CLI and desktop app get them in lockstep.

Upgrade path

Claude Desktop extension:

  1. Open Claude Desktop, Settings, Connectors, Minutes.
  2. Click Update, or uninstall and reinstall from the new minutes.mcpb attached below.

Homebrew:

brew update && brew upgrade silverstein/tap/minutes

Direct CLI:

cargo install minutes-cli

npm / MCP:

npx minutes-mcp@latest
# or
npm i minutes-sdk@latest

Claude Code plugin:

/plugin marketplace update minutes
/plugin update minutes@minutes

Then restart Claude Code so the plugin reloads.

Desktop app: download the DMG below (Apple Silicon) or the Windows installer. Linux users: cargo install minutes-cli is the supported path.

Thanks

  • @athal7 for two excellent field reports with logs, repro shapes, and patience while we worked through the state-race diagnosis.
  • Everyone who opened issues, tried recent releases, and sent feedback. Keep it coming.

v0.13.2: Mic-mute toggle + 0.13 series rollup

18 Apr 16:48

Choose a tag to compare

0.13.2 adds the mic-mute toggle for passive attendance and rolls up everything that shipped in the 0.13 series this week. If you installed Minutes before 0.13.0 landed two days ago, this is the single version to move to. If you updated to 0.13.0 or 0.13.1 already, you only get the mic-mute change on top of what you have.

What's new in 0.13.2: mic-mute

You're on a webinar, an all-hands, or a panel where you're not going to speak. You want the meeting transcript, but you don't want your breathing, typing, coffee-shop background, or the phone call in the next room feeding noise into your speaker attribution. One tap: mic muted, system audio keeps flowing.

This is not a Zoom/Teams/Meet mute. It's a Minutes-local gate that drops your microphone from the recording while the system audio stream keeps going untouched. Meeting content stays intact, your side of the room doesn't.

Thanks to @maxtacu for the clean feature request in discussion #146.

Three ways to use it:

  • Desktop app: tray menu, "Mute My Mic (Recording Only)". Click again to unmute.
  • CLI, at record start: minutes record --mute-mic begins the session muted.
  • CLI, mid-recording: minutes mic-toggle flips the current state. minutes mic-toggle --state on or --state off forces a specific state. Useful from scripts, keyboard shortcut tools, or Stream Deck bindings.

Events MicMuted and MicUnmuted are appended to ~/.minutes/events.jsonl whenever the state changes, so anything subscribed to the event stream can react.

Only meaningful when dual-source capture is active (mic + system audio). If you're recording with a single mic, muting it just produces silence, so Minutes treats it as a no-op there. In dual-source mode, the voice stem is zero-filled during the mute window (preserving timing and stem alignment) while the system stem is untouched. State is scoped to a single recording: start a new session and the mic comes back up.

Rolled up from 0.13.1 (packaging fix, yesterday)

The 0.13.0 minutes.mcpb contained two Next.js chunks whose filenames literally included ... Claude Desktop 1.3109.0 shipped a strict path-traversal guard that rejected any zip entry with .., even when it was literal characters inside a filename and not a directory traversal. Users on the new Claude Desktop saw "Failed to preview extension: Unsafe file path detected" at install time, or a silent server disconnect after the initialize handshake if they had installed 0.13.0 on an older Claude Desktop and then upgraded.

  • .mcpbignore now excludes /.vercel/ and /.next/ at the repo root, so release builds never leak these files again.
  • scripts/check_mcpb_bundle.sh fails if any packed entry contains .., so this regression gets caught before the release is cut.
  • New crates/mcp/src/crashTracer.ts: a synchronous file-based crash tracer that bootstraps before any other import and writes to ~/.minutes/logs/mcp-crash.log. If a future host swallows stderr the way Claude Desktop did here, the next regression produces a readable trace instead of a silent exit.
  • Bumped @modelcontextprotocol/ext-apps to 1.6.0 while we were here.

Rolled up from 0.13.0 (two days ago)

0.13.0 was a "come back and try it again" release. The biggest theme was trust.

  • Settings UX tighter: important toggle rows no longer drift out of sync with what you clicked. The command palette shortcut finally has a real UI row instead of a half-wired path.
  • Stronger identity setup: add your name, emails, and name variants so Minutes recognizes you more reliably across calendars, frontmatter, and conversation memory.
  • Smarter call-aware recording: Teams web detection works across Arc, Safari, and Chrome. stop_when_call_ends is now exposed in the desktop UI.
  • More resilient capture: pinned-device capture is more stable on Linux, and device handling is better when labels are decorated or ambiguous.
  • Autoresearch tooling: compare decode-hint eval runs and list recent research runs directly from the CLI.
  • Safer Claude Desktop packaging: the .mcpb bundle includes the runtime files it actually needs, which fixed a broken-extension class of failure on install. (The 0.13.1 fix above covers the other half of that story, the filename path-traversal piece.)

Who should care

  • Passive-attendance users: anyone who joins webinars, all-hands, or panels where they want the meeting transcript without their side of the room bleeding in. Mic-mute is built for you.
  • Desktop users who bounced off weird settings behavior before, or wanted better call-aware recording.
  • Claude Desktop users who install Minutes as an extension. If 0.13.0 broke for you, 0.13.2 fixes it.
  • CLI and operator-heavy users who tune recognition quality or run eval loops.
  • Anyone who wants Minutes to recognize them more consistently across meetings.

CLI / MCP / desktop impact

  • Desktop: new tray menu item for mic-mute. Everything 0.13.0 added (settings UX, identity config, Teams detection, call-end behavior) is intact.
  • CLI: two new surfaces (record --mute-mic flag, mic-toggle subcommand), plus the 0.13.0 autoresearch commands.
  • MCP: minutes-mcp@0.13.2 on npm. The bundle is clean of .. filenames, the crash tracer is in place, and the handshake / tools / resources contract is unchanged from 0.13.x.
  • Shared engine: mic-mute gate lives in crates/core/src/streaming.rs and capture.rs, so it's consistent across the CLI and desktop app.

Upgrade path

Claude Desktop extension:

  1. Open Claude Desktop, Settings, Connectors, Minutes.
  2. Click Uninstall.
  3. Download the new minutes.mcpb from this release and reinstall.

npx minutes-mcp: run npx minutes-mcp@latest and restart the client.

CLI or desktop app directly:

cargo install minutes-cli
# or
brew install silverstein/tap/minutes

Then run minutes setup --model tiny or minutes setup --parakeet on first use.

Breaking changes or migration notes

None. Strictly additive feature work plus the 0.13.1 packaging and diagnostic fixes.

Known issues

  • The Windows desktop installer is still unsigned, so Windows may show SmartScreen / unknown publisher warnings even though the build is valid.
  • Homebrew tap updates may lag the GitHub release briefly after publish.

v0.13.1: Fix Claude Desktop extension install on 1.3109.0

18 Apr 03:27

Choose a tag to compare

v0.13.1: Fix Claude Desktop extension install on 1.3109.0

What changed

This is a patch release that fixes a broken install surface in the Claude Desktop extension, reported in #149.

The v0.13.0 minutes.mcpb bundle contained two Next.js chunks whose filenames literally include ..:

.vercel/output/static/_next/static/chunks/0c1n75d4d01s..js
.vercel/output/static/_next/static/chunks/0yhyx4ni~s7z..js

Claude Desktop 1.3109.0 shipped a strict path-traversal guard that rejects any zip entry containing .., even when the .. is literal characters inside a filename and not a directory traversal. Result: users on the new Claude Desktop saw either "Failed to preview extension: Unsafe file path detected" at install time, or a silent server disconnect right after the initialize handshake if they had installed v0.13.0 on an older Claude Desktop and then upgraded.

Root cause: release checklist step 12 runs npx vercel build from the repo root, which creates a .vercel/output/ tree at the top level. .mcpbignore only excluded site/, so those Next.js chunks leaked into the bundle.

What you get in 0.13.1

  • .mcpbignore now excludes /.vercel/ and /.next/ at the repo root, so release builds never leak these files again.
  • scripts/check_mcpb_bundle.sh now fails if any packed entry contains .., so this regression gets caught before the release is cut, not after users hit it.
  • Bumped @modelcontextprotocol/ext-apps to 1.6.0 while we were here.
  • New crates/mcp/src/crashTracer.ts: a synchronous file-based crash tracer that bootstraps before any other import and writes to ~/.minutes/logs/mcp-crash.log. If a future host swallows stderr the way Claude Desktop did here, the next regression will produce a readable trace instead of a silent exit.

Who should care

  • Anyone who installed the Minutes Claude Desktop extension and saw it disappear after updating Claude Desktop.
  • Anyone who tried to install the v0.13.0 .mcpb on Claude Desktop 1.3109.0 or later and hit "Failed to preview extension."

Upgrade path

If you use the Claude Desktop extension:

  1. Open Claude Desktop → Settings → Connectors → Minutes.
  2. Click Uninstall.
  3. Download the new minutes.mcpb from this release and reinstall.

If you use npx minutes-mcp: just run npx minutes-mcp@latest and restart the client. No manual reinstall step.

If you use the CLI or desktop app directly: nothing to do. Those binaries did not change in this release.

CLI / MCP / desktop impact

  • Desktop app: no functional change. Same binary as v0.13.0.
  • CLI: no functional change. Same binary as v0.13.0.
  • MCP: packaging fix only. Handshake, tools, and resources are unchanged.

Breaking changes or migration notes

None. This is strictly a packaging and diagnostic release.

Known issues

  • The Windows desktop installer is still unsigned, so Windows may show SmartScreen / unknown publisher warnings even though the build is valid.
  • Homebrew tap updates may lag the GitHub release briefly after publish.

v0.13.0: Settings you can trust, smarter call capture, and better operator tooling

17 Apr 00:47

Choose a tag to compare

v0.13.0: Settings you can trust, smarter call capture, and better operator tooling

What changed

Minutes 0.13.0 is a “come back and try it again” release.

The biggest theme is trust:

  • Settings behavior is much tighter now. Important toggle rows no longer drift out of sync with what you clicked, and the command palette shortcut finally has a real UI row instead of a half-wired path.
  • Identity setup is stronger. You can add your name, emails, and name variants so Minutes recognizes you more reliably across calendars, frontmatter, and conversation memory.
  • Call-aware recording is better. Teams web detection is smarter across Arc, Safari, and Chrome, and stop_when_call_ends is now exposed in the desktop UI.
  • Capture is more resilient. Pinned-device capture got more stable on Linux, and device handling is better when labels are decorated or ambiguous.
  • Operator workflows got new local research tooling. You can now compare decode-hint eval runs and list recent research runs directly from the CLI.
  • Claude Desktop extension packaging is safer. The .mcpb bundle now includes the runtime files it actually needs, which fixes a broken-extension class of failure on install.

Who should care

  • Desktop users who bounced off weird settings behavior or wanted better call-aware recording should care.
  • Claude Desktop users who install Minutes as an extension should care.
  • CLI and operator-heavy users who tune recognition quality or run eval loops should care.
  • Anyone who wants Minutes to recognize them more consistently across meetings should care.

CLI / MCP / desktop impact

  • Desktop: this is the biggest surface in the release. Settings UX, identity configuration, Teams web detection, and call-end behavior all got meaningfully better.
  • CLI: new autoresearch commands make it easier to compare decode-hint eval runs and inspect recent research output locally.
  • MCP: the minutes-mcp package is now 0.13.0, and the Claude Desktop .mcpb bundle includes the runtime files it needs.
  • Shared engine: capture stability, summarization-language support, and recognition/eval infrastructure improvements all land underneath multiple surfaces.

Breaking changes or migration notes

  • No intentional breaking changes in the user-facing command or tool contract.
  • If you are using the Claude Desktop extension and had a broken older install, reinstall from the new minutes.mcpb attached to this release.
  • If you install through npm, upgrade to the current packages:
    • npx minutes-mcp@latest
    • npm i minutes-sdk@latest

Known issues

  • The Windows desktop installer is still unsigned, so Windows may show SmartScreen / unknown publisher warnings even though the build is valid.
  • Homebrew tap updates and other off-repo distribution surfaces may lag the GitHub release briefly after publish.
  • As always, if a stable release surfaces a serious regression, we cut a new patch version; we do not retag or silently replace history.

v0.12.2: Live transcription that actually works on quiet audio

15 Apr 22:32

Choose a tag to compare

v0.12.2: Live transcription that actually works on quiet audio

Why this release exists

A meeting today produced 11 fragments over 40 minutes of live transcript — mostly whisper placeholder tokens like [typing] and [BLANK_AUDIO]. Meanwhile the post-recording batch transcript cleanly recovered 2,259 words from the same WAV. Same audio, two different code paths, 200x quality gap.

Three problems were working against live mode:

  1. The recording sidecar used a simple energy-threshold VAD. Quiet audio (-44 dB RMS when you're on headphones and the other person barely bleeds through) fell below the threshold and got gated out before whisper ever saw it.
  2. engine = "parakeet" in the config was effectively a lie. It controlled the post-recording batch path but live-during-record was hard-coded to whisper.
  3. Whisper's quiet-audio placeholder tokens ([typing], [Musik], [BLANK_AUDIO]) were flowing straight into the live JSONL output, trashing agent context.

v0.12.2 fixes all three.

Fixes

  • Silero VAD in the recording sidecar. Same ML-based model the batch path uses, already on disk from minutes setup. Graceful fallback to the old energy VAD if Silero initialization fails. Adds gating stats to the finalize log so you can see how many samples were fed vs gated.
  • engine = "parakeet" now applies to live transcription during minutes record. Per-utterance dispatch to Parakeet through the existing crate::transcribe::transcribe entry point, which reuses the warm sidecar socket when parakeet_sidecar_enabled = true. Mid-session Parakeet failures flip the session back to whisper with a clear warning instead of silently breaking.
  • Whisper placeholder tokens no longer make it into live JSONL. The streaming write path now routes text through whisper-guard's collapse_noise_markers and strip_foreign_script filters before writing. Empty results are dropped instead of producing blank utterances.
  • Clear docs on which code paths use which engine. docs/PARAKEET.md gains a Scope section listing exactly where Parakeet is wired today: batch transcription, folder watcher memos, and recording-sidecar live transcription. Standalone minutes live and dictation still use whisper and are documented as such.

For users on v0.12.1

If you set engine = "parakeet" and tried live mode, you got whisper with a weak VAD. This release is the fix. The desktop app auto-update and brew upgrade silverstein/tap/minutes will pick it up.

Install

CLI:

brew upgrade silverstein/tap/minutes
# or
cargo install minutes-cli

MCP server (zero-install):

npx minutes-mcp@latest

Desktop app: download the DMG from useminutes.app or let the auto-updater pick it up.

Claude Desktop: grab minutes.mcpb from this release and drag it into Claude Desktop's Extensions settings.

v0.12.1: Frontmatter polish, Parakeet hardening, LLM titles

15 Apr 18:52

Choose a tag to compare

v0.12.1: Frontmatter polish, Parakeet hardening, and LLM titles

What changed

This release is a focused polish pass over the work that landed in v0.12.0. The transcription pipeline was doing a lot — transcribe, diarize, summarize, extract entities, match calendar events, write markdown — and the seams between those steps were leaking. Speaker labels from diarization were ending up in attendee lists, email addresses from calendars were spawning duplicate people, and "Untitled Recording" was the title more often than anyone was willing to admit.

v0.12.1 closes those seams.

Frontmatter polish

The biggest visible change is that meeting frontmatter now reflects real humans instead of pipeline artifacts.

  • Speaker labels like SPEAKER_1, Speaker_1 (Name), and Name (speaker_1) no longer leak into attendees, people, entities.people, or action_items[].assignee. They get resolved to names via the speaker map, or stripped if the confidence was too low.
  • Calendar email addresses now fold onto the matching person entity instead of spawning their own. A calendar attendee like alex@example.com becomes an alias of the existing Alex entity instead of producing a separate alex-example-com slug.
  • /-disambiguated hedges like Alex / Alexander collapse to the canonical head (Alex) in both attendees and entities.people, and the full form is preserved as an alias.
  • Decision topics no longer read speaker 1 provide speaker. They get normalized through the speaker map before topic derivation.
  • Project slugs reject task-like verb starts (pioneer-asked-build, reach-out) while still preserving legitimate noun phrases (Review Board, Study Group).

New: [identity] config for multi-email humans

Most users have more than one email address — work, personal, consulting — and the same human shows up under different ones across different calendars. v0.12.1 adds emails and aliases under [identity] so Minutes can recognize you across all of them.

[identity]
name = "Mat"
emails = [
    "mat@work.com",
    "mat@personal.com",
    "mat@consulting.co",
]
aliases = ["Mathieu", "Matthew"]

Everything listed here folds onto the Mat entity instead of spawning duplicates in entities.people or graph.db. Your legacy email = "..." field still works.

LLM-driven title refinement

"Untitled Recording" is no longer the default. After summarization, a lightweight LLM title pass looks at the summary and proposes a real title like Command RX PBM Reconciliation and 835 File Access Planning. The pipeline logs both the LLM duration and the filename-rename time separately so it's obvious which step is slow when one of them is.

Parakeet hardening

The opt-in Parakeet path introduced in v0.12.0 got a lot of work too.

  • Binary auto-resolution searches /opt/homebrew/bin, /usr/local/bin, and ~/.local/bin if parakeet_binary is unset, and logs which candidate it picked on every resolution.
  • The binary health check no longer probes with --version (which exits non-zero on most Parakeet builds); it now checks that the file exists and is executable.
  • parakeet_fp16 now defaults to true on Apple Silicon, matching the measured ~35% faster transcription with lower GPU memory.
  • Optional warm sidecar (parakeet_sidecar_enabled = true) reuses a single Parakeet process across chunks for lower per-chunk latency. Falls back to subprocess on crash.

Observability

Every pipeline stage now emits a structured JSON log line with step, duration_ms, and step-specific extra metadata:

  • transcribe, summarize, entity_extract, action_items, intent_extract, speaker_mapping, title_generation, attribution, write, pipeline_complete

Useful for debugging slow pipelines and for the upcoming dashboard integrations.

Calendar + EventKit

Meeting processing now passes the recording's actual timestamp to EventKit when looking for a matching calendar event, so delayed processing (voice memos from yesterday, old recordings reprocessed) matches the right event instead of whatever is happening right now. No more AppleScript fallback being triggered unnecessarily.

Tauri auto-update UX

The macOS desktop app's auto-updater gains a real state machine: checking, downloading, verifying, installing, ready, and error phases are all surfaced to the UI, along with progress percentage, ETA, and a cancel affordance.

Misc

  • Arc browser added to Google Meet call detection
  • XDG_CONFIG_HOME is now honored when locating config.toml
  • Cross-platform parakeet feature build added to the main CI matrix so Linux regressions surface before tag push, not after
  • Meeting prompt titles no longer double-escape when URL-encoded

Install

CLI only:

brew install silverstein/tap/minutes
# or
cargo install minutes-cli

MCP server (zero-install):

npx minutes-mcp@latest

Desktop app: download the DMG from useminutes.app.

Claude Desktop: grab minutes.mcpb from this release and drag it into Claude Desktop's Extensions settings.

v0.12.0: Parakeet multilingual by default + native VAD

14 Apr 16:32

Choose a tag to compare

v0.12.0: Parakeet is multilingual by default

What changed

This release makes the Parakeet path feel like a first-class part of Minutes instead of an advanced toggle you had to babysit.

The biggest change is the default model. If you choose Parakeet and do not pin a model explicitly, Minutes now defaults to tdt-600m, the multilingual v3 model, instead of the older English-only tdt-ctc-110m. That means better support for bilingual meetings, better WER, and a much more honest default for how people actually use the app.

Parakeet itself also got a real sweep of upgrades. Native VAD now replaces the old fixed 45-second slicing when the weights are available, so longer recordings are handled on speech boundaries instead of being chopped into arbitrary windows. The folder watcher now batches memo bursts, which cuts the raw transcription time for a 10-file burst from 18.77 seconds to 7.25 seconds in our local benchmark. There is also a new opt-in fp16 mode for people who want to experiment with lower memory use, and an opt-in graph-driven vocabulary boost path for proper nouns and project names.

The app is more honest about upgrades now too. If you already had the old 110m Parakeet model on disk and silently inherit the new default, the error message tells you exactly what happened, tells you to run minutes setup --parakeet, and shows you how to pin the old model if that is what you want.

Breaking-ish behavior change

Parakeet now defaults to tdt-600m instead of tdt-ctc-110m.

If you already use Parakeet, do one of these:

  1. Run:
minutes setup --parakeet

That fetches the new multilingual default.

  1. Or pin the old English-only model in ~/.config/minutes/config.toml:
[transcription]
parakeet_model = "tdt-ctc-110m"
parakeet_vocab = "tdt-ctc-110m.tokenizer.vocab"

Why the default changed:

  • tdt-600m is multilingual v3
  • it handles Spanish and other European languages properly
  • it gives lower WER than the old compact English model

Highlights

  • Parakeet is multilingual by default with tdt-600m
  • Native Parakeet VAD replaces the old fixed 45-second chunking behavior when weights are available
  • minutes setup --parakeet now installs the native Parakeet VAD weights automatically
  • Folder watcher memo bursts are batched for much faster Parakeet processing
  • parakeet_fp16 is available as an experimental opt-in for GPU runs
  • Graph-derived --boost phrases are available as an experimental opt-in for proper nouns and project names
  • Upgrade-time Parakeet errors now point to the correct setup command and can detect the old 110m-only install state

Install

# CLI
brew tap silverstein/tap && brew install minutes
# or
cargo install minutes-cli

# MCP server
npx minutes-mcp@0.12.0

# SDK
npm install minutes-sdk@^0.12.0

Desktop builds are attached below:

  • macOS Apple Silicon DMG
  • Windows installer

Notes

  • parakeet_fp16 is intentionally off by default for now. Quality held in our benchmark, but cold-start latency regressed on the current process-per-transcription runtime.
  • Graph-derived boost phrases are also off by default for now. The first evaluation was mixed, so the mechanism is shipped as an experimental tuning surface instead of a silent heuristic.