Open-source conversation memory. Ā useminutes.app
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. Ask Claude "what did I promise Sarah?" ā and get an answer. Your AI remembers every conversation you've had.
Claude Code ⢠Codex ⢠Gemini CLI ⢠Claude Desktop ⢠Mistral Vibe ⢠Obsidian ⢠Logseq ⢠Phone Voice Memos ⢠Any MCP client
# 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
# 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, Gemini CLI, Claude Desktop, etc.)
npx minutes-mcpminutes setup --model small # Download whisper model (466MB, recommended)
minutes record # Start recording
minutes stop # Stop and transcribeAudio ā 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.
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 stop # Stop from another terminalminutes note "Alex wants monthly billing not annual billing" # Timestamped, feeds into summary
minutes note "Logan agreed" # LLM weights your notes heavilyminutes process ~/Downloads/voice-memo.m4a # Any audio format
minutes watch # Auto-process new files in inboxminutes 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"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 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"). Powered by a SQLite index rebuilt from your markdown in <50ms.
minutes research "pricing strategy" # Search across all meetings
minutes person "Alex" # Build a profile from meeting history
minutes consistency # Flag contradicting decisions + stale commitmentsminutes live # Start real-time transcription
minutes stop # Stop live sessionStreams whisper transcription to a JSONL file in real time ā any AI agent can read it mid-meeting for live coaching. The MCP read_live_transcript tool provides delta reads (by line cursor or wall-clock duration). Works with Claude Code, Codex, Gemini CLI, or any agent that reads files. The Tauri desktop app has a Live Mode toggle that starts this with one click.
minutes dictate # Speak ā text appears as you talk
minutes dictate --stdout # Output to stdout instead of clipboardText 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. Local whisper, no cloud.
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 ~/.config/minutes/config.toml. The Settings dropdown also offers āā§O and āā§U if āā§K collides with your IDE.
minutes demo --full # Seed 5 sample meetings (Snow Crash theme)
minutes demo --query # Cross-meeting intelligence demo
minutes demo --clean # Remove sample meetingsThe interactive demo seeds interconnected meetings, then lets you pick a thread to explore. Two storylines, five meetings, zero setup.
minutes health # Check model, mic, calendar, disk
minutes demo # Run a pipeline test (bundled audio, no mic)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.
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/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.
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 |
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 existsStep 2: Add the sync folder to your watch config in ~/.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
iPhone (Apple Shortcuts)
- Open the Shortcuts app on your iPhone
- Tap + ā Add Action ā search "Save File"
- Set destination to
iCloud Drive/minutes-inbox/(or your Dropbox/Google Drive folder) - Turn OFF "Ask Where to Save"
- Tap the (i) info button ā enable Share Sheet ā set to accept Audio
- Name it "Save to Minutes"
Now: Voice Memos ā Share ā Save to Minutes ā done.
Android
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.
Manual (any phone)
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 # Or install as background service (auto-starts on login, macOS)
minutes service restart # Restart in place (e.g. after upgrading the binary)
minutes service status # Check if it's running and which PIDUpgrading? macOS launchd holds the running watcher's binary in memory, so a fresh
brew upgrade(or any other binary swap) leaves the old version running until you restart it. Runminutes service installagain ā it's idempotent and will reload launchd with the new binary path. Or useminutes service restartif the plist hasn't changed.
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].
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.
minutes vault setup # Auto-detect vaults, configure sync
minutes vault status # Check health
minutes vault sync # Copy existing meetings to vaultThree 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.
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
Minutes exposes a standard MCP server. Point any MCP-compatible client at it:
{
"mcpServers": {
"minutes": {
"command": "npx",
"args": ["minutes-mcp"]
}
}
}26 tools: start_recording, stop_recording, get_status, list_processing_jobs, list_meetings, search_meetings, get_meeting, process_audio, add_note, consistency_report, get_person_profile, research_topic, qmd_collection_status, register_qmd_collection, start_dictation, stop_dictation, track_commitments, relationship_map, list_voices, confirm_speaker, get_meeting_insights, start_live_transcript, read_live_transcript, open_dashboard, ingest_meeting, knowledge_status
7 resources: minutes://meetings/recent, minutes://status, minutes://actions/open, minutes://events/recent, minutes://meetings/{slug}, minutes://ideas/recent, ui://minutes/dashboard
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, consistency reports. Text-only clients see the same data as plain text.
Add Minutes to your ~/.vibe/config.toml:
[[mcp_servers]]
name = "minutes"
transport = "stdio"
command = "npx"
args = ["minutes-mcp"]All 26 tools are available in Vibe as minutes_* (e.g. minutes_start_recording, minutes_search_meetings).
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 agentUpgrading? 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 apply18 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
āāā 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-graph "everyone who mentioned Stripe" ā cross-meeting entity queries
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 Assistantopens or focuses the persistent assistant windowDiscuss with AIreuses that same assistant and switches its active meeting focus- Auto-updates from GitHub Releases with signed artifacts, never interrupting a recording
MCP tools are automatically available in Cowork. From your phone via Dispatch: "Start recording" ā Mac captures ā Claude processes ā summary on your phone.
# Use your existing Claude Code or Codex subscription (recommended)
[summarization]
engine = "agent"
agent_command = "claude" # or "codex" for OpenAI Codex users
# 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"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 meetingThree output formats:
- Wiki ā
people/{slug}.mdwith facts grouped by category - PARA ā
areas/people/{slug}/items.jsonwith 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.
# 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# 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-featuresNote: If diarization fails to compile on Windows, use
--no-default-features. This is a known upstream issue withpyannote-rs's ONNX Runtime dependency. Everything except speaker labels works without it.
# 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/cliWhy each dep is needed:
build-essential,cmakeā whisper.cpp buildclang,libclang-devā bindgen (used bywhisper-rsandpipewire-sys)libasound2-devā cpal's ALSA backendlibpipewire-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
Build with GPU support for significantly faster transcription:
| Backend | Platform | Feature flag | Prerequisites |
|---|---|---|---|
| Metal | macOS | metal |
Xcode Command Line Tools |
| CoreML | macOS | coreml |
Xcode Command Line Tools |
| CUDA | Windows/Linux | cuda |
CUDA Toolkit |
| ROCm/HIP | Linux | hipblas |
ROCm 6.1+ (hipcc, hipblas, rocblas) |
| Vulkan | Windows/Linux | vulkan |
Vulkan SDK (+ vulkan-headers on Arch) |
Metal is the only backend that is exercised daily by the maintainer. CUDA, ROCm/HIP, and Vulkan should be considered experimental: they wire through to whisper.cpp via whisper-rs and are expected to work, but have not been validated in CI.
# Apple Metal (macOS)
cargo install --path crates/cli --features metal
# Apple CoreML (macOS Neural Engine)
cargo install --path crates/cli --features coreml
# NVIDIA GPU (Windows/Linux)
cargo install --path crates/cli --features cuda
# AMD GPU via ROCm (Linux ā experimental)
cargo install --path crates/cli --features hipblas
# Vulkan (Windows/Linux ā experimental)
cargo install --path crates/cli --features vulkanWindows CUDA users: You may need to set environment variables before building:
$env:CUDA_PATH = "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.4" $env:CMAKE_CUDA_COMPILER = "$env:CUDA_PATH\bin\nvcc.exe" $env:LIBCLANG_PATH = "C:\Program Files\LLVM\bin" $env:CMAKE_GENERATOR = "NMake Makefiles"The first CUDA build takes longer than usual (compiling GPU kernels) ā this is a one-time cost.
ROCm/HIP users: The build expects ROCm installed at
/opt/rocm. If your installation is elsewhere, setHIP_PATHbefore building:export HIP_PATH=/path/to/rocmVulkan users: On Windows and macOS, set
VULKAN_SDKto your SDK install root before building. On Linux,whisper-rs-syslinks against the systemlibvulkan.
# Download whisper model (also downloads Silero VAD model for non-English audio)
minutes setup --model small # Recommended (466MB, good accuracy)
minutes setup --model tiny # Fastest (75MB, but misses quiet audio)
minutes setup --model base # Middle ground (141MB)
# Install ffmpeg for best transcription quality (strongly recommended for non-English audio)
brew install ffmpeg # macOS
# apt install ffmpeg # Linux
# Without ffmpeg, symphonia handles m4a/mp3 decoding ā works for English but may
# produce loops on non-English audio. ffmpeg is optional but recommended.
# Enable speaker diarization (optional, ~34MB ONNX models)
minutes setup --diarization
# Alternative: use Parakeet engine (opt-in, lower WER than Whisper)
# Requires parakeet.cpp installed: https://github.com/Frikallo/parakeet.cpp
minutes setup --parakeet # English model (tdt-ctc-110m, ~220MB)
minutes setup --parakeet --parakeet-model tdt-600m # Multilingual (25 EU languages, ~1.2GB)
# Enroll your voice for automatic speaker identification
minutes enroll # Records 10s of your voice
minutes voices # View enrolled profilesMinutes maps anonymous speaker labels (SPEAKER_1, SPEAKER_2) to real names using four levels of confidence-aware attribution:
| Level | How | Confidence | Requires | ||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Calendar attendees + identity.name ā deterministic mapping for 1-on-1 meetings |
Medium | Calendar access, [identity] name in config |
||||||||||||||||||||||||||||
| 1 | LLM analyzes transcript context clues and maps speakers to attendees | Medium (capped) | Attendees known + summarization engine or agent CLI | ||||||||||||||||||||||||||||
| 2 | Your enrolled voice is matched against speaker segments | High | minutes enroll (one-time 10s recording) |
||||||||||||||||||||||||||||
| 3 | You confirm "SPEAKER_1 is Sarah" after a meeting | High | minutes confirm --meeting <path> |

