Skip to content

Memory Phase 3 — SessionStart Inject Hook

Section titled “Memory Phase 3 — SessionStart Inject Hook”

Promoted from KB-OS-Context §5 (KB-OS Memory v1 deferred item). Memory v1 shipped store (SessionEnd digest hook) and recall (qmd) as mechanism, but left inject as convention: CLAUDE.md/AGENTS.md tell the agent to read _active.md + STATUS, and /task-start//task-continue auto-load the dept charter chain. There is no SessionStart hook — so on a plain session (no skill invoked) nothing current is injected unasked.

This is Simon Scrapes’ step 1 (“the frozen snapshot”) — the one piece of his plan KB-OS adopted the goal of but deferred the build. Governing rule: CONSTITUTION Principle #8 (vault owns truth; the hook only injects a view of it, never a new store).

A Claude Code SessionStart hook that silently injects a small, frozen-for-the-session snapshot of current priorities at the start of every main session — so any agent already knows “what’s true right now” before Talbot types a word — and kicks a background qmd update so recall is fresh from the first query.

Hook: ~/ai-config/claude/hooks/session-start-inject.sh (SSOT in ai-config; deploys to ~/.claude/hooks/), registered as a SessionStart matcher in ~/ai-config/claude/settings.wsl.json (mirror of the existing SessionEnd block, lines ~95). Model this on ~/.claude/hooks/session-digest.sh — reuse its stdin-JSON + env-var recursion-guard patterns.

What it injects (keep it SMALL — Simon’s cap ~2k chars; a snapshot, not a junk drawer):

  1. Biggest Rocks — the curated table from Core/DASHBOARD.md (the ”## Biggest Rocks” section only).
  2. Active work — a capped slice of Core/_WorkingOn/Tasks/_active.md (e.g. the ... open-task lines, not the ✅ completed history — the file has grown long).
    • Emit via SessionStart’s hookSpecificOutput.additionalContext (or plain stdout, whichever the current Claude Code SessionStart contract injects). Silent — no greeting, no recap.

Background refresh: detached qmd update (fire-and-forget, like the digest hook’s tail) so the index tracks any out-of-session edits — but must not block session start. Skip qmd embed here (too slow for startup; SessionEnd already handles embedding).

Guards / decisions:

  • Recursion / subagent guard — env var (e.g. KB_SESSION_INJECT=1) so any claude -p the hook might spawn, and subagent sessions, don’t re-inject. (SessionStart source values: startup, resume, clear, compact — decide which to inject on. Likely startup + clear; maybe skip compact/resume to avoid double-injection.)
  • Cap enforcement — truncate the injected block to a hard char budget so a bloated _active.md can’t flood context.
  • Frozen for the session — injection happens once at start; writes take effect next session (this is inherent to SessionStart, just document it).
  • Fast — the snapshot read must be near-instant (plain file reads + grep/awk section extraction; no claude -p on the critical path).
  • Confirm the design above (what to inject, which source values, the char cap)
  • Write session-start-inject.sh in ai-config/claude/hooks/ (recursion guard, section extraction, char cap, backgrounded qmd update)
  • Register SessionStart in ai-config/claude/settings.wsl.json (diff-before-deploy: reconcile source←deployed first per the AGENTS.md rule)
  • Deploy (cd ~/ai-config && git commit → post-commit hook redeploys) — this is a global-deploying change → escalate/confirm with Talbot before the commit
  • Test (Simon’s “prove it — inject”): start a fresh session, ask “what were we working on?” without any reminder — it should already know from the snapshot alone. Verify: injected silently (no greeting), within char budget, subagents don’t re-inject, qmd update ran in background.
  • Update KB-OS-Context §3 (Inject row: convention → mechanism) + §5 (mark Phase 3 done) + KB-OS/logs/
  • Fresh session knows current Biggest Rocks + open tasks unprompted.
  • No greeting/recap; injection is silent background context.
  • Injected block ≤ char cap even when _active.md is large.
  • Subagent sessions and any hook-spawned claude -p do not trigger injection.
  • Session start is not perceptibly slowed (qmd update detached).
  • Pattern to mirror: ~/.claude/hooks/session-digest.sh (stdin JSON, recursion guard, detached worker)
  • Hook wiring: ~/ai-config/claude/settings.wsl.json SessionEnd block
  • Snapshot sources: Core/DASHBOARD.md (Biggest Rocks), Core/_WorkingOn/Tasks/_active.md
  • Concept: KB-OS-Context §1 (frozen snapshot / memory plane), §3 (inject)
  • Claude Code SessionStart hook contract (verify current additionalContext mechanism at build time)

Summary:

  • Confirmed design in plan mode before building: inject on startup+clear only (skip resume/compact); 2000-char cap, line-boundary truncated, Biggest Rocks first then open _active.md lines; verified live SessionStart hook contract (hookSpecificOutput.additionalContext) against current Claude Code docs rather than assuming
  • Wrote ~/ai-config/claude/hooks/session-start-inject.sh — recursion guard (KB_SESSION_INJECT), source filtering, awk/grep extraction, char cap, backgrounded detached qmd update
  • Registered SessionStart in ai-config/claude/settings.wsl.json
  • Scope addition found during exploration: session-digest.sh (the pattern this task was told to mirror) was never actually SSOT’d in ai-config — hand-placed in ~/.claude/hooks/, untracked, and deploy.sh had no hooks-copy step at all. Migrated it into ai-config/claude/hooks/ (byte-identical, verified via diff) and added the missing deploy.sh step, so both hooks are now version-controlled and deploy correctly
  • Deployed — committed ai-config 6f86d15 (confirmed with Talbot before committing, per the task’s own escalation flag), post-commit hook redeployed automatically
  • Test: fixture stdin for startup/resume/compact, recursion guard, bash -n syntax, live smoke test of the deployed copy — all pass. Not verified from inside this session: a genuinely fresh top-level session silently already knowing “what were we working on” — that requires an actual new session after deploy
  • Updated KB-OS-Context §3 (Inject: convention → mechanism) + §5 (Phase 3 moved to Shipped ✅) + STATUS.md + log logs/2026-07-13_Memory-Phase3-SessionStart-Inject-Hook.md

Next Steps for Talbot:

  • Start a genuinely fresh session (new terminal, or /clear) and ask “what were we working on?” without any other prompt — confirm it already knows from the injected snapshot alone, with no greeting/recap leaking into the reply 1.
  • If the Biggest Rocks / active-work extraction ever looks wrong or stale, the fix lives in ~/ai-config/claude/hooks/session-start-inject.sh (commit, redeploys automatically) 1.