minutes

GitHub stars License: MIT crates.io

Open-source conversation memory.   useminutes.app

Your AI remembers every conversation — and no one can take it from you.

Agents have run logs. Humans have conversations. minutes captures the human side — the decisions, the intent, the context that agents need but can't observe — and makes it queryable. Record a meeting. Capture a voice memo on a walk. Dictate a thought at your cursor. Ask Claude "what did I promise Sarah?" — and get an answer.

Everything is transcribed on your machine and written to ~/meetings/ as plain markdown, which every AI you use (Claude Code, Codex, Gemini CLI, Cursor, OpenCode, Pi) reads directly. Nothing is uploaded. When a cloud memory app gets acquired or subpoenaed, your recordings aren't theirs to hand over — they never left your disk.

The private, owned conversation-memory layer. Not another AI notetaker — that category ships free inside Zoom and Meet now. Minutes is audio capture, transcripts, decisions, commitments, people, and provenance as plain files, CLI commands, MCP tools, and live transcript streams. No SDK. No API key. No vendor to outlive. Ten years from now, grep still works on your corpus.  For agents →  ·  Frontmatter schema →

Works with

Quick start

# macOS — Desktop app (menu bar, recording UI, AI assistant)
brew install --cask silverstein/tap/minutes

# macOS — CLI only
brew tap silverstein/tap && brew install minutes

# Newer Homebrew versions distrust third-party taps by default; if brew warns
# "Skipping silverstein/tap because it is not trusted", run once:
brew trust silverstein/tap

# Any platform — from source (requires Rust + cmake; Windows also needs LLVM)
cargo install minutes-cli                          # macOS/Linux
cargo install minutes-cli --no-default-features    # Windows (see install notes below)

# MCP server only — no Rust needed (Claude Code, Codex, OpenCode, Gemini CLI, Claude Desktop, etc.)
npx minutes-mcp
minutes setup --model small   # Download whisper model (466MB, recommended)
minutes record                # Start recording
minutes stop                  # Stop and transcribe

Docs and agent surfaces

The README is now the product overview and install guide, not the only home for agent-facing reference.

Choose your surface

  • Desktop appbrew install --cask silverstein/tap/minutes Best for first recording, live capture, Recall, and post-meeting artifact work.
  • MCP servernpx minutes-mcp Best for agent-first search, recall, and meeting-memory workflows in Claude Desktop, Codex, OpenCode, Gemini CLI, and other MCP clients.
  • CLIbrew tap silverstein/tap && brew install minutes Best for terminal-first local operator workflows, import, search, and vault sync.
  • Claude Code pluginclaude plugin marketplace add silverstein/minutes Best for workflow guidance, prep, debrief, and meeting coaching with the lifecycle skills and hooks.
  • OpenCode project integration — built-in .opencode/skills/ + .opencode/commands/ Best for OpenCode users who want native /minutes-* commands plus the portable Minutes skill pack in the repo.

How it works

Audio → Transcribe → Diarize → Summarize → Structured Markdown → Relationship Graph
         (local)     (local)     (LLM)       (decisions,            (people, commitments,
        whisper.cpp  pyannote-rs Claude/       action items,          topics, scores)
        /parakeet    (native)    Ollama/       people, entities)      SQLite index
                                Mistral/OpenAI

Everything runs locally. Your audio never leaves your machine (unless you opt into cloud LLM summarization). Speakers are identified via native diarization. The relationship graph indexes people, commitments, and topics across all meetings for instant queries.

Features

Record meetings

minutes record                                    # Record from mic
minutes record --title "Standup" --context "Sprint 4 blockers"  # With context
minutes record --language ur                      # Force Urdu (ISO 639-1 code)
minutes record --device "AirPods Pro"             # Use specific audio device
minutes record --template standup                 # Apply a summary template
minutes stop                                      # Stop from another terminal

Recording calls (Zoom, Meet, Teams, Webex): the desktop app captures both your mic and the call's audio natively (ScreenCaptureKit, macOS 15+, no extra software). Grant Screen Recording + Microphone permission and start from the "Call detected" banner; Google Meet and Teams-in-browser need their experimental detection toggles enabled. The CLI (minutes record) cannot use native capture, so for command-line call recording you route system audio through BlackHole and a Multi-Output Device. Full setup in docs/architecture/audio-devices.md.

