superlocalmemory 4.1.18 → 4.1.20
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/.claude-plugin/marketplace.json +3 -3
- package/CHANGELOG.md +183 -0
- package/README.md +132 -661
- package/bin/slm-npm +1 -1
- package/ide/configs/cursor-mcp.json +4 -1
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +2 -2
- package/plugin/.mcp.json +7 -2
- package/plugin/CLAUDE.md +4 -4
- package/plugin/agents/slm-governance-advisor.md +1 -1
- package/plugin/agents/slm-loop-runner.md +1 -1
- package/plugin/agents/slm-memory-advisor.md +1 -1
- package/plugin/agents/slm-optimize-advisor.md +1 -1
- package/plugin/hooks/hooks.json +9 -9
- package/plugin/requirements.txt +1 -1
- package/plugin/scripts/ensure-venv.bat +5 -5
- package/plugin/scripts/ensure-venv.sh +27 -5
- package/plugin/scripts/slm-launch +60 -68
- package/plugin/scripts/slm-launch.bat +10 -1
- package/plugin/scripts/slm-resolve.sh +128 -0
- package/plugin/scripts/slm-run +76 -0
- package/plugin/skills/slm-cache/SKILL.md +1 -1
- package/plugin/skills/slm-compress/SKILL.md +1 -1
- package/plugin/skills/slm-governance/SKILL.md +1 -1
- package/plugin/skills/slm-graph/SKILL.md +1 -1
- package/plugin/skills/slm-loop/SKILL.md +1 -1
- package/plugin/skills/slm-mesh/SKILL.md +1 -1
- package/plugin/skills/slm-profile/SKILL.md +4 -4
- package/plugin/skills/slm-recall/SKILL.md +1 -1
- package/plugin/skills/slm-remember/SKILL.md +1 -1
- package/plugin/skills/slm-scope/SKILL.md +1 -1
- package/plugin/skills/slm-session/SKILL.md +1 -1
- package/plugin/skills/slm-status/SKILL.md +1 -1
- package/plugin-src/agents/slm-memory-advisor.md +1 -1
- package/plugin-src/agents/slm-optimize-advisor.md +1 -1
- package/plugin-src/rules/AGENTS.md +22 -11
- package/plugin-src/skills/slm-cache/SKILL.md +1 -1
- package/plugin-src/skills/slm-compress/SKILL.md +1 -1
- package/plugin-src/skills/slm-governance/SKILL.md +1 -1
- package/plugin-src/skills/slm-graph/SKILL.md +1 -1
- package/plugin-src/skills/slm-loop/SKILL.md +1 -1
- package/plugin-src/skills/slm-mesh/SKILL.md +1 -1
- package/plugin-src/skills/slm-profile/SKILL.md +4 -4
- package/plugin-src/skills/slm-recall/SKILL.md +1 -1
- package/plugin-src/skills/slm-remember/SKILL.md +1 -1
- package/plugin-src/skills/slm-scope/SKILL.md +1 -1
- package/plugin-src/skills/slm-session/SKILL.md +1 -1
- package/plugin-src/skills/slm-status/SKILL.md +1 -1
- package/scripts/postinstall.js +47 -16
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# slm-run — run slm for a plugin hook, using the slm the MCP server uses.
|
|
3
|
+
#
|
|
4
|
+
# "${CLAUDE_PLUGIN_ROOT}/scripts/slm-run" hook <name>
|
|
5
|
+
#
|
|
6
|
+
# Hooks used to call a bare `slm`, so on a machine where SuperLocalMemory lives
|
|
7
|
+
# only in the plugin venv every hook was "command not found" — and the error was
|
|
8
|
+
# thrown away, so memory capture stopped with nothing to say why. This wrapper
|
|
9
|
+
# resolves slm with the launcher's own code (slm-resolve.sh), honours the same
|
|
10
|
+
# SLM_LAUNCHER, and passes stdin, stdout and the arguments straight through.
|
|
11
|
+
#
|
|
12
|
+
# A hook must never break the session that runs it, so this ALWAYS exits 0
|
|
13
|
+
# (Claude Code reads exit 2 as "block"). When slm cannot be found, or fails, the
|
|
14
|
+
# reason goes to
|
|
15
|
+
# ${SLM_DATA_DIR:-~/.superlocalmemory}/logs/plugin-hooks.log
|
|
16
|
+
# and one line naming that file goes to stderr. A hook that succeeds is silent:
|
|
17
|
+
# whatever slm wrote to stderr is discarded, exactly as before.
|
|
18
|
+
|
|
19
|
+
_slm_args="$*"
|
|
20
|
+
_log_dir="${SLM_DATA_DIR:-${HOME}/.superlocalmemory}/logs"
|
|
21
|
+
_log="${_log_dir}/plugin-hooks.log"
|
|
22
|
+
_LOG_MAX_BYTES=1048576
|
|
23
|
+
|
|
24
|
+
# Append one entry. Best effort: an unwritable log must not fail the hook.
|
|
25
|
+
_log_entry() {
|
|
26
|
+
{
|
|
27
|
+
mkdir -p "${_log_dir}" || return 1
|
|
28
|
+
if [ -f "${_log}" ] && [ "$(wc -c < "${_log}")" -gt "${_LOG_MAX_BYTES}" ]; then
|
|
29
|
+
mv -f "${_log}" "${_log}.1"
|
|
30
|
+
fi
|
|
31
|
+
printf '%s slm %s: %s\n' "$(date -u '+%Y-%m-%dT%H:%M:%SZ')" "${_slm_args}" "$1" >> "${_log}"
|
|
32
|
+
} 2>/dev/null
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
# Record a failure, tell stderr where to look, and leave the session alone.
|
|
36
|
+
_give_up() {
|
|
37
|
+
if _log_entry "$1"; then
|
|
38
|
+
echo "SLM plugin: hook 'slm ${_slm_args}' did not run cleanly; see ${_log}" >&2
|
|
39
|
+
else
|
|
40
|
+
echo "SLM plugin: hook 'slm ${_slm_args}' did not run cleanly: $1" >&2
|
|
41
|
+
fi
|
|
42
|
+
exit 0
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
_here="${BASH_SOURCE[0]%/*}"
|
|
46
|
+
[ "${_here}" = "${BASH_SOURCE[0]}" ] && _here=.
|
|
47
|
+
# shellcheck source=slm-resolve.sh
|
|
48
|
+
if ! . "${_here}/slm-resolve.sh" 2>/dev/null; then
|
|
49
|
+
_give_up "the plugin is incomplete: ${_here}/slm-resolve.sh is missing"
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
if ! slm_choose; then
|
|
53
|
+
_give_up "$(printf '%s' "${SLM_RESOLVE_ERROR}" | tr '\n' ' ')"
|
|
54
|
+
fi
|
|
55
|
+
|
|
56
|
+
if [ "${SLM_CHOICE_READY}" -ne 1 ]; then
|
|
57
|
+
if [ "${SLM_LAUNCHER:-auto}" = "auto" ]; then
|
|
58
|
+
_give_up "$(slm_not_found_message | tr '\n' ' ') (A plugin venv is built by SessionStart; the first session can run its hooks before it exists.)"
|
|
59
|
+
fi
|
|
60
|
+
_give_up "${SLM_CHOICE} slm is not executable: ${SLM_CHOICE_BIN}"
|
|
61
|
+
fi
|
|
62
|
+
|
|
63
|
+
# slm's stderr is kept only long enough to report a failure. The trap removes
|
|
64
|
+
# it however this script ends, including a host timeout killing the hook.
|
|
65
|
+
_err="$(mktemp "${TMPDIR:-/tmp}/slm-hook.XXXXXX" 2>/dev/null)" || _err=/dev/null
|
|
66
|
+
trap '[ "${_err}" = /dev/null ] || rm -f "${_err}"' EXIT
|
|
67
|
+
trap 'exit 0' HUP INT TERM
|
|
68
|
+
|
|
69
|
+
"${SLM_CHOICE_BIN}" "$@" 2>"${_err}"
|
|
70
|
+
_rc=$?
|
|
71
|
+
if [ "${_rc}" -ne 0 ]; then
|
|
72
|
+
_detail=""
|
|
73
|
+
[ "${_err}" = /dev/null ] || _detail="$(tail -n 5 "${_err}" 2>/dev/null | tr '\n' ' ')"
|
|
74
|
+
_give_up "exit ${_rc} from ${SLM_CHOICE_BIN} (${SLM_CHOICE})${_detail:+: ${_detail}}"
|
|
75
|
+
fi
|
|
76
|
+
exit 0
|
|
@@ -31,9 +31,9 @@ project, a client engagement, a production vs staging environment.
|
|
|
31
31
|
| Profile | Tools | When to use |
|
|
32
32
|
|---------|-------|-------------|
|
|
33
33
|
| `core` | 18 tools — remember, recall, search, session, optimize | Minimal footprint, no code tools |
|
|
34
|
-
| `code` |
|
|
35
|
-
| `full` |
|
|
36
|
-
| `power` |
|
|
34
|
+
| `code` | 38 tools — core + portable Brain evidence + code graph + profile switching + bounded loops + memory-kind management | Default for IDE/coding agents |
|
|
35
|
+
| `full` | 54 tools — code + all memory ops + mesh + bounded loops | Multi-session, team workflows |
|
|
36
|
+
| `power` | 66 tools — full + governance + behavioral tools | Enterprise, admin, audit use cases |
|
|
37
37
|
| `mesh` | 8 tools — mesh coordination only | Lightweight cross-session signalling |
|
|
38
38
|
|
|
39
39
|
The profile is set at MCP server startup via `SLM_MCP_PROFILE` in the MCP config.
|
|
@@ -146,4 +146,4 @@ Name them differently in your MCP config (e.g. `superlocalmemory-personal` and
|
|
|
146
146
|
|
|
147
147
|
---
|
|
148
148
|
|
|
149
|
-
*SuperLocalMemory v4.1.
|
|
149
|
+
*SuperLocalMemory v4.1.20 · Qualixar · AGPL-3.0-or-later*
|
|
@@ -47,4 +47,4 @@ slm-recall · slm-remember · slm-session · slm-scope · slm-profile · slm-gov
|
|
|
47
47
|
# What NOT to do
|
|
48
48
|
Never session_init twice; never forget dry_run=False without reporting preview; never dump a whole file into remember; never invent a memory; never claim "saved" without success:true / clean CLI exit; never bypass scope or governance restrictions.
|
|
49
49
|
|
|
50
|
-
SuperLocalMemory v4.1.
|
|
50
|
+
SuperLocalMemory v4.1.20 · Qualixar · AGPL-3.0-or-later
|
|
@@ -41,4 +41,4 @@ slm-compress · slm-cache · slm-status · slm-profile
|
|
|
41
41
|
# What NOT to do
|
|
42
42
|
Never compress code-for-edit/JSON-to-parse/<500 chars; never store secrets/ccr_ids; never let optimize failure block/alter the task; never claim a specific savings %; never carry ccr_ids across profile switches.
|
|
43
43
|
|
|
44
|
-
SuperLocalMemory v4.1.
|
|
44
|
+
SuperLocalMemory v4.1.20 · Qualixar · AGPL-3.0-or-later
|
|
@@ -83,16 +83,27 @@ When the SLM MCP server is unavailable, use these CLI equivalents:
|
|
|
83
83
|
|
|
84
84
|
## Tool reference (core profile — 18 tools)
|
|
85
85
|
|
|
86
|
-
> The MCP config ships `
|
|
87
|
-
>
|
|
88
|
-
>
|
|
89
|
-
>
|
|
90
|
-
> `
|
|
91
|
-
>
|
|
92
|
-
> `
|
|
93
|
-
> `
|
|
94
|
-
>
|
|
95
|
-
>
|
|
86
|
+
> The MCP config ships only `SLM_AGENT_ID=claude_code` — no `SLM_MCP_PROFILE` —
|
|
87
|
+
> so it falls back to the same no-profile default every install gets: the
|
|
88
|
+
> 54-tool `full` surface. That is the 18 core tools below **plus** mesh
|
|
89
|
+
> coordination (8: `mesh_summary`, `mesh_peers`, `mesh_send`, `mesh_inbox`,
|
|
90
|
+
> `mesh_state`, `mesh_lock`, `mesh_events`, `mesh_status`), portable-evidence
|
|
91
|
+
> tools (5: `get_brain_evidence_status`, `record_agent_experience`,
|
|
92
|
+
> `record_cognitive_turn`, `finalize_cognitive_turn`,
|
|
93
|
+
> `observe_bounded_loop_evidence`), memory-kind tools (4: `set_memory_kind`,
|
|
94
|
+
> `memory_kinds_status`, `review_memory_kinds`, `confirm_memory_kinds`),
|
|
95
|
+
> bounded-loop tools (3: `slm_loop_run`, `slm_loop_history`, `slm_loop_show`),
|
|
96
|
+
> usefulness reports (2: `report_outcome`, `report_feedback`) and 14 more
|
|
97
|
+
> administration/learning tools (`delete_memory`, `get_status`, `observe`,
|
|
98
|
+
> `run_maintenance`, `consolidate_cognitive`, `get_soft_prompts`, `set_mode`,
|
|
99
|
+
> `log_tool_event`, `get_assertions`, `reinforce_assertion`,
|
|
100
|
+
> `contradict_assertion`, `evolve_skill`, `skill_health`, `skill_lineage`).
|
|
101
|
+
> Set `SLM_MCP_PROFILE=code` yourself for the narrower 38-tool `code` surface,
|
|
102
|
+
> which trades mesh and administration tools for 6 code-graph tools
|
|
103
|
+
> (`build_code_graph`, `get_blast_radius`, `query_graph`,
|
|
104
|
+
> `semantic_search_code`, `get_review_context`, `detect_changes`). Use
|
|
105
|
+
> `power` (66 tools) for governance and audit tools. See slm-profile for
|
|
106
|
+
> profile switching.
|
|
96
107
|
|
|
97
108
|
| Tool | Signature (key params) | Notes |
|
|
98
109
|
|--------------------|----------------------------------------------------------------------------------------------|----------------------------------------|
|
|
@@ -138,4 +149,4 @@ When the SLM MCP server is unavailable, use these CLI equivalents:
|
|
|
138
149
|
- **slm-optimize-advisor** — context compression and KV cache
|
|
139
150
|
- **slm-governance-advisor** — scope/role compliance, retention policies, GDPR
|
|
140
151
|
|
|
141
|
-
SuperLocalMemory v4.1.
|
|
152
|
+
SuperLocalMemory v4.1.20 · Qualixar · AGPL-3.0-or-later
|
|
@@ -31,9 +31,9 @@ project, a client engagement, a production vs staging environment.
|
|
|
31
31
|
| Profile | Tools | When to use |
|
|
32
32
|
|---------|-------|-------------|
|
|
33
33
|
| `core` | 18 tools — remember, recall, search, session, optimize | Minimal footprint, no code tools |
|
|
34
|
-
| `code` |
|
|
35
|
-
| `full` |
|
|
36
|
-
| `power` |
|
|
34
|
+
| `code` | 38 tools — core + portable Brain evidence + code graph + profile switching + bounded loops + memory-kind management | Default for IDE/coding agents |
|
|
35
|
+
| `full` | 54 tools — code + all memory ops + mesh + bounded loops | Multi-session, team workflows |
|
|
36
|
+
| `power` | 66 tools — full + governance + behavioral tools | Enterprise, admin, audit use cases |
|
|
37
37
|
| `mesh` | 8 tools — mesh coordination only | Lightweight cross-session signalling |
|
|
38
38
|
|
|
39
39
|
The profile is set at MCP server startup via `SLM_MCP_PROFILE` in the MCP config.
|
|
@@ -146,4 +146,4 @@ Name them differently in your MCP config (e.g. `superlocalmemory-personal` and
|
|
|
146
146
|
|
|
147
147
|
---
|
|
148
148
|
|
|
149
|
-
*SuperLocalMemory v4.1.
|
|
149
|
+
*SuperLocalMemory v4.1.20 · Qualixar · AGPL-3.0-or-later*
|
package/scripts/postinstall.js
CHANGED
|
@@ -17,7 +17,7 @@ const fs = require('fs');
|
|
|
17
17
|
const path = require('path');
|
|
18
18
|
const os = require('os');
|
|
19
19
|
|
|
20
|
-
const MIN_PYTHON = Object.freeze([3,
|
|
20
|
+
const MIN_PYTHON = Object.freeze([3, 12]);
|
|
21
21
|
const MAX_PYTHON_EXCLUSIVE = Object.freeze([3, 15]);
|
|
22
22
|
const INSTALL_TIMEOUT_MS = 15 * 60 * 1000;
|
|
23
23
|
|
|
@@ -43,12 +43,19 @@ function pythonCandidates(platform = os.platform()) {
|
|
|
43
43
|
['py', '-3.14'],
|
|
44
44
|
['py', '-3.13'],
|
|
45
45
|
['py', '-3.12'],
|
|
46
|
-
['py', '-3.11'],
|
|
47
46
|
['python3'],
|
|
48
47
|
['python'],
|
|
49
48
|
];
|
|
50
49
|
}
|
|
50
|
+
// Debian 12, Ubuntu 22.04 (with deadsnakes) and RHEL 9 all ship a system
|
|
51
|
+
// `python3` older than 3.12, with the supported versioned interpreter
|
|
52
|
+
// installed alongside it, unused. Try the versioned names first so that
|
|
53
|
+
// interpreter is found before falling back to the bare names and the
|
|
54
|
+
// fixed absolute paths below.
|
|
51
55
|
return [
|
|
56
|
+
['python3.14'],
|
|
57
|
+
['python3.13'],
|
|
58
|
+
['python3.12'],
|
|
52
59
|
['python3'],
|
|
53
60
|
['python'],
|
|
54
61
|
['/opt/homebrew/bin/python3'],
|
|
@@ -57,21 +64,44 @@ function pythonCandidates(platform = os.platform()) {
|
|
|
57
64
|
];
|
|
58
65
|
}
|
|
59
66
|
|
|
67
|
+
function probePython(command, prefixArgs) {
|
|
68
|
+
try {
|
|
69
|
+
const result = spawnSync(command, [...prefixArgs, '--version'], {
|
|
70
|
+
stdio: 'pipe',
|
|
71
|
+
timeout: 5000,
|
|
72
|
+
env: process.env,
|
|
73
|
+
});
|
|
74
|
+
const output = `${(result.stdout || '').toString()} ${(result.stderr || '').toString()}`;
|
|
75
|
+
return { status: result.status, version: parsePythonVersion(output) };
|
|
76
|
+
} catch (error) {
|
|
77
|
+
return { status: null, version: null, error };
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
60
81
|
function findSupportedPython() {
|
|
82
|
+
const override = String(process.env.SLM_PYTHON || '').trim();
|
|
83
|
+
if (override) {
|
|
84
|
+
// The user named this interpreter explicitly (docs/getting-started.md's
|
|
85
|
+
// escape hatch for a system where no supported `python3` is on PATH, for
|
|
86
|
+
// example a deadsnakes or pyenv install at a custom path). Honour it,
|
|
87
|
+
// but still version-check it — and if it fails, say so plainly instead
|
|
88
|
+
// of silently trying a different interpreter the user did not choose.
|
|
89
|
+
const probe = probePython(override, []);
|
|
90
|
+
if (probe.status === 0 && isSupportedPython(probe.version)) {
|
|
91
|
+
return { command: override, prefixArgs: [], version: probe.version };
|
|
92
|
+
}
|
|
93
|
+
const detail = probe.status === 0 && probe.version
|
|
94
|
+
? `found Python ${probe.version.join('.')}, which is not supported (need 3.12-3.14)`
|
|
95
|
+
: 'could not be run (check the path and that it is executable)';
|
|
96
|
+
console.error(`SuperLocalMemory: SLM_PYTHON=${override} ${detail}.`);
|
|
97
|
+
console.error('Point SLM_PYTHON at a Python 3.12-3.14 interpreter, or unset it to let the installer search automatically.');
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
|
|
61
101
|
for (const candidate of pythonCandidates()) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
timeout: 5000,
|
|
66
|
-
env: process.env,
|
|
67
|
-
});
|
|
68
|
-
const output = `${(result.stdout || '').toString()} ${(result.stderr || '').toString()}`;
|
|
69
|
-
const version = parsePythonVersion(output);
|
|
70
|
-
if (result.status === 0 && isSupportedPython(version)) {
|
|
71
|
-
return { command: candidate[0], prefixArgs: candidate.slice(1), version };
|
|
72
|
-
}
|
|
73
|
-
} catch (_error) {
|
|
74
|
-
// Try the next interpreter without mutating PATH or the machine.
|
|
102
|
+
const probe = probePython(candidate[0], candidate.slice(1));
|
|
103
|
+
if (probe.status === 0 && isSupportedPython(probe.version)) {
|
|
104
|
+
return { command: candidate[0], prefixArgs: candidate.slice(1), version: probe.version };
|
|
75
105
|
}
|
|
76
106
|
}
|
|
77
107
|
return null;
|
|
@@ -142,7 +172,7 @@ function validateRuntimeLocation(venvRoot) {
|
|
|
142
172
|
|
|
143
173
|
function printPythonGuidance() {
|
|
144
174
|
console.error('');
|
|
145
|
-
console.error('SuperLocalMemory requires Python 3.
|
|
175
|
+
console.error('SuperLocalMemory requires Python 3.12, 3.13, or 3.14.');
|
|
146
176
|
console.error('Install Python from https://www.python.org/downloads/ and rerun:');
|
|
147
177
|
console.error(' npm rebuild superlocalmemory');
|
|
148
178
|
console.error('The npm installer will create a private virtual environment;');
|
|
@@ -296,6 +326,7 @@ module.exports = {
|
|
|
296
326
|
isSupportedPython,
|
|
297
327
|
main,
|
|
298
328
|
parsePythonVersion,
|
|
329
|
+
probePython,
|
|
299
330
|
pypiSpecifier,
|
|
300
331
|
pythonCandidates,
|
|
301
332
|
runtimePythonPath,
|