qualia-framework 2.5.1 → 2.6.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.
- package/bin/cli.js +90 -0
- package/framework/qualia-framework/VERSION +1 -1
- package/package.json +6 -2
- package/uninstall.sh +90 -0
package/bin/cli.js
CHANGED
|
@@ -167,6 +167,94 @@ function prompt(question) {
|
|
|
167
167
|
});
|
|
168
168
|
}
|
|
169
169
|
|
|
170
|
+
// ── Uninstall ──
|
|
171
|
+
async function runUninstall() {
|
|
172
|
+
log('');
|
|
173
|
+
log(`${c.red}\u2554${'═'.repeat(54)}\u2557${c.reset}`);
|
|
174
|
+
log(`${c.red}\u2551${c.reset}${c.bold} QUALIA FRAMEWORK \u2014 UNINSTALLER ${c.reset}${c.red}\u2551${c.reset}`);
|
|
175
|
+
log(`${c.red}\u255A${'═'.repeat(54)}\u255D${c.reset}`);
|
|
176
|
+
log('');
|
|
177
|
+
|
|
178
|
+
if (!fs.existsSync(CLAUDE_DIR)) {
|
|
179
|
+
warn('Nothing to uninstall \u2014 ~/.claude/ does not exist.');
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Count everything in ~/.claude/
|
|
184
|
+
const totalFiles = countFilesRecursive(CLAUDE_DIR);
|
|
185
|
+
|
|
186
|
+
log(`${c.bold} NUCLEAR UNINSTALL \u2014 deleting EVERYTHING in ~/.claude/${c.reset}`);
|
|
187
|
+
log('');
|
|
188
|
+
log(` ${c.red}\u2022${c.reset} ${totalFiles} files will be permanently deleted`);
|
|
189
|
+
log(` ${c.red}\u2022${c.reset} settings.json will be reset to {}`);
|
|
190
|
+
log(` ${c.red}\u2022${c.reset} All skills, agents, hooks, rules, knowledge \u2014 gone`);
|
|
191
|
+
log(` ${c.red}\u2022${c.reset} All memory, projects, plans, cache \u2014 gone`);
|
|
192
|
+
log(` ${c.red}\u2022${c.reset} CLAUDE.md, .env.claude, all config \u2014 gone`);
|
|
193
|
+
log('');
|
|
194
|
+
|
|
195
|
+
// Confirmation
|
|
196
|
+
const force = process.argv.includes('--force');
|
|
197
|
+
if (!force) {
|
|
198
|
+
log(`${c.red} \u26A0 THIS CANNOT BE UNDONE.${c.reset}`);
|
|
199
|
+
log(`${c.red} \u26A0 ~/.claude/ will be wiped clean. Nothing survives.${c.reset}`);
|
|
200
|
+
log('');
|
|
201
|
+
const answer = await prompt(` Type 'UNINSTALL' to confirm: `);
|
|
202
|
+
if (answer !== 'UNINSTALL') {
|
|
203
|
+
log('');
|
|
204
|
+
ok('Cancelled. Nothing was deleted.');
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
log('');
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Step 1: Nuke everything in ~/.claude/ except settings.json (we handle that separately)
|
|
211
|
+
step(1, 2, 'Nuking ~/.claude/ ...');
|
|
212
|
+
|
|
213
|
+
for (const entry of fs.readdirSync(CLAUDE_DIR, { withFileTypes: true })) {
|
|
214
|
+
const p = path.join(CLAUDE_DIR, entry.name);
|
|
215
|
+
|
|
216
|
+
// Skip settings.json — we reset it in step 2
|
|
217
|
+
if (entry.name === 'settings.json') continue;
|
|
218
|
+
|
|
219
|
+
try {
|
|
220
|
+
if (entry.isDirectory()) {
|
|
221
|
+
fs.rmSync(p, { recursive: true, force: true });
|
|
222
|
+
ok(`${entry.name}/`);
|
|
223
|
+
} else if (isSymlink(p)) {
|
|
224
|
+
fs.unlinkSync(p);
|
|
225
|
+
ok(`${entry.name} (symlink)`);
|
|
226
|
+
} else {
|
|
227
|
+
fs.unlinkSync(p);
|
|
228
|
+
ok(entry.name);
|
|
229
|
+
}
|
|
230
|
+
} catch (e) {
|
|
231
|
+
fail(`${entry.name}: ${e.message}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Step 2: Reset settings.json to empty
|
|
236
|
+
step(2, 2, 'Resetting settings.json ...');
|
|
237
|
+
const settingsPath = path.join(CLAUDE_DIR, 'settings.json');
|
|
238
|
+
if (fs.existsSync(settingsPath)) {
|
|
239
|
+
fs.writeFileSync(settingsPath, '{}\n');
|
|
240
|
+
ok('settings.json reset to {}');
|
|
241
|
+
} else {
|
|
242
|
+
ok('No settings.json found');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
log('');
|
|
246
|
+
log(`${c.green}\u2554${'═'.repeat(54)}\u2557${c.reset}`);
|
|
247
|
+
log(`${c.green}\u2551${c.reset}${c.bold} \u2713 NUKED \u2014 ~/.claude/ is clean ${c.reset}${c.green}\u2551${c.reset}`);
|
|
248
|
+
log(`${c.green}\u255A${'═'.repeat(54)}\u255D${c.reset}`);
|
|
249
|
+
log('');
|
|
250
|
+
log(` ${c.dim}Claude Code will use default behavior on next launch.${c.reset}`);
|
|
251
|
+
log('');
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
function isSymlink(p) {
|
|
255
|
+
try { fs.lstatSync(p); return fs.lstatSync(p).isSymbolicLink(); } catch { return false; }
|
|
256
|
+
}
|
|
257
|
+
|
|
170
258
|
// ── Main ──
|
|
171
259
|
async function main() {
|
|
172
260
|
const command = process.argv[2];
|
|
@@ -175,6 +263,8 @@ async function main() {
|
|
|
175
263
|
await runUpdate();
|
|
176
264
|
} else if (command === 'verify') {
|
|
177
265
|
runVerify();
|
|
266
|
+
} else if (command === 'uninstall') {
|
|
267
|
+
await runUninstall();
|
|
178
268
|
} else {
|
|
179
269
|
await runInstall();
|
|
180
270
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.6.0
|
package/package.json
CHANGED
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "qualia-framework",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0",
|
|
4
4
|
"description": "Qualia Solutions — Claude Code Framework",
|
|
5
5
|
"bin": {
|
|
6
6
|
"qualia-framework": "./bin/cli.js"
|
|
7
7
|
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"preuninstall": "node bin/cli.js uninstall --force"
|
|
10
|
+
},
|
|
8
11
|
"files": [
|
|
9
12
|
"bin/",
|
|
10
13
|
"framework/",
|
|
11
14
|
"profiles/",
|
|
12
|
-
"templates/"
|
|
15
|
+
"templates/",
|
|
16
|
+
"uninstall.sh"
|
|
13
17
|
],
|
|
14
18
|
"engines": {
|
|
15
19
|
"node": ">=18.0.0"
|
package/uninstall.sh
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Qualia Framework — Nuclear Uninstaller
|
|
3
|
+
# Wipes EVERYTHING in ~/.claude/ — nothing survives
|
|
4
|
+
#
|
|
5
|
+
# Usage: ./uninstall.sh
|
|
6
|
+
# ./uninstall.sh --force (skip confirmation)
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
# Colors
|
|
11
|
+
RED='\033[38;2;239;68;68m'
|
|
12
|
+
GREEN='\033[38;2;52;211;153m'
|
|
13
|
+
YELLOW='\033[38;2;234;179;8m'
|
|
14
|
+
WHITE='\033[38;2;220;225;230m'
|
|
15
|
+
DIM='\033[38;2;70;78;88m'
|
|
16
|
+
RESET='\033[0m'
|
|
17
|
+
|
|
18
|
+
CLAUDE_DIR="$HOME/.claude"
|
|
19
|
+
|
|
20
|
+
printf "\n"
|
|
21
|
+
printf "${RED}━━━${RESET} ${WHITE}QUALIA FRAMEWORK — NUCLEAR UNINSTALLER${RESET}\n"
|
|
22
|
+
printf "\n"
|
|
23
|
+
|
|
24
|
+
if [ ! -d "$CLAUDE_DIR" ]; then
|
|
25
|
+
printf "${YELLOW} Nothing to uninstall — $CLAUDE_DIR does not exist.${RESET}\n\n"
|
|
26
|
+
exit 0
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
# Count everything
|
|
30
|
+
TOTAL=$(find "$CLAUDE_DIR" -type f 2>/dev/null | wc -l | tr -d ' ')
|
|
31
|
+
|
|
32
|
+
printf "${WHITE} NUCLEAR UNINSTALL — deleting EVERYTHING in ~/.claude/${RESET}\n\n"
|
|
33
|
+
printf " ${RED}*${RESET} ${TOTAL} files will be permanently deleted\n"
|
|
34
|
+
printf " ${RED}*${RESET} settings.json will be reset to {}\n"
|
|
35
|
+
printf " ${RED}*${RESET} All skills, agents, hooks, rules, knowledge — gone\n"
|
|
36
|
+
printf " ${RED}*${RESET} All memory, projects, plans, cache — gone\n"
|
|
37
|
+
printf " ${RED}*${RESET} CLAUDE.md, .env.claude, all config — gone\n\n"
|
|
38
|
+
|
|
39
|
+
# ─── Confirmation ───
|
|
40
|
+
if [ "${1:-}" != "--force" ]; then
|
|
41
|
+
printf "${RED} WARNING: THIS CANNOT BE UNDONE.${RESET}\n"
|
|
42
|
+
printf "${RED} ~/.claude/ will be wiped clean. Nothing survives.${RESET}\n\n"
|
|
43
|
+
read -rp " Type 'UNINSTALL' to confirm: " CONFIRM </dev/tty
|
|
44
|
+
if [ "$CONFIRM" != "UNINSTALL" ]; then
|
|
45
|
+
printf "\n${GREEN} Cancelled. Nothing was deleted.${RESET}\n\n"
|
|
46
|
+
exit 0
|
|
47
|
+
fi
|
|
48
|
+
printf "\n"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
# ─── Step 1: Nuke everything except settings.json ───
|
|
52
|
+
printf "${YELLOW}[1/2] Nuking ~/.claude/ ...${RESET}\n"
|
|
53
|
+
|
|
54
|
+
for entry in "$CLAUDE_DIR"/* "$CLAUDE_DIR"/.*; do
|
|
55
|
+
[ ! -e "$entry" ] && [ ! -L "$entry" ] && continue
|
|
56
|
+
name=$(basename "$entry")
|
|
57
|
+
|
|
58
|
+
# Skip . and ..
|
|
59
|
+
[ "$name" = "." ] || [ "$name" = ".." ] && continue
|
|
60
|
+
|
|
61
|
+
# Skip settings.json — we reset it in step 2
|
|
62
|
+
[ "$name" = "settings.json" ] && continue
|
|
63
|
+
|
|
64
|
+
if [ -L "$entry" ]; then
|
|
65
|
+
rm -f "$entry"
|
|
66
|
+
printf "${GREEN} ✓ ${name} (symlink)${RESET}\n"
|
|
67
|
+
elif [ -d "$entry" ]; then
|
|
68
|
+
rm -rf "$entry"
|
|
69
|
+
printf "${GREEN} ✓ ${name}/${RESET}\n"
|
|
70
|
+
elif [ -f "$entry" ]; then
|
|
71
|
+
rm -f "$entry"
|
|
72
|
+
printf "${GREEN} ✓ ${name}${RESET}\n"
|
|
73
|
+
fi
|
|
74
|
+
done
|
|
75
|
+
|
|
76
|
+
# ─── Step 2: Reset settings.json ───
|
|
77
|
+
printf "${YELLOW}[2/2] Resetting settings.json ...${RESET}\n"
|
|
78
|
+
|
|
79
|
+
if [ -f "$CLAUDE_DIR/settings.json" ]; then
|
|
80
|
+
echo '{}' > "$CLAUDE_DIR/settings.json"
|
|
81
|
+
printf "${GREEN} ✓ settings.json reset to {}${RESET}\n"
|
|
82
|
+
else
|
|
83
|
+
printf "${GREEN} ✓ No settings.json found${RESET}\n"
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
# ─── Done ───
|
|
87
|
+
printf "\n"
|
|
88
|
+
printf "${GREEN}━━━${RESET} ${WHITE}NUKED${RESET}\n\n"
|
|
89
|
+
printf " ${WHITE}~/.claude/ is clean. Nothing survived.${RESET}\n"
|
|
90
|
+
printf " ${DIM}Claude Code will use default behavior on next launch.${RESET}\n\n"
|