Gran 👵🏻

Auth and Configuration

Prefer API keys, keep desktop auth as fallback, and configure the toolkit without repeating flags.

Auth

Prefer a Granola Personal API key:

gran auth login --api-key grn_...
gran auth status
gran auth use api-key

Desktop-session import remains available as a fallback:

gran auth login
gran auth status
gran auth refresh
gran auth use stored
gran auth use supabase
gran auth logout

gran auth supports:

  • login --api-key <token> to store a Granola Personal API key in the toolkit store
  • login to import the desktop app session into the toolkit store
  • status to inspect the active source, API-key availability, stored-session availability, refresh support, and last auth error
  • refresh to refresh the stored session explicitly
  • use api-key, use stored, or use supabase to switch the active auth source
  • logout to delete stored credentials

The same auth actions are also available from the browser workspace. The first-run web onboarding flow prefers API keys and uses the same local auth store, so a key saved in the browser is immediately available to the CLI, web workspace, and TUI surfaces. The TUI auth overlay uses the same API-key-first language and points back to the CLI command when you still need to store the key itself.

Configuration Precedence

The CLI reads configuration in this order:

  1. command-line flags
  2. environment variables
  3. project ./.gran/config.json
  4. ~/.config/gran/config.json
  5. platform defaults

Config File

gran init generates a good starting point automatically in ~/.config/gran/config.json. If you prefer a project-local override, gran init --project writes ./.gran/config.json, which can look like this:

{
  "agent-provider": "openrouter",
  "agent-model": "openai/gpt-5-mini",
  "agent-harnesses-file": "./agent-harnesses.json",
  "automation-rules-file": "./automation-rules.json",
  "hooks": [
    {
      "id": "transcript-script",
      "events": ["transcript.ready"],
      "kind": "script",
      "run": "./scripts/gran-hook.mjs"
    }
  ],
  "pkm-targets-file": "./pkm-targets.json",
  "output": "../exports/notes",
  "transcript-output": "../exports/transcripts"
}

Relative paths in the chosen config file resolve from the directory that contains that file, not from whatever shell directory happened to launch the command.

If you want Gran to notify another local tool, add hooks entries here. Script hooks receive the event JSON on stdin; webhook hooks get the same payload via HTTP POST.

Environment Variables

  • DEBUG_MODE
  • GRAN_API_KEY
  • GRAN_OPENAI_API_KEY
  • GRAN_OPENROUTER_API_KEY
  • GRAN_AUTOMATION_RULES_FILE
  • GRAN_AGENT_HARNESSES_FILE
  • SUPABASE_FILE
  • OUTPUT
  • TIMEOUT
  • CACHE_FILE
  • TRANSCRIPT_OUTPUT
  • GRAN_CLIENT_VERSION

Notes on Auth Sources

The preferred auth path is a Granola Personal API key. It is the cleanest way to authenticate scripts, sync loops, and automations without depending on desktop-session extraction.

Stored desktop sessions remain useful when you want refreshable local auth without managing a key. The supabase.json fallback remains useful for one-off imports or when the stored session is unavailable.

Provider Setup

For OpenRouter-backed harnesses:

export OPENROUTER_API_KEY=...
gran init --provider openrouter
gran auth login --api-key grn_...
gran sync

For OpenAI-backed harnesses:

export OPENAI_API_KEY=...
gran init --provider openai
gran auth login --api-key grn_...
gran sync

For local Codex-backed harnesses:

gran init --provider codex
gran auth login --api-key grn_...
codex exec --help
gran sync

On this page