_
_ | |
__ _ _ __ __ _ _ __ ___ | | __ _ | |
/ _` | '__/ _` | '_ \ / _ \| |/ _` | | |
| (_| | | | (_| | | | | (_) | | (_| | | |
\__, |_| \__,_|_| |_|\___/|_|\__,_| | |
|___/ |_|
Export your Granola notes and transcripts to local files for backup, migration, or offline access.
- π Own Your Data - Keep local copies of all your meeting notes
- ποΈ Full Transcripts - Export complete, timestamped transcripts of your meetings
- πΎ Backup & Migration - Safeguard your notes or move them to other tools
- π Smart Updates - Only exports new or changed content
- β‘ Fast & Simple - One command to export everything
- Go to the releases page
- Download the appropriate file for your operating system:
- macOS:
granola_Darwin_x86_64.tar.gz(Intel) orgranola_Darwin_arm64.tar.gz(Apple Silicon) - Linux:
granola_Linux_x86_64.tar.gz - Windows:
granola_Windows_x86_64.zip
- macOS:
- Extract the archive and move
granolato a location in your PATH
If you have Go installed:
go install github.com/theantichris/granola@latestYour notes are the AI-generated summaries and formatted content from Granola.
macOS/Linux:
granola notes --supabase "$HOME/Library/Application Support/Granola/supabase.json"Windows (PowerShell):
granola notes --supabase "$env:APPDATA\Granola\supabase.json"Notes will be exported to a notes/ directory as Markdown files.
Transcripts are the raw, timestamped recordings of everything said in your meetings.
Note: Transcripts are only available for meetings where you enabled audio recording.
macOS:
granola transcriptsLinux:
granola transcripts --cache "$HOME/.config/Granola/cache-v3.json"Windows (PowerShell):
granola transcripts --cache "$env:APPDATA\Granola\cache-v3.json"Transcripts will be exported to a transcripts/ directory as text files.
Granola uses a supabase.json file for API authentication:
- macOS:
~/Library/Application Support/Granola/supabase.json - Linux:
~/.config/Granola/supabase.jsonor~/.local/share/Granola/supabase.json - Windows:
%APPDATA%\Granola\supabase.json
Granola stores raw transcripts in a local cache file:
- macOS:
~/Library/Application Support/Granola/cache-v3.json - Linux:
~/.config/Granola/cache-v3.jsonor~/.local/share/Granola/cache-v3.json - Windows:
%APPDATA%\Granola\cache-v3.json
# Export notes to a specific location
granola notes --output ~/Documents/MyNotes
# Export transcripts to a specific location
granola transcripts --output ~/Documents/MyTranscriptsCreate a .granola.toml file in your home directory to avoid specifying paths every time:
# Notes configuration
supabase = "/Users/yourname/Library/Application Support/Granola/supabase.json"
output = "/Users/yourname/Documents/Notes"
# Transcripts configuration
cache-file = "/Users/yourname/Library/Application Support/Granola/cache-v3.json"
transcript-output = "/Users/yourname/Documents/Transcripts"Then simply run:
granola notes
granola transcriptsgranola notes --debug
granola transcripts --debugEach note becomes a separate .md file with:
- YAML frontmatter - ID, timestamps, tags
- Title - As a top-level heading
- Content - Formatted as Markdown with headings, lists, etc.
Example:
---
id: abc-123
created: "2024-01-01T00:00:00Z"
updated: "2024-01-02T00:00:00Z"
tags:
- work
- planning
---
# Meeting Notes
## Key Points
- First important point
- Second important pointEach transcript becomes a .txt file with:
- Header - Title, ID, timestamps, segment count
- Timestamped dialogue -
[HH:MM:SS] Speaker: Text - Speaker labels - "System" (others) or "You" (your microphone)
Example:
================================================================================
π€ Team Sync Meeting
ID: abc-123
Created: 2024-01-01T14:00:00.000Z
Segments: 142
================================================================================
[14:00:04] System: Good morning everyone, how's it going?
[14:00:06] You: Good morning! Ready to start.
- Make sure Granola is installed and you've logged in at least once
- Check that the path to
supabase.jsonis correct for your OS - Try running Granola app first, then export
- Transcripts are only available for meetings where audio recording was enabled
- Check that the cache file path is correct
- Make sure you've had at least one meeting with recording enabled
- Make sure you have read access to the Granola files
- Try running without
sudo- it's not needed
- Check the
--helpoutput:granola notes --help - Open an issue on GitHub
The sections below are for those who want to contribute to the project or build from source.
Requirements:
- Go 1.23.1 or higher
- Git
Clone and build:
git clone https://github.com/theantichris/granola.git
cd granola
go build -o granolaCross-platform builds:
# Linux
GOOS=linux GOARCH=amd64 go build -o granola-linux
# macOS Intel
GOOS=darwin GOARCH=amd64 go build -o granola-darwin
# macOS Apple Silicon
GOOS=darwin GOARCH=arm64 go build -o granola-darwin-arm64
# Windows
GOOS=windows GOARCH=amd64 go build -o granola.exegranola/
βββ cmd/ # Command implementations
β βββ root.go # Root command and configuration
β βββ notes.go # Notes export (API-based)
β βββ transcripts.go # Transcripts export (cache-based)
βββ internal/ # Internal packages
β βββ api/ # Granola API client
β βββ cache/ # Cache file reader
β βββ converter/ # Document to Markdown converter
β βββ prosemirror/ # ProseMirror JSON parser
β βββ transcript/ # Transcript formatter
β βββ writer/ # File system operations
βββ main.go # Entry point
βββ README.md # This file
βββ CLAUDE.md # AI assistant guidelines
βββ SPEC.md # Technical specification
βββ LICENSE # MIT License
# Run tests
go test ./...
# Run tests with coverage
go test -cover ./...
# Run linter (requires golangci-lint)
golangci-lint run
# Run markdown linter (requires markdownlint-cli2)
markdownlint-cli2 "**/*.md" "#notes" "#transcripts"
# Run the CLI without building
go run main.go notes --helpThe project uses Go's standard testing framework with:
- Unit tests for individual components
- Table-driven tests for comprehensive coverage
- Afero for filesystem abstraction in tests
- Parallel test execution where possible
Run tests:
go test ./... # All tests
go test -v ./... # Verbose output
go test -cover ./... # With coverageReleases are automated using GoReleaser:
# Create and push a new tag
git tag v1.0.0
git push origin v1.0.0
# GitHub Actions will automatically build and publish the releaseFor local testing:
goreleaser release --snapshot --cleanContributions are welcome! Here's how to help:
- Fork the repository
- Create a branch for your feature (
git checkout -b feature/amazing-feature) - Write tests for your changes
- Ensure tests pass (
go test ./...) - Commit your changes (
git commit -m 'Add amazing feature') - Push to your branch (
git push origin feature/amazing-feature) - Open a Pull Request
Guidelines:
- Follow existing code style
- Add tests for new functionality
- Update documentation as needed
- Keep PRs focused on a single change
For more details, see CLAUDE.md (AI development guidelines) and SPEC.md (technical specification).
- Cobra - CLI framework
- Viper - Configuration management
- Charmbracelet Log - Structured logging
- Afero - Filesystem abstraction
Notes Export (API-based):
- Read Supabase credentials from local file
- Authenticate with Granola API
- Fetch all documents as JSON
- Convert ProseMirror JSON to Markdown
- Write files with YAML frontmatter
Transcripts Export (Cache-based):
- Read local cache file (double-JSON encoded)
- Extract transcript segments by document ID
- Format segments with timestamps and speakers
- Write text files with metadata headers
For detailed technical documentation, see SPEC.md.
This project is licensed under the MIT License - see the LICENSE file for details.
- Granola - The amazing note-taking app this tool exports from
- The Go team for the excellent language and tooling
- Cobra and Viper for the CLI framework
- Charmbracelet for beautiful terminal tools
For issues, questions, or feature requests:
- Open an issue on GitHub
- Check existing issues for solutions
- Include debug output (
--debug) when reporting problems
Built with β€οΈ by the community