grans
A fast CLI tool for searching, filtering, and querying your Granola meeting notes. Data is synced from the Granola API and stored in a local SQLite database.
Installation
cargo install --path .Or build from source:
cargo build --release
# Binary at target/release/grans
# With GPU acceleration for semantic search (Windows and Linux):
cargo build --release --features directml # Windows (any GPU, recommended)
cargo build --release --features cuda # NVIDIA (requires CUDA toolkit + cuDNN)On macOS, build plain. Embedding there goes through llama.cpp on Metal, which is selected by platform rather than by a cargo feature, so there is nothing to enable. Building from source needs the Xcode Command Line Tools and cmake (brew install cmake), since llama.cpp is compiled into the binary. The reranker still runs through ONNX Runtime on the CPU on every platform.
Quick Start
# Sync everything from Granola (requires being logged into Granola app)
grans sync --all
# Now you can query your meetings
grans list
grans search "project kickoff"Usage
grans [OPTIONS] <COMMAND>Global Options
| Flag | Description | |------|-------------| | --db <path | Use a specific database file instead of the default | | --token <token | Use a specific API token (also read from GRANSTOKEN) | | --json | Output as JSON | | --no-color | Disable colored output (human-readable format without ANSI codes) | | --utc | Display timestamps in UTC instead of local time | | --verbose / -v | Enable verbose debug output (written to stderr) |
Data Storage
grans stores your meeting data in a local SQLite database at:
- macOS: ~/Library/Application Support/grans/grans.db
- Linux: ~/.local/share/grans/grans.db
- Windows: %APPDATA%/grans/grans.db
The database runs in SQLite's write-ahead logging mode, so you will see grans.db-wal and grans.db-shm beside it. They are part of the database: copy or move all three together, or run grans dropbox push (which folds the log into the database file first). Deleting them by hand while grans is running loses recent writes.
Data is fetched from the Granola API using grans sync and accumulates over time. Unlike Granola's local cache (which only holds recent meetings), grans preserves all your synced data indefinitely.