Consent disclosure aid

For meetings where participant notice is required, Minutes can show a reminder, require an interactive acknowledgement, and stamp the chosen basis into the markdown frontmatter. This is a disclosure aid, not advice; ensure everyone present consents where required.

minutes record --consent verbal_all_parties
minutes record --consent notice_in_invite --consent-notice "Notice was included in the calendar invite."
[consent]
mode = "remind" # off | remind | require
disclosure_script = "Heads up: I'm using Minutes to transcribe this conversation locally on my device for my own notes. Let me know if you'd prefer I didn't."
# default_basis = "notice_in_invite"

When present, artifacts include:

consent: verbal_all_parties
consent_notice: Heads up: I'm using Minutes to transcribe this conversation locally on my device for my own notes. Let me know if you'd prefer I didn't.

Sensitive meetings

Use a sensitive meeting when you want timed typed markers and a saved meeting artifact, but no audio capture.

minutes sensitive start --title "Board prep"
minutes note "Opened with pricing risk"
minutes sensitive stop

The stop flow writes a normal markdown meeting with capture: none and sensitivity: restricted. In a terminal, Minutes prompts for a short debrief. From scripts or other non-interactive callers it saves immediately with debrief: pending so an assistant can help finish the written summary later.

Take notes during meetings

minutes note "Alex wants monthly billing not annual billing"          # Timestamped, feeds into summary
minutes note "Logan agreed"                       # LLM weights your notes heavily

Process voice memos

minutes process ~/Downloads/voice-memo.m4a        # Any audio format
minutes process ~/.minutes/native-captures/2026-05-19-120148-call.voice.wav --type meeting
minutes watch                                     # Auto-process new files in inbox

Search everything

minutes search "pricing"                          # Full-text search
minutes search "onboarding" -t memo               # Filter by type
minutes actions                                   # Open action items across all meetings
minutes actions --assignee sarah                   # Filter by person
minutes list                                      # Recent recordings

Relationship intelligence

"What did I promise Sarah?" — the query nobody else can answer.

minutes people                                     # Who you talk to, how often, about what
minutes people --rebuild                           # Rebuild the relationship index
minutes people merge junrei junlei jun-rei          # Confirm variants are one person (canonical first)
minutes commitments                                # All open + overdue commitments
minutes commitments --person alex                   # What did I promise Alex?

Tracks people, commitments, topics, and relationship health across every meeting. Detects when you're losing touch with someone. Suggests duplicate contacts ("Sarah Chen" ↔ "Sarah") and name-variant fragments a transcriber spelled several ways ("junrei" ↔ "junlei" ↔ "jun-rei"). minutes people --rebuild prints a ready-to-run minutes people merge command under each suggested cluster; confirming it records a durable alias so every variant collapses to the canonical person on future rebuilds. Powered by a SQLite index rebuilt from your markdown in <50ms.

Cross-meeting intelligence

minutes research "pricing strategy"               # Search across all meetings
minutes person "Alex"                              # Build a profile from meeting history
minutes consistency                                # Flag contradicting decisions + stale commitments

Live transcript (real-time coaching)

minutes live                                     # Start real-time transcription
minutes stop                                     # Stop live session

Streams local transcription to a JSONL file in real time — any AI agent can read it mid-meeting for live coaching. When the session stops, the default [live_transcript] promote_on_stop = "process" preserves the raw WAV/JSONL pair and runs the normal diarization and summarization pipeline to create a meeting; use "preserve" to keep only the timestamped source pair or "off" for the legacy overwrite-prone fixed slot. Depending on your build and config, live mode can run on Whisper, Parakeet, or the experimental Apple Speech standalone-live path. Apple Speech currently applies to standalone live transcript (minutes live) and opt-in dictation finalization, not recording-sidecar or batch transcription, and it falls back to a ready Parakeet backend before Whisper if Apple Speech is unavailable or fails mid-session in live mode. See docs/architecture/apple-speech.md for the current Apple Speech scope. The MCP read_live_transcript tool provides delta reads (by line cursor or wall-clock duration). Works with Claude Code, Codex, OpenCode, Gemini CLI, or any agent that reads files. The Tauri desktop app has a Live Mode toggle that starts this with one click.

