claude-mem-lite 2.32.8 → 2.33.0

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.
@@ -10,7 +10,7 @@
10
10
  "plugins": [
11
11
  {
12
12
  "name": "claude-mem-lite",
13
- "version": "2.32.8",
13
+ "version": "2.33.0",
14
14
  "source": "./",
15
15
  "description": "Lightweight persistent memory system for Claude Code — FTS5 search, episode batching, error-triggered recall"
16
16
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "2.32.8",
3
+ "version": "2.33.0",
4
4
  "description": "Lightweight persistent memory system for Claude Code — FTS5 search, episode batching, error-triggered recall",
5
5
  "author": {
6
6
  "name": "sdsrss"
package/adopt-cli.mjs CHANGED
@@ -9,7 +9,7 @@
9
9
  // --dry-run = print intent without writing
10
10
  // --status = list all adopted projects + versions
11
11
 
12
- import { existsSync, readdirSync, statSync } from 'fs';
12
+ import { existsSync, readdirSync, statSync, mkdirSync, writeFileSync } from 'fs';
13
13
  import { homedir } from 'os';
14
14
  import { join } from 'path';
15
15
  import {
@@ -121,6 +121,58 @@ function adoptOne(memdir, { force, dryRun, all }) {
121
121
  }
122
122
  }
123
123
 
124
+ /**
125
+ * silentAutoAdopt — plugin-mode first-run auto-adopt helper (v2.33.0).
126
+ *
127
+ * Preconditions (caller must gate): CLAUDE_PLUGIN_ROOT set, MEM_NO_AUTO_ADOPT!=1,
128
+ * MEM_QUIET_HOOKS!=1, first-attempt marker absent. This helper does NOT re-check
129
+ * those — it only does the write + marker persistence.
130
+ *
131
+ * Behavior:
132
+ * - Writes plugin sentinel + detail doc to the memdir for `cwd`.
133
+ * - Writes a per-project first-attempt marker under `markerDir` so a later
134
+ * `/unadopt` is respected (no re-adopt loop).
135
+ * - Silent: never logs, never throws. Returns structured result.
136
+ *
137
+ * Returns { ok, action, reason } — caller uses for telemetry / debugLog only.
138
+ */
139
+ export function silentAutoAdopt({ cwd, markerDir, markerKey }) {
140
+ const memdir = memdirPath(cwd);
141
+ try {
142
+ if (isAdopted(memdir, PLUGIN_SLUG)) {
143
+ writeMarker(markerDir, markerKey);
144
+ return { ok: true, action: 'already-adopted' };
145
+ }
146
+ writePluginSection(memdir, {
147
+ slug: PLUGIN_SLUG,
148
+ version: CURRENT_SENTINEL_VERSION,
149
+ contentLine: getIndexLine(),
150
+ force: false,
151
+ });
152
+ writePluginDoc(memdir, PLUGIN_SLUG, getDetailDoc());
153
+ writeMarker(markerDir, markerKey);
154
+ return { ok: true, action: 'adopted' };
155
+ } catch (e) {
156
+ // Budget exceeded, user-edited conflict, or FS error — write marker so we
157
+ // don't retry on every SessionStart. User can run /adopt --force manually.
158
+ try { writeMarker(markerDir, markerKey); } catch { /* marker best-effort */ }
159
+ const reason = e instanceof UserEditedError ? 'user-edited'
160
+ : e instanceof BudgetExceededError ? 'budget-exceeded'
161
+ : 'error';
162
+ return { ok: false, action: 'skipped', reason, err: e };
163
+ }
164
+ }
165
+
166
+ function writeMarker(markerDir, markerKey) {
167
+ if (!existsSync(markerDir)) mkdirSync(markerDir, { recursive: true });
168
+ const path = join(markerDir, `.auto-adopt-${markerKey}`);
169
+ writeFileSync(path, JSON.stringify({ firstAttemptAt: new Date().toISOString() }));
170
+ }
171
+
172
+ export function hasAutoAdoptMarker(markerDir, markerKey) {
173
+ return existsSync(join(markerDir, `.auto-adopt-${markerKey}`));
174
+ }
175
+
124
176
  function statusAll() {
125
177
  const dirs = listAllMemdirs();
126
178
  log('[adopt --status] scanning ~/.claude/projects/*/memory/');
package/hook.mjs CHANGED
@@ -32,6 +32,7 @@ import { searchRelevantMemories } from './hook-memory.mjs';
32
32
  import { buildAndSaveHandoff, detectContinuationIntent, renderHandoffInjection, extractUnfinishedSummary } from './hook-handoff.mjs';
33
33
  import { checkForUpdate } from './hook-update.mjs';
34
34
  import { handleLLMOptimize } from './hook-optimize.mjs';
35
+ import { silentAutoAdopt, hasAutoAdoptMarker } from './adopt-cli.mjs';
35
36
  // plugin-cache-guard.mjs loaded dynamically — pre-2.31.2 installs that auto-upgraded
36
37
  // from an older hook-update.mjs SOURCE_FILES (which did not list this module) would
37
38
  // crash on static import. Degrade gracefully to no-op when the module is absent.
@@ -425,6 +426,35 @@ async function handleSessionStart() {
425
426
  }
426
427
  } catch (e) { debugCatch(e, 'session-start-cache-heal'); }
427
428
 
429
+ // v2.33.0: plugin-mode first-run auto-adopt. /plugin install IS consent to
430
+ // integration — writing the MEMORY.md sentinel once per project on first
431
+ // SessionStart avoids the opt-in friction. Scope is narrow:
432
+ // - gated by CLAUDE_PLUGIN_ROOT (npm/npx installs stay opt-in)
433
+ // - gated by !MEM_NO_AUTO_ADOPT (explicit escape hatch)
434
+ // - gated by !MEM_QUIET_HOOKS (quiet = no side-effects semantics)
435
+ // - first-attempt marker persists in RUNTIME_DIR so a subsequent /unadopt
436
+ // is respected (no re-adopt loop).
437
+ // Failures (user-edited sentinel, budget exceeded, FS errors) are swallowed;
438
+ // the marker is still written so we don't retry on every SessionStart.
439
+ try {
440
+ if (
441
+ process.env.CLAUDE_PLUGIN_ROOT
442
+ && process.env.MEM_NO_AUTO_ADOPT !== '1'
443
+ && process.env.MEM_QUIET_HOOKS !== '1'
444
+ ) {
445
+ const project = inferProject();
446
+ if (!hasAutoAdoptMarker(RUNTIME_DIR, project)) {
447
+ const cwd = process.env.CLAUDE_PROJECT_DIR || process.cwd();
448
+ const r = silentAutoAdopt({ cwd, markerDir: RUNTIME_DIR, markerKey: project });
449
+ if (r.ok) {
450
+ debugLog('DEBUG', 'session-start-auto-adopt', `action=${r.action} project=${project}`);
451
+ } else {
452
+ debugLog('DEBUG', 'session-start-auto-adopt', `skipped project=${project} reason=${r.reason}`);
453
+ }
454
+ }
455
+ }
456
+ } catch (e) { debugCatch(e, 'session-start-auto-adopt'); }
457
+
428
458
  // Read CC real session_id from hook stdin — used to scope handoff rows so parallel
429
459
  // sessions for the same project don't clobber each other (see docs/bug.txt).
430
460
  let ccSessionId = null;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-mem-lite",
3
- "version": "2.32.8",
3
+ "version": "2.33.0",
4
4
  "description": "Lightweight persistent memory system for Claude Code",
5
5
  "type": "module",
6
6
  "engines": {