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.
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.
GET /v1/search
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:
| name | notes |
|---|---|
| q | required. the query text. operators allowed. |
| from | shortcut for ?q=...+from:name. |
| source | restrict to one connector. |
| before, after | iso date or relative shortcut (e.g. 1w). |
| limit | default 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.
| command | does |
|---|---|
| ghostbrain status | connectors, 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 list | list 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 doctor | run 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.
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).