skillstogether 0.1.5 → 0.1.7
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/README.md +13 -4
- package/dist/index.js +272 -169
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -45,9 +45,7 @@ npx skillstogether add <organization-slug>
|
|
|
45
45
|
# Install all skills without prompts
|
|
46
46
|
npx skillstogether add <organization-slug> -y
|
|
47
47
|
|
|
48
|
-
# Install a specific skill
|
|
49
|
-
npx skillstogether add <organization-slug>/<skill-slug>
|
|
50
|
-
# or
|
|
48
|
+
# Install a specific skill (skill slugs already include the org prefix)
|
|
51
49
|
npx skillstogether add <organization-slug> --skill <skill-slug>
|
|
52
50
|
|
|
53
51
|
# Install globally (in home directory)
|
|
@@ -60,6 +58,17 @@ npx skillstogether add <organization-slug> --force
|
|
|
60
58
|
npx skillstogether add <organization-slug> --dir ./my-skills
|
|
61
59
|
```
|
|
62
60
|
|
|
61
|
+
### Uninstalling Skills
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Uninstall all skills from an organization
|
|
65
|
+
npx skillstogether uninstall <organization-slug>
|
|
66
|
+
|
|
67
|
+
# Uninstall a specific skill (skill slug already includes the org prefix)
|
|
68
|
+
npx skillstogether uninstall <organization-slug> --skill <skill-slug>
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
|
|
63
72
|
### Options
|
|
64
73
|
|
|
65
74
|
| Option | Alias | Description |
|
|
@@ -67,7 +76,7 @@ npx skillstogether add <organization-slug> --dir ./my-skills
|
|
|
67
76
|
| `--dir <path>` | `-d` | Custom installation directory |
|
|
68
77
|
| `--force` | `-f` | Overwrite existing skill files |
|
|
69
78
|
| `--yes` | `-y` | Skip interactive prompts, install all |
|
|
70
|
-
| `--skill <slug>` | — | Install a specific skill by slug
|
|
79
|
+
| `--skill <slug>` | — | Install a specific skill by slug (org-prefixed) |
|
|
71
80
|
| `--global` | — | Install globally (in home directory) |
|
|
72
81
|
|
|
73
82
|
---
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command9 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/commands/add.ts
|
|
7
7
|
import * as p2 from "@clack/prompts";
|
|
@@ -278,6 +278,13 @@ function trackDownloads(events) {
|
|
|
278
278
|
}).catch(() => {
|
|
279
279
|
});
|
|
280
280
|
}
|
|
281
|
+
async function submitSkillResult(organizationSlug, skillSlug, result) {
|
|
282
|
+
return apiPost(`/cli/skills/${encodeURIComponent(skillSlug)}/results`, {
|
|
283
|
+
organizationSlug,
|
|
284
|
+
skillSlug,
|
|
285
|
+
body: result
|
|
286
|
+
});
|
|
287
|
+
}
|
|
281
288
|
|
|
282
289
|
// src/lib/errors.ts
|
|
283
290
|
var DEFAULT_ERROR_MESSAGE = "Unknown error";
|
|
@@ -309,9 +316,11 @@ var skillSlugSchema = z.string().min(1, "Skill slug is required").max(100).regex
|
|
|
309
316
|
var addTargetSchema = z.string().min(1, "Target is required").refine(
|
|
310
317
|
(val) => {
|
|
311
318
|
const parts = val.split("/");
|
|
312
|
-
return parts.length
|
|
319
|
+
return parts.length === 1;
|
|
313
320
|
},
|
|
314
|
-
{
|
|
321
|
+
{
|
|
322
|
+
message: "Target must be an organization slug (no '/'). Use --skill to target a specific skill."
|
|
323
|
+
}
|
|
315
324
|
).refine(
|
|
316
325
|
(val) => {
|
|
317
326
|
const parts = val.split("/");
|
|
@@ -330,20 +339,17 @@ var updateTargetSchema = z.string().max(200).optional().refine(
|
|
|
330
339
|
var uninstallTargetSchema = z.string().min(1, "Target is required").refine(
|
|
331
340
|
(val) => {
|
|
332
341
|
const parts = val.split("/");
|
|
333
|
-
return parts.length
|
|
342
|
+
return parts.length === 1 && parts.every((part) => slugRegex.test(part));
|
|
334
343
|
},
|
|
335
|
-
{
|
|
344
|
+
{
|
|
345
|
+
message: "Target must be an organization slug (no '/'). Use --skill to target a specific skill."
|
|
346
|
+
}
|
|
336
347
|
);
|
|
337
|
-
var agentSchema = z.string().min(1).max(50);
|
|
338
348
|
var customDirSchema = z.string().min(1).max(4096);
|
|
339
349
|
function parseAddTarget(target) {
|
|
340
350
|
const parsed = addTargetSchema.parse(target);
|
|
341
|
-
const
|
|
342
|
-
|
|
343
|
-
return {
|
|
344
|
-
organizationSlug,
|
|
345
|
-
skillSlug: parts.length === 2 ? parts[1] : void 0
|
|
346
|
-
};
|
|
351
|
+
const organizationSlug = organizationSlugSchema.parse(parsed);
|
|
352
|
+
return { organizationSlug };
|
|
347
353
|
}
|
|
348
354
|
function parseUpdateTarget(target) {
|
|
349
355
|
if (target === void 0 || target === "") return {};
|
|
@@ -357,10 +363,8 @@ function parseUpdateTarget(target) {
|
|
|
357
363
|
}
|
|
358
364
|
function parseUninstallTarget(target) {
|
|
359
365
|
const parsed = uninstallTargetSchema.parse(target);
|
|
360
|
-
const parts = parsed.split("/");
|
|
361
366
|
return {
|
|
362
|
-
organizationSlug:
|
|
363
|
-
skillSlug: parts.length === 2 ? parts[1] : void 0
|
|
367
|
+
organizationSlug: parsed
|
|
364
368
|
};
|
|
365
369
|
}
|
|
366
370
|
function isValidSlug(slug) {
|
|
@@ -411,7 +415,10 @@ async function downloadFile(url) {
|
|
|
411
415
|
timeout: DEFAULT_REQUEST_TIMEOUT_MS
|
|
412
416
|
});
|
|
413
417
|
}
|
|
414
|
-
var SKILL_FOLDER_PATTERN = (organizationSlug, skillSlug) =>
|
|
418
|
+
var SKILL_FOLDER_PATTERN = (organizationSlug, skillSlug) => {
|
|
419
|
+
const prefix = `${organizationSlug}-`;
|
|
420
|
+
return skillSlug.startsWith(prefix) ? skillSlug : `${prefix}${skillSlug}`;
|
|
421
|
+
};
|
|
415
422
|
var SKILL_FILENAME = "SKILL.md";
|
|
416
423
|
async function installSkill(skill, organizationSlug, options) {
|
|
417
424
|
if (!isValidSlug(organizationSlug)) {
|
|
@@ -1213,7 +1220,10 @@ function buildDownloadEvents(allResults, skills, scopeLabel) {
|
|
|
1213
1220
|
}
|
|
1214
1221
|
return events;
|
|
1215
1222
|
}
|
|
1216
|
-
var addCommand = new Command("add").description("Install skills from an organization").argument("<target>", "Organization slug
|
|
1223
|
+
var addCommand = new Command("add").description("Install skills from an organization").argument("<target>", "Organization slug").option("-d, --dir <path>", "Custom installation directory").option("-f, --force", "Overwrite existing skill files", false).option("-y, --yes", "Skip interactive prompts and install all skills", false).option(
|
|
1224
|
+
"--skill <slug>",
|
|
1225
|
+
"Install a specific skill by slug (already org-prefixed, e.g. acme-onboarding)"
|
|
1226
|
+
).option("--global", "Install globally (in home directory)", false).option(
|
|
1217
1227
|
"--target <agents>",
|
|
1218
1228
|
"Comma-separated list of agent IDs to install to (e.g., claude-code,cursor)"
|
|
1219
1229
|
).action(
|
|
@@ -1237,13 +1247,7 @@ var addCommand = new Command("add").description("Install skills from an organiza
|
|
|
1237
1247
|
p2.outro(pc3.red("Invalid format"));
|
|
1238
1248
|
process.exit(1);
|
|
1239
1249
|
}
|
|
1240
|
-
if (
|
|
1241
|
-
await installSingleSkill(
|
|
1242
|
-
parsed.organizationSlug,
|
|
1243
|
-
parsed.skillSlug,
|
|
1244
|
-
options
|
|
1245
|
-
);
|
|
1246
|
-
} else if (options.skill) {
|
|
1250
|
+
if (options.skill) {
|
|
1247
1251
|
const skillResult = skillSlugSchema.safeParse(options.skill);
|
|
1248
1252
|
if (!skillResult.success) {
|
|
1249
1253
|
const msg = skillResult.error.issues?.[0]?.message ?? skillResult.error.message ?? "Invalid skill slug";
|
|
@@ -1251,6 +1255,14 @@ var addCommand = new Command("add").description("Install skills from an organiza
|
|
|
1251
1255
|
p2.outro(pc3.red("Invalid format"));
|
|
1252
1256
|
process.exit(1);
|
|
1253
1257
|
}
|
|
1258
|
+
const expectedPrefix = `${parsed.organizationSlug}-`;
|
|
1259
|
+
if (!skillResult.data.startsWith(expectedPrefix)) {
|
|
1260
|
+
p2.log.error(
|
|
1261
|
+
`Skill slug must be prefixed with the organization slug (e.g., ${pc3.cyan(`${expectedPrefix}my-skill`)})`
|
|
1262
|
+
);
|
|
1263
|
+
p2.outro(pc3.red("Invalid format"));
|
|
1264
|
+
process.exit(1);
|
|
1265
|
+
}
|
|
1254
1266
|
await installSingleSkill(
|
|
1255
1267
|
parsed.organizationSlug,
|
|
1256
1268
|
skillResult.data,
|
|
@@ -2108,33 +2120,115 @@ var doctorCommand = new Command3("doctor").description("Diagnose and fix common
|
|
|
2108
2120
|
}
|
|
2109
2121
|
});
|
|
2110
2122
|
|
|
2111
|
-
// src/commands/
|
|
2123
|
+
// src/commands/feedback.ts
|
|
2112
2124
|
import * as p5 from "@clack/prompts";
|
|
2113
2125
|
import { Command as Command4 } from "commander";
|
|
2114
2126
|
import pc6 from "picocolors";
|
|
2127
|
+
var feedbackCommand = new Command4("feedback").description("Submit feedback for a skill after task completion").argument(
|
|
2128
|
+
"<skillSlug>",
|
|
2129
|
+
"Skill slug (already org-prefixed, e.g., 'acme-onboarding')"
|
|
2130
|
+
).option("-s, --success", "Task completed successfully", true).option("-f, --failed", "Task failed").option("-q, --quality <rating>", "Quality rating 1-5", parseInt).option("-t, --time <seconds>", "Time spent in seconds", parseInt).option("-c, --files-count <count>", "Number of files modified", parseInt).option("-m, --summary <text>", "Brief summary of what was accomplished").option("--challenges <text>", "Difficulties encountered").option("-a, --agent <agent>", "Agent used (e.g., 'cursor', 'claude')").action(async (skillSlug, options) => {
|
|
2131
|
+
printCompactBanner();
|
|
2132
|
+
p5.intro(pc6.bgCyan(pc6.black(" Skill Feedback ")));
|
|
2133
|
+
const token = getToken();
|
|
2134
|
+
if (!token) {
|
|
2135
|
+
p5.log.error("Not authenticated. Run 'auth login' first.");
|
|
2136
|
+
p5.outro(pc6.red("\u2717 Failed"));
|
|
2137
|
+
process.exit(1);
|
|
2138
|
+
}
|
|
2139
|
+
const slugResult = skillSlugSchema.safeParse(skillSlug);
|
|
2140
|
+
if (!slugResult.success) {
|
|
2141
|
+
const msg = slugResult.error.issues?.[0]?.message ?? slugResult.error.message ?? "Invalid skill slug";
|
|
2142
|
+
p5.log.error(msg);
|
|
2143
|
+
p5.outro(pc6.red("\u2717 Failed"));
|
|
2144
|
+
process.exit(1);
|
|
2145
|
+
}
|
|
2146
|
+
const installedSkills = scanInstalledSkills({});
|
|
2147
|
+
const matches = installedSkills.filter((s2) => s2.slug === skillSlug);
|
|
2148
|
+
const organizations = new Set(
|
|
2149
|
+
matches.map((match) => match.organization).filter(Boolean)
|
|
2150
|
+
);
|
|
2151
|
+
if (organizations.size === 0) {
|
|
2152
|
+
p5.log.error(`Skill ${pc6.cyan(skillSlug)} not found in installed skills.`);
|
|
2153
|
+
p5.log.info(
|
|
2154
|
+
`Install it first, then retry. Example: ${pc6.cyan(`npx skillstogether add <org-slug> --skill ${skillSlug}`)}`
|
|
2155
|
+
);
|
|
2156
|
+
p5.outro(pc6.red("\u2717 Failed"));
|
|
2157
|
+
process.exit(1);
|
|
2158
|
+
}
|
|
2159
|
+
if (organizations.size > 1) {
|
|
2160
|
+
p5.log.error(
|
|
2161
|
+
`Multiple organizations found for ${pc6.cyan(skillSlug)}: ${pc6.cyan(
|
|
2162
|
+
Array.from(organizations).join(", ")
|
|
2163
|
+
)}`
|
|
2164
|
+
);
|
|
2165
|
+
p5.log.info("Use the org-prefixed skill slug to disambiguate.");
|
|
2166
|
+
p5.outro(pc6.red("\u2717 Failed"));
|
|
2167
|
+
process.exit(1);
|
|
2168
|
+
}
|
|
2169
|
+
const organizationSlug = Array.from(organizations)[0];
|
|
2170
|
+
if (options.quality !== void 0 && (options.quality < 1 || options.quality > 5)) {
|
|
2171
|
+
p5.log.error("Quality rating must be between 1 and 5");
|
|
2172
|
+
p5.outro(pc6.red("\u2717 Failed"));
|
|
2173
|
+
process.exit(1);
|
|
2174
|
+
}
|
|
2175
|
+
const result = {
|
|
2176
|
+
success: !options.failed,
|
|
2177
|
+
quality: options.quality,
|
|
2178
|
+
timeSeconds: options.time,
|
|
2179
|
+
filesCount: options.filesCount,
|
|
2180
|
+
summary: options.summary,
|
|
2181
|
+
challenges: options.challenges,
|
|
2182
|
+
agent: options.agent
|
|
2183
|
+
};
|
|
2184
|
+
const s = p5.spinner();
|
|
2185
|
+
s.start(
|
|
2186
|
+
`Submitting feedback for ${pc6.cyan(`${organizationSlug}/${skillSlug}`)}`
|
|
2187
|
+
);
|
|
2188
|
+
try {
|
|
2189
|
+
const response = await submitSkillResult(
|
|
2190
|
+
organizationSlug,
|
|
2191
|
+
skillSlug,
|
|
2192
|
+
result
|
|
2193
|
+
);
|
|
2194
|
+
s.stop(`Feedback submitted`);
|
|
2195
|
+
p5.log.success(response.message);
|
|
2196
|
+
p5.outro(pc6.green("\u2713 Feedback recorded!"));
|
|
2197
|
+
} catch (error) {
|
|
2198
|
+
s.stop("Failed to submit feedback");
|
|
2199
|
+
p5.log.error(error instanceof Error ? error.message : "Unknown error");
|
|
2200
|
+
p5.outro(pc6.red("\u2717 Failed"));
|
|
2201
|
+
process.exit(1);
|
|
2202
|
+
}
|
|
2203
|
+
});
|
|
2204
|
+
|
|
2205
|
+
// src/commands/list.ts
|
|
2206
|
+
import * as p6 from "@clack/prompts";
|
|
2207
|
+
import { Command as Command5 } from "commander";
|
|
2208
|
+
import pc7 from "picocolors";
|
|
2115
2209
|
function displaySkillsTable(skills) {
|
|
2116
2210
|
if (skills.length === 0) {
|
|
2117
|
-
|
|
2211
|
+
p6.log.info(pc7.dim("No skills installed"));
|
|
2118
2212
|
return;
|
|
2119
2213
|
}
|
|
2120
2214
|
const byOrg = groupSkillsByOrganization(skills);
|
|
2121
2215
|
for (const [org, orgSkills] of byOrg) {
|
|
2122
2216
|
console.log();
|
|
2123
|
-
console.log(
|
|
2217
|
+
console.log(pc7.cyan(` ${org}/`));
|
|
2124
2218
|
for (const skill of orgSkills) {
|
|
2125
|
-
const agentBadge =
|
|
2126
|
-
const scopeBadge = skill.scope === "global" ?
|
|
2127
|
-
const versionStr = skill.version ?
|
|
2219
|
+
const agentBadge = pc7.dim(`[${skill.agent.name}]`);
|
|
2220
|
+
const scopeBadge = skill.scope === "global" ? pc7.yellow("(global)") : pc7.dim("(project)");
|
|
2221
|
+
const versionStr = skill.version ? pc7.dim(`v${skill.version}`) : "";
|
|
2128
2222
|
console.log(
|
|
2129
|
-
` ${
|
|
2223
|
+
` ${pc7.white(skill.name)} ${versionStr} ${agentBadge} ${scopeBadge}`
|
|
2130
2224
|
);
|
|
2131
|
-
console.log(
|
|
2225
|
+
console.log(pc7.dim(` ${shortenPath(skill.path)}`));
|
|
2132
2226
|
}
|
|
2133
2227
|
}
|
|
2134
2228
|
}
|
|
2135
2229
|
function displaySkillsByAgent(skills) {
|
|
2136
2230
|
if (skills.length === 0) {
|
|
2137
|
-
|
|
2231
|
+
p6.log.info(pc7.dim("No skills installed"));
|
|
2138
2232
|
return;
|
|
2139
2233
|
}
|
|
2140
2234
|
const byAgent = groupSkillsByAgent(skills);
|
|
@@ -2142,26 +2236,26 @@ function displaySkillsByAgent(skills) {
|
|
|
2142
2236
|
const agentConfig = AGENTS.find((a) => a.id === agent);
|
|
2143
2237
|
const agentName = agentConfig?.name || agent;
|
|
2144
2238
|
console.log();
|
|
2145
|
-
console.log(
|
|
2239
|
+
console.log(pc7.cyan(` ${agentName}`));
|
|
2146
2240
|
for (const skill of agentSkills) {
|
|
2147
|
-
const scopeBadge = skill.scope === "global" ?
|
|
2241
|
+
const scopeBadge = skill.scope === "global" ? pc7.yellow("(global)") : pc7.dim("(project)");
|
|
2148
2242
|
console.log(
|
|
2149
|
-
` ${
|
|
2243
|
+
` ${pc7.white(`${skill.organization}/${skill.slug}`)} ${scopeBadge}`
|
|
2150
2244
|
);
|
|
2151
2245
|
}
|
|
2152
2246
|
}
|
|
2153
2247
|
}
|
|
2154
|
-
var listCommand = new
|
|
2248
|
+
var listCommand = new Command5("list").description("List installed skills").option("--global", "Show only globally installed skills").option("--project", "Show only project-installed skills").option("--agent <id>", "Show only skills for a specific agent").option("--by-agent", "Group output by agent instead of organization").action(
|
|
2155
2249
|
async (options) => {
|
|
2156
2250
|
printCompactBanner();
|
|
2157
|
-
|
|
2251
|
+
p6.intro(pc7.bgCyan(pc7.black(" Installed Skills ")));
|
|
2158
2252
|
let scope;
|
|
2159
2253
|
if (options.global && !options.project) {
|
|
2160
2254
|
scope = "global";
|
|
2161
2255
|
} else if (options.project && !options.global) {
|
|
2162
2256
|
scope = "project";
|
|
2163
2257
|
}
|
|
2164
|
-
const s =
|
|
2258
|
+
const s = p6.spinner();
|
|
2165
2259
|
s.start("Scanning for installed skills...");
|
|
2166
2260
|
const skills = scanInstalledSkills({
|
|
2167
2261
|
scope,
|
|
@@ -2170,15 +2264,15 @@ var listCommand = new Command4("list").description("List installed skills").opti
|
|
|
2170
2264
|
const uniqueSkills = deduplicateSkills(skills);
|
|
2171
2265
|
const uniqueCount = uniqueSkills.length;
|
|
2172
2266
|
const totalInstances = skills.length;
|
|
2173
|
-
const countDisplay = uniqueCount === totalInstances ? `${
|
|
2267
|
+
const countDisplay = uniqueCount === totalInstances ? `${pc7.green(uniqueCount.toString())} skill${uniqueCount !== 1 ? "s" : ""}` : `${pc7.green(uniqueCount.toString())} unique skill${uniqueCount !== 1 ? "s" : ""} (${totalInstances} installations)`;
|
|
2174
2268
|
s.stop(`Found ${countDisplay}`);
|
|
2175
2269
|
if (skills.length === 0) {
|
|
2176
|
-
|
|
2177
|
-
|
|
2270
|
+
p6.log.info(
|
|
2271
|
+
pc7.dim(
|
|
2178
2272
|
"No skills found. Install skills with: npx skillstogether add <org-slug>"
|
|
2179
2273
|
)
|
|
2180
2274
|
);
|
|
2181
|
-
|
|
2275
|
+
p6.outro(pc7.dim("Done"));
|
|
2182
2276
|
return;
|
|
2183
2277
|
}
|
|
2184
2278
|
if (options.byAgent) {
|
|
@@ -2193,21 +2287,21 @@ var listCommand = new Command4("list").description("List installed skills").opti
|
|
|
2193
2287
|
).length;
|
|
2194
2288
|
const orgCount = new Set(uniqueSkills.map((s2) => s2.organization)).size;
|
|
2195
2289
|
const agentCount = new Set(skills.map((s2) => s2.agent.id)).size;
|
|
2196
|
-
|
|
2197
|
-
|
|
2290
|
+
p6.log.info(
|
|
2291
|
+
pc7.dim(
|
|
2198
2292
|
`${uniqueCount} unique skill${uniqueCount !== 1 ? "s" : ""}, ${orgCount} organization${orgCount !== 1 ? "s" : ""}, ${agentCount} agent${agentCount !== 1 ? "s" : ""}, ${globalCount} global, ${projectCount} project`
|
|
2199
2293
|
)
|
|
2200
2294
|
);
|
|
2201
|
-
|
|
2295
|
+
p6.outro(pc7.dim("Done"));
|
|
2202
2296
|
}
|
|
2203
2297
|
);
|
|
2204
2298
|
|
|
2205
2299
|
// src/commands/status.ts
|
|
2206
|
-
import * as
|
|
2207
|
-
import { Command as
|
|
2208
|
-
import
|
|
2300
|
+
import * as p7 from "@clack/prompts";
|
|
2301
|
+
import { Command as Command6 } from "commander";
|
|
2302
|
+
import pc8 from "picocolors";
|
|
2209
2303
|
function formatDate(dateStr) {
|
|
2210
|
-
if (!dateStr) return
|
|
2304
|
+
if (!dateStr) return pc8.dim("unknown");
|
|
2211
2305
|
try {
|
|
2212
2306
|
const date = new Date(dateStr);
|
|
2213
2307
|
return date.toLocaleDateString("en-US", {
|
|
@@ -2218,7 +2312,7 @@ function formatDate(dateStr) {
|
|
|
2218
2312
|
minute: "2-digit"
|
|
2219
2313
|
});
|
|
2220
2314
|
} catch {
|
|
2221
|
-
return
|
|
2315
|
+
return pc8.dim("invalid");
|
|
2222
2316
|
}
|
|
2223
2317
|
}
|
|
2224
2318
|
function groupByOrganization(skills) {
|
|
@@ -2230,16 +2324,16 @@ function groupByOrganization(skills) {
|
|
|
2230
2324
|
}
|
|
2231
2325
|
return groups;
|
|
2232
2326
|
}
|
|
2233
|
-
var statusCommand = new
|
|
2327
|
+
var statusCommand = new Command6("status").description("Check for skill updates").argument("[org-slug]", "Organization to check (optional)").option("--global", "Check only globally installed skills").option("--project", "Check only project-installed skills").action(
|
|
2234
2328
|
async (organizationSlug, options) => {
|
|
2235
2329
|
printCompactBanner();
|
|
2236
|
-
|
|
2330
|
+
p7.intro(pc8.bgCyan(pc8.black(" Check for Updates ")));
|
|
2237
2331
|
const token = getToken();
|
|
2238
2332
|
if (!token) {
|
|
2239
|
-
|
|
2240
|
-
`Not authenticated. Run ${
|
|
2333
|
+
p7.log.error(
|
|
2334
|
+
`Not authenticated. Run ${pc8.cyan("npx skillstogether auth login")} first.`
|
|
2241
2335
|
);
|
|
2242
|
-
|
|
2336
|
+
p7.outro(pc8.red("Authentication required"));
|
|
2243
2337
|
process.exit(1);
|
|
2244
2338
|
}
|
|
2245
2339
|
let scope;
|
|
@@ -2248,7 +2342,7 @@ var statusCommand = new Command5("status").description("Check for skill updates"
|
|
|
2248
2342
|
} else if (options.project && !options.global) {
|
|
2249
2343
|
scope = "project";
|
|
2250
2344
|
}
|
|
2251
|
-
const s =
|
|
2345
|
+
const s = p7.spinner();
|
|
2252
2346
|
s.start("Scanning installed skills...");
|
|
2253
2347
|
const installedSkills = scanUniqueSkills({
|
|
2254
2348
|
scope,
|
|
@@ -2256,17 +2350,17 @@ var statusCommand = new Command5("status").description("Check for skill updates"
|
|
|
2256
2350
|
});
|
|
2257
2351
|
if (installedSkills.length === 0) {
|
|
2258
2352
|
s.stop("No installed skills found");
|
|
2259
|
-
|
|
2260
|
-
|
|
2353
|
+
p7.log.info(
|
|
2354
|
+
pc8.dim("Install skills with: npx skillstogether add <org-slug>")
|
|
2261
2355
|
);
|
|
2262
|
-
|
|
2356
|
+
p7.outro(pc8.dim("Done"));
|
|
2263
2357
|
return;
|
|
2264
2358
|
}
|
|
2265
2359
|
s.stop(
|
|
2266
|
-
`Found ${
|
|
2360
|
+
`Found ${pc8.green(installedSkills.length.toString())} installed skill${installedSkills.length !== 1 ? "s" : ""}`
|
|
2267
2361
|
);
|
|
2268
2362
|
const byOrg = groupByOrganization(installedSkills);
|
|
2269
|
-
const checkSpinner =
|
|
2363
|
+
const checkSpinner = p7.spinner();
|
|
2270
2364
|
checkSpinner.start("Checking for updates...");
|
|
2271
2365
|
const allUpdates = [];
|
|
2272
2366
|
const errors = [];
|
|
@@ -2291,57 +2385,57 @@ var statusCommand = new Command5("status").description("Check for skill updates"
|
|
|
2291
2385
|
);
|
|
2292
2386
|
if (outdatedSkills.length > 0) {
|
|
2293
2387
|
console.log();
|
|
2294
|
-
|
|
2295
|
-
`${
|
|
2388
|
+
p7.log.warn(
|
|
2389
|
+
`${pc8.yellow(outdatedSkills.length.toString())} skill${outdatedSkills.length !== 1 ? "s" : ""} ${outdatedSkills.length !== 1 ? "have" : "has"} updates available:`
|
|
2296
2390
|
);
|
|
2297
2391
|
for (const { org, updates } of allUpdates) {
|
|
2298
2392
|
const orgOutdated = updates.filter((u) => u.hasUpdate);
|
|
2299
2393
|
if (orgOutdated.length === 0) continue;
|
|
2300
2394
|
console.log();
|
|
2301
|
-
console.log(
|
|
2395
|
+
console.log(pc8.cyan(` ${org}/`));
|
|
2302
2396
|
for (const update of orgOutdated) {
|
|
2303
|
-
console.log(` ${
|
|
2397
|
+
console.log(` ${pc8.yellow("\u2191")} ${pc8.white(update.name)}`);
|
|
2304
2398
|
console.log(
|
|
2305
|
-
` Installed: ${
|
|
2399
|
+
` Installed: ${pc8.dim(formatDate(update.installedAt))}`
|
|
2306
2400
|
);
|
|
2307
2401
|
console.log(
|
|
2308
|
-
` Available: ${
|
|
2402
|
+
` Available: ${pc8.green(formatDate(update.updatedAt))} ${pc8.dim(`(v${update.currentVersion})`)}`
|
|
2309
2403
|
);
|
|
2310
2404
|
}
|
|
2311
2405
|
}
|
|
2312
2406
|
console.log();
|
|
2313
|
-
|
|
2314
|
-
`Run ${
|
|
2407
|
+
p7.log.info(
|
|
2408
|
+
`Run ${pc8.cyan("npx skillstogether update")} to update all skills`
|
|
2315
2409
|
);
|
|
2316
2410
|
if (organizationSlug) {
|
|
2317
|
-
|
|
2318
|
-
`Or ${
|
|
2411
|
+
p7.log.info(
|
|
2412
|
+
`Or ${pc8.cyan(`npx skillstogether update ${organizationSlug}`)} to update this organization only`
|
|
2319
2413
|
);
|
|
2320
2414
|
}
|
|
2321
2415
|
} else {
|
|
2322
|
-
|
|
2323
|
-
`All ${
|
|
2416
|
+
p7.log.success(
|
|
2417
|
+
`All ${pc8.green(upToDateSkills.length.toString())} skill${upToDateSkills.length !== 1 ? "s are" : " is"} up to date!`
|
|
2324
2418
|
);
|
|
2325
2419
|
}
|
|
2326
2420
|
if (errors.length > 0) {
|
|
2327
2421
|
console.log();
|
|
2328
|
-
|
|
2422
|
+
p7.log.error(
|
|
2329
2423
|
`Failed to check ${errors.length} organization${errors.length !== 1 ? "s" : ""}:`
|
|
2330
2424
|
);
|
|
2331
2425
|
for (const error of errors) {
|
|
2332
|
-
console.log(` ${
|
|
2426
|
+
console.log(` ${pc8.red("\u2022")} ${error}`);
|
|
2333
2427
|
}
|
|
2334
2428
|
}
|
|
2335
|
-
|
|
2429
|
+
p7.outro(pc8.dim("Done"));
|
|
2336
2430
|
}
|
|
2337
2431
|
);
|
|
2338
2432
|
|
|
2339
2433
|
// src/commands/uninstall.ts
|
|
2340
|
-
import * as
|
|
2341
|
-
import { Command as
|
|
2434
|
+
import * as p8 from "@clack/prompts";
|
|
2435
|
+
import { Command as Command7 } from "commander";
|
|
2342
2436
|
import { rmSync } from "fs";
|
|
2343
2437
|
import { dirname as dirname2 } from "path";
|
|
2344
|
-
import
|
|
2438
|
+
import pc9 from "picocolors";
|
|
2345
2439
|
function removeSkill(skill) {
|
|
2346
2440
|
try {
|
|
2347
2441
|
const skillDir = dirname2(skill.path);
|
|
@@ -2354,10 +2448,13 @@ function removeSkill(skill) {
|
|
|
2354
2448
|
};
|
|
2355
2449
|
}
|
|
2356
2450
|
}
|
|
2357
|
-
var uninstallCommand = new
|
|
2451
|
+
var uninstallCommand = new Command7("uninstall").description("Remove installed skills").argument("<target>", "Organization slug").option("--all", "Remove all skills from the organization").option(
|
|
2452
|
+
"--skill <slug>",
|
|
2453
|
+
"Remove a specific skill by slug (already org-prefixed, e.g. acme-onboarding)"
|
|
2454
|
+
).option("--global", "Remove from global installation only").option("--project", "Remove from project installation only").option("-y, --yes", "Skip confirmation prompts").action(
|
|
2358
2455
|
async (target, options) => {
|
|
2359
2456
|
printCompactBanner();
|
|
2360
|
-
|
|
2457
|
+
p8.intro(pc9.bgCyan(pc9.black(" Uninstall Skills ")));
|
|
2361
2458
|
let scope;
|
|
2362
2459
|
if (options.global && !options.project) {
|
|
2363
2460
|
scope = "global";
|
|
@@ -2369,64 +2466,69 @@ var uninstallCommand = new Command6("uninstall").description("Remove installed s
|
|
|
2369
2466
|
parsed = parseUninstallTarget(target);
|
|
2370
2467
|
} catch (err) {
|
|
2371
2468
|
const msg = err instanceof Error && "message" in err ? err.message : "Invalid target format";
|
|
2372
|
-
|
|
2373
|
-
|
|
2469
|
+
p8.log.error(msg);
|
|
2470
|
+
p8.outro(pc9.red("Invalid format"));
|
|
2374
2471
|
process.exit(1);
|
|
2375
2472
|
}
|
|
2376
|
-
if (
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
);
|
|
2381
|
-
|
|
2382
|
-
|
|
2473
|
+
if (options.skill) {
|
|
2474
|
+
const skillResult = skillSlugSchema.safeParse(options.skill);
|
|
2475
|
+
if (!skillResult.success) {
|
|
2476
|
+
const msg = skillResult.error.issues?.[0]?.message ?? skillResult.error.message ?? "Invalid skill slug";
|
|
2477
|
+
p8.log.error(msg);
|
|
2478
|
+
p8.outro(pc9.red("Invalid format"));
|
|
2479
|
+
process.exit(1);
|
|
2480
|
+
}
|
|
2481
|
+
const expectedPrefix = `${parsed.organizationSlug}-`;
|
|
2482
|
+
if (!skillResult.data.startsWith(expectedPrefix)) {
|
|
2483
|
+
p8.log.error(
|
|
2484
|
+
`Skill slug must be prefixed with the organization slug (e.g., ${pc9.cyan(`${expectedPrefix}my-skill`)})`
|
|
2383
2485
|
);
|
|
2384
|
-
|
|
2486
|
+
p8.outro(pc9.red("Invalid format"));
|
|
2385
2487
|
process.exit(1);
|
|
2386
2488
|
}
|
|
2387
|
-
await uninstallOrganization(parsed.organizationSlug, scope, options.yes);
|
|
2388
|
-
} else {
|
|
2389
2489
|
await uninstallSkill(
|
|
2390
2490
|
parsed.organizationSlug,
|
|
2391
|
-
|
|
2491
|
+
skillResult.data,
|
|
2392
2492
|
scope,
|
|
2393
2493
|
options.yes
|
|
2394
2494
|
);
|
|
2495
|
+
return;
|
|
2395
2496
|
}
|
|
2497
|
+
await uninstallOrganization(parsed.organizationSlug, scope, options.yes);
|
|
2396
2498
|
}
|
|
2397
2499
|
);
|
|
2398
2500
|
async function uninstallOrganization(organizationSlug, scope, skipConfirm) {
|
|
2399
|
-
const s =
|
|
2400
|
-
s.start(`Finding skills from ${
|
|
2501
|
+
const s = p8.spinner();
|
|
2502
|
+
s.start(`Finding skills from ${pc9.cyan(organizationSlug)}...`);
|
|
2401
2503
|
const skills = scanInstalledSkills({ organization: organizationSlug, scope });
|
|
2402
2504
|
if (skills.length === 0) {
|
|
2403
|
-
s.stop(`No skills found from ${
|
|
2404
|
-
|
|
2505
|
+
s.stop(`No skills found from ${pc9.cyan(organizationSlug)}`);
|
|
2506
|
+
p8.outro(pc9.yellow("Nothing to uninstall"));
|
|
2405
2507
|
return;
|
|
2406
2508
|
}
|
|
2407
2509
|
s.stop(
|
|
2408
|
-
`Found ${
|
|
2510
|
+
`Found ${pc9.green(skills.length.toString())} skill${skills.length !== 1 ? "s" : ""} from ${pc9.cyan(organizationSlug)}`
|
|
2409
2511
|
);
|
|
2410
2512
|
console.log();
|
|
2411
|
-
|
|
2513
|
+
p8.log.info("Skills to remove:");
|
|
2412
2514
|
for (const skill of skills) {
|
|
2413
|
-
const scopeBadge = skill.scope === "global" ?
|
|
2515
|
+
const scopeBadge = skill.scope === "global" ? pc9.yellow("(global)") : pc9.dim("(project)");
|
|
2414
2516
|
console.log(
|
|
2415
|
-
` ${
|
|
2517
|
+
` ${pc9.red("\u2022")} ${skill.name} ${pc9.dim(`[${skill.agent.name}]`)} ${scopeBadge}`
|
|
2416
2518
|
);
|
|
2417
2519
|
}
|
|
2418
2520
|
console.log();
|
|
2419
2521
|
if (!skipConfirm) {
|
|
2420
|
-
const confirmed = await
|
|
2522
|
+
const confirmed = await p8.confirm({
|
|
2421
2523
|
message: `Remove all ${skills.length} skill${skills.length !== 1 ? "s" : ""} from ${organizationSlug}?`,
|
|
2422
2524
|
initialValue: false
|
|
2423
2525
|
});
|
|
2424
|
-
if (
|
|
2425
|
-
|
|
2526
|
+
if (p8.isCancel(confirmed) || !confirmed) {
|
|
2527
|
+
p8.cancel("Uninstall cancelled");
|
|
2426
2528
|
process.exit(0);
|
|
2427
2529
|
}
|
|
2428
2530
|
}
|
|
2429
|
-
const removeSpinner =
|
|
2531
|
+
const removeSpinner = p8.spinner();
|
|
2430
2532
|
removeSpinner.start("Removing skills...");
|
|
2431
2533
|
let removed = 0;
|
|
2432
2534
|
let failed = 0;
|
|
@@ -2442,53 +2544,53 @@ async function uninstallOrganization(organizationSlug, scope, skipConfirm) {
|
|
|
2442
2544
|
}
|
|
2443
2545
|
removeSpinner.stop("Removal complete");
|
|
2444
2546
|
if (removed > 0) {
|
|
2445
|
-
|
|
2446
|
-
`Removed ${
|
|
2547
|
+
p8.log.success(
|
|
2548
|
+
`Removed ${pc9.green(removed.toString())} skill${removed !== 1 ? "s" : ""}`
|
|
2447
2549
|
);
|
|
2448
2550
|
}
|
|
2449
2551
|
if (failed > 0) {
|
|
2450
|
-
|
|
2451
|
-
`Failed to remove ${
|
|
2552
|
+
p8.log.error(
|
|
2553
|
+
`Failed to remove ${pc9.red(failed.toString())} skill${failed !== 1 ? "s" : ""}`
|
|
2452
2554
|
);
|
|
2453
2555
|
for (const error of errors) {
|
|
2454
|
-
|
|
2556
|
+
p8.log.error(pc9.dim(` ${error}`));
|
|
2455
2557
|
}
|
|
2456
2558
|
}
|
|
2457
|
-
|
|
2559
|
+
p8.outro(pc9.dim("Done"));
|
|
2458
2560
|
}
|
|
2459
2561
|
async function uninstallSkill(organizationSlug, skillSlug, scope, skipConfirm) {
|
|
2460
|
-
const s =
|
|
2461
|
-
s.start(`Finding ${
|
|
2562
|
+
const s = p8.spinner();
|
|
2563
|
+
s.start(`Finding ${pc9.cyan(`${organizationSlug}/${skillSlug}`)}...`);
|
|
2462
2564
|
const instances = findSkillInstances(organizationSlug, skillSlug, { scope });
|
|
2463
2565
|
if (instances.length === 0) {
|
|
2464
|
-
s.stop(`Skill ${
|
|
2465
|
-
|
|
2566
|
+
s.stop(`Skill ${pc9.cyan(`${organizationSlug}/${skillSlug}`)} not found`);
|
|
2567
|
+
p8.outro(pc9.yellow("Nothing to uninstall"));
|
|
2466
2568
|
return;
|
|
2467
2569
|
}
|
|
2468
2570
|
s.stop(
|
|
2469
|
-
`Found ${
|
|
2571
|
+
`Found ${pc9.green(instances.length.toString())} instance${instances.length !== 1 ? "s" : ""} of ${pc9.cyan(`${organizationSlug}/${skillSlug}`)}`
|
|
2470
2572
|
);
|
|
2471
2573
|
console.log();
|
|
2472
|
-
|
|
2574
|
+
p8.log.info("Instances to remove:");
|
|
2473
2575
|
for (const skill of instances) {
|
|
2474
|
-
const scopeBadge = skill.scope === "global" ?
|
|
2576
|
+
const scopeBadge = skill.scope === "global" ? pc9.yellow("(global)") : pc9.dim("(project)");
|
|
2475
2577
|
console.log(
|
|
2476
|
-
` ${
|
|
2578
|
+
` ${pc9.red("\u2022")} ${pc9.dim(`[${skill.agent.name}]`)} ${scopeBadge}`
|
|
2477
2579
|
);
|
|
2478
|
-
console.log(` ${
|
|
2580
|
+
console.log(` ${pc9.dim(shortenPath(skill.path))}`);
|
|
2479
2581
|
}
|
|
2480
2582
|
console.log();
|
|
2481
2583
|
if (!skipConfirm) {
|
|
2482
|
-
const confirmed = await
|
|
2584
|
+
const confirmed = await p8.confirm({
|
|
2483
2585
|
message: `Remove ${instances.length} instance${instances.length !== 1 ? "s" : ""} of ${organizationSlug}/${skillSlug}?`,
|
|
2484
2586
|
initialValue: false
|
|
2485
2587
|
});
|
|
2486
|
-
if (
|
|
2487
|
-
|
|
2588
|
+
if (p8.isCancel(confirmed) || !confirmed) {
|
|
2589
|
+
p8.cancel("Uninstall cancelled");
|
|
2488
2590
|
process.exit(0);
|
|
2489
2591
|
}
|
|
2490
2592
|
}
|
|
2491
|
-
const removeSpinner =
|
|
2593
|
+
const removeSpinner = p8.spinner();
|
|
2492
2594
|
removeSpinner.start("Removing skill...");
|
|
2493
2595
|
let removed = 0;
|
|
2494
2596
|
let failed = 0;
|
|
@@ -2504,26 +2606,26 @@ async function uninstallSkill(organizationSlug, skillSlug, scope, skipConfirm) {
|
|
|
2504
2606
|
}
|
|
2505
2607
|
removeSpinner.stop("Removal complete");
|
|
2506
2608
|
if (removed > 0) {
|
|
2507
|
-
|
|
2508
|
-
`Removed ${
|
|
2609
|
+
p8.log.success(
|
|
2610
|
+
`Removed ${pc9.green(removed.toString())} instance${removed !== 1 ? "s" : ""}`
|
|
2509
2611
|
);
|
|
2510
2612
|
}
|
|
2511
2613
|
if (failed > 0) {
|
|
2512
|
-
|
|
2513
|
-
`Failed to remove ${
|
|
2614
|
+
p8.log.error(
|
|
2615
|
+
`Failed to remove ${pc9.red(failed.toString())} instance${failed !== 1 ? "s" : ""}`
|
|
2514
2616
|
);
|
|
2515
2617
|
for (const error of errors) {
|
|
2516
|
-
|
|
2618
|
+
p8.log.error(pc9.dim(` ${error}`));
|
|
2517
2619
|
}
|
|
2518
2620
|
}
|
|
2519
|
-
|
|
2621
|
+
p8.outro(pc9.dim("Done"));
|
|
2520
2622
|
}
|
|
2521
2623
|
|
|
2522
2624
|
// src/commands/update.ts
|
|
2523
|
-
import * as
|
|
2524
|
-
import { Command as
|
|
2625
|
+
import * as p9 from "@clack/prompts";
|
|
2626
|
+
import { Command as Command8 } from "commander";
|
|
2525
2627
|
import { writeFileSync as writeFileSync3 } from "fs";
|
|
2526
|
-
import
|
|
2628
|
+
import pc10 from "picocolors";
|
|
2527
2629
|
function generateUpdatedContent(skill, organizationSlug) {
|
|
2528
2630
|
const frontmatter = generateFrontmatter({
|
|
2529
2631
|
name: skill.name,
|
|
@@ -2535,16 +2637,16 @@ function generateUpdatedContent(skill, organizationSlug) {
|
|
|
2535
2637
|
});
|
|
2536
2638
|
return frontmatter + "\n" + (skill.content || "");
|
|
2537
2639
|
}
|
|
2538
|
-
var updateCommand = new
|
|
2640
|
+
var updateCommand = new Command8("update").description("Update installed skills to latest version").argument("[target]", "Organization slug or organization/skill slug").option("--global", "Update only globally installed skills").option("--project", "Update only project-installed skills").option("-y, --yes", "Skip confirmation prompts").option("--dry-run", "Show what would be updated without making changes").action(
|
|
2539
2641
|
async (target, options) => {
|
|
2540
2642
|
printCompactBanner();
|
|
2541
|
-
|
|
2643
|
+
p9.intro(pc10.bgCyan(pc10.black(" Update Skills ")));
|
|
2542
2644
|
const token = getToken();
|
|
2543
2645
|
if (!token) {
|
|
2544
|
-
|
|
2545
|
-
`Not authenticated. Run ${
|
|
2646
|
+
p9.log.error(
|
|
2647
|
+
`Not authenticated. Run ${pc10.cyan("npx skillstogether auth login")} first.`
|
|
2546
2648
|
);
|
|
2547
|
-
|
|
2649
|
+
p9.outro(pc10.red("Authentication required"));
|
|
2548
2650
|
process.exit(1);
|
|
2549
2651
|
}
|
|
2550
2652
|
let scope;
|
|
@@ -2562,12 +2664,12 @@ var updateCommand = new Command7("update").description("Update installed skills
|
|
|
2562
2664
|
skillSlug = parsed.skillSlug;
|
|
2563
2665
|
} catch (err) {
|
|
2564
2666
|
const msg = err instanceof Error && "message" in err ? err.message : "Invalid target format";
|
|
2565
|
-
|
|
2566
|
-
|
|
2667
|
+
p9.log.error(msg);
|
|
2668
|
+
p9.outro(pc10.red("Invalid format"));
|
|
2567
2669
|
process.exit(1);
|
|
2568
2670
|
}
|
|
2569
2671
|
}
|
|
2570
|
-
const s =
|
|
2672
|
+
const s = p9.spinner();
|
|
2571
2673
|
s.start("Scanning installed skills...");
|
|
2572
2674
|
const allInstalledSkills = scanInstalledSkills({
|
|
2573
2675
|
scope,
|
|
@@ -2579,15 +2681,15 @@ var updateCommand = new Command7("update").description("Update installed skills
|
|
|
2579
2681
|
}
|
|
2580
2682
|
if (skillsToCheck.length === 0) {
|
|
2581
2683
|
s.stop("No installed skills found");
|
|
2582
|
-
|
|
2583
|
-
|
|
2684
|
+
p9.log.info(
|
|
2685
|
+
pc10.dim("Install skills with: npx skillstogether add <org-slug>")
|
|
2584
2686
|
);
|
|
2585
|
-
|
|
2687
|
+
p9.outro(pc10.dim("Done"));
|
|
2586
2688
|
return;
|
|
2587
2689
|
}
|
|
2588
2690
|
const uniqueSkills = deduplicateSkills(skillsToCheck);
|
|
2589
2691
|
s.stop(
|
|
2590
|
-
`Found ${
|
|
2692
|
+
`Found ${pc10.green(uniqueSkills.length.toString())} installed skill${uniqueSkills.length !== 1 ? "s" : ""}`
|
|
2591
2693
|
);
|
|
2592
2694
|
const byOrg = /* @__PURE__ */ new Map();
|
|
2593
2695
|
for (const skill of uniqueSkills) {
|
|
@@ -2595,7 +2697,7 @@ var updateCommand = new Command7("update").description("Update installed skills
|
|
|
2595
2697
|
existing.push(skill);
|
|
2596
2698
|
byOrg.set(skill.organization, existing);
|
|
2597
2699
|
}
|
|
2598
|
-
const checkSpinner =
|
|
2700
|
+
const checkSpinner = p9.spinner();
|
|
2599
2701
|
checkSpinner.start("Checking for updates...");
|
|
2600
2702
|
const skillsToUpdate = [];
|
|
2601
2703
|
const errors = [];
|
|
@@ -2624,17 +2726,17 @@ var updateCommand = new Command7("update").description("Update installed skills
|
|
|
2624
2726
|
}
|
|
2625
2727
|
checkSpinner.stop("Update check complete");
|
|
2626
2728
|
if (skillsToUpdate.length === 0) {
|
|
2627
|
-
|
|
2729
|
+
p9.log.success("All skills are up to date!");
|
|
2628
2730
|
if (errors.length > 0) {
|
|
2629
2731
|
console.log();
|
|
2630
|
-
|
|
2732
|
+
p9.log.error(
|
|
2631
2733
|
`Failed to check ${errors.length} organization${errors.length !== 1 ? "s" : ""}:`
|
|
2632
2734
|
);
|
|
2633
2735
|
for (const error of errors) {
|
|
2634
|
-
console.log(` ${
|
|
2736
|
+
console.log(` ${pc10.red("\u2022")} ${error}`);
|
|
2635
2737
|
}
|
|
2636
2738
|
}
|
|
2637
|
-
|
|
2739
|
+
p9.outro(pc10.dim("Done"));
|
|
2638
2740
|
return;
|
|
2639
2741
|
}
|
|
2640
2742
|
const totalInstances = skillsToUpdate.reduce(
|
|
@@ -2642,33 +2744,33 @@ var updateCommand = new Command7("update").description("Update installed skills
|
|
|
2642
2744
|
0
|
|
2643
2745
|
);
|
|
2644
2746
|
console.log();
|
|
2645
|
-
const updateMsg = skillsToUpdate.length === totalInstances ? `${
|
|
2646
|
-
|
|
2747
|
+
const updateMsg = skillsToUpdate.length === totalInstances ? `${pc10.yellow(skillsToUpdate.length.toString())} skill${skillsToUpdate.length !== 1 ? "s" : ""} will be updated:` : `${pc10.yellow(skillsToUpdate.length.toString())} skill${skillsToUpdate.length !== 1 ? "s" : ""} (${totalInstances} installations) will be updated:`;
|
|
2748
|
+
p9.log.info(updateMsg);
|
|
2647
2749
|
for (const { unique, remoteVersion } of skillsToUpdate) {
|
|
2648
2750
|
const agentNames = unique.agents.map((a) => a.name).join(", ");
|
|
2649
|
-
const scopeBadge = unique.scope === "global" ?
|
|
2751
|
+
const scopeBadge = unique.scope === "global" ? pc10.yellow("(global)") : pc10.dim("(project)");
|
|
2650
2752
|
console.log(
|
|
2651
|
-
` ${
|
|
2753
|
+
` ${pc10.yellow("\u2191")} ${pc10.white(`${unique.organization}/${unique.slug}`)} ${pc10.dim(`v${unique.version || "?"}`)} \u2192 ${pc10.green(`v${remoteVersion}`)} ${pc10.dim(`[${agentNames}]`)} ${scopeBadge}`
|
|
2652
2754
|
);
|
|
2653
2755
|
}
|
|
2654
2756
|
console.log();
|
|
2655
2757
|
if (options.dryRun) {
|
|
2656
|
-
|
|
2657
|
-
|
|
2758
|
+
p9.log.info(pc10.dim("Dry run - no changes made"));
|
|
2759
|
+
p9.outro(pc10.dim("Done"));
|
|
2658
2760
|
return;
|
|
2659
2761
|
}
|
|
2660
2762
|
if (!options.yes) {
|
|
2661
2763
|
const confirmMsg = skillsToUpdate.length === totalInstances ? `Update ${skillsToUpdate.length} skill${skillsToUpdate.length !== 1 ? "s" : ""}?` : `Update ${skillsToUpdate.length} skill${skillsToUpdate.length !== 1 ? "s" : ""} (${totalInstances} installations)?`;
|
|
2662
|
-
const confirmed = await
|
|
2764
|
+
const confirmed = await p9.confirm({
|
|
2663
2765
|
message: confirmMsg,
|
|
2664
2766
|
initialValue: true
|
|
2665
2767
|
});
|
|
2666
|
-
if (
|
|
2667
|
-
|
|
2768
|
+
if (p9.isCancel(confirmed) || !confirmed) {
|
|
2769
|
+
p9.cancel("Update cancelled");
|
|
2668
2770
|
process.exit(0);
|
|
2669
2771
|
}
|
|
2670
2772
|
}
|
|
2671
|
-
const updateSpinner =
|
|
2773
|
+
const updateSpinner = p9.spinner();
|
|
2672
2774
|
updateSpinner.start("Updating skills...");
|
|
2673
2775
|
let updatedSkills = 0;
|
|
2674
2776
|
let updatedInstances = 0;
|
|
@@ -2692,23 +2794,23 @@ var updateCommand = new Command7("update").description("Update installed skills
|
|
|
2692
2794
|
}
|
|
2693
2795
|
updateSpinner.stop("Update complete");
|
|
2694
2796
|
if (updatedSkills > 0) {
|
|
2695
|
-
const summaryMsg = updatedSkills === updatedInstances ? `Updated ${
|
|
2696
|
-
|
|
2797
|
+
const summaryMsg = updatedSkills === updatedInstances ? `Updated ${pc10.green(updatedSkills.toString())} skill${updatedSkills !== 1 ? "s" : ""}` : `Updated ${pc10.green(updatedSkills.toString())} skill${updatedSkills !== 1 ? "s" : ""} (${updatedInstances} installations)`;
|
|
2798
|
+
p9.log.success(summaryMsg);
|
|
2697
2799
|
}
|
|
2698
2800
|
if (failed > 0) {
|
|
2699
|
-
|
|
2700
|
-
`Failed to update ${
|
|
2801
|
+
p9.log.error(
|
|
2802
|
+
`Failed to update ${pc10.red(failed.toString())} skill${failed !== 1 ? "s" : ""}`
|
|
2701
2803
|
);
|
|
2702
2804
|
for (const error of updateErrors) {
|
|
2703
|
-
console.log(` ${
|
|
2805
|
+
console.log(` ${pc10.red("\u2022")} ${error}`);
|
|
2704
2806
|
}
|
|
2705
2807
|
}
|
|
2706
|
-
|
|
2808
|
+
p9.outro(pc10.dim("Done"));
|
|
2707
2809
|
}
|
|
2708
2810
|
);
|
|
2709
2811
|
|
|
2710
2812
|
// src/index.ts
|
|
2711
|
-
var program = new
|
|
2813
|
+
var program = new Command9();
|
|
2712
2814
|
program.name("skillstogether").description("CLI tool to install organization skills").version("0.1.0").hook("preAction", (thisCommand) => {
|
|
2713
2815
|
const commandName = thisCommand.name();
|
|
2714
2816
|
if (commandName === "skillstogether") {
|
|
@@ -2724,6 +2826,7 @@ program.helpInformation = function() {
|
|
|
2724
2826
|
program.addCommand(authCommand);
|
|
2725
2827
|
program.addCommand(addCommand);
|
|
2726
2828
|
program.addCommand(doctorCommand);
|
|
2829
|
+
program.addCommand(feedbackCommand);
|
|
2727
2830
|
program.addCommand(listCommand);
|
|
2728
2831
|
program.addCommand(statusCommand);
|
|
2729
2832
|
program.addCommand(uninstallCommand);
|