Dictation mode

minutes dictate                                  # Speak → text appears as you talk
minutes dictate --stdout                         # Output to stdout instead of clipboard

Text streams progressively as you speak (partial results every 2 seconds). By default it accumulates across pauses and writes the combined text to clipboard + daily note when dictation ends. Set [dictation] accumulate = false to keep the older per-pause behavior. The default backend is local Whisper; on supported macOS builds, [dictation] backend = "apple-speech" tries Apple DictationTranscriber for final utterances, and [dictation] backend = "parakeet" tries the installed Parakeet backend for final utterances. Both opt-in paths keep Whisper partials and fallback. Linux clipboard output works through wl-clipboard on Wayland or xclip / xsel on X11; desktop auto-paste only attempts X11 paste automation when xdotool is available. Local engines, no cloud.

Command palette (desktop app)

Press ⌘⇧K from anywhere on macOS to open a keyboard-first palette of every Minutes command. Start a recording, drop a note into the active session, jump to the latest meeting, search transcripts, or rename the meeting open in your assistant — all without leaving the keyboard. Backed by a single typed command registry in minutes-core, so visibility follows real backend state: stop-recording only appears while you're recording, mid-recording dictation rows are hidden, and the list re-fetches automatically when state changes.

Recents float to the top with their original payload intact (re-running a Search transcripts: pricing from history skips the retype). The shortcut defaults on for both fresh installs and upgrades, with a one-time macOS notification on first launch announcing the binding. Disable it from the Settings overlay (Command Palette section) or by setting [palette] shortcut_enabled = false in your config file ($XDG_CONFIG_HOME/minutes/config.toml when XDG_CONFIG_HOME is set, otherwise ~/.config/minutes/config.toml). The Settings dropdown also offers ⌘⇧O and ⌘⇧U if ⌘⇧K collides with your IDE.

Templates (RFC 0001, Phase 1)

minutes template list                             # Bundled + project + user templates
minutes template show standup                     # Inspect a template
minutes record --template standup                 # Apply when recording
minutes process voice-memo.m4a --template voice-memo

Templates layer prompt-level guidance on top of the baseline structured extraction (KEY POINTS, DECISIONS, ACTION ITEMS, OPEN QUESTIONS, COMMITMENTS, PARTICIPANTS). Phase 1 ships four bundled templates (meeting, standup, 1-on-1, voice-memo) and resolves overrides from .minutes/templates/ (project) and ~/.minutes/templates/ (user). Custom extract: schemas, policy rules, and clinical templates land in later phases — see docs/rfcs/0001-templates.md.

Try it without a mic

minutes demo --full                              # Seed 5 sample meetings (Snow Crash theme)
minutes demo --query                             # Cross-meeting intelligence demo
minutes demo --clean                             # Remove sample meetings

The interactive demo seeds interconnected meetings, then lets you pick a thread to explore. Two storylines, five meetings, zero setup.

System diagnostics

minutes health                                   # Check model, mic, calendar, disk
minutes demo                                     # Run a pipeline test (bundled audio, no mic)

Switching from Granola?

Import your meeting history into Minutes' conversation memory. Once imported, your meetings become searchable context for AI agents, feed the relationship graph for meeting prep, and surface action items and decision patterns across months of conversations.

minutes import granola --dry-run    # Preview what will be imported
minutes import granola              # Import all meetings to ~/meetings/

Reads from ~/.granola-archivist/output/. Meetings are converted to Minutes' markdown format with YAML frontmatter. Duplicates are skipped automatically. All your data stays local — no cloud, no $18/mo.

