How CRAFTs are structured on this instance: razor-thin CRAFT.ipynb, dynamic CRAFTs for tools and reference, notebook templates for reference and tool CRAFTs, 4-notebook project state pattern, token cost guidelines.
- Razor thin CRAFT — only put text in CRAFT that's essential for every single prompt. Everything else is a dynamic CRAFTs/ file pulled on-demand.
- Additive only — never remove or rename sections that other dialogs might depend on.
- KV cache friendly — the thinner and more stable the CRAFT, the more cache hits. Batch edits. Don't use dynamic expressions.
- No
.mdreference files — all reference content lives in.ipynbdynamic CRAFTs so the AI can discover and load them automatically. Plain.mdfiles are invisible to the dynamic CRAFT system.
Each CRAFT.ipynb has at most 2-3 messages:
- Note — minimal identity (2-3 sentences: who, what project, stack). References to dynamic CRAFTs.
- Code cell (optional) — general code or utilities that should be loaded in every session's context.
- Note (optional) —
&backtick tool registrations for stable, always-needed tools.
- Stable, frequently-used tools → register with
&backtick in a CRAFT note (gives AI native tool calling) - In-development or less-frequently-used tools → available via dynamic CRAFT load on demand
- Promotion path → once a tool stabilizes and proves useful, add
®istration to its notebook's tool note - Why
&is needed —globals().update()imports functions into the kernel but does NOT register them as AI tools. Only&backtick syntax triggers schema extraction for native tool calling.
| Type | Example | Notes |
|---|---|---|
| Tool notebooks | git_tools.ipynb |
Dynamic CRAFT. Code runs on load, & tools register |
| Reference notebooks | working_style.ipynb |
Dynamic CRAFT. Notes-only, loaded on demand |
| Project state notebooks | status.ipynb, decisions.ipynb |
Dynamic CRAFT. Loaded when orienting or planning |
- All context and tool notebooks live in
CRAFTs/as dynamic CRAFTs - AI sees first message + file size on every prompt; loads via
load_dialogwhen relevant - Code cells execute on load;
&tool registrations activate on load - On kernel restart, loaded dynamic CRAFTs re-run and tools re-register
CRAFT.ipynbis razor-thin: at most 2-3 cells- First message is critical — it's what the AI reads to decide whether to load. Make it clear and descriptive.
Active projects use dynamic CRAFTs organized into three MECE groups. Add lazily — only when work resumes on a project.
| Notebook | Purpose | Load when... |
|---|---|---|
vision |
North star, system architecture, high-level goals | Orienting, onboarding, architecture discussions |
decisions |
Locked strategic/architectural choices | Something feels already decided, adding a new decision |
| Notebook | Purpose | Load when... |
|---|---|---|
todos |
Active focus + immediate next steps | Starting a session, planning |
backlog |
Planned work not yet queued | Prioritising, writing agent tasks |
status |
What's built and working now | Orienting after a gap, reviewing completeness |
changelog |
Dated one-liner per session | Reviewing history, onboarding |
| Notebook | Purpose | Load when... |
|---|---|---|
working_style |
Coding conventions | Writing new code, reviewing style |
security |
Data handling constraints | Touching credentials, external APIs |
testing |
Test strategy | Writing tests, setting up fixtures |
runbook |
How-tos + gotchas for common workflows | Adding endpoints, dev setup, export |
| (project-specific) | e.g. url_mapping, data_model |
As needed per project |
Not every project needs all of these — start with the 4 minimum (todos, backlog, status, decisions) and add others as the project matures.
Items flow: backlog → todos → changelog (one line) + status (if it changes what's built).
| CRAFT | Growth model | Anti-bloat mechanism |
|---|---|---|
| todos | Stays small (~1k) | Delete done items — never strikethrough |
| backlog | Shrinks over time | Delete done items, only future work lives here |
| status | Stable size (~2k) | Rewrite in place; compress stable subsystems to one-liners |
| changelog | Grows slowly (~50b/session) | Append-only, one line per session; archive old entries when long |
| decisions | Grows slowly | Append-only; rarely needs pruning |
| vision | Stable | Rewrite when direction shifts |
| Reference CRAFTs | Stable | Update in place |
- MECE — every item belongs in exactly one CRAFT. No duplication across files.
- Direction answers why/where, Work Tracking answers what/when, Reference answers how.
- Decisions vs changelog vs status: decisions = why we chose this (locked reasoning), changelog = when things changed (chronological), status = what exists now (topical current state).
- Extract, don't invent — CRAFTs decompose what's already known from controllers/dialogs.
- Controller stays as coordination hub — links to CRAFTs, doesn't duplicate their content.
- Self-contained — loading one CRAFT shouldn't require loading another to make sense.
CRAFTs/— active CRAFTs only. No retired files.Archive/(tracked) — retired CRAFTs and files worth preserving in git history.Origins/(or similar, untracked) — seed material from prior efforts that won't be maintained.
Reference / State CRAFTs — exactly 2 note messages:
- Header (H1):
# {Name} — {Purpose}+ 1-2 sentences on what it tracks and when to load. - Content: H2 sections with the actual material.
Tool CRAFTs — 3-4 messages:
- Header note (H1): same as above — name, purpose, "Load this CRAFT to get X tools registered."
- Code cell (
export): function definitions. Use#| exportflag for nbdev export. - Registration note:
&backtick tool registrations (e.g.&`git_status_``). - Export code cell (optional): runs
nb_export_to generate the.pymodule.
- CRAFT content is at the top of AI context — every edit invalidates the entire KV cache downstream
- Keep CRAFT content stable. Evolving content goes in dynamic CRAFTs
- Use tools (
load_dialog,view,rg,read_url) for on-demand context instead of stuffing into CRAFT - Batch CRAFT edits together to minimize cache invalidations
- Cached input tokens cost ~90% less — maximize cache hits by working at the bottom of dialogs
- What breaks cache: editing CRAFT/early messages, hiding/unhiding messages, dynamic
$expressions, reordering - What doesn't break cache: page reloads, kernel restarts, adding messages at bottom, running code cells
- Notes: first message shown as summary on every prompt (AI decides whether to load)
- Code: ✅ executes when loaded via
load_dialog; re-runs on kernel restart - Tools:
®istrations in dynamic CRAFTs activate on load and persist across kernel restarts load_dialogdoes NOT respectskippedflag — stale cells must have their content cleared, not just skipped- Hierarchical loading works — parent and child
CRAFTs/folders both load - Coexists with
CRAFT.ipynb— both work together
- Root CRAFT — instance-wide identity, global tools, universal instructions
- Domain CRAFTs (e.g.
Projects/CRAFT) — shared defaults for related projects - Project CRAFTs — specific to one project's codebase and status
- Sub-folder CRAFTs (e.g.
Projects/Crucible/nbs/CRAFT) — scoped to a specific subfolder