Compare commits

...

9 Commits

Author SHA1 Message Date
Alex Newman cd05b626a7 chore: bump version to 10.4.2
Publish to npm / publish (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:32:51 -05:00
Alex Newman 04e320b190 fix: add CLAUDE_PLUGIN_ROOT fallback for Stop hooks (#1215)
Upstream Claude Code bug (anthropics/claude-code#24529) leaves
CLAUDE_PLUGIN_ROOT unset for Stop hooks on macOS and ALL hooks
on Linux. Two-layer defense:

1. Shell-level: hooks.json commands now use inline fallback
   _R="${CLAUDE_PLUGIN_ROOT}"; [ -z "$_R" ] && _R="$HOME/...";
   falling back to the known marketplace install path.

2. Script-level: bun-runner.js self-resolves plugin root from
   its own filesystem location via import.meta.url, and fixes
   broken /scripts/... paths that result from empty expansion.

Added test to verify all hook commands include the fallback path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 17:36:51 -05:00
Alex Newman 9c187d6261 fix: resolve PostToolUse hook crashes and 5s latency (#1220)
Three compounding bugs caused hook failures:

1. Missing break statements in worker-service.ts switch — if async
   code threw before process.exit(), execution fell through to
   subsequent cases. Added break to all 7 cases missing them.

2. Unhandled promise rejection on main() — added .catch() that logs
   the error and exits 0 (per project exit code strategy: don't block
   Claude Code or leave Windows Terminal tabs open).

3. Redundant start commands in hooks.json — PostToolUse,
   UserPromptSubmit, and Stop groups each had a standalone start
   command that was redundant (the hook case already calls
   ensureWorkerStarted internally). The redundant start also caused
   5s latency via bun-runner.js collectStdin() timeout since Claude
   Code never closes stdin.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 17:27:10 -05:00
Alex Newman 494f681cbf docs: update CHANGELOG.md for v10.4.1 2026-02-23 22:13:35 -05:00
Alex Newman 4144010264 chore: bump version to 10.4.1
Publish to npm / publish (push) Has been cancelled
2026-02-23 22:13:11 -05:00
Alex Newman d482f3ed76 chore: bump version to 10.4.1 2026-02-23 22:10:38 -05:00
Alex Newman 3c4486e69e feat: convert make-plan and do commands to skills (#1216) 2026-02-23 22:08:21 -05:00
alan e0fec4bad7 feat: add terminal output control for SessionStart context (#1143)
* feat: add terminal output control for SessionStart context

Add CLAUDE_MEM_CONTEXT_SHOW_TERMINAL_OUTPUT setting to control whether
context is displayed in the terminal at SessionStart.

When set to "false", the terminal remains clean at startup while
context is still injected into Claude's system prompt. This allows
users who find the context output verbose to disable it without
losing the automatic context injection.

Defaults to "true" for backward compatibility.

Changes:
- Add CLAUDE_MEM_CONTEXT_SHOW_TERMINAL_OUTPUT to SettingsDefaultsManager
- Check setting in context handler before setting systemMessage
- Update settings file format to include new option

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* fix: use USER_SETTINGS_PATH and skip color fetch when disabled

Address PR feedback from automated review:

1. Use shared USER_SETTINGS_PATH constant instead of hardcoded path
   - Respects custom CLAUDE_MEM_DATA_DIR override
   - Consistent with other handlers (session-init, observation)

2. Skip color fetch when terminal output disabled
   - Check setting before making HTTP requests
   - Saves network round-trip on every session start

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: Alan Dong <adong@Alans-MacBook-Pro.local>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-23 21:05:05 -05:00
Alex Newman f5a873ffdc docs: update CHANGELOG.md for v10.4.0 2026-02-23 19:39:59 -05:00
25 changed files with 762 additions and 414 deletions
+1 -1
View File
@@ -10,7 +10,7 @@
"plugins": [
{
"name": "claude-mem",
"version": "10.4.0",
"version": "10.4.2",
"source": "./plugin",
"description": "Persistent memory system for Claude Code - context compression across sessions"
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "claude-mem",
"version": "10.2.5",
"version": "10.4.1",
"description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions",
"author": {
"name": "Alex Newman"
+214
View File
@@ -0,0 +1,214 @@
# 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:
1. The PostToolUse hook waits for the SDK agent to process the observation
2. The processed observation (title, narrative, facts) is injected back into Claude's context via `additionalContext`
3. Large tool inputs are cleared from the transcript to save tokens
4. 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 pattern
- `git show beta/endless-mode:src/hooks/context-injection.ts` — observation formatting
- `git show beta/endless-mode:src/hooks/pre-tool-use-hook.ts` — tool_use_id tracking
- `git 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 format
- `src/services/worker/SessionManager.ts:21-100` — current session management
- `src/services/worker/SDKAgent.ts:43-150` — current SDK agent flow, event emission
- `src/services/worker/http/routes/SessionRoutes.ts:498-573` — current observation endpoint
- `src/services/sqlite/SessionStore.ts:1503-1560` — current storeObservation
- `src/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 `PreToolUse` hook type is available in Claude Code plugin spec
- Check `additionalContext` field 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 TEXT` column 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 optional `tool_use_id?: string`
### Files to modify
- `src/services/sqlite/SessionStore.ts` — migration + store method
- `src/services/sqlite/observations/types.ts` — add tool_use_id to StoreObservationResult
- `src/types/transcript.ts` — verify ToolResultContent.tool_use_id matches Claude's format
### Verification
- `npm run build` succeeds
- 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.ts` DEFAULTS (~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`: Add `waitForNextObservation(sessionDbId, toolUseId, timeoutMs)` method
- Uses existing `sessionQueues` EventEmitter infrastructure
- Waits for `observation_saved` event matching toolUseId
- Returns the observation or null on timeout
- In `SDKAgent.ts`: After `storeObservation()` call, emit `observation_saved` event with observation data and toolUseId
- In `SessionRoutes.ts`:
- Accept `tool_use_id` in observation POST body
- Accept `wait_until_observation_is_saved=true` query parameter
- When waiting: call `SessionManager.waitForNextObservation()` before responding
- When not waiting (default): existing fire-and-forget behavior
### Files to modify
- `src/services/worker/SessionManager.ts`
- `src/services/worker/SDKAgent.ts`
- `src/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=true` and 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:
1. Check if endless mode is enabled via settings
2. Extract `tool_use_id` from the hook input (Claude Code provides this)
3. If endless mode ON: POST observation with `wait_until_observation_is_saved=true` and `tool_use_id`
4. Receive processed observation in HTTP response
5. Format observation as markdown (copy pattern from old `context-injection.ts`)
6. Return hook response with `additionalContext` field containing formatted observation
7. If endless mode OFF: existing fire-and-forget behavior (unchanged)
- Create `src/hooks/observation-formatter.ts` utility 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` — add `additionalContext` support 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:
1. Enable endless mode in settings.json
2. Start a Claude Code session
3. Execute tool uses and verify observations appear in context
4. Verify non-endless mode is unaffected
- Add basic unit tests in `tests/endless-mode/`
### Verification checklist
- [ ] `npm run build` succeeds 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_input` from Claude's transcript JSONL
- This is the actual token savings mechanism — compressed observation replaces raw tool data
- Read from old branch: `git show beta/endless-mode:src/hooks/context-injection.ts` for `clearToolInputInTranscript()`
### Files to modify
- `src/hooks/save-hook.ts` — add transcript clearing after successful injection
- `src/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
1. **Branch name**: `feature/endless-mode-v2` (proposed) — acceptable?
2. **Scope**: Phases 1-5 are core. Phase 6 is optional. Should Phase 6 be included?
3. **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?
+231
View File
@@ -0,0 +1,231 @@
# Hook Bugs Investigation & Fix Plan
## Problem Summary
Two open issues report hook failures affecting users on v10.4.0+:
### Issue #1215 — Stop hooks fail: `${CLAUDE_PLUGIN_ROOT}` not injected
- **Root cause**: Upstream Claude Code bug — `${CLAUDE_PLUGIN_ROOT}` is not set when Claude Code executes Stop hooks
- **Scope**: On macOS, only Stop hooks affected. On Linux (Claude Code v2.1.51), ALL hooks affected
- **Upstream refs**: `anthropics/claude-code#24529`, `anthropics/claude-code#27145`
- **Impact**: Session-end summarization and session-complete never run
### Issue #1220 — PostToolUse hooks crash on stdin
- **Bug 1**: `start` command exits 1 when stdin has data (every PostToolUse call sends stdin to all commands in the hook group, including `start` which doesn't need it)
- **Bug 2**: `observation` command crashes on payloads > ~350 bytes
- **Impact**: Every tool call produces 2x `PostToolUse:<tool> hook error` messages; observation data never processed
## Root Cause Analysis
### Issue #1215 (CLAUDE_PLUGIN_ROOT)
This is an **upstream Claude Code bug**, not a regression we introduced. The `${CLAUDE_PLUGIN_ROOT}` variable is supposed to be set by Claude Code's hook executor for all hook types, but Stop hooks don't receive it. Our hooks.json uses this variable in all commands:
```
node "${CLAUDE_PLUGIN_ROOT}/scripts/bun-runner.js" "${CLAUDE_PLUGIN_ROOT}/scripts/worker-service.cjs" ...
```
When not set, the path resolves to `/scripts/bun-runner.js` which doesn't exist.
### Issue #1220 (stdin crashes) — ROOT CAUSE IDENTIFIED
Three compounding code-level bugs:
**1. Missing `break` statements in switch — `src/services/worker-service.ts:1022-1204`**
Only the `hook` case (line 1142) has a `break`. All 7 other cases (`start`, `stop`, `restart`, `status`, `cursor`, `generate`, `clean`) rely on `process.exit()` to prevent fall-through. This is fragile — if any async operation throws before `process.exit()` is reached, execution falls through to the next case. For `start`, if `ensureWorkerStarted()` throws, it falls through into `stop``restart` → etc.
**2. Unhandled promise rejection — `src/services/worker-service.ts:1213`**
`main()` is called as `Hge && Fge()` (compiled) without a `.catch()`. The `ensureWorkerStarted()` function CAN throw — specifically via `getInstalledPluginVersion()` in `src/services/infrastructure/HealthMonitor.ts:132` which calls `readFileSync()` and can throw on non-ENOENT/EBUSY errors. An unhandled rejection causes Bun to exit with code 1 silently — matching the reported symptoms exactly.
**3. Redundant `start` command in hooks.json — `plugin/hooks/hooks.json:65`**
The PostToolUse hook group has a standalone `start` command that receives stdin it doesn't need. This is redundant because the `hook` case at `worker-service.ts:1101` already calls `ensureWorkerStarted()` internally. The extra `start` command adds latency (bun-runner.js waits up to 5s for stdin EOF via `collectStdin()`) and triggers the crash path described above.
**Why Bug 2 (large payloads) manifests at ~350 bytes:**
The same unhandled-rejection chain. When `ensureWorkerStarted()` inside the `hook` case throws before `hookCommand()` reads stdin, the process exits 1. Larger payloads affect the timing of stdin buffering vs. the concurrent HTTP health check calls, making the throw more likely to occur before stdin is fully consumed.
## Phases
### Phase 0: Documentation Discovery & Reproduction
**Tasks:**
1. Read Claude Code's hook documentation to understand the stdin contract:
- Does Claude Code pass stdin to all commands in a hook group, or only specific ones?
- Does Claude Code close stdin after writing, or leave it open?
- What are the expected exit code semantics?
2. Check Claude Code upstream issues for any resolution on CLAUDE_PLUGIN_ROOT:
- `anthropics/claude-code#24529`
- `anthropics/claude-code#27145`
3. Reproduce issue #1220 locally:
```bash
# Bug 1: start with stdin
echo '{"tool_name":"Read","tool_response":"test"}' | bun plugin/scripts/worker-service.cjs start
echo $? # Expected: 1 (broken), should be: 0
# Bug 2: observation with large payload
python3 -c "import json; print(json.dumps({'tool_name':'Read','tool_response':'x'*400,'session_id':'test','cwd':'/tmp'}))" | bun plugin/scripts/worker-service.cjs hook claude-code observation
echo $? # Expected: 1 (broken), should be: 0
```
4. Check `bun-runner.js` stdin timeout behavior:
```bash
# Time how long the start command takes through bun-runner
time echo '{}' | node plugin/scripts/bun-runner.js plugin/scripts/worker-service.cjs start
# If this takes ~5s, the collectStdin timeout is the bottleneck
```
**Verification:** Issue #1220 bugs reproduced locally with exact exit codes documented.
### Phase 1: Fix the three root causes (#1220)
**Fix 1: Add `break` statements to all switch cases**
File: `src/services/worker-service.ts:1022-1204`
Add `break` after every case in the switch statement. Currently only the `hook` case has one. Every other case relies on `process.exit()` which is fragile if the preceding async code throws.
```typescript
case 'start': {
const success = await ensureWorkerStarted(port);
if (success) {
exitWithStatus('ready');
} else {
exitWithStatus('error', 'Failed to start worker');
}
break; // ADD THIS
}
case 'stop': {
// ...
process.exit(0);
break; // ADD THIS (defensive, even after process.exit)
}
// ... same for restart, status, cursor, generate, clean
```
**Fix 2: Add `.catch()` to `main()` invocation**
File: `src/services/worker-service.ts:1213`
The compiled code calls `Fge()` (main) without error handling. Add a catch:
```typescript
if (isMainModule) {
main().catch((error) => {
logger.error('SYSTEM', 'Fatal error in main', {}, error instanceof Error ? error : undefined);
process.exit(0); // Exit 0: don't block Claude Code, don't leave Windows Terminal tabs open
});
}
```
**Fix 3: Remove redundant `start` command from hook groups**
File: `plugin/hooks/hooks.json`
Remove the standalone `start` command from PostToolUse, UserPromptSubmit, and Stop hook groups. The `hook` case in worker-service.ts already calls `ensureWorkerStarted()` internally (line 1101), making the separate `start` command redundant. This also eliminates:
- The 5s stdin timeout delay in bun-runner.js `collectStdin()`
- The stdin-crash path entirely
Before:
```json
"PostToolUse": [{
"matcher": "*",
"hooks": [
{ "command": "... worker-service.cjs start", "timeout": 60 },
{ "command": "... worker-service.cjs hook claude-code observation", "timeout": 120 }
]
}]
```
After:
```json
"PostToolUse": [{
"matcher": "*",
"hooks": [
{ "command": "... worker-service.cjs hook claude-code observation", "timeout": 120 }
]
}]
```
Apply the same removal to UserPromptSubmit and Stop groups.
**Files to modify:**
- `src/services/worker-service.ts` — add break statements + .catch() on main()
- `plugin/hooks/hooks.json` — remove redundant `start` commands from PostToolUse, UserPromptSubmit, Stop
**Verification:**
```bash
# Bug 1 fixed — start no longer called from hooks, but also safe if called directly
echo '{"tool_name":"Read","tool_response":"test"}' | bun plugin/scripts/worker-service.cjs start
echo $? # Should be 0
# Bug 2 fixed — observation handles large payloads
python3 -c "import json; print(json.dumps({'tool_name':'Read','tool_response':'x'*2000,'session_id':'test','cwd':'/tmp'}))" | bun plugin/scripts/worker-service.cjs hook claude-code observation
echo $? # Should be 0
# No error messages in Claude Code UI during normal tool use
```
### Phase 2: Workaround for CLAUDE_PLUGIN_ROOT (#1215)
Since this is an upstream Claude Code bug, our options are limited:
**Option 1: Resolve paths at Setup time (preferred)**
In the `Setup` hook (which DOES receive CLAUDE_PLUGIN_ROOT), write the resolved path to a file:
```bash
# In setup.sh
echo "${CLAUDE_PLUGIN_ROOT}" > ~/.claude-mem/.plugin-root
```
Then in bun-runner.js, fall back to reading this file when CLAUDE_PLUGIN_ROOT is empty.
**Option 2: Self-resolve using __dirname**
The scripts know their own location on disk. Instead of relying on CLAUDE_PLUGIN_ROOT, resolve the plugin root from the script's own path:
```javascript
const PLUGIN_ROOT = path.resolve(__dirname, '..');
```
Then use this instead of the environment variable.
**Option 3: Document the workaround**
Add to README/docs: users can run `sed` to replace `${CLAUDE_PLUGIN_ROOT}` with absolute paths in hooks.json.
**Files to modify:**
- `plugin/scripts/bun-runner.js` — add PLUGIN_ROOT self-resolution fallback
- `plugin/hooks/hooks.json` — potentially use self-resolving paths
- Docs — document the upstream issue and workaround
**Anti-patterns to avoid:**
- Don't hardcode absolute paths in hooks.json (varies per installation)
- Don't remove CLAUDE_PLUGIN_ROOT usage entirely (it works on most platforms)
**Verification:**
```bash
# Simulate missing CLAUDE_PLUGIN_ROOT
unset CLAUDE_PLUGIN_ROOT
node plugin/scripts/bun-runner.js plugin/scripts/worker-service.cjs start
echo $? # Should be 0 (falls back to self-resolved path)
```
### Phase 3: Verification & Testing
1. Run existing hook tests:
```bash
npm test -- --grep "hook"
```
2. Verify all 5 hook types work end-to-end:
- SessionStart: context injection
- UserPromptSubmit: session-init
- PostToolUse: observation (small AND large payloads)
- Stop: summarize + session-complete (if CLAUDE_PLUGIN_ROOT is available)
3. Check for regressions:
- No error messages in Claude Code UI during normal operation
- Observations are stored correctly
- Worker starts reliably
4. Build and verify:
```bash
npm run build-and-sync
```
**Anti-patterns to avoid:**
- Don't suppress errors that indicate real bugs (the stderr suppression from PR #1214 may be hiding issues)
- Don't add try/catch blocks that swallow errors silently during development
+78 -120
View File
@@ -2,6 +2,84 @@
All notable changes to claude-mem.
## [v10.4.1] - 2026-02-24
### Refactor
- **Skills Conversion**: Converted `/make-plan` and `/do` commands into first-class skills in `plugin/skills/`.
- **Organization**: Centralized planning and execution instructions alongside `mem-search`.
- **Compatibility**: Added symlinks for `openclaw/skills/` to ensure seamless integration with OpenClaw.
### Chore
- **Version Bump**: Aligned all package and plugin manifests to v10.4.1.
## [v10.4.0] - 2026-02-24
## v10.4.0 — Stability & Platform Hardening
Massive reliability release: 30+ root-cause bug fixes across 10 triage phases, plus new features for agent attribution, Chroma control, and broader platform support.
### New Features
- **Session custom titles** — Agents can now set `custom_title` on sessions for attribution (migration 23, new endpoint)
- **Chroma toggle** — `CLAUDE_MEM_CHROMA_ENABLED` setting allows SQLite-only fallback mode (#707)
- **Plugin disabled state** — Early exit check in all hook entry points when plugin is disabled (#781)
- **Context re-injection guard** — `contextInjected` session flag prevents re-injecting context on every UserPromptSubmit turn (#1079)
### Bug Fixes
#### Data Integrity
- SHA-256 content-hash deduplication on observation INSERT (migration 22 with backfill + index)
- Project name collision fix: `getCurrentProjectName()` now returns `parent/basename`
- Empty project string guard with cwd-derived fallback
- Stuck `isProcessing` reset: pending work older than 5 minutes auto-clears
#### ChromaDB
- Python version pinning in uvx args for both local and remote mode (#1196, #1206, #1208)
- Windows backslash-to-forward-slash path conversion for `--data-dir` (#1199)
- Metadata sanitization: filter null/undefined/empty values in `addDocuments()` (#1183, #1188)
- Transport error auto-reconnect in `callTool()` (#1162)
- Stale transport retry with transparent reconnect (#1131)
#### Hook Lifecycle
- Suppress `process.stderr.write` in `hookCommand()` to prevent diagnostic output showing as error UI (#1181)
- Route all `console.error()` through logger instead of stderr
- Verified all 7 handlers return `suppressOutput: true` (#598, #784)
#### Worker Lifecycle
- PID file mtime guard prevents concurrent restart storms (#1145)
- `getInstalledPluginVersion()` ENOENT/EBUSY handling (#1042)
#### SQLite Migrations
- Schema initialization always creates core tables via `CREATE TABLE IF NOT EXISTS`
- Migrations 5-7 check actual DB state instead of version tracking (fixes version collision between old/new migration systems, #979)
- Crash-safe temp table rebuilds
#### Platform Support
- **Windows**: `cmd.exe /c` uvx spawn, PowerShell `$_` elimination with WQL filtering, `windowsHide: true`, FTS5 runtime probe with fallback (#1190, #1192, #1199, #1024, #1062, #1048, #791)
- **Cursor IDE**: Adapter field fallbacks, tolerant session-init validation (#838, #1049)
- **Codex CLI**: `session_id` fallbacks, unknown platform tolerance, undefined guard (#744)
#### API & Infrastructure
- `/api/logs` OOM fix: tail-read replaces full-file `readFileSync` (64KB expanding chunks, 10MB cap, #1203)
- CORS: explicit methods and allowedHeaders (#1029)
- MCP type coercion for batch endpoints: string-to-array for `ids` and `memorySessionIds`
- Defensive observation error handling returns 200 on recoverable errors instead of 500
- `.git/` directory write guard on all 4 CLAUDE.md/AGENTS.md write sites (#1165)
#### Stale AbortController Fix
- `lastGeneratorActivity` timestamp tracking with 30s timeout (#1099)
- Stale generator detection + abort + restart in `ensureGeneratorRunning`
- `AbortSignal.timeout(30000)` in `deleteSession` prevents indefinite hang
### Installation
- `resolveRoot()` replaces hardcoded marketplace path using `CLAUDE_PLUGIN_ROOT` env var (#1128, #1166)
- `installCLI()` path correction and `verifyCriticalModules()` post-install check
- Build-time distribution verification for skills, hooks, and plugin manifest (#1187)
### Testing
- 50+ new tests across hook lifecycle, context re-injection, plugin distribution, migration runner, data integrity, stale abort controller, logs tail-read, CORS, MCP type coercion, and smart-install
- 68 files changed, ~4200 insertions, ~900 deletions
## [v10.3.3] - 2026-02-23
### Bug Fixes
@@ -1319,123 +1397,3 @@ Fixed a critical memory leak where Claude SDK child processes were never termina
Thanks to @yonnock for the detailed bug report and investigation in #499!
## [v8.5.1] - 2025-12-30
## Bug Fix
**Fixed**: Migration 17 column rename failing for databases in intermediate states (#481)
### Problem
Migration 17 renamed session ID columns but used a single check to determine if ALL tables were migrated. This caused errors for databases in partial migration states:
- `no such column: sdk_session_id` (when columns already renamed)
- `table observations has no column named memory_session_id` (when not renamed)
### Solution
- Rewrote migration 17 to check **each table individually** before renaming
- Added `safeRenameColumn()` helper that handles all edge cases gracefully
- Handles all database states: fresh, old, and partially migrated
### Who was affected
- Users upgrading from pre-v8.2.6 versions
- Users whose migration was interrupted (crash, restart, etc.)
- Users who restored database from backup
---
🤖 Generated with [Claude Code](https://claude.com/claude-code)
## [v8.5.0] - 2025-12-30
# Cursor Support Now Available 🎉
This is a major release introducing **full Cursor IDE support**. Claude-mem now works with Cursor, bringing persistent AI memory to Cursor users with or without a Claude Code subscription.
## Highlights
**Give Cursor persistent memory.** Every Cursor session starts fresh - your AI doesn't remember what it worked on yesterday. Claude-mem changes that. Your agent builds cumulative knowledge about your codebase, decisions, and patterns over time.
### Works Without Claude Code
You can now use claude-mem with Cursor using free AI providers:
- **Gemini** (recommended): 1,500 free requests/day, no credit card required
- **OpenRouter**: Access to 100+ models including free options
- **Claude SDK**: For Claude Code subscribers
### Cross-Platform Support
Full support for all major platforms:
- **macOS**: Bash scripts with `jq` and `curl`
- **Linux**: Same toolchain as macOS
- **Windows**: Native PowerShell scripts, no WSL required
## New Features
### Interactive Setup Wizard (`bun run cursor:setup`)
A guided installer that:
- Detects your environment (Claude Code present or not)
- Helps you choose and configure an AI provider
- Installs Cursor hooks automatically
- Starts the worker service
- Verifies everything is working
### Cursor Lifecycle Hooks
Complete hook integration with Cursor's native hook system:
- `session-init.sh/.ps1` - Session start with context injection
- `user-message.sh/.ps1` - User prompt capture
- `save-observation.sh/.ps1` - Tool usage logging
- `save-file-edit.sh/.ps1` - File edit tracking
- `session-summary.sh/.ps1` - Session end summary
- `context-inject.sh/.ps1` - Load relevant history
### Context Injection via `.cursor/rules`
Relevant past context is automatically injected into Cursor sessions via the `.cursor/rules/claude-mem-context.mdc` file, giving your AI immediate awareness of prior work.
### Project Registry
Multi-project support with automatic project detection:
- Projects registered in `~/.claude-mem/cursor-projects.json`
- Context automatically scoped to current project
- Works across multiple workspaces simultaneously
### MCP Search Tools
Full MCP server integration for Cursor:
- `search` - Find observations by query, date, type
- `timeline` - Get context around specific observations
- `get_observations` - Fetch full details for filtered IDs
## New Commands
| Command | Description |
|---------|-------------|
| `bun run cursor:setup` | Interactive setup wizard |
| `bun run cursor:install` | Install Cursor hooks |
| `bun run cursor:uninstall` | Remove Cursor hooks |
| `bun run cursor:status` | Check hook installation status |
## Documentation
Full documentation available at [docs.claude-mem.ai/cursor](https://docs.claude-mem.ai/cursor):
- Cursor Integration Overview
- Gemini Setup Guide (free tier)
- OpenRouter Setup Guide
- Troubleshooting
## Getting Started
### For Cursor-Only Users (No Claude Code)
```bash
git clone https://github.com/thedotmack/claude-mem.git
cd claude-mem && bun install && bun run build
bun run cursor:setup
```
### For Claude Code Users
```bash
/plugin marketplace add thedotmack/claude-mem
/plugin install claude-mem
claude-mem cursor install
```
**Full Changelog**: https://github.com/thedotmack/claude-mem/compare/v8.2.10...v8.5.0
+4
View File
@@ -14,6 +14,10 @@ Claude-mem is a Claude Code plugin providing persistent memory across sessions.
**Search Skill** (`plugin/skills/mem-search/SKILL.md`) - HTTP API for searching past work, auto-invoked when users ask about history
**Planning Skill** (`plugin/skills/make-plan/SKILL.md`) - Orchestrator instructions for creating phased implementation plans with documentation discovery
**Execution Skill** (`plugin/skills/do/SKILL.md`) - Orchestrator instructions for executing phased plans using subagents
**Chroma** (`src/services/sync/ChromaSync.ts`) - Vector embeddings for semantic search
**Viewer UI** (`src/ui/viewer/`) - React interface at http://localhost:37777, built to `plugin/ui/viewer.html`
+2 -2
View File
@@ -3,10 +3,10 @@
"name": "Claude-Mem (Persistent Memory)",
"description": "Official OpenClaw plugin for Claude-Mem. Records observations from embedded runner sessions and streams them to messaging channels.",
"kind": "memory",
"version": "1.0.0",
"version": "10.4.1",
"author": "thedotmack",
"homepage": "https://claude-mem.com",
"skills": ["skills/make-plan", "skills/do-plan"],
"skills": ["skills/make-plan", "skills/do"],
"configSchema": {
"type": "object",
"additionalProperties": false,
+1
View File
@@ -0,0 +1 @@
../../../plugin/skills/do/SKILL.md
-63
View File
@@ -1,63 +0,0 @@
---
name: make-plan
description: Create a detailed, phased implementation plan with documentation discovery. Use when asked to plan a feature, task, or multi-step implementation — especially before executing with do-plan.
---
# Make Plan
You are an ORCHESTRATOR. Create an LLM-friendly plan in phases that can be executed consecutively in new chat contexts.
## Delegation Model
Use subagents for *fact gathering and extraction* (docs, examples, signatures, grep results). Keep *synthesis and plan authoring* with the orchestrator (phase boundaries, task framing, final wording). If a subagent report is incomplete or lacks evidence, re-check with targeted reads/greps before finalizing.
### Subagent Reporting Contract (MANDATORY)
Each subagent response must include:
1. Sources consulted (files/URLs) and what was read
2. Concrete findings (exact API names/signatures; exact file paths/locations)
3. Copy-ready snippet locations (example files/sections to copy)
4. "Confidence" note + known gaps (what might still be missing)
Reject and redeploy the subagent if it reports conclusions without sources.
## Plan Structure
### Phase 0: Documentation Discovery (ALWAYS FIRST)
Before planning implementation, deploy "Documentation Discovery" subagents to:
1. Search for and read relevant documentation, examples, and existing patterns
2. Identify the actual APIs, methods, and signatures available (not assumed)
3. Create a brief "Allowed APIs" list citing specific documentation sources
4. Note any anti-patterns to avoid (methods that DON'T exist, deprecated parameters)
The orchestrator consolidates findings into a single Phase 0 output.
### Each Implementation Phase Must Include
1. **What to implement** — Frame tasks to COPY from docs, not transform existing code
- Good: "Copy the V2 session pattern from docs/examples.ts:45-60"
- Bad: "Migrate the existing code to V2"
2. **Documentation references** — Cite specific files/lines for patterns to follow
3. **Verification checklist** — How to prove this phase worked (tests, grep checks)
4. **Anti-pattern guards** — What NOT to do (invented APIs, undocumented params)
### Final Phase: Verification
1. Verify all implementations match documentation
2. Check for anti-patterns (grep for known bad patterns)
3. Run tests to confirm functionality
## Key Principles
- Documentation Availability ≠ Usage: Explicitly require reading docs
- Task Framing Matters: Direct agents to docs, not just outcomes
- Verify > Assume: Require proof, not assumptions about APIs
- Session Boundaries: Each phase should be self-contained with its own doc references
## Anti-Patterns to Prevent
- Inventing API methods that "should" exist
- Adding parameters not in documentation
- Skipping verification steps
- Assuming structure without checking examples
+1
View File
@@ -0,0 +1 @@
../../../plugin/skills/make-plan/SKILL.md
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "claude-mem",
"version": "10.4.0",
"version": "10.4.2",
"description": "Memory compression system for Claude Code - persist context across sessions",
"keywords": [
"claude",
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "claude-mem",
"version": "10.4.0",
"version": "10.4.2",
"description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions",
"author": {
"name": "Alex Newman"
-43
View File
@@ -1,43 +0,0 @@
---
description: "Execute a plan using subagents for implementation"
argument-hint: "[task or plan reference]"
---
You are an ORCHESTRATOR.
Primary instruction: deploy subagents to execute *all* work for #$ARGUMENTS.
Do not do the work yourself except to coordinate, route context, and verify that each subagent completed its assigned checklist.
Deploy subagents to execute each phase of #$ARGUMENTS independently and consecutively. For every checklist item below, explicitly deploy (or reuse) a subagent responsible for that item and record its outcome before proceeding.
## Execution Protocol (Orchestrator-Driven)
Orchestrator rules:
- Each phase uses fresh subagents where noted (or when context is large/unclear).
- The orchestrator assigns one clear objective per subagent and requires evidence (commands run, outputs, files changed).
- Do not advance to the next step until the assigned subagent reports completion and the orchestrator confirms it matches the plan.
### During Each Phase:
Deploy an "Implementation" subagent to:
1. Execute the implementation as specified
2. COPY patterns from documentation, don't invent
3. Cite documentation sources in code comments when using unfamiliar APIs
4. If an API seems missing, STOP and verify - don't assume it exists
### After Each Phase:
Deploy subagents for each post-phase responsibility:
1. **Run verification checklist** - Deploy a "Verification" subagent to prove the phase worked
2. **Anti-pattern check** - Deploy an "Anti-pattern" subagent to grep for known bad patterns from the plan
3. **Code quality review** - Deploy a "Code Quality" subagent to review changes
4. **Commit only if verified** - Deploy a "Commit" subagent *only after* verification passes; otherwise, do not commit
### Between Phases:
Deploy a "Branch/Sync" subagent to:
- Push to working branch after each verified phase
- Prepare the next phase handoff so the next phase's subagents start fresh but have plan context
## Failure Modes to Prevent
- Don't invent APIs that "should" exist - verify against docs
- Don't add undocumented parameters - copy exact signatures
- Don't skip verification - deploy a verification subagent and run the checklist
- Don't commit before verification passes (or without explicit orchestrator approval)
-66
View File
@@ -1,66 +0,0 @@
---
description: "Create an implementation plan with documentation discovery"
argument-hint: "[feature or task description]"
---
You are an ORCHESTRATOR.
Create an LLM-friendly plan in phases that can be executed consecutively in new chat contexts.
Delegation model (because subagents can under-report):
- Use subagents for *fact gathering and extraction* (docs, examples, signatures, grep results).
- Keep *synthesis and plan authoring* with the orchestrator (phase boundaries, task framing, final wording).
- If a subagent report is incomplete or lacks evidence, the orchestrator must re-check with targeted reads/greps before finalizing the plan.
Subagent reporting contract (MANDATORY):
- Each subagent response must include:
1) Sources consulted (files/URLs) and what was read
2) Concrete findings (exact API names/signatures; exact file paths/locations)
3) Copy-ready snippet locations (example files/sections to copy)
4) "Confidence" note + known gaps (what might still be missing)
- Reject and redeploy the subagent if it reports conclusions without sources.
## Plan Structure Requirements
### Phase 0: Documentation Discovery (ALWAYS FIRST)
Before planning implementation, you MUST:
Deploy one or more "Documentation Discovery" subagents to:
1. Search for and read relevant documentation, examples, and existing patterns
2. Identify the actual APIs, methods, and signatures available (not assumed)
3. Create a brief "Allowed APIs" list citing specific documentation sources
4. Note any anti-patterns to avoid (methods that DON'T exist, deprecated parameters)
Then the orchestrator consolidates their findings into a single Phase 0 output.
### Each Implementation Phase Must Include:
1. **What to implement** - Frame tasks to COPY from docs, not transform existing code
- Good: "Copy the V2 session pattern from docs/examples.ts:45-60"
- Bad: "Migrate the existing code to V2"
2. **Documentation references** - Cite specific files/lines for patterns to follow
3. **Verification checklist** - How to prove this phase worked (tests, grep checks)
4. **Anti-pattern guards** - What NOT to do (invented APIs, undocumented params)
Subagent-friendly split:
- Subagents can propose candidate doc references and verification commands.
- The orchestrator must write the final phase text, ensuring tasks are copy-based, scoped, and independently executable.
### Final Phase: Verification
1. Verify all implementations match documentation
2. Check for anti-patterns (grep for known bad patterns)
3. Run tests to confirm functionality
Delegation guidance:
- Deploy a "Verification" subagent to draft the checklist and commands.
- The orchestrator must review the checklist for completeness and ensure it maps to earlier phase outputs.
## Key Principles
- Documentation Availability ≠ Usage: Explicitly require reading docs
- Task Framing Matters: Direct agents to docs, not just outcomes
- Verify > Assume: Require proof, not assumptions about APIs
- Session Boundaries: Each phase should be self-contained with its own doc references
## Anti-Patterns to Prevent
- Inventing API methods that "should" exist
- Adding parameters not in documentation
- Skipping verification steps
- Assuming structure without checking examples
+8 -23
View File
@@ -7,7 +7,7 @@
"hooks": [
{
"type": "command",
"command": "${CLAUDE_PLUGIN_ROOT}/scripts/setup.sh",
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; \"$_R/scripts/setup.sh\"",
"timeout": 300
}
]
@@ -19,7 +19,7 @@
"hooks": [
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/smart-install.js\"",
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; node \"$_R/scripts/smart-install.js\"",
"timeout": 300
}
]
@@ -29,12 +29,12 @@
"hooks": [
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/bun-runner.js\" \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-service.cjs\" start",
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" start",
"timeout": 60
},
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/bun-runner.js\" \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-service.cjs\" hook claude-code context",
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code context",
"timeout": 60
}
]
@@ -45,12 +45,7 @@
"hooks": [
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/bun-runner.js\" \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-service.cjs\" start",
"timeout": 60
},
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/bun-runner.js\" \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-service.cjs\" hook claude-code session-init",
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code session-init",
"timeout": 60
}
]
@@ -62,12 +57,7 @@
"hooks": [
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/bun-runner.js\" \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-service.cjs\" start",
"timeout": 60
},
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/bun-runner.js\" \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-service.cjs\" hook claude-code observation",
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code observation",
"timeout": 120
}
]
@@ -78,17 +68,12 @@
"hooks": [
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/bun-runner.js\" \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-service.cjs\" start",
"timeout": 60
},
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/bun-runner.js\" \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-service.cjs\" hook claude-code summarize",
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code summarize",
"timeout": 120
},
{
"type": "command",
"command": "node \"${CLAUDE_PLUGIN_ROOT}/scripts/bun-runner.js\" \"${CLAUDE_PLUGIN_ROOT}/scripts/worker-service.cjs\" hook claude-code session-complete",
"command": "_R=\"${CLAUDE_PLUGIN_ROOT}\"; [ -z \"$_R\" ] && _R=\"$HOME/.claude/plugins/marketplaces/thedotmack/plugin\"; node \"$_R/scripts/bun-runner.js\" \"$_R/scripts/worker-service.cjs\" hook claude-code session-complete",
"timeout": 30
}
]
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "claude-mem-plugin",
"version": "10.4.0",
"version": "10.4.2",
"private": true,
"description": "Runtime dependencies for claude-mem bundled hooks",
"type": "module",
+29 -1
View File
@@ -13,11 +13,36 @@
*/
import { spawnSync, spawn } from 'child_process';
import { existsSync, readFileSync } from 'fs';
import { join } from 'path';
import { join, dirname, resolve } from 'path';
import { homedir } from 'os';
import { fileURLToPath } from 'url';
const IS_WINDOWS = process.platform === 'win32';
// Self-resolve plugin root when CLAUDE_PLUGIN_ROOT is not set by Claude Code.
// Upstream bug: anthropics/claude-code#24529 — Stop hooks (and on Linux, all hooks)
// don't receive CLAUDE_PLUGIN_ROOT, causing script paths to resolve to /scripts/...
// which doesn't exist. This fallback derives the plugin root from bun-runner.js's
// own filesystem location (this file lives in <plugin-root>/scripts/).
const __bun_runner_dirname = dirname(fileURLToPath(import.meta.url));
const RESOLVED_PLUGIN_ROOT = process.env.CLAUDE_PLUGIN_ROOT || resolve(__bun_runner_dirname, '..');
/**
* Fix script path arguments that were broken by empty CLAUDE_PLUGIN_ROOT.
* When CLAUDE_PLUGIN_ROOT is empty, "${CLAUDE_PLUGIN_ROOT}/scripts/foo.cjs"
* expands to "/scripts/foo.cjs" which doesn't exist. Detect this and rewrite
* the path using our self-resolved plugin root.
*/
function fixBrokenScriptPath(argPath) {
if (argPath.startsWith('/scripts/') && !existsSync(argPath)) {
const fixedPath = join(RESOLVED_PLUGIN_ROOT, argPath);
if (existsSync(fixedPath)) {
return fixedPath;
}
}
return argPath;
}
/**
* Find Bun executable - checks PATH first, then common install locations
*/
@@ -80,6 +105,9 @@ if (args.length === 0) {
process.exit(1);
}
// Fix broken script paths caused by empty CLAUDE_PLUGIN_ROOT (#1215)
args[0] = fixBrokenScriptPath(args[0]);
const bunPath = findBun();
if (!bunPath) {
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
---
name: do-plan
name: do
description: Execute a phased implementation plan using subagents. Use when asked to execute, run, or carry out a plan — especially one created by make-plan.
---
+63
View File
@@ -0,0 +1,63 @@
---
name: make-plan
description: Create a detailed, phased implementation plan with documentation discovery. Use when asked to plan a feature, task, or multi-step implementation — especially before executing with do.
---
# Make Plan
You are an ORCHESTRATOR. Create an LLM-friendly plan in phases that can be executed consecutively in new chat contexts.
## Delegation Model
Use subagents for *fact gathering and extraction* (docs, examples, signatures, grep results). Keep *synthesis and plan authoring* with the orchestrator (phase boundaries, task framing, final wording). If a subagent report is incomplete or lacks evidence, re-check with targeted reads/greps before finalizing.
### Subagent Reporting Contract (MANDATORY)
Each subagent response must include:
1. Sources consulted (files/URLs) and what was read
2. Concrete findings (exact API names/signatures; exact file paths/locations)
3. Copy-ready snippet locations (example files/sections to copy)
4. "Confidence" note + known gaps (what might still be missing)
Reject and redeploy the subagent if it reports conclusions without sources.
## Plan Structure
### Phase 0: Documentation Discovery (ALWAYS FIRST)
Before planning implementation, deploy "Documentation Discovery" subagents to:
1. Search for and read relevant documentation, examples, and existing patterns
2. Identify the actual APIs, methods, and signatures available (not assumed)
3. Create a brief "Allowed APIs" list citing specific documentation sources
4. Note any anti-patterns to avoid (methods that DON'T exist, deprecated parameters)
The orchestrator consolidates findings into a single Phase 0 output.
### Each Implementation Phase Must Include
1. **What to implement** — Frame tasks to COPY from docs, not transform existing code
- Good: "Copy the V2 session pattern from docs/examples.ts:45-60"
- Bad: "Migrate the existing code to V2"
2. **Documentation references** — Cite specific files/lines for patterns to follow
3. **Verification checklist** — How to prove this phase worked (tests, grep checks)
4. **Anti-pattern guards** — What NOT to do (invented APIs, undocumented params)
### Final Phase: Verification
1. Verify all implementations match documentation
2. Check for anti-patterns (grep for known bad patterns)
3. Run tests to confirm functionality
## Key Principles
- Documentation Availability ≠ Usage: Explicitly require reading docs
- Task Framing Matters: Direct agents to docs, not just outcomes
- Verify > Assume: Require proof, not assumptions about APIs
- Session Boundaries: Each phase should be self-contained with its own doc references
## Anti-Patterns to Prevent
- Inventing API methods that "should" exist
- Adding parameters not in documentation
- Skipping verification steps
- Assuming structure without checking examples
+10 -3
View File
@@ -10,6 +10,8 @@ import { ensureWorkerRunning, getWorkerPort } from '../../shared/worker-utils.js
import { getProjectContext } from '../../utils/project-name.js';
import { HOOK_EXIT_CODES } from '../../shared/hook-constants.js';
import { logger } from '../../utils/logger.js';
import { SettingsDefaultsManager } from '../../shared/SettingsDefaultsManager.js';
import { USER_SETTINGS_PATH } from '../../shared/paths.js';
export const contextHandler: EventHandler = {
async execute(input: NormalizedHookInput): Promise<HookResult> {
@@ -30,6 +32,10 @@ export const contextHandler: EventHandler = {
const context = getProjectContext(cwd);
const port = getWorkerPort();
// Check if terminal output should be shown (load settings early)
const settings = SettingsDefaultsManager.loadFromFile(USER_SETTINGS_PATH);
const showTerminalOutput = settings.CLAUDE_MEM_CONTEXT_SHOW_TERMINAL_OUTPUT === 'true';
// Pass all projects (parent + worktree if applicable) for unified timeline
const projectsParam = context.allProjects.join(',');
const url = `http://127.0.0.1:${port}/api/context/inject?projects=${encodeURIComponent(projectsParam)}`;
@@ -37,11 +43,11 @@ export const contextHandler: EventHandler = {
// Note: Removed AbortSignal.timeout due to Windows Bun cleanup issue (libuv assertion)
// Worker service has its own timeouts, so client-side timeout is redundant
try {
// Fetch both markdown (for Claude context) and colored (for user display) truly in parallel
// Fetch markdown (for Claude context) and optionally colored (for user display)
const colorUrl = `${url}&colors=true`;
const [response, colorResponse] = await Promise.all([
fetch(url),
fetch(colorUrl).catch(() => null)
showTerminalOutput ? fetch(colorUrl).catch(() => null) : Promise.resolve(null)
]);
if (!response.ok) {
@@ -60,7 +66,8 @@ export const contextHandler: EventHandler = {
const additionalContext = contextResult.trim();
const coloredTimeline = colorResult.trim();
const systemMessage = coloredTimeline
const systemMessage = showTerminalOutput && coloredTimeline
? `${coloredTimeline}\n\nView Observations Live @ http://localhost:${port}`
: undefined;
+11 -1
View File
@@ -1027,6 +1027,7 @@ async function main() {
} else {
exitWithStatus('error', 'Failed to start worker');
}
break;
}
case 'stop': {
@@ -1038,6 +1039,7 @@ async function main() {
removePidFile();
logger.info('SYSTEM', 'Worker stopped successfully');
process.exit(0);
break;
}
case 'restart': {
@@ -1074,6 +1076,7 @@ async function main() {
logger.info('SYSTEM', 'Worker restarted successfully');
process.exit(0);
break;
}
case 'status': {
@@ -1088,12 +1091,14 @@ async function main() {
console.log('Worker is not running');
}
process.exit(0);
break;
}
case 'cursor': {
const subcommand = process.argv[3];
const cursorResult = await handleCursorCommand(subcommand, process.argv.slice(4));
process.exit(cursorResult);
break;
}
case 'hook': {
@@ -1147,6 +1152,7 @@ async function main() {
const { generateClaudeMd } = await import('../cli/claude-md-commands.js');
const result = await generateClaudeMd(dryRun);
process.exit(result);
break;
}
case 'clean': {
@@ -1154,6 +1160,7 @@ async function main() {
const { cleanClaudeMd } = await import('../cli/claude-md-commands.js');
const result = await cleanClaudeMd(dryRun);
process.exit(result);
break;
}
case '--daemon':
@@ -1210,5 +1217,8 @@ const isMainModule = typeof require !== 'undefined' && typeof module !== 'undefi
: import.meta.url === `file://${process.argv[1]}` || process.argv[1]?.endsWith('worker-service');
if (isMainModule) {
main();
main().catch((error) => {
logger.error('SYSTEM', 'Fatal error in main', {}, error instanceof Error ? error : undefined);
process.exit(0); // Exit 0: don't block Claude Code, don't leave Windows Terminal tabs open
});
}
+2
View File
@@ -51,6 +51,7 @@ export interface SettingsDefaults {
// Feature Toggles
CLAUDE_MEM_CONTEXT_SHOW_LAST_SUMMARY: string;
CLAUDE_MEM_CONTEXT_SHOW_LAST_MESSAGE: string;
CLAUDE_MEM_CONTEXT_SHOW_TERMINAL_OUTPUT: string;
CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED: string;
// Process Management
CLAUDE_MEM_MAX_CONCURRENT_AGENTS: string; // Max concurrent Claude SDK agent subprocesses (default: 2)
@@ -112,6 +113,7 @@ export class SettingsDefaultsManager {
// Feature Toggles
CLAUDE_MEM_CONTEXT_SHOW_LAST_SUMMARY: 'true',
CLAUDE_MEM_CONTEXT_SHOW_LAST_MESSAGE: 'false',
CLAUDE_MEM_CONTEXT_SHOW_TERMINAL_OUTPUT: 'true',
CLAUDE_MEM_FOLDER_CLAUDEMD_ENABLED: 'false',
// Process Management
CLAUDE_MEM_MAX_CONCURRENT_AGENTS: '2', // Max concurrent Claude SDK agent subprocesses
@@ -81,6 +81,22 @@ describe('Plugin Distribution - hooks.json Integrity', () => {
}
}
});
it('should include CLAUDE_PLUGIN_ROOT fallback in all hook commands (#1215)', () => {
const hooksPath = path.join(projectRoot, 'plugin/hooks/hooks.json');
const parsed = JSON.parse(readFileSync(hooksPath, 'utf-8'));
const expectedFallbackPath = '$HOME/.claude/plugins/marketplaces/thedotmack/plugin';
for (const [eventName, matchers] of Object.entries(parsed.hooks)) {
for (const matcher of matchers as any[]) {
for (const hook of matcher.hooks) {
if (hook.type === 'command') {
expect(hook.command).toContain(expectedFallbackPath);
}
}
}
}
});
});
describe('Plugin Distribution - package.json Files Field', () => {