@supa-media/context-hook
v0.1.0
Published
Save what an AI coding session learned into your Context, automatically, when the session ends
Readme
@supa-media/context-hook
Brackets an AI coding session with your Context: the orientation goes in at the start, what was learned comes back at the end, and neither depends on the agent remembering to.
npx -y @supa-media/context-hook installThat signs you in once in your browser and adds two hooks to
~/.claude/settings.json:
SessionStartputs orientation in front of the model before it answers anything, so reading your context stops depending on the agent choosing to.SessionEndsaves the session's user-visible messages to0-inbox/, so writing back stops depending on it too.
The session-start hook, and the one real choice in this package
Claude Code injects a SessionStart hook's output into the session before the
first turn. That is the only mechanism here that does not rely on an agent
deciding anything, and there are two versions of it:
By default it injects an instruction — that this context exists, that the
answer is probably already in it, and to call orient before answering. It
needs no read access and it is strictly stronger than a tool description,
because it is in the conversation rather than in a list the model may skim.
With --orient it injects your actual orientation, fetched at session
start: your front page, what you touched recently, your folders. This is the
strongest version and it costs something real — reading requires read access on
a credential that lives on your laptop unattended. That is why it is a flag you
type rather than a default you discover later.
npx -y @supa-media/context-hook install --orientNeither version ever asks for context:private. A hook that could read every
note you marked private is past what convenience is worth, so on a
mostly-private context the injected orientation is thin — and says so, rather
than implying your context is empty.
Why this exists
A connected client can call save_context when it finishes. Sometimes it does.
The failure is not that agents refuse — it is that a long session ends without
one, and the thing worth keeping was in the part nobody wrote down. This is the
safety net for that, and it does not depend on the agent choosing to cooperate.
It is not a replacement for save_context. An agent that files its own
decisions into the right project folder produces something far better than a
transcript in an inbox. This catches the sessions where that did not happen.
What it sends, and what it does not
User-visible user and assistant messages. Nothing else.
A session log on disk holds much more than the conversation: the system prompt,
the model's own reasoning, every tool call and its full result, the contents of
files read along the way, whatever was in the environment when a command ran.
None of that is sent. The rule is an allow-list — a message travels only if its
role is user or assistant and its content block is declared text — rather
than a filter that strips things that look sensitive, because that kind of
filter fails silently and only in the direction that matters.
That is deliberately lossy. A session whose substance was all tool output comes out thin, and thin is the right failure.
What it can do to your context
By default, nothing except add to your inbox.
The hook asks for context:capture and no other scope. That grant can write a
capture and cannot read a single note — it cannot search, cannot list, and
cannot tell you whether a note exists. A stolen credential from this file is
worth very little, which is the point: it sits on a laptop, unattended, for a
long time.
--orient widens that to context:read so the start hook can fetch your
orientation. That is a real widening and the reason it is a flag: the same
credential can then read your team-visible notes. It still never asks for
context:private, so notes you marked private stay out of reach either way.
It appears in Connections in the Context console like any other client, under
the name Context hook (<your hostname>), and is revoked there on its own.
Where the credential lives
~/.context/hook.json, created 0600 inside a 0700 directory, written
atomically. It holds a refresh token and the client id this machine registered.
It is never printed, never passed on a command line, and never written into
your client's settings file — so a settings.json you paste into a bug report
carries no secret.
Commands
npx -y @supa-media/context-hook install # sign in, then add the hook
npx -y @supa-media/context-hook status # is this machine signed in?
npx -y @supa-media/context-hook uninstall # remove the hook, forget the credential--endpoint <url> points it at your own gateway if you self-host.
Which clients
Claude Code, Codex CLI, and Gemini CLI. All three ship documented hook
systems of the same shape: a command per lifecycle event, JSON on stdin
carrying session_id, transcript_path and cwd, and an additionalContext
field at session start that injects text into the model's context.
npx -y @supa-media/context-hook install --client codex
npx -y @supa-media/context-hook install --client gemini-cliThey differ in three details this package handles for you: the file
(~/.claude/settings.json, ~/.codex/hooks.json, ~/.gemini/settings.json),
what the end of a session is called (Codex says Stop, the others say
SessionEnd), and the unit of timeout — seconds for Claude Code and Codex,
milliseconds for Gemini CLI. Nothing here writes a timeout rather than carry
a number that means two different things depending on where it lands.
Not supported, and why. Cursor has hooks (beforeSubmitPrompt through
stop) but no documented transcript path, so the capture half has nothing to
read. Hosted ChatGPT has no hook system at all — it is a product rather than a
harness, and the MCP connector is the whole surface.
Every one of those clients still has some standing-instruction surface it re-reads on its own — a system prompt setting, a rules file — even without a hook to install into it. Paste this there once and the client starts every turn already knowing to check:
Always orient using the Context MCP (call
orient) before answering anything about me or my work, and save what you learn withsave_contextbefore you finish.
The Context console's connect card has this pre-filled per client, with where
to paste it — Settings → Personalization for ChatGPT, CLAUDE.md for Claude
Code, and so on.
One honest caveat. The transcript parser was written against Claude Code's format. Codex and Gemini CLI hand over a path to their own; the parser drops anything it does not positively recognise, so the worst case there is a save that keeps less than it could — and it says so on the spot rather than going quiet. The session-start half reads no transcript at all and is unaffected.
Dependencies
None. Node built-ins only, like the gateway, because this is a thing people run on their own machines and its supply chain should be its own source.
