@soleri/cli 9.3.1 → 9.4.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/dist/commands/agent.js +51 -2
- package/dist/commands/agent.js.map +1 -1
- package/dist/commands/pack.js +62 -13
- package/dist/commands/pack.js.map +1 -1
- package/dist/commands/staging.d.ts +49 -0
- package/dist/commands/staging.js +108 -18
- package/dist/commands/staging.js.map +1 -1
- package/dist/commands/yolo.d.ts +2 -0
- package/dist/commands/yolo.js +86 -0
- package/dist/commands/yolo.js.map +1 -0
- package/dist/hook-packs/yolo-safety/manifest.json +2 -2
- package/dist/hook-packs/yolo-safety/scripts/anti-deletion.sh +121 -61
- package/dist/main.js +2 -0
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/hook-packs.test.ts +1 -1
- package/src/__tests__/wizard-e2e.mjs +1 -1
- package/src/commands/agent.ts +65 -2
- package/src/commands/pack.ts +80 -14
- package/src/commands/staging.ts +143 -20
- package/src/commands/yolo.ts +103 -0
- package/src/hook-packs/yolo-safety/manifest.json +2 -2
- package/src/hook-packs/yolo-safety/scripts/anti-deletion.sh +121 -61
- package/src/main.ts +2 -0
- package/vitest.config.ts +1 -0
- package/src/__tests__/archetypes.test.ts +0 -84
- package/src/__tests__/create.test.ts +0 -207
- package/src/prompts/archetypes.ts +0 -343
package/dist/commands/staging.js
CHANGED
|
@@ -2,11 +2,13 @@ import { existsSync, readdirSync, statSync, rmSync, cpSync, mkdirSync } from 'no
|
|
|
2
2
|
import { join, relative } from 'node:path';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import * as log from '../utils/logger.js';
|
|
5
|
-
const STAGING_ROOT = join(homedir(), '.soleri', 'staging');
|
|
5
|
+
export const STAGING_ROOT = join(homedir(), '.soleri', 'staging');
|
|
6
|
+
/** Default max age for stale staging entries (7 days). */
|
|
7
|
+
const DEFAULT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
6
8
|
/**
|
|
7
9
|
* Walk a directory tree and collect all items with their relative paths.
|
|
8
10
|
*/
|
|
9
|
-
function walkDir(dir, base) {
|
|
11
|
+
export function walkDir(dir, base) {
|
|
10
12
|
const results = [];
|
|
11
13
|
if (!existsSync(dir))
|
|
12
14
|
return results;
|
|
@@ -27,7 +29,7 @@ function walkDir(dir, base) {
|
|
|
27
29
|
/**
|
|
28
30
|
* List all staged entries.
|
|
29
31
|
*/
|
|
30
|
-
function listStaged() {
|
|
32
|
+
export function listStaged() {
|
|
31
33
|
if (!existsSync(STAGING_ROOT))
|
|
32
34
|
return [];
|
|
33
35
|
const entries = [];
|
|
@@ -52,7 +54,7 @@ function listStaged() {
|
|
|
52
54
|
/**
|
|
53
55
|
* Parse a duration string like "7d", "24h", "30m" into milliseconds.
|
|
54
56
|
*/
|
|
55
|
-
function parseDuration(duration) {
|
|
57
|
+
export function parseDuration(duration) {
|
|
56
58
|
const match = duration.match(/^(\d+)(d|h|m)$/);
|
|
57
59
|
if (!match)
|
|
58
60
|
return null;
|
|
@@ -69,13 +71,63 @@ function parseDuration(duration) {
|
|
|
69
71
|
return null;
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
|
-
function formatSize(bytes) {
|
|
74
|
+
export function formatSize(bytes) {
|
|
73
75
|
if (bytes < 1024)
|
|
74
76
|
return `${bytes} B`;
|
|
75
77
|
if (bytes < 1024 * 1024)
|
|
76
78
|
return `${(bytes / 1024).toFixed(1)} KB`;
|
|
77
79
|
return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
|
|
78
80
|
}
|
|
81
|
+
/**
|
|
82
|
+
* Check for staging entries older than a given age.
|
|
83
|
+
* Pure function — no I/O side effects beyond reading the filesystem.
|
|
84
|
+
*
|
|
85
|
+
* @param maxAgeMs - Maximum age in milliseconds (default: 7 days)
|
|
86
|
+
* @returns Info about stale entries, or null if none found.
|
|
87
|
+
*/
|
|
88
|
+
export function getStaleStagingInfo(maxAgeMs = DEFAULT_MAX_AGE_MS) {
|
|
89
|
+
const entries = listStaged();
|
|
90
|
+
if (entries.length === 0)
|
|
91
|
+
return null;
|
|
92
|
+
const cutoff = Date.now() - maxAgeMs;
|
|
93
|
+
const staleEntries = entries.filter((entry) => {
|
|
94
|
+
try {
|
|
95
|
+
const stat = statSync(entry.path);
|
|
96
|
+
return stat.mtimeMs < cutoff;
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
if (staleEntries.length === 0)
|
|
103
|
+
return null;
|
|
104
|
+
const totalBytes = staleEntries.reduce((sum, e) => sum + e.size, 0);
|
|
105
|
+
return {
|
|
106
|
+
staleEntries,
|
|
107
|
+
totalBytes,
|
|
108
|
+
totalSize: formatSize(totalBytes),
|
|
109
|
+
count: staleEntries.length,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Purge stale staging entries. Returns the number of entries removed.
|
|
114
|
+
*
|
|
115
|
+
* @param entries - Entries to purge (from getStaleStagingInfo().staleEntries)
|
|
116
|
+
* @returns Number of entries successfully removed.
|
|
117
|
+
*/
|
|
118
|
+
export function purgeStagingEntries(entries) {
|
|
119
|
+
let removed = 0;
|
|
120
|
+
for (const entry of entries) {
|
|
121
|
+
try {
|
|
122
|
+
rmSync(entry.path, { recursive: true, force: true });
|
|
123
|
+
removed++;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Skip failures silently — entry may have been removed concurrently
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return removed;
|
|
130
|
+
}
|
|
79
131
|
export function registerStaging(program) {
|
|
80
132
|
const staging = program.command('staging').description('Manage anti-deletion staging folder');
|
|
81
133
|
staging
|
|
@@ -135,41 +187,79 @@ export function registerStaging(program) {
|
|
|
135
187
|
log.info(`Restored ${restored}/${files.length} file(s) from snapshot "${id}"`);
|
|
136
188
|
});
|
|
137
189
|
staging
|
|
138
|
-
.command('
|
|
139
|
-
.option('--older-than <duration>', 'Only
|
|
140
|
-
.
|
|
190
|
+
.command('clean')
|
|
191
|
+
.option('--older-than <duration>', 'Only remove snapshots older than duration (default: 7d)', '7d')
|
|
192
|
+
.option('--all', 'Remove all snapshots regardless of age')
|
|
193
|
+
.option('--dry-run', 'Show what would be removed without deleting')
|
|
194
|
+
.description('Remove staging backups older than 7 days (or --all)')
|
|
141
195
|
.action((opts) => {
|
|
142
196
|
if (!existsSync(STAGING_ROOT)) {
|
|
143
|
-
log.info('No staging directory found. Nothing to
|
|
197
|
+
log.info('No staging directory found. Nothing to clean.');
|
|
144
198
|
return;
|
|
145
199
|
}
|
|
146
200
|
const entries = listStaged();
|
|
147
201
|
if (entries.length === 0) {
|
|
148
|
-
log.info('No staged files to
|
|
202
|
+
log.info('No staged files to clean.');
|
|
149
203
|
return;
|
|
150
204
|
}
|
|
151
|
-
let
|
|
152
|
-
if (opts.
|
|
205
|
+
let toClean = entries;
|
|
206
|
+
if (!opts.all) {
|
|
153
207
|
const maxAge = parseDuration(opts.olderThan);
|
|
154
208
|
if (!maxAge) {
|
|
155
209
|
log.fail(`Invalid duration: "${opts.olderThan}". Use format like 7d, 24h, 30m`);
|
|
156
210
|
process.exit(1);
|
|
157
211
|
}
|
|
158
212
|
const cutoff = Date.now() - maxAge;
|
|
159
|
-
|
|
213
|
+
toClean = entries.filter((entry) => {
|
|
160
214
|
const stat = statSync(entry.path);
|
|
161
215
|
return stat.mtimeMs < cutoff;
|
|
162
216
|
});
|
|
163
217
|
}
|
|
164
|
-
if (
|
|
165
|
-
log.info('No snapshots match the
|
|
218
|
+
if (toClean.length === 0) {
|
|
219
|
+
log.info('No snapshots match the clean criteria.');
|
|
220
|
+
return;
|
|
221
|
+
}
|
|
222
|
+
if (opts.dryRun) {
|
|
223
|
+
log.heading('Dry run — would remove:');
|
|
224
|
+
for (const entry of toClean) {
|
|
225
|
+
log.warn(`${entry.id}`, formatSize(entry.size));
|
|
226
|
+
}
|
|
227
|
+
log.info(`Would remove ${toClean.length} staging snapshot(s)`);
|
|
166
228
|
return;
|
|
167
229
|
}
|
|
168
|
-
for (const entry of
|
|
230
|
+
for (const entry of toClean) {
|
|
169
231
|
rmSync(entry.path, { recursive: true, force: true });
|
|
170
|
-
log.warn(`
|
|
232
|
+
log.warn(`Removed ${entry.id}`);
|
|
233
|
+
}
|
|
234
|
+
log.info(`Removed ${toClean.length} staging snapshot(s)`);
|
|
235
|
+
});
|
|
236
|
+
staging
|
|
237
|
+
.command('cleanup')
|
|
238
|
+
.option('--older-than <duration>', 'Max age for stale entries (default: 7d)', '7d')
|
|
239
|
+
.option('--yes', 'Skip confirmation prompt')
|
|
240
|
+
.description('Check for and remove stale staging backups (default: older than 7 days)')
|
|
241
|
+
.action((opts) => {
|
|
242
|
+
const maxAge = parseDuration(opts.olderThan);
|
|
243
|
+
if (!maxAge) {
|
|
244
|
+
log.fail(`Invalid duration: "${opts.olderThan}". Use format like 7d, 24h, 30m`);
|
|
245
|
+
process.exit(1);
|
|
246
|
+
}
|
|
247
|
+
const info = getStaleStagingInfo(maxAge);
|
|
248
|
+
if (!info) {
|
|
249
|
+
log.info('No stale staging backups found.');
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
log.heading('Stale Staging Backups');
|
|
253
|
+
log.info(`Found ${info.count} staging backup(s) older than ${opts.olderThan} (${info.totalSize}).`);
|
|
254
|
+
for (const entry of info.staleEntries) {
|
|
255
|
+
log.dim(` ${entry.id} ${formatSize(entry.size)}`);
|
|
256
|
+
}
|
|
257
|
+
if (!opts.yes) {
|
|
258
|
+
log.info(`Run with --yes to remove, or use: soleri staging purge --older-than ${opts.olderThan}`);
|
|
259
|
+
return;
|
|
171
260
|
}
|
|
172
|
-
|
|
261
|
+
const removed = purgeStagingEntries(info.staleEntries);
|
|
262
|
+
log.pass(`Cleaned up ${removed} stale staging backup(s), freed ${info.totalSize}.`);
|
|
173
263
|
});
|
|
174
264
|
}
|
|
175
265
|
//# sourceMappingURL=staging.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"staging.js","sourceRoot":"","sources":["../../src/commands/staging.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACvF,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,KAAK,GAAG,MAAM,oBAAoB,CAAC;AAE1C,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"staging.js","sourceRoot":"","sources":["../../src/commands/staging.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { isPackInstalled, installPack } from '../hook-packs/installer.js';
|
|
3
|
+
import { getPack } from '../hook-packs/registry.js';
|
|
4
|
+
import * as log from '../utils/logger.js';
|
|
5
|
+
const YOLO_PACK = 'yolo-safety';
|
|
6
|
+
const RESET = '\x1b[0m';
|
|
7
|
+
const BOLD = '\x1b[1m';
|
|
8
|
+
const RED = '\x1b[31m';
|
|
9
|
+
const YELLOW = '\x1b[33m';
|
|
10
|
+
export function registerYolo(program) {
|
|
11
|
+
program
|
|
12
|
+
.command('yolo')
|
|
13
|
+
.description('Launch Claude Code in YOLO mode with safety guardrails')
|
|
14
|
+
.option('--dry-run', 'Show what would happen without launching Claude')
|
|
15
|
+
.option('--project', 'Install safety hooks to project .claude/ instead of global ~/.claude/')
|
|
16
|
+
.action((opts) => {
|
|
17
|
+
runYolo(opts);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function runYolo(opts) {
|
|
21
|
+
// 1. Verify the yolo-safety pack exists in registry
|
|
22
|
+
const pack = getPack(YOLO_PACK);
|
|
23
|
+
if (!pack) {
|
|
24
|
+
log.fail(`Hook pack "${YOLO_PACK}" not found in registry. Is @soleri/cli up to date?`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
// 2. Check if already installed, install if not
|
|
28
|
+
const projectDir = opts.project ? process.cwd() : undefined;
|
|
29
|
+
const installed = isPackInstalled(YOLO_PACK, { projectDir });
|
|
30
|
+
if (installed === true) {
|
|
31
|
+
log.pass(`${YOLO_PACK} hook pack already installed`);
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
if (installed === 'partial') {
|
|
35
|
+
log.warn(`${YOLO_PACK} hook pack partially installed — reinstalling`);
|
|
36
|
+
}
|
|
37
|
+
const result = installPack(YOLO_PACK, { projectDir });
|
|
38
|
+
const target = opts.project ? '.claude/' : '~/.claude/';
|
|
39
|
+
for (const script of result.scripts) {
|
|
40
|
+
log.pass(`Installed ${script} → ${target}`);
|
|
41
|
+
}
|
|
42
|
+
for (const lc of result.lifecycleHooks) {
|
|
43
|
+
log.pass(`Registered lifecycle hook: ${lc}`);
|
|
44
|
+
}
|
|
45
|
+
const totalInstalled = result.installed.length + result.scripts.length + result.lifecycleHooks.length;
|
|
46
|
+
if (totalInstalled > 0) {
|
|
47
|
+
log.pass(`${YOLO_PACK} hook pack installed (${totalInstalled} items)`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// 3. Print safety warning
|
|
51
|
+
console.log();
|
|
52
|
+
console.log(` ${RED}${BOLD}⚡ YOLO MODE${RESET}`);
|
|
53
|
+
console.log();
|
|
54
|
+
console.log(` ${YELLOW}Approval gates skipped — Claude will execute commands without asking.${RESET}`);
|
|
55
|
+
console.log(` ${YELLOW}Safety hooks active — destructive commands (rm, git push --force,${RESET}`);
|
|
56
|
+
console.log(` ${YELLOW}git reset --hard, drop table, docker rm) are intercepted.${RESET}`);
|
|
57
|
+
console.log();
|
|
58
|
+
if (opts.dryRun) {
|
|
59
|
+
log.info('Dry run — would launch:');
|
|
60
|
+
log.dim(' claude --dangerously-skip-permissions');
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
// 4. Launch Claude Code with permissions skipped
|
|
64
|
+
log.info('Launching Claude Code in YOLO mode...');
|
|
65
|
+
console.log();
|
|
66
|
+
const child = spawn('claude', ['--dangerously-skip-permissions'], {
|
|
67
|
+
stdio: 'inherit',
|
|
68
|
+
env: { ...process.env },
|
|
69
|
+
});
|
|
70
|
+
child.on('error', (err) => {
|
|
71
|
+
if (err.code === 'ENOENT') {
|
|
72
|
+
log.fail('Claude CLI not found. Install it first: https://docs.anthropic.com/en/docs/claude-code');
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
log.fail(`Failed to launch Claude: ${err.message}`);
|
|
76
|
+
}
|
|
77
|
+
process.exit(1);
|
|
78
|
+
});
|
|
79
|
+
child.on('exit', (code, signal) => {
|
|
80
|
+
if (signal) {
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
process.exit(code ?? 0);
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=yolo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yolo.js","sourceRoot":"","sources":["../../src/commands/yolo.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yolo-safety",
|
|
3
3
|
"version": "1.0.0",
|
|
4
|
-
"description": "
|
|
4
|
+
"description": "Safety guardrails for YOLO mode — intercepts destructive commands (rm, git push --force, git reset --hard, git clean, drop table, docker rm), stages files before deletion, blocks everything else",
|
|
5
5
|
"hooks": [],
|
|
6
6
|
"scripts": [
|
|
7
7
|
{
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"event": "PreToolUse",
|
|
16
16
|
"matcher": "Bash",
|
|
17
17
|
"type": "command",
|
|
18
|
-
"command": "
|
|
18
|
+
"command": "sh ~/.claude/hooks/anti-deletion.sh",
|
|
19
19
|
"timeout": 10,
|
|
20
20
|
"statusMessage": "Checking for destructive commands..."
|
|
21
21
|
}
|