Commit Graph

23 Commits

Author SHA1 Message Date
Jesse Vincent 30916f8cad feat(harness): add Cursor (#113) and opencode (#117) support
Adds Cursor (live transcripts + opt-in state.vscdb backfill) and opencode (DB->JSONL export) as harnesses, following the existing Codex pattern. opencode summarization is fixed to route via transcript text instead of a doomed claude --resume, and hasConversationContent recognizes opencode_message lines. Harness union is 'claude'|'codex'|'cursor'|'opencode'. Also pins conversation timestamps to en-US/UTC in every renderer (#130) and restores valid YAML in the search agent frontmatter (#153).

Co-authored-by: vicnaum <vicnaum@users.noreply.github.com>

Co-authored-by: slandau3 <slandau3@users.noreply.github.com>

Co-authored-by: arimu1 <arimu1@users.noreply.github.com>

Claude-Session: https://claude.ai/code/session_0112vdwZphiWzfCYfaXMes4C
2026-09-08 18:47:47 +00:00
Jesse Vincent cbc4881732 fix(install): verify the native binding loads instead of trusting exit codes (#150)
Co-authored-by: PauloACRibeiro <PauloACRibeiro@users.noreply.github.com>

Claude-Session: https://claude.ai/code/session_0112vdwZphiWzfCYfaXMes4C
2026-09-08 18:05:10 +00:00
Jesse Vincent 6303454940 fix: single-instance lock for sync --background (#97)
Independent SessionStart events from multiple Claude Code sessions
each fire `episodic-memory sync --background`, which forks a detached
worker. Without coordination, N parents trigger N concurrent worker
processes racing the same archive and SQLite database.

The reentrancy guard (#87) covers same-process recursion, but it
can't stop SessionStart events from independent sessions whose envs
don't carry EPISODIC_MEMORY_SUMMARIZER_GUARD.

Reproduced locally on macOS: 3 parallel `node dist/sync-cli.js`
processes against the same TEST_ARCHIVE_DIR — worker 1 completes;
workers 2 and 3 crash with `SqliteError: database is locked`
(SQLITE_BUSY) trying to init the DB. On Windows, the reporter's
setup with ~67 worktrees instead piles up enough claude.exe children
to exhaust the desktop heap and crash with STATUS_DLL_INIT_FAILED
(0xC0000142). Same root cause; different blast radius depending on
how far the workers get before stepping on each other.

Fix: a single-instance lock around the sync worker, implemented as a
thin wrapper in src/file-lock.ts over the `proper-lockfile` package.
A first attempt at a hand-rolled openSync('wx') + PID-file protocol
had a residual race under concurrent stale-stealers that pure file
primitives cannot fully close without advisory locking.
proper-lockfile uses an atomic-mkdir + mtime-heartbeat protocol that
is race-free under that contention shape — the same approach npm
itself uses.

sync-cli.ts acquires <log-dir>/episodic-memory-sync.lock after the
source-dir check and before initDatabase(); if another live process
holds it, the worker prints "sync already running (pid X); skipping"
to stderr and exits 0. The lock releases on normal exit and on the
common signals (SIGINT/SIGTERM/SIGHUP).

Embedding migration's own lock now delegates to the generic helper;
its old export names (acquireMigrationLock, releaseMigrationLock,
MigrationLockHandle) stay for back-compat.

proper-lockfile is excluded from the esbuild bundle (runtime dep on
the same level as better-sqlite3/transformers/etc.) so the MCP
server bundle size is unchanged. The wrapper's install-health probe
(#95 Bug 1) gains proper-lockfile as a required package so a partial
extraction surfaces a useful diagnostic.

Tests:
- test/file-lock.test.ts: acquire/release, contention,
  parent-dir creation, garbage diagnostic content, I/O error
  propagation, N-concurrent-acquirers stress test, mtime-based
  stale recovery, fresh-lock-not-reclaimable. Subprocess imports
  use pathToFileURL for Windows compatibility.
- test/sync-cli-single-instance.test.ts: integration via real
  child-process spawn — two concurrent workers (one completes,
  one skips), single sequential run still works, lock released
  on normal exit, stale lock from a dead PID is reclaimable.
- Existing test/embedding-migration.test.ts continues to pass.

Closes #97.
2026-05-21 11:26:10 -07:00
Jesse Vincent 32c8382c2d fix: probe each required package's manifest before launching the MCP server (#95 Bug 1)
cli/mcp-server-wrapper.js previously checked only `existsSync(node_modules)`
to decide whether to run `npm install`. A partial extraction — the
directory exists, but a package is missing its package.json and lib/ —
slips past that check, hands off to dist/mcp-server.js, and crashes with
a confusing `ERR_MODULE_NOT_FOUND` after the wrapper has already declared
deps healthy. The reporter on Windows 11 saw exactly this for
better-sqlite3 (folder contained only `deps/` and `LICENSE`).

New module cli/install-check.js exports findMissingDeps(pluginRoot) which
returns the list of runtime-required packages whose package.json is
missing under node_modules. The wrapper now logs the missing packages
before re-running `npm install`, giving the user a useful diagnostic when
the partial-extract case strikes again.

Probing each package's manifest — not just the directory — catches the
specific failure shape that originally motivated the issue. Optional and
OS-specific externals (sharp, fsevents) are deliberately excluded from
the check.

Tests in test/install-check.test.ts cover the no-node_modules case, the
empty-node_modules case, the all-present happy path, the
partial-extraction case (better-sqlite3 dir present but manifest gone),
multi-missing reporting, and the optional-deps-excluded behavior.

Addresses Bug 1 of #95; Bug 2 (onnxruntime-common hoisting) is deferred
pending a Windows reproduction.
2026-05-21 10:22:50 -07:00
Jesse Vincent a97fd5ef3b fix: harden Codex production support 2026-05-12 15:38:46 -07:00
Jesse Vincent da18d8de63 feat: make skills and hooks Codex-aware 2026-05-12 13:12:49 -07:00
Matt Van Horn 99b4dfb8c3 fix: remove --prefer-offline from MCP wrapper npm install (#76) (#86)
The --prefer-offline flag instructs npm to skip the registry when local
metadata exists, even if it's stale. On a fresh plugin install where the
user's npm cache is older than the plugin's better-sqlite3 dependency
range (^12.4.1), npm fails with ETARGET because the cached metadata still
points at older versions, and the MCP server never starts.

Dropping the flag lets npm refresh metadata as needed. The other two
flags (--no-audit --no-fund) are kept; they suppress noise but do not
gate registry access.

Fixes #76
2026-05-02 15:31:01 -07:00
Jesse Vincent c656adc64e fix: Add SIGHUP handler and stdin close detection to prevent orphaned MCP processes (#54)
Forward terminal hangup signal to child process, and detect parent
death via stdin close to catch kill -9 and crashes.

Fixes #53

Co-authored-by: Zohaib Shahab <57931096+shahabzohaib@users.noreply.github.com>
2026-03-27 18:18:55 -07:00
Jesse Vincent 1a592f02f0 Remove package-lock.json deletion from MCP wrapper
Stop shipping package-lock.json (was tracked despite .gitignore) and
remove the code that deleted it on first run. This was a sledgehammer
fix for cross-platform optional dependencies - npm handles this fine
without a lockfile present.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 21:31:45 +00:00
Jesse Vincent 9c342901f6 Use compiled JS for all CLI commands, remove tsx from runtime
- Route all CLI commands through dist/*.js instead of npx tsx src/*.ts
- Fixes background sync silently failing (#25 root cause)
- Faster startup, lighter runtime dependencies
- tsx is now dev-only

This properly fixes the issue @stromseth identified in PR #25 by
addressing the root cause rather than just the sync command.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 22:08:45 +00:00
Jesse Vincent 218a14ec85 Replace bash CLI scripts with Node.js wrappers
- Convert all CLI entry points (episodic-memory, index-conversations,
  search-conversations, mcp-server) from bash to Node.js
- Add search-conversations.js to complete Node.js CLI coverage
- Update SessionStart hook to call node directly
- Eliminates bash dependency for full cross-platform support
  (Windows, NixOS, etc.)

Obsoletes PRs #29, #17, #11 which all modified bash scripts.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-14 21:06:48 +00:00
Andrew Choi 5c109fa7da Fix: Windows spawn ENOENT error - Add shell option for npx commands (#36)
* Fix: Add Windows compatibility for spawn() in runCommand()

Fixes spawn ENOENT error on Windows when running npx commands.

On Windows, npx is a .cmd file, not an executable. The spawn() function
requires shell:true to execute .cmd files, otherwise it fails with ENOENT.

This fix adds shell: process.platform === 'win32' to the spawn options,
matching the pattern already used in mcp-server-wrapper.js:43.

Before this fix:
- spawn('npx', ...) → Error: spawn npx ENOENT
- Plugin fails to initialize on Windows
- SessionStart hook fails silently

After this fix:
- spawn('npx', ..., {shell: true}) → Works correctly
- Plugin initializes and syncs successfully
- All features work as expected on Windows

Tested on:
- Windows 10/11
- Node.js v22.14.0
- Verified sync command executes successfully

* Fix: Apply Windows spawn fix to index-conversations.js

Addresses CodeRabbit's review feedback - the same Windows spawn issue
affects index-conversations.js.

This file also spawns npx without the shell option, causing the same
ENOENT error on Windows. Applied the identical fix for consistency.

Changes:
- Added shell: process.platform === 'win32' to spawn() options in runTsxCommand()
- Matches the pattern in episodic-memory.js and mcp-server-wrapper.js

This ensures all npx spawn calls work correctly on Windows.
2025-12-14 11:13:04 -08:00
Jesse Vincent d8ef256b1b Remove obsolete bash script mcp-server-wrapper
The bash script cli/mcp-server-wrapper is no longer needed since we now use
the cross-platform Node.js version cli/mcp-server-wrapper.js for Windows
compatibility.

This eliminates dead code and prevents confusion about which wrapper to use.
All MCP server functionality now goes through the Node.js wrapper.
2025-10-31 14:29:14 -07:00
Jesse Vincent 172f389938 Release v1.0.8: Fix Windows support for MCP server (closes #7)
This release resolves Windows compatibility issues with the MCP server by replacing
the bash script wrapper with a cross-platform Node.js implementation.

### Key Changes:
- Replace bash script `mcp-server-wrapper` with Node.js version `mcp-server-wrapper.js`
- Update plugin.json to use `node cli/mcp-server-wrapper.js` instead of bash script
- Add Windows-compatible npm command detection (npm.cmd vs npm)
- Improve signal forwarding and error handling in wrapper

### Files Updated:
- Created: cli/mcp-server-wrapper.js (cross-platform Node.js wrapper)
- Modified: .claude-plugin/plugin.json (MCP server command)
- Updated: CHANGELOG.md, package.json, marketplace.json files
- Version: 1.0.7 → 1.0.8

### Windows Support:
- MCP server now works with Claude Code native install on Windows
- Resolves "/bin/bash: No such file or directory" errors
- Proper dependency installation across all platforms

Closes #7
2025-10-31 14:25:12 -07:00
Jesse Vincent f8b5833898 Release v1.0.6: Critical installation fixes for Windows and macOS ARM64 (#6)
* Fix critical installation issues #1 and #4

Addresses GitHub issues #1 (Windows CLI execution failure) and #4 (sqlite-vec extension loading).

Issue #4 - sqlite-vec extension loading:
- Add --external:sqlite-vec to esbuild configuration
- Prevents bundling sqlite-vec, preserving native module loading
- Fixes "Loadable extension for sqlite-vec not found" error on macOS ARM64 and Linux

Issue #1 - Windows CLI execution failure:
- Create cross-platform Node.js CLI implementation (cli/episodic-memory.js)
- Create Node.js version of index-conversations script
- Add proper symlink resolution with realpathSync()
- Remove shell dependency for improved security
- Add comprehensive error handling and npx availability checks
- Update package.json bin entries to use Node.js scripts
- Remove unnecessary .cmd wrapper file

Technical improvements:
- All 71 tests pass
- No regressions to existing functionality
- Enhanced cross-platform compatibility
- Better error messages and debugging info
- Eliminated command injection vulnerabilities

Both issues now fully resolved with Windows, macOS, and Linux support.

* Release v1.0.6: Critical installation fixes for Windows and macOS ARM64

* Update CHANGELOG.md for v1.0.6 release

- Document fixes for GitHub issues #1 and #4
- Add comprehensive details about Windows CLI and macOS ARM64/Linux sqlite-vec fixes
- Include security improvements and cross-platform compatibility enhancements
2025-10-27 19:30:17 -07:00
Jesse Vincent 47ce8ce5fc Release v1.0.5: Fix sqlite-vec optional dependency installation
Fix MCP server startup error by ensuring platform-specific sqlite-vec
packages are installed correctly. The issue was that npm would use an
existing package-lock.json that didn't include the platform-specific
optional dependencies.

Changes:
- Wrapper script now deletes package-lock.json before npm install
- Add package-lock.json to .gitignore to prevent cross-platform issues
- Bump version to 1.0.5
- Update CHANGELOG.md

Testing:
- Reproduced error by removing sqlite-vec-darwin-arm64 package
- Confirmed fix: deleting package-lock.json ensures correct installation
- All 71 tests pass

Fixes: Error "Loadable extension for sqlite-vec not found. Was the
sqlite-vec-darwin-arm64 package installed?"
2025-10-25 13:41:21 -07:00
Jesse Vincent c9c4e8ae31 Release v1.0.3: Auto-install dependencies via MCP server wrapper
Fix MCP server startup errors by implementing a wrapper script that
automatically runs npm install before starting the server. This solves
the "Cannot find module" errors that occurred because MCP servers start
before SessionStart hooks can run.

Changes:
- Add cli/mcp-server-wrapper that checks for node_modules and runs npm install
- Update plugin.json to use wrapper script instead of direct node execution
- Add esbuild bundling to reduce dependency size
- Remove cli/ensure-dependencies (no longer needed)
- Remove ensure-dependencies from SessionStart hook
- Bump version to 1.0.3 in package.json, plugin.json, marketplace.json
- Update CHANGELOG.md

Fixes: Error [ERR_MODULE_NOT_FOUND]: Cannot find package '@modelcontextprotocol/sdk'
2025-10-23 15:13:37 -07:00
Jesse Vincent 0e11bef16b Release v1.0.1: Automatic dependency installation
Add automatic npm install on plugin installation via SessionStart hook.
This ensures dependencies are available after plugin install without
requiring manual intervention.

Changes:
- Add ensure-dependencies script to check and install npm packages
- Update SessionStart hook to run dependency check before sync
- Bump version to 1.0.1 in package.json and plugin.json
- Add CHANGELOG.md to track releases

Fixes the issue where plugin dependencies were not automatically
installed after running /plugin install.
2025-10-23 14:06:39 -07:00
Jesse Vincent a4f14359be Add MCP server and Claude Code plugin integration with resume-based summarization
- Created MCP server (src/mcp-server.ts) with 2 tools:
  - episodic_memory_search: Unified single/multi-concept search
  - episodic_memory_show: Display full conversations in markdown
- Added Claude Code plugin structure (.claude-plugin/, hooks/, commands/)
- Implemented resume-based summarization using SDK resume option
- Updated sync to generate summaries for all conversations (max 10/run)
- Consolidated plugin config to top level, removed old claude-code-plugin/ dir
- Added MCP dependencies (@modelcontextprotocol/sdk, zod)
- SessionEnd hook automatically syncs and indexes conversations
- Improved summarization prompt with context about search usage
2025-10-15 10:56:15 -07:00
Jesse Vincent 16f4d46a7a Add sync command for session-end hook integration
Implements episodic-memory sync to copy and index new conversations atomically.

Features:
- Copies .jsonl files from ~/.claude/projects to archive
- Only copies new or modified files (mtime check)
- Generates embeddings and indexes copied files
- Idempotent - safe to run repeatedly
- No explicit locking - uses atomic operations + SQLite WAL

Race condition handling:
- Atomic file copy (temp + rename)
- SQLite WAL mode for concurrent database writes
- mtime checks prevent duplicate copies
- last_indexed prevents duplicate indexing

Designed for Claude Code session-end hooks to automatically index
conversations without blocking or causing conflicts.

Tests: 66/66 passing including 5 new sync tests
2025-10-14 00:04:57 -07:00
Jesse Vincent 25e1ff539f Add stats command and fix unified CLI symlink handling
- Implements episodic-memory stats to show index statistics
- Displays conversation counts, date ranges, project breakdowns
- Shows summary coverage (important for search result quality)
- Fixes unified CLI to resolve symlinks properly for npm link
- Updates search routing to use TypeScript directly

Stats output includes:
- Total conversations and exchanges
- Summary coverage percentage
- Date range (earliest to latest)
- Top 10 projects by conversation count
2025-10-13 23:33:35 -07:00
Jesse Vincent cdd9375b41 Add conversation display with unified CLI and rich formatting
Implements episodic-memory show command to display conversations in human-readable formats.

New features:
- Unified CLI: episodic-memory <command> (index, search, show)
- Show command with markdown and HTML output formats
- Markdown rendering for rich assistant responses
- Sidechain grouping with visual indicators
- Inline tool results paired with tool calls
- Linkable message anchors
- Compact token usage display
- Role labels (User/Agent in main, Agent/Subagent in sidechains)
- Clean Apple-inspired design for HTML output
- Filters out system messages (file-history-snapshot, etc.)

The show command makes conversations readable in terminal (markdown) or browser (HTML),
preserving all conversation details including tool calls, results, and parallel execution.
2025-10-13 21:04:57 -07:00
Jesse Vincent be4f28a47f Initial episodic-memory package and plugin
Extract remembering-conversations skill from superpowers into standalone
package with Claude Code plugin integration.

Architecture:
- Core package (root): Installable npm package for indexing and search
- Claude Code plugin (claude-code-plugin/): Plugin integration with hooks and commands
- CLI tools (cli/): Standalone command-line utilities

Features:
- Semantic search using Transformers.js embeddings
- Exact text search for SHAs and error codes
- SQLite + sqlite-vec for vector similarity
- AI-generated conversation summaries
- Auto-indexing via SessionEnd hook
- /search-conversations slash command
2025-10-13 11:15:04 -07:00