superlocalmemory 3.6.13 → 3.6.14

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.
Files changed (124) hide show
  1. package/.claude-plugin/marketplace.json +17 -0
  2. package/README.md +187 -741
  3. package/package.json +12 -5
  4. package/plugin/.claude-plugin/plugin.json +20 -0
  5. package/plugin/.mcp.json +12 -0
  6. package/plugin/CLAUDE.md +43 -0
  7. package/plugin/_GENERATED.md +6 -0
  8. package/plugin/agents/slm-memory-advisor.md +43 -0
  9. package/plugin/agents/slm-optimize-advisor.md +38 -0
  10. package/plugin/hooks/hooks.json +14 -0
  11. package/plugin/requirements.txt +1 -0
  12. package/plugin/scripts/ensure-venv.bat +122 -0
  13. package/plugin/scripts/ensure-venv.sh +105 -0
  14. package/plugin/scripts/slm-launch +15 -0
  15. package/plugin/scripts/slm-launch.bat +17 -0
  16. package/plugin/settings.json +16 -0
  17. package/plugin/skills/slm-cache/SKILL.md +140 -0
  18. package/plugin/skills/slm-compress/SKILL.md +143 -0
  19. package/plugin/skills/slm-graph/SKILL.md +300 -0
  20. package/plugin/skills/slm-recall/SKILL.md +196 -0
  21. package/plugin/skills/slm-remember/SKILL.md +182 -0
  22. package/plugin/skills/slm-session/SKILL.md +207 -0
  23. package/plugin/skills/slm-status/SKILL.md +149 -0
  24. package/plugin-src/.mcp.json +12 -0
  25. package/plugin-src/agents/slm-memory-advisor.md +43 -0
  26. package/plugin-src/agents/slm-optimize-advisor.md +38 -0
  27. package/plugin-src/commands/slm-optimize.md +22 -0
  28. package/plugin-src/commands/slm-recall.md +16 -0
  29. package/plugin-src/commands/slm-remember.md +16 -0
  30. package/plugin-src/commands/slm-status.md +15 -0
  31. package/plugin-src/hooks/.gitkeep +0 -0
  32. package/plugin-src/hooks/hooks.json +14 -0
  33. package/plugin-src/manifest.json +25 -0
  34. package/plugin-src/requirements.txt +1 -0
  35. package/plugin-src/rules/AGENTS.md +90 -0
  36. package/plugin-src/rules/CLAUDE.md.fragment +43 -0
  37. package/plugin-src/scripts/ensure-venv.bat +122 -0
  38. package/plugin-src/scripts/ensure-venv.sh +105 -0
  39. package/plugin-src/scripts/slm-launch +15 -0
  40. package/plugin-src/scripts/slm-launch.bat +17 -0
  41. package/plugin-src/settings.json +16 -0
  42. package/plugin-src/skills/slm-cache/SKILL.md +140 -0
  43. package/plugin-src/skills/slm-compress/SKILL.md +143 -0
  44. package/plugin-src/skills/slm-graph/SKILL.md +300 -0
  45. package/plugin-src/skills/slm-recall/SKILL.md +196 -0
  46. package/plugin-src/skills/slm-remember/SKILL.md +182 -0
  47. package/plugin-src/skills/slm-session/SKILL.md +207 -0
  48. package/plugin-src/skills/slm-status/SKILL.md +149 -0
  49. package/pyproject.toml +6 -2
  50. package/scripts/__tests__/build-plugin.test.mjs +613 -0
  51. package/scripts/_savings_math.py +270 -0
  52. package/scripts/build-plugin.js +742 -0
  53. package/scripts/dogfood_savings.py +490 -0
  54. package/scripts/install-skills.ps1 +4 -334
  55. package/scripts/install-skills.sh +4 -435
  56. package/scripts/postinstall-interactive.js +0 -27
  57. package/scripts/postinstall.js +21 -2
  58. package/src/superlocalmemory/__init__.py +1 -1
  59. package/src/superlocalmemory/cli/_lazy_init.py +115 -0
  60. package/src/superlocalmemory/cli/commands.py +348 -39
  61. package/src/superlocalmemory/cli/main.py +47 -4
  62. package/src/superlocalmemory/cli/setup_wizard.py +20 -6
  63. package/src/superlocalmemory/core/config.py +79 -9
  64. package/src/superlocalmemory/core/embeddings.py +10 -5
  65. package/src/superlocalmemory/core/engine.py +2 -2
  66. package/src/superlocalmemory/hooks/claude_code_hooks.py +27 -3
  67. package/src/superlocalmemory/hooks/portable_kit.py +506 -0
  68. package/src/superlocalmemory/infra/cloud_backup.py +99 -23
  69. package/src/superlocalmemory/mcp/cli_fallback.py +602 -0
  70. package/src/superlocalmemory/mcp/server.py +75 -4
  71. package/src/superlocalmemory/mcp/tools_code_graph.py +3 -3
  72. package/src/superlocalmemory/mcp/tools_core.py +12 -4
  73. package/src/superlocalmemory/optimize/cache/boundary_store.py +25 -6
  74. package/src/superlocalmemory/optimize/cache/centroid_store.py +27 -4
  75. package/src/superlocalmemory/optimize/cache/manager.py +92 -6
  76. package/src/superlocalmemory/optimize/cache/semantic.py +20 -1
  77. package/src/superlocalmemory/optimize/compress/ccr.py +12 -0
  78. package/src/superlocalmemory/optimize/compress/router.py +46 -13
  79. package/src/superlocalmemory/optimize/config/schema.py +6 -0
  80. package/src/superlocalmemory/optimize/proxy/_helpers.py +111 -8
  81. package/src/superlocalmemory/optimize/proxy/anthropic_surface.py +14 -4
  82. package/src/superlocalmemory/optimize/proxy/gemini_surface.py +23 -6
  83. package/src/superlocalmemory/optimize/proxy/openai_surface.py +10 -4
  84. package/src/superlocalmemory/optimize/proxy/server.py +11 -0
  85. package/src/superlocalmemory/optimize/proxy/vertex_surface.py +246 -0
  86. package/src/superlocalmemory/optimize/storage/db.py +30 -0
  87. package/src/superlocalmemory/server/recall_serializer.py +3 -1
  88. package/src/superlocalmemory/server/unified_daemon.py +24 -6
  89. package/src/superlocalmemory/ui/css/legacy-dashboard.css +18 -0
  90. package/src/superlocalmemory/ui/css/neural-glass.css +5 -0
  91. package/src/superlocalmemory/ui/index.html +2 -2
  92. package/src/superlocalmemory/ui/js/core.js +98 -0
  93. package/src/superlocalmemory/ui/js/dashboard.js +8 -1
  94. package/src/superlocalmemory/ui/js/ide-status.js +16 -3
  95. package/src/superlocalmemory/ui/js/math-health.js +15 -3
  96. package/src/superlocalmemory/ui/js/optimize.js +18 -2
  97. package/src/superlocalmemory/ui/js/trust-dashboard.js +10 -1
  98. package/src/superlocalmemory.egg-info/PKG-INFO +189 -742
  99. package/src/superlocalmemory.egg-info/SOURCES.txt +6 -9
  100. package/src/superlocalmemory.egg-info/requires.txt +1 -0
  101. package/ide/skills/slm-build-graph/SKILL.md +0 -423
  102. package/ide/skills/slm-list-recent/SKILL.md +0 -348
  103. package/ide/skills/slm-recall/SKILL.md +0 -326
  104. package/ide/skills/slm-remember/SKILL.md +0 -194
  105. package/ide/skills/slm-show-patterns/SKILL.md +0 -224
  106. package/ide/skills/slm-status/SKILL.md +0 -363
  107. package/ide/skills/slm-switch-profile/SKILL.md +0 -442
  108. package/skills/slm-build-graph/SKILL.md +0 -423
  109. package/skills/slm-list-recent/SKILL.md +0 -348
  110. package/skills/slm-optimize/README.md +0 -55
  111. package/skills/slm-optimize/SKILL.md +0 -139
  112. package/skills/slm-recall/SKILL.md +0 -343
  113. package/skills/slm-remember/SKILL.md +0 -194
  114. package/skills/slm-show-patterns/SKILL.md +0 -224
  115. package/skills/slm-status/SKILL.md +0 -363
  116. package/skills/slm-switch-profile/SKILL.md +0 -442
  117. package/src/superlocalmemory/cli/doctor_cmd.py +0 -152
  118. package/src/superlocalmemory/skills/slm-build-graph/SKILL.md +0 -423
  119. package/src/superlocalmemory/skills/slm-list-recent/SKILL.md +0 -348
  120. package/src/superlocalmemory/skills/slm-recall/SKILL.md +0 -343
  121. package/src/superlocalmemory/skills/slm-remember/SKILL.md +0 -194
  122. package/src/superlocalmemory/skills/slm-show-patterns/SKILL.md +0 -224
  123. package/src/superlocalmemory/skills/slm-status/SKILL.md +0 -363
  124. package/src/superlocalmemory/skills/slm-switch-profile/SKILL.md +0 -442
