superlocalmemory 3.6.13 → 3.6.15
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 +17 -0
- package/CHANGELOG.md +28 -0
- package/README.md +189 -740
- package/package.json +12 -5
- package/plugin/.claude-plugin/plugin.json +20 -0
- package/plugin/.mcp.json +12 -0
- package/plugin/CLAUDE.md +44 -0
- package/plugin/_GENERATED.md +6 -0
- package/plugin/agents/slm-memory-advisor.md +44 -0
- package/plugin/agents/slm-optimize-advisor.md +38 -0
- package/plugin/hooks/hooks.json +14 -0
- package/plugin/requirements.txt +1 -0
- package/plugin/scripts/ensure-venv.bat +122 -0
- package/plugin/scripts/ensure-venv.sh +105 -0
- package/plugin/scripts/slm-launch +15 -0
- package/plugin/scripts/slm-launch.bat +17 -0
- package/plugin/settings.json +16 -0
- package/plugin/skills/slm-cache/SKILL.md +140 -0
- package/plugin/skills/slm-compress/SKILL.md +143 -0
- package/plugin/skills/slm-graph/SKILL.md +300 -0
- package/plugin/skills/slm-recall/SKILL.md +204 -0
- package/plugin/skills/slm-remember/SKILL.md +194 -0
- package/plugin/skills/slm-session/SKILL.md +207 -0
- package/plugin/skills/slm-status/SKILL.md +149 -0
- package/plugin-src/.mcp.json +12 -0
- package/plugin-src/agents/slm-memory-advisor.md +44 -0
- package/plugin-src/agents/slm-optimize-advisor.md +38 -0
- package/plugin-src/commands/slm-optimize.md +22 -0
- package/plugin-src/commands/slm-recall.md +16 -0
- package/plugin-src/commands/slm-remember.md +16 -0
- package/plugin-src/commands/slm-status.md +15 -0
- package/plugin-src/hooks/.gitkeep +0 -0
- package/plugin-src/hooks/hooks.json +14 -0
- package/plugin-src/manifest.json +25 -0
- package/plugin-src/requirements.txt +1 -0
- package/plugin-src/rules/AGENTS.md +91 -0
- package/plugin-src/rules/CLAUDE.md.fragment +44 -0
- package/plugin-src/scripts/ensure-venv.bat +122 -0
- package/plugin-src/scripts/ensure-venv.sh +105 -0
- package/plugin-src/scripts/slm-launch +15 -0
- package/plugin-src/scripts/slm-launch.bat +17 -0
- package/plugin-src/settings.json +16 -0
- package/plugin-src/skills/slm-cache/SKILL.md +140 -0
- package/plugin-src/skills/slm-compress/SKILL.md +143 -0
- package/plugin-src/skills/slm-graph/SKILL.md +300 -0
- package/plugin-src/skills/slm-recall/SKILL.md +204 -0
- package/plugin-src/skills/slm-remember/SKILL.md +194 -0
- package/plugin-src/skills/slm-session/SKILL.md +207 -0
- package/plugin-src/skills/slm-status/SKILL.md +149 -0
- package/pyproject.toml +6 -2
- package/scripts/__tests__/build-plugin.test.mjs +613 -0
- package/scripts/_savings_math.py +270 -0
- package/scripts/build-plugin.js +742 -0
- package/scripts/dogfood_savings.py +490 -0
- package/scripts/install-skills.ps1 +4 -334
- package/scripts/install-skills.sh +4 -435
- package/scripts/postinstall-interactive.js +0 -27
- package/scripts/postinstall.js +21 -2
- package/src/superlocalmemory/__init__.py +1 -1
- package/src/superlocalmemory/cli/_lazy_init.py +115 -0
- package/src/superlocalmemory/cli/commands.py +439 -41
- package/src/superlocalmemory/cli/main.py +92 -4
- package/src/superlocalmemory/cli/setup_wizard.py +47 -6
- package/src/superlocalmemory/core/backend_orchestrator.py +12 -8
- package/src/superlocalmemory/core/config.py +194 -9
- package/src/superlocalmemory/core/embeddings.py +10 -5
- package/src/superlocalmemory/core/engine.py +76 -5
- package/src/superlocalmemory/core/fact_consolidator.py +20 -3
- package/src/superlocalmemory/core/platform_utils.py +8 -0
- package/src/superlocalmemory/core/recall_pipeline.py +7 -0
- package/src/superlocalmemory/core/recall_worker.py +7 -0
- package/src/superlocalmemory/core/store_pipeline.py +23 -1
- package/src/superlocalmemory/core/worker_pool.py +14 -2
- package/src/superlocalmemory/hooks/claude_code_hooks.py +27 -3
- package/src/superlocalmemory/hooks/portable_kit.py +506 -0
- package/src/superlocalmemory/hooks/session_registry.py +8 -4
- package/src/superlocalmemory/infra/cloud_backup.py +99 -23
- package/src/superlocalmemory/mcp/_daemon_proxy.py +12 -2
- package/src/superlocalmemory/mcp/_pool_adapter.py +15 -6
- package/src/superlocalmemory/mcp/cli_fallback.py +602 -0
- package/src/superlocalmemory/mcp/server.py +75 -4
- package/src/superlocalmemory/mcp/tools_code_graph.py +3 -3
- package/src/superlocalmemory/mcp/tools_core.py +37 -4
- package/src/superlocalmemory/mcp/tools_v3.py +6 -1
- package/src/superlocalmemory/mcp/tools_v33.py +8 -4
- package/src/superlocalmemory/optimize/cache/boundary_store.py +25 -6
- package/src/superlocalmemory/optimize/cache/centroid_store.py +27 -4
- package/src/superlocalmemory/optimize/cache/manager.py +92 -6
- package/src/superlocalmemory/optimize/cache/semantic.py +20 -1
- package/src/superlocalmemory/optimize/compress/ccr.py +12 -0
- package/src/superlocalmemory/optimize/compress/router.py +46 -13
- package/src/superlocalmemory/optimize/config/schema.py +6 -0
- package/src/superlocalmemory/optimize/proxy/_helpers.py +111 -8
- package/src/superlocalmemory/optimize/proxy/anthropic_surface.py +14 -4
- package/src/superlocalmemory/optimize/proxy/gemini_surface.py +23 -6
- package/src/superlocalmemory/optimize/proxy/openai_surface.py +10 -4
- package/src/superlocalmemory/optimize/proxy/server.py +11 -0
- package/src/superlocalmemory/optimize/proxy/vertex_surface.py +246 -0
- package/src/superlocalmemory/optimize/storage/db.py +30 -0
- package/src/superlocalmemory/retrieval/bm25_channel.py +12 -2
- package/src/superlocalmemory/retrieval/engine.py +36 -3
- package/src/superlocalmemory/retrieval/entity_channel.py +5 -5
- package/src/superlocalmemory/retrieval/hopfield_channel.py +10 -2
- package/src/superlocalmemory/retrieval/semantic_channel.py +10 -2
- package/src/superlocalmemory/server/recall_serializer.py +3 -1
- package/src/superlocalmemory/server/unified_daemon.py +156 -16
- package/src/superlocalmemory/storage/database.py +215 -43
- package/src/superlocalmemory/storage/migration_runner.py +17 -1
- package/src/superlocalmemory/storage/migrations/M016_add_scope_support.py +120 -0
- package/src/superlocalmemory/storage/models.py +10 -0
- package/src/superlocalmemory/storage/schema.py +15 -10
- package/src/superlocalmemory/ui/css/legacy-dashboard.css +18 -0
- package/src/superlocalmemory/ui/css/neural-glass.css +5 -0
- package/src/superlocalmemory/ui/index.html +2 -2
- package/src/superlocalmemory/ui/js/core.js +98 -0
- package/src/superlocalmemory/ui/js/dashboard.js +8 -1
- package/src/superlocalmemory/ui/js/ide-status.js +16 -3
- package/src/superlocalmemory/ui/js/math-health.js +15 -3
- package/src/superlocalmemory/ui/js/optimize.js +18 -2
- package/src/superlocalmemory/ui/js/trust-dashboard.js +10 -1
- package/src/superlocalmemory.egg-info/PKG-INFO +191 -741
- package/src/superlocalmemory.egg-info/SOURCES.txt +7 -9
- package/src/superlocalmemory.egg-info/requires.txt +1 -0
- package/ide/skills/slm-build-graph/SKILL.md +0 -423
- package/ide/skills/slm-list-recent/SKILL.md +0 -348
- package/ide/skills/slm-recall/SKILL.md +0 -326
- package/ide/skills/slm-remember/SKILL.md +0 -194
- package/ide/skills/slm-show-patterns/SKILL.md +0 -224
- package/ide/skills/slm-status/SKILL.md +0 -363
- package/ide/skills/slm-switch-profile/SKILL.md +0 -442
- package/skills/slm-build-graph/SKILL.md +0 -423
- package/skills/slm-list-recent/SKILL.md +0 -348
- package/skills/slm-optimize/README.md +0 -55
- package/skills/slm-optimize/SKILL.md +0 -139
- package/skills/slm-recall/SKILL.md +0 -343
- package/skills/slm-remember/SKILL.md +0 -194
- package/skills/slm-show-patterns/SKILL.md +0 -224
- package/skills/slm-status/SKILL.md +0 -363
- package/skills/slm-switch-profile/SKILL.md +0 -442
- package/src/superlocalmemory/cli/doctor_cmd.py +0 -152
- package/src/superlocalmemory/skills/slm-build-graph/SKILL.md +0 -423
- package/src/superlocalmemory/skills/slm-list-recent/SKILL.md +0 -348
- package/src/superlocalmemory/skills/slm-recall/SKILL.md +0 -343
- package/src/superlocalmemory/skills/slm-remember/SKILL.md +0 -194
- package/src/superlocalmemory/skills/slm-show-patterns/SKILL.md +0 -224
- package/src/superlocalmemory/skills/slm-status/SKILL.md +0 -363
- package/src/superlocalmemory/skills/slm-switch-profile/SKILL.md +0 -442
|
@@ -1,436 +1,5 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
|
-
|
|
3
|
-
#
|
|
4
|
-
|
|
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();
|
package/scripts/postinstall.js
CHANGED
|
@@ -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
|
-
|
|
135
|
-
|
|
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.
|
|
35
|
+
__version__ = "3.6.15"
|
|
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
|