docsiq registers a SessionStart hook with supported AI clients so that whenever a coding session begins, the client POSTs the repo's git remote to docsiq, and docsiq replies with a project-scoped context blob that the client injects into the agent's prompt.
The endpoint is POST /api/hook/SessionStart. See rest-api.md
for the request / response shape.
docsiq hooks install # all supported clients
docsiq hooks install --client claude # just Claude Code
docsiq hooks install --dry-run # preview without writing files
docsiq hooks install --hook-url http://192.168.1.10:8080 # custom server URLOn install, docsiq:
- Extracts
hook.shto$DATA_DIR/hooks/hook.sh(0755). The script reads the client's JSON payload, resolves the local git remote withgit -C "$CWD" remote get-url origin, and POSTs the result to the configured hook URL. - Writes the client-specific config fragment (schema depends on the client — see the matrix below).
Uninstall reverses step 2 and leaves hook.sh in place. docsiq hooks status prints which clients currently have a docsiq hook registered.
docsiq registers a SessionStart hook with each AI client so GraphRAG
context is loaded when the client starts. Only Claude Code publishes a
documented SessionStart hook schema — the others are a best-effort
placeholder pinned by fixture tests. Installing an unverified hook
prints a slog.Warn so operators can opt out.
| Client | Config path | Schema source | Status |
|---|---|---|---|
| Claude Code | ~/.claude/settings.json |
docs.claude.com/en/docs/claude-code/hooks (fetched 2026-04-17) | verified |
| Cursor | ~/.cursor/docsiq-hooks.json |
no docs (docs.cursor.com/en/agent/hooks returned empty, 2026-04-17) | unverified |
| Copilot CLI | ~/.config/github-copilot/hooks.json |
no docs (github.com/copilot CLI docs publish no hook schema, 2026-04-17) | unverified |
| Codex CLI | ~/.codex/hooks.json |
no docs (github.com/openai/codex docs/config.md documents only a Notify post-turn hook, no SessionStart, 2026-04-17) |
unverified |
Unverified means we mirrored the shape used by the original
kgraph codebase (which was itself a best-effort guess). When a client
publishes a real schema, the corresponding installer in
internal/hookinstaller/ should be updated along with its fixture pair
in internal/hookinstaller/fixtures/<client>/.
- Verified installers match the client's published schema exactly; a schema bump on the client side will break our installer and needs an update on our side.
- Unverified installers write the kgraph-style shape and may be ignored entirely by the client. An unverified install is a no-op until either the schema matches or the client starts honoring the kgraph shape.
Claude Code example flow:
- User runs
claudeinside~/src/my-repo. - Claude Code reads
~/.claude/settings.json, sees the docsiq hook, and invokes$DATA_DIR/hooks/hook.shwith a JSON payload on stdin. hook.shresolves the repo's origin remote and POSTs it tohttp://127.0.0.1:8080/api/hook/SessionStart.- docsiq normalizes the remote with
project.Slug(), looks up the registry, and responds:- Registered →
200 {project, additionalContext}. Claude Code injectsadditionalContextinto the prompt. - Unregistered →
204 No Content. Claude Code stays silent.
- Registered →
Work the list top-to-bottom:
-
Is the hook actually installed?
docsiq hooks statusEvery client listed should say
registered. If it saysmissing, rundocsiq hooks install --client <name>. -
Does
hook.shexist and is it executable?ls -la $(docsiq stats --json | jq -r .data_dir)/hooks/hook.shShould be mode
0755. Re-run install to re-extract if missing. -
Is the docsiq server reachable from the client?
curl -s http://127.0.0.1:8080/health # {"status":"ok"}If not:
docsiq serveis not running, or a firewall blocks the hook URL, or--hook-urlwas overridden to an unreachable address. -
Did the client ever call the hook? Check the docsiq server logs for a line like:
level=INFO msg=http method=POST path=/api/hook/SessionStart status=200If you never see that line, the client isn't firing the hook at all — almost always a schema mismatch (see unverified clients above) or a typo'd config path.
-
Is your repo registered? An unregistered remote yields
204 No Content— the hook ran, but docsiq has nothing to say.docsiq projects list docsiq init # inside the repo, if missing -
Is the bearer key set correctly? When
server.api_key/DOCSIQ_API_KEYis configured,hook.shneeds the matching key. The extracted script reads$DOCSIQ_API_KEYfrom the client's environment — make sure that's exported at the shell launching the client. A 401 response in the logs is the signal. -
Is the client running from the right cwd? Claude Code, Cursor, etc. each resolve the "current repo" slightly differently. If
hook.shruns outside a git checkout, theremotefield is empty and docsiq replies400. Launch the client from inside the repo tree. -
Does
docsiq hooks install --dry-runshow what you expect? Dry-run prints the exact JSON it would write. If the config shape looks wrong for your client's version, capture the output and file a bug with the client's own hook docs attached.
The response body is generated server-side from the project's
registered name + slug. To tailor it further, index a note named
_session-prelude.md in the project's notes directory — the hook
handler prepends that note's content to additionalContext when
present.