diff --git a/.gitignore b/.gitignore index 0723da81..baaa2b68 100644 --- a/.gitignore +++ b/.gitignore @@ -7,5 +7,4 @@ node_modules/ *.temp .claude/settings.local.json plugin/data/ -plugin/data.backup/ -plugin/scripts/package-lock.json \ No newline at end of file +plugin/data.backup/ \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 62fb8561..b838f4b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,19 +9,15 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Fixed - **Windows PowerShell compatibility**: Fixed SessionStart hook error on Windows systems - - Replaced bash-specific command (`[`, `&&`, `||`) with cross-platform Node.js installer - - Created `ensure-dependencies.js` script for automatic dependency installation - - Dependencies (`better-sqlite3`) now install correctly on Windows, macOS, and Linux - -### Added -- **Cross-platform dependency installer**: New `ensure-dependencies.js` script handles runtime dependency installation -- **Automatic package.json generation**: Build process now creates `package.json` in `plugin/scripts/` directory -- **Enhanced build output**: Build script now generates installer alongside hooks and services + - Replaced bash-specific test command `[` with standard cross-platform npm install + - Simplified hook command to use idempotent npm install (fast when dependencies exist) + - Dependencies install from root package.json in marketplace folder ### Changed -- **SessionStart hook command**: Now uses `node ensure-dependencies.js && node context-hook.js` instead of bash syntax -- **Build process**: Added installer script bundling and package.json generation steps -- **.gitignore**: Added `plugin/scripts/package-lock.json` to prevent version control conflicts +- **SessionStart hook command**: Now uses `cd ... && npm install --prefer-offline --no-audit --no-fund --loglevel=error && node context-hook.js` + - Removed bash-specific conditional check + - npm install is fast (~500ms) and idempotent when dependencies already exist + - Works cross-platform on Windows, macOS, and Linux ## [4.2.1] - 2025-10-22 diff --git a/CLAUDE.md b/CLAUDE.md index 2f4226dd..3314cab3 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -26,7 +26,7 @@ This creates a continuous memory system where Claude can learn from past session Claude-mem integrates with Claude Code through 5 lifecycle hooks: 1. **SessionStart Hook** (`context-hook`) - - Auto-installs dependencies on first run (cross-platform Node.js installer) + - Ensures dependencies are installed (runs fast idempotent npm install) - Injects context from previous sessions - Auto-starts PM2 worker service - Retrieves last 10 session summaries with three-tier verbosity (v4.2.0) @@ -201,16 +201,12 @@ npm run build && git commit -a -m "Build and update" && git push && cd ~/.claude ``` 1) Compiles TypeScript and outputs hook executables to `plugin/scripts/` -2) Generates `ensure-dependencies.js` - cross-platform installer script -3) Creates `package.json` in `plugin/scripts/` with runtime dependencies -4) Does all the things needed to update and test since plugin-based installs are out of the .claude/ folder +2) Does all the things needed to update and test since plugin-based installs are out of the .claude/ folder **Build Outputs**: - Hook executables: `*-hook.js` (ESM format) - Worker service: `worker-service.cjs` (CJS format) - Search server: `search-server.js` (ESM format) -- Dependency installer: `ensure-dependencies.js` (ESM format) -- Runtime manifest: `package.json` (includes `better-sqlite3` dependency) ## Version History @@ -219,15 +215,14 @@ npm run build && git commit -a -m "Build and update" && git push && cd ~/.claude **Fixes**: - Fixed Windows PowerShell compatibility issue with SessionStart hook -- Replaced bash-specific installation command with cross-platform Node.js installer -- Added `ensure-dependencies.js` script for automatic dependency installation -- Build process now generates `package.json` with runtime dependencies in `plugin/scripts/` +- Replaced bash-specific test command `[` with cross-platform npm install command +- Hook now runs `npm install` with quiet flags (fast and idempotent when dependencies exist) **Technical Details**: -- Created `src/bin/ensure-dependencies.ts` for cross-platform dependency management -- Updated `plugin/hooks/hooks.json` to use Node.js command chain instead of shell syntax -- Dependencies (`better-sqlite3`) are now installed automatically on first run across all platforms -- Added `.gitignore` rule for `plugin/scripts/package-lock.json` +- Updated `plugin/hooks/hooks.json` SessionStart command to use standard shell syntax +- Changed from: `[ ! -d ... ] && cd ... && npm install && node ... || node ...` +- Changed to: `cd ... && npm install --prefer-offline --no-audit --no-fund --loglevel=error && node ...` +- Dependencies are installed in marketplace folder (parent of CLAUDE_PLUGIN_ROOT) where root package.json exists ### v4.2.0 **Breaking Changes**: None (minor version) diff --git a/README.md b/README.md index d48b8277..2f3365f9 100644 --- a/README.md +++ b/README.md @@ -255,7 +255,7 @@ npm install -g claude-mem 1. **Automatic Dependency Installation** - The plugin automatically installs required dependencies (`better-sqlite3`) on first run. This happens when you first start Claude Code after installation. The process is cross-platform and works on Windows, macOS, and Linux. + Dependencies are installed automatically during plugin installation. The SessionStart hook also ensures dependencies are up-to-date on each session start (this is fast and idempotent). Works cross-platform on Windows, macOS, and Linux. 2. **Verify Plugin Installation** diff --git a/plugin/hooks/hooks.json b/plugin/hooks/hooks.json index 282291a0..a069acb7 100644 --- a/plugin/hooks/hooks.json +++ b/plugin/hooks/hooks.json @@ -6,7 +6,7 @@ "hooks": [ { "type": "command", - "command": "node ${CLAUDE_PLUGIN_ROOT}/scripts/ensure-dependencies.js && node ${CLAUDE_PLUGIN_ROOT}/scripts/context-hook.js", + "command": "cd \"${CLAUDE_PLUGIN_ROOT}/..\" && npm install --prefer-offline --no-audit --no-fund --loglevel=error && node ${CLAUDE_PLUGIN_ROOT}/scripts/context-hook.js", "timeout": 120 } ] diff --git a/plugin/scripts/ensure-dependencies.js b/plugin/scripts/ensure-dependencies.js deleted file mode 100755 index 092c9934..00000000 --- a/plugin/scripts/ensure-dependencies.js +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env node - -// src/bin/ensure-dependencies.ts -import { existsSync, mkdirSync, writeFileSync } from "fs"; -import { join, dirname } from "path"; -import { execSync } from "child_process"; -import { fileURLToPath } from "url"; -function getDirname() { - return typeof __dirname !== "undefined" ? __dirname : dirname(fileURLToPath(import.meta.url)); -} -var scriptDir = getDirname(); -var isBuilt = scriptDir.includes("plugin/scripts") || scriptDir.includes("plugin\\scripts"); -var targetDir = isBuilt ? scriptDir : join(scriptDir, "../../plugin/scripts"); -var nodeModulesPath = join(targetDir, "node_modules"); -var packageJsonPath = join(targetDir, "package.json"); -if (existsSync(nodeModulesPath)) { - const betterSqlitePath = join(nodeModulesPath, "better-sqlite3"); - if (existsSync(betterSqlitePath)) { - process.exit(0); - } -} -if (!existsSync(targetDir)) { - mkdirSync(targetDir, { recursive: true }); -} -if (!existsSync(packageJsonPath)) { - const packageJson = { - name: "claude-mem-scripts", - version: "4.2.1", - description: "Runtime dependencies for claude-mem plugin hooks", - private: true, - type: "module", - dependencies: { - "better-sqlite3": "^11.0.0" - } - }; - writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); -} -try { - console.log("Installing claude-mem dependencies..."); - execSync("npm install --prefer-offline --no-audit --no-fund --loglevel error", { - cwd: targetDir, - stdio: "inherit" - }); - console.log("Dependencies installed successfully."); - process.exit(0); -} catch (error) { - console.error("Failed to install dependencies:", error.message); - process.exit(1); -} diff --git a/plugin/scripts/package.json b/plugin/scripts/package.json deleted file mode 100644 index 0bee6074..00000000 --- a/plugin/scripts/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "claude-mem-scripts", - "version": "4.2.1", - "description": "Runtime dependencies for claude-mem plugin hooks", - "private": true, - "type": "module", - "dependencies": { - "better-sqlite3": "^11.0.0" - } -} \ No newline at end of file diff --git a/scripts/build-hooks.js b/scripts/build-hooks.js index a776822f..b221cf1a 100644 --- a/scripts/build-hooks.js +++ b/scripts/build-hooks.js @@ -30,11 +30,6 @@ const SEARCH_SERVER = { source: 'src/servers/search-server.ts' }; -const INSTALLER = { - name: 'ensure-dependencies', - source: 'src/bin/ensure-dependencies.ts' -}; - async function buildHooks() { console.log('šŸ”Ø Building claude-mem hooks, worker service, and search server...\n'); @@ -133,52 +128,11 @@ async function buildHooks() { const searchStats = fs.statSync(`${hooksDir}/${SEARCH_SERVER.name}.js`); console.log(`āœ“ search-server built (${(searchStats.size / 1024).toFixed(2)} KB)`); - // Build dependency installer - console.log(`\nšŸ”§ Building dependency installer...`); - await build({ - entryPoints: [INSTALLER.source], - bundle: true, - platform: 'node', - target: 'node18', - format: 'esm', - outfile: `${hooksDir}/${INSTALLER.name}.js`, - minify: false, // Keep readable for debugging - banner: { - js: '#!/usr/bin/env node' - } - }); - - // Make installer executable - fs.chmodSync(`${hooksDir}/${INSTALLER.name}.js`, 0o755); - const installerStats = fs.statSync(`${hooksDir}/${INSTALLER.name}.js`); - console.log(`āœ“ installer built (${(installerStats.size / 1024).toFixed(2)} KB)`); - - // Create package.json for plugin/scripts - console.log('\nšŸ“¦ Creating package.json...'); - const scriptsPackageJson = { - name: 'claude-mem-scripts', - version: version, - description: 'Runtime dependencies for claude-mem plugin hooks', - private: true, - type: 'module', - dependencies: { - 'better-sqlite3': '^11.0.0' - } - }; - - fs.writeFileSync( - `${hooksDir}/package.json`, - JSON.stringify(scriptsPackageJson, null, 2) - ); - console.log('āœ“ package.json created'); - console.log('\nāœ… All hooks, worker service, and search server built successfully!'); console.log(` Output: ${hooksDir}/`); console.log(` - Hooks: *-hook.js`); console.log(` - Worker: worker-service.cjs`); console.log(` - Search: search-server.js`); - console.log(` - Installer: ensure-dependencies.js`); - console.log(` - Dependencies: package.json`); console.log('\nšŸ’” Note: Dependencies will be auto-installed on first hook execution'); } catch (error) { diff --git a/src/bin/ensure-dependencies.ts b/src/bin/ensure-dependencies.ts deleted file mode 100644 index 10ee3a0d..00000000 --- a/src/bin/ensure-dependencies.ts +++ /dev/null @@ -1,66 +0,0 @@ -/** - * Cross-platform dependency installer for claude-mem plugin hooks - * Ensures better-sqlite3 is installed in the plugin/scripts directory - */ - -import { existsSync, mkdirSync, writeFileSync } from 'fs'; -import { join, dirname } from 'path'; -import { execSync } from 'child_process'; -import { fileURLToPath } from 'url'; - -function getDirname() { - return typeof __dirname !== 'undefined' ? __dirname : dirname(fileURLToPath(import.meta.url)); -} - -const scriptDir = getDirname(); - -// Determine if we're in the built plugin/scripts directory or src/bin -const isBuilt = scriptDir.includes('plugin/scripts') || scriptDir.includes('plugin\\scripts'); -const targetDir = isBuilt ? scriptDir : join(scriptDir, '../../plugin/scripts'); - -const nodeModulesPath = join(targetDir, 'node_modules'); -const packageJsonPath = join(targetDir, 'package.json'); - -// Check if better-sqlite3 is already installed -if (existsSync(nodeModulesPath)) { - const betterSqlitePath = join(nodeModulesPath, 'better-sqlite3'); - if (existsSync(betterSqlitePath)) { - // Dependencies already installed - process.exit(0); - } -} - -// Ensure target directory exists -if (!existsSync(targetDir)) { - mkdirSync(targetDir, { recursive: true }); -} - -// Create minimal package.json if it doesn't exist -if (!existsSync(packageJsonPath)) { - const packageJson = { - name: 'claude-mem-scripts', - version: '4.2.1', - description: 'Runtime dependencies for claude-mem plugin hooks', - private: true, - type: 'module', - dependencies: { - 'better-sqlite3': '^11.0.0' - } - }; - - writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2)); -} - -// Install dependencies -try { - console.log('Installing claude-mem dependencies...'); - execSync('npm install --prefer-offline --no-audit --no-fund --loglevel error', { - cwd: targetDir, - stdio: 'inherit' - }); - console.log('Dependencies installed successfully.'); - process.exit(0); -} catch (error: any) { - console.error('Failed to install dependencies:', error.message); - process.exit(1); -}