See exactly what your agent sees — and what it had to guess.
A glass-box context tool. Paste your material onto a canvas as cards, select the ones that matter, pick what you're producing, and before anything is sent you can read the exact document the model receives. Then the output comes back with a receipt: which cards it quoted, which it merely leaned on, which it ignored, and what it had to guess because no card told it.
Live: briefing-board-delta.vercel.app · Free, no signup, board lives in your browser.
Context tools hide the prompt. You drop in documents, type an instruction, and something comes back — with no way to know whether the model read the thing you cared about, or quietly invented the constraint you forgot to state.
For creative work you can eyeball the result and move on. For engineering work you can't: the failure mode isn't a bad sentence, it's a spec that silently assumed the wrong deadline.
So this inverts it. Nothing is hidden and nothing is silently preprocessed. If a card gets truncated you see a --- trimmed here --- line in the payload viewer. If the receipt can't be parsed you get an honest "receipt unavailable" rather than a fabricated one.
The underlying claim is small and, if you write software, familiar: a good agent brief is a spec — role, context, constraints, done-looks-like. You've written specs for years. This just makes the invisible part visible.
This is the part worth reading before you fork it, because it's the whole design and it is easy to break:
- The client assembles the entire payload.
api/generate.jsrelays it to the Claude API verbatim. There is no system prompt. The server adds nothing. - The payload viewer is byte-identical to what gets sent. Not a preview, not a summary — the same string.
- Truncation is client-side and visible. Never a silent trim.
- The receipt comes back as a trailing fenced JSON block, split off server-side, with card ids validated against the ones actually sent. Parse failure sets
receipt: nulland the UI says so.
If you change one thing, keep that. A context tool that quietly rewrites your prompt is the thing this exists to argue against.
The receipt is the model's own account of what it used — self-reported, not instrumented. That's a real limitation and the UI says so out loud. It is still worth having: a model reporting it ignored the card you thought was central tells you something true.
- Universal capture — paste text, ⌘V anywhere, drag-drop; PDFs parsed client-side via pdf.js; article fetch; YouTube transcripts best-effort with a first-class paste fallback; voice via Web Speech API
- Selection is retrieval — no embeddings, no chunking, no similarity search. You choose the cards. That's the point.
- 6 recipes × 4 brief slots (role / task+context / constraints / done-looks-like)
- Brief Grade — deterministic, computed locally, no API call
- The receipt — per-card verdict plus up to 3 named gaps with one-click fixes
- Standing cards (voice / audience / offer) persist in localStorage and auto-attach
- Export/import — the whole board is one human-readable JSON file
Deliberately not included, and please read the reasoning before adding them: embeddings and chunking (they defeat "selection is retrieval"), auto-summarisation (silent preprocessing), multi-turn chat, sentence-level provenance, posting integrations.
Three files, no build step, no framework.
| File | What |
|---|---|
index.html |
The entire front end — vanilla JS, hand-rolled drag, dark theme |
api/generate.js |
Verbatim relay to the Claude API + receipt split and validation |
api/ingest.js |
YouTube transcript + article fetch, SSRF-guarded |
api/ingest.js restricts fetches to http/https, rejects IP-literal hosts and non-default ports, and re-checks after redirects.
git clone https://github.com/sinkrest/briefing-board.git
cd briefing-board
npx vercel deploy --prodThen set two environment variables on the project:
| Variable | Required | What |
|---|---|---|
ANTHROPIC_API_KEY |
yes | Your key from console.anthropic.com |
ALLOWED_ORIGIN_RE |
recommended | Regex matching your own deploy, e.g. ^https://my-board[a-z0-9.-]*\.vercel\.app$. Defaults to the reference deployment's pattern; localhost is always allowed. |
Rate limiting is per-IP, 5 requests/minute, with a 150k-character server-side payload cap. You are paying for every generate call, so if you put this somewhere public, keep the origin check and consider tightening the limit.
index.html ships with <meta name="robots" content="noindex"> — delete that line if you want your deploy indexed.
It's a static file plus two serverless functions, so:
npx vercel devFront-end-only changes need nothing at all — open index.html in a browser; everything except generate and ingest works offline.
MIT — see LICENSE.