skillstogether 0.1.4 → 0.1.6
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 +269 -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) {
|
|
@@ -1213,7 +1217,10 @@ function buildDownloadEvents(allResults, skills, scopeLabel) {
|
|
|
1213
1217
|
}
|
|
1214
1218
|
return events;
|
|
1215
1219
|
}
|
|
1216
|
-
var addCommand = new Command("add").description("Install skills from an organization").argument("<target>", "Organization slug
|
|
1220
|
+
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(
|
|
1221
|
+
"--skill <slug>",
|
|
1222
|
+
"Install a specific skill by slug (already org-prefixed, e.g. acme-onboarding)"
|
|
1223
|
+
).option("--global", "Install globally (in home directory)", false).option(
|
|
1217
1224
|
"--target <agents>",
|
|
1218
1225
|
"Comma-separated list of agent IDs to install to (e.g., claude-code,cursor)"
|
|
1219
1226
|
).action(
|
|
@@ -1237,20 +1244,22 @@ var addCommand = new Command("add").description("Install skills from an organiza
|
|
|
1237
1244
|
p2.outro(pc3.red("Invalid format"));
|
|
1238
1245
|
process.exit(1);
|
|
1239
1246
|
}
|
|
1240
|
-
if (
|
|
1241
|
-
await installSingleSkill(
|
|
1242
|
-
parsed.organizationSlug,
|
|
1243
|
-
parsed.skillSlug,
|
|
1244
|
-
options
|
|
1245
|
-
);
|
|
1246
|
-
} else if (options.skill) {
|
|
1247
|
+
if (options.skill) {
|
|
1247
1248
|
const skillResult = skillSlugSchema.safeParse(options.skill);
|
|
1248
1249
|
if (!skillResult.success) {
|
|
1249
|
-
const msg = skillResult.error.
|
|
1250
|
+
const msg = skillResult.error.issues?.[0]?.message ?? skillResult.error.message ?? "Invalid skill slug";
|
|
1250
1251
|
p2.log.error(msg);
|
|
1251
1252
|
p2.outro(pc3.red("Invalid format"));
|
|
1252
1253
|
process.exit(1);
|
|
1253
1254
|
}
|
|
1255
|
+
const expectedPrefix = `${parsed.organizationSlug}-`;
|
|
1256
|
+
if (!skillResult.data.startsWith(expectedPrefix)) {
|
|
1257
|
+
p2.log.error(
|
|
1258
|
+
`Skill slug must be prefixed with the organization slug (e.g., ${pc3.cyan(`${expectedPrefix}my-skill`)})`
|
|
1259
|
+
);
|
|
1260
|
+
p2.outro(pc3.red("Invalid format"));
|
|
1261
|
+
process.exit(1);
|
|
1262
|
+
}
|
|
1254
1263
|
await installSingleSkill(
|
|
1255
1264
|
parsed.organizationSlug,
|
|
1256
1265
|
skillResult.data,
|
|
@@ -2108,33 +2117,115 @@ var doctorCommand = new Command3("doctor").description("Diagnose and fix common
|
|
|
2108
2117
|
}
|
|
2109
2118
|
});
|
|
2110
2119
|
|
|
2111
|
-
// src/commands/
|
|
2120
|
+
// src/commands/feedback.ts
|
|
2112
2121
|
import * as p5 from "@clack/prompts";
|
|
2113
2122
|
import { Command as Command4 } from "commander";
|
|
2114
2123
|
import pc6 from "picocolors";
|
|
2124
|
+
var feedbackCommand = new Command4("feedback").description("Submit feedback for a skill after task completion").argument(
|
|
2125
|
+
"<skillSlug>",
|
|
2126
|
+
"Skill slug (already org-prefixed, e.g., 'acme-onboarding')"
|
|
2127
|
+
).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) => {
|
|
2128
|
+
printCompactBanner();
|
|
2129
|
+
p5.intro(pc6.bgCyan(pc6.black(" Skill Feedback ")));
|
|
2130
|
+
const token = getToken();
|
|
2131
|
+
if (!token) {
|
|
2132
|
+
p5.log.error("Not authenticated. Run 'auth login' first.");
|
|
2133
|
+
p5.outro(pc6.red("\u2717 Failed"));
|
|
2134
|
+
process.exit(1);
|
|
2135
|
+
}
|
|
2136
|
+
const slugResult = skillSlugSchema.safeParse(skillSlug);
|
|
2137
|
+
if (!slugResult.success) {
|
|
2138
|
+
const msg = slugResult.error.issues?.[0]?.message ?? slugResult.error.message ?? "Invalid skill slug";
|
|
2139
|
+
p5.log.error(msg);
|
|
2140
|
+
p5.outro(pc6.red("\u2717 Failed"));
|
|
2141
|
+
process.exit(1);
|
|
2142
|
+
}
|
|
2143
|
+
const installedSkills = scanInstalledSkills({});
|
|
2144
|
+
const matches = installedSkills.filter((s2) => s2.slug === skillSlug);
|
|
2145
|
+
const organizations = new Set(
|
|
2146
|
+
matches.map((match) => match.organization).filter(Boolean)
|
|
2147
|
+
);
|
|
2148
|
+
if (organizations.size === 0) {
|
|
2149
|
+
p5.log.error(`Skill ${pc6.cyan(skillSlug)} not found in installed skills.`);
|
|
2150
|
+
p5.log.info(
|
|
2151
|
+
`Install it first, then retry. Example: ${pc6.cyan(`npx skillstogether add <org-slug> --skill ${skillSlug}`)}`
|
|
2152
|
+
);
|
|
2153
|
+
p5.outro(pc6.red("\u2717 Failed"));
|
|
2154
|
+
process.exit(1);
|
|
2155
|
+
}
|
|
2156
|
+
if (organizations.size > 1) {
|
|
2157
|
+
p5.log.error(
|
|
2158
|
+
`Multiple organizations found for ${pc6.cyan(skillSlug)}: ${pc6.cyan(
|
|
2159
|
+
Array.from(organizations).join(", ")
|
|
2160
|
+
)}`
|
|
2161
|
+
);
|
|
2162
|
+
p5.log.info("Use the org-prefixed skill slug to disambiguate.");
|
|
2163
|
+
p5.outro(pc6.red("\u2717 Failed"));
|
|
2164
|
+
process.exit(1);
|
|
2165
|
+
}
|
|
2166
|
+
const organizationSlug = Array.from(organizations)[0];
|
|
2167
|
+
if (options.quality !== void 0 && (options.quality < 1 || options.quality > 5)) {
|
|
2168
|
+
p5.log.error("Quality rating must be between 1 and 5");
|
|
2169
|
+
p5.outro(pc6.red("\u2717 Failed"));
|
|
2170
|
+
process.exit(1);
|
|
2171
|
+
}
|
|
2172
|
+
const result = {
|
|
2173
|
+
success: !options.failed,
|
|
2174
|
+
quality: options.quality,
|
|
2175
|
+
timeSeconds: options.time,
|
|
2176
|
+
filesCount: options.filesCount,
|
|
2177
|
+
summary: options.summary,
|
|
2178
|
+
challenges: options.challenges,
|
|
2179
|
+
agent: options.agent
|
|
2180
|
+
};
|
|
2181
|
+
const s = p5.spinner();
|
|
2182
|
+
s.start(
|
|
2183
|
+
`Submitting feedback for ${pc6.cyan(`${organizationSlug}/${skillSlug}`)}`
|
|
2184
|
+
);
|
|
2185
|
+
try {
|
|
2186
|
+
const response = await submitSkillResult(
|
|
2187
|
+
organizationSlug,
|
|
2188
|
+
skillSlug,
|
|
2189
|
+
result
|
|
2190
|
+
);
|
|
2191
|
+
s.stop(`Feedback submitted`);
|
|
2192
|
+
p5.log.success(response.message);
|
|
2193
|
+
p5.outro(pc6.green("\u2713 Feedback recorded!"));
|
|
2194
|
+
} catch (error) {
|
|
2195
|
+
s.stop("Failed to submit feedback");
|
|
2196
|
+
p5.log.error(error instanceof Error ? error.message : "Unknown error");
|
|
2197
|
+
p5.outro(pc6.red("\u2717 Failed"));
|
|
2198
|
+
process.exit(1);
|
|
2199
|
+
}
|
|
2200
|
+
});
|
|
2201
|
+
|
|
2202
|
+
// src/commands/list.ts
|
|
2203
|
+
import * as p6 from "@clack/prompts";
|
|
2204
|
+
import { Command as Command5 } from "commander";
|
|
2205
|
+
import pc7 from "picocolors";
|
|
2115
2206
|
function displaySkillsTable(skills) {
|
|
2116
2207
|
if (skills.length === 0) {
|
|
2117
|
-
|
|
2208
|
+
p6.log.info(pc7.dim("No skills installed"));
|
|
2118
2209
|
return;
|
|
2119
2210
|
}
|
|
2120
2211
|
const byOrg = groupSkillsByOrganization(skills);
|
|
2121
2212
|
for (const [org, orgSkills] of byOrg) {
|
|
2122
2213
|
console.log();
|
|
2123
|
-
console.log(
|
|
2214
|
+
console.log(pc7.cyan(` ${org}/`));
|
|
2124
2215
|
for (const skill of orgSkills) {
|
|
2125
|
-
const agentBadge =
|
|
2126
|
-
const scopeBadge = skill.scope === "global" ?
|
|
2127
|
-
const versionStr = skill.version ?
|
|
2216
|
+
const agentBadge = pc7.dim(`[${skill.agent.name}]`);
|
|
2217
|
+
const scopeBadge = skill.scope === "global" ? pc7.yellow("(global)") : pc7.dim("(project)");
|
|
2218
|
+
const versionStr = skill.version ? pc7.dim(`v${skill.version}`) : "";
|
|
2128
2219
|
console.log(
|
|
2129
|
-
` ${
|
|
2220
|
+
` ${pc7.white(skill.name)} ${versionStr} ${agentBadge} ${scopeBadge}`
|
|
2130
2221
|
);
|
|
2131
|
-
console.log(
|
|
2222
|
+
console.log(pc7.dim(` ${shortenPath(skill.path)}`));
|
|
2132
2223
|
}
|
|
2133
2224
|
}
|
|
2134
2225
|
}
|
|
2135
2226
|
function displaySkillsByAgent(skills) {
|
|
2136
2227
|
if (skills.length === 0) {
|
|
2137
|
-
|
|
2228
|
+
p6.log.info(pc7.dim("No skills installed"));
|
|
2138
2229
|
return;
|
|
2139
2230
|
}
|
|
2140
2231
|
const byAgent = groupSkillsByAgent(skills);
|
|
@@ -2142,26 +2233,26 @@ function displaySkillsByAgent(skills) {
|
|
|
2142
2233
|
const agentConfig = AGENTS.find((a) => a.id === agent);
|
|
2143
2234
|
const agentName = agentConfig?.name || agent;
|
|
2144
2235
|
console.log();
|
|
2145
|
-
console.log(
|
|
2236
|
+
console.log(pc7.cyan(` ${agentName}`));
|
|
2146
2237
|
for (const skill of agentSkills) {
|
|
2147
|
-
const scopeBadge = skill.scope === "global" ?
|
|
2238
|
+
const scopeBadge = skill.scope === "global" ? pc7.yellow("(global)") : pc7.dim("(project)");
|
|
2148
2239
|
console.log(
|
|
2149
|
-
` ${
|
|
2240
|
+
` ${pc7.white(`${skill.organization}/${skill.slug}`)} ${scopeBadge}`
|
|
2150
2241
|
);
|
|
2151
2242
|
}
|
|
2152
2243
|
}
|
|
2153
2244
|
}
|
|
2154
|
-
var listCommand = new
|
|
2245
|
+
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
2246
|
async (options) => {
|
|
2156
2247
|
printCompactBanner();
|
|
2157
|
-
|
|
2248
|
+
p6.intro(pc7.bgCyan(pc7.black(" Installed Skills ")));
|
|
2158
2249
|
let scope;
|
|
2159
2250
|
if (options.global && !options.project) {
|
|
2160
2251
|
scope = "global";
|
|
2161
2252
|
} else if (options.project && !options.global) {
|
|
2162
2253
|
scope = "project";
|
|
2163
2254
|
}
|
|
2164
|
-
const s =
|
|
2255
|
+
const s = p6.spinner();
|
|
2165
2256
|
s.start("Scanning for installed skills...");
|
|
2166
2257
|
const skills = scanInstalledSkills({
|
|
2167
2258
|
scope,
|
|
@@ -2170,15 +2261,15 @@ var listCommand = new Command4("list").description("List installed skills").opti
|
|
|
2170
2261
|
const uniqueSkills = deduplicateSkills(skills);
|
|
2171
2262
|
const uniqueCount = uniqueSkills.length;
|
|
2172
2263
|
const totalInstances = skills.length;
|
|
2173
|
-
const countDisplay = uniqueCount === totalInstances ? `${
|
|
2264
|
+
const countDisplay = uniqueCount === totalInstances ? `${pc7.green(uniqueCount.toString())} skill${uniqueCount !== 1 ? "s" : ""}` : `${pc7.green(uniqueCount.toString())} unique skill${uniqueCount !== 1 ? "s" : ""} (${totalInstances} installations)`;
|
|
2174
2265
|
s.stop(`Found ${countDisplay}`);
|
|
2175
2266
|
if (skills.length === 0) {
|
|
2176
|
-
|
|
2177
|
-
|
|
2267
|
+
p6.log.info(
|
|
2268
|
+
pc7.dim(
|
|
2178
2269
|
"No skills found. Install skills with: npx skillstogether add <org-slug>"
|
|
2179
2270
|
)
|
|
2180
2271
|
);
|
|
2181
|
-
|
|
2272
|
+
p6.outro(pc7.dim("Done"));
|
|
2182
2273
|
return;
|
|
2183
2274
|
}
|
|
2184
2275
|
if (options.byAgent) {
|
|
@@ -2193,21 +2284,21 @@ var listCommand = new Command4("list").description("List installed skills").opti
|
|
|
2193
2284
|
).length;
|
|
2194
2285
|
const orgCount = new Set(uniqueSkills.map((s2) => s2.organization)).size;
|
|
2195
2286
|
const agentCount = new Set(skills.map((s2) => s2.agent.id)).size;
|
|
2196
|
-
|
|
2197
|
-
|
|
2287
|
+
p6.log.info(
|
|
2288
|
+
pc7.dim(
|
|
2198
2289
|
`${uniqueCount} unique skill${uniqueCount !== 1 ? "s" : ""}, ${orgCount} organization${orgCount !== 1 ? "s" : ""}, ${agentCount} agent${agentCount !== 1 ? "s" : ""}, ${globalCount} global, ${projectCount} project`
|
|
2199
2290
|
)
|
|
2200
2291
|
);
|
|
2201
|
-
|
|
2292
|
+
p6.outro(pc7.dim("Done"));
|
|
2202
2293
|
}
|
|
2203
2294
|
);
|
|
2204
2295
|
|
|
2205
2296
|
// src/commands/status.ts
|
|
2206
|
-
import * as
|
|
2207
|
-
import { Command as
|
|
2208
|
-
import
|
|
2297
|
+
import * as p7 from "@clack/prompts";
|
|
2298
|
+
import { Command as Command6 } from "commander";
|
|
2299
|
+
import pc8 from "picocolors";
|
|
2209
2300
|
function formatDate(dateStr) {
|
|
2210
|
-
if (!dateStr) return
|
|
2301
|
+
if (!dateStr) return pc8.dim("unknown");
|
|
2211
2302
|
try {
|
|
2212
2303
|
const date = new Date(dateStr);
|
|
2213
2304
|
return date.toLocaleDateString("en-US", {
|
|
@@ -2218,7 +2309,7 @@ function formatDate(dateStr) {
|
|
|
2218
2309
|
minute: "2-digit"
|
|
2219
2310
|
});
|
|
2220
2311
|
} catch {
|
|
2221
|
-
return
|
|
2312
|
+
return pc8.dim("invalid");
|
|
2222
2313
|
}
|
|
2223
2314
|
}
|
|
2224
2315
|
function groupByOrganization(skills) {
|
|
@@ -2230,16 +2321,16 @@ function groupByOrganization(skills) {
|
|
|
2230
2321
|
}
|
|
2231
2322
|
return groups;
|
|
2232
2323
|
}
|
|
2233
|
-
var statusCommand = new
|
|
2324
|
+
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
2325
|
async (organizationSlug, options) => {
|
|
2235
2326
|
printCompactBanner();
|
|
2236
|
-
|
|
2327
|
+
p7.intro(pc8.bgCyan(pc8.black(" Check for Updates ")));
|
|
2237
2328
|
const token = getToken();
|
|
2238
2329
|
if (!token) {
|
|
2239
|
-
|
|
2240
|
-
`Not authenticated. Run ${
|
|
2330
|
+
p7.log.error(
|
|
2331
|
+
`Not authenticated. Run ${pc8.cyan("npx skillstogether auth login")} first.`
|
|
2241
2332
|
);
|
|
2242
|
-
|
|
2333
|
+
p7.outro(pc8.red("Authentication required"));
|
|
2243
2334
|
process.exit(1);
|
|
2244
2335
|
}
|
|
2245
2336
|
let scope;
|
|
@@ -2248,7 +2339,7 @@ var statusCommand = new Command5("status").description("Check for skill updates"
|
|
|
2248
2339
|
} else if (options.project && !options.global) {
|
|
2249
2340
|
scope = "project";
|
|
2250
2341
|
}
|
|
2251
|
-
const s =
|
|
2342
|
+
const s = p7.spinner();
|
|
2252
2343
|
s.start("Scanning installed skills...");
|
|
2253
2344
|
const installedSkills = scanUniqueSkills({
|
|
2254
2345
|
scope,
|
|
@@ -2256,17 +2347,17 @@ var statusCommand = new Command5("status").description("Check for skill updates"
|
|
|
2256
2347
|
});
|
|
2257
2348
|
if (installedSkills.length === 0) {
|
|
2258
2349
|
s.stop("No installed skills found");
|
|
2259
|
-
|
|
2260
|
-
|
|
2350
|
+
p7.log.info(
|
|
2351
|
+
pc8.dim("Install skills with: npx skillstogether add <org-slug>")
|
|
2261
2352
|
);
|
|
2262
|
-
|
|
2353
|
+
p7.outro(pc8.dim("Done"));
|
|
2263
2354
|
return;
|
|
2264
2355
|
}
|
|
2265
2356
|
s.stop(
|
|
2266
|
-
`Found ${
|
|
2357
|
+
`Found ${pc8.green(installedSkills.length.toString())} installed skill${installedSkills.length !== 1 ? "s" : ""}`
|
|
2267
2358
|
);
|
|
2268
2359
|
const byOrg = groupByOrganization(installedSkills);
|
|
2269
|
-
const checkSpinner =
|
|
2360
|
+
const checkSpinner = p7.spinner();
|
|
2270
2361
|
checkSpinner.start("Checking for updates...");
|
|
2271
2362
|
const allUpdates = [];
|
|
2272
2363
|
const errors = [];
|
|
@@ -2291,57 +2382,57 @@ var statusCommand = new Command5("status").description("Check for skill updates"
|
|
|
2291
2382
|
);
|
|
2292
2383
|
if (outdatedSkills.length > 0) {
|
|
2293
2384
|
console.log();
|
|
2294
|
-
|
|
2295
|
-
`${
|
|
2385
|
+
p7.log.warn(
|
|
2386
|
+
`${pc8.yellow(outdatedSkills.length.toString())} skill${outdatedSkills.length !== 1 ? "s" : ""} ${outdatedSkills.length !== 1 ? "have" : "has"} updates available:`
|
|
2296
2387
|
);
|
|
2297
2388
|
for (const { org, updates } of allUpdates) {
|
|
2298
2389
|
const orgOutdated = updates.filter((u) => u.hasUpdate);
|
|
2299
2390
|
if (orgOutdated.length === 0) continue;
|
|
2300
2391
|
console.log();
|
|
2301
|
-
console.log(
|
|
2392
|
+
console.log(pc8.cyan(` ${org}/`));
|
|
2302
2393
|
for (const update of orgOutdated) {
|
|
2303
|
-
console.log(` ${
|
|
2394
|
+
console.log(` ${pc8.yellow("\u2191")} ${pc8.white(update.name)}`);
|
|
2304
2395
|
console.log(
|
|
2305
|
-
` Installed: ${
|
|
2396
|
+
` Installed: ${pc8.dim(formatDate(update.installedAt))}`
|
|
2306
2397
|
);
|
|
2307
2398
|
console.log(
|
|
2308
|
-
` Available: ${
|
|
2399
|
+
` Available: ${pc8.green(formatDate(update.updatedAt))} ${pc8.dim(`(v${update.currentVersion})`)}`
|
|
2309
2400
|
);
|
|
2310
2401
|
}
|
|
2311
2402
|
}
|
|
2312
2403
|
console.log();
|
|
2313
|
-
|
|
2314
|
-
`Run ${
|
|
2404
|
+
p7.log.info(
|
|
2405
|
+
`Run ${pc8.cyan("npx skillstogether update")} to update all skills`
|
|
2315
2406
|
);
|
|
2316
2407
|
if (organizationSlug) {
|
|
2317
|
-
|
|
2318
|
-
`Or ${
|
|
2408
|
+
p7.log.info(
|
|
2409
|
+
`Or ${pc8.cyan(`npx skillstogether update ${organizationSlug}`)} to update this organization only`
|
|
2319
2410
|
);
|
|
2320
2411
|
}
|
|
2321
2412
|
} else {
|
|
2322
|
-
|
|
2323
|
-
`All ${
|
|
2413
|
+
p7.log.success(
|
|
2414
|
+
`All ${pc8.green(upToDateSkills.length.toString())} skill${upToDateSkills.length !== 1 ? "s are" : " is"} up to date!`
|
|
2324
2415
|
);
|
|
2325
2416
|
}
|
|
2326
2417
|
if (errors.length > 0) {
|
|
2327
2418
|
console.log();
|
|
2328
|
-
|
|
2419
|
+
p7.log.error(
|
|
2329
2420
|
`Failed to check ${errors.length} organization${errors.length !== 1 ? "s" : ""}:`
|
|
2330
2421
|
);
|
|
2331
2422
|
for (const error of errors) {
|
|
2332
|
-
console.log(` ${
|
|
2423
|
+
console.log(` ${pc8.red("\u2022")} ${error}`);
|
|
2333
2424
|
}
|
|
2334
2425
|
}
|
|
2335
|
-
|
|
2426
|
+
p7.outro(pc8.dim("Done"));
|
|
2336
2427
|
}
|
|
2337
2428
|
);
|
|
2338
2429
|
|
|
2339
2430
|
// src/commands/uninstall.ts
|
|
2340
|
-
import * as
|
|
2341
|
-
import { Command as
|
|
2431
|
+
import * as p8 from "@clack/prompts";
|
|
2432
|
+
import { Command as Command7 } from "commander";
|
|
2342
2433
|
import { rmSync } from "fs";
|
|
2343
2434
|
import { dirname as dirname2 } from "path";
|
|
2344
|
-
import
|
|
2435
|
+
import pc9 from "picocolors";
|
|
2345
2436
|
function removeSkill(skill) {
|
|
2346
2437
|
try {
|
|
2347
2438
|
const skillDir = dirname2(skill.path);
|
|
@@ -2354,10 +2445,13 @@ function removeSkill(skill) {
|
|
|
2354
2445
|
};
|
|
2355
2446
|
}
|
|
2356
2447
|
}
|
|
2357
|
-
var uninstallCommand = new
|
|
2448
|
+
var uninstallCommand = new Command7("uninstall").description("Remove installed skills").argument("<target>", "Organization slug").option("--all", "Remove all skills from the organization").option(
|
|
2449
|
+
"--skill <slug>",
|
|
2450
|
+
"Remove a specific skill by slug (already org-prefixed, e.g. acme-onboarding)"
|
|
2451
|
+
).option("--global", "Remove from global installation only").option("--project", "Remove from project installation only").option("-y, --yes", "Skip confirmation prompts").action(
|
|
2358
2452
|
async (target, options) => {
|
|
2359
2453
|
printCompactBanner();
|
|
2360
|
-
|
|
2454
|
+
p8.intro(pc9.bgCyan(pc9.black(" Uninstall Skills ")));
|
|
2361
2455
|
let scope;
|
|
2362
2456
|
if (options.global && !options.project) {
|
|
2363
2457
|
scope = "global";
|
|
@@ -2369,64 +2463,69 @@ var uninstallCommand = new Command6("uninstall").description("Remove installed s
|
|
|
2369
2463
|
parsed = parseUninstallTarget(target);
|
|
2370
2464
|
} catch (err) {
|
|
2371
2465
|
const msg = err instanceof Error && "message" in err ? err.message : "Invalid target format";
|
|
2372
|
-
|
|
2373
|
-
|
|
2466
|
+
p8.log.error(msg);
|
|
2467
|
+
p8.outro(pc9.red("Invalid format"));
|
|
2374
2468
|
process.exit(1);
|
|
2375
2469
|
}
|
|
2376
|
-
if (
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
);
|
|
2381
|
-
|
|
2382
|
-
|
|
2470
|
+
if (options.skill) {
|
|
2471
|
+
const skillResult = skillSlugSchema.safeParse(options.skill);
|
|
2472
|
+
if (!skillResult.success) {
|
|
2473
|
+
const msg = skillResult.error.issues?.[0]?.message ?? skillResult.error.message ?? "Invalid skill slug";
|
|
2474
|
+
p8.log.error(msg);
|
|
2475
|
+
p8.outro(pc9.red("Invalid format"));
|
|
2476
|
+
process.exit(1);
|
|
2477
|
+
}
|
|
2478
|
+
const expectedPrefix = `${parsed.organizationSlug}-`;
|
|
2479
|
+
if (!skillResult.data.startsWith(expectedPrefix)) {
|
|
2480
|
+
p8.log.error(
|
|
2481
|
+
`Skill slug must be prefixed with the organization slug (e.g., ${pc9.cyan(`${expectedPrefix}my-skill`)})`
|
|
2383
2482
|
);
|
|
2384
|
-
|
|
2483
|
+
p8.outro(pc9.red("Invalid format"));
|
|
2385
2484
|
process.exit(1);
|
|
2386
2485
|
}
|
|
2387
|
-
await uninstallOrganization(parsed.organizationSlug, scope, options.yes);
|
|
2388
|
-
} else {
|
|
2389
2486
|
await uninstallSkill(
|
|
2390
2487
|
parsed.organizationSlug,
|
|
2391
|
-
|
|
2488
|
+
skillResult.data,
|
|
2392
2489
|
scope,
|
|
2393
2490
|
options.yes
|
|
2394
2491
|
);
|
|
2492
|
+
return;
|
|
2395
2493
|
}
|
|
2494
|
+
await uninstallOrganization(parsed.organizationSlug, scope, options.yes);
|
|
2396
2495
|
}
|
|
2397
2496
|
);
|
|
2398
2497
|
async function uninstallOrganization(organizationSlug, scope, skipConfirm) {
|
|
2399
|
-
const s =
|
|
2400
|
-
s.start(`Finding skills from ${
|
|
2498
|
+
const s = p8.spinner();
|
|
2499
|
+
s.start(`Finding skills from ${pc9.cyan(organizationSlug)}...`);
|
|
2401
2500
|
const skills = scanInstalledSkills({ organization: organizationSlug, scope });
|
|
2402
2501
|
if (skills.length === 0) {
|
|
2403
|
-
s.stop(`No skills found from ${
|
|
2404
|
-
|
|
2502
|
+
s.stop(`No skills found from ${pc9.cyan(organizationSlug)}`);
|
|
2503
|
+
p8.outro(pc9.yellow("Nothing to uninstall"));
|
|
2405
2504
|
return;
|
|
2406
2505
|
}
|
|
2407
2506
|
s.stop(
|
|
2408
|
-
`Found ${
|
|
2507
|
+
`Found ${pc9.green(skills.length.toString())} skill${skills.length !== 1 ? "s" : ""} from ${pc9.cyan(organizationSlug)}`
|
|
2409
2508
|
);
|
|
2410
2509
|
console.log();
|
|
2411
|
-
|
|
2510
|
+
p8.log.info("Skills to remove:");
|
|
2412
2511
|
for (const skill of skills) {
|
|
2413
|
-
const scopeBadge = skill.scope === "global" ?
|
|
2512
|
+
const scopeBadge = skill.scope === "global" ? pc9.yellow("(global)") : pc9.dim("(project)");
|
|
2414
2513
|
console.log(
|
|
2415
|
-
` ${
|
|
2514
|
+
` ${pc9.red("\u2022")} ${skill.name} ${pc9.dim(`[${skill.agent.name}]`)} ${scopeBadge}`
|
|
2416
2515
|
);
|
|
2417
2516
|
}
|
|
2418
2517
|
console.log();
|
|
2419
2518
|
if (!skipConfirm) {
|
|
2420
|
-
const confirmed = await
|
|
2519
|
+
const confirmed = await p8.confirm({
|
|
2421
2520
|
message: `Remove all ${skills.length} skill${skills.length !== 1 ? "s" : ""} from ${organizationSlug}?`,
|
|
2422
2521
|
initialValue: false
|
|
2423
2522
|
});
|
|
2424
|
-
if (
|
|
2425
|
-
|
|
2523
|
+
if (p8.isCancel(confirmed) || !confirmed) {
|
|
2524
|
+
p8.cancel("Uninstall cancelled");
|
|
2426
2525
|
process.exit(0);
|
|
2427
2526
|
}
|
|
2428
2527
|
}
|
|
2429
|
-
const removeSpinner =
|
|
2528
|
+
const removeSpinner = p8.spinner();
|
|
2430
2529
|
removeSpinner.start("Removing skills...");
|
|
2431
2530
|
let removed = 0;
|
|
2432
2531
|
let failed = 0;
|
|
@@ -2442,53 +2541,53 @@ async function uninstallOrganization(organizationSlug, scope, skipConfirm) {
|
|
|
2442
2541
|
}
|
|
2443
2542
|
removeSpinner.stop("Removal complete");
|
|
2444
2543
|
if (removed > 0) {
|
|
2445
|
-
|
|
2446
|
-
`Removed ${
|
|
2544
|
+
p8.log.success(
|
|
2545
|
+
`Removed ${pc9.green(removed.toString())} skill${removed !== 1 ? "s" : ""}`
|
|
2447
2546
|
);
|
|
2448
2547
|
}
|
|
2449
2548
|
if (failed > 0) {
|
|
2450
|
-
|
|
2451
|
-
`Failed to remove ${
|
|
2549
|
+
p8.log.error(
|
|
2550
|
+
`Failed to remove ${pc9.red(failed.toString())} skill${failed !== 1 ? "s" : ""}`
|
|
2452
2551
|
);
|
|
2453
2552
|
for (const error of errors) {
|
|
2454
|
-
|
|
2553
|
+
p8.log.error(pc9.dim(` ${error}`));
|
|
2455
2554
|
}
|
|
2456
2555
|
}
|
|
2457
|
-
|
|
2556
|
+
p8.outro(pc9.dim("Done"));
|
|
2458
2557
|
}
|
|
2459
2558
|
async function uninstallSkill(organizationSlug, skillSlug, scope, skipConfirm) {
|
|
2460
|
-
const s =
|
|
2461
|
-
s.start(`Finding ${
|
|
2559
|
+
const s = p8.spinner();
|
|
2560
|
+
s.start(`Finding ${pc9.cyan(`${organizationSlug}/${skillSlug}`)}...`);
|
|
2462
2561
|
const instances = findSkillInstances(organizationSlug, skillSlug, { scope });
|
|
2463
2562
|
if (instances.length === 0) {
|
|
2464
|
-
s.stop(`Skill ${
|
|
2465
|
-
|
|
2563
|
+
s.stop(`Skill ${pc9.cyan(`${organizationSlug}/${skillSlug}`)} not found`);
|
|
2564
|
+
p8.outro(pc9.yellow("Nothing to uninstall"));
|
|
2466
2565
|
return;
|
|
2467
2566
|
}
|
|
2468
2567
|
s.stop(
|
|
2469
|
-
`Found ${
|
|
2568
|
+
`Found ${pc9.green(instances.length.toString())} instance${instances.length !== 1 ? "s" : ""} of ${pc9.cyan(`${organizationSlug}/${skillSlug}`)}`
|
|
2470
2569
|
);
|
|
2471
2570
|
console.log();
|
|
2472
|
-
|
|
2571
|
+
p8.log.info("Instances to remove:");
|
|
2473
2572
|
for (const skill of instances) {
|
|
2474
|
-
const scopeBadge = skill.scope === "global" ?
|
|
2573
|
+
const scopeBadge = skill.scope === "global" ? pc9.yellow("(global)") : pc9.dim("(project)");
|
|
2475
2574
|
console.log(
|
|
2476
|
-
` ${
|
|
2575
|
+
` ${pc9.red("\u2022")} ${pc9.dim(`[${skill.agent.name}]`)} ${scopeBadge}`
|
|
2477
2576
|
);
|
|
2478
|
-
console.log(` ${
|
|
2577
|
+
console.log(` ${pc9.dim(shortenPath(skill.path))}`);
|
|
2479
2578
|
}
|
|
2480
2579
|
console.log();
|
|
2481
2580
|
if (!skipConfirm) {
|
|
2482
|
-
const confirmed = await
|
|
2581
|
+
const confirmed = await p8.confirm({
|
|
2483
2582
|
message: `Remove ${instances.length} instance${instances.length !== 1 ? "s" : ""} of ${organizationSlug}/${skillSlug}?`,
|
|
2484
2583
|
initialValue: false
|
|
2485
2584
|
});
|
|
2486
|
-
if (
|
|
2487
|
-
|
|
2585
|
+
if (p8.isCancel(confirmed) || !confirmed) {
|
|
2586
|
+
p8.cancel("Uninstall cancelled");
|
|
2488
2587
|
process.exit(0);
|
|
2489
2588
|
}
|
|
2490
2589
|
}
|
|
2491
|
-
const removeSpinner =
|
|
2590
|
+
const removeSpinner = p8.spinner();
|
|
2492
2591
|
removeSpinner.start("Removing skill...");
|
|
2493
2592
|
let removed = 0;
|
|
2494
2593
|
let failed = 0;
|
|
@@ -2504,26 +2603,26 @@ async function uninstallSkill(organizationSlug, skillSlug, scope, skipConfirm) {
|
|
|
2504
2603
|
}
|
|
2505
2604
|
removeSpinner.stop("Removal complete");
|
|
2506
2605
|
if (removed > 0) {
|
|
2507
|
-
|
|
2508
|
-
`Removed ${
|
|
2606
|
+
p8.log.success(
|
|
2607
|
+
`Removed ${pc9.green(removed.toString())} instance${removed !== 1 ? "s" : ""}`
|
|
2509
2608
|
);
|
|
2510
2609
|
}
|
|
2511
2610
|
if (failed > 0) {
|
|
2512
|
-
|
|
2513
|
-
`Failed to remove ${
|
|
2611
|
+
p8.log.error(
|
|
2612
|
+
`Failed to remove ${pc9.red(failed.toString())} instance${failed !== 1 ? "s" : ""}`
|
|
2514
2613
|
);
|
|
2515
2614
|
for (const error of errors) {
|
|
2516
|
-
|
|
2615
|
+
p8.log.error(pc9.dim(` ${error}`));
|
|
2517
2616
|
}
|
|
2518
2617
|
}
|
|
2519
|
-
|
|
2618
|
+
p8.outro(pc9.dim("Done"));
|
|
2520
2619
|
}
|
|
2521
2620
|
|
|
2522
2621
|
// src/commands/update.ts
|
|
2523
|
-
import * as
|
|
2524
|
-
import { Command as
|
|
2622
|
+
import * as p9 from "@clack/prompts";
|
|
2623
|
+
import { Command as Command8 } from "commander";
|
|
2525
2624
|
import { writeFileSync as writeFileSync3 } from "fs";
|
|
2526
|
-
import
|
|
2625
|
+
import pc10 from "picocolors";
|
|
2527
2626
|
function generateUpdatedContent(skill, organizationSlug) {
|
|
2528
2627
|
const frontmatter = generateFrontmatter({
|
|
2529
2628
|
name: skill.name,
|
|
@@ -2535,16 +2634,16 @@ function generateUpdatedContent(skill, organizationSlug) {
|
|
|
2535
2634
|
});
|
|
2536
2635
|
return frontmatter + "\n" + (skill.content || "");
|
|
2537
2636
|
}
|
|
2538
|
-
var updateCommand = new
|
|
2637
|
+
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
2638
|
async (target, options) => {
|
|
2540
2639
|
printCompactBanner();
|
|
2541
|
-
|
|
2640
|
+
p9.intro(pc10.bgCyan(pc10.black(" Update Skills ")));
|
|
2542
2641
|
const token = getToken();
|
|
2543
2642
|
if (!token) {
|
|
2544
|
-
|
|
2545
|
-
`Not authenticated. Run ${
|
|
2643
|
+
p9.log.error(
|
|
2644
|
+
`Not authenticated. Run ${pc10.cyan("npx skillstogether auth login")} first.`
|
|
2546
2645
|
);
|
|
2547
|
-
|
|
2646
|
+
p9.outro(pc10.red("Authentication required"));
|
|
2548
2647
|
process.exit(1);
|
|
2549
2648
|
}
|
|
2550
2649
|
let scope;
|
|
@@ -2562,12 +2661,12 @@ var updateCommand = new Command7("update").description("Update installed skills
|
|
|
2562
2661
|
skillSlug = parsed.skillSlug;
|
|
2563
2662
|
} catch (err) {
|
|
2564
2663
|
const msg = err instanceof Error && "message" in err ? err.message : "Invalid target format";
|
|
2565
|
-
|
|
2566
|
-
|
|
2664
|
+
p9.log.error(msg);
|
|
2665
|
+
p9.outro(pc10.red("Invalid format"));
|
|
2567
2666
|
process.exit(1);
|
|
2568
2667
|
}
|
|
2569
2668
|
}
|
|
2570
|
-
const s =
|
|
2669
|
+
const s = p9.spinner();
|
|
2571
2670
|
s.start("Scanning installed skills...");
|
|
2572
2671
|
const allInstalledSkills = scanInstalledSkills({
|
|
2573
2672
|
scope,
|
|
@@ -2579,15 +2678,15 @@ var updateCommand = new Command7("update").description("Update installed skills
|
|
|
2579
2678
|
}
|
|
2580
2679
|
if (skillsToCheck.length === 0) {
|
|
2581
2680
|
s.stop("No installed skills found");
|
|
2582
|
-
|
|
2583
|
-
|
|
2681
|
+
p9.log.info(
|
|
2682
|
+
pc10.dim("Install skills with: npx skillstogether add <org-slug>")
|
|
2584
2683
|
);
|
|
2585
|
-
|
|
2684
|
+
p9.outro(pc10.dim("Done"));
|
|
2586
2685
|
return;
|
|
2587
2686
|
}
|
|
2588
2687
|
const uniqueSkills = deduplicateSkills(skillsToCheck);
|
|
2589
2688
|
s.stop(
|
|
2590
|
-
`Found ${
|
|
2689
|
+
`Found ${pc10.green(uniqueSkills.length.toString())} installed skill${uniqueSkills.length !== 1 ? "s" : ""}`
|
|
2591
2690
|
);
|
|
2592
2691
|
const byOrg = /* @__PURE__ */ new Map();
|
|
2593
2692
|
for (const skill of uniqueSkills) {
|
|
@@ -2595,7 +2694,7 @@ var updateCommand = new Command7("update").description("Update installed skills
|
|
|
2595
2694
|
existing.push(skill);
|
|
2596
2695
|
byOrg.set(skill.organization, existing);
|
|
2597
2696
|
}
|
|
2598
|
-
const checkSpinner =
|
|
2697
|
+
const checkSpinner = p9.spinner();
|
|
2599
2698
|
checkSpinner.start("Checking for updates...");
|
|
2600
2699
|
const skillsToUpdate = [];
|
|
2601
2700
|
const errors = [];
|
|
@@ -2624,17 +2723,17 @@ var updateCommand = new Command7("update").description("Update installed skills
|
|
|
2624
2723
|
}
|
|
2625
2724
|
checkSpinner.stop("Update check complete");
|
|
2626
2725
|
if (skillsToUpdate.length === 0) {
|
|
2627
|
-
|
|
2726
|
+
p9.log.success("All skills are up to date!");
|
|
2628
2727
|
if (errors.length > 0) {
|
|
2629
2728
|
console.log();
|
|
2630
|
-
|
|
2729
|
+
p9.log.error(
|
|
2631
2730
|
`Failed to check ${errors.length} organization${errors.length !== 1 ? "s" : ""}:`
|
|
2632
2731
|
);
|
|
2633
2732
|
for (const error of errors) {
|
|
2634
|
-
console.log(` ${
|
|
2733
|
+
console.log(` ${pc10.red("\u2022")} ${error}`);
|
|
2635
2734
|
}
|
|
2636
2735
|
}
|
|
2637
|
-
|
|
2736
|
+
p9.outro(pc10.dim("Done"));
|
|
2638
2737
|
return;
|
|
2639
2738
|
}
|
|
2640
2739
|
const totalInstances = skillsToUpdate.reduce(
|
|
@@ -2642,33 +2741,33 @@ var updateCommand = new Command7("update").description("Update installed skills
|
|
|
2642
2741
|
0
|
|
2643
2742
|
);
|
|
2644
2743
|
console.log();
|
|
2645
|
-
const updateMsg = skillsToUpdate.length === totalInstances ? `${
|
|
2646
|
-
|
|
2744
|
+
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:`;
|
|
2745
|
+
p9.log.info(updateMsg);
|
|
2647
2746
|
for (const { unique, remoteVersion } of skillsToUpdate) {
|
|
2648
2747
|
const agentNames = unique.agents.map((a) => a.name).join(", ");
|
|
2649
|
-
const scopeBadge = unique.scope === "global" ?
|
|
2748
|
+
const scopeBadge = unique.scope === "global" ? pc10.yellow("(global)") : pc10.dim("(project)");
|
|
2650
2749
|
console.log(
|
|
2651
|
-
` ${
|
|
2750
|
+
` ${pc10.yellow("\u2191")} ${pc10.white(`${unique.organization}/${unique.slug}`)} ${pc10.dim(`v${unique.version || "?"}`)} \u2192 ${pc10.green(`v${remoteVersion}`)} ${pc10.dim(`[${agentNames}]`)} ${scopeBadge}`
|
|
2652
2751
|
);
|
|
2653
2752
|
}
|
|
2654
2753
|
console.log();
|
|
2655
2754
|
if (options.dryRun) {
|
|
2656
|
-
|
|
2657
|
-
|
|
2755
|
+
p9.log.info(pc10.dim("Dry run - no changes made"));
|
|
2756
|
+
p9.outro(pc10.dim("Done"));
|
|
2658
2757
|
return;
|
|
2659
2758
|
}
|
|
2660
2759
|
if (!options.yes) {
|
|
2661
2760
|
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
|
|
2761
|
+
const confirmed = await p9.confirm({
|
|
2663
2762
|
message: confirmMsg,
|
|
2664
2763
|
initialValue: true
|
|
2665
2764
|
});
|
|
2666
|
-
if (
|
|
2667
|
-
|
|
2765
|
+
if (p9.isCancel(confirmed) || !confirmed) {
|
|
2766
|
+
p9.cancel("Update cancelled");
|
|
2668
2767
|
process.exit(0);
|
|
2669
2768
|
}
|
|
2670
2769
|
}
|
|
2671
|
-
const updateSpinner =
|
|
2770
|
+
const updateSpinner = p9.spinner();
|
|
2672
2771
|
updateSpinner.start("Updating skills...");
|
|
2673
2772
|
let updatedSkills = 0;
|
|
2674
2773
|
let updatedInstances = 0;
|
|
@@ -2692,23 +2791,23 @@ var updateCommand = new Command7("update").description("Update installed skills
|
|
|
2692
2791
|
}
|
|
2693
2792
|
updateSpinner.stop("Update complete");
|
|
2694
2793
|
if (updatedSkills > 0) {
|
|
2695
|
-
const summaryMsg = updatedSkills === updatedInstances ? `Updated ${
|
|
2696
|
-
|
|
2794
|
+
const summaryMsg = updatedSkills === updatedInstances ? `Updated ${pc10.green(updatedSkills.toString())} skill${updatedSkills !== 1 ? "s" : ""}` : `Updated ${pc10.green(updatedSkills.toString())} skill${updatedSkills !== 1 ? "s" : ""} (${updatedInstances} installations)`;
|
|
2795
|
+
p9.log.success(summaryMsg);
|
|
2697
2796
|
}
|
|
2698
2797
|
if (failed > 0) {
|
|
2699
|
-
|
|
2700
|
-
`Failed to update ${
|
|
2798
|
+
p9.log.error(
|
|
2799
|
+
`Failed to update ${pc10.red(failed.toString())} skill${failed !== 1 ? "s" : ""}`
|
|
2701
2800
|
);
|
|
2702
2801
|
for (const error of updateErrors) {
|
|
2703
|
-
console.log(` ${
|
|
2802
|
+
console.log(` ${pc10.red("\u2022")} ${error}`);
|
|
2704
2803
|
}
|
|
2705
2804
|
}
|
|
2706
|
-
|
|
2805
|
+
p9.outro(pc10.dim("Done"));
|
|
2707
2806
|
}
|
|
2708
2807
|
);
|
|
2709
2808
|
|
|
2710
2809
|
// src/index.ts
|
|
2711
|
-
var program = new
|
|
2810
|
+
var program = new Command9();
|
|
2712
2811
|
program.name("skillstogether").description("CLI tool to install organization skills").version("0.1.0").hook("preAction", (thisCommand) => {
|
|
2713
2812
|
const commandName = thisCommand.name();
|
|
2714
2813
|
if (commandName === "skillstogether") {
|
|
@@ -2724,6 +2823,7 @@ program.helpInformation = function() {
|
|
|
2724
2823
|
program.addCommand(authCommand);
|
|
2725
2824
|
program.addCommand(addCommand);
|
|
2726
2825
|
program.addCommand(doctorCommand);
|
|
2826
|
+
program.addCommand(feedbackCommand);
|
|
2727
2827
|
program.addCommand(listCommand);
|
|
2728
2828
|
program.addCommand(statusCommand);
|
|
2729
2829
|
program.addCommand(uninstallCommand);
|