Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 19af455c57 | |||
| b5807aed2e |
@@ -10,7 +10,7 @@
|
||||
"plugins": [
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "7.1.1",
|
||||
"version": "7.1.2",
|
||||
"source": "./plugin",
|
||||
"description": "Persistent memory system for Claude Code - context compression across sessions"
|
||||
}
|
||||
|
||||
+27
-81
@@ -4,93 +4,39 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
|
||||
## [7.1.1] - 2025-12-12
|
||||
## [7.1.1] - 2025-12-13
|
||||
|
||||
### Fixed
|
||||
## 🚨 Critical Fixes
|
||||
|
||||
**CRITICAL: Windows 11 Bun Auto-Install Broken**
|
||||
### Windows 11 Bun Auto-Install Fixed
|
||||
- **Problem**: v7.1.0 had a chicken-and-egg bug where `bun smart-install.js` failed if Bun wasn't installed
|
||||
- **Solution**: SessionStart hook now uses `node` (always available) for smart-install.js
|
||||
- **Impact**: Fresh Windows installations now work out-of-box
|
||||
|
||||
- **Chicken-and-Egg Problem**: v7.1.0 hooks called `bun smart-install.js`, but if Bun wasn't installed, the command failed with "bun is not recognized" before smart-install.js could run to install Bun
|
||||
- **Root Cause**: v7.1.0 migration removed Bun/uv auto-installation logic from smart-install.js
|
||||
- **Solution**:
|
||||
- Changed SessionStart hook to use `node` (always available) for smart-install.js
|
||||
- Restored Bun auto-installation logic: isBunInstalled(), installBun()
|
||||
- Restored uv auto-installation for Chroma support
|
||||
- Fresh Windows installations now work correctly
|
||||
### Path Quoting for Windows
|
||||
- Fixed `hooks.json` to quote all paths
|
||||
- Prevents SyntaxError for usernames with spaces (e.g., "C:\Users\John Doe\")
|
||||
|
||||
**Path Quoting for Windows Usernames with Spaces**
|
||||
## ✨ New Feature
|
||||
|
||||
- Fixed `hooks.json` to quote all `${CLAUDE_PLUGIN_ROOT}` paths
|
||||
- Prevents SyntaxError for Windows users with spaces in usernames (e.g., "C:\Users\John Doe\...")
|
||||
### Automatic Worker Restart on Version Updates
|
||||
- Worker now automatically restarts when plugin version changes
|
||||
- No more manual `npm run worker:restart` needed after upgrades
|
||||
- Eliminates connection errors from running old worker code
|
||||
|
||||
### Added
|
||||
## 📝 Notes
|
||||
|
||||
**Automatic Worker Restart on Version Updates**
|
||||
- **No manual actions required** - worker auto-restarts on next session start
|
||||
- All future upgrades will automatically restart the worker
|
||||
- Fresh installs on Windows 11 work correctly
|
||||
|
||||
- Added `/api/version` endpoint to worker service
|
||||
- Added version checking in `ensureWorkerRunning()`:
|
||||
- Compares plugin version with running worker version
|
||||
- Automatically restarts worker when version mismatch detected
|
||||
- Logs version mismatch for debugging
|
||||
- **Impact**: Users no longer need to manually restart worker after upgrades
|
||||
- **Critical for**: All future releases - eliminates connection errors from running old worker code
|
||||
## 🔗 Links
|
||||
|
||||
### Notes
|
||||
|
||||
- No manual actions required - worker auto-restarts on next session start
|
||||
- Fresh installs on Windows 11 now work out-of-box
|
||||
- All hooks now run with correct runtime (node for install, bun for execution)
|
||||
- [Full Changelog](https://github.com/thedotmack/claude-mem/blob/main/CHANGELOG.md#711---2025-12-12)
|
||||
- [Documentation](https://docs.claude-mem.ai)
|
||||
|
||||
## [7.1.0] - 2025-12-13
|
||||
|
||||
## Security Fix: Localhost-Only Binding
|
||||
|
||||
**BREAKING CHANGE**: Worker service now binds to `127.0.0.1` (localhost) by default instead of `0.0.0.0` (all interfaces).
|
||||
|
||||
### Security Issue Fixed
|
||||
|
||||
The worker service was previously binding to `0.0.0.0:37777` by default, exposing all API endpoints to the network without authentication. This posed security risks:
|
||||
- Unauthorized access to memory data from any network device
|
||||
- Potential data injection into the database
|
||||
- Settings modification from remote devices
|
||||
- Full access to Web Viewer UI from the network
|
||||
|
||||
### Solution
|
||||
|
||||
Default worker binding changed to `127.0.0.1` (localhost-only), with a new configurable setting `CLAUDE_MEM_WORKER_HOST` for users who need remote access.
|
||||
|
||||
### Changes
|
||||
|
||||
- **Core**: Added `CLAUDE_MEM_WORKER_HOST` setting with default value `127.0.0.1`
|
||||
- **Worker**: Modified `worker-service.ts` to bind to configured host address
|
||||
- **API**: Added host validation in `SettingsRoutes.ts` (IP address format check)
|
||||
- **UI**: Added host configuration field in Settings panel
|
||||
- **Docs**: Updated README.md and CLAUDE.md with new setting
|
||||
|
||||
### Configuration
|
||||
|
||||
**Default (secure):** localhost only
|
||||
```bash
|
||||
CLAUDE_MEM_WORKER_HOST=127.0.0.1
|
||||
```
|
||||
|
||||
**Remote access (server deployments):**
|
||||
```bash
|
||||
CLAUDE_MEM_WORKER_HOST=0.0.0.0
|
||||
```
|
||||
|
||||
Can be configured via:
|
||||
- `~/.claude-mem/settings.json`
|
||||
- Web Viewer UI Settings panel
|
||||
|
||||
### Migration
|
||||
|
||||
**Automatic**: Existing installations will use `127.0.0.1` on next worker restart. If you need remote access, set `CLAUDE_MEM_WORKER_HOST=0.0.0.0` in `~/.claude-mem/settings.json`.
|
||||
|
||||
### Contributors
|
||||
|
||||
Thanks to @7Sageer for identifying and fixing this security issue!
|
||||
|
||||
## Major Architectural Migration
|
||||
|
||||
This release completely replaces PM2 with native Bun-based process management and migrates from better-sqlite3 to bun:sqlite.
|
||||
@@ -1991,12 +1937,12 @@ None (patch version)
|
||||
|
||||
## [4.3.0] - 2025-10-25
|
||||
|
||||
## What's Changed
|
||||
* feat: Enhanced context hook with session observations and cross-platform improvements by @thedotmack in https://github.com/thedotmack/claude-mem/pull/25
|
||||
|
||||
## New Contributors
|
||||
* @thedotmack made their first contribution in https://github.com/thedotmack/claude-mem/pull/25
|
||||
|
||||
## What's Changed
|
||||
* feat: Enhanced context hook with session observations and cross-platform improvements by @thedotmack in https://github.com/thedotmack/claude-mem/pull/25
|
||||
|
||||
## New Contributors
|
||||
* @thedotmack made their first contribution in https://github.com/thedotmack/claude-mem/pull/25
|
||||
|
||||
**Full Changelog**: https://github.com/thedotmack/claude-mem/compare/v4.2.11...v4.3.0
|
||||
|
||||
## [4.2.10] - 2025-10-25
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
Claude-mem is a Claude Code plugin providing persistent memory across sessions. It captures tool usage, compresses observations using the Claude Agent SDK, and injects relevant context into future sessions.
|
||||
|
||||
**Current Version**: 7.1.1
|
||||
**Current Version**: 7.1.2
|
||||
|
||||
## Architecture
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "7.1.1",
|
||||
"version": "7.1.2",
|
||||
"description": "Memory compression system for Claude Code - persist context across sessions",
|
||||
"keywords": [
|
||||
"claude",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "claude-mem",
|
||||
"version": "7.1.1",
|
||||
"version": "7.1.2",
|
||||
"description": "Persistent memory system for Claude Code - seamlessly preserve context across sessions",
|
||||
"author": {
|
||||
"name": "Alex Newman"
|
||||
|
||||
@@ -24,18 +24,56 @@ function isBunInstalled() {
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
shell: IS_WINDOWS
|
||||
});
|
||||
return result.status === 0;
|
||||
if (result.status === 0) return true;
|
||||
} catch {
|
||||
return false;
|
||||
// PATH check failed, try common installation paths
|
||||
}
|
||||
|
||||
// Check common installation paths (handles fresh installs before PATH reload)
|
||||
const bunPaths = IS_WINDOWS
|
||||
? [join(homedir(), '.bun', 'bin', 'bun.exe')]
|
||||
: [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun'];
|
||||
|
||||
return bunPaths.some(existsSync);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Bun executable path (from PATH or common install locations)
|
||||
*/
|
||||
function getBunPath() {
|
||||
// Try PATH first
|
||||
try {
|
||||
const result = spawnSync('bun', ['--version'], {
|
||||
encoding: 'utf-8',
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
shell: IS_WINDOWS
|
||||
});
|
||||
if (result.status === 0) return 'bun';
|
||||
} catch {
|
||||
// Not in PATH
|
||||
}
|
||||
|
||||
// Check common installation paths
|
||||
const bunPaths = IS_WINDOWS
|
||||
? [join(homedir(), '.bun', 'bin', 'bun.exe')]
|
||||
: [join(homedir(), '.bun', 'bin', 'bun'), '/usr/local/bin/bun'];
|
||||
|
||||
for (const bunPath of bunPaths) {
|
||||
if (existsSync(bunPath)) return bunPath;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Bun version if installed
|
||||
*/
|
||||
function getBunVersion() {
|
||||
const bunPath = getBunPath();
|
||||
if (!bunPath) return null;
|
||||
|
||||
try {
|
||||
const result = spawnSync('bun', ['--version'], {
|
||||
const result = spawnSync(bunPath, ['--version'], {
|
||||
encoding: 'utf-8',
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
shell: IS_WINDOWS
|
||||
@@ -56,10 +94,17 @@ function isUvInstalled() {
|
||||
stdio: ['pipe', 'pipe', 'pipe'],
|
||||
shell: IS_WINDOWS
|
||||
});
|
||||
return result.status === 0;
|
||||
if (result.status === 0) return true;
|
||||
} catch {
|
||||
return false;
|
||||
// PATH check failed, try common installation paths
|
||||
}
|
||||
|
||||
// Check common installation paths (handles fresh installs before PATH reload)
|
||||
const uvPaths = IS_WINDOWS
|
||||
? [join(homedir(), '.local', 'bin', 'uv.exe'), join(homedir(), '.cargo', 'bin', 'uv.exe')]
|
||||
: [join(homedir(), '.local', 'bin', 'uv'), join(homedir(), '.cargo', 'bin', 'uv'), '/usr/local/bin/uv'];
|
||||
|
||||
return uvPaths.some(existsSync);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -226,12 +271,21 @@ function needsInstall() {
|
||||
* Install dependencies using Bun
|
||||
*/
|
||||
function installDeps() {
|
||||
const bunPath = getBunPath();
|
||||
if (!bunPath) {
|
||||
throw new Error('Bun executable not found');
|
||||
}
|
||||
|
||||
console.error('📦 Installing dependencies with Bun...');
|
||||
|
||||
// Quote path for Windows paths with spaces
|
||||
const bunCmd = IS_WINDOWS && bunPath.includes(' ') ? `"${bunPath}"` : bunPath;
|
||||
|
||||
try {
|
||||
execSync('bun install', { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS });
|
||||
execSync(`${bunCmd} install`, { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS });
|
||||
} catch {
|
||||
// Retry with force flag
|
||||
execSync('bun install --force', { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS });
|
||||
execSync(`${bunCmd} install --force`, { cwd: ROOT, stdio: 'inherit', shell: IS_WINDOWS });
|
||||
}
|
||||
|
||||
// Write version marker
|
||||
|
||||
@@ -4,8 +4,10 @@
|
||||
*/
|
||||
export function handleWorkerError(error: any): never {
|
||||
if (error.cause?.code === 'ECONNREFUSED' ||
|
||||
error.code === 'ConnectionRefused' || // Bun-specific error format
|
||||
error.name === 'TimeoutError' ||
|
||||
error.message?.includes('fetch failed')) {
|
||||
error.message?.includes('fetch failed') ||
|
||||
error.message?.includes('Unable to connect')) {
|
||||
throw new Error(
|
||||
"There's a problem with the worker. Try: npm run worker:restart"
|
||||
);
|
||||
|
||||
@@ -194,13 +194,6 @@ export async function ensureWorkerRunning(): Promise<void> {
|
||||
// Try to start the worker
|
||||
const started = await startWorker();
|
||||
|
||||
// Final health check before throwing error
|
||||
// Worker might be already running but was temporarily unresponsive
|
||||
if (!started && await isWorkerHealthy()) {
|
||||
await ensureWorkerVersionMatches();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!started) {
|
||||
const port = getWorkerPort();
|
||||
throw new Error(
|
||||
@@ -209,4 +202,22 @@ export async function ensureWorkerRunning(): Promise<void> {
|
||||
`If already running, try: npm run worker:restart`
|
||||
);
|
||||
}
|
||||
|
||||
// Wait for worker to become responsive after starting
|
||||
// Try up to 5 times with 500ms delays (2.5 seconds total)
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await new Promise(resolve => setTimeout(resolve, 500));
|
||||
if (await isWorkerHealthy()) {
|
||||
await ensureWorkerVersionMatches();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Worker started but isn't responding
|
||||
const port = getWorkerPort();
|
||||
logger.error('SYSTEM', 'Worker started but not responding to health checks');
|
||||
throw new Error(
|
||||
`Worker service started but is not responding on port ${port}.\n\n` +
|
||||
`Try: npm run worker:restart`
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user