Zekra
القائمة · Zekra

Capture hook

An opt-in Claude Code Stop hook that retains durable decisions and facts from each assistant turn, with private-span and secret redaction.

The capture hook fills a brain automatically while you work. It is a Claude Code Stop hook: at the end of each assistant turn it reads the turn, keeps it only if it states something durable, redacts it, and sends it to POST /api/brain/retain.

It lives in the Zekra server repository at .claude/hooks/capture-mode.py. It needs Python 3 and no extra packages.

Authentication: the hook sends your access token as X-Zekra-Token (from ZEKRA_TOKEN, or the legacy CABRAIN_TOKEN) and posts to app.zekra.dev by default. The token needs write access on the target brain. Without a token it works only against a self-hosted instance that accepts requests without one (see Security).

What it captures

The hook keeps a turn only if it looks like a conclusion, not chatter:

  • It must be at least 40 characters long.
  • It must contain a decision or fact marker, such as decided, chose, because, instead of, rather than, turns out, the root cause, should use or should not, constraint, gotcha, note that, important, prefer, corrected, endpoint, schema, contract or convention.

Routine turns, such as file listings, status updates and acknowledgements, are skipped. The server's write decision then drops anything already known.

Privacy

  • Any <private>…</private> span is removed before the request is sent. If nothing is left, the turn is dropped.
  • If a turn contains something shaped like a credential (an AWS access key, a private-key block, or password=, secret:, token= or api_key= followed by a value), the whole turn is dropped.
  • The server also moves any secrets it detects into the brain's vault.

Enable it

Capture is opt-in and does nothing unless ZEKRA_CAPTURE=1. Add the hook to .claude/settings.json in your project, or to ~/.claude/settings.json for all projects:

json
VariableDefaultMeaning
ZEKRA_CAPTUREoffMust be 1 to capture anything
ZEKRA_API_URLhttps://app.zekra.devYour Zekra instance (self-hosted: your URL)
ZEKRA_TOKENnone (falls back to CABRAIN_TOKEN)Sent as X-Zekra-Token; needs write on the brain
ZEKRA_NAMESPACElower-cased name of the working directoryBrain to write to
ZEKRA_AGENT_IDnoneSent as X-Agent-Id

Each captured memory is stored with sourceKind: "claude_code" and sourceRef set to the Claude Code session id, so you can trace a memory back to the session it came from.

Behavior

  • Never blocks. The request times out after 2 seconds, and any failure (server down, turn not worth keeping, everything private) exits silently with status 0.
  • Importance is computed on the server. The hook only decides whether a turn is worth sending.