Compare commits
11 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 50d1dfb7ee | |||
| 0b034af98b | |||
| b43ad00f8b | |||
| dd1b812443 | |||
| ad3d236cec | |||
| 494f681cbf | |||
| 4144010264 | |||
| d482f3ed76 | |||
| 3c4486e69e | |||
| e0fec4bad7 | |||
| f5a873ffdc |
@@ -10,7 +10,7 @@
|
||||
"plugins": [
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "10.4.0",
|
||||
"version": "10.4.4",
|
||||
"source": "./plugin",
|
||||
"description": "Persistent memory system for Claude Code - context compression across sessions"
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -0,0 +1,736 @@
|
||||
# Plan: NPX Distribution + Universal IDE/CLI Coverage for claude-mem
|
||||
|
||||
## Problem
|
||||
|
||||
1. **Installation is slow and fragile**: Current install clones the full git repo, runs `npm install`, and builds from source. The npm package already ships pre-built artifacts.
|
||||
|
||||
2. **IDE coverage is limited**: claude-mem only supports Claude Code (plugin) and Cursor (hooks installer). The AI coding tools landscape has exploded — Gemini CLI (95k stars), OpenCode (110k stars), Windsurf (~1M users), Codex CLI, Antigravity, Goose, Crush, Copilot CLI, and more all support extensibility.
|
||||
|
||||
## Key Insights
|
||||
|
||||
- **npm package already has everything**: `plugin/` directory ships pre-built. No git clone or build needed.
|
||||
- **Transcript watcher already exists**: `src/services/transcripts/` has a fully built schema-based JSONL tailer. It just needs schemas for more tools.
|
||||
- **3 integration tiers exist**: (1) Hook/plugin-based (Claude Code, Gemini CLI, OpenCode, Windsurf, Codex CLI, OpenClaw), (2) MCP-based (Cursor, Copilot CLI, Antigravity, Goose, Crush, Roo Code), (3) Transcript-based (anything with structured log files).
|
||||
- **OpenClaw plugin already built**: Full plugin at `openclaw/src/index.ts` (1000+ lines). Needs to be wired into the npx installer.
|
||||
- **Gemini CLI is architecturally near-identical to Claude Code**: 11 lifecycle hooks, JSON via stdin/stdout, exit code 0/2 convention, `GEMINI.md` context files, `~/.gemini/settings.json`. This is the easiest high-value integration.
|
||||
- **OpenCode has the richest plugin system**: 20+ hook events across 12 categories, JS/TS plugin modules, custom tool creation, MCP support. 110k stars — largest open-source AI CLI.
|
||||
- **`npx skills` by Vercel supports 41 agents** — proving the multi-IDE installer UX works. Their agent detection pattern (check if config dir exists) is the right model.
|
||||
- **All IDEs share a single worker on port 37777**: One worker serves all integrations. Session source (which IDE) is tracked via the `source` field in hook payloads. No per-IDE worker instances.
|
||||
- **This npx CLI fully replaces the old `claude-mem-installer`**: Not a supplement — the complete replacement.
|
||||
|
||||
## Solution
|
||||
|
||||
`npx claude-mem` becomes a unified CLI: install, configure any IDE, manage the worker, search memory.
|
||||
|
||||
```
|
||||
npx claude-mem # Interactive install + IDE selection
|
||||
npx claude-mem install # Same as above
|
||||
npx claude-mem install --ide windsurf # Direct IDE setup
|
||||
npx claude-mem start / stop / status # Worker management
|
||||
npx claude-mem search <query> # Search memory from terminal
|
||||
npx claude-mem transcript watch # Start transcript watcher
|
||||
```
|
||||
|
||||
## Platform Support
|
||||
|
||||
**Windows, macOS, and Linux are all first-class targets.** Platform-specific considerations:
|
||||
|
||||
- **Config paths**: Use `os.homedir()` and `path.join()` everywhere — never hardcode `/` or `~`
|
||||
- **Shebangs**: `#!/usr/bin/env node` for the CLI entry point (cross-platform via Node)
|
||||
- **Bun detection**: Check `PATH`, common install locations per platform (`%USERPROFILE%\.bun\bin\bun.exe` on Windows, `~/.bun/bin/bun` on Unix)
|
||||
- **File permissions**: `fs.chmod` is a no-op on Windows; don't gate on it
|
||||
- **Process management**: Worker start/stop uses signals on Unix, taskkill on Windows — match existing `worker-service.ts` patterns
|
||||
- **VS Code paths**: `~/Library/Application Support/Code/` (macOS), `~/.config/Code/` (Linux), `%APPDATA%/Code/` (Windows)
|
||||
- **Shell config**: `.bashrc`/`.zshrc` on Unix, PowerShell profile on Windows (for PATH modifications if needed)
|
||||
|
||||
---
|
||||
|
||||
## Phase 0: Research Findings
|
||||
|
||||
### IDE Integration Tiers
|
||||
|
||||
**Tier 1 — Native Hook/Plugin Systems** (highest fidelity, real-time capture):
|
||||
|
||||
| Tool | Hooks | Config Location | Context Injection | Stars/Users |
|
||||
|------|-------|----------------|-------------------|-------------|
|
||||
| Claude Code | 5 lifecycle hooks | `~/.claude/settings.json` | CLAUDE.md, plugins | ~25% market |
|
||||
| Gemini CLI | 11 lifecycle hooks | `~/.gemini/settings.json` | GEMINI.md | ~95k stars |
|
||||
| OpenCode | 20+ event hooks + plugin SDK | `~/.config/opencode/opencode.json` | AGENTS.md + rules dirs | ~110k stars |
|
||||
| Windsurf | 11 Cascade hooks | `.windsurf/hooks.json` | `.windsurf/rules/*.md` | ~1M users |
|
||||
| Codex CLI | `notify` hook | `~/.codex/config.toml` | `.codex/AGENTS.md`, MCP | Growing (OpenAI) |
|
||||
| OpenClaw | 8 event hooks + plugin SDK | `~/.openclaw/openclaw.json` | MEMORY.md sync | ~196k stars |
|
||||
|
||||
**Tier 2 — MCP Integration** (tool-based, search + context injection):
|
||||
|
||||
| Tool | MCP Support | Config Location | Context Injection |
|
||||
|------|------------|----------------|-------------------|
|
||||
| Cursor | First-class | `.cursor/mcp.json` | `.cursor/rules/*.mdc` |
|
||||
| Copilot CLI | First-class (default MCP) | `~/.copilot/config` | `.github/copilot-instructions.md` |
|
||||
| Antigravity | First-class + MCP Store | `~/.gemini/antigravity/mcp_config.json` | `.agent/rules/`, GEMINI.md |
|
||||
| Goose | Native MCP (co-developed protocol) | `~/.config/goose/config.yaml` | MCP context |
|
||||
| Crush | MCP + Skills | JSON config (charm.land schema) | Skills system |
|
||||
| Roo Code | First-class | `.roo/` | `.roo/rules/*.md`, `AGENTS.md` |
|
||||
| Warp | MCP + Warp Drive | `WARP.md` + Warp Drive UI | `WARP.md` |
|
||||
|
||||
**Tier 3 — Transcript File Watching** (passive, file-based):
|
||||
|
||||
| Tool | Transcript Location | Format |
|
||||
|------|-------------------|--------|
|
||||
| Claude Code | `~/.claude/projects/<proj>/<session>.jsonl` | JSONL |
|
||||
| Codex CLI | `~/.codex/sessions/**/*.jsonl` | JSONL |
|
||||
| Gemini CLI | `~/.gemini/tmp/<hash>/chats/` | JSON |
|
||||
| OpenCode | `.opencode/` (SQLite) | SQLite — needs export |
|
||||
|
||||
### What claude-mem Already Has
|
||||
|
||||
| Component | Status | Location |
|
||||
|-----------|--------|----------|
|
||||
| Claude Code plugin | Complete | `plugin/hooks/hooks.json` |
|
||||
| Cursor hooks installer | Complete | `src/services/integrations/CursorHooksInstaller.ts` |
|
||||
| Platform adapters | Claude Code + Cursor + raw | `src/cli/adapters/` |
|
||||
| Transcript watcher | Complete (schema-based JSONL) | `src/services/transcripts/` |
|
||||
| Codex transcript schema | Sample exists | `src/services/transcripts/config.ts` |
|
||||
| OpenClaw plugin | Complete (1000+ lines) | `openclaw/src/index.ts` |
|
||||
| MCP server | Complete | `plugin/scripts/mcp-server.cjs` |
|
||||
| Gemini CLI support | Not started | — |
|
||||
| OpenCode support | Not started | — |
|
||||
| Windsurf support | Not started | — |
|
||||
|
||||
### Patterns to Copy
|
||||
|
||||
- **Agent detection from `npx skills`** (`vercel-labs/skills/src/agents.ts`): Check if config directory exists
|
||||
- **Existing installer logic** (`installer/src/steps/install.ts:29-83`): registerMarketplace, registerPlugin, enablePluginInClaudeSettings — **extract shared logic** from existing installer into reusable modules (DRY with the new CLI)
|
||||
- **Bun resolution** (`plugin/scripts/bun-runner.js`): PATH lookup + common locations per platform
|
||||
- **CursorHooksInstaller** (`src/services/integrations/CursorHooksInstaller.ts`): Reference implementation for IDE hooks installation
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: NPX CLI Entry Point
|
||||
|
||||
### What to implement
|
||||
|
||||
1. **Add `bin` field to `package.json`**:
|
||||
```json
|
||||
"bin": {
|
||||
"claude-mem": "./dist/cli/index.js"
|
||||
}
|
||||
```
|
||||
|
||||
2. **Create `src/npx-cli/index.ts`** — a Node.js CLI router (NOT Bun) with command categories:
|
||||
|
||||
**Install commands** (pure Node.js, no Bun required):
|
||||
- `npx claude-mem` or `npx claude-mem install` → interactive install (IDE multi-select)
|
||||
- `npx claude-mem install --ide <name>` → direct IDE setup (only for implemented IDEs; unimplemented ones error with "Support for <name> coming soon")
|
||||
- `npx claude-mem update` → update to latest version
|
||||
- `npx claude-mem uninstall` → remove plugin and IDE configs
|
||||
- `npx claude-mem version` → print version
|
||||
|
||||
**Runtime commands** (delegate to Bun via installed plugin):
|
||||
- `npx claude-mem start` → spawns `bun worker-service.cjs start`
|
||||
- `npx claude-mem stop` → spawns `bun worker-service.cjs stop`
|
||||
- `npx claude-mem restart` → spawns `bun worker-service.cjs restart`
|
||||
- `npx claude-mem status` → spawns `bun worker-service.cjs status`
|
||||
- `npx claude-mem search <query>` → hits `GET http://localhost:37777/api/search?q=<query>`
|
||||
- `npx claude-mem transcript watch` → starts transcript watcher
|
||||
|
||||
**Runtime commands must check for installation first**: If plugin directory doesn't exist at `~/.claude/plugins/marketplaces/thedotmack/`, print "claude-mem is not installed. Run: npx claude-mem install" and exit.
|
||||
|
||||
3. **The install flow** (fully replaces git clone + build):
|
||||
- Detect the npm package's own location (`import.meta.url` or `__dirname`)
|
||||
- Copy `plugin/` from the npm package to `~/.claude/plugins/marketplaces/thedotmack/`
|
||||
- Copy `plugin/` to `~/.claude/plugins/cache/thedotmack/claude-mem/<version>/`
|
||||
- Register marketplace in `~/.claude/plugins/known_marketplaces.json`
|
||||
- Register plugin in `~/.claude/plugins/installed_plugins.json`
|
||||
- Enable in `~/.claude/settings.json`
|
||||
- Run `npm install` in the marketplace dir (for `@chroma-core/default-embed` — native ONNX binaries, can't be bundled)
|
||||
- Trigger smart-install.js for Bun/uv setup
|
||||
- Run IDE-specific setup for each selected IDE
|
||||
|
||||
4. **Interactive IDE selection** (auto-detect + prompt):
|
||||
- Auto-detect installed IDEs by checking config directories
|
||||
- Present multi-select with detected IDEs pre-selected
|
||||
- Detection map:
|
||||
- Claude Code: `~/.claude/` exists
|
||||
- Gemini CLI: `~/.gemini/` exists
|
||||
- OpenCode: `~/.config/opencode/` exists OR `opencode` in PATH
|
||||
- OpenClaw: `~/.openclaw/` exists
|
||||
- Windsurf: `~/.codeium/windsurf/` exists
|
||||
- Codex CLI: `~/.codex/` exists
|
||||
- Cursor: `~/.cursor/` exists
|
||||
- Copilot CLI: `copilot` in PATH (it's a CLI tool, not a config dir)
|
||||
- Antigravity: `~/.gemini/antigravity/` exists
|
||||
- Goose: `~/.config/goose/` exists OR `goose` in PATH
|
||||
- Crush: `crush` in PATH
|
||||
- Roo Code: check for VS Code extension directory containing `roo-code`
|
||||
- Warp: `~/.warp/` exists OR `warp` in PATH
|
||||
|
||||
5. **The runtime command routing**:
|
||||
- Locate the installed plugin directory
|
||||
- Find Bun binary (same logic as `bun-runner.js`, platform-aware)
|
||||
- Spawn `bun worker-service.cjs <command>` and pipe stdio through
|
||||
- For `search`: HTTP request to running worker
|
||||
|
||||
### Patterns to follow
|
||||
|
||||
- `installer/src/steps/install.ts:29-83` for marketplace registration — **extract to shared module**
|
||||
- `plugin/scripts/bun-runner.js` for Bun resolution
|
||||
- `vercel-labs/skills/src/agents.ts` for IDE auto-detection pattern
|
||||
|
||||
### Verification
|
||||
|
||||
- `npx claude-mem install` copies plugin to correct directories on macOS, Linux, and Windows
|
||||
- Auto-detection finds installed IDEs
|
||||
- `npx claude-mem start/stop/status` work after install
|
||||
- `npx claude-mem search "test"` returns results
|
||||
- `npx claude-mem start` before install prints helpful error message
|
||||
- `npx claude-mem update` and `npx claude-mem uninstall` work correctly
|
||||
- `npx claude-mem version` prints version
|
||||
|
||||
### Anti-patterns
|
||||
|
||||
- Do NOT require Bun for install commands — pure Node.js
|
||||
- Do NOT clone the git repo
|
||||
- Do NOT build from source at install time
|
||||
- Do NOT depend on `bun:sqlite` in the CLI entry point
|
||||
|
||||
---
|
||||
|
||||
## Phase 2: Build Pipeline Integration
|
||||
|
||||
### What to implement
|
||||
|
||||
1. **Add CLI build step to `scripts/build-hooks.js`**:
|
||||
- Compile `src/npx-cli/index.ts` → `dist/cli/index.js`
|
||||
- Bundle `@clack/prompts` and `picocolors` into the output (self-contained)
|
||||
- Shebang: `#!/usr/bin/env node`
|
||||
- Set executable permissions (no-op on Windows, that's fine)
|
||||
|
||||
2. **Move `@clack/prompts` and `picocolors`** to main package.json as dev dependencies (bundled by esbuild into dist/cli/index.js)
|
||||
|
||||
3. **Verify `package.json` `files` field**: Currently `["dist", "plugin"]`. `dist/cli/index.js` is already included since it's under `dist/`. No change needed.
|
||||
|
||||
4. **Update `prepublishOnly`** to ensure CLI is built before npm publish (already covered — `npm run build` calls `build-hooks.js`)
|
||||
|
||||
5. **Pre-build OpenClaw plugin**: Add an esbuild step that compiles `openclaw/src/index.ts` → `openclaw/dist/index.js` so it ships ready-to-use. No `tsc` at install time.
|
||||
|
||||
6. **Add `openclaw/dist/` to `package.json` `files` field** (or add `openclaw` if the whole directory should ship)
|
||||
|
||||
### Verification
|
||||
|
||||
- `npm run build` produces `dist/cli/index.js` with correct shebang
|
||||
- `npm run build` produces `openclaw/dist/index.js` pre-built
|
||||
- `npm pack` includes both `dist/cli/index.js` and `openclaw/dist/`
|
||||
- `node dist/cli/index.js --help` works without Bun
|
||||
- Package size is reasonable (check with `npm pack --dry-run`)
|
||||
|
||||
---
|
||||
|
||||
## Phase 3: Gemini CLI Integration (Tier 1 — Hook-Based)
|
||||
|
||||
**Why first among new IDEs**: Near-identical architecture to Claude Code. 11 lifecycle hooks with JSON stdin/stdout, same exit code conventions (0=success, 2=block), `GEMINI.md` context files. 95k GitHub stars. Lowest effort, highest confidence.
|
||||
|
||||
### Gemini CLI Hook Events
|
||||
|
||||
| Event | Map to claude-mem | Use |
|
||||
|-------|-------------------|-----|
|
||||
| `SessionStart` | `session-init` | Start tracking session |
|
||||
| `BeforeAgent` | `user-prompt` | Capture user prompt |
|
||||
| `AfterAgent` | `observation` | Capture full agent response |
|
||||
| `BeforeTool` | — | Skip (pre-execution, no result yet) |
|
||||
| `AfterTool` | `observation` | Capture tool name + input + response |
|
||||
| `BeforeModel` | — | Skip (too low-level, LLM request details) |
|
||||
| `AfterModel` | — | Skip (raw LLM response, redundant with AfterAgent) |
|
||||
| `BeforeToolSelection` | — | Skip (internal planning step) |
|
||||
| `PreCompress` | `summary` | Trigger summary before context compression |
|
||||
| `Notification` | — | Skip (system alerts, not session data) |
|
||||
| `SessionEnd` | `session-end` | Finalize session |
|
||||
|
||||
**Mapped**: 5 of 11 events. **Skipped**: 6 events that are either too low-level (BeforeModel/AfterModel), pre-execution (BeforeTool, BeforeToolSelection), or system-level (Notification).
|
||||
|
||||
### Verified Stdin Payload Schemas (from `packages/core/src/hooks/types.ts`)
|
||||
|
||||
**Base input (all hooks receive):**
|
||||
```typescript
|
||||
{ session_id: string, transcript_path: string, cwd: string, hook_event_name: string, timestamp: string }
|
||||
```
|
||||
|
||||
**Event-specific fields:**
|
||||
| Event | Additional Fields |
|
||||
|-------|-------------------|
|
||||
| `SessionStart` | `source: "startup" \| "resume" \| "clear"` |
|
||||
| `SessionEnd` | `reason: "exit" \| "clear" \| "logout" \| "prompt_input_exit" \| "other"` |
|
||||
| `BeforeAgent` | `prompt: string` |
|
||||
| `AfterAgent` | `prompt: string, prompt_response: string, stop_hook_active: boolean` |
|
||||
| `BeforeTool` | `tool_name: string, tool_input: Record<string, unknown>, mcp_context?: McpToolContext, original_request_name?: string` |
|
||||
| `AfterTool` | `tool_name: string, tool_input: Record<string, unknown>, tool_response: Record<string, unknown>, mcp_context?: McpToolContext` |
|
||||
| `PreCompress` | `trigger: "auto" \| "manual"` |
|
||||
| `Notification` | `notification_type: "ToolPermission", message: string, details: Record<string, unknown>` |
|
||||
|
||||
**Output (all hooks can return):**
|
||||
```typescript
|
||||
{ continue?: boolean, stopReason?: string, suppressOutput?: boolean, systemMessage?: string, decision?: "allow" | "deny" | "block" | "approve" | "ask", reason?: string, hookSpecificOutput?: Record<string, unknown> }
|
||||
```
|
||||
|
||||
**Advisory (non-blocking) hooks:** SessionStart, SessionEnd, PreCompress, Notification — `continue` and `decision` fields are ignored.
|
||||
|
||||
**Environment variables provided:** `GEMINI_PROJECT_DIR`, `GEMINI_SESSION_ID`, `GEMINI_CWD`, `CLAUDE_PROJECT_DIR` (compat alias)
|
||||
|
||||
### What to implement
|
||||
|
||||
1. **Create Gemini CLI platform adapter** at `src/cli/adapters/gemini-cli.ts`:
|
||||
- Normalize Gemini CLI's hook JSON to `NormalizedHookInput`
|
||||
- Base fields always present: `session_id`, `transcript_path`, `cwd`, `hook_event_name`, `timestamp`
|
||||
- Map per event:
|
||||
- `SessionStart`: `source` → session init metadata
|
||||
- `BeforeAgent`: `prompt` → user prompt text
|
||||
- `AfterAgent`: `prompt` + `prompt_response` → full conversation turn
|
||||
- `AfterTool`: `tool_name` + `tool_input` + `tool_response` → observation
|
||||
- `PreCompress`: `trigger` → summary trigger
|
||||
- `SessionEnd`: `reason` → session finalization
|
||||
|
||||
2. **Create Gemini CLI hooks installer** at `src/services/integrations/GeminiCliHooksInstaller.ts`:
|
||||
- Write hooks to `~/.gemini/settings.json` under the `hooks` key
|
||||
- Must **merge** with existing settings (read → parse → deep merge → write)
|
||||
- Hook config format (verified against official docs):
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"AfterTool": [{
|
||||
"matcher": "*",
|
||||
"hooks": [{ "name": "claude-mem", "type": "command", "command": "<path-to-hook-script>", "timeout": 5000 }]
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
- Note: `matcher` uses regex for tool events, exact string for lifecycle events. `"*"` or `""` matches all.
|
||||
- Hook groups support `sequential: boolean` (default false = parallel execution)
|
||||
- Security: Project-level hooks are fingerprinted — if name/command changes, user is warned
|
||||
- Context injection via `~/.gemini/GEMINI.md` (append claude-mem section with `<claude-mem-context>` tags, same pattern as CLAUDE.md)
|
||||
- Settings hierarchy: project `.gemini/settings.json` > user `~/.gemini/settings.json` > system `/etc/gemini-cli/settings.json`
|
||||
|
||||
3. **Register `gemini-cli` in `getPlatformAdapter()`** at `src/cli/adapters/index.ts`
|
||||
|
||||
4. **Add Gemini CLI to installer IDE selection**
|
||||
|
||||
### Verification
|
||||
|
||||
- `npx claude-mem install --ide gemini-cli` merges hooks into `~/.gemini/settings.json`
|
||||
- Gemini CLI sessions are captured by the worker
|
||||
- `AfterTool` events produce observations with correct `tool_name`, `tool_input`, `tool_response`
|
||||
- `GEMINI.md` gets claude-mem context section
|
||||
- Existing Gemini CLI settings are preserved (merge, not overwrite)
|
||||
- Verify `session_id` from base input is used for session tracking
|
||||
|
||||
### Anti-patterns
|
||||
|
||||
- Do NOT overwrite `~/.gemini/settings.json` — must deep merge
|
||||
- Do NOT map all 11 events — the 6 skipped events would produce noise, not signal
|
||||
- Do NOT use `type: "runtime"` — that's for internal extensions only; use `type: "command"`
|
||||
- Advisory hooks (SessionStart, SessionEnd, PreCompress, Notification) cannot block — don't set `decision` or `continue` fields on them
|
||||
|
||||
---
|
||||
|
||||
## Phase 4: OpenCode Integration (Tier 1 — Plugin-Based)
|
||||
|
||||
**Why next**: 110k stars, richest plugin ecosystem. OpenCode plugins are JS/TS modules auto-loaded from plugin directories. OpenCode also has a Claude Code compatibility fallback (reads `~/.claude/CLAUDE.md` if no global `AGENTS.md` exists, controllable via `OPENCODE_DISABLE_CLAUDE_CODE_PROMPT=1`).
|
||||
|
||||
### Verified Plugin API (from `packages/plugin/src/index.ts`)
|
||||
|
||||
**Plugin signature:**
|
||||
```typescript
|
||||
import { type Plugin, tool } from "@opencode-ai/plugin"
|
||||
|
||||
export const ClaudeMemPlugin: Plugin = async (ctx) => {
|
||||
// ctx: { client, project, directory, worktree, serverUrl, $ }
|
||||
return { /* hooks object */ }
|
||||
}
|
||||
```
|
||||
|
||||
**PluginInput type (6 properties, not 4):**
|
||||
```typescript
|
||||
type PluginInput = {
|
||||
client: ReturnType<typeof createOpencodeClient> // OpenCode SDK client
|
||||
project: Project // Current project info
|
||||
directory: string // Current working directory
|
||||
worktree: string // Git worktree path
|
||||
serverUrl: URL // Server URL
|
||||
$: BunShell // Bun shell API
|
||||
}
|
||||
```
|
||||
|
||||
**Two hook mechanisms (important distinction):**
|
||||
|
||||
1. **Direct interceptor hooks** — keys on the returned `Hooks` object, receive `(input, output)` allowing mutation:
|
||||
- `tool.execute.before`: `(input: { tool, sessionID, callID }, output: { args })`
|
||||
- `tool.execute.after`: `(input: { tool, sessionID, callID, args }, output: { title, output, metadata })`
|
||||
- `shell.env`, `chat.message`, `chat.params`, `chat.headers`, `permission.ask`, `command.execute.before`
|
||||
- Experimental: `experimental.session.compacting`, `experimental.chat.messages.transform`, `experimental.chat.system.transform`
|
||||
|
||||
2. **Bus event catch-all** — generic `event` hook, receives `{ event }` where `event.type` is the event name:
|
||||
- `session.created`, `session.compacted`, `session.deleted`, `session.idle`, `session.error`, `session.status`, `session.updated`, `session.diff`
|
||||
- `message.updated`, `message.part.updated`, `message.part.removed`, `message.removed`
|
||||
- `file.edited`, `file.watcher.updated`
|
||||
- `command.executed`, `todo.updated`, `installation.updated`, `server.connected`
|
||||
- `permission.asked`, `permission.replied`
|
||||
- `lsp.client.diagnostics`, `lsp.updated`
|
||||
- `tui.prompt.append`, `tui.command.execute`, `tui.toast.show`
|
||||
- Total: **27 bus events** across **12 categories**
|
||||
|
||||
**Custom tool registration (CORRECTED — name is the key, not positional arg):**
|
||||
```typescript
|
||||
return {
|
||||
tool: {
|
||||
claude_mem_search: tool({
|
||||
description: "Search claude-mem memory database",
|
||||
args: { query: tool.schema.string() },
|
||||
async execute(args, context) {
|
||||
// context: { sessionID, messageID, agent, directory, worktree, abort, metadata, ask }
|
||||
const response = await fetch(`http://localhost:37777/api/search?q=${encodeURIComponent(args.query)}`)
|
||||
return await response.text()
|
||||
},
|
||||
}),
|
||||
},
|
||||
}
|
||||
```
|
||||
|
||||
### What to implement
|
||||
|
||||
1. **Create OpenCode plugin** at `src/integrations/opencode-plugin/index.ts`:
|
||||
- Export a `Plugin` function receiving full `PluginInput` context
|
||||
- Use **direct interceptor** `tool.execute.after` for tool observation capture (gives `tool`, `args`, `output`)
|
||||
- Use **bus event catch-all** `event` for session lifecycle:
|
||||
|
||||
| Mechanism | Event | Map to claude-mem |
|
||||
|-----------|-------|-------------------|
|
||||
| interceptor | `tool.execute.after` | `observation` (tool name + args + output) |
|
||||
| bus event | `session.created` | `session-init` |
|
||||
| bus event | `message.updated` | `observation` (assistant messages) |
|
||||
| bus event | `session.compacted` | `summary` |
|
||||
| bus event | `file.edited` | `observation` (file changes) |
|
||||
| bus event | `session.deleted` | `session-end` |
|
||||
|
||||
- Register `claude_mem_search` custom tool using correct `tool({ description, args, execute })` API
|
||||
- Hit `localhost:37777` API endpoints from the plugin
|
||||
|
||||
2. **Build the plugin** in the esbuild pipeline → `dist/opencode-plugin/index.js`
|
||||
|
||||
3. **Create OpenCode setup in installer** (two options, prefer file-based):
|
||||
- **Option A (file-based):** Copy plugin to `~/.config/opencode/plugins/claude-mem.ts` (auto-loaded at startup)
|
||||
- **Option B (npm-based):** Add to `~/.config/opencode/opencode.json` under `"plugin"` array: `["claude-mem"]`
|
||||
- Config also supports JSONC (`opencode.jsonc`) and legacy `config.json`
|
||||
- Context injection: Append to `~/.config/opencode/AGENTS.md` (or create it) with `<claude-mem-context>` tags
|
||||
- Additional context via `"instructions"` config key (supports file paths, globs, remote URLs)
|
||||
|
||||
4. **Add OpenCode to installer IDE selection**
|
||||
|
||||
### OpenCode Verification
|
||||
|
||||
- `npx claude-mem install --ide opencode` registers the plugin (file or npm)
|
||||
- OpenCode loads the plugin on next session
|
||||
- `tool.execute.after` interceptor produces observations with `tool`, `args`, `output`
|
||||
- Bus events (`session.created`, `session.deleted`) handle session lifecycle
|
||||
- `claude_mem_search` custom tool works in OpenCode sessions
|
||||
- Context is injected via AGENTS.md
|
||||
|
||||
### OpenCode Anti-patterns
|
||||
|
||||
- Do NOT try to use OpenCode's `session.diff` for full capture — it's a summary diff, not raw data
|
||||
- Do NOT use `tool('name', schema, handler)` — wrong signature. Name is the key in the `tool:{}` map
|
||||
- Do NOT assume bus events have the same `(input, output)` mutation pattern — they only receive `{ event }`
|
||||
- OpenCode plugins run in Bun — the plugin CAN use Bun APIs (unlike the npx CLI itself)
|
||||
- Do NOT hardcode `~/.config/opencode/` — respect `OPENCODE_CONFIG_DIR` env var if set
|
||||
|
||||
---
|
||||
|
||||
## Phase 5: Windsurf Integration (Tier 1 — Hook-Based)
|
||||
|
||||
**Why next**: 11 Cascade hooks, ~1M users. Hook architecture uses JSON stdin with a consistent envelope format.
|
||||
|
||||
### Verified Windsurf Hook Events (from docs.windsurf.com/windsurf/cascade/hooks)
|
||||
|
||||
**Naming pattern**: `pre_`/`post_` prefix + 5 action categories, plus 2 standalone post-only events.
|
||||
|
||||
| Event | Can Block? | Map to claude-mem | Use |
|
||||
|-------|-----------|-------------------|-----|
|
||||
| `pre_user_prompt` | Yes | `session-init` + `context` | Start session, inject context |
|
||||
| `pre_read_code` | Yes | — | Skip (pre-execution, can block file reads) |
|
||||
| `post_read_code` | No | — | Skip (too noisy, file reads are frequent) |
|
||||
| `pre_write_code` | Yes | — | Skip (pre-execution, can block writes) |
|
||||
| `post_write_code` | No | `observation` | Code generation |
|
||||
| `pre_run_command` | Yes | — | Skip (pre-execution, can block commands) |
|
||||
| `post_run_command` | No | `observation` | Shell command execution |
|
||||
| `pre_mcp_tool_use` | Yes | — | Skip (pre-execution, can block MCP calls) |
|
||||
| `post_mcp_tool_use` | No | `observation` | MCP tool results |
|
||||
| `post_cascade_response` | No | `observation` | Full AI response |
|
||||
| `post_setup_worktree` | No | — | Skip (informational) |
|
||||
|
||||
**Mapped**: 5 of 11 events (all post-action). **Skipped**: 4 pre-hooks (blocking-capable, pre-execution) + 2 low-value post-hooks.
|
||||
|
||||
### Verified Stdin Payload Schema
|
||||
|
||||
**Common envelope (all hooks):**
|
||||
```json
|
||||
{
|
||||
"agent_action_name": "string",
|
||||
"trajectory_id": "string",
|
||||
"execution_id": "string",
|
||||
"timestamp": "ISO 8601 string",
|
||||
"tool_info": { /* event-specific payload */ }
|
||||
}
|
||||
```
|
||||
|
||||
**Event-specific `tool_info` payloads:**
|
||||
|
||||
| Event | `tool_info` fields |
|
||||
|-------|-------------------|
|
||||
| `pre_user_prompt` | `{ user_prompt: string }` |
|
||||
| `pre_read_code` / `post_read_code` | `{ file_path: string }` |
|
||||
| `pre_write_code` / `post_write_code` | `{ file_path: string, edits: [{ old_string: string, new_string: string }] }` |
|
||||
| `pre_run_command` / `post_run_command` | `{ command_line: string, cwd: string }` |
|
||||
| `pre_mcp_tool_use` | `{ mcp_server_name: string, mcp_tool_name: string, mcp_tool_arguments: {} }` |
|
||||
| `post_mcp_tool_use` | `{ mcp_server_name: string, mcp_tool_name: string, mcp_tool_arguments: {}, mcp_result: string }` |
|
||||
| `post_cascade_response` | `{ response: string }` (markdown) |
|
||||
| `post_setup_worktree` | `{ worktree_path: string, root_workspace_path: string }` |
|
||||
|
||||
**Exit codes:** `0` = success, `2` = block (pre-hooks only; stderr shown to agent), any other = non-blocking warning.
|
||||
|
||||
### What to implement
|
||||
|
||||
1. **Create Windsurf platform adapter** at `src/cli/adapters/windsurf.ts`:
|
||||
- Normalize Windsurf's hook input format to `NormalizedHookInput`
|
||||
- Common envelope: `agent_action_name`, `trajectory_id`, `execution_id`, `timestamp`, `tool_info`
|
||||
- Map: `trajectory_id` → `sessionId`, `tool_info` fields per event type
|
||||
- For `post_write_code`: `tool_info.file_path` + `tool_info.edits` → file change observation
|
||||
- For `post_run_command`: `tool_info.command_line` + `tool_info.cwd` → command observation
|
||||
- For `post_mcp_tool_use`: `tool_info.mcp_tool_name` + `tool_info.mcp_tool_arguments` + `tool_info.mcp_result` → tool observation
|
||||
- For `post_cascade_response`: `tool_info.response` → full AI response observation
|
||||
|
||||
2. **Create Windsurf hooks installer** at `src/services/integrations/WindsurfHooksInstaller.ts`:
|
||||
- Write hooks to `~/.codeium/windsurf/hooks.json` (user-level, for global coverage)
|
||||
- Per-workspace override at `.windsurf/hooks.json` if user chooses workspace-level install
|
||||
- Config format (verified):
|
||||
```json
|
||||
{
|
||||
"hooks": {
|
||||
"post_write_code": [{
|
||||
"command": "<path-to-hook-script>",
|
||||
"show_output": false,
|
||||
"working_directory": "<optional>"
|
||||
}]
|
||||
}
|
||||
}
|
||||
```
|
||||
- Note: Tilde expansion (`~`) is NOT supported in `working_directory` — use absolute paths
|
||||
- Merge order: cloud → system → user → workspace (all hooks at all levels execute)
|
||||
- Context injection via `.windsurf/rules/claude-mem-context.md` (workspace-level; Windsurf rules are workspace-scoped)
|
||||
- Rule limits: 6,000 chars per file, 12,000 chars total across all rules
|
||||
|
||||
3. **Register `windsurf` in `getPlatformAdapter()`** at `src/cli/adapters/index.ts`
|
||||
|
||||
4. **Add Windsurf to installer IDE selection**
|
||||
|
||||
### Windsurf Verification
|
||||
|
||||
- `npx claude-mem install --ide windsurf` creates hooks config at `~/.codeium/windsurf/hooks.json`
|
||||
- Windsurf sessions are captured by the worker via post-action hooks
|
||||
- `trajectory_id` is used as session identifier
|
||||
- Context is injected via `.windsurf/rules/claude-mem-context.md` (under 6K char limit)
|
||||
- Existing hooks.json is preserved (merge, not overwrite)
|
||||
|
||||
### Windsurf Anti-patterns
|
||||
|
||||
- Do NOT use fabricated event names (`post_search_code`, `post_lint_code`, `on_error`, `pre_tool_execution`) — they don't exist
|
||||
- Do NOT assume Windsurf's stdin JSON matches Claude Code's — it uses `tool_info` envelope, not flat fields
|
||||
- Do NOT use tilde (`~`) in `working_directory` — not supported, use absolute paths
|
||||
- Do NOT exceed 6K chars in the context rule file — Windsurf truncates beyond that
|
||||
- Pre-hooks can block actions (exit 2) — only use post-hooks for observation capture
|
||||
|
||||
---
|
||||
|
||||
## Phase 6: Codex CLI Integration (Tier 1 — Hook + Transcript)
|
||||
|
||||
### Dedup strategy
|
||||
|
||||
Codex has both a `notify` hook (real-time) and transcript files (complete history). Use **transcript watching only** — it's more complete and avoids the complexity of dual capture paths. The `notify` hook is a simpler mechanism that doesn't provide enough granularity to justify maintaining two integration paths. If transcript watching proves insufficient, add the notify hook later.
|
||||
|
||||
### What to implement
|
||||
|
||||
1. **Create Codex transcript schema** — the sample in `src/services/transcripts/config.ts` is already production-quality. Verify against current Codex CLI JSONL format and update if needed.
|
||||
|
||||
2. **Create Codex setup in installer**:
|
||||
- Write transcript-watch config to `~/.claude-mem/transcript-watch.json`
|
||||
- Set up watch for `~/.codex/sessions/**/*.jsonl` using existing CODEX_SAMPLE_SCHEMA
|
||||
- Context injection via `.codex/AGENTS.md` (Codex reads this natively)
|
||||
- Must merge with existing `config.toml` if it exists (read → parse → merge → write)
|
||||
|
||||
3. **Add Codex CLI to installer IDE selection**
|
||||
|
||||
### Verification
|
||||
|
||||
- `npx claude-mem install --ide codex` creates transcript watch config
|
||||
- Codex sessions appear in claude-mem database
|
||||
- `AGENTS.md` updated with context after sessions
|
||||
- Existing `config.toml` is preserved
|
||||
|
||||
---
|
||||
|
||||
## Phase 7: OpenClaw Integration (Tier 1 — Plugin-Based)
|
||||
|
||||
**Plugin is already fully built** at `openclaw/src/index.ts` (~1000 lines). Has event hooks, SSE observation feed, MEMORY.md sync, slash commands. Only wiring into the installer is needed.
|
||||
|
||||
### What to implement
|
||||
|
||||
1. **Wire OpenClaw into the npx installer**:
|
||||
- Detect `~/.openclaw/` directory
|
||||
- Copy pre-built plugin from `openclaw/dist/` (built in Phase 2) to OpenClaw plugins location
|
||||
- Register in `~/.openclaw/openclaw.json` under `plugins.claude-mem`
|
||||
- Configure worker port, project name, syncMemoryFile
|
||||
- Optionally prompt for observation feed setup (channel type + target ID)
|
||||
|
||||
2. **Add OpenClaw to IDE selection TUI** with hint about messaging channel support
|
||||
|
||||
### Verification
|
||||
|
||||
- `npx claude-mem install --ide openclaw` registers the plugin
|
||||
- OpenClaw gateway loads the plugin on restart
|
||||
- Observations are recorded from OpenClaw sessions
|
||||
- MEMORY.md syncs to agent workspaces
|
||||
|
||||
### Anti-patterns
|
||||
|
||||
- Do NOT rebuild the OpenClaw plugin from source at install time — it ships pre-built from Phase 2
|
||||
- Do NOT modify the plugin's event handling — it's battle-tested
|
||||
|
||||
---
|
||||
|
||||
## Phase 8: MCP-Based Integrations (Tier 2)
|
||||
|
||||
**These get the MCP server for free** — it already exists at `plugin/scripts/mcp-server.cjs`. The installer just needs to write the right config files per IDE.
|
||||
|
||||
MCP-only integrations provide: search tools + context injection. They do NOT capture transcripts or tool usage in real-time.
|
||||
|
||||
### What to implement
|
||||
|
||||
1. **Copilot CLI MCP setup**:
|
||||
- Write MCP config to `~/.copilot/config` (merge, not overwrite)
|
||||
- Context injection: `.github/copilot-instructions.md`
|
||||
- Detection: `copilot` command in PATH
|
||||
|
||||
2. **Antigravity MCP setup**:
|
||||
- Write MCP config to `~/.gemini/antigravity/mcp_config.json` (merge, not overwrite)
|
||||
- Context injection: `~/.gemini/GEMINI.md` (shared with Gemini CLI) and/or `.agent/rules/claude-mem-context.md`
|
||||
- Detection: `~/.gemini/antigravity/` exists
|
||||
- Note: Antigravity has NO hook system — MCP is the only integration path
|
||||
|
||||
3. **Goose MCP setup**:
|
||||
- Write MCP config to `~/.config/goose/config.yaml` (YAML merge — use a lightweight YAML parser or write the block manually if config doesn't exist)
|
||||
- Detection: `~/.config/goose/` exists OR `goose` in PATH
|
||||
- Note: Goose co-developed MCP with Anthropic, so MCP support is excellent
|
||||
|
||||
4. **Crush MCP setup**:
|
||||
- Write MCP config to Crush's JSON config
|
||||
- Detection: `crush` in PATH
|
||||
|
||||
5. **Roo Code MCP setup**:
|
||||
- Write MCP config to `.roo/` or workspace settings
|
||||
- Context injection: `.roo/rules/claude-mem-context.md`
|
||||
- Detection: Check for VS Code extension directory containing `roo-code`
|
||||
|
||||
6. **Warp MCP setup**:
|
||||
- Warp uses `WARP.md` in project root for context injection (similar to CLAUDE.md)
|
||||
- MCP servers configured via Warp Drive UI, but also via config files
|
||||
- Detection: `~/.warp/` exists OR `warp` in PATH
|
||||
- Note: Warp is a terminal replacement (~26k stars), not just a CLI tool — multi-agent orchestration with management UI
|
||||
|
||||
7. **For each**: Add to installer IDE detection and selection
|
||||
|
||||
### Config merging strategy
|
||||
|
||||
JSON configs: Read → parse → deep merge → write back. YAML configs (Goose): If file exists, read and append the MCP block. If not, create from template. Avoid pulling in a full YAML parser library — write the MCP block as a string append with proper indentation if the format is predictable.
|
||||
|
||||
### Verification
|
||||
|
||||
- Each IDE can search claude-mem via MCP tools
|
||||
- Context files are written to IDE-specific locations
|
||||
- Existing configs are preserved
|
||||
|
||||
### Anti-patterns
|
||||
|
||||
- MCP-only integrations do NOT capture transcripts — don't claim "full integration"
|
||||
- Do NOT overwrite existing config files — always merge
|
||||
- Do NOT add a heavy YAML parser dependency for one integration
|
||||
|
||||
---
|
||||
|
||||
## Phase 9: Remove Old Installer
|
||||
|
||||
This is a **full replacement**, not a deprecation.
|
||||
|
||||
### What to implement
|
||||
|
||||
1. Remove `claude-mem-installer` npm package (unpublish or mark deprecated with message pointing to `npx claude-mem`)
|
||||
2. Update `install/public/install.sh` → redirect to `npx claude-mem`
|
||||
3. Remove `installer/` directory from the repository (it's replaced by `src/npx-cli/`)
|
||||
4. Update docs site to reflect the new install command
|
||||
5. Update README.md install instructions
|
||||
|
||||
---
|
||||
|
||||
## Phase 10: Final Verification
|
||||
|
||||
### All platforms (macOS, Linux, Windows)
|
||||
|
||||
1. `npm run build` succeeds, produces `dist/cli/index.js` and `openclaw/dist/index.js`
|
||||
2. `node dist/cli/index.js install` works clean (no prior install)
|
||||
3. Auto-detects installed IDEs correctly per platform
|
||||
4. `npx claude-mem start/stop/status/search` all work
|
||||
5. `npx claude-mem update` updates correctly
|
||||
6. `npx claude-mem uninstall` cleans up all IDE configs
|
||||
7. `npx claude-mem version` prints version
|
||||
8. `npx claude-mem start` before install shows helpful error
|
||||
9. No Bun dependency at install time
|
||||
|
||||
### Per-integration verification
|
||||
|
||||
| Integration | Type | Captures Sessions | Search via MCP | Context Injection |
|
||||
|-------------|------|-------------------|----------------|-------------------|
|
||||
| Claude Code | Plugin | Yes (hooks) | Yes | CLAUDE.md |
|
||||
| Gemini CLI | Hooks | Yes (AfterTool, AfterAgent) | Yes (via hook) | GEMINI.md |
|
||||
| OpenCode | Plugin | Yes (tool.execute.after, message.updated) | Yes (custom tool) | AGENTS.md / rules |
|
||||
| Windsurf | Hooks | Yes (post_cascade_response, etc.) | Yes (via hook) | .windsurf/rules/ |
|
||||
| Codex CLI | Transcript | Yes (JSONL watcher) | No (passive only) | .codex/AGENTS.md |
|
||||
| OpenClaw | Plugin | Yes (event hooks) | Yes (slash commands) | MEMORY.md |
|
||||
| Copilot CLI | MCP | No | Yes | copilot-instructions.md |
|
||||
| Antigravity | MCP | No | Yes | .agent/rules/ |
|
||||
| Goose | MCP | No | Yes | MCP context |
|
||||
| Crush | MCP | No | Yes | Skills |
|
||||
| Roo Code | MCP | No | Yes | .roo/rules/ |
|
||||
| Warp | MCP | No | Yes | WARP.md |
|
||||
|
||||
---
|
||||
|
||||
## Priority Order & Impact
|
||||
|
||||
| Phase | IDE/Tool | Integration Type | Stars/Users | Effort |
|
||||
|-------|----------|-----------------|-------------|--------|
|
||||
| 1-2 | (infrastructure) | npx CLI + build pipeline | All users | Medium |
|
||||
| 3 | Gemini CLI | Hooks (Tier 1) | ~95k stars | Medium (near-identical to Claude Code) |
|
||||
| 4 | OpenCode | Plugin (Tier 1) | ~110k stars | Medium (rich plugin SDK) |
|
||||
| 5 | Windsurf | Hooks (Tier 1) | ~1M users | Medium |
|
||||
| 6 | Codex CLI | Transcript (Tier 3) | Growing (OpenAI) | Low (schema already exists) |
|
||||
| 7 | OpenClaw | Plugin (Tier 1) — pre-built | ~196k stars | Low (wire into installer) |
|
||||
| 8 | Copilot CLI, Antigravity, Goose, Crush, Warp, Roo Code | MCP (Tier 2) | 20M+ combined | Low per IDE |
|
||||
| 9 | (remove old installer) | — | — | Low |
|
||||
| 10 | (final verification) | — | — | Low |
|
||||
|
||||
## Out of Scope
|
||||
|
||||
- **Removing Bun as runtime dependency**: Worker still requires Bun for `bun:sqlite`. Runtime commands delegate to Bun; install commands don't need it.
|
||||
- **JetBrains plugin**: Requires Kotlin/Java development — different ecosystem entirely.
|
||||
- **Zed extension**: WASM sandbox limits feasibility.
|
||||
- **Neovim/Emacs plugins**: Niche audiences, complex plugin ecosystems (Lua/Elisp). Could be added later via MCP (gptel supports it).
|
||||
- **Amazon Q / Kiro**: Amazon Q Developer CLI has been sunsetted in favor of Kiro (proprietary, no public extensibility API yet). Revisit when Kiro opens up.
|
||||
- **Aider**: Niche audience, writes Markdown transcripts (not JSONL), would require a markdown parser mode in the watcher. Add if demand materializes.
|
||||
- **Continue.dev**: Small user base relative to other MCP tools. Can be added as a Tier 2 MCP integration later if requested.
|
||||
- **Toad / Qwen Code / Oh-my-pi**: Too early-stage or too niche. Monitor for growth.
|
||||
- **OpenClaw plugin development**: The plugin is already complete. Only installer wiring is in scope.
|
||||
+97
-287
@@ -2,6 +2,103 @@
|
||||
|
||||
All notable changes to claude-mem.
|
||||
|
||||
## [v10.4.3] - 2026-02-25
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **Fix PostToolUse hook crashes and 5-second latency (#1220)**: Added missing `break` statements to all 7 switch cases in `worker-service.ts` preventing fall-through execution, added `.catch()` on `main()` to handle unhandled promise rejections, and removed redundant `start` commands from hook groups that triggered the 5-second `collectStdin()` timeout
|
||||
- **Fix CLAUDE_PLUGIN_ROOT fallback for Stop hooks (#1215)**: Added POSIX shell-level `CLAUDE_PLUGIN_ROOT` fallback in `hooks.json` for environments where the variable isn't injected, added script-level self-resolution via `import.meta.url` in `bun-runner.js`, and regression test added in `plugin-distribution.test.ts`
|
||||
|
||||
## Maintenance
|
||||
|
||||
- Synced all version files (plugin.json was stuck at 10.4.0)
|
||||
|
||||
## [v10.4.2] - 2026-02-25
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **Fix PostToolUse hook crashes and 5-second latency (#1220)**: Added missing `break` statements to all 7 switch cases in `worker-service.ts` preventing fall-through execution, added `.catch()` on `main()` to handle unhandled promise rejections, and removed redundant `start` commands from hook groups that triggered the 5-second `collectStdin()` timeout
|
||||
- **Fix CLAUDE_PLUGIN_ROOT fallback for Stop hooks (#1215)**: Added POSIX shell-level `CLAUDE_PLUGIN_ROOT` fallback in `hooks.json` for environments where the variable isn't injected, added script-level self-resolution via `import.meta.url` in `bun-runner.js`, and regression test added in `plugin-distribution.test.ts`
|
||||
- **Sync plugin.json version**: Fixed `plugin.json` being stuck at 10.4.0 while other version files were at 10.4.1
|
||||
|
||||
## [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
|
||||
@@ -1152,290 +1249,3 @@ Implemented interactive log filtering in the viewer UI:
|
||||
- **Smart Auto-Scroll** - Maintains scroll position when reviewing older logs
|
||||
- **Responsive Design** - Filter bar adapts to smaller screens
|
||||
|
||||
## [v8.5.3] - 2026-01-02
|
||||
|
||||
# 🛡️ Error Handling Hardening & Developer Tools
|
||||
|
||||
Version 8.5.3 introduces comprehensive error handling improvements that prevent silent failures and reduce debugging time from hours to minutes. This release also adds new developer tools for queue management and log monitoring.
|
||||
|
||||
---
|
||||
|
||||
## 🔴 Critical Error Handling Improvements
|
||||
|
||||
### The Problem
|
||||
A single overly-broad try-catch block caused a **10-hour debugging session** by silently swallowing errors. This pattern was pervasive throughout the codebase, creating invisible failure modes.
|
||||
|
||||
### The Solution
|
||||
|
||||
**Automated Anti-Pattern Detection** (`scripts/detect-error-handling-antipatterns.ts`)
|
||||
- Detects 7 categories of error handling anti-patterns
|
||||
- Enforces zero-tolerance policy for empty catch blocks
|
||||
- Identifies large try-catch blocks (>10 lines) that mask specific errors
|
||||
- Flags missing error logging that causes silent failures
|
||||
- Supports approved overrides with justification comments
|
||||
- Exit code 1 if critical issues detected (enforceable in CI)
|
||||
|
||||
**New Error Handling Standards** (Added to `CLAUDE.md`)
|
||||
- **5-Question Pre-Flight Checklist**: Required before writing any try-catch
|
||||
1. What SPECIFIC error am I catching?
|
||||
2. Show documentation proving this error can occur
|
||||
3. Why can't this error be prevented?
|
||||
4. What will the catch block DO?
|
||||
5. Why shouldn't this error propagate?
|
||||
- **Forbidden Patterns**: Empty catch, catch without logging, large try blocks, promise catch without handlers
|
||||
- **Allowed Patterns**: Specific errors, logged failures, minimal scope, explicit recovery
|
||||
- **Meta-Rule**: Uncertainty triggers research, NOT try-catch
|
||||
|
||||
### Fixes Applied
|
||||
|
||||
**Wave 1: Empty Catch Blocks** (5 files)
|
||||
- `import-xml-observations.ts` - Log skipped invalid JSON
|
||||
- `bun-path.ts` - Log when bun not in PATH
|
||||
- `cursor-utils.ts` - Log failed registry reads & corrupt MCP config
|
||||
- `worker-utils.ts` - Log failed health checks
|
||||
|
||||
**Wave 2: Promise Catches on Critical Paths** (8 locations)
|
||||
- `worker-service.ts` - Background initialization failures
|
||||
- `SDKAgent.ts` - Session processor errors (2 locations)
|
||||
- `GeminiAgent.ts` - Finalization failures (2 locations)
|
||||
- `OpenRouterAgent.ts` - Finalization failures (2 locations)
|
||||
- `SessionManager.ts` - Generator promise failures
|
||||
|
||||
**Wave 3: Comprehensive Audit** (29 catch blocks)
|
||||
- Added logging to 16 catch blocks (UI, servers, worker, routes, services)
|
||||
- Documented 13 intentional exceptions with justification comments
|
||||
- All patterns now follow error handling guidelines with appropriate log levels
|
||||
|
||||
### Approved Override System
|
||||
|
||||
For justified exceptions (performance-critical paths, expected failures), use:
|
||||
```typescript
|
||||
// [APPROVED OVERRIDE]: Brief technical justification
|
||||
try {
|
||||
// code
|
||||
} catch {
|
||||
// allowed exception
|
||||
}
|
||||
```
|
||||
|
||||
**Progress**: 163 anti-patterns → 26 approved overrides (84% reduction in silent failures)
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ Queue Management Features
|
||||
|
||||
**New Commands**
|
||||
- `npm run queue:clear` - Interactive removal of failed messages
|
||||
- `npm run queue:clear -- --all` - Clear all messages (pending, processing, failed)
|
||||
- `npm run queue:clear -- --force` - Non-interactive mode
|
||||
|
||||
**HTTP API Endpoints**
|
||||
- `DELETE /api/pending-queue/failed` - Remove failed messages
|
||||
- `DELETE /api/pending-queue/all` - Complete queue reset
|
||||
|
||||
Failed messages exceed max retry count and remain for debugging. These commands provide clean queue maintenance.
|
||||
|
||||
---
|
||||
|
||||
## 🪵 Developer Console (Chrome DevTools Style)
|
||||
|
||||
**UI Improvements**
|
||||
- Bottom drawer console (slides up from bottom-left corner)
|
||||
- Draggable resize handle for height adjustment
|
||||
- Auto-refresh toggle (2s interval)
|
||||
- Clear logs button with confirmation
|
||||
- Monospace font (SF Mono/Monaco/Consolas)
|
||||
- Minimum height: 150px, adjustable to window height - 100px
|
||||
|
||||
**API Endpoints**
|
||||
- `GET /api/logs` - Fetch last 1000 lines of current day's log
|
||||
- `DELETE /api/logs` - Clear current log file
|
||||
|
||||
Logs viewer accessible via floating console button in UI.
|
||||
|
||||
---
|
||||
|
||||
## 📚 Architecture Documentation
|
||||
|
||||
**Session ID Architecture** (`docs/SESSION_ID_ARCHITECTURE.md`)
|
||||
- Comprehensive documentation of 1:1 session mapping guarantees
|
||||
- 19 validation tests proving UNIQUE constraints and resume consistency
|
||||
- Documents single-transition vulnerability (application-level enforcement)
|
||||
- Complete reference for session lifecycle management
|
||||
|
||||
---
|
||||
|
||||
## 📊 Impact Summary
|
||||
|
||||
- **Debugging Time**: 10 hours → minutes (proper error visibility)
|
||||
- **Test Coverage**: +19 critical architecture validation tests
|
||||
- **Silent Failures**: 84% reduction (163 → 26 approved exceptions)
|
||||
- **Protection**: Automated detection prevents regression
|
||||
- **Developer UX**: Console logs, queue management, comprehensive docs
|
||||
|
||||
---
|
||||
|
||||
## 🔧 Technical Details
|
||||
|
||||
**Files Changed**: 25+ files across error handling, queue management, UI, and documentation
|
||||
|
||||
**Critical Path Protection**
|
||||
These files now have strict error propagation (no catch-and-continue):
|
||||
- `SDKAgent.ts`
|
||||
- `GeminiAgent.ts`
|
||||
- `OpenRouterAgent.ts`
|
||||
- `SessionStore.ts`
|
||||
- `worker-service.ts`
|
||||
|
||||
**Build Verification**: All changes tested, build successful
|
||||
|
||||
---
|
||||
|
||||
**Full Changelog**: https://github.com/thedotmack/claude-mem/compare/v8.5.2...v8.5.3
|
||||
|
||||
## [v8.5.2] - 2025-12-31
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
### Fixed SDK Agent Memory Leak (#499)
|
||||
|
||||
Fixed a critical memory leak where Claude SDK child processes were never terminated after sessions completed. Over extended usage, this caused hundreds of orphaned processes consuming 40GB+ of RAM.
|
||||
|
||||
**Root Cause:**
|
||||
- When the SDK agent generator completed naturally (no more messages to process), the `AbortController` was never aborted
|
||||
- Child processes spawned by the Agent SDK remained running indefinitely
|
||||
- Sessions stayed in memory (by design for future events) but underlying processes were never cleaned up
|
||||
|
||||
**Fix:**
|
||||
- Added proper cleanup to SessionRoutes finally block
|
||||
- Now calls `abortController.abort()` when generator completes with no pending work
|
||||
- Creates new `AbortController` when crash recovery restarts generators
|
||||
- Ensures cleanup happens even if recovery logic fails
|
||||
|
||||
**Impact:**
|
||||
- Prevents orphaned `claude` processes from accumulating
|
||||
- Eliminates multi-gigabyte memory leaks during normal usage
|
||||
- Maintains crash recovery functionality with proper resource cleanup
|
||||
|
||||
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
|
||||
|
||||
|
||||
@@ -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`
|
||||
|
||||
@@ -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,
|
||||
|
||||
Symlink
+1
@@ -0,0 +1 @@
|
||||
../../../plugin/skills/do/SKILL.md
|
||||
@@ -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
@@ -0,0 +1 @@
|
||||
../../../plugin/skills/make-plan/SKILL.md
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "10.4.0",
|
||||
"version": "10.4.4",
|
||||
"description": "Memory compression system for Claude Code - persist context across sessions",
|
||||
"keywords": [
|
||||
"claude",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "10.4.0",
|
||||
"version": "10.4.4",
|
||||
"description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions",
|
||||
"author": {
|
||||
"name": "Alex Newman"
|
||||
|
||||
@@ -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)
|
||||
@@ -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
@@ -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
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem-plugin",
|
||||
"version": "10.4.0",
|
||||
"version": "10.4.4",
|
||||
"private": true,
|
||||
"description": "Runtime dependencies for claude-mem bundled hooks",
|
||||
"type": "module",
|
||||
|
||||
@@ -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.
|
||||
---
|
||||
|
||||
@@ -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,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;
|
||||
|
||||
|
||||
@@ -233,31 +233,6 @@ NEVER fetch full details without filtering first. 10x token savings.`,
|
||||
handler: async (args: any) => {
|
||||
return await callWorkerAPIPost('/api/observations/batch', args);
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'save_observation',
|
||||
description: 'Save an observation to the database. Params: text (required), title, project',
|
||||
inputSchema: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
text: {
|
||||
type: 'string',
|
||||
description: 'Content to remember (required)'
|
||||
},
|
||||
title: {
|
||||
type: 'string',
|
||||
description: 'Short title (auto-generated from text if omitted)'
|
||||
},
|
||||
project: {
|
||||
type: 'string',
|
||||
description: 'Project name (uses "claude-mem" if omitted)'
|
||||
}
|
||||
},
|
||||
required: ['text']
|
||||
},
|
||||
handler: async (args: any) => {
|
||||
return await callWorkerAPIPost('/api/memory/save', args);
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -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
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
Reference in New Issue
Block a user