ghostbrain/docs/api & cli

api & cli

ghostbrain runs a small http server on loopback so the plugin (and any scripts you write) can talk to the indexer. the same operations are exposed through the ghostbrain command-line tool. nothing here is exposed to the network — there's no auth because there's no listening socket beyond 127.0.0.1.

http api

default base: http://127.0.0.1:7349. port is configurable via GHOSTBRAIN_PORT. content type is application/json everywhere.

note

the server only binds to 127.0.0.1 and refuses to start on any other interface. there is no --bind 0.0.0.0 flag. if you need a remote api, run ghostbrain through an ssh tunnel.

lexical + semantic search. returns ranked results without synthesis.

GET /v1/search?q=q3+launch&from=marie&limit=10

# →
{
  "hits": [
    {
      "id": "slack/T01/C0X/p1714145600.000",
      "source": "slack",
      "title": "#launch · marie",
      "snippet": "locking the date. team agreed: jun 11.",
      "occurred_at": "2026-04-26T15:23:11Z",
      "vault_path": "threads/launch/2026-04-26.md",
      "score": 0.84
    }
  ],
  "took_ms": 142
}

parameters:

namenotes
qrequired. the query text. operators allowed.
fromshortcut for ?q=...+from:name.
sourcerestrict to one connector.
before, afteriso date or relative shortcut (e.g. 1w).
limitdefault 20, max 200.

POST /v1/ask

synthesised answer with citations. equivalent to a !-prefixed query in the sidebar.

POST /v1/ask
Content-Type: application/json

{
  "query": "what did we decide about pricing in march",
  "limit": 5
}

# streamed response (sse)
event: token
data: {"text": "On 2026-03-14, "}

event: citation
data: {"n": 1, "id": "slack/.../p1710...", "vault_path": "threads/pricing/..."}

event: done
data: {"took_ms": 1820}

GET /v1/items/:id

fetch the canonical record for one item, including the rendered markdown.

GET /v1/connectors

list connectors with status, last cursor, and per-source counts.

POST /v1/reindex

kick a manual reindex. body accepts { "source": "slack" } to scope; omitting reindexes everything. returns a job id you can poll at /v1/jobs/:id.

cli reference

installed as ghostbrain in your $PATH on macos and linux; ghostbrain.exe on windows. all commands accept --json for machine-readable output.

commanddoes
ghostbrain statusconnectors, queue depth, vault size, indexer health.
ghostbrain search "<q>"same as /v1/search.
ghostbrain ask "<q>"same as /v1/ask, prints synthesised answer to stdout.
ghostbrain connector listlist connectors, last sync, item counts.
ghostbrain connector disconnect <name>remove token; keep notes.
ghostbrain connector purge <name> [--dry-run]remove token + every note written by that connector.
ghostbrain reindex [--source=<name>]force a re-scan.
ghostbrain doctorrun health checks. prints a single ok or a list of issues.
ghostbrain logs [--follow]tail the indexer log.
ghostbrain export <path>tar.gz the vault + .ghostbrain/ for backup.

examples

# quick sanity check after install
ghostbrain doctor

# pipe into jq
ghostbrain search "deploy" --source=slack --limit=50 --json \
  | jq '.hits[] | {date: .occurred_at, who: .author, title: .title}'

# nightly backup to time machine drive
ghostbrain export /Volumes/Backup/ghostbrain-$(date +%F).tar.gz

hooks & scheduled queries

hooks let you run a shell command whenever something happens in ghostbrain. configure them in vault/.ghostbrain/hooks.yaml:

hooks:
  # every monday 09:00 local, run a saved query and append to inbox
  - on: schedule
    at: "0 9 * * mon"
    run: ghostbrain ask "what did i miss last week" >> inbox/monday.md

  # whenever a github review is captured from eli, ping me
  - on: item.captured
    when: "source == 'github' and type == 'review' and author == 'eli'"
    run: osascript -e 'display notification "eli reviewed your pr"'

  # at the end of every calendar meeting, summarise
  - on: meeting.ended
    run: ghostbrain ask "summarise {meeting.title}" > meetings/{meeting.slug}.md

available events: item.captured, connector.connected, connector.disconnected, meeting.ended, query.run, plus the cron-style schedule.

tip

placeholders ({meeting.title}, {item.author}, etc.) are shell-escaped automatically — you don't need to quote them.

outgoing webhooks

ghostbrain can post a json payload to a url on the same events. set them up under settings → ghostbrain → webhooks. the payload signature is in the x-ghostbrain-signature header (hmac-sha256 over the body, key from settings).