Documentation
Granola CLI
granola-pp-cli
Install
npx -y @mvanhorn/printing-press-library install granolaInstalls the CLI binary and the agent skill for Claude Code, Codex, Cursor, Gemini CLI, Copilot, and more. Add --cli-only or --skill-only for one half. Requires Node.
Documentation
Every Granola feature — plus offline SQLite cross-meeting search, attendee timelines, and a MEMO pipeline runner no other Granola tool has.
granola-pp-cli reads Granola’s local cache directly and adds the queries Granola.ai’s web app and existing community CLIs cannot answer. Cache-first, then internal API, then public API — transparent fallthrough. memo run, memo queue, attendee timeline, recipes coverage, calendar overlay, and talktime are local-data joins no per-meeting tool produces. Works offline; agent-native JSON by default.
Created by @dstevens (Damien Stevens).
Authentication
Three auth surfaces, ordered fastest to most permissioned. The local cache at ~/Library/Application Support/Granola/cache-v6.json needs no credentials. The internal API at api.granola.ai auto-discovers your WorkOS access_token from supabase.json / stored-accounts.json and rotates the refresh token through WorkOS on every call. The public API at public-api.granola.ai accepts a Bearer key in GRANOLA_API_KEY for workspace-scoped queries; it backs the typed notes and folders top-level commands and is the source when you pass --data-source live.
Quick Start
# Confirm cache + WorkOS token + (optional) public API key all resolve.
granola-pp-cli doctor --json
# Hydrate the local SQLite store from cache + any deltas via internal API.
granola-pp-cli sync
# What’s in cache but not yet MEMO’d this week.
granola-pp-cli memo queue --since 7d --json
# Run the full MEMO pipeline on every meeting since yesterday.
granola-pp-cli memo run --since 24h --to ~/Documents/Dev/meeting-transcripts --json
# Every meeting with Trevin in the last 60 days, oldest first, with the recipes applied per row.
granola-pp-cli attendee timeline alice@example.com --since 60d --json --select id,title,started_at,recipes
# Meetings missing the Discovery panel — the Friday retro gap.
granola-pp-cli recipes coverage --since 14d --json
Unique Features
These capabilities aren't available in any other tool for this API.
MEMO pipeline
-
memo run— Run the preflight → extract pipeline on one meeting or every new meeting since a timestamp, emitting the MEMO three-file artifact and an ndjson run-state ledger.Replaces the per-meeting shell loop that drives the MEMO pipeline — one call, one ndjson stream, agent-readable.
granola-pp-cli memo run --since 24h --to ~/Documents/Dev/meeting-transcripts --json -
memo queue— List every meeting whose transcript is in the cache but whose MEMO triple is not yet on disk.Answers the daily question “what’s still un-MEMO’d?” without the user opening Granola at all.
granola-pp-cli memo queue --since 7d --json
Attendee intelligence
-
attendee timeline— Every meeting with a given attendee, ordered oldest→newest, with title, date, folder, and recipe-applied flag per row.Pre-call prep in one command; surfaces the conversation arc with a single person across months of meetings.
granola-pp-cli attendee timeline alice@example.com --since 60d --json --select id,title,started_at,folder,recipes -
attendee brief— Pulls the last N meetings with an attendee and stitches together their real cached notes plus real AI panel summaries — no synthesis.Eliminates the click-each-meeting copy-paste that account leads do before every external call.
granola-pp-cli attendee brief alice@example.com --last 3 --panel action-items --json
Folders + recipes
-
folder stream— ndjson stream of every meeting in a Granola folder (resolved via documentLists + listRules) with notes and a named panel inlined.Replaces the weekly retro workflow of opening a folder and copy-pasting each meeting’s summary into a spreadsheet.
granola-pp-cli folder stream client-foo --panel summary --json -
recipes coverage— Surface meetings that did NOT have a named panel template/recipe applied within a date range.Friday retro question “did I run the Discovery recipe on every new-prospect call?” answered in one row per gap.
granola-pp-cli recipes coverage discovery --since 14d --json
Transcript analytics
-
talktime— Per-segment-source talk-time for one meeting — microphone (you) vs system (everyone else) in minutes.Confidence column lets you grade transcript accuracy; mic vs system split is the input to “am I talking too much” retros.
granola-pp-cli talktime 196037d9 --json -
talktime— Lifts the per-source talk-time aggregation across N meetings since a date — who-talked-most over time.Time-defrag retro input that no per-meeting tool can produce.
granola-pp-cli talktime --by participant --since 7d --json
Cache-native data
-
chat list— List and dump Granola’s AI chat threads anchored to a meeting (entities.chat_thread + entities.chat_message in the cache).Recovers the AI Q&A history a user has accumulated against a meeting — useful when chasing what you asked about an account weeks ago.
granola-pp-cli chat list 196037d9 --json -
calendar overlay— Left-anti-join meetingsMetadata calendar events with documents.google_calendar_event to find calendared-but-not-recorded meetings.Sarah’s Friday retro and Damien’s “what did I miss” sweep both reduce to this row-level diff.
granola-pp-cli calendar overlay --week 2026-05-11 --missed-only --json
Pipeline hygiene
-
duplicates scan— Hash (title, date-bucket, attendee-email-set) across the cache and a meeting-transcripts repo to surface duplicates at scale.Repos accumulate near-duplicate files when meetings are re-extracted; this returns the dupe groups for cleanup.
granola-pp-cli duplicates scan --root ~/Documents/Dev/meeting-transcripts --json -
tiptap extract— Render documents[id].notes (TipTap JSON: headings, bullet_list, list_item, bold marks, paragraph_break) to canonical markdown instead of falling back to notes_plain.The MEMO summary file’s quality is bounded by extractor fidelity; granola.py loses sub-list hierarchy and bold runs.
granola-pp-cli tiptap extract 196037d9 --as markdown
Usage
Run granola-pp-cli --help for the full command reference and flag list.
Commands
This CLI exposes 35+ commands. Use granola-pp-cli --help for the canonical tree and granola-pp-cli which "<capability>" to find the right command from natural language. Grouped overview:
| Group | Commands |
|---|---|
| MEMO pipeline | memo run, memo queue, preflight, extract |
| Meetings | meetings list / get / fetch-batch / delete / restore, show |
| Three streams | notes-show, panel get, transcript get, tiptap extract |
| Export | export <id> -o FILE, export-all --since DATE -o DIR |
| Cross-meeting analytics | attendee timeline / brief, folder stream, recipes coverage, talktime, calendar overlay, stats frequency / duration / attendees / calendar, collect, duplicates scan, chat list / get |
| Granola entities | folders, folder list / stream, recipes list / describe / coverage, workspaces list |
| Public API mirrors | notes list / get, folders (require GRANOLA_API_KEY) |
| Sync / system | sync, sync-api, doctor, auth login / status / set-token / logout, which, agent-context, version, import |
| GUI bridge (macOS only) | warm <id> <query> — prints by default; --launch activates the Granola desktop app |
Output Formats
# Human-readable table (default in terminal, JSON when piped)
granola-pp-cli folders
# JSON for scripting and agents
granola-pp-cli folders --json
# Filter to specific fields
granola-pp-cli folders --json --select id,name,status
# Dry run — show the request without sending
granola-pp-cli folders --dry-run
# Agent mode — JSON + compact + no prompts in one flag
granola-pp-cli folders --agent
Agent Usage
This CLI is designed for AI agent consumption:
- Non-interactive - never prompts, every input is a flag
- Pipeable -
--jsonoutput to stdout, errors to stderr - Filterable -
--select id,namereturns only fields you need - Previewable -
--dry-runshows the request without sending - Read-only by default with a narrow opt-in write surface —
meetings delete,meetings restore,import, andwarm --launchmutate state; everything else inspects, exports, syncs, or analyzes - Offline-friendly -
syncand themeetings list --query <text>FTS path use the local SQLite store - Agent-safe by default - no colors or formatting unless
--human-friendlyis set
Exit codes: 0 success, 2 usage error, 3 not found, 4 auth error, 5 API error, 7 rate limited, 10 config error.
Auto-Refresh
Every command auto-refreshes the local store as its first action. You do not need to run granola-pp-cli sync before meetings list, panel get, or any other read.
Both auth surfaces refresh independently: the desktop encrypted cache (~/Library/Application Support/Granola/cache-v6.json.enc) via the embedded sync path, and the public REST API (when GRANOLA_API_KEY is set or an access token is saved) via the embedded sync-api path. When both are available, both refresh routines fire. When neither is configured, auto-refresh is a silent no-op.
A one-line provenance summary lands on stderr in interactive mode: auto-refresh: cache=ok (1.2s, 47 rows). It is suppressed under --agent, --json, --compact, --quiet, and when stderr is piped — so agent and CI consumers see no chatter on stdout or stderr.
Opt out with --no-refresh for a single command, GRANOLA_NO_AUTO_REFRESH=1 for a shell session or CI job, or by saving a profile with --no-refresh (granola-pp-cli profile save fast --no-refresh). The skip list (commands that never auto-refresh) is sync, sync-api, auth, doctor, help, version, completion, agent-context, profile, feedback, which. Run granola-pp-cli agent-context --json to see the full contract as structured JSON.
Auto-refresh reads from Granola desktop's encrypted cache file; it does not poke the desktop app to refresh from Granola servers. The freshness ceiling is whatever Granola desktop has already pulled.
Health Check
granola-pp-cli doctor
Verifies configuration, credentials, and connectivity to the API.
Configuration
Config file: ~/.config/granola-pp-cli/config.toml
Static request headers can be configured under headers; per-command header overrides take precedence.
Environment variables:
| Name | Kind | Required | Description |
|---|---|---|---|
GRANOLA_API_KEY | per_call | No | Set to your API credential. |
Troubleshooting
Authentication errors (exit code 4)
- Run
granola-pp-cli doctorto check credentials - Verify the environment variable is set:
echo $GRANOLA_API_KEYNot found errors (exit code 3) - Check the resource ID is correct
- Run the
listcommand to see available items
API-specific
- doctor reports cache file not found — Make sure Granola is installed and you’ve opened it at least once. Override the path with GRANOLA_CACHE_PATH=/custom/path/cache-v6.json.
- WorkOS token expired warning — Open the Granola desktop app once — it refreshes the token. Or pass a personal API key via GRANOLA_API_KEY to route through the public API instead.
- memo run --since reports duplicate_of — A file with the same title-date-attendees fingerprint already exists in --to. Pick a different
--todirectory, remove the existing file, ormvit out of the way. - Transcript missing for a recent meeting — Granola hasn’t flushed it yet. Run warm --launch to bring it forward in the GUI, wait 30 s, then re-run preflight.
- stats / talktime returns empty rows — Auto-refresh runs
syncon every command, so this usually means there is nothing to sync. Confirm Granola desktop is signed in and has captured at least one meeting; rungranola-pp-cli doctorto verify the cache is decryptable. If you bypassed auto-refresh with--no-refreshorGRANOLA_NO_AUTO_REFRESH=1, rungranola-pp-cli syncmanually.
Sources & Inspiration
This CLI was built by studying these projects and resources:
- granola.py — Python
- GranolaMCP (pedramamini) — Python
- granola-mcp (chrisguillory) — Python
- reverse-engineering-granola-api (getprobo) — Python
- granola-claude-mcp (cobblehillmachine) — Python
- granola-mcp (btn0s) — TypeScript
- granola-mcp-server (EoinFalconer) — TypeScript
- granola-ai-mcp-server (maxgerlach1) — TypeScript
Generated by CLI Printing Press
For agents: pass /documentation/granola/agents.md to install this CLI from a prompt.