Local Agent Hook Setup
This guide captures Claude Code and Codex sessions as Oliver events. Codex hooks capture prompt submit and stop events; Claude Code hooks also capture tool use events.
The current path is split in two:
olivergraph(theoliverCLI): installs Claude/Codex hooks, writes hook payloads to a local queue, and can run a periodic uploader.cmd/api: backend server that accepts authenticatedPOST /eventswrites scoped by bearer token andX-Workspace.
The uploader normalizes queued hook payloads into Oliver events and posts them
to authenticated POST /events.
Prerequisites
Run commands from the repository root unless a step says otherwise.
The CLI targets production by default. For local development, point it at your local
stack once per shell (or pass --env local on each command):
export OLIVER_ENV=local
- Start the Oliver local stack. For local development:
scripts/start-local-stack.sh
- Sign in (optional —
oliver startopens this same login on first run):
oliver login
oliver login opens the portal, signs in with Supabase, creates access to the shared
default workspace, and saves local credentials in .oliver/agent-hooks. You can skip
this and let oliver start prompt the login for you; run it explicitly when you want to
re-authenticate or switch workspace.
For headless/dev fallback, mint a token manually and export it:
cd backend
go run ./cmd/issue-token \
--kind agent \
--display-name "Local Agent Hooks" \
--workspace default \
--workspace-name "Default"
cd ..
export OLIVER_API=http://127.0.0.1:8081
export OLIVER_TOKEN=usr_...
export OLIVER_WORKSPACE=default
You can also create a key in the portal under API Keys, copy it once, and save it while starting the uploader:
oliver start --api-key usr_... --workspace default
--api-key is accepted on oliver start only. It writes the token to
.oliver/agent-hooks/auth.json and does not pass the token as a daemon argument.
extensions/agent-hooks/.env.example contains the same uploader variables as a local
template. Source a copied .env yourself if you prefer file-based setup.
If your API runs on port 8080, use OLIVER_API=http://127.0.0.1:8080.
Install And Start
Install the CLI globally, then run oliver start in the repo you want to capture:
npm install -g olivergraph
cd your-project
oliver start
oliver start is the single entry point: it wires the hooks (idempotent), then runs the
background uploader, opening the portal to sign in on first run. It updates only repo-local
files by default:
.codex/config.toml.claude/settings.local.json.oliver/agent-hooks/config.json
These files are local machine state and are ignored by git. They contain the absolute path
to the installed CLI so Claude/Codex can call the collector. Install globally rather than via
npx, since an npx cache path can be garbage-collected out from under the installed hooks.
To wire user-global agent config, opt in explicitly:
OLIVER_AGENT_HOOK_SCOPE=user oliver install
That writes ~/.codex/config.toml and ~/.claude/settings.json, so it may need normal
filesystem permission to edit files outside the repo.
oliver install (advanced) wires the hooks without starting the uploader — useful for CI,
headless setups, or user-scope installs where the uploader runs elsewhere. oliver start
covers it for the common case.
Local Queue And Upload
Hook commands return quickly. They write raw payloads to:
.oliver/agent-hooks/pending.jsonl
The collector includes an uploader that wakes up on a fixed interval, normalizes queued
payloads into local_agent_event records, and sends them to POST /events. The default
interval is five minutes:
OLIVER_AGENT_PUSH_INTERVAL_SECONDS=300
Start the uploader when you want to inspect or test that path:
oliver start
If you created a portal API key instead of using oliver login, pass it on the first
start:
oliver start --api-key usr_... --workspace default
It writes uploader state and logs under .oliver/agent-hooks. Check or stop it with:
oliver status
oliver stop
You can try a manual flush to inspect the current uploader behavior:
oliver flush
Or keep a foreground uploader running:
oliver watch
Configuration:
OLIVER_API: backend API URL, defaulthttp://127.0.0.1:8081OLIVER_APP: portal URL for browser login, defaulthttp://127.0.0.1:5173OLIVER_TOKEN: bearer token for the user or agent writing events; normally saved by loginOLIVER_WORKSPACE: workspace slug for event writes, defaultdefaultOLIVER_AGENT_PUSH_INTERVAL_SECONDS: uploader/flush cadence, default300OLIVER_AGENT_PUSH_BATCH_SIZE: max events to flush per pass, default100OLIVER_PROJECT: project target value, defaultdefault
Verify Capture
After triggering a Claude Code prompt/tool call or a Codex prompt/stop event, check local status. It includes pending queue size, successful submitted counts, and uploader process state:
oliver status
Then list recent stored events:
curl -H "Authorization: Bearer $OLIVER_TOKEN" \
-H "X-Workspace: $OLIVER_WORKSPACE" \
"$OLIVER_API/events?limit=20"
Captured events have:
kind:local_agent_eventsession_id: a stablelocal_agent:<agent>:<session>:<turn>:<hook>style keytargets:project,source,agent,hook_event,session,turn,tool,cwd, andtranscriptwhen presentmodelandusagewhen the hook payload includes them
Compatibility Listener
The older listener still works for setups that prefer direct HTTP hooks:
cd backend
go run ./cmd/agent-hook-listener \
--project oliver \
--port 8765 \
--verbose
It accepts native hook payloads on:
http://127.0.0.1:8765/agent-hooks/{codex|claude}
Unlike the npm collector, the listener receives hook payloads over HTTP and forwards each normalized event to the API immediately.
Privacy And Safety
Payloads are redacted for common secret keys and token-looking text before storage in the backend, but prompts, tool inputs, tool outputs, paths, and transcript references may still contain sensitive project data. Configure these hooks only for users and repos whose agent activity should be stored in Oliver.
The local queue is unredacted because it stores native hook payloads before normalization.
Keep .oliver/ local and do not commit it.
Troubleshooting
- No events appear in Oliver: run
oliver status, then runoliver flush. - Codex does not call the hook: restart Codex after installation, trust the hook command
if prompted, and use
/hooksto confirm Codex found the configured hooks. - Claude does not call the hook: restart Claude Code after installation and confirm it is
loading the repo-local
.claude/settings.local.jsonor the user-level settings file. - Backend rejects uploads: confirm
OLIVER_TOKENis valid, the user belongs toOLIVER_WORKSPACE, and the backend API URL points at the current Oliver service.