@@ -1,436 +1,5 @@
1
1
  #!/bin/bash
2
-
3
- # SuperLocalMemory V2 - Universal Skills Installer
4
- # Installs skills for Claude Code, Codex, Gemini CLI, Antigravity, and Windsurf
5
-
6
- set -e
7
-
8
- # Colors for output
9
- RED='\033[0;31m'
10
- GREEN='\033[0;32m'
11
- YELLOW='\033[1;33m'
12
- BLUE='\033[0;34m'
13
- NC='\033[0m' # No Color
14
-
15
- # Configuration
16
- REPO_DIR="$(cd "$(dirname "$0")" && pwd)"
17
- SKILLS_SOURCE="$REPO_DIR/skills"
18
-
19
- # Parse arguments
20
- AUTO_MODE=false
21
- for arg in "$@"; do
22
- case $arg in
23
- --auto)
24
- AUTO_MODE=true
25
- shift
26
- ;;
27
- esac
28
- done
29
-
30
- # Tool definitions (parallel arrays for bash 3.2 compatibility)
31
- TOOL_IDS=("claude_code" "codex" "gemini_cli" "antigravity" "windsurf" "cursor" "vscode_copilot")
32
- TOOL_NAMES=("Claude Code" "Codex" "Gemini CLI" "Antigravity" "Windsurf" "Cursor" "VS Code/Copilot")
33
- TOOL_DIRS=(
34
- "$HOME/.claude/skills"
35
- "$HOME/.codex/skills"
36
- "$HOME/.gemini/skills"
37
- "$HOME/.gemini/antigravity/skills"
38
- "$HOME/.windsurf/skills"
39
- "$HOME/.cursor/skills"
40
- "$HOME/.copilot/skills"
41
- )
42
-
43
- # Helper function to get tool name by ID
44
- get_tool_name() {
45
- local tool_id="$1"
46
- for i in "${!TOOL_IDS[@]}"; do
47
- if [ "${TOOL_IDS[$i]}" = "$tool_id" ]; then
48
- echo "${TOOL_NAMES[$i]}"
49
- return
50
- fi
51
- done
52
- echo "$tool_id"
53
- }
54
-
55
- # Helper function to get tool directory by ID
56
- get_tool_dir() {
57
- local tool_id="$1"
58
- for i in "${!TOOL_IDS[@]}"; do
59
- if [ "${TOOL_IDS[$i]}" = "$tool_id" ]; then
60
- echo "${TOOL_DIRS[$i]}"
61
- return
62
- fi
63
- done
64
- echo ""
65
- }
66
-
67
- # Skills to install (from skills/ directory)
68
- SKILLS=(
69
- "slm-remember"
70
- "slm-recall"
71
- "slm-status"
72
- "slm-list-recent"
73
- "slm-build-graph"
74
- "slm-switch-profile"
75
- )
76
-
77
- echo "=========================================="
78
- echo "SuperLocalMemory V2 - Universal Skills Installer"
79
- echo "=========================================="
80
- echo ""
81
-
82
- # Check if SuperLocalMemory V2 is installed
83
- if [ ! -d "$HOME/.superlocalmemory" ]; then
84
- echo -e "${YELLOW}Warning:${NC} SuperLocalMemory V2 not found at ~/.superlocalmemory/"
85
- echo "Skills require SuperLocalMemory V2 to be installed first."
86
- echo ""
87
- if [ "$AUTO_MODE" = true ]; then
88
- echo "Auto mode: continuing anyway..."
89
- else
90
- read -p "Do you want to continue anyway? (y/n) " -n 1 -r
91
- echo ""
92
- if [[ ! $REPLY =~ ^[Yy]$ ]]; then
93
- echo "Installation cancelled."
94
- echo "Please install SuperLocalMemory V2 first: ./install.sh"
95
- exit 1
96
- fi
97
- fi
98
- fi
99
-
100
- # Check if skills source directory exists
101
- if [ ! -d "$SKILLS_SOURCE" ]; then
102
- echo -e "${RED}Error:${NC} Skills directory not found: $SKILLS_SOURCE"
103
- echo "Please run this script from the superlocalmemory-repo directory."
104
- exit 1
105
- fi
106
-
107
- # Verify all skill directories exist
108
- echo "Verifying skill files..."
109
- MISSING_SKILLS=0
110
- for skill in "${SKILLS[@]}"; do
111
- if [ ! -d "$SKILLS_SOURCE/$skill" ]; then
112
- echo -e "${RED}✗${NC} Missing: $skill/"
113
- ((MISSING_SKILLS++))
114
- elif [ ! -f "$SKILLS_SOURCE/$skill/SKILL.md" ]; then
115
- echo -e "${RED}✗${NC} Missing: $skill/SKILL.md"
116
- ((MISSING_SKILLS++))
117
- else
118
- echo -e "${GREEN}✓${NC} Found: $skill/SKILL.md"
119
- fi
120
- done
121
-
122
- if [ "$MISSING_SKILLS" -gt 0 ]; then
123
- echo -e "${RED}Error:${NC} $MISSING_SKILLS skill(s) missing. Cannot proceed."
124
- exit 1
125
- fi
126
-
127
- echo ""
128
- echo "Found ${#SKILLS[@]} skills to install"
129
- echo ""
130
-
131
- # Detect available tools
132
- echo "=========================================="
133
- echo "Detecting AI Tools"
134
- echo "=========================================="
135
- echo ""
136
-
137
- DETECTED_TOOLS=()
138
-
139
- for i in "${!TOOL_IDS[@]}"; do
140
- tool_id="${TOOL_IDS[$i]}"
141
- tool_name="${TOOL_NAMES[$i]}"
142
- tool_dir="${TOOL_DIRS[$i]}"
143
- parent_dir=$(dirname "$tool_dir")
144
-
145
- # Check if parent directory exists (tool is installed)
146
- if [ -d "$parent_dir" ]; then
147
- echo -e "${GREEN}✓${NC} $tool_name detected: $tool_dir"
148
- DETECTED_TOOLS+=("$tool_id")
149
- else
150
- echo -e "${BLUE}○${NC} $tool_name not found: $parent_dir"
151
- fi
152
- done
153
-
154
- echo ""
155
-
156
- if [ ${#DETECTED_TOOLS[@]} -eq 0 ]; then
157
- if [ "$AUTO_MODE" = true ]; then
158
- echo -e "${YELLOW}Warning:${NC} No supported AI tools detected. Skipping skills installation."
159
- echo ""
160
- exit 0
161
- fi
162
- echo -e "${YELLOW}Warning:${NC} No supported AI tools detected."
163
- echo ""
164
- echo "Supported tools:"
165
- for i in "${!TOOL_IDS[@]}"; do
166
- echo " - ${TOOL_NAMES[$i]}: ${TOOL_DIRS[$i]}"
167
- done
168
- echo ""
169
- read -p "Do you want to continue and create directories anyway? (y/n) " -n 1 -r
170
- echo ""
171
- if [[ ! $REPLY =~ ^[Yy]$ ]]; then
172
- echo "Installation cancelled."
173
- exit 1
174
- fi
175
- # If user wants to continue, add all tools to install list
176
- for tool_id in "${TOOL_IDS[@]}"; do
177
- DETECTED_TOOLS+=("$tool_id")
178
- done
179
- else
180
- echo "Will install skills for ${#DETECTED_TOOLS[@]} tool(s)"
181
- echo ""
182
- fi
183
-
184
- # Ask user for installation method
185
- if [ "$AUTO_MODE" = true ]; then
186
- METHOD="symlink"
187
- echo "Auto mode: Using symlink method..."
188
- else
189
- echo "Installation Methods:"
190
- echo " 1. Symlink (recommended) - Changes in repo reflect immediately"
191
- echo " 2. Copy - Stable, requires manual updates"
192
- echo ""
193
- read -p "Choose installation method (1 or 2): " -n 1 -r
194
- echo ""
195
- echo ""
196
-
197
- if [[ $REPLY == "1" ]]; then
198
- METHOD="symlink"
199
- echo "Installing via symlink..."
200
- elif [[ $REPLY == "2" ]]; then
201
- METHOD="copy"
202
- echo "Installing via copy..."
203
- else
204
- echo -e "${RED}Invalid choice.${NC} Please enter 1 or 2."
205
- exit 1
206
- fi
207
- fi
208
-
209
- echo ""
210
-
211
- # Install skills for each detected tool
212
- TOTAL_INSTALLED=0
213
- TOTAL_FAILED=0
214
- TOTAL_SKIPPED=0
215
-
216
- for tool_id in "${DETECTED_TOOLS[@]}"; do
217
- tool_name=$(get_tool_name "$tool_id")
218
- echo "=========================================="
219
- echo "Installing for: $tool_name"
220
- echo "=========================================="
221
-
222
- skills_dir=$(get_tool_dir "$tool_id")
223
-
224
- # Create skills directory if it doesn't exist
225
- if [ ! -d "$skills_dir" ]; then
226
- echo "Creating directory: $skills_dir"
227
- if mkdir -p "$skills_dir"; then
228
- echo -e "${GREEN}✓${NC} Directory created"
229
- else
230
- echo -e "${RED}✗${NC} Failed to create directory"
231
- echo ""
232
- ((TOTAL_SKIPPED+=${#SKILLS[@]}))
233
- continue
234
- fi
235
- else
236
- echo "Directory exists: $skills_dir"
237
- fi
238
-
239
- echo ""
240
-
241
- # Install each skill
242
- for skill in "${SKILLS[@]}"; do
243
- source_file="$SKILLS_SOURCE/$skill/SKILL.md"
244
- target_file="$skills_dir/$skill.md"
245
-
246
- # Remove existing file or symlink
247
- if [ -e "$target_file" ] || [ -L "$target_file" ]; then
248
- rm "$target_file"
249
- fi
250
-
251
- if [ "$METHOD" == "symlink" ]; then
252
- if ln -s "$source_file" "$target_file" 2>/dev/null; then
253
- echo -e "${GREEN}✓${NC} Symlinked: $skill.md"
254
- ((TOTAL_INSTALLED++))
255
- else
256
- echo -e "${RED}✗${NC} Failed to symlink: $skill.md"
257
- ((TOTAL_FAILED++))
258
- fi
259
- else
260
- if cp "$source_file" "$target_file" 2>/dev/null; then
261
- echo -e "${GREEN}✓${NC} Copied: $skill.md"
262
- ((TOTAL_INSTALLED++))
263
- else
264
- echo -e "${RED}✗${NC} Failed to copy: $skill.md"
265
- ((TOTAL_FAILED++))
266
- fi
267
- fi
268
- done
269
-
270
- # Make skills executable (if they have execute permissions)
271
- chmod +x "$skills_dir"/*.md 2>/dev/null || true
272
-
273
- echo ""
274
- done
275
-
276
- # Installation Summary
277
- echo "=========================================="
278
- echo "Installation Summary"
279
- echo "=========================================="
280
- echo ""
281
- echo -e "Tools configured: ${BLUE}${#DETECTED_TOOLS[@]}${NC}"
282
- echo -e "Skills installed: ${GREEN}$TOTAL_INSTALLED${NC}"
283
- if [ "$TOTAL_FAILED" -gt 0 ]; then
284
- echo -e "Failed: ${RED}$TOTAL_FAILED${NC}"
285
- fi
286
- if [ "$TOTAL_SKIPPED" -gt 0 ]; then
287
- echo -e "Skipped: ${YELLOW}$TOTAL_SKIPPED${NC}"
288
- fi
289
- echo "Installation method: $METHOD"
290
- echo ""
291
-
292
- # List installation locations
293
- echo "Skills installed to:"
294
- for tool_id in "${DETECTED_TOOLS[@]}"; do
295
- tool_name=$(get_tool_name "$tool_id")
296
- tool_dir=$(get_tool_dir "$tool_id")
297
- if [ -d "$tool_dir" ] && [ "$(ls -A "$tool_dir"/*.md 2>/dev/null | wc -l | tr -d ' ')" -gt 0 ]; then
298
- count=$(ls -1 "$tool_dir"/*.md 2>/dev/null | wc -l | tr -d ' ')
299
- echo -e " ${GREEN}✓${NC} $tool_name: $tool_dir ($count skills)"
300
- fi
301
- done
302
-
303
- echo ""
304
-
305
- # Verify installation
306
- EXPECTED_TOTAL=$((${#DETECTED_TOOLS[@]} * ${#SKILLS[@]}))
307
- if [ "$TOTAL_INSTALLED" -eq "$EXPECTED_TOTAL" ]; then
308
- echo -e "${GREEN}✓${NC} All skills installed successfully!"
309
- else
310
- echo -e "${YELLOW}⚠${NC} Some skills failed to install."
311
- echo "Expected: $EXPECTED_TOTAL, Installed: $TOTAL_INSTALLED"
312
- fi
313
-
314
- echo ""
315
-
316
- # List available skills
317
- echo "=========================================="
318
- echo "Available Skills"
319
- echo "=========================================="
320
- echo ""
321
- for skill in "${SKILLS[@]}"; do
322
- echo " • $skill"
323
- done
324
- echo ""
325
-
326
- # Legacy Claude CLI skills (from claude-skills/)
327
- if [ -d "$REPO_DIR/claude-skills" ] && [ -d "$HOME/.claude/skills" ]; then
328
- echo "=========================================="
329
- echo "Legacy Claude CLI Skills"
330
- echo "=========================================="
331
- echo ""
332
- echo "Found legacy claude-skills/ directory for Claude CLI."
333
- echo "These are different from the universal skills above."
334
- echo ""
335
- if [ "$AUTO_MODE" = true ]; then
336
- REPLY="y"
337
- else
338
- read -p "Do you want to install legacy Claude CLI skills too? (y/n) " -n 1 -r
339
- echo ""
340
- echo ""
341
- fi
342
-
343
- if [[ $REPLY =~ ^[Yy]$ ]]; then
344
- LEGACY_COUNT=0
345
- for skill_file in "$REPO_DIR/claude-skills"/superlocalmemoryv2-*.md; do
346
- if [ -f "$skill_file" ]; then
347
- skill_name=$(basename "$skill_file")
348
- target="$HOME/.claude/skills/$skill_name"
349
-
350
- if [ -e "$target" ] || [ -L "$target" ]; then
351
- rm "$target"
352
- fi
353
-
354
- if [ "$METHOD" == "symlink" ]; then
355
- ln -s "$skill_file" "$target" 2>/dev/null && ((LEGACY_COUNT++))
356
- else
357
- cp "$skill_file" "$target" 2>/dev/null && ((LEGACY_COUNT++))
358
- fi
359
- fi
360
- done
361
- echo -e "${GREEN}✓${NC} Installed $LEGACY_COUNT legacy Claude CLI skills"
362
- echo ""
363
- fi
364
- fi
365
-
366
- # Next Steps
367
- echo "=========================================="
368
- echo "Next Steps"
369
- echo "=========================================="
370
- echo ""
371
- echo "1. ${YELLOW}Restart your AI tool${NC} to load the new skills"
372
- echo ""
373
- echo "2. Verify skills are loaded:"
374
- for tool_id in "${DETECTED_TOOLS[@]}"; do
375
- case "$tool_id" in
376
- "claude_code")
377
- echo " ${GREEN}claude${NC} (type /skills to list)"
378
- ;;
379
- "codex")
380
- echo " ${GREEN}codex${NC} (type /skills to list)"
381
- ;;
382
- "gemini_cli")
383
- echo " ${GREEN}gemini${NC} (check available commands)"
384
- ;;
385
- "antigravity")
386
- echo " ${GREEN}antigravity${NC} (check available commands)"
387
- ;;
388
- "windsurf")
389
- echo " ${GREEN}windsurf${NC} (check available commands)"
390
- ;;
391
- "cursor")
392
- echo " ${GREEN}cursor${NC} (check available commands)"
393
- ;;
394
- "vscode_copilot")
395
- echo " ${GREEN}VS Code/Copilot${NC} (check available commands)"
396
- ;;
397
- esac
398
- done
399
- echo ""
400
- echo "3. Try your first skill:"
401
- echo " ${GREEN}/slm-status${NC} or ${GREEN}/slm-remember \"test\"${NC}"
402
- echo ""
403
- echo "4. Read skill documentation:"
404
- echo " Each skill has detailed docs in: $SKILLS_SOURCE/<skill-name>/SKILL.md"
405
- echo ""
406
-
407
- if [ "$METHOD" == "symlink" ]; then
408
- echo "Note: Using symlinks. To update skills:"
409
- echo " cd $REPO_DIR"
410
- echo " git pull"
411
- echo " # Restart your AI tool"
412
- echo ""
413
- fi
414
-
415
- if [ "$METHOD" == "copy" ]; then
416
- echo "Note: Using copies. To update skills:"
417
- echo " cd $REPO_DIR"
418
- echo " git pull"
419
- echo " ./install-skills.sh"
420
- echo " # Choose option 2 again"
421
- echo ""
422
- fi
423
-
424
- echo "=========================================="
425
- echo ""
426
- echo -e "${GREEN}✓ Universal skills installation complete!${NC}"
427
- echo ""
428
- echo "Skills installed for:"
429
- for tool_id in "${DETECTED_TOOLS[@]}"; do
430
- tool_name=$(get_tool_name "$tool_id")
431
- echo " • $tool_name"
432
- done
433
- echo ""
434
- echo "Remember: Skills are OPTIONAL convenience wrappers."
435
- echo "SuperLocalMemory V2 works standalone via terminal commands."
436
- echo ""
2
+ # DEPRECATED in v3.6.14 — skills are now delivered via the Claude Code plugin.
3
+ # Use: claude plugin install superlocalmemory@qualixar
4
+ echo "SLM skills are now delivered via the Claude Code plugin (/plugin install) standalone skill install is retired in v3.6.14."
5
+ exit 0
@@ -689,33 +689,6 @@ async function main() {
689
689
  return 4;
690
690
  }
691
691
 
692
- // S9-DASH-11: auto-install SLM skills into ~/.claude/skills/ so
693
- // /slm-recall, /slm-remember, /slm-status etc. appear immediately
694
- // in Claude Code without a manual step.
695
- try {
696
- const skillsSrc = path.join(__dirname, '..', 'skills');
697
- const claudeSkillsDir = path.join(os.homedir(), '.claude', 'skills');
698
- if (fs.existsSync(skillsSrc)) {
699
- fs.mkdirSync(claudeSkillsDir, { recursive: true, mode: 0o700 });
700
- const skillDirs = fs.readdirSync(skillsSrc);
701
- let installed = 0;
702
- for (const d of skillDirs) {
703
- const src = path.join(skillsSrc, d, 'SKILL.md');
704
- if (fs.existsSync(src)) {
705
- const dst = path.join(claudeSkillsDir, d + '.md');
706
- fs.copyFileSync(src, dst);
707
- installed += 1;
708
- }
709
- }
710
- if (installed > 0) {
711
- console.log('SLM: installed ' + installed + ' skills → ' + claudeSkillsDir);
712
- console.log(' Use /slm-recall, /slm-remember, /slm-status in Claude Code');
713
- }
714
- }
715
- } catch (e) {
716
- // Non-fatal — skills can be installed manually via install-skills.sh
717
- console.log('SLM: skill install skipped (' + e.message + ')');
718
- }
719
692
 
720
693
  // UX-G2: show the one-screen delta banner so upgraders see what shipped.
721
694
  printLivingBrainDelta();
@@ -131,12 +131,31 @@ if (pipInstallPkg.status === 0) {
131
131
  if (retryResult.status === 0) {
132
132
  console.log('✓ SuperLocalMemory Python package installed (--user)');
133
133
  } else {
134
- console.log('⚠ Could not pip install the package. The Node.js wrapper (slm-npm)');
135
- console.log(' sets PYTHONPATH automatically, so CLI will still work.');
134
+ // WP-07: --user also failed try --break-system-packages last-resort,
135
+ // then surface the pipx hint (PEP 668 advisory).
136
+ const retryBsp = spawnSync(pythonParts[0], [
137
+ ...pythonParts.slice(1), '-m', 'pip', 'install', '--quiet',
138
+ '--disable-pip-version-check', '--break-system-packages', pkgRoot,
139
+ ], { stdio: 'pipe', timeout: 300000, env: { ...process.env, PATH: '/opt/homebrew/bin:/usr/local/bin:/usr/bin:' + (process.env.PATH || '') } });
140
+ if (retryBsp.status === 0) {
141
+ console.log('✓ SuperLocalMemory Python package installed (--break-system-packages)');
142
+ } else {
143
+ console.log('⚠ pip install failed (PEP 668 — externally managed Python).');
144
+ console.log(' The Node.js wrapper (slm-npm) sets PYTHONPATH automatically,');
145
+ console.log(' so the CLI will still work via npm.');
146
+ console.log('');
147
+ console.log(' To install into an isolated environment (recommended):');
148
+ console.log(' pipx install superlocalmemory');
149
+ console.log(' Last resort (may break OS packages):');
150
+ console.log(' pip install --break-system-packages superlocalmemory');
151
+ }
136
152
  }
137
153
  } else {
138
154
  console.log('⚠ Could not pip install the package. The Node.js wrapper (slm-npm)');
139
155
  console.log(' sets PYTHONPATH automatically, so CLI will still work.');
156
+ console.log('');
157
+ console.log(' If you see a PEP 668 error in future, install via:');
158
+ console.log(' pipx install superlocalmemory');
140
159
  }
141
160
  }
142
161
 
@@ -32,7 +32,7 @@ if "OMP_NUM_THREADS" not in os.environ:
32
32
  os.environ["OMP_NUM_THREADS"] = "2"
33
33
  # ---------------------------------------------------------------------------
34
34
 
35
- __version__ = "3.6.10"
35
+ __version__ = "3.6.14"
36
36
 
37
37
  _REQUIRED_VERSIONS = {
38
38
  "sentence_transformers": "5.3.0",
@@ -0,0 +1,115 @@
1
+ # Copyright (c) 2026 Varun Pratap Bhardwaj / Qualixar
2
+ # Licensed under AGPL-3.0-or-later - see LICENSE file
3
+ # Part of SuperLocalMemory V3 | https://qualixar.com | https://varunpratap.com
4
+
5
+ """WP-07 — Lazy first-run initialisation (pip cross-install).
6
+
7
+ stdlib-only — zero heavy imports, STDOUT-SILENT.
8
+
9
+ Public API
10
+ ----------
11
+ slm_home() -> Path
12
+ Resolve the SLM data directory from env aliases, falling back to
13
+ ~/.superlocalmemory. Pure: no mkdir, no I/O beyond os.environ reads.
14
+ Priority: SLM_DATA_DIR -> SL_MEMORY_PATH -> SLM_HOME -> default.
15
+
16
+ _ensure_initialized() -> None
17
+ Idempotent first-run guard: creates the home dir + a minimal mode-A
18
+ config.json if absent. Fast-path returns immediately when both dir
19
+ and config exist. Never raises, never prints to stdout.
20
+ """
21
+
22
+ from __future__ import annotations
23
+
24
+ import json
25
+ import os
26
+ from pathlib import Path
27
+
28
+
29
+ # ---------------------------------------------------------------------------
30
+ # Public: home resolution
31
+ # ---------------------------------------------------------------------------
32
+
33
+
34
+ def slm_home() -> Path:
35
+ """Resolve the SLM data directory.
36
+
37
+ Resolution order (first non-empty wins):
38
+ 1. SLM_DATA_DIR — canonical env var
39
+ 2. SL_MEMORY_PATH — legacy alias (setup_wizard.py)
40
+ 3. SLM_HOME — hook alias (hooks/_outcome_common.py)
41
+ 4. ~/.superlocalmemory — hard default
42
+
43
+ Pure: no mkdir, no side effects.
44
+ """
45
+ for var in ("SLM_DATA_DIR", "SL_MEMORY_PATH", "SLM_HOME"):
46
+ val = os.environ.get(var, "").strip()
47
+ if val:
48
+ return Path(val)
49
+ return Path.home() / ".superlocalmemory"
50
+
51
+
52
+ # ---------------------------------------------------------------------------
53
+ # Public: idempotent first-run init
54
+ # ---------------------------------------------------------------------------
55
+
56
+ # Minimal mode-A config written on first-run pip install.
57
+ # Only mode + base_dir; everything else uses SLMConfig defaults.
58
+ _MINIMAL_CONFIG: dict = {
59
+ "mode": "a",
60
+ "version": "3.6.14",
61
+ }
62
+
63
+
64
+ def _ensure_initialized() -> None:
65
+ """Idempotent first-run guard.
66
+
67
+ Creates ~/.superlocalmemory/ (or env-overridden path) and a minimal
68
+ mode-A config.json if they are absent.
69
+
70
+ Contract:
71
+ - NEVER raises (OSError → silent degrade, AC4).
72
+ - NEVER prints to stdout (CRIT-3).
73
+ - NEVER overwrites an existing config.json (AC3).
74
+ - 2nd call is a no-op — mtime of config unchanged (AC2).
75
+ - Does NOT write the .setup-complete sentinel.
76
+ """
77
+ try:
78
+ home = slm_home()
79
+ config = home / "config.json"
80
+
81
+ # Fast path: both dir and config exist — nothing to do (AC2).
82
+ if home.is_dir() and config.exists():
83
+ return
84
+
85
+ # Ensure the directory exists.
86
+ home.mkdir(parents=True, exist_ok=True)
87
+
88
+ # Write config only when absent (AC3 + AC2).
89
+ if not config.exists():
90
+ _write_minimal_config(home, config)
91
+
92
+ except OSError:
93
+ # Read-only home or any I/O failure → degrade silently (AC4).
94
+ return
95
+
96
+
97
+ def _write_minimal_config(home: Path, config: Path) -> None:
98
+ """Atomically write a minimal mode-A config.json inside *home*.
99
+
100
+ Uses a .tmp file inside the same directory so os.replace() is always
101
+ on the same filesystem (no cross-FS rename). Never writes to /tmp.
102
+ """
103
+ # PID-namespaced tmp so two `slm` processes first-running concurrently don't
104
+ # clobber each other's tmp (which would make one os.replace fail mid-race).
105
+ tmp_path = home / f".config.json.tmp.{os.getpid()}"
106
+ try:
107
+ payload = json.dumps(_MINIMAL_CONFIG, indent=2)
108
+ tmp_path.write_text(payload, encoding="utf-8")
109
+ os.replace(str(tmp_path), str(config))
110
+ except OSError:
111
+ # Clean up tmp on failure; ignore errors — degrade silently.
112
+ try:
113
+ tmp_path.unlink(missing_ok=True)
114
+ except OSError:
115
+ pass