argos-harness 0.1.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/LICENSE +21 -0
- package/README.md +21 -0
- package/assets/agents/auditor.md +140 -0
- package/assets/agents/commit-pr-pilot.md +154 -0
- package/assets/agents/explorer.md +93 -0
- package/assets/agents/implementer.md +117 -0
- package/assets/agents/leader.md +149 -0
- package/assets/agents/researcher.md +89 -0
- package/assets/agents/review-readability.md +87 -0
- package/assets/agents/review-reliability.md +100 -0
- package/assets/agents/review-resilience.md +87 -0
- package/assets/agents/review-risk.md +87 -0
- package/assets/agents/reviewer.md +167 -0
- package/assets/agents/ticket-audit.md +129 -0
- package/assets/hooks/argos-guard-destructive.sh +127 -0
- package/assets/hooks/argos-quality-gate.sh +129 -0
- package/assets/managed/aterrizaje.md +24 -0
- package/assets/managed/formato-respuesta.md +21 -0
- package/assets/managed/identidad.md +48 -0
- package/assets/managed/operaciones-seguras.md +14 -0
- package/assets/managed/orquestacion.md +169 -0
- package/assets/output-styles/argos.md +71 -0
- package/assets/skills/ai-sdk-5/SKILL.md +230 -0
- package/assets/skills/angular/SKILL.md +19 -0
- package/assets/skills/angular/references/architecture.md +137 -0
- package/assets/skills/angular/references/core.md +197 -0
- package/assets/skills/angular/references/forms.md +115 -0
- package/assets/skills/angular/references/performance.md +124 -0
- package/assets/skills/apollo-client/SKILL.md +61 -0
- package/assets/skills/app-blueprint/SKILL.md +45 -0
- package/assets/skills/app-blueprint/assets/module-template.md +48 -0
- package/assets/skills/app-blueprint/assets/system-template.md +38 -0
- package/assets/skills/app-blueprint/references/workflow.md +101 -0
- package/assets/skills/app-builder/SKILL.md +43 -0
- package/assets/skills/app-builder/phases/0-product.md +58 -0
- package/assets/skills/app-builder/phases/1-scaffold.md +33 -0
- package/assets/skills/app-builder/phases/10-store.md +40 -0
- package/assets/skills/app-builder/phases/2-data.md +34 -0
- package/assets/skills/app-builder/phases/3-domain.md +33 -0
- package/assets/skills/app-builder/phases/4-ui-nav.md +32 -0
- package/assets/skills/app-builder/phases/5-identity.md +30 -0
- package/assets/skills/app-builder/phases/6-polish.md +34 -0
- package/assets/skills/app-builder/phases/7-brand.md +31 -0
- package/assets/skills/app-builder/phases/8-web.md +30 -0
- package/assets/skills/app-builder/phases/9-docs.md +31 -0
- package/assets/skills/app-ia/SKILL.md +54 -0
- package/assets/skills/astro/SKILL.md +39 -0
- package/assets/skills/axios/SKILL.md +61 -0
- package/assets/skills/branch-pr/SKILL.md +200 -0
- package/assets/skills/bullmq/SKILL.md +55 -0
- package/assets/skills/chained-pr/SKILL.md +48 -0
- package/assets/skills/chained-pr/references/chaining-details.md +99 -0
- package/assets/skills/cognitive-doc-design/SKILL.md +81 -0
- package/assets/skills/comment-writer/SKILL.md +74 -0
- package/assets/skills/dashboard-ia/SKILL.md +54 -0
- package/assets/skills/django-drf/SKILL.md +180 -0
- package/assets/skills/go-testing/SKILL.md +47 -0
- package/assets/skills/go-testing/references/examples.md +89 -0
- package/assets/skills/issue-creation/SKILL.md +223 -0
- package/assets/skills/jira-epic/SKILL.md +306 -0
- package/assets/skills/jira-task/SKILL.md +382 -0
- package/assets/skills/judgment-day/SKILL.md +52 -0
- package/assets/skills/judgment-day/references/prompts-and-formats.md +98 -0
- package/assets/skills/lightsail-deploy/SKILL.md +44 -0
- package/assets/skills/lightsail-deploy/references/runbook.md +102 -0
- package/assets/skills/loop-back-debug/SKILL.md +102 -0
- package/assets/skills/mantine-form/SKILL.md +57 -0
- package/assets/skills/mongoose/SKILL.md +66 -0
- package/assets/skills/nextjs-15/SKILL.md +144 -0
- package/assets/skills/not-boring-mobile/SKILL.md +43 -0
- package/assets/skills/not-boring-mobile/references/not-boring-playbook.md +65 -0
- package/assets/skills/playwright/SKILL.md +315 -0
- package/assets/skills/pr-comments/SKILL.md +93 -0
- package/assets/skills/pr-create/SKILL.md +64 -0
- package/assets/skills/promo-video/SKILL.md +52 -0
- package/assets/skills/promo-video/assets/package.template.json +22 -0
- package/assets/skills/promo-video/assets/promo.template.tsx +469 -0
- package/assets/skills/promo-video/assets/theme.template.ts +27 -0
- package/assets/skills/promo-video/references/pipeline.md +119 -0
- package/assets/skills/promo-video-web/SKILL.md +51 -0
- package/assets/skills/promo-video-web/assets/browser-promo.template.tsx +385 -0
- package/assets/skills/promo-video-web/assets/capture.template.ts +70 -0
- package/assets/skills/promo-video-web/assets/package.template.json +26 -0
- package/assets/skills/promo-video-web/references/pipeline.md +84 -0
- package/assets/skills/pytest/SKILL.md +180 -0
- package/assets/skills/react-19/SKILL.md +118 -0
- package/assets/skills/react-hook-form/SKILL.md +59 -0
- package/assets/skills/react-router/SKILL.md +60 -0
- package/assets/skills/redux-toolkit/SKILL.md +60 -0
- package/assets/skills/review-diff/SKILL.md +101 -0
- package/assets/skills/ship-docs/SKILL.md +45 -0
- package/assets/skills/ship-docs/references/ship-docs-playbook.md +31 -0
- package/assets/skills/skill-creator/SKILL.md +97 -0
- package/assets/skills/skill-creator/assets/SKILL-TEMPLATE.md +68 -0
- package/assets/skills/skill-creator/references/skill-style-guide.md +79 -0
- package/assets/skills/skill-improver/SKILL.md +50 -0
- package/assets/skills/skill-improver/references/skill-style-guide.md +79 -0
- package/assets/skills/socketio/SKILL.md +58 -0
- package/assets/skills/spec-bootstrap/SKILL.md +62 -0
- package/assets/skills/store-ship/SKILL.md +52 -0
- package/assets/skills/store-ship/assets/android-supply.template.md +22 -0
- package/assets/skills/store-ship/assets/eas.template.json +32 -0
- package/assets/skills/store-ship/assets/maestro-flow.template.yaml +27 -0
- package/assets/skills/store-ship/assets/store.config.template.json +28 -0
- package/assets/skills/store-ship/references/pipeline.md +198 -0
- package/assets/skills/stripe/SKILL.md +83 -0
- package/assets/skills/tailwind-4/SKILL.md +193 -0
- package/assets/skills/tamagui/SKILL.md +60 -0
- package/assets/skills/tanstack-query/SKILL.md +58 -0
- package/assets/skills/ticket-intake/SKILL.md +55 -0
- package/assets/skills/typescript/SKILL.md +134 -0
- package/assets/skills/verify-before-done/SKILL.md +111 -0
- package/assets/skills/webapp-rebuilder/SKILL.md +48 -0
- package/assets/skills/webapp-rebuilder/assets/charter-template.md +46 -0
- package/assets/skills/webapp-rebuilder/references/workflow.md +47 -0
- package/assets/skills/winston-logging/SKILL.md +61 -0
- package/assets/skills/work-unit-commits/SKILL.md +84 -0
- package/assets/skills/zod-4/SKILL.md +210 -0
- package/assets/skills/zustand-5/SKILL.md +216 -0
- package/bin/argos.js +6 -0
- package/dist/commands/adopt.d.ts +35 -0
- package/dist/commands/adopt.d.ts.map +1 -0
- package/dist/commands/adopt.js +347 -0
- package/dist/commands/adopt.js.map +1 -0
- package/dist/commands/doctor.d.ts +20 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +478 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/init.d.ts +32 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +358 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/remove.d.ts +62 -0
- package/dist/commands/remove.d.ts.map +1 -0
- package/dist/commands/remove.js +487 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/workspace.d.ts +73 -0
- package/dist/commands/workspace.d.ts.map +1 -0
- package/dist/commands/workspace.js +354 -0
- package/dist/commands/workspace.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/assets.d.ts +29 -0
- package/dist/lib/assets.d.ts.map +1 -0
- package/dist/lib/assets.js +57 -0
- package/dist/lib/assets.js.map +1 -0
- package/dist/lib/atomic-write.d.ts +17 -0
- package/dist/lib/atomic-write.d.ts.map +1 -0
- package/dist/lib/atomic-write.js +41 -0
- package/dist/lib/atomic-write.js.map +1 -0
- package/dist/lib/backup.d.ts +11 -0
- package/dist/lib/backup.d.ts.map +1 -0
- package/dist/lib/backup.js +42 -0
- package/dist/lib/backup.js.map +1 -0
- package/dist/lib/config.d.ts +36 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +52 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/detect.d.ts +58 -0
- package/dist/lib/detect.d.ts.map +1 -0
- package/dist/lib/detect.js +330 -0
- package/dist/lib/detect.js.map +1 -0
- package/dist/lib/ficha.d.ts +10 -0
- package/dist/lib/ficha.d.ts.map +1 -0
- package/dist/lib/ficha.js +38 -0
- package/dist/lib/ficha.js.map +1 -0
- package/dist/lib/git.d.ts +27 -0
- package/dist/lib/git.d.ts.map +1 -0
- package/dist/lib/git.js +79 -0
- package/dist/lib/git.js.map +1 -0
- package/dist/lib/managed-files.d.ts +35 -0
- package/dist/lib/managed-files.d.ts.map +1 -0
- package/dist/lib/managed-files.js +97 -0
- package/dist/lib/managed-files.js.map +1 -0
- package/dist/lib/markers.d.ts +64 -0
- package/dist/lib/markers.d.ts.map +1 -0
- package/dist/lib/markers.js +157 -0
- package/dist/lib/markers.js.map +1 -0
- package/dist/lib/navori-import.d.ts +42 -0
- package/dist/lib/navori-import.d.ts.map +1 -0
- package/dist/lib/navori-import.js +65 -0
- package/dist/lib/navori-import.js.map +1 -0
- package/dist/lib/openclaw-agents.d.ts +53 -0
- package/dist/lib/openclaw-agents.d.ts.map +1 -0
- package/dist/lib/openclaw-agents.js +118 -0
- package/dist/lib/openclaw-agents.js.map +1 -0
- package/dist/lib/package-root.d.ts +11 -0
- package/dist/lib/package-root.d.ts.map +1 -0
- package/dist/lib/package-root.js +23 -0
- package/dist/lib/package-root.js.map +1 -0
- package/dist/lib/paths.d.ts +11 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/paths.js +16 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/settings-merge.d.ts +125 -0
- package/dist/lib/settings-merge.d.ts.map +1 -0
- package/dist/lib/settings-merge.js +373 -0
- package/dist/lib/settings-merge.js.map +1 -0
- package/dist/lib/version.d.ts +3 -0
- package/dist/lib/version.d.ts.map +1 -0
- package/dist/lib/version.js +13 -0
- package/dist/lib/version.js.map +1 -0
- package/dist/lib/which.d.ts +8 -0
- package/dist/lib/which.d.ts.map +1 -0
- package/dist/lib/which.js +30 -0
- package/dist/lib/which.js.map +1 -0
- package/dist/lib/workspaces.d.ts +133 -0
- package/dist/lib/workspaces.d.ts.map +1 -0
- package/dist/lib/workspaces.js +241 -0
- package/dist/lib/workspaces.js.map +1 -0
- package/dist/lib/zod-messages.d.ts +4 -0
- package/dist/lib/zod-messages.d.ts.map +1 -0
- package/dist/lib/zod-messages.js +28 -0
- package/dist/lib/zod-messages.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,487 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
import { existsSync, readdirSync, readFileSync, rmSync, rmdirSync } from "node:fs";
|
|
3
|
+
import { join, relative, sep } from "node:path";
|
|
4
|
+
import pc from "picocolors";
|
|
5
|
+
import { listSkillFiles, listSkillIds, MANAGED_BLOCK_IDS, resolveAssetsDir } from "../lib/assets.js";
|
|
6
|
+
import { writeFileAtomic } from "../lib/atomic-write.js";
|
|
7
|
+
import { createBackup } from "../lib/backup.js";
|
|
8
|
+
import { listBlocks, removeBlock } from "../lib/markers.js";
|
|
9
|
+
import { hasArgosFileMarker, hasArgosShellFileMarker } from "../lib/managed-files.js";
|
|
10
|
+
import { resolveArgosHome, resolveClaudeDir } from "../lib/paths.js";
|
|
11
|
+
import { removeAllArgosHooksFromSettings } from "../lib/settings-merge.js";
|
|
12
|
+
const STATUS_COUNT_ORDER = [
|
|
13
|
+
"removed",
|
|
14
|
+
"would-remove",
|
|
15
|
+
"skipped-foreign",
|
|
16
|
+
"info",
|
|
17
|
+
"warning",
|
|
18
|
+
"error"
|
|
19
|
+
];
|
|
20
|
+
function summarize(rows, apply) {
|
|
21
|
+
const counts = {
|
|
22
|
+
removed: 0,
|
|
23
|
+
"would-remove": 0,
|
|
24
|
+
"skipped-foreign": 0,
|
|
25
|
+
info: 0,
|
|
26
|
+
warning: 0,
|
|
27
|
+
error: 0
|
|
28
|
+
};
|
|
29
|
+
for (const row of rows)counts[row.status]++;
|
|
30
|
+
const parts = STATUS_COUNT_ORDER.filter((s)=>counts[s] > 0).map((s)=>`${counts[s]} ${s}`);
|
|
31
|
+
const verb = apply ? "argos remove" : "argos remove (preview — nada se tocó)";
|
|
32
|
+
return parts.length === 0 ? `${verb}: nada que hacer.` : `${verb}: ${parts.join(", ")}.`;
|
|
33
|
+
}
|
|
34
|
+
function errorMessage(err) {
|
|
35
|
+
return err instanceof Error ? err.message : String(err);
|
|
36
|
+
}
|
|
37
|
+
/** Strip every present managed block from CLAUDE.md; delete the file entirely if it becomes empty. */ function processClaudeMd(claudeDir, apply, rows) {
|
|
38
|
+
const claudeMdPath = join(claudeDir, "CLAUDE.md");
|
|
39
|
+
if (!existsSync(claudeMdPath)) return;
|
|
40
|
+
let claudeMd;
|
|
41
|
+
try {
|
|
42
|
+
claudeMd = readFileSync(claudeMdPath, "utf-8");
|
|
43
|
+
} catch (err) {
|
|
44
|
+
rows.push({
|
|
45
|
+
path: "CLAUDE.md",
|
|
46
|
+
category: "claude-md-block",
|
|
47
|
+
status: "error",
|
|
48
|
+
detail: errorMessage(err)
|
|
49
|
+
});
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
let next = claudeMd;
|
|
53
|
+
const removedIds = [];
|
|
54
|
+
for (const id of MANAGED_BLOCK_IDS){
|
|
55
|
+
const hadBlock = listBlocks(next).some((b)=>b.id === id);
|
|
56
|
+
if (!hadBlock) continue;
|
|
57
|
+
const beforeThisId = next;
|
|
58
|
+
// removeBlock only strips the first occurrence — loop to self-heal any
|
|
59
|
+
// crash-residue duplicates left by injectBlock (see lib/markers.ts).
|
|
60
|
+
// Progress-guarded: a dangling open marker with no matching close (see
|
|
61
|
+
// lib/markers.ts's findBlock/listDanglingBlockIds) makes removeBlock a
|
|
62
|
+
// no-op — its output equals its input — which would otherwise spin this
|
|
63
|
+
// loop forever since listBlocks still reports the id as present. Break
|
|
64
|
+
// and surface it as a warning instead of hanging.
|
|
65
|
+
while(listBlocks(next).some((b)=>b.id === id)){
|
|
66
|
+
const before = next;
|
|
67
|
+
next = removeBlock(next, id);
|
|
68
|
+
if (next === before) {
|
|
69
|
+
rows.push({
|
|
70
|
+
path: "CLAUDE.md",
|
|
71
|
+
category: "claude-md-block",
|
|
72
|
+
status: "warning",
|
|
73
|
+
detail: "marker argos huérfano sin cierre en CLAUDE.md — remuévelo a mano"
|
|
74
|
+
});
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (next !== beforeThisId) removedIds.push(id);
|
|
79
|
+
}
|
|
80
|
+
if (removedIds.length === 0) return;
|
|
81
|
+
for (const id of removedIds){
|
|
82
|
+
rows.push({
|
|
83
|
+
path: `CLAUDE.md#${id}`,
|
|
84
|
+
category: "claude-md-block",
|
|
85
|
+
status: apply ? "removed" : "would-remove"
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (!apply) return;
|
|
89
|
+
try {
|
|
90
|
+
if (next.trim().length === 0) {
|
|
91
|
+
rmSync(claudeMdPath, {
|
|
92
|
+
force: true
|
|
93
|
+
});
|
|
94
|
+
} else {
|
|
95
|
+
writeFileAtomic(claudeMdPath, next);
|
|
96
|
+
}
|
|
97
|
+
} catch (err) {
|
|
98
|
+
rows.push({
|
|
99
|
+
path: "CLAUDE.md",
|
|
100
|
+
category: "claude-md-block",
|
|
101
|
+
status: "error",
|
|
102
|
+
detail: errorMessage(err)
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function walkFiles(dir) {
|
|
107
|
+
if (!existsSync(dir)) return [];
|
|
108
|
+
const out = [];
|
|
109
|
+
for (const entry of readdirSync(dir, {
|
|
110
|
+
withFileTypes: true
|
|
111
|
+
})){
|
|
112
|
+
const full = join(dir, entry.name);
|
|
113
|
+
if (entry.isDirectory()) out.push(...walkFiles(full));
|
|
114
|
+
else if (entry.isFile()) out.push(full);
|
|
115
|
+
}
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
118
|
+
/** Remove now-empty directories bottom-up under `dir`, leaving any dir that still holds foreign content. */ function removeEmptyDirsUnder(dir) {
|
|
119
|
+
if (!existsSync(dir)) return;
|
|
120
|
+
for (const entry of readdirSync(dir, {
|
|
121
|
+
withFileTypes: true
|
|
122
|
+
})){
|
|
123
|
+
if (entry.isDirectory()) removeEmptyDirsUnder(join(dir, entry.name));
|
|
124
|
+
}
|
|
125
|
+
const remaining = existsSync(dir) ? readdirSync(dir) : [];
|
|
126
|
+
if (remaining.length === 0) {
|
|
127
|
+
try {
|
|
128
|
+
rmdirSync(dir);
|
|
129
|
+
} catch {
|
|
130
|
+
// Best-effort cleanup — a leftover empty dir is cosmetic, not an error.
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Remove every Argos-owned file (carrying the ownership marker) under
|
|
136
|
+
* `claudeDir/<topDir>`, recursively — skills live in subdirectories, hence
|
|
137
|
+
* the recursive walk. Foreign files (no marker) are reported
|
|
138
|
+
* "skipped-foreign" and left byte-identical.
|
|
139
|
+
*/ function processManagedDir(claudeDir, topDir, category, hasMarker, apply, rows) {
|
|
140
|
+
const dirPath = join(claudeDir, topDir);
|
|
141
|
+
const files = walkFiles(dirPath);
|
|
142
|
+
for (const file of files){
|
|
143
|
+
const relPath = relative(claudeDir, file);
|
|
144
|
+
let content;
|
|
145
|
+
try {
|
|
146
|
+
content = readFileSync(file, "utf-8");
|
|
147
|
+
} catch (err) {
|
|
148
|
+
rows.push({
|
|
149
|
+
path: relPath,
|
|
150
|
+
category,
|
|
151
|
+
status: "error",
|
|
152
|
+
detail: errorMessage(err)
|
|
153
|
+
});
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
if (!hasMarker(content)) {
|
|
157
|
+
rows.push({
|
|
158
|
+
path: relPath,
|
|
159
|
+
category,
|
|
160
|
+
status: "skipped-foreign"
|
|
161
|
+
});
|
|
162
|
+
continue;
|
|
163
|
+
}
|
|
164
|
+
if (!apply) {
|
|
165
|
+
rows.push({
|
|
166
|
+
path: relPath,
|
|
167
|
+
category,
|
|
168
|
+
status: "would-remove"
|
|
169
|
+
});
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
try {
|
|
173
|
+
rmSync(file, {
|
|
174
|
+
force: true
|
|
175
|
+
});
|
|
176
|
+
rows.push({
|
|
177
|
+
path: relPath,
|
|
178
|
+
category,
|
|
179
|
+
status: "removed"
|
|
180
|
+
});
|
|
181
|
+
} catch (err) {
|
|
182
|
+
rows.push({
|
|
183
|
+
path: relPath,
|
|
184
|
+
category,
|
|
185
|
+
status: "error",
|
|
186
|
+
detail: errorMessage(err)
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
if (apply) removeEmptyDirsUnder(dirPath);
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Remove Argos-owned skill directories under `claudeDir/skills/`.
|
|
194
|
+
*
|
|
195
|
+
* Unlike `processManagedDir` (per-file marker check), ownership here is
|
|
196
|
+
* decided PER SKILL DIRECTORY: the skill's `SKILL.md` `argos:file` marker is
|
|
197
|
+
* the sentinel (mirrors the install policy in commands/init.ts). Supporting
|
|
198
|
+
* files (`references/*.md`, `phases/*.md`, etc.) never carry a marker of
|
|
199
|
+
* their own, so a per-file marker check would wrongly treat every one of
|
|
200
|
+
* them as foreign.
|
|
201
|
+
* - `SKILL.md` missing, or present without the marker → the whole directory
|
|
202
|
+
* is foreign (or not argos-installed at all); every file under it is left
|
|
203
|
+
* untouched, reported "skipped-foreign".
|
|
204
|
+
* - `SKILL.md` present with the marker → argos-owned. Only the files the
|
|
205
|
+
* CURRENTLY shipped asset manifest lists for that skill id
|
|
206
|
+
* (`listSkillFiles`) are removed; anything else in the directory — a
|
|
207
|
+
* user-added extra file, or every file if this CLI version no longer
|
|
208
|
+
* ships the skill at all — is left in place.
|
|
209
|
+
*/ function processSkillsDir(claudeDir, apply, rows) {
|
|
210
|
+
const skillsRoot = join(claudeDir, "skills");
|
|
211
|
+
if (!existsSync(skillsRoot)) return;
|
|
212
|
+
const assetsDir = resolveAssetsDir();
|
|
213
|
+
const shippedSkillIds = new Set(listSkillIds(assetsDir));
|
|
214
|
+
for (const entry of readdirSync(skillsRoot, {
|
|
215
|
+
withFileTypes: true
|
|
216
|
+
})){
|
|
217
|
+
if (!entry.isDirectory()) continue; // skills/ only ever holds skill subdirectories
|
|
218
|
+
const skillId = entry.name;
|
|
219
|
+
const skillDir = join(skillsRoot, skillId);
|
|
220
|
+
const skillMdPath = join(skillDir, "SKILL.md");
|
|
221
|
+
let skillMdContent = null;
|
|
222
|
+
if (existsSync(skillMdPath)) {
|
|
223
|
+
try {
|
|
224
|
+
skillMdContent = readFileSync(skillMdPath, "utf-8");
|
|
225
|
+
} catch (err) {
|
|
226
|
+
rows.push({
|
|
227
|
+
path: relative(claudeDir, skillMdPath),
|
|
228
|
+
category: "skills-file",
|
|
229
|
+
status: "error",
|
|
230
|
+
detail: errorMessage(err)
|
|
231
|
+
});
|
|
232
|
+
continue;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
const isArgosOwned = skillMdContent !== null && hasArgosFileMarker(skillMdContent);
|
|
236
|
+
const manifest = isArgosOwned && shippedSkillIds.has(skillId) ? new Set(listSkillFiles(assetsDir, skillId)) : new Set();
|
|
237
|
+
for (const file of walkFiles(skillDir)){
|
|
238
|
+
const relToClaudeDir = relative(claudeDir, file);
|
|
239
|
+
if (!isArgosOwned || !manifest.has(relative(skillDir, file).split(sep).join("/"))) {
|
|
240
|
+
rows.push({
|
|
241
|
+
path: relToClaudeDir,
|
|
242
|
+
category: "skills-file",
|
|
243
|
+
status: "skipped-foreign"
|
|
244
|
+
});
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (!apply) {
|
|
248
|
+
rows.push({
|
|
249
|
+
path: relToClaudeDir,
|
|
250
|
+
category: "skills-file",
|
|
251
|
+
status: "would-remove"
|
|
252
|
+
});
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
rmSync(file, {
|
|
257
|
+
force: true
|
|
258
|
+
});
|
|
259
|
+
rows.push({
|
|
260
|
+
path: relToClaudeDir,
|
|
261
|
+
category: "skills-file",
|
|
262
|
+
status: "removed"
|
|
263
|
+
});
|
|
264
|
+
} catch (err) {
|
|
265
|
+
rows.push({
|
|
266
|
+
path: relToClaudeDir,
|
|
267
|
+
category: "skills-file",
|
|
268
|
+
status: "error",
|
|
269
|
+
detail: errorMessage(err)
|
|
270
|
+
});
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
if (apply) removeEmptyDirsUnder(skillsRoot);
|
|
275
|
+
}
|
|
276
|
+
const PURGE_FILES = [
|
|
277
|
+
"global.json",
|
|
278
|
+
"workspaces.json"
|
|
279
|
+
];
|
|
280
|
+
function processPurge(apply, rows, warnings) {
|
|
281
|
+
const argosHome = resolveArgosHome();
|
|
282
|
+
for (const name of PURGE_FILES){
|
|
283
|
+
const p = join(argosHome, name);
|
|
284
|
+
if (!existsSync(p)) continue;
|
|
285
|
+
const label = join("~", ".argos", name);
|
|
286
|
+
if (!apply) {
|
|
287
|
+
rows.push({
|
|
288
|
+
path: label,
|
|
289
|
+
category: "argos-home",
|
|
290
|
+
status: "would-remove"
|
|
291
|
+
});
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
try {
|
|
295
|
+
rmSync(p, {
|
|
296
|
+
force: true
|
|
297
|
+
});
|
|
298
|
+
rows.push({
|
|
299
|
+
path: label,
|
|
300
|
+
category: "argos-home",
|
|
301
|
+
status: "removed"
|
|
302
|
+
});
|
|
303
|
+
} catch (err) {
|
|
304
|
+
rows.push({
|
|
305
|
+
path: label,
|
|
306
|
+
category: "argos-home",
|
|
307
|
+
status: "error",
|
|
308
|
+
detail: errorMessage(err)
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
// Backups LAST, and always explicitly flagged: they're the safety net for
|
|
313
|
+
// every previous (and this very) destructive operation, so purging them
|
|
314
|
+
// removes the one thing that could otherwise undo a mistake.
|
|
315
|
+
const backupsDir = join(argosHome, "backups");
|
|
316
|
+
const backupsLabel = join("~", ".argos", "backups");
|
|
317
|
+
if (existsSync(backupsDir)) {
|
|
318
|
+
warnings.push("--purge elimina ~/.argos/backups — se pierde la red de seguridad de esta y de toda operación anterior.");
|
|
319
|
+
if (!apply) {
|
|
320
|
+
rows.push({
|
|
321
|
+
path: backupsLabel,
|
|
322
|
+
category: "argos-home",
|
|
323
|
+
status: "would-remove"
|
|
324
|
+
});
|
|
325
|
+
} else {
|
|
326
|
+
try {
|
|
327
|
+
rmSync(backupsDir, {
|
|
328
|
+
recursive: true,
|
|
329
|
+
force: true
|
|
330
|
+
});
|
|
331
|
+
rows.push({
|
|
332
|
+
path: backupsLabel,
|
|
333
|
+
category: "argos-home",
|
|
334
|
+
status: "removed"
|
|
335
|
+
});
|
|
336
|
+
} catch (err) {
|
|
337
|
+
rows.push({
|
|
338
|
+
path: backupsLabel,
|
|
339
|
+
category: "argos-home",
|
|
340
|
+
status: "error",
|
|
341
|
+
detail: errorMessage(err)
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Core, testable implementation of `argos remove`: uninstalls everything
|
|
349
|
+
* `runInit` (commands/init.ts) installs into `resolveClaudeDir()`. Pure
|
|
350
|
+
* function of the filesystem — no process.exit, no console output.
|
|
351
|
+
*
|
|
352
|
+
* Preview by default (`apply: false`): computes the full report without
|
|
353
|
+
* writing anything. `apply: true` performs the removal, backing up
|
|
354
|
+
* everything affected first (same `createBackup` call `runInit` makes,
|
|
355
|
+
* before any mutation). `purge: true` additionally removes `~/.argos` data
|
|
356
|
+
* (kept by default) — backups are removed last and always warned about.
|
|
357
|
+
*/ export function runRemove(options = {}) {
|
|
358
|
+
const apply = options.apply ?? false;
|
|
359
|
+
const purge = options.purge ?? false;
|
|
360
|
+
const claudeDir = resolveClaudeDir();
|
|
361
|
+
const rows = [];
|
|
362
|
+
const warnings = [];
|
|
363
|
+
let backupPath;
|
|
364
|
+
if (apply) {
|
|
365
|
+
try {
|
|
366
|
+
backupPath = createBackup(claudeDir, [
|
|
367
|
+
"CLAUDE.md",
|
|
368
|
+
"agents",
|
|
369
|
+
"skills",
|
|
370
|
+
"output-styles",
|
|
371
|
+
"hooks",
|
|
372
|
+
"settings.json"
|
|
373
|
+
]);
|
|
374
|
+
} catch (err) {
|
|
375
|
+
const detail = errorMessage(err);
|
|
376
|
+
rows.push({
|
|
377
|
+
path: "backup",
|
|
378
|
+
category: "argos-home",
|
|
379
|
+
status: "error",
|
|
380
|
+
detail
|
|
381
|
+
});
|
|
382
|
+
return {
|
|
383
|
+
rows,
|
|
384
|
+
summary: `backup falló — no se tocó nada (${detail}).`,
|
|
385
|
+
exitCode: 1,
|
|
386
|
+
warnings
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
processClaudeMd(claudeDir, apply, rows);
|
|
391
|
+
processManagedDir(claudeDir, "agents", "agents-file", hasArgosFileMarker, apply, rows);
|
|
392
|
+
processSkillsDir(claudeDir, apply, rows);
|
|
393
|
+
processManagedDir(claudeDir, "output-styles", "output-styles-file", hasArgosFileMarker, apply, rows);
|
|
394
|
+
processManagedDir(claudeDir, "hooks", "hooks-file", hasArgosShellFileMarker, apply, rows);
|
|
395
|
+
const settingsPath = join(claudeDir, "settings.json");
|
|
396
|
+
const settingsResult = removeAllArgosHooksFromSettings(settingsPath, join(claudeDir, "hooks"), {
|
|
397
|
+
dryRun: !apply
|
|
398
|
+
});
|
|
399
|
+
if (settingsResult.status === "error") {
|
|
400
|
+
rows.push({
|
|
401
|
+
path: "settings.json",
|
|
402
|
+
category: "settings-entries",
|
|
403
|
+
status: "error",
|
|
404
|
+
detail: settingsResult.detail
|
|
405
|
+
});
|
|
406
|
+
} else if (settingsResult.removedCount > 0) {
|
|
407
|
+
const noun = settingsResult.removedCount === 1 ? "entry" : "entries";
|
|
408
|
+
rows.push({
|
|
409
|
+
path: "settings.json",
|
|
410
|
+
category: "settings-entries",
|
|
411
|
+
status: apply ? "removed" : "would-remove",
|
|
412
|
+
detail: `${settingsResult.removedCount} hook ${noun}`
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
if (purge) processPurge(apply, rows, warnings);
|
|
416
|
+
// Always-present closing note: repo-side artifacts (argos.config.json, the
|
|
417
|
+
// ficha block in a repo's own CLAUDE.md) are out of scope for `remove` —
|
|
418
|
+
// see the module doc comment above.
|
|
419
|
+
rows.push({
|
|
420
|
+
path: "scope",
|
|
421
|
+
category: "scope-note",
|
|
422
|
+
status: "info",
|
|
423
|
+
detail: "los repos adoptados conservan su argos.config.json y ficha — este comando solo limpia ~/.claude y ~/.argos"
|
|
424
|
+
});
|
|
425
|
+
const exitCode = rows.some((r)=>r.status === "error") ? 1 : 0;
|
|
426
|
+
return {
|
|
427
|
+
rows,
|
|
428
|
+
summary: summarize(rows, apply),
|
|
429
|
+
exitCode,
|
|
430
|
+
backupPath,
|
|
431
|
+
warnings
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
export const removeCommand = defineCommand({
|
|
435
|
+
meta: {
|
|
436
|
+
name: "remove",
|
|
437
|
+
description: "Uninstall the Argos engine from the global Claude Code home (preview by default)."
|
|
438
|
+
},
|
|
439
|
+
args: {
|
|
440
|
+
apply: {
|
|
441
|
+
type: "boolean",
|
|
442
|
+
default: false,
|
|
443
|
+
description: "Actually perform the removal (default: dry-run preview, touches nothing)."
|
|
444
|
+
},
|
|
445
|
+
purge: {
|
|
446
|
+
type: "boolean",
|
|
447
|
+
default: false,
|
|
448
|
+
description: "Also remove ~/.argos data (registry, global.json, backups). Irreversible."
|
|
449
|
+
}
|
|
450
|
+
},
|
|
451
|
+
run ({ args }) {
|
|
452
|
+
const report = runRemove({
|
|
453
|
+
apply: args.apply,
|
|
454
|
+
purge: args.purge
|
|
455
|
+
});
|
|
456
|
+
const colorize = (status)=>{
|
|
457
|
+
const padded = status.padEnd(18);
|
|
458
|
+
switch(status){
|
|
459
|
+
case "skipped-foreign":
|
|
460
|
+
return pc.yellow(padded);
|
|
461
|
+
case "removed":
|
|
462
|
+
return pc.cyan(padded);
|
|
463
|
+
case "would-remove":
|
|
464
|
+
return pc.dim(padded);
|
|
465
|
+
case "warning":
|
|
466
|
+
return pc.yellow(padded);
|
|
467
|
+
case "info":
|
|
468
|
+
return pc.dim(padded);
|
|
469
|
+
case "error":
|
|
470
|
+
return pc.red(padded);
|
|
471
|
+
default:
|
|
472
|
+
return padded;
|
|
473
|
+
}
|
|
474
|
+
};
|
|
475
|
+
for (const row of report.rows){
|
|
476
|
+
const suffix = row.detail ? ` (${row.detail})` : "";
|
|
477
|
+
console.log(`${colorize(row.status)} ${row.path}${suffix}`);
|
|
478
|
+
}
|
|
479
|
+
console.log("");
|
|
480
|
+
console.log(report.summary);
|
|
481
|
+
if (report.backupPath) console.log(`backup en ${report.backupPath}`);
|
|
482
|
+
for (const warning of report.warnings)console.log(pc.yellow(`aviso: ${warning}`));
|
|
483
|
+
process.exit(report.exitCode);
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
|
|
487
|
+
//# sourceMappingURL=remove.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/commands/remove.ts"],"sourcesContent":["import { defineCommand } from \"citty\";\nimport { existsSync, readdirSync, readFileSync, rmSync, rmdirSync } from \"node:fs\";\nimport { join, relative, sep } from \"node:path\";\nimport pc from \"picocolors\";\nimport { listSkillFiles, listSkillIds, MANAGED_BLOCK_IDS, resolveAssetsDir } from \"../lib/assets.js\";\nimport { writeFileAtomic } from \"../lib/atomic-write.js\";\nimport { createBackup } from \"../lib/backup.js\";\nimport { listBlocks, removeBlock } from \"../lib/markers.js\";\nimport { hasArgosFileMarker, hasArgosShellFileMarker } from \"../lib/managed-files.js\";\nimport { resolveArgosHome, resolveClaudeDir } from \"../lib/paths.js\";\nimport { removeAllArgosHooksFromSettings } from \"../lib/settings-merge.js\";\n\n/**\n * Uninstaller for `argos init`: the mirror image of `runInit` (see\n * commands/init.ts). Removes only what Argos itself owns — a managed\n * CLAUDE.md block, a file carrying the `argos:file`/shell marker, or a\n * settings.json hook entry pointing at an Argos script — and leaves every\n * foreign file, block, and entry byte-identical.\n *\n * Scope: this command only touches `~/.claude` (via `resolveClaudeDir()`)\n * and, with `--purge`, `~/.argos` (via `resolveArgosHome()`) — the global\n * Argos engine and its registry. Repo-side artifacts are intentionally out\n * of scope and are NEVER touched here: a repo's own `argos.config.json` and\n * the \"ficha\" managed block `argos adopt` writes into that repo's own\n * `CLAUDE.md` both survive `remove` untouched, including `remove --purge`.\n * (See the final \"scope\" row every report ends with.)\n */\n\nexport type RemoveRowStatus = \"removed\" | \"would-remove\" | \"skipped-foreign\" | \"warning\" | \"info\" | \"error\";\n\nexport type RemoveRowCategory =\n | \"claude-md-block\"\n | \"agents-file\"\n | \"skills-file\"\n | \"output-styles-file\"\n | \"hooks-file\"\n | \"settings-entries\"\n | \"argos-home\"\n | \"scope-note\";\n\nexport interface RemoveRow {\n path: string;\n category: RemoveRowCategory;\n status: RemoveRowStatus;\n detail?: string;\n}\n\nexport interface RemoveOptions {\n /** Actually perform the removal. Default false = dry-run preview, touches nothing on disk. */\n apply?: boolean;\n /** Also remove ~/.argos data (registry, global.json, backups). Backups are removed LAST. */\n purge?: boolean;\n}\n\nexport interface RemoveReport {\n rows: RemoveRow[];\n summary: string;\n exitCode: 0 | 1;\n backupPath?: string;\n /** Non-fatal warnings surfaced alongside the report, e.g. the --purge/backups tradeoff. */\n warnings: string[];\n}\n\nconst STATUS_COUNT_ORDER: RemoveRowStatus[] = [\n \"removed\",\n \"would-remove\",\n \"skipped-foreign\",\n \"info\",\n \"warning\",\n \"error\",\n];\n\nfunction summarize(rows: RemoveRow[], apply: boolean): string {\n const counts: Record<RemoveRowStatus, number> = {\n removed: 0,\n \"would-remove\": 0,\n \"skipped-foreign\": 0,\n info: 0,\n warning: 0,\n error: 0,\n };\n for (const row of rows) counts[row.status]++;\n\n const parts = STATUS_COUNT_ORDER.filter((s) => counts[s] > 0).map((s) => `${counts[s]} ${s}`);\n const verb = apply ? \"argos remove\" : \"argos remove (preview — nada se tocó)\";\n return parts.length === 0 ? `${verb}: nada que hacer.` : `${verb}: ${parts.join(\", \")}.`;\n}\n\nfunction errorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n/** Strip every present managed block from CLAUDE.md; delete the file entirely if it becomes empty. */\nfunction processClaudeMd(claudeDir: string, apply: boolean, rows: RemoveRow[]): void {\n const claudeMdPath = join(claudeDir, \"CLAUDE.md\");\n if (!existsSync(claudeMdPath)) return;\n\n let claudeMd: string;\n try {\n claudeMd = readFileSync(claudeMdPath, \"utf-8\");\n } catch (err) {\n rows.push({ path: \"CLAUDE.md\", category: \"claude-md-block\", status: \"error\", detail: errorMessage(err) });\n return;\n }\n\n let next = claudeMd;\n const removedIds: string[] = [];\n for (const id of MANAGED_BLOCK_IDS) {\n const hadBlock = listBlocks(next).some((b) => b.id === id);\n if (!hadBlock) continue;\n const beforeThisId = next;\n // removeBlock only strips the first occurrence — loop to self-heal any\n // crash-residue duplicates left by injectBlock (see lib/markers.ts).\n // Progress-guarded: a dangling open marker with no matching close (see\n // lib/markers.ts's findBlock/listDanglingBlockIds) makes removeBlock a\n // no-op — its output equals its input — which would otherwise spin this\n // loop forever since listBlocks still reports the id as present. Break\n // and surface it as a warning instead of hanging.\n while (listBlocks(next).some((b) => b.id === id)) {\n const before = next;\n next = removeBlock(next, id);\n if (next === before) {\n rows.push({\n path: \"CLAUDE.md\",\n category: \"claude-md-block\",\n status: \"warning\",\n detail: \"marker argos huérfano sin cierre en CLAUDE.md — remuévelo a mano\",\n });\n break;\n }\n }\n if (next !== beforeThisId) removedIds.push(id);\n }\n\n if (removedIds.length === 0) return;\n for (const id of removedIds) {\n rows.push({ path: `CLAUDE.md#${id}`, category: \"claude-md-block\", status: apply ? \"removed\" : \"would-remove\" });\n }\n\n if (!apply) return;\n\n try {\n if (next.trim().length === 0) {\n rmSync(claudeMdPath, { force: true });\n } else {\n writeFileAtomic(claudeMdPath, next);\n }\n } catch (err) {\n rows.push({ path: \"CLAUDE.md\", category: \"claude-md-block\", status: \"error\", detail: errorMessage(err) });\n }\n}\n\nfunction walkFiles(dir: string): string[] {\n if (!existsSync(dir)) return [];\n const out: string[] = [];\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n const full = join(dir, entry.name);\n if (entry.isDirectory()) out.push(...walkFiles(full));\n else if (entry.isFile()) out.push(full);\n }\n return out;\n}\n\n/** Remove now-empty directories bottom-up under `dir`, leaving any dir that still holds foreign content. */\nfunction removeEmptyDirsUnder(dir: string): void {\n if (!existsSync(dir)) return;\n for (const entry of readdirSync(dir, { withFileTypes: true })) {\n if (entry.isDirectory()) removeEmptyDirsUnder(join(dir, entry.name));\n }\n const remaining = existsSync(dir) ? readdirSync(dir) : [];\n if (remaining.length === 0) {\n try {\n rmdirSync(dir);\n } catch {\n // Best-effort cleanup — a leftover empty dir is cosmetic, not an error.\n }\n }\n}\n\n/**\n * Remove every Argos-owned file (carrying the ownership marker) under\n * `claudeDir/<topDir>`, recursively — skills live in subdirectories, hence\n * the recursive walk. Foreign files (no marker) are reported\n * \"skipped-foreign\" and left byte-identical.\n */\nfunction processManagedDir(\n claudeDir: string,\n topDir: \"agents\" | \"output-styles\" | \"hooks\",\n category: RemoveRowCategory,\n hasMarker: (content: string) => boolean,\n apply: boolean,\n rows: RemoveRow[],\n): void {\n const dirPath = join(claudeDir, topDir);\n const files = walkFiles(dirPath);\n for (const file of files) {\n const relPath = relative(claudeDir, file);\n let content: string;\n try {\n content = readFileSync(file, \"utf-8\");\n } catch (err) {\n rows.push({ path: relPath, category, status: \"error\", detail: errorMessage(err) });\n continue;\n }\n\n if (!hasMarker(content)) {\n rows.push({ path: relPath, category, status: \"skipped-foreign\" });\n continue;\n }\n\n if (!apply) {\n rows.push({ path: relPath, category, status: \"would-remove\" });\n continue;\n }\n\n try {\n rmSync(file, { force: true });\n rows.push({ path: relPath, category, status: \"removed\" });\n } catch (err) {\n rows.push({ path: relPath, category, status: \"error\", detail: errorMessage(err) });\n }\n }\n\n if (apply) removeEmptyDirsUnder(dirPath);\n}\n\n/**\n * Remove Argos-owned skill directories under `claudeDir/skills/`.\n *\n * Unlike `processManagedDir` (per-file marker check), ownership here is\n * decided PER SKILL DIRECTORY: the skill's `SKILL.md` `argos:file` marker is\n * the sentinel (mirrors the install policy in commands/init.ts). Supporting\n * files (`references/*.md`, `phases/*.md`, etc.) never carry a marker of\n * their own, so a per-file marker check would wrongly treat every one of\n * them as foreign.\n * - `SKILL.md` missing, or present without the marker → the whole directory\n * is foreign (or not argos-installed at all); every file under it is left\n * untouched, reported \"skipped-foreign\".\n * - `SKILL.md` present with the marker → argos-owned. Only the files the\n * CURRENTLY shipped asset manifest lists for that skill id\n * (`listSkillFiles`) are removed; anything else in the directory — a\n * user-added extra file, or every file if this CLI version no longer\n * ships the skill at all — is left in place.\n */\nfunction processSkillsDir(claudeDir: string, apply: boolean, rows: RemoveRow[]): void {\n const skillsRoot = join(claudeDir, \"skills\");\n if (!existsSync(skillsRoot)) return;\n\n const assetsDir = resolveAssetsDir();\n const shippedSkillIds = new Set(listSkillIds(assetsDir));\n\n for (const entry of readdirSync(skillsRoot, { withFileTypes: true })) {\n if (!entry.isDirectory()) continue; // skills/ only ever holds skill subdirectories\n const skillId = entry.name;\n const skillDir = join(skillsRoot, skillId);\n const skillMdPath = join(skillDir, \"SKILL.md\");\n\n let skillMdContent: string | null = null;\n if (existsSync(skillMdPath)) {\n try {\n skillMdContent = readFileSync(skillMdPath, \"utf-8\");\n } catch (err) {\n rows.push({\n path: relative(claudeDir, skillMdPath),\n category: \"skills-file\",\n status: \"error\",\n detail: errorMessage(err),\n });\n continue;\n }\n }\n\n const isArgosOwned = skillMdContent !== null && hasArgosFileMarker(skillMdContent);\n const manifest =\n isArgosOwned && shippedSkillIds.has(skillId) ? new Set(listSkillFiles(assetsDir, skillId)) : new Set<string>();\n\n for (const file of walkFiles(skillDir)) {\n const relToClaudeDir = relative(claudeDir, file);\n\n if (!isArgosOwned || !manifest.has(relative(skillDir, file).split(sep).join(\"/\"))) {\n rows.push({ path: relToClaudeDir, category: \"skills-file\", status: \"skipped-foreign\" });\n continue;\n }\n\n if (!apply) {\n rows.push({ path: relToClaudeDir, category: \"skills-file\", status: \"would-remove\" });\n continue;\n }\n\n try {\n rmSync(file, { force: true });\n rows.push({ path: relToClaudeDir, category: \"skills-file\", status: \"removed\" });\n } catch (err) {\n rows.push({ path: relToClaudeDir, category: \"skills-file\", status: \"error\", detail: errorMessage(err) });\n }\n }\n }\n\n if (apply) removeEmptyDirsUnder(skillsRoot);\n}\n\nconst PURGE_FILES = [\"global.json\", \"workspaces.json\"] as const;\n\nfunction processPurge(apply: boolean, rows: RemoveRow[], warnings: string[]): void {\n const argosHome = resolveArgosHome();\n\n for (const name of PURGE_FILES) {\n const p = join(argosHome, name);\n if (!existsSync(p)) continue;\n const label = join(\"~\", \".argos\", name);\n if (!apply) {\n rows.push({ path: label, category: \"argos-home\", status: \"would-remove\" });\n continue;\n }\n try {\n rmSync(p, { force: true });\n rows.push({ path: label, category: \"argos-home\", status: \"removed\" });\n } catch (err) {\n rows.push({ path: label, category: \"argos-home\", status: \"error\", detail: errorMessage(err) });\n }\n }\n\n // Backups LAST, and always explicitly flagged: they're the safety net for\n // every previous (and this very) destructive operation, so purging them\n // removes the one thing that could otherwise undo a mistake.\n const backupsDir = join(argosHome, \"backups\");\n const backupsLabel = join(\"~\", \".argos\", \"backups\");\n if (existsSync(backupsDir)) {\n warnings.push(\n \"--purge elimina ~/.argos/backups — se pierde la red de seguridad de esta y de toda operación anterior.\",\n );\n if (!apply) {\n rows.push({ path: backupsLabel, category: \"argos-home\", status: \"would-remove\" });\n } else {\n try {\n rmSync(backupsDir, { recursive: true, force: true });\n rows.push({ path: backupsLabel, category: \"argos-home\", status: \"removed\" });\n } catch (err) {\n rows.push({ path: backupsLabel, category: \"argos-home\", status: \"error\", detail: errorMessage(err) });\n }\n }\n }\n}\n\n/**\n * Core, testable implementation of `argos remove`: uninstalls everything\n * `runInit` (commands/init.ts) installs into `resolveClaudeDir()`. Pure\n * function of the filesystem — no process.exit, no console output.\n *\n * Preview by default (`apply: false`): computes the full report without\n * writing anything. `apply: true` performs the removal, backing up\n * everything affected first (same `createBackup` call `runInit` makes,\n * before any mutation). `purge: true` additionally removes `~/.argos` data\n * (kept by default) — backups are removed last and always warned about.\n */\nexport function runRemove(options: RemoveOptions = {}): RemoveReport {\n const apply = options.apply ?? false;\n const purge = options.purge ?? false;\n const claudeDir = resolveClaudeDir();\n const rows: RemoveRow[] = [];\n const warnings: string[] = [];\n\n let backupPath: string | undefined;\n if (apply) {\n try {\n backupPath = createBackup(claudeDir, [\n \"CLAUDE.md\",\n \"agents\",\n \"skills\",\n \"output-styles\",\n \"hooks\",\n \"settings.json\",\n ]);\n } catch (err) {\n const detail = errorMessage(err);\n rows.push({ path: \"backup\", category: \"argos-home\", status: \"error\", detail });\n return { rows, summary: `backup falló — no se tocó nada (${detail}).`, exitCode: 1, warnings };\n }\n }\n\n processClaudeMd(claudeDir, apply, rows);\n\n processManagedDir(claudeDir, \"agents\", \"agents-file\", hasArgosFileMarker, apply, rows);\n processSkillsDir(claudeDir, apply, rows);\n processManagedDir(claudeDir, \"output-styles\", \"output-styles-file\", hasArgosFileMarker, apply, rows);\n processManagedDir(claudeDir, \"hooks\", \"hooks-file\", hasArgosShellFileMarker, apply, rows);\n\n const settingsPath = join(claudeDir, \"settings.json\");\n const settingsResult = removeAllArgosHooksFromSettings(settingsPath, join(claudeDir, \"hooks\"), { dryRun: !apply });\n if (settingsResult.status === \"error\") {\n rows.push({ path: \"settings.json\", category: \"settings-entries\", status: \"error\", detail: settingsResult.detail });\n } else if (settingsResult.removedCount > 0) {\n const noun = settingsResult.removedCount === 1 ? \"entry\" : \"entries\";\n rows.push({\n path: \"settings.json\",\n category: \"settings-entries\",\n status: apply ? \"removed\" : \"would-remove\",\n detail: `${settingsResult.removedCount} hook ${noun}`,\n });\n }\n\n if (purge) processPurge(apply, rows, warnings);\n\n // Always-present closing note: repo-side artifacts (argos.config.json, the\n // ficha block in a repo's own CLAUDE.md) are out of scope for `remove` —\n // see the module doc comment above.\n rows.push({\n path: \"scope\",\n category: \"scope-note\",\n status: \"info\",\n detail: \"los repos adoptados conservan su argos.config.json y ficha — este comando solo limpia ~/.claude y ~/.argos\",\n });\n\n const exitCode: 0 | 1 = rows.some((r) => r.status === \"error\") ? 1 : 0;\n return { rows, summary: summarize(rows, apply), exitCode, backupPath, warnings };\n}\n\nexport const removeCommand = defineCommand({\n meta: {\n name: \"remove\",\n description: \"Uninstall the Argos engine from the global Claude Code home (preview by default).\",\n },\n args: {\n apply: {\n type: \"boolean\",\n default: false,\n description: \"Actually perform the removal (default: dry-run preview, touches nothing).\",\n },\n purge: {\n type: \"boolean\",\n default: false,\n description: \"Also remove ~/.argos data (registry, global.json, backups). Irreversible.\",\n },\n },\n run({ args }) {\n const report = runRemove({ apply: args.apply, purge: args.purge });\n\n const colorize = (status: RemoveRowStatus): string => {\n const padded = status.padEnd(18);\n switch (status) {\n case \"skipped-foreign\":\n return pc.yellow(padded);\n case \"removed\":\n return pc.cyan(padded);\n case \"would-remove\":\n return pc.dim(padded);\n case \"warning\":\n return pc.yellow(padded);\n case \"info\":\n return pc.dim(padded);\n case \"error\":\n return pc.red(padded);\n default:\n return padded;\n }\n };\n for (const row of report.rows) {\n const suffix = row.detail ? ` (${row.detail})` : \"\";\n console.log(`${colorize(row.status)} ${row.path}${suffix}`);\n }\n console.log(\"\");\n console.log(report.summary);\n if (report.backupPath) console.log(`backup en ${report.backupPath}`);\n for (const warning of report.warnings) console.log(pc.yellow(`aviso: ${warning}`));\n\n process.exit(report.exitCode);\n },\n});\n"],"names":["defineCommand","existsSync","readdirSync","readFileSync","rmSync","rmdirSync","join","relative","sep","pc","listSkillFiles","listSkillIds","MANAGED_BLOCK_IDS","resolveAssetsDir","writeFileAtomic","createBackup","listBlocks","removeBlock","hasArgosFileMarker","hasArgosShellFileMarker","resolveArgosHome","resolveClaudeDir","removeAllArgosHooksFromSettings","STATUS_COUNT_ORDER","summarize","rows","apply","counts","removed","info","warning","error","row","status","parts","filter","s","map","verb","length","errorMessage","err","Error","message","String","processClaudeMd","claudeDir","claudeMdPath","claudeMd","push","path","category","detail","next","removedIds","id","hadBlock","some","b","beforeThisId","before","trim","force","walkFiles","dir","out","entry","withFileTypes","full","name","isDirectory","isFile","removeEmptyDirsUnder","remaining","processManagedDir","topDir","hasMarker","dirPath","files","file","relPath","content","processSkillsDir","skillsRoot","assetsDir","shippedSkillIds","Set","skillId","skillDir","skillMdPath","skillMdContent","isArgosOwned","manifest","has","relToClaudeDir","split","PURGE_FILES","processPurge","warnings","argosHome","p","label","backupsDir","backupsLabel","recursive","runRemove","options","purge","backupPath","summary","exitCode","settingsPath","settingsResult","dryRun","removedCount","noun","r","removeCommand","meta","description","args","type","default","run","report","colorize","padded","padEnd","yellow","cyan","dim","red","suffix","console","log","process","exit"],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { type OpenclawRunner, type WorkspaceAgentRow } from "../lib/openclaw-agents.js";
|
|
2
|
+
import { type LinkAction } from "../lib/workspaces.js";
|
|
3
|
+
export interface WorkspaceLinkOptions {
|
|
4
|
+
cwd: string;
|
|
5
|
+
/** Explicit workspace name passed on the command line, if any. */
|
|
6
|
+
explicit?: string;
|
|
7
|
+
/** Overwrite a name collision (same config.name, different physical repo) instead of refusing. */
|
|
8
|
+
force?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export interface WorkspaceLinkReport {
|
|
11
|
+
exitCode: 0 | 1;
|
|
12
|
+
error?: string;
|
|
13
|
+
ambiguousCandidates?: string[];
|
|
14
|
+
workspaceName?: string;
|
|
15
|
+
action?: LinkAction;
|
|
16
|
+
createdWorkspace?: boolean;
|
|
17
|
+
/** Remote identity persisted as a new match rule, if the offer fired. */
|
|
18
|
+
matchRuleAdded?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Core, testable implementation of `argos workspace link [nombre]`: resolves
|
|
22
|
+
* which workspace the repo at `cwd` belongs to (explicit name > config >
|
|
23
|
+
* match rules) and registers it. When a brand-new workspace was created via
|
|
24
|
+
* an explicit name and the repo has a remote, teaches the registry that
|
|
25
|
+
* remote as a match rule so future repos under the same identity auto-link.
|
|
26
|
+
*/
|
|
27
|
+
export declare function runWorkspaceLink(options: WorkspaceLinkOptions): WorkspaceLinkReport;
|
|
28
|
+
export interface WorkspaceShowRepoRow {
|
|
29
|
+
workspace: string;
|
|
30
|
+
name: string;
|
|
31
|
+
path: string;
|
|
32
|
+
missing: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface WorkspaceShowReport {
|
|
35
|
+
rows: WorkspaceShowRepoRow[];
|
|
36
|
+
exitCode: 0 | 1;
|
|
37
|
+
error?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface WorkspaceShowOptions {
|
|
40
|
+
/** Injectable for tests; defaults to node:fs existsSync. */
|
|
41
|
+
pathExists?: (path: string) => boolean;
|
|
42
|
+
}
|
|
43
|
+
/** Core, testable implementation of `argos workspace show [nombre]`. */
|
|
44
|
+
export declare function runWorkspaceShow(name?: string, options?: WorkspaceShowOptions): WorkspaceShowReport;
|
|
45
|
+
export interface RunWorkspaceAgentsOptions {
|
|
46
|
+
/** false (default) = preview only; true = actually run `openclaw agents add`. */
|
|
47
|
+
apply?: boolean;
|
|
48
|
+
prefix?: string;
|
|
49
|
+
/** Injectable for tests; defaults to lib/which.ts hasBinary. */
|
|
50
|
+
hasBinary?: (name: string) => boolean;
|
|
51
|
+
/** Injectable for tests; forwarded to planWorkspaceAgents. */
|
|
52
|
+
runner?: OpenclawRunner;
|
|
53
|
+
/** Injectable for tests; forwarded to planWorkspaceAgents. */
|
|
54
|
+
pathExists?: (path: string) => boolean;
|
|
55
|
+
}
|
|
56
|
+
export type RunWorkspaceAgentsEarlyReason = "workspace-not-found" | "no-repos" | "binary-missing";
|
|
57
|
+
export interface RunWorkspaceAgentsResult {
|
|
58
|
+
exitCode: 0 | 1;
|
|
59
|
+
preview: boolean;
|
|
60
|
+
reason?: RunWorkspaceAgentsEarlyReason;
|
|
61
|
+
error?: string;
|
|
62
|
+
rows: WorkspaceAgentRow[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Core logic for `workspace agents <nombre>`. Preview (default) never
|
|
66
|
+
* spawns anything — it only formats the commands that would run. `--apply`
|
|
67
|
+
* requires the `openclaw` binary on PATH; a per-repo failure never aborts
|
|
68
|
+
* the rest of the workspace (planWorkspaceAgents already guarantees this),
|
|
69
|
+
* so the exit code reflects the honest partial summary.
|
|
70
|
+
*/
|
|
71
|
+
export declare function runWorkspaceAgents(name: string, options?: RunWorkspaceAgentsOptions): RunWorkspaceAgentsResult;
|
|
72
|
+
export declare const workspaceCommand: import("citty").CommandDef<import("citty").ArgsDef>;
|
|
73
|
+
//# sourceMappingURL=workspace.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace.d.ts","sourceRoot":"","sources":["../../src/commands/workspace.ts"],"names":[],"mappings":"AAKA,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,iBAAiB,EAEvB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAML,KAAK,UAAU,EAChB,MAAM,sBAAsB,CAAC;AAS9B,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,kEAAkE;IAClE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kGAAkG;IAClG,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,yEAAyE;IACzE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,oBAAoB,GAAG,mBAAmB,CA4EnF;AAiDD,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,oBAAoB,EAAE,CAAC;IAC7B,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,oBAAoB;IACnC,4DAA4D;IAC5D,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACxC;AAED,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,mBAAmB,CA8BvG;AAkCD,MAAM,WAAW,yBAAyB;IACxC,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gEAAgE;IAChE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACtC,8DAA8D;IAC9D,MAAM,CAAC,EAAE,cAAc,CAAC;IACxB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACxC;AAED,MAAM,MAAM,6BAA6B,GAAG,qBAAqB,GAAG,UAAU,GAAG,gBAAgB,CAAC;AAElG,MAAM,WAAW,wBAAwB;IACvC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,6BAA6B,CAAC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,iBAAiB,EAAE,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,yBAA8B,GACtC,wBAAwB,CAsC1B;AAkED,eAAO,MAAM,gBAAgB,qDAU3B,CAAC"}
|