Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
9.6 KiB
Plan: Endless Mode Re-implementation on Current Main
Context
Endless mode was implemented on beta/endless-mode branch (diverged at v7.0.0). Main is now at v10.4.1 — 902 commits ahead. Rebasing is impractical. This plan re-implements endless mode on top of current main, using the old branch as a reference for concepts only.
What Endless Mode Does
When enabled, after each tool execution:
- The PostToolUse hook waits for the SDK agent to process the observation
- The processed observation (title, narrative, facts) is injected back into Claude's context via
additionalContext - Large tool inputs are cleared from the transcript to save tokens
- Net effect: Claude sees compressed observations instead of raw tool data → extends effective context window
Key Problem from Previous Attempt
The save-hook blocked for 60-90s waiting for SDK processing, making sessions unusably slow. The fundamental tension: AI-processed observations require time, but hooks have a 120s hard limit.
Branch Strategy
Create a new branch feature/endless-mode-v2 from current main. Do NOT touch the old beta/endless-mode branch.
Phase 0: Documentation Discovery (Reference Gathering)
0.1 — Read old branch implementation for reference patterns
git show beta/endless-mode:src/hooks/save-hook.ts— synchronous wait patterngit show beta/endless-mode:src/hooks/context-injection.ts— observation formattinggit show beta/endless-mode:src/hooks/pre-tool-use-hook.ts— tool_use_id trackinggit show beta/endless-mode:src/services/worker/SessionManager.ts—waitForNextObservation()git show beta/endless-mode:docs/context/state-of-endless.md— architecture doc
0.2 — Read current main integration points
src/hooks/hook-response.ts:1-15— current hook response formatsrc/services/worker/SessionManager.ts:21-100— current session managementsrc/services/worker/SDKAgent.ts:43-150— current SDK agent flow, event emissionsrc/services/worker/http/routes/SessionRoutes.ts:498-573— current observation endpointsrc/services/sqlite/SessionStore.ts:1503-1560— current storeObservationsrc/shared/SettingsDefaultsManager.ts:77-133— current settings defaults
0.3 — Identify Claude Code hook contract
plugin/plugin.json— current hook configuration (which hooks exist, their types)- Check if
PreToolUsehook type is available in Claude Code plugin spec - Check
additionalContextfield availability in hook response contract
Deliverable
List of exact APIs, file locations, and patterns available for each integration point. Anti-pattern list of methods that existed on the old branch but don't exist on current main.
Phase 1: Database Schema — Add tool_use_id Column
What to implement
- Add migration 20 to
src/services/sqlite/SessionStore.ts(after migration 19 at ~line 53) - Add nullable
tool_use_id TEXTcolumn to observations table - Add index:
CREATE INDEX idx_observations_tool_use_id ON observations(tool_use_id) - Add
getObservationsByToolUseId(toolUseId: string)method to SessionStore - Update
storeObservation()signature to accept optionaltool_use_id?: string
Files to modify
src/services/sqlite/SessionStore.ts— migration + store methodsrc/services/sqlite/observations/types.ts— add tool_use_id to StoreObservationResultsrc/types/transcript.ts— verify ToolResultContent.tool_use_id matches Claude's format
Verification
npm run buildsucceeds- Worker starts without errors
- New column appears in observations table:
sqlite3 ~/.claude-mem/claude-mem.db ".schema observations"
Anti-patterns
- Do NOT make tool_use_id NOT NULL — old observations won't have it
- Do NOT modify existing migrations — only append new ones
Phase 2: Settings — Add Endless Mode Configuration
What to implement
- Add to
SettingsDefaultsManager.tsDEFAULTS (~line 77):CLAUDE_MEM_ENDLESS_MODE:'false'(disabled by default)CLAUDE_MEM_ENDLESS_WAIT_TIMEOUT_MS:'90000'(90 second timeout)
- Add helper method
isEndlessModeEnabled(): boolean
Files to modify
src/shared/SettingsDefaultsManager.ts
Verification
- Settings load correctly with defaults
- Can override via
~/.claude-mem/settings.json - Can override via environment variable
Anti-patterns
- Do NOT add UI for toggling yet — settings.json is sufficient for beta
Phase 3: Worker-Side — Event-Based Observation Completion Signaling
What to implement
- In
SessionManager.ts: AddwaitForNextObservation(sessionDbId, toolUseId, timeoutMs)method- Uses existing
sessionQueuesEventEmitter infrastructure - Waits for
observation_savedevent matching toolUseId - Returns the observation or null on timeout
- Uses existing
- In
SDKAgent.ts: AfterstoreObservation()call, emitobservation_savedevent with observation data and toolUseId - In
SessionRoutes.ts:- Accept
tool_use_idin observation POST body - Accept
wait_until_observation_is_saved=truequery parameter - When waiting: call
SessionManager.waitForNextObservation()before responding - When not waiting (default): existing fire-and-forget behavior
- Accept
Files to modify
src/services/worker/SessionManager.tssrc/services/worker/SDKAgent.tssrc/services/worker/http/routes/SessionRoutes.ts
Verification
- Worker builds and starts
- Default (non-endless) observation flow is unaffected
- Can POST with
wait_until_observation_is_saved=trueand get observation back in response
Anti-patterns
- Do NOT add SSE/streaming — simple HTTP request/response with await is sufficient
- Do NOT modify the existing fire-and-forget path — only add the new waiting path
- Do NOT add a pre-tool-use endpoint yet — tool_use_id comes from the hook, not a separate call
Phase 4: Hook-Side — PostToolUse Synchronous Injection
What to implement
- Modify the PostToolUse hook (save-hook) to:
- Check if endless mode is enabled via settings
- Extract
tool_use_idfrom the hook input (Claude Code provides this) - If endless mode ON: POST observation with
wait_until_observation_is_saved=trueandtool_use_id - Receive processed observation in HTTP response
- Format observation as markdown (copy pattern from old
context-injection.ts) - Return hook response with
additionalContextfield containing formatted observation - If endless mode OFF: existing fire-and-forget behavior (unchanged)
- Create
src/hooks/observation-formatter.tsutility for markdown formatting
Files to modify
src/hooks/save-hook.ts(or whatever the current PostToolUse hook source is)src/hooks/observation-formatter.ts(NEW)src/hooks/hook-response.ts— addadditionalContextsupport to response type
Verification
- With endless mode OFF: behavior identical to current
- With endless mode ON: observations appear in Claude's context after tool use
- Hook respects 120s Claude Code timeout (90s observation wait + buffer)
Anti-patterns
- Do NOT add transcript clearing in this phase — that's a separate optimization
- Do NOT block indefinitely — always use timeout with graceful fallback
- Do NOT swallow errors in the wait path — if it fails, fall back to fire-and-forget
Phase 5: Build, Test, and Validate
What to implement
npm run build-and-sync— full build- Manual testing:
- Enable endless mode in settings.json
- Start a Claude Code session
- Execute tool uses and verify observations appear in context
- Verify non-endless mode is unaffected
- Add basic unit tests in
tests/endless-mode/
Verification checklist
npm run buildsucceeds with zero errors- Worker starts without errors
- Non-endless mode behavior unchanged (regression check)
- With endless mode ON: observation appears in Claude's context after tool use
- Timeout fallback works (kill worker mid-processing, verify graceful degradation)
- Settings toggle works (on/off without restart)
- Database migration applies cleanly on fresh and existing databases
Anti-patterns
- Do NOT ship to npm/release yet — this is beta
- Do NOT add documentation updates yet — feature must be validated first
- Do NOT add telemetry or analytics in initial implementation
Phase 6: Transcript Clearing Optimization (Optional, After Validation)
What to implement
- After observation injection is working, add transcript clearing:
- After successful observation injection, clear the large
tool_inputfrom Claude's transcript JSONL - This is the actual token savings mechanism — compressed observation replaces raw tool data
- After successful observation injection, clear the large
- Read from old branch:
git show beta/endless-mode:src/hooks/context-injection.tsforclearToolInputInTranscript()
Files to modify
src/hooks/save-hook.ts— add transcript clearing after successful injectionsrc/hooks/transcript-clearer.ts(NEW) — utility for JSONL manipulation
Verification
- Token count decreases after observation injection
- Transcript JSONL remains valid after clearing
- Claude Code doesn't break when transcript entries are modified
Anti-patterns
- Do NOT clear transcript if observation injection failed — leave raw data intact
- Do NOT modify transcript entries other than the current tool use
- Do NOT implement until Phase 5 validation is complete
Decisions Needed from User
- Branch name:
feature/endless-mode-v2(proposed) — acceptable? - Scope: Phases 1-5 are core. Phase 6 is optional. Should Phase 6 be included?
- Pre-tool-use hook: The old branch had a separate PreToolUse hook to send tool_use_id before execution. The PostToolUse hook already receives tool_use_id from Claude Code. Do we need PreToolUse, or is PostToolUse sufficient?