Populating the export directory: ~/.granola-archivist/output/ has to be filled by a separate Granola export tool first. Recent Granola versions encrypt their local cache, which can break exporters that scrape it. If minutes import granola finds nothing, use the API-based granola-to-minutes route below instead (it reads Granola's API and writes straight to ~/meetings/).

Want transcripts and AI summaries?

granola-to-minutes exports richer data using granola-cli, a community-built CLI tool (not affiliated with Granola Labs) that accesses Granola's internal API:

minutes import granola granola-to-minutes
Data source Local export (~/.granola-archivist/output/) Granola internal API via granola-cli
Notes & transcript
AI-enhanced summaries
Action items & decisions ✓ (extracted via Claude)
Speaker attribution ✓ (speaker_map in frontmatter)
Setup Export from Granola desktop app npm install -g granola-to-minutes
Works on free tier
API stability N/A (local files) Internal API — may change without notice
npx granola-to-minutes export    # Export to ~/meetings/

Output format

Meetings save as markdown with structured YAML frontmatter:

---
title: Q2 Pricing Discussion with Alex
type: meeting
date: 2026-03-17T14:00:00
duration: 42m
context: "Discuss Q2 pricing, follow up on annual billing decision"
action_items:
  - assignee: mat
    task: Send pricing doc
    due: Friday
    status: open
  - assignee: sarah
    task: Review competitor grid
    due: March 21
    status: open
decisions:
  - text: Run pricing experiment at monthly billing with 10 advisors
    topic: pricing experiment
---

## Summary
- Alex proposed lowering API launch timeline from annual billing to monthly billing/mo
- Compromise: run experiment with 10 advisors at monthly billing

## Transcript
[SPEAKER_0 0:00] So let's talk about the pricing...
[SPEAKER_1 4:20] I think monthly billing makes more sense...

Works with Obsidian, grep, or any markdown tool. Action items and decisions are queryable via the CLI and MCP tools.

Phone → desktop voice memo pipeline

No phone app needed. Record a thought on your phone, and it becomes searchable memory on your desktop. Claude even surfaces recent memos proactively — "you had a voice memo about pricing yesterday."

The watcher is folder-agnostic — it processes any audio file that lands in a watched folder. Pick the sync method that matches your setup:

Phone Desktop Sync method
iPhone Mac iCloud Drive (built-in, ~5-30s)
iPhone Windows/Linux iCloud for Windows, or Dropbox/Google Drive
Android Any Dropbox, Google Drive, Syncthing, or any folder sync
Any Any AirDrop, USB, email — drop the file in the watched folder

Setup (one-time)

Step 1: Create a sync folder — pick one that syncs between your phone and desktop:

# macOS + iPhone (iCloud Drive)
mkdir -p ~/Library/Mobile\ Documents/com~apple~CloudDocs/minutes-inbox

# Any platform (Dropbox)
mkdir -p ~/Dropbox/minutes-inbox

# Any platform (Google Drive)
mkdir -p ~/Google\ Drive/minutes-inbox

# Or just use the default inbox (manually drop files into it)
# ~/.minutes/inbox/  ← already exists

Step 2: Add the sync folder to your watch config in your config file ($XDG_CONFIG_HOME/minutes/config.toml when XDG_CONFIG_HOME is set, otherwise ~/.config/minutes/config.toml):

[watch]
paths = [
  "~/.minutes/inbox",
  # Add your sync folder here — uncomment one:
  # "~/Library/Mobile Documents/com~apple~CloudDocs/minutes-inbox",  # iCloud
  # "~/Dropbox/minutes-inbox",                                       # Dropbox
  # "~/Google Drive/minutes-inbox",                                  # Google Drive
]

Step 3: Set up your phone

  1. Open the Shortcuts app on your iPhone
  2. Tap + → Add Action → search "Save File"
  3. Set destination to iCloud Drive/minutes-inbox/ (or your Dropbox/Google Drive folder)
  4. Turn OFF "Ask Where to Save"
  5. Tap the (i) info button → enable Share Sheet → set to accept Audio
  6. Name it "Save to Minutes"

Now: Voice Memos → Share → Save to Minutes → done.

Use any voice recorder app + your cloud sync of choice:

  • Dropbox: Record with any app → Share → Save to Dropbox → minutes-inbox/
  • Google Drive: Record → Share → Save to Drive → minutes-inbox/
  • Syncthing (no cloud): Set up a Syncthing share between phone and desktop pointing at your watched folder. Fully local, no cloud.
  • Tasker/Automate (power users): Auto-move new recordings from your recorder app to the sync folder.

No sync setup needed — just get the audio file to your desktop's watched folder:

  • AirDrop (Apple): Share → AirDrop to Mac → move to ~/.minutes/inbox/
  • Email: Email the recording to yourself → save attachment to watched folder
  • USB: Transfer directly

Step 4: Start the watcher (or install as a background service):

minutes watch                  # Run in foreground
minutes service install        # Install all background services (macOS launchd / Linux systemd)
minutes service status         # Check what's running
minutes service restart        # Restart all services (e.g. after upgrading the binary)

minutes service install sets up three agents:

Agent Schedule What it does
watcher Always on Processes voice memos from ~/.minutes/inbox/
weekly-summary Sundays 7pm Generates a weekly digest to ~/.minutes/automations/
proactive-context Daily 8am Builds a context bundle (recent meetings, stale commitments, losing-touch alerts)

Upgrading? minutes service install is idempotent. Re-running it after a binary upgrade rewrites all plists/units and reloads with the new binary path.

How it works

Phone (any)                   Desktop (any)
───────────                   ─────────────
Record voice memo        →    Cloud sync / manual transfer
Share to sync folder               │
                                   ▼
                            minutes watch detects file
                                   │
                            probe duration (<2 min?)
                              ├── yes → memo pipeline (fast, no diarization)
                              └── no  → meeting pipeline (full)
                                   │
                            transcribe → save markdown
                                   │
                            ├── event: VoiceMemoProcessed
                            ├── daily note backlink
                            └── surfaces in next Claude session

Short voice memos (<2 minutes) automatically route through the fast memo pipeline — no diarization, no heavy summarization. Long recordings get the full meeting treatment. The threshold is configurable: dictation_threshold_secs = 120 in [watch].

Optional: sidecar metadata

If your phone workflow also saves a .json file alongside the audio (same name, .json extension), Minutes reads it for enriched metadata:

{"device": "iPhone", "source": "voice-memos", "captured_at": "2026-03-24T08:41:00-07:00"}

This adds device and captured_at to the meeting's frontmatter. Works with any automation tool (Apple Shortcuts, Tasker, etc.).

Supports .m4a, .mp3, .wav, .ogg, .webm. Format conversion is automatic — uses ffmpeg when available (recommended for non-English audio), falls back to symphonia.

If a desktop call capture leaves a raw file under ~/.minutes/native-captures/, process that audio file directly with minutes process <path> --type meeting. For compatibility, minutes import <audio-file> also routes to the same meeting-processing path; minutes import granola remains the Granola history importer.

Vault sync (Obsidian / Logseq)

minutes vault setup              # Auto-detect vaults, configure sync
minutes vault status             # Check health
minutes vault sync               # Copy existing meetings to vault

Three strategies: symlink (zero-copy), copy (works with iCloud/Obsidian Sync), direct (write to vault). minutes vault setup detects your vault and recommends the right strategy automatically.

Claude integration

minutes is a native extension for the Claude ecosystem. No API keys needed — Claude summarizes your meetings when you ask, using your existing Claude subscription.

You: "Summarize my last meeting"
Claude: [calls get_meeting] → reads transcript → summarizes in conversation

You: "What did Alex say about pricing?"
Claude: [calls search_meetings] → finds matches → synthesizes answer

You: "Any open action items for me?"
Claude: [calls list_meetings] → scans frontmatter → reports open items

Any MCP client (Claude Code, Codex, OpenCode, Gemini CLI, Claude Desktop, or your own agent)

Minutes exposes a standard MCP server. Point any MCP-compatible client at it:

{
  "mcpServers": {
    "minutes": {
      "command": "npx",
      "args": ["minutes-mcp"]
    }
  }
}

Canonical MCP reference now lives at:

The MCP surface currently includes recording control, meeting search/retrieval, relationship memory, structured insights, live transcript reading, dictation, QMD integration, and an interactive dashboard resource. Tool names, resource URIs, and prompt templates are generated from the live product surface instead of hand-maintained in this README.

Interactive dashboard (Claude Desktop): tools render an inline interactive UI via MCP Apps — meeting list with filter/search, detail view with fullscreen + "Send to Claude" context injection, People tab with relationship cards and click-through profiles, and consistency reports. Text-only clients see the same data as plain text.

OpenCode CLI

Minutes now ships a project-local OpenCode integration layer:

  • .opencode/skills/minutes-* for OpenCode's one-level skill discovery
  • .opencode/commands/minutes-*.md so you can run native slash commands like /minutes-brief
  • the same portable runtime helpers used by the Codex/Gemini skill pack

OpenCode also reads this repo's AGENTS.md, so the project rules carry over automatically.

For MCP tools in OpenCode, the official CLI flow is:

opencode mcp add

Choose a local stdio server and point it at:

npx minutes-mcp

If you're wiring OpenCode against this repo before the next npm release is cut, point it at the repo-local entrypoint instead:

npm --prefix /absolute/path/to/minutes/crates/mcp exec tsx src/index.ts

For the native skill/command workflow, just launch OpenCode in this repo:

opencode

Then use commands like:

/minutes-brief
/minutes-prep Alex
/minutes-debrief
/minutes-weekly
/minutes-video-review /absolute/path/to/demo.mp4

Pi coding agent

Minutes works with Mario Zechner's pi coding agent in two places:

  • engine = "agent" can call pi directly for local meeting summarization.
  • The desktop Recall panel can launch Pi when [assistant].agent = "pi".
  • Pi auto-discovers this repo's existing .agents/skills/minutes/ skill pack, so there is no separate .pi/skills tree to keep in sync.

Install Pi, log in or configure a provider, then set:

[summarization]
engine = "agent"
agent_command = "pi"

Minutes invokes Pi in non-interactive, no-tools mode with a private prompt file. Configure provider/model defaults in Pi itself; Minutes does not currently forward extra [summarization] CLI flags. That keeps summarization opt-in and prevents the agent from writing to the repo while it is turning a transcript into notes.

For the interactive Recall panel, Minutes launches Pi directly and passes [assistant].agent_args through. Pi still owns provider auth and model selection: use Pi's /login and /model flows first. If a GitHub Copilot model reports that personal access tokens are unsupported, refresh the Pi Copilot login instead of adding a GitHub PAT to Minutes.

This is separate from Inflection's Pi chatbot/model. Inflection's Pi models are optimized for warmth and emotional intelligence, but the Inflection API terms say not to send regulated personal data. Meeting transcripts often contain personal data, so Minutes does not route transcripts to Inflection by default.

Mistral Vibe

Add Minutes to your ~/.vibe/config.toml:

[[mcp_servers]]
name = "minutes"
transport = "stdio"
command = "npx"
args = ["minutes-mcp"]

All 36 tools are available in Vibe as minutes_* (e.g. minutes_start_recording, minutes_search_meetings).

Claude Code (Plugin)

Install the plugin from the marketplace:

# First-time install
claude plugin marketplace add silverstein/minutes
claude plugin install minutes
# Restart Claude Code to load skills, hooks, and the meeting-analyst agent

Upgrading? claude plugin marketplace add is a no-op when the marketplace is already on disk — it won't fetch new versions. To pick up new skills and hooks after a release, refresh the marketplace mirror first, then update the plugin:

claude plugin marketplace update minutes    # git pulls the local marketplace mirror
claude plugin update minutes@minutes        # installs the new version into the cache
# Restart Claude Code to apply

19 skills, 1 agent, 2 hooks:

├── Capture:      /minutes-record, note, list, recap, cleanup, verify, setup
├── Search:       /minutes-search
├── Lifecycle:    /minutes-brief, prep, debrief, weekly
├── Coaching:     /minutes-tag, mirror
├── Knowledge:    /minutes-ideas, lint, ingest
├── Intelligence: /minutes-graph
├── Artifacts:    /minutes-video-review
├── Agent:        meeting-analyst (cross-meeting intelligence)
└── Hooks:        SessionStart meeting briefings + PostToolUse recording alerts

Meeting lifecycle skills — inspired by gstack's interactive skill pattern:

/minutes-brief                      → fast one-pager (or fired automatically by hook 15 min before calls)
  ↓
/minutes-prep "call with Alex"      → deeper relationship brief + talking points + goal-setting
  ↓
minutes record → minutes stop       → hook alerts if decisions conflict with prior meetings
  ↓
/minutes-tag won|lost|stalled       → 5-second outcome label (unlocks mirror correlation)
  ↓
/minutes-debrief                    → "You wanted to resolve pricing. Did you?"
  ↓
/minutes-mirror                     → talk-time, hedging, what your winning meetings have in common
  ↓
/minutes-weekly                     → themes, decision arcs, stale items, Monday brief
  ↓
/minutes-video-review <video-or-url> → durable artifact bundle from a Loom, ScreenPal, or local walkthrough
  ↓
/minutes-graph "everyone who mentioned Stripe"  → cross-meeting entity queries

For the stable public agent-facing docs surface, use:

Minutes Desktop Assistant

The Tauri menu bar app includes a built-in AI Assistant window backed by the same local meeting artifacts. It runs as a singleton assistant session:

  • AI Assistant opens or focuses the persistent assistant window
  • Discuss with AI reuses that same assistant and switches its active meeting focus
  • Recall writes matching CLAUDE.md and AGENTS.md instructions into its assistant workspace so Claude-style and AGENTS.md-aware terminal agents get the same meeting context
  • Auto-updates from GitHub Releases with signed artifacts, never interrupting a recording

Cowork / Dispatch

The currently verified path for Cowork is plugin-oriented, not “raw MCP automatically appears everywhere.” Minutes ships a Cowork extension scaffold under integrations/claude-cowork-extension/ and a local bundle build script at scripts/build_cowork_extension.sh. On this machine, the bundle build is verified; actual in-Cowork install/use remains a proof-of-life workflow, not a guaranteed default path. Treat Dispatch-triggered recording and other mobile workflows as experimental until the plugin-native path is installed and checked end to end.

Optional: automated summarization

# Use your existing Claude Code, Codex, OpenCode, or Pi subscription (recommended)
[summarization]
engine = "agent"
agent_command = "claude"  # or "codex" / "opencode" / "pi"

# Or use Mistral API (requires MISTRAL_API_KEY)
[summarization]
engine = "mistral"
mistral_model = "mistral-large-latest"

# Or use a free local LLM
[summarization]
engine = "ollama"
ollama_model = "llama3.2"

# Or use any OpenAI-compatible gateway/local server.
# Desktop users can paste cloud gateway keys in Settings; Minutes stores them
# in macOS Keychain and hydrates its own runtime secret without rewriting this
# shared config. CLI users can set any env var and name it below. Local servers
# can leave it blank.
[summarization]
engine = "openai-compatible"
openai_compatible_base_url = "https://openrouter.ai/api/v1"
openai_compatible_model = "openai/gpt-4o-mini"
openai_compatible_api_key_env = "OPENROUTER_API_KEY" # leave blank for local servers

File-backed automation primitives

Minutes can emit small automation artifacts that are easy to schedule with launchd, cron, or any external runner.

minutes automate weekly-summary --json
minutes automate proactive-context --json

Each run writes:

  • a markdown artifact under ~/.minutes/automation-runs/
  • a matching JSON run record beside it

This is intentionally simple: explicit files, explicit output paths, and no hidden scheduler subsystem.

Codex epic runner

When you want Codex to keep draining a bd epic instead of stopping after one child bead, use the repo-local epic runner:

node scripts/codex_epic_runner.mjs <epic-id> -- --full-auto

What it does:

  • uses bd as the source of truth for epic ancestry and ready work
  • picks the next ready non-epic descendant bead under the target epic
  • claims that bead, runs codex exec against it, then checks whether the bead was actually closed
  • continues only after a real close; pauses on blocked/needs-human outcomes instead of guessing

Dry-run the order first:

node scripts/codex_epic_runner.mjs <epic-id> --dry-run

If you install a Taskmaster-style Codex wrapper later, use it as the per-bead engine without changing the epic logic:

node scripts/codex_epic_runner.mjs <epic-id> --taskmaster -- --sandbox danger-full-access -a never

This is intentionally separate from the Claude plugin hooks. The Minutes plugin hooks are Claude-specific today; the Codex epic runner is a repo-local workflow layer on top of bd and codex exec.

Optional: knowledge base integration

Maintain a living knowledge base from your conversations — person profiles, decision history, and a chronological log that compounds over time. Inspired by Karpathy's LLM Wiki pattern.

[knowledge]
enabled = true
path = "~/wiki"        # or your Obsidian vault, PARA system, etc.
adapter = "wiki"       # "wiki" (flat markdown), "para" (atomic facts), "obsidian" (wiki + [[links]])
engine = "none"        # "none" = structured YAML only (safest), "agent" = LLM extraction
min_confidence = "strong"

After each meeting, structured facts (decisions, action items, commitments) flow into person profiles automatically. Every fact carries provenance back to its source meeting.

minutes ingest --dry-run --all   # Preview what would be extracted
minutes ingest --all              # Backfill existing meetings
minutes ingest ~/meetings/call.md # Process a single meeting

Three output formats:

  • Wikipeople/{slug}.md with facts grouped by category
  • PARAareas/people/{slug}/items.json with atomic facts (id, status, supersededBy)
  • Obsidian — Wiki format with [[wikilinks]] for cross-references

Safety: default engine = "none" extracts only from parsed YAML frontmatter. No LLM call, zero hallucination risk. Confidence thresholds filter speculative facts. Corrupt data is backed up, never silently destroyed.

Install

macOS

# Desktop app (menu bar, recording UI, AI assistant)
brew install --cask silverstein/tap/minutes

# CLI only (terminal recording, search, vault sync)
brew tap silverstein/tap
brew install minutes

# Or from source (requires Rust + cmake)
export CXXFLAGS="-I$(xcrun --show-sdk-path)/usr/include/c++/v1"
cargo install --path crates/cli

Windows

# Download pre-built binary from GitHub releases, or build from source:
# Requires: Rust, cmake, MSVC build tools, LLVM (for libclang)

# Install LLVM (needed by whisper-rs bindgen):
winget install LLVM.LLVM
[Environment]::SetEnvironmentVariable("LIBCLANG_PATH", "C:\Program Files\LLVM\bin", "User")
# Restart your terminal after setting LIBCLANG_PATH

# Full build (includes speaker diarization):
cargo install --path crates/cli

# Without speaker diarization:
cargo install --path crates/cli --no-default-features

Note: If diarization fails to compile on Windows, use --no-default-features. This is a known upstream issue with pyannote-rs's ONNX Runtime dependency. Everything except speaker labels works without it.

Linux

# Debian/Ubuntu — full dep list:
sudo apt-get install -y \
  build-essential cmake pkg-config \
  clang libclang-dev \
  libasound2-dev libpipewire-0.3-dev libspa-0.2-dev \
  ffmpeg

cargo install minutes-cli
# or, from a checkout:
cargo install --path crates/cli

Why each dep is needed:

  • build-essential, cmake — whisper.cpp build
  • clang, libclang-dev — bindgen (used by whisper-rs and pipewire-sys)
  • libasound2-dev — cpal's ALSA backend
  • libpipewire-0.3-dev, libspa-0.2-dev — cpal's PipeWire backend (compiled unconditionally on Linux)
  • ffmpeg — preferred audio decoder for .m4a/.mp3/.ogg (falls back to pure-Rust symphonia if absent)

Other distros (best-effort — Debian/Ubuntu is the validated path; please open an issue if any package name is wrong on your distro):

  • Fedora/RHEL: sudo dnf install -y gcc-c++ cmake pkgconf-pkg-config clang clang-devel alsa-lib-devel pipewire-devel ffmpeg-free
  • Arch: sudo pacman -S --needed base-devel cmake clang alsa-lib pipewire ffmpeg

Chromebook (Crostini)

Yes, Minutes runs on a Chromebook via the Linux development environment (Crostini). The CLI is the supported path — there's no native ChromeOS build and the Tauri desktop app