Integrations
Treat Gran as a local-first source app for scripts, webhooks, SDK code, or another local tool.
Gran works best as the local source of truth for your Granola archive.
This is the preferred advanced extension path when another tool should build on top of Gran instead of Gran doing everything itself.
That means the cleanest integration model is:
- Gran syncs and indexes your meetings locally
- Gran exposes a small machine-readable seam
- another tool decides what to automate or publish
Today, the simplest seam is the local event stream plus machine-readable meeting commands.
Follow The Local Event Stream
gran events --format jsonl --followThis prints one JSON object per event and keeps following new ones until you stop it.
That gives another local process an easy way to notice:
- new meetings
- changed meetings
- transcript readiness
- other sync-derived changes
If you only want a snapshot of recent events:
gran events --format jsonl --limit 50gran sync events still works as a compatibility alias, but gran events is the primary command.
Run Hooks On Matching Events
Gran can also run a local script or post to a webhook when matching events appear during sync.
Add hooks to ~/.config/gran/config.json or ./.gran/config.json:
{
"hooks": [
{
"id": "transcript-script",
"events": ["transcript.ready"],
"kind": "script",
"run": "./scripts/gran-hook.mjs"
},
{
"id": "local-bridge",
"events": ["meeting.created", "meeting.changed"],
"kind": "webhook",
"url": "http://127.0.0.1:4124/hooks/gran"
}
]
}Script hooks receive:
- the event payload as JSON on stdin
- metadata in env vars like
GRAN_EVENT_KIND,GRAN_EVENT_ID, andGRAN_EVENT_MEETING_ID
Webhook hooks receive:
- a JSON
POSTbody with{ source, event }
Hook failures warn and continue. They do not make the sync itself fail.
Fetch The Affected Meeting
Once your script sees an event, fetch the full meeting record in a machine-readable format:
gran meeting get <id> --format json
gran meeting notes <id> --format json
gran meeting transcript <id> --format jsonFolder and search surfaces also support machine-readable output:
gran folder view Personal --format json
gran search "merchant onboarding" --format jsonWhen you use --format json or --format yaml, Gran now keeps stdout clean and skips the human
progress lines. That makes these commands safe to pipe directly into scripts.
That keeps the boundary universal:
- events tell you what changed
- fetch commands tell you what to process
Good Fit For External Automation
This model works well when you want:
- a local script that watches transcript-ready events
- a webhook bridge to another local service
- a Node app built on the SDK
- another local app that reacts to Gran events
The important part is that Gran does not need to know the downstream tool's internal contracts.
Example Shape
One process follows Gran events:
gran events --format jsonl --followThen, when it sees a meeting.updated or transcript.ready event, it can fetch the meeting and
run its own logic:
gran meeting get <id> --format jsonThat is enough to build:
- review-first note generators
- PKM publishing pipelines
- daily-note compilers
- search indexes
- custom notification flows
What Gran Should Own
Gran should own:
- Granola auth
- sync and local indexing
- browse/search/read workflows
- practical local exports and vault publishing
- stable local integration seams
Downstream tools should own:
- cross-source automation logic
- remote publishing APIs
- complex review pipelines
That keeps Gran simple and makes the integration more reusable.