claude-memory-hub 0.9.4 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +27 -0
- package/dist/cli.js +46 -12
- package/dist/hooks/post-compact.js +5 -0
- package/dist/hooks/post-tool-use.js +5 -0
- package/dist/hooks/pre-compact.js +5 -0
- package/dist/hooks/session-end.js +5 -0
- package/dist/hooks/user-prompt-submit.js +5 -0
- package/dist/index.js +5 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,33 @@ Format follows [Keep a Changelog](https://keepachangelog.com/).
|
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
+
## [0.9.5] - 2026-04-03
|
|
9
|
+
|
|
10
|
+
Stable install path — hooks no longer break after reboot or bunx cache cleanup.
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
- **Hooks pointing to temp `bunx` path** — `bunx claude-memory-hub install` registered hooks at `/private/tmp/bunx-*/...` (macOS) or `%TEMP%/bunx-*/...` (Windows). These paths are ephemeral and get deleted on reboot or cache cleanup, causing **all hooks to silently fail** — sessions stop being captured with no error visible to the user
|
|
15
|
+
- **Install now copies `dist/` to `~/.claude-memory-hub/dist/`** — a stable, persistent location under the user's home directory. Both hooks and MCP server reference this path instead of the package install location
|
|
16
|
+
- **Old hook entries auto-replaced** — `install` removes previous claude-memory-hub hook entries before registering new ones, fixing stale paths from prior installs without manual cleanup
|
|
17
|
+
- **`install.sh` updated** — shell-based installer uses the same stable path strategy with full bun binary resolution
|
|
18
|
+
|
|
19
|
+
### How It Works
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
bunx claude-memory-hub install
|
|
23
|
+
1. Downloads package to temp dir (bunx behavior)
|
|
24
|
+
2. Copies dist/*.js + dist/hooks/*.js → ~/.claude-memory-hub/dist/ ← NEW
|
|
25
|
+
3. Registers hooks pointing to ~/.claude-memory-hub/dist/hooks/ ← STABLE
|
|
26
|
+
4. Registers MCP server pointing to ~/.claude-memory-hub/dist/index.js
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Upgrade Note
|
|
30
|
+
|
|
31
|
+
Run `bunx claude-memory-hub@latest install` to fix broken hooks. No data loss — only hook paths are updated.
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
8
35
|
## [0.9.4] - 2026-04-02
|
|
9
36
|
|
|
10
37
|
Windows path fix — backslashes no longer eaten by bash.
|
package/dist/cli.js
CHANGED
|
@@ -1669,7 +1669,7 @@ var init_importer = __esm(() => {
|
|
|
1669
1669
|
});
|
|
1670
1670
|
|
|
1671
1671
|
// src/cli/main.ts
|
|
1672
|
-
import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync, writeFileSync } from "fs";
|
|
1672
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync, writeFileSync, readdirSync } from "fs";
|
|
1673
1673
|
import { homedir as homedir5 } from "os";
|
|
1674
1674
|
import { join as join5, resolve, dirname } from "path";
|
|
1675
1675
|
|
|
@@ -1967,6 +1967,7 @@ import { spawnSync } from "child_process";
|
|
|
1967
1967
|
var CLAUDE_DIR = join5(homedir5(), ".claude");
|
|
1968
1968
|
var SETTINGS_PATH = join5(CLAUDE_DIR, "settings.json");
|
|
1969
1969
|
var PKG_DIR = resolve(dirname(import.meta.dir));
|
|
1970
|
+
var STABLE_DIR = join5(homedir5(), ".claude-memory-hub");
|
|
1970
1971
|
function shellPath(p) {
|
|
1971
1972
|
const normalized = p.replace(/\\/g, "/");
|
|
1972
1973
|
return normalized.includes(" ") ? `"${normalized}"` : normalized;
|
|
@@ -1988,11 +1989,37 @@ function getBunPath() {
|
|
|
1988
1989
|
}
|
|
1989
1990
|
return "bun";
|
|
1990
1991
|
}
|
|
1992
|
+
function copyDistToStableDir() {
|
|
1993
|
+
const srcDist = join5(PKG_DIR, "dist");
|
|
1994
|
+
const destDist = join5(STABLE_DIR, "dist");
|
|
1995
|
+
if (!existsSync5(srcDist)) {
|
|
1996
|
+
throw new Error(`dist/ not found at ${srcDist}. Run 'bun run build:all' first.`);
|
|
1997
|
+
}
|
|
1998
|
+
const destHooks = join5(destDist, "hooks");
|
|
1999
|
+
mkdirSync3(destHooks, { recursive: true });
|
|
2000
|
+
for (const file of readdirSync(srcDist)) {
|
|
2001
|
+
if (file.endsWith(".js")) {
|
|
2002
|
+
const src = join5(srcDist, file);
|
|
2003
|
+
const dest = join5(destDist, file);
|
|
2004
|
+
writeFileSync(dest, readFileSync(src));
|
|
2005
|
+
}
|
|
2006
|
+
}
|
|
2007
|
+
const srcHooks = join5(srcDist, "hooks");
|
|
2008
|
+
if (existsSync5(srcHooks)) {
|
|
2009
|
+
for (const file of readdirSync(srcHooks)) {
|
|
2010
|
+
if (file.endsWith(".js")) {
|
|
2011
|
+
const src = join5(srcHooks, file);
|
|
2012
|
+
const dest = join5(destHooks, file);
|
|
2013
|
+
writeFileSync(dest, readFileSync(src));
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
}
|
|
1991
2018
|
function getHookPath(hookName) {
|
|
1992
|
-
return shellPath(join5(
|
|
2019
|
+
return shellPath(join5(STABLE_DIR, "dist", "hooks", `${hookName}.js`));
|
|
1993
2020
|
}
|
|
1994
2021
|
function getMcpServerPath() {
|
|
1995
|
-
return shellPath(join5(
|
|
2022
|
+
return shellPath(join5(STABLE_DIR, "dist", "index.js"));
|
|
1996
2023
|
}
|
|
1997
2024
|
function loadSettings() {
|
|
1998
2025
|
if (!existsSync5(SETTINGS_PATH))
|
|
@@ -2012,7 +2039,16 @@ function saveSettings(settings) {
|
|
|
2012
2039
|
function install() {
|
|
2013
2040
|
console.log(`claude-memory-hub \u2014 install
|
|
2014
2041
|
`);
|
|
2015
|
-
console.log("
|
|
2042
|
+
console.log("0. Copying dist/ to ~/.claude-memory-hub/dist/...");
|
|
2043
|
+
try {
|
|
2044
|
+
copyDistToStableDir();
|
|
2045
|
+
console.log(" Files copied to stable location.");
|
|
2046
|
+
} catch (e) {
|
|
2047
|
+
console.error(` Failed to copy dist/: ${e}`);
|
|
2048
|
+
console.error(" Hooks will reference package location (may break after bunx cleanup).");
|
|
2049
|
+
}
|
|
2050
|
+
console.log(`
|
|
2051
|
+
1. Registering MCP server...`);
|
|
2016
2052
|
const mcpPath = getMcpServerPath();
|
|
2017
2053
|
const bunBin = getBunPath();
|
|
2018
2054
|
const result = spawnSync("claude", ["mcp", "add", "claude-memory-hub", "-s", "user", "--", bunBin, "run", mcpPath], {
|
|
@@ -2044,14 +2080,12 @@ function install() {
|
|
|
2044
2080
|
for (const [event, scriptPath] of hookEntries) {
|
|
2045
2081
|
const hooks = settings.hooks;
|
|
2046
2082
|
hooks[event] ??= [];
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
registered++;
|
|
2054
|
-
}
|
|
2083
|
+
hooks[event] = hooks[event].filter((e) => !JSON.stringify(e).includes("claude-memory-hub"));
|
|
2084
|
+
hooks[event].push({
|
|
2085
|
+
matcher: "",
|
|
2086
|
+
hooks: [{ type: "command", command: `${bunBin} run ${scriptPath}` }]
|
|
2087
|
+
});
|
|
2088
|
+
registered++;
|
|
2055
2089
|
}
|
|
2056
2090
|
saveSettings(settings);
|
|
2057
2091
|
console.log(` ${registered} hook(s) registered. (${5 - registered} already existed)`);
|
|
@@ -376,6 +376,11 @@ class SessionStore {
|
|
|
376
376
|
this.db.run("UPDATE sessions SET status = 'completed', ended_at = ? WHERE id = ?", [Date.now(), id]);
|
|
377
377
|
}
|
|
378
378
|
insertEntity(entity) {
|
|
379
|
+
if (entity.entity_type === "decision" || entity.entity_type === "observation") {
|
|
380
|
+
const existing = this.db.query("SELECT COUNT(*) as c FROM entities WHERE session_id = ? AND entity_type = ? AND entity_value = ?").get(entity.session_id, entity.entity_type, entity.entity_value);
|
|
381
|
+
if (existing && existing.c > 0)
|
|
382
|
+
return -1;
|
|
383
|
+
}
|
|
379
384
|
const result = this.db.run(`INSERT INTO entities(session_id, project, tool_name, entity_type, entity_value, context, importance, created_at, prompt_number)
|
|
380
385
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
381
386
|
entity.session_id,
|
|
@@ -376,6 +376,11 @@ class SessionStore {
|
|
|
376
376
|
this.db.run("UPDATE sessions SET status = 'completed', ended_at = ? WHERE id = ?", [Date.now(), id]);
|
|
377
377
|
}
|
|
378
378
|
insertEntity(entity) {
|
|
379
|
+
if (entity.entity_type === "decision" || entity.entity_type === "observation") {
|
|
380
|
+
const existing = this.db.query("SELECT COUNT(*) as c FROM entities WHERE session_id = ? AND entity_type = ? AND entity_value = ?").get(entity.session_id, entity.entity_type, entity.entity_value);
|
|
381
|
+
if (existing && existing.c > 0)
|
|
382
|
+
return -1;
|
|
383
|
+
}
|
|
379
384
|
const result = this.db.run(`INSERT INTO entities(session_id, project, tool_name, entity_type, entity_value, context, importance, created_at, prompt_number)
|
|
380
385
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
381
386
|
entity.session_id,
|
|
@@ -376,6 +376,11 @@ class SessionStore {
|
|
|
376
376
|
this.db.run("UPDATE sessions SET status = 'completed', ended_at = ? WHERE id = ?", [Date.now(), id]);
|
|
377
377
|
}
|
|
378
378
|
insertEntity(entity) {
|
|
379
|
+
if (entity.entity_type === "decision" || entity.entity_type === "observation") {
|
|
380
|
+
const existing = this.db.query("SELECT COUNT(*) as c FROM entities WHERE session_id = ? AND entity_type = ? AND entity_value = ?").get(entity.session_id, entity.entity_type, entity.entity_value);
|
|
381
|
+
if (existing && existing.c > 0)
|
|
382
|
+
return -1;
|
|
383
|
+
}
|
|
379
384
|
const result = this.db.run(`INSERT INTO entities(session_id, project, tool_name, entity_type, entity_value, context, importance, created_at, prompt_number)
|
|
380
385
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
381
386
|
entity.session_id,
|
|
@@ -376,6 +376,11 @@ class SessionStore {
|
|
|
376
376
|
this.db.run("UPDATE sessions SET status = 'completed', ended_at = ? WHERE id = ?", [Date.now(), id]);
|
|
377
377
|
}
|
|
378
378
|
insertEntity(entity) {
|
|
379
|
+
if (entity.entity_type === "decision" || entity.entity_type === "observation") {
|
|
380
|
+
const existing = this.db.query("SELECT COUNT(*) as c FROM entities WHERE session_id = ? AND entity_type = ? AND entity_value = ?").get(entity.session_id, entity.entity_type, entity.entity_value);
|
|
381
|
+
if (existing && existing.c > 0)
|
|
382
|
+
return -1;
|
|
383
|
+
}
|
|
379
384
|
const result = this.db.run(`INSERT INTO entities(session_id, project, tool_name, entity_type, entity_value, context, importance, created_at, prompt_number)
|
|
380
385
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
381
386
|
entity.session_id,
|
|
@@ -376,6 +376,11 @@ class SessionStore {
|
|
|
376
376
|
this.db.run("UPDATE sessions SET status = 'completed', ended_at = ? WHERE id = ?", [Date.now(), id]);
|
|
377
377
|
}
|
|
378
378
|
insertEntity(entity) {
|
|
379
|
+
if (entity.entity_type === "decision" || entity.entity_type === "observation") {
|
|
380
|
+
const existing = this.db.query("SELECT COUNT(*) as c FROM entities WHERE session_id = ? AND entity_type = ? AND entity_value = ?").get(entity.session_id, entity.entity_type, entity.entity_value);
|
|
381
|
+
if (existing && existing.c > 0)
|
|
382
|
+
return -1;
|
|
383
|
+
}
|
|
379
384
|
const result = this.db.run(`INSERT INTO entities(session_id, project, tool_name, entity_type, entity_value, context, importance, created_at, prompt_number)
|
|
380
385
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
381
386
|
entity.session_id,
|
package/dist/index.js
CHANGED
|
@@ -14140,6 +14140,11 @@ class SessionStore {
|
|
|
14140
14140
|
this.db.run("UPDATE sessions SET status = 'completed', ended_at = ? WHERE id = ?", [Date.now(), id]);
|
|
14141
14141
|
}
|
|
14142
14142
|
insertEntity(entity) {
|
|
14143
|
+
if (entity.entity_type === "decision" || entity.entity_type === "observation") {
|
|
14144
|
+
const existing = this.db.query("SELECT COUNT(*) as c FROM entities WHERE session_id = ? AND entity_type = ? AND entity_value = ?").get(entity.session_id, entity.entity_type, entity.entity_value);
|
|
14145
|
+
if (existing && existing.c > 0)
|
|
14146
|
+
return -1;
|
|
14147
|
+
}
|
|
14143
14148
|
const result = this.db.run(`INSERT INTO entities(session_id, project, tool_name, entity_type, entity_value, context, importance, created_at, prompt_number)
|
|
14144
14149
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, [
|
|
14145
14150
|
entity.session_id,
|
package/package.json
CHANGED