ghostbrain/docs/connectors

connectors

a connector is a small daemon that talks to one app, pulls items in batches, and hands them to the local indexer. each connector runs in its own sandboxed process, uses an os-keychain-stored token, and can be ripped out without touching the other six.

things that apply to every connector

gmail

uses google oauth via the desktop flow. scopes requested:

https://www.googleapis.com/auth/gmail.readonly
https://www.googleapis.com/auth/gmail.metadata

what's pulled: every thread you can read, including ones you're cc'd or bcc'd on. attachments are indexed by filename only — bodies of attachments aren't downloaded.

setup: in the sidebar, connect → gmail. a browser opens, you pick a google account, you approve. done. tokens refresh automatically.

note

workspace gmail accounts may need an admin to whitelist ghostbrain's oauth client. the error message will tell you what to ask for.

slack

uses slack's user-token oauth (not a bot install — ghostbrain reads what you can read).

scopes: channels:history, groups:history, im:history, mpim:history, plus the matching :read scopes. ghostbrain can index public channels you've joined, private channels you're a member of, dms, and group dms.

setup: connect → slack, pick a workspace, approve. you can connect multiple workspaces — each appears as a separate row in the sidebar.

warning

some workspaces have retention policies that auto-delete messages older than 90 days. ghostbrain will index whatever the api returns, but it will not resurrect messages that slack has already purged.

notion

uses an internal integration token. you'll create one once at notion.so/my-integrations, then share the pages or workspaces you want ghostbrain to see with the integration.

what's pulled: every page, every database row, comments, and the block tree. images and file blocks are indexed by caption + filename.

setup:

  1. create the integration on notion, copy the secret.
  2. paste it into connect → notion → token.
  3. open the notion pages or databases you want indexed, click ···add connections → ghostbrain.

linear

linear gives out personal api keys; no oauth dance.

  1. open linear → settings → api → personal api keys.
  2. create a key labelled "ghostbrain" with read scopes.
  3. paste into connect → linear → key.

what's pulled: issues you can read, projects, cycles, comments, and issue history. attachments by url and title.

github

two auth modes. pick one:

what's pulled: prs, issues, comments, mentions of you, and review threads. commits are indexed by message + author, not by patch contents.

google calendar

google oauth, same desktop flow as gmail. scope: https://www.googleapis.com/auth/calendar.readonly.

what's pulled: every event in your primary calendar plus any calendar you've subscribed to. attendees, descriptions, response statuses, and meeting links. recurring events are stored once with a rule, not exploded.

tip

calendar pairs well with gmail — ghostbrain can tell you what an attendee said in email both before and after the meeting, on one screen.

google drive

google oauth. scope: https://www.googleapis.com/auth/drive.metadata.readonly by default; you can opt-in to drive.readonly in settings to index document contents.

what's pulled by default: file titles, owners, sharing changes, and folder structure. with drive.readonly enabled, also: doc text, sheet titles + cell summaries, slide titles + speaker notes.

disconnecting & purging

two different operations:

actionwhat happens
disconnecttoken deleted from keychain. no further fetches. existing notes stay in the vault.
purgedisconnect + delete every markdown file ghostbrain ever wrote for that source. files in your vault you've moved or edited are skipped — your edits are sacred.
# from the cli
ghostbrain connector disconnect slack
ghostbrain connector purge slack --dry-run

both operations are also available from the sidebar under ··· on the connector row.

a connector i need isn't here

open an issue on github with the app name and what you'd want indexed. the connector interface is small (~150 lines of typescript) — pull requests welcome.