@agentver/cli 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/agentver.js CHANGED
@@ -2,10 +2,10 @@
2
2
 
3
3
  // bin/agentver.ts
4
4
  import { createRequire as createRequire2 } from "module";
5
- import { dirname as dirname6, join as join23 } from "path";
5
+ import { dirname as dirname7, join as join26 } from "path";
6
6
  import { fileURLToPath as fileURLToPath2 } from "url";
7
7
  import { Command } from "commander";
8
- import chalk28 from "chalk";
8
+ import chalk33 from "chalk";
9
9
  import updateNotifier from "update-notifier";
10
10
 
11
11
  // src/commands/adopt.ts
@@ -960,7 +960,8 @@ var manifestV2PackageSchema = z.object({
960
960
  source: packageSourceSchema,
961
961
  agents: z.array(z.string()).default([]),
962
962
  installedAt: z.string().datetime(),
963
- modified: z.boolean().default(false)
963
+ modified: z.boolean().default(false),
964
+ pinned: z.boolean().optional()
964
965
  });
965
966
  var manifestV2Schema = z.object({
966
967
  version: z.literal(2),
@@ -1147,7 +1148,8 @@ var statusResultSchema = z2.object({
1147
1148
  name: z2.string(),
1148
1149
  status: z2.string(),
1149
1150
  modified: z2.boolean(),
1150
- upstream: z2.boolean()
1151
+ upstream: z2.boolean(),
1152
+ pinned: z2.boolean().optional()
1151
1153
  })),
1152
1154
  summary: z2.object({
1153
1155
  total: z2.number(),
@@ -1205,6 +1207,39 @@ var adoptResultSchema = z2.object({
1205
1207
  reason: z2.string()
1206
1208
  }))
1207
1209
  });
1210
+ var infoResultSchema = z2.object({
1211
+ name: z2.string(),
1212
+ source: z2.object({
1213
+ type: z2.string(),
1214
+ uri: z2.string().optional(),
1215
+ ref: z2.string().optional(),
1216
+ commit: z2.string().optional(),
1217
+ hostname: z2.string().optional()
1218
+ }),
1219
+ agents: z2.array(z2.string()),
1220
+ installedAt: z2.string(),
1221
+ modified: z2.boolean(),
1222
+ integrity: z2.string().optional(),
1223
+ files: z2.object({
1224
+ count: z2.number(),
1225
+ totalSize: z2.number()
1226
+ }),
1227
+ skill: z2.object({
1228
+ title: z2.string(),
1229
+ description: z2.string()
1230
+ }).optional()
1231
+ });
1232
+ var doctorCheckSchema = z2.object({
1233
+ name: z2.string(),
1234
+ status: z2.enum(["pass", "fail", "warn"]),
1235
+ message: z2.string()
1236
+ });
1237
+ var doctorResultSchema = z2.object({
1238
+ checks: z2.array(doctorCheckSchema),
1239
+ passed: z2.number(),
1240
+ failed: z2.number(),
1241
+ warnings: z2.number()
1242
+ });
1208
1243
 
1209
1244
  // ../shared/dist/errors.js
1210
1245
  var AgentverError = class extends Error {
@@ -1774,7 +1809,7 @@ function formatWithOptions(inspectOptions, ...args) {
1774
1809
  const first = args[0];
1775
1810
  let a = 0;
1776
1811
  let str = "";
1777
- let join24 = "";
1812
+ let join27 = "";
1778
1813
  if (typeof first === "string") {
1779
1814
  if (args.length === 1) {
1780
1815
  return first;
@@ -1873,7 +1908,7 @@ function formatWithOptions(inspectOptions, ...args) {
1873
1908
  }
1874
1909
  if (lastPos !== 0) {
1875
1910
  a++;
1876
- join24 = " ";
1911
+ join27 = " ";
1877
1912
  if (lastPos < first.length) {
1878
1913
  str += first.slice(lastPos);
1879
1914
  }
@@ -1881,9 +1916,9 @@ function formatWithOptions(inspectOptions, ...args) {
1881
1916
  }
1882
1917
  while (a < args.length) {
1883
1918
  const value = args[a];
1884
- str += join24;
1919
+ str += join27;
1885
1920
  str += typeof value !== "string" ? inspect(value, inspectOptions) : value;
1886
- join24 = " ";
1921
+ join27 = " ";
1887
1922
  a++;
1888
1923
  }
1889
1924
  return str;
@@ -2957,6 +2992,22 @@ var AGENTVER_EXTENSION_FIELDS = [
2957
2992
  "dependsOn",
2958
2993
  "conflictsWith"
2959
2994
  ];
2995
+ function parseSkillFrontmatter(content) {
2996
+ const { rawData, body, hasFrontmatter } = parseFrontmatter(content);
2997
+ if (!hasFrontmatter) {
2998
+ throw new Error("No YAML frontmatter found. Expected content delimited by --- markers.");
2999
+ }
3000
+ const parsed = agentverSkillSchema.safeParse(rawData);
3001
+ if (!parsed.success) {
3002
+ const messages = parsed.error.issues.map((issue) => {
3003
+ const path = issue.path.join(".");
3004
+ return path ? `${path}: ${issue.message}` : issue.message;
3005
+ });
3006
+ throw new Error(`Invalid SKILL.md frontmatter:
3007
+ ${messages.join("\n")}`);
3008
+ }
3009
+ return { frontmatter: parsed.data, body };
3010
+ }
2960
3011
  function validateSkillMd(content) {
2961
3012
  const errors = [];
2962
3013
  const warnings = [];
@@ -4526,6 +4577,9 @@ async function isAuthenticated() {
4526
4577
  // src/registry/config.ts
4527
4578
  var CONFIG_DIR = join7(homedir4(), ".agentver");
4528
4579
  var CONFIG_PATH = join7(CONFIG_DIR, "config.json");
4580
+ function getConfigPath() {
4581
+ return CONFIG_PATH;
4582
+ }
4529
4583
  function readConfig() {
4530
4584
  if (!existsSync6(CONFIG_PATH)) {
4531
4585
  return {};
@@ -4928,8 +4982,325 @@ Auditing ${packageNames.length} package${packageNames.length === 1 ? "" : "s"}..
4928
4982
  });
4929
4983
  }
4930
4984
 
4931
- // src/commands/diff.ts
4985
+ // src/commands/completion.ts
4986
+ import { appendFileSync, existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
4987
+ import { homedir as homedir6 } from "os";
4988
+ import { join as join10 } from "path";
4932
4989
  import chalk5 from "chalk";
4990
+ var TOP_LEVEL_COMMANDS = [
4991
+ "adopt",
4992
+ "audit",
4993
+ "completion",
4994
+ "config",
4995
+ "diff",
4996
+ "doctor",
4997
+ "draft",
4998
+ "info",
4999
+ "init",
5000
+ "install",
5001
+ "list",
5002
+ "log",
5003
+ "login",
5004
+ "logout",
5005
+ "publish",
5006
+ "remove",
5007
+ "save",
5008
+ "scan",
5009
+ "search",
5010
+ "status",
5011
+ "suggest",
5012
+ "suggestions",
5013
+ "sync",
5014
+ "update",
5015
+ "upgrade",
5016
+ "verify",
5017
+ "version",
5018
+ "whoami"
5019
+ ];
5020
+ var SUBCOMMANDS = {
5021
+ draft: ["create", "list", "switch", "publish", "discard"],
5022
+ version: ["create", "list"],
5023
+ config: ["list", "get", "set", "unset", "path"],
5024
+ completion: ["bash", "zsh", "fish"]
5025
+ };
5026
+ var COMMON_FLAGS = ["--json", "--global", "--dry-run", "--help"];
5027
+ function generateBashScript() {
5028
+ const subcmdCases = Object.entries(SUBCOMMANDS).map(
5029
+ ([cmd, subs]) => ` ${cmd})
5030
+ COMPREPLY=( $(compgen -W "${subs.join(" ")}" -- "$cur") )
5031
+ return 0
5032
+ ;;`
5033
+ ).join("\n");
5034
+ return `# agentver bash completion
5035
+ _agentver() {
5036
+ local cur prev commands
5037
+ COMPREPLY=()
5038
+ cur="\${COMP_WORDS[COMP_CWORD]}"
5039
+ prev="\${COMP_WORDS[COMP_CWORD-1]}"
5040
+ commands="${TOP_LEVEL_COMMANDS.join(" ")}"
5041
+
5042
+ if [[ "$COMP_CWORD" -eq 1 ]]; then
5043
+ COMPREPLY=( $(compgen -W "$commands" -- "$cur") )
5044
+ return 0
5045
+ fi
5046
+
5047
+ if [[ "$cur" == -* ]]; then
5048
+ COMPREPLY=( $(compgen -W "${COMMON_FLAGS.join(" ")}" -- "$cur") )
5049
+ return 0
5050
+ fi
5051
+
5052
+ case "$prev" in
5053
+ ${subcmdCases}
5054
+ esac
5055
+
5056
+ return 0
5057
+ }
5058
+
5059
+ complete -F _agentver agentver
5060
+ `;
5061
+ }
5062
+ function generateZshScript() {
5063
+ const subcmdCases = Object.entries(SUBCOMMANDS).map(
5064
+ ([cmd, subs]) => ` ${cmd})
5065
+ _values 'subcommand' ${subs.map((s) => `'${s}'`).join(" ")}
5066
+ ;;`
5067
+ ).join("\n");
5068
+ return `# agentver zsh completion
5069
+ _agentver() {
5070
+ local -a commands
5071
+ commands=(
5072
+ ${TOP_LEVEL_COMMANDS.map((c) => ` '${c}'`).join("\n")}
5073
+ )
5074
+
5075
+ _arguments -C '--json[Output results as structured JSON]' '--global[Apply globally]' '--dry-run[Preview changes without applying]' '--help[Show help]' '1:command:->cmd' '*::arg:->args'
5076
+
5077
+ case "$state" in
5078
+ cmd)
5079
+ _describe 'command' commands
5080
+ ;;
5081
+ args)
5082
+ case "\${words[1]}" in
5083
+ ${subcmdCases}
5084
+ esac
5085
+ ;;
5086
+ esac
5087
+ }
5088
+
5089
+ compdef _agentver agentver
5090
+ `;
5091
+ }
5092
+ function generateFishScript() {
5093
+ const topLevelCompletions = TOP_LEVEL_COMMANDS.map(
5094
+ (cmd) => `complete -c agentver -n '__fish_use_subcommand' -a '${cmd}'`
5095
+ ).join("\n");
5096
+ const subcmdCompletions = Object.entries(SUBCOMMANDS).flatMap(
5097
+ ([cmd, subs]) => subs.map((sub) => `complete -c agentver -n '__fish_seen_subcommand_from ${cmd}' -a '${sub}'`)
5098
+ ).join("\n");
5099
+ const flagCompletions = [
5100
+ "complete -c agentver -l json -d 'Output results as structured JSON'",
5101
+ "complete -c agentver -l global -d 'Apply globally'",
5102
+ "complete -c agentver -l dry-run -d 'Preview changes without applying'",
5103
+ "complete -c agentver -l help -d 'Show help'"
5104
+ ].join("\n");
5105
+ return `# agentver fish completion
5106
+ ${topLevelCompletions}
5107
+ ${subcmdCompletions}
5108
+ ${flagCompletions}
5109
+ `;
5110
+ }
5111
+ var SHELL_GENERATORS = {
5112
+ bash: generateBashScript,
5113
+ zsh: generateZshScript,
5114
+ fish: generateFishScript
5115
+ };
5116
+ var RC_PATHS = {
5117
+ bash: join10(homedir6(), ".bashrc"),
5118
+ zsh: join10(homedir6(), ".zshrc"),
5119
+ fish: join10(homedir6(), ".config", "fish", "config.fish")
5120
+ };
5121
+ var EVAL_LINES = {
5122
+ bash: 'eval "$(agentver completion bash)"',
5123
+ zsh: 'eval "$(agentver completion zsh)"',
5124
+ fish: "agentver completion fish | source"
5125
+ };
5126
+ function installCompletion(shell) {
5127
+ const rcPath = RC_PATHS[shell];
5128
+ const evalLine = EVAL_LINES[shell];
5129
+ if (existsSync8(rcPath)) {
5130
+ const content = readFileSync7(rcPath, "utf-8");
5131
+ if (content.includes(evalLine)) {
5132
+ process.stdout.write(chalk5.dim(`Completion already installed in ${rcPath}
5133
+ `));
5134
+ return;
5135
+ }
5136
+ }
5137
+ appendFileSync(rcPath, `
5138
+ # agentver shell completion
5139
+ ${evalLine}
5140
+ `);
5141
+ process.stdout.write(
5142
+ chalk5.green(`Completion installed in ${rcPath}
5143
+ `) + chalk5.dim("Restart your shell or run: ") + chalk5.cyan(`source ${rcPath}`) + "\n"
5144
+ );
5145
+ }
5146
+ function registerCompletionCommand(program2) {
5147
+ program2.command("completion <shell>").description("Generate shell completion scripts (bash, zsh, fish)").option("--install", "Install the completion script to your shell RC file").action((shell, options) => {
5148
+ const jsonMode = isJSONMode();
5149
+ if (!["bash", "zsh", "fish"].includes(shell)) {
5150
+ if (jsonMode) {
5151
+ outputError("INVALID_SHELL", `Unsupported shell "${shell}". Supported: bash, zsh, fish`);
5152
+ process.exit(1);
5153
+ }
5154
+ process.stderr.write(
5155
+ chalk5.red(`Unsupported shell "${shell}". Supported: bash, zsh, fish
5156
+ `)
5157
+ );
5158
+ process.exit(1);
5159
+ }
5160
+ const validShell = shell;
5161
+ const script = SHELL_GENERATORS[validShell]();
5162
+ if (options.install) {
5163
+ if (jsonMode) {
5164
+ installCompletion(validShell);
5165
+ outputSuccess({ shell: validShell, installed: true, rcPath: RC_PATHS[validShell] });
5166
+ return;
5167
+ }
5168
+ installCompletion(validShell);
5169
+ return;
5170
+ }
5171
+ if (jsonMode) {
5172
+ outputSuccess({ shell: validShell, script });
5173
+ return;
5174
+ }
5175
+ process.stdout.write(script);
5176
+ });
5177
+ }
5178
+
5179
+ // src/commands/config.ts
5180
+ import chalk6 from "chalk";
5181
+ var KNOWN_KEYS = ["platformUrl", "defaultOrg", "telemetry"];
5182
+ function isKnownKey(key) {
5183
+ return KNOWN_KEYS.includes(key);
5184
+ }
5185
+ function formatValue2(value) {
5186
+ if (value === void 0 || value === null) return "";
5187
+ if (typeof value === "object") return JSON.stringify(value);
5188
+ return String(value);
5189
+ }
5190
+ function validateKey(key) {
5191
+ if (!isKnownKey(key)) {
5192
+ if (isJSONMode()) {
5193
+ outputError("INVALID_KEY", `Unknown config key: ${key}. Valid keys: ${KNOWN_KEYS.join(", ")}`);
5194
+ } else {
5195
+ console.error(chalk6.red(`Unknown config key: ${key}. Valid keys: ${KNOWN_KEYS.join(", ")}`));
5196
+ }
5197
+ return false;
5198
+ }
5199
+ return true;
5200
+ }
5201
+ function validateValue(key, value) {
5202
+ switch (key) {
5203
+ case "telemetry": {
5204
+ if (value !== "true" && value !== "false") {
5205
+ if (isJSONMode()) {
5206
+ outputError("INVALID_VALUE", "telemetry must be true or false");
5207
+ } else {
5208
+ console.error(chalk6.red("telemetry must be true or false"));
5209
+ }
5210
+ return { valid: false };
5211
+ }
5212
+ return { valid: true, parsed: value === "true" };
5213
+ }
5214
+ case "platformUrl": {
5215
+ if (!value.startsWith("https://")) {
5216
+ if (isJSONMode()) {
5217
+ outputError("INVALID_VALUE", "platformUrl must start with https://");
5218
+ } else {
5219
+ console.error(chalk6.red("platformUrl must start with https://"));
5220
+ }
5221
+ return { valid: false };
5222
+ }
5223
+ return { valid: true, parsed: value };
5224
+ }
5225
+ default:
5226
+ return { valid: true, parsed: value };
5227
+ }
5228
+ }
5229
+ function registerConfigCommand(program2) {
5230
+ const configCmd = program2.command("config").description("Manage CLI configuration");
5231
+ configCmd.command("list").description("Show all config values").option("--json", "Output as JSON").action(() => {
5232
+ const config = readConfig();
5233
+ const jsonMode = isJSONMode();
5234
+ if (jsonMode) {
5235
+ outputSuccess(config);
5236
+ return;
5237
+ }
5238
+ const entries = Object.entries(config);
5239
+ if (entries.length === 0) {
5240
+ console.log(chalk6.dim("No configuration set."));
5241
+ return;
5242
+ }
5243
+ console.log(chalk6.bold("\nConfiguration:\n"));
5244
+ for (const [key, value] of entries) {
5245
+ console.log(` ${chalk6.green(key)} = ${chalk6.cyan(formatValue2(value))}`);
5246
+ }
5247
+ console.log();
5248
+ });
5249
+ configCmd.command("get").description("Get a config value").argument("<key>", "Config key to read").option("--json", "Output as JSON").action((key) => {
5250
+ const jsonMode = isJSONMode();
5251
+ if (!validateKey(key)) {
5252
+ process.exit(1);
5253
+ }
5254
+ const config = readConfig();
5255
+ const value = config[key];
5256
+ if (jsonMode) {
5257
+ outputSuccess({ key, value: value ?? null });
5258
+ return;
5259
+ }
5260
+ if (value === void 0) {
5261
+ process.exit(0);
5262
+ }
5263
+ console.log(formatValue2(value));
5264
+ });
5265
+ configCmd.command("set").description("Set a config value").argument("<key>", "Config key to set").argument("<value>", "Value to set").option("--json", "Output as JSON").action((key, value) => {
5266
+ const jsonMode = isJSONMode();
5267
+ if (!validateKey(key)) {
5268
+ process.exit(1);
5269
+ }
5270
+ const validation = validateValue(key, value);
5271
+ if (!validation.valid) {
5272
+ process.exit(1);
5273
+ }
5274
+ const config = readConfig();
5275
+ const updated = { ...config, [key]: validation.parsed };
5276
+ writeConfig(updated);
5277
+ if (jsonMode) {
5278
+ outputSuccess({ key, value: validation.parsed });
5279
+ return;
5280
+ }
5281
+ console.log(chalk6.green(`Set ${key} = ${formatValue2(validation.parsed)}`));
5282
+ });
5283
+ configCmd.command("unset").description("Remove a config key").argument("<key>", "Config key to remove").option("--json", "Output as JSON").action((key) => {
5284
+ const jsonMode = isJSONMode();
5285
+ if (!validateKey(key)) {
5286
+ process.exit(1);
5287
+ }
5288
+ const config = readConfig();
5289
+ delete config[key];
5290
+ writeConfig(config);
5291
+ if (jsonMode) {
5292
+ outputSuccess({ key, removed: true });
5293
+ return;
5294
+ }
5295
+ console.log(chalk6.green(`Removed ${key}`));
5296
+ });
5297
+ configCmd.command("path").description("Print the config file path").action(() => {
5298
+ console.log(getConfigPath());
5299
+ });
5300
+ }
5301
+
5302
+ // src/commands/diff.ts
5303
+ import chalk7 from "chalk";
4933
5304
 
4934
5305
  // src/git/resolver.ts
4935
5306
  var logger4 = createLogger("git:resolver");
@@ -5314,17 +5685,17 @@ function diffFiles(upstreamFiles, localFiles) {
5314
5685
  function formatDiff(diffs) {
5315
5686
  const output = [];
5316
5687
  for (const diff of diffs) {
5317
- output.push(chalk5.bold(`--- a/${diff.path}`));
5318
- output.push(chalk5.bold(`+++ b/${diff.path}`));
5688
+ output.push(chalk7.bold(`--- a/${diff.path}`));
5689
+ output.push(chalk7.bold(`+++ b/${diff.path}`));
5319
5690
  for (const hunk of diff.hunks) {
5320
5691
  output.push(
5321
- chalk5.cyan(`@@ -${hunk.oldStart},${hunk.oldCount} +${hunk.newStart},${hunk.newCount} @@`)
5692
+ chalk7.cyan(`@@ -${hunk.oldStart},${hunk.oldCount} +${hunk.newStart},${hunk.newCount} @@`)
5322
5693
  );
5323
5694
  for (const line of hunk.lines) {
5324
5695
  if (line.startsWith("+")) {
5325
- output.push(chalk5.green(line));
5696
+ output.push(chalk7.green(line));
5326
5697
  } else if (line.startsWith("-")) {
5327
- output.push(chalk5.red(line));
5698
+ output.push(chalk7.red(line));
5328
5699
  } else {
5329
5700
  output.push(line);
5330
5701
  }
@@ -5346,7 +5717,7 @@ function registerDiffCommand(program2) {
5346
5717
  outputError("NOT_INSTALLED", `Package "${name}" is not installed.`);
5347
5718
  process.exit(1);
5348
5719
  }
5349
- console.error(chalk5.red(`Package "${name}" is not installed.`));
5720
+ console.error(chalk7.red(`Package "${name}" is not installed.`));
5350
5721
  process.exit(1);
5351
5722
  }
5352
5723
  const { source, agents } = manifestEntry;
@@ -5356,11 +5727,11 @@ function registerDiffCommand(program2) {
5356
5727
  process.exit(1);
5357
5728
  }
5358
5729
  console.error(
5359
- chalk5.red(
5730
+ chalk7.red(
5360
5731
  `Package "${name}" was installed from a well-known source (${source.hostname}).`
5361
5732
  )
5362
5733
  );
5363
- console.error(chalk5.dim("Diff is not yet supported for well-known sources."));
5734
+ console.error(chalk7.dim("Diff is not yet supported for well-known sources."));
5364
5735
  process.exit(1);
5365
5736
  }
5366
5737
  if (source.uri === "unknown") {
@@ -5372,11 +5743,11 @@ function registerDiffCommand(program2) {
5372
5743
  process.exit(1);
5373
5744
  }
5374
5745
  console.error(
5375
- chalk5.red(`Package "${name}" was migrated from v1 and has no known Git source.`)
5746
+ chalk7.red(`Package "${name}" was migrated from v1 and has no known Git source.`)
5376
5747
  );
5377
5748
  console.error(
5378
- chalk5.dim("Reinstall it using a Git source URL to enable diff:\n") + chalk5.dim(` agentver remove ${name}
5379
- `) + chalk5.dim(` agentver install <git-source>`)
5749
+ chalk7.dim("Reinstall it using a Git source URL to enable diff:\n") + chalk7.dim(` agentver remove ${name}
5750
+ `) + chalk7.dim(` agentver install <git-source>`)
5380
5751
  );
5381
5752
  process.exit(1);
5382
5753
  }
@@ -5430,7 +5801,7 @@ function registerDiffCommand(program2) {
5430
5801
  return;
5431
5802
  }
5432
5803
  if (diffs.length === 0) {
5433
- console.log(chalk5.green("No differences found."));
5804
+ console.log(chalk7.green("No differences found."));
5434
5805
  return;
5435
5806
  }
5436
5807
  console.log(formatDiff(diffs));
@@ -5446,132 +5817,449 @@ function registerDiffCommand(program2) {
5446
5817
  });
5447
5818
  }
5448
5819
 
5449
- // src/commands/draft.ts
5450
- import { existsSync as existsSync8, readFileSync as readFileSync7 } from "fs";
5451
- import { basename as basename2, join as join10 } from "path";
5452
- import chalk6 from "chalk";
5453
- import ora2 from "ora";
5454
-
5455
- // src/registry/platform.ts
5456
- var DEFAULT_TIMEOUT_MS = 1e4;
5457
- async function platformFetch(path, options = {}) {
5458
- const platformUrl = getPlatformUrl();
5459
- if (!platformUrl) {
5460
- throw new AgentverError(
5461
- "UNAUTHORISED",
5462
- "No platform URL configured. Run `agentver login <url>` to connect."
5463
- );
5820
+ // src/commands/doctor.ts
5821
+ import { execSync } from "child_process";
5822
+ import { existsSync as existsSync9, lstatSync as lstatSync2, readFileSync as readFileSync8, readlinkSync as readlinkSync2 } from "fs";
5823
+ import { dirname as dirname4, join as join11 } from "path";
5824
+ import chalk8 from "chalk";
5825
+ var MANIFEST_DIR2 = ".agentver";
5826
+ var MANIFEST_FILE2 = "manifest.json";
5827
+ var LOCKFILE_FILE2 = "lockfile.json";
5828
+ var NETWORK_TIMEOUT_MS = 3e3;
5829
+ var MIN_NODE_VERSION = 20;
5830
+ function check(name, status, message) {
5831
+ return { name, status, message };
5832
+ }
5833
+ function checkManifestIntegrity(projectRoot) {
5834
+ const manifestPath = join11(projectRoot, MANIFEST_DIR2, MANIFEST_FILE2);
5835
+ if (!existsSync9(manifestPath)) {
5836
+ return check("manifest-integrity", "warn", "Manifest file not found (no skills installed yet)");
5837
+ }
5838
+ let raw;
5839
+ try {
5840
+ raw = readFileSync8(manifestPath, "utf-8");
5841
+ } catch {
5842
+ return check("manifest-integrity", "fail", "Cannot read manifest file");
5464
5843
  }
5465
- const credentials = await getCredentials();
5466
- if (!credentials?.token && !credentials?.apiKey) {
5467
- throw new AgentverError("UNAUTHORISED", "Not authenticated. Run `agentver login` to sign in.");
5844
+ let parsed;
5845
+ try {
5846
+ parsed = JSON.parse(raw);
5847
+ } catch {
5848
+ return check("manifest-integrity", "fail", "Manifest contains invalid JSON");
5468
5849
  }
5469
- const url = `${platformUrl}/api/v1${path}`;
5470
- const headers = {
5471
- "Content-Type": "application/json"
5472
- };
5473
- if (credentials.token) {
5474
- headers.Authorization = `Bearer ${credentials.token}`;
5475
- } else if (credentials.apiKey) {
5476
- headers["X-API-Key"] = credentials.apiKey;
5850
+ const result = manifestAnySchema.safeParse(parsed);
5851
+ if (!result.success) {
5852
+ return check("manifest-integrity", "fail", "Manifest does not match expected schema");
5477
5853
  }
5478
- const controller = new AbortController();
5479
- const timeoutMs = options.timeout ?? DEFAULT_TIMEOUT_MS;
5480
- const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
5854
+ return check("manifest-integrity", "pass", "Manifest is valid");
5855
+ }
5856
+ function checkLockfileIntegrity(projectRoot) {
5857
+ const lockfilePath = join11(projectRoot, MANIFEST_DIR2, LOCKFILE_FILE2);
5858
+ if (!existsSync9(lockfilePath)) {
5859
+ return check("lockfile-integrity", "warn", "Lockfile not found (no skills installed yet)");
5860
+ }
5861
+ let raw;
5481
5862
  try {
5482
- const response = await fetch(url, {
5483
- method: options.method ?? "GET",
5484
- headers,
5485
- body: options.body ? JSON.stringify(options.body) : void 0,
5486
- signal: controller.signal
5487
- });
5488
- if (!response.ok) {
5489
- const errorBody = await response.text().catch(() => "Unknown error");
5490
- throw new AgentverError("INTERNAL_ERROR", `Platform error (${response.status}): ${errorBody}`);
5491
- }
5492
- return response.json();
5493
- } finally {
5494
- clearTimeout(timeoutId);
5863
+ raw = readFileSync8(lockfilePath, "utf-8");
5864
+ } catch {
5865
+ return check("lockfile-integrity", "fail", "Cannot read lockfile");
5495
5866
  }
5496
- }
5497
- async function platformFetchSilent(path, options = {}) {
5867
+ let parsed;
5498
5868
  try {
5499
- return await platformFetch(path, options);
5869
+ parsed = JSON.parse(raw);
5500
5870
  } catch {
5501
- return null;
5871
+ return check("lockfile-integrity", "fail", "Lockfile contains invalid JSON");
5502
5872
  }
5873
+ const result = lockfileAnySchema.safeParse(parsed);
5874
+ if (!result.success) {
5875
+ return check("lockfile-integrity", "fail", "Lockfile does not match expected schema");
5876
+ }
5877
+ return check("lockfile-integrity", "pass", "Lockfile is valid");
5503
5878
  }
5504
-
5505
- // src/commands/draft.ts
5506
- function resolveSkillIdentity() {
5507
- const cwd = process.cwd();
5508
- const skillMdPath = join10(cwd, "SKILL.md");
5509
- let skillName = null;
5510
- if (existsSync8(skillMdPath)) {
5511
- const content = readFileSync7(skillMdPath, "utf-8");
5512
- const nameMatch = content.match(/^name:\s*(.+)$/m);
5513
- skillName = nameMatch?.[1]?.trim() ?? basename2(cwd);
5879
+ function checkManifestLockfileSync(projectRoot) {
5880
+ const manifest = readManifest(projectRoot);
5881
+ const lockfile = readLockfile(projectRoot);
5882
+ const manifestNames = new Set(Object.keys(manifest.packages));
5883
+ const lockfileNames = new Set(Object.keys(lockfile.packages));
5884
+ if (manifestNames.size === 0 && lockfileNames.size === 0) {
5885
+ return check("manifest-lockfile-sync", "pass", "Manifest and lockfile are in sync (both empty)");
5514
5886
  }
5515
- if (!skillName) {
5516
- skillName = basename2(cwd);
5887
+ const inManifestOnly = [];
5888
+ const inLockfileOnly = [];
5889
+ for (const name of manifestNames) {
5890
+ if (!lockfileNames.has(name)) {
5891
+ inManifestOnly.push(name);
5892
+ }
5517
5893
  }
5518
- const manifest = readManifest(cwd);
5519
- const entry = manifest.packages[skillName];
5520
- if (entry?.source.type === "git") {
5521
- const parts = entry.source.uri.split("/");
5522
- const org = parts.length >= 2 ? parts[parts.length - 2] : parts[0];
5523
- if (org) {
5524
- return { org, name: skillName };
5894
+ for (const name of lockfileNames) {
5895
+ if (!manifestNames.has(name)) {
5896
+ inLockfileOnly.push(name);
5525
5897
  }
5526
5898
  }
5527
- const pathParts = cwd.split("/");
5528
- const skillsIdx = pathParts.lastIndexOf("skills");
5529
- if (skillsIdx >= 0 && pathParts.length > skillsIdx + 2) {
5530
- return { org: pathParts[skillsIdx + 1], name: skillName };
5899
+ if (inManifestOnly.length > 0 || inLockfileOnly.length > 0) {
5900
+ const parts = [];
5901
+ if (inManifestOnly.length > 0) {
5902
+ parts.push(`in manifest but not lockfile: ${inManifestOnly.join(", ")}`);
5903
+ }
5904
+ if (inLockfileOnly.length > 0) {
5905
+ parts.push(`in lockfile but not manifest: ${inLockfileOnly.join(", ")}`);
5906
+ }
5907
+ return check("manifest-lockfile-sync", "fail", `Out of sync \u2014 ${parts.join("; ")}`);
5531
5908
  }
5532
- return null;
5909
+ return check("manifest-lockfile-sync", "pass", "Manifest and lockfile are in sync");
5533
5910
  }
5534
- function registerDraftCommand(program2) {
5535
- const draft = program2.command("draft").description("Manage skill drafts (branches)");
5536
- draft.command("create <name>").description("Create a draft branch for the current skill").option("--json", "Output as JSON").action(async (name, options) => {
5537
- const identity = resolveSkillIdentity();
5538
- if (!identity) {
5539
- process.stderr.write(
5540
- chalk6.red("Could not determine skill identity. Run this from a skill directory.\n")
5541
- );
5542
- process.exit(1);
5911
+ function checkSkillFilesExist(projectRoot) {
5912
+ const manifest = readManifest(projectRoot);
5913
+ const entries = Object.keys(manifest.packages);
5914
+ if (entries.length === 0) {
5915
+ return check("skill-files-exist", "pass", "No packages installed");
5916
+ }
5917
+ const missing = [];
5918
+ for (const name of entries) {
5919
+ const canonicalPath = getCanonicalSkillPath(projectRoot, name, "project");
5920
+ if (!existsSync9(canonicalPath) || !lstatSync2(canonicalPath).isDirectory()) {
5921
+ missing.push(name);
5543
5922
  }
5544
- const spinner = ora2(`Creating draft "${name}"...`).start();
5545
- try {
5546
- const result = await platformFetch(
5547
- `/skills/@${identity.org}/${identity.name}/drafts`,
5548
- {
5549
- method: "POST",
5550
- body: { name }
5923
+ }
5924
+ if (missing.length > 0) {
5925
+ return check("skill-files-exist", "fail", `Missing skill directories: ${missing.join(", ")}`);
5926
+ }
5927
+ return check("skill-files-exist", "pass", `All ${entries.length} skill directories present`);
5928
+ }
5929
+ function checkSymlinksValid(projectRoot) {
5930
+ const manifest = readManifest(projectRoot);
5931
+ const entries = Object.entries(manifest.packages);
5932
+ if (entries.length === 0) {
5933
+ return check("symlinks-valid", "pass", "No packages installed");
5934
+ }
5935
+ const broken = [];
5936
+ for (const [name, pkg2] of entries) {
5937
+ for (const agentId of pkg2.agents) {
5938
+ const placementPath = getSkillPlacementPath(agentId, name, "project");
5939
+ if (!placementPath) continue;
5940
+ const agentSkillPath = join11(projectRoot, placementPath);
5941
+ if (!existsSync9(agentSkillPath)) {
5942
+ broken.push(`${name}/${agentId}`);
5943
+ continue;
5944
+ }
5945
+ try {
5946
+ const stats = lstatSync2(agentSkillPath);
5947
+ if (stats.isSymbolicLink()) {
5948
+ const target = readlinkSync2(agentSkillPath);
5949
+ const resolvedTarget = join11(dirname4(agentSkillPath), target);
5950
+ if (!existsSync9(resolvedTarget)) {
5951
+ broken.push(`${name}/${agentId} (broken symlink)`);
5952
+ }
5551
5953
  }
5552
- );
5553
- if (options.json) {
5554
- spinner.stop();
5555
- console.log(JSON.stringify(result, null, 2));
5556
- } else {
5557
- spinner.succeed(
5558
- `Draft ${chalk6.green(result.name)} created on branch ${chalk6.cyan(result.branchName)}`
5559
- );
5954
+ } catch {
5955
+ broken.push(`${name}/${agentId} (unreadable)`);
5560
5956
  }
5561
- } catch (error) {
5562
- spinner.fail(
5563
- `Failed to create draft: ${error instanceof Error ? error.message : String(error)}`
5564
- );
5565
- process.exit(1);
5566
- }
5567
- });
5568
- draft.command("list").description("List open drafts for the current skill").option("--json", "Output as JSON").action(async (options) => {
5569
- const identity = resolveSkillIdentity();
5570
- if (!identity) {
5571
- process.stderr.write(
5572
- chalk6.red("Could not determine skill identity. Run this from a skill directory.\n")
5573
- );
5574
- process.exit(1);
5957
+ }
5958
+ }
5959
+ if (broken.length > 0) {
5960
+ return check("symlinks-valid", "fail", `Invalid symlinks: ${broken.join(", ")}`);
5961
+ }
5962
+ const totalLinks = entries.reduce((sum, [, pkg2]) => sum + pkg2.agents.length, 0);
5963
+ return check("symlinks-valid", "pass", `All ${totalLinks} symlinks valid`);
5964
+ }
5965
+ async function checkAuthentication() {
5966
+ const creds = await getCredentials();
5967
+ const hasCredentials = !!(creds?.token ?? creds?.apiKey);
5968
+ if (!hasCredentials) {
5969
+ return check("authentication", "warn", "No credentials configured (run agentver login)");
5970
+ }
5971
+ const platformUrl = getPlatformUrl();
5972
+ if (!platformUrl) {
5973
+ return check("authentication", "warn", "Credentials present but no platform URL configured");
5974
+ }
5975
+ try {
5976
+ const controller = new AbortController();
5977
+ const timeout = setTimeout(() => controller.abort(), NETWORK_TIMEOUT_MS);
5978
+ const response = await fetch(`${platformUrl}/health`, {
5979
+ signal: controller.signal
5980
+ });
5981
+ clearTimeout(timeout);
5982
+ if (response.ok) {
5983
+ return check("authentication", "pass", "Authenticated and platform reachable");
5984
+ }
5985
+ return check(
5986
+ "authentication",
5987
+ "warn",
5988
+ `Platform returned status ${String(response.status)} (offline mode available)`
5989
+ );
5990
+ } catch {
5991
+ return check("authentication", "warn", "Platform unreachable (offline mode available)");
5992
+ }
5993
+ }
5994
+ function checkGitAvailable() {
5995
+ try {
5996
+ execSync("git --version", { stdio: "pipe" });
5997
+ return check("git-available", "pass", "Git is available");
5998
+ } catch {
5999
+ return check("git-available", "fail", "Git is not installed or not on PATH");
6000
+ }
6001
+ }
6002
+ function checkNodeVersion() {
6003
+ const major = parseInt(process.versions.node.split(".")[0] ?? "0", 10);
6004
+ if (major >= MIN_NODE_VERSION) {
6005
+ return check(
6006
+ "node-version",
6007
+ "pass",
6008
+ `Node ${process.versions.node} (>= ${String(MIN_NODE_VERSION)})`
6009
+ );
6010
+ }
6011
+ return check(
6012
+ "node-version",
6013
+ "fail",
6014
+ `Node ${process.versions.node} is below minimum ${String(MIN_NODE_VERSION)}`
6015
+ );
6016
+ }
6017
+ function formatCheck(result) {
6018
+ switch (result.status) {
6019
+ case "pass":
6020
+ return ` ${chalk8.green("\u2713")} ${result.message}`;
6021
+ case "fail":
6022
+ return ` ${chalk8.red("\u2717")} ${result.message}`;
6023
+ case "warn":
6024
+ return ` ${chalk8.yellow("\u26A0")} ${result.message}`;
6025
+ }
6026
+ }
6027
+ function registerDoctorCommand(program2) {
6028
+ program2.command("doctor").description("Run health checks to diagnose common issues").option("--json", "Output as JSON").action(async (options) => {
6029
+ const jsonMode = isJSONMode() || options.json === true;
6030
+ const projectRoot = process.cwd();
6031
+ const checks = [];
6032
+ checks.push(checkManifestIntegrity(projectRoot));
6033
+ checks.push(checkLockfileIntegrity(projectRoot));
6034
+ checks.push(checkManifestLockfileSync(projectRoot));
6035
+ checks.push(checkSkillFilesExist(projectRoot));
6036
+ checks.push(checkSymlinksValid(projectRoot));
6037
+ checks.push(await checkAuthentication());
6038
+ checks.push(checkGitAvailable());
6039
+ checks.push(checkNodeVersion());
6040
+ const passed = checks.filter((c) => c.status === "pass").length;
6041
+ const failed = checks.filter((c) => c.status === "fail").length;
6042
+ const warnings = checks.filter((c) => c.status === "warn").length;
6043
+ if (jsonMode) {
6044
+ const result = { checks, passed, failed, warnings };
6045
+ outputSuccess(result);
6046
+ process.exit(failed > 0 ? 1 : 0);
6047
+ return;
6048
+ }
6049
+ console.log(chalk8.bold("\nHealth checks:\n"));
6050
+ for (const result of checks) {
6051
+ console.log(formatCheck(result));
6052
+ }
6053
+ console.log();
6054
+ console.log(
6055
+ chalk8.dim(
6056
+ `${chalk8.green(String(passed))} passed, ${chalk8.red(String(failed))} failed, ${chalk8.yellow(String(warnings))} warnings`
6057
+ )
6058
+ );
6059
+ console.log();
6060
+ process.exit(failed > 0 ? 1 : 0);
6061
+ });
6062
+ }
6063
+
6064
+ // src/commands/draft.ts
6065
+ import { existsSync as existsSync10, readFileSync as readFileSync9 } from "fs";
6066
+ import { basename as basename2, join as join12 } from "path";
6067
+ import chalk9 from "chalk";
6068
+ import ora2 from "ora";
6069
+
6070
+ // src/utils/retry.ts
6071
+ var MAX_RETRY_ATTEMPTS = 3;
6072
+ var RETRY_BASE_DELAY_MS = 1e3;
6073
+ var RequestTimeoutError = class extends Error {
6074
+ constructor(label) {
6075
+ super(`${label} request timed out. The service may be experiencing issues.`);
6076
+ this.name = "RequestTimeoutError";
6077
+ }
6078
+ };
6079
+ function isRetryable(error, response) {
6080
+ if (error instanceof RequestTimeoutError) return false;
6081
+ if (error instanceof DOMException && error.name === "AbortError") return false;
6082
+ if (!response) return true;
6083
+ return response.status >= 500;
6084
+ }
6085
+ function delay(ms) {
6086
+ return new Promise((resolve4) => setTimeout(resolve4, ms));
6087
+ }
6088
+ function isAuthExpired(status) {
6089
+ return status === 401;
6090
+ }
6091
+ async function fetchWithRetry(options) {
6092
+ let lastError;
6093
+ let lastResponse;
6094
+ for (let attempt = 1; attempt <= MAX_RETRY_ATTEMPTS; attempt++) {
6095
+ const controller = new AbortController();
6096
+ const timeoutId = setTimeout(() => controller.abort(), options.timeoutMs);
6097
+ try {
6098
+ const config = options.buildRequest();
6099
+ const response = await fetch(config.url, {
6100
+ method: config.method ?? "GET",
6101
+ headers: config.headers,
6102
+ body: config.body,
6103
+ signal: controller.signal
6104
+ });
6105
+ clearTimeout(timeoutId);
6106
+ if (response.ok) {
6107
+ return response.json();
6108
+ }
6109
+ if (isAuthExpired(response.status)) {
6110
+ options.onAuthExpired();
6111
+ }
6112
+ lastResponse = response;
6113
+ lastError = new Error(
6114
+ `${options.label} error (${response.status}): ${await response.text().catch(() => "Unknown error")}`
6115
+ );
6116
+ if (!isRetryable(void 0, response)) {
6117
+ throw lastError;
6118
+ }
6119
+ } catch (error) {
6120
+ clearTimeout(timeoutId);
6121
+ if (error instanceof DOMException && error.name === "AbortError") {
6122
+ throw new RequestTimeoutError(options.label);
6123
+ }
6124
+ lastError = error;
6125
+ lastResponse = void 0;
6126
+ if (!isRetryable(error)) {
6127
+ throw error;
6128
+ }
6129
+ }
6130
+ if (attempt < MAX_RETRY_ATTEMPTS) {
6131
+ const retryDelay = RETRY_BASE_DELAY_MS * 2 ** (attempt - 1);
6132
+ process.stderr.write(
6133
+ `${options.label} request failed (attempt ${attempt}/${MAX_RETRY_ATTEMPTS}), retrying in ${retryDelay / 1e3}s...
6134
+ `
6135
+ );
6136
+ await delay(retryDelay);
6137
+ }
6138
+ }
6139
+ if (lastResponse && !lastResponse.ok) {
6140
+ throw lastError;
6141
+ }
6142
+ throw lastError;
6143
+ }
6144
+
6145
+ // src/registry/platform.ts
6146
+ var REQUEST_TIMEOUT_MS = 3e4;
6147
+ async function platformFetch(path, options = {}) {
6148
+ const platformUrl = getPlatformUrl();
6149
+ if (!platformUrl) {
6150
+ throw new AgentverError(
6151
+ "UNAUTHORISED",
6152
+ "No platform URL configured. Run `agentver login <url>` to connect."
6153
+ );
6154
+ }
6155
+ const credentials = await getCredentials();
6156
+ if (!credentials?.token && !credentials?.apiKey) {
6157
+ throw new AgentverError("UNAUTHORISED", "Not authenticated. Run `agentver login` to sign in.");
6158
+ }
6159
+ const url = `${platformUrl}/api/v1${path}`;
6160
+ const headers = {
6161
+ "Content-Type": "application/json"
6162
+ };
6163
+ if (credentials.token) {
6164
+ headers.Authorization = `Bearer ${credentials.token}`;
6165
+ } else if (credentials.apiKey) {
6166
+ headers["X-API-Key"] = credentials.apiKey;
6167
+ }
6168
+ return fetchWithRetry({
6169
+ label: "Platform",
6170
+ timeoutMs: options.timeout ?? REQUEST_TIMEOUT_MS,
6171
+ buildRequest: () => ({
6172
+ url,
6173
+ method: options.method ?? "GET",
6174
+ headers,
6175
+ body: options.body ? JSON.stringify(options.body) : void 0
6176
+ }),
6177
+ onAuthExpired: () => {
6178
+ throw new AgentverError(
6179
+ "UNAUTHORISED",
6180
+ "Authentication expired. Run `agentver login` to re-authenticate."
6181
+ );
6182
+ }
6183
+ });
6184
+ }
6185
+ async function platformFetchSilent(path, options = {}) {
6186
+ try {
6187
+ return await platformFetch(path, options);
6188
+ } catch {
6189
+ return null;
6190
+ }
6191
+ }
6192
+
6193
+ // src/commands/draft.ts
6194
+ function resolveSkillIdentity() {
6195
+ const cwd = process.cwd();
6196
+ const skillMdPath = join12(cwd, "SKILL.md");
6197
+ let skillName = null;
6198
+ if (existsSync10(skillMdPath)) {
6199
+ const content = readFileSync9(skillMdPath, "utf-8");
6200
+ const nameMatch = content.match(/^name:\s*(.+)$/m);
6201
+ skillName = nameMatch?.[1]?.trim() ?? basename2(cwd);
6202
+ }
6203
+ if (!skillName) {
6204
+ skillName = basename2(cwd);
6205
+ }
6206
+ const manifest = readManifest(cwd);
6207
+ const entry = manifest.packages[skillName];
6208
+ if (entry?.source.type === "git") {
6209
+ const parts = entry.source.uri.split("/");
6210
+ const org = parts.length >= 2 ? parts[parts.length - 2] : parts[0];
6211
+ if (org) {
6212
+ return { org, name: skillName };
6213
+ }
6214
+ }
6215
+ const pathParts = cwd.split("/");
6216
+ const skillsIdx = pathParts.lastIndexOf("skills");
6217
+ if (skillsIdx >= 0 && pathParts.length > skillsIdx + 2) {
6218
+ return { org: pathParts[skillsIdx + 1], name: skillName };
6219
+ }
6220
+ return null;
6221
+ }
6222
+ function registerDraftCommand(program2) {
6223
+ const draft = program2.command("draft").description("Manage skill drafts (branches)");
6224
+ draft.command("create <name>").description("Create a draft branch for the current skill").option("--json", "Output as JSON").action(async (name, options) => {
6225
+ const identity = resolveSkillIdentity();
6226
+ if (!identity) {
6227
+ process.stderr.write(
6228
+ chalk9.red("Could not determine skill identity. Run this from a skill directory.\n")
6229
+ );
6230
+ process.exit(1);
6231
+ }
6232
+ const spinner = ora2(`Creating draft "${name}"...`).start();
6233
+ try {
6234
+ const result = await platformFetch(
6235
+ `/skills/@${identity.org}/${identity.name}/drafts`,
6236
+ {
6237
+ method: "POST",
6238
+ body: { name }
6239
+ }
6240
+ );
6241
+ if (options.json) {
6242
+ spinner.stop();
6243
+ console.log(JSON.stringify(result, null, 2));
6244
+ } else {
6245
+ spinner.succeed(
6246
+ `Draft ${chalk9.green(result.name)} created on branch ${chalk9.cyan(result.branchName)}`
6247
+ );
6248
+ }
6249
+ } catch (error) {
6250
+ spinner.fail(
6251
+ `Failed to create draft: ${error instanceof Error ? error.message : String(error)}`
6252
+ );
6253
+ process.exit(1);
6254
+ }
6255
+ });
6256
+ draft.command("list").description("List open drafts for the current skill").option("--json", "Output as JSON").action(async (options) => {
6257
+ const identity = resolveSkillIdentity();
6258
+ if (!identity) {
6259
+ process.stderr.write(
6260
+ chalk9.red("Could not determine skill identity. Run this from a skill directory.\n")
6261
+ );
6262
+ process.exit(1);
5575
6263
  }
5576
6264
  const spinner = ora2("Fetching drafts...").start();
5577
6265
  try {
@@ -5584,16 +6272,16 @@ function registerDraftCommand(program2) {
5584
6272
  return;
5585
6273
  }
5586
6274
  if (drafts.length === 0) {
5587
- process.stdout.write(chalk6.dim("No open drafts.\n"));
6275
+ process.stdout.write(chalk9.dim("No open drafts.\n"));
5588
6276
  return;
5589
6277
  }
5590
- process.stdout.write(chalk6.bold(`
6278
+ process.stdout.write(chalk9.bold(`
5591
6279
  Drafts for @${identity.org}/${identity.name}:
5592
6280
 
5593
6281
  `));
5594
6282
  for (const d of drafts) {
5595
6283
  process.stdout.write(
5596
- ` ${chalk6.green(d.name)} ${chalk6.dim(`(${d.latestCommitId.slice(0, 7)})`)} ${chalk6.dim(d.latestMessage)}
6284
+ ` ${chalk9.green(d.name)} ${chalk9.dim(`(${d.latestCommitId.slice(0, 7)})`)} ${chalk9.dim(d.latestMessage)}
5597
6285
  `
5598
6286
  );
5599
6287
  }
@@ -5609,7 +6297,7 @@ Drafts for @${identity.org}/${identity.name}:
5609
6297
  const identity = resolveSkillIdentity();
5610
6298
  if (!identity) {
5611
6299
  process.stderr.write(
5612
- chalk6.red("Could not determine skill identity. Run this from a skill directory.\n")
6300
+ chalk9.red("Could not determine skill identity. Run this from a skill directory.\n")
5613
6301
  );
5614
6302
  process.exit(1);
5615
6303
  }
@@ -5617,7 +6305,7 @@ Drafts for @${identity.org}/${identity.name}:
5617
6305
  const lockfile = readLockfile(projectRoot);
5618
6306
  const lockEntry = lockfile.packages[identity.name];
5619
6307
  if (!lockEntry) {
5620
- process.stderr.write(chalk6.red(`Skill "${identity.name}" not found in lockfile.
6308
+ process.stderr.write(chalk9.red(`Skill "${identity.name}" not found in lockfile.
5621
6309
  `));
5622
6310
  process.exit(1);
5623
6311
  }
@@ -5639,7 +6327,7 @@ Drafts for @${identity.org}/${identity.name}:
5639
6327
  );
5640
6328
  } else {
5641
6329
  process.stdout.write(
5642
- `Switched to draft ${chalk6.green(name)} ${chalk6.dim(`(ref: draft/${identity.name}/${name})`)}
6330
+ `Switched to draft ${chalk9.green(name)} ${chalk9.dim(`(ref: draft/${identity.name}/${name})`)}
5643
6331
  `
5644
6332
  );
5645
6333
  }
@@ -5648,7 +6336,7 @@ Drafts for @${identity.org}/${identity.name}:
5648
6336
  const identity = resolveSkillIdentity();
5649
6337
  if (!identity) {
5650
6338
  process.stderr.write(
5651
- chalk6.red("Could not determine skill identity. Run this from a skill directory.\n")
6339
+ chalk9.red("Could not determine skill identity. Run this from a skill directory.\n")
5652
6340
  );
5653
6341
  process.exit(1);
5654
6342
  }
@@ -5656,12 +6344,12 @@ Drafts for @${identity.org}/${identity.name}:
5656
6344
  const lockfile = readLockfile(projectRoot);
5657
6345
  const lockEntry = lockfile.packages[identity.name];
5658
6346
  if (!lockEntry || lockEntry.source.type !== "git") {
5659
- process.stderr.write(chalk6.red("Skill not found in lockfile.\n"));
6347
+ process.stderr.write(chalk9.red("Skill not found in lockfile.\n"));
5660
6348
  process.exit(1);
5661
6349
  }
5662
6350
  const currentRef = lockEntry.source.ref;
5663
6351
  if (!currentRef.startsWith("draft/")) {
5664
- process.stderr.write(chalk6.red(`Not on a draft branch. Current ref: ${currentRef}
6352
+ process.stderr.write(chalk9.red(`Not on a draft branch. Current ref: ${currentRef}
5665
6353
  `));
5666
6354
  process.exit(1);
5667
6355
  }
@@ -5694,7 +6382,7 @@ Drafts for @${identity.org}/${identity.name}:
5694
6382
  );
5695
6383
  } else {
5696
6384
  spinner.succeed(
5697
- `Draft merged to main ${result.commitSha ? chalk6.dim(`(${result.commitSha.slice(0, 7)})`) : ""}`
6385
+ `Draft merged to main ${result.commitSha ? chalk9.dim(`(${result.commitSha.slice(0, 7)})`) : ""}`
5698
6386
  );
5699
6387
  }
5700
6388
  } catch (error) {
@@ -5708,7 +6396,7 @@ Drafts for @${identity.org}/${identity.name}:
5708
6396
  const identity = resolveSkillIdentity();
5709
6397
  if (!identity) {
5710
6398
  process.stderr.write(
5711
- chalk6.red("Could not determine skill identity. Run this from a skill directory.\n")
6399
+ chalk9.red("Could not determine skill identity. Run this from a skill directory.\n")
5712
6400
  );
5713
6401
  process.exit(1);
5714
6402
  }
@@ -5716,12 +6404,12 @@ Drafts for @${identity.org}/${identity.name}:
5716
6404
  const lockfile = readLockfile(projectRoot);
5717
6405
  const lockEntry = lockfile.packages[identity.name];
5718
6406
  if (!lockEntry || lockEntry.source.type !== "git") {
5719
- process.stderr.write(chalk6.red("Skill not found in lockfile.\n"));
6407
+ process.stderr.write(chalk9.red("Skill not found in lockfile.\n"));
5720
6408
  process.exit(1);
5721
6409
  }
5722
6410
  const currentRef = lockEntry.source.ref;
5723
6411
  if (!currentRef.startsWith("draft/")) {
5724
- process.stderr.write(chalk6.red(`Not on a draft branch. Current ref: ${currentRef}
6412
+ process.stderr.write(chalk9.red(`Not on a draft branch. Current ref: ${currentRef}
5725
6413
  `));
5726
6414
  process.exit(1);
5727
6415
  }
@@ -5750,7 +6438,7 @@ Drafts for @${identity.org}/${identity.name}:
5750
6438
  )
5751
6439
  );
5752
6440
  } else {
5753
- spinner.succeed(`Draft discarded. Switched back to ${chalk6.cyan("main")}.`);
6441
+ spinner.succeed(`Draft discarded. Switched back to ${chalk9.cyan("main")}.`);
5754
6442
  }
5755
6443
  } catch (error) {
5756
6444
  spinner.fail(
@@ -5761,10 +6449,124 @@ Drafts for @${identity.org}/${identity.name}:
5761
6449
  });
5762
6450
  }
5763
6451
 
6452
+ // src/commands/info.ts
6453
+ import { readFileSync as readFileSync10 } from "fs";
6454
+ import { join as join13 } from "path";
6455
+ import chalk10 from "chalk";
6456
+ function formatBytes2(bytes) {
6457
+ if (bytes < 1024) return `${bytes} B`;
6458
+ if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
6459
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
6460
+ }
6461
+ function registerInfoCommand(program2) {
6462
+ program2.command("info <name>").description("Show detailed information about an installed package").option("--json", "Output as JSON").action(async (name, options) => {
6463
+ const jsonMode = isJSONMode() || options.json === true;
6464
+ const projectRoot = process.cwd();
6465
+ const manifest = readManifest(projectRoot);
6466
+ const pkg2 = manifest.packages[name];
6467
+ if (!pkg2) {
6468
+ if (jsonMode) {
6469
+ outputError("NOT_FOUND", `Package "${name}" is not installed.`);
6470
+ process.exit(1);
6471
+ }
6472
+ console.error(chalk10.red(`Package "${name}" is not installed.`));
6473
+ process.exit(1);
6474
+ }
6475
+ const spinner = createSpinner("Reading package information...").start();
6476
+ const lockfile = readLockfile(projectRoot);
6477
+ const lockfileEntry = lockfile.packages[name];
6478
+ const shortName = name.split("/").pop();
6479
+ let fileCount = 0;
6480
+ let totalSize = 0;
6481
+ let locallyModified = false;
6482
+ let skillTitle;
6483
+ let skillDescription;
6484
+ const readPath = resolveReadPath(projectRoot, shortName, pkg2.agents);
6485
+ if (readPath) {
6486
+ try {
6487
+ const files = await readFilesFromDirectory(readPath);
6488
+ fileCount = files.length;
6489
+ totalSize = files.reduce((sum, f) => sum + f.size, 0);
6490
+ if (lockfileEntry?.integrity && files.length > 0) {
6491
+ const localIntegrity = computeSha256FromFiles(files);
6492
+ locallyModified = localIntegrity !== lockfileEntry.integrity;
6493
+ }
6494
+ const skillMdPath = join13(readPath, "SKILL.md");
6495
+ try {
6496
+ const skillMdContent = readFileSync10(skillMdPath, "utf-8");
6497
+ const { frontmatter } = parseSkillFrontmatter(skillMdContent);
6498
+ skillTitle = frontmatter.name;
6499
+ skillDescription = frontmatter.description;
6500
+ } catch {
6501
+ }
6502
+ } catch {
6503
+ }
6504
+ }
6505
+ const sourceInfo = pkg2.source.type === "git" ? {
6506
+ type: "git",
6507
+ uri: pkg2.source.uri,
6508
+ ref: pkg2.source.ref,
6509
+ commit: pkg2.source.commit
6510
+ } : { type: "well-known", hostname: pkg2.source.hostname };
6511
+ const result = {
6512
+ name,
6513
+ source: sourceInfo,
6514
+ agents: pkg2.agents,
6515
+ installedAt: pkg2.installedAt,
6516
+ modified: locallyModified,
6517
+ integrity: lockfileEntry?.integrity,
6518
+ files: {
6519
+ count: fileCount,
6520
+ totalSize
6521
+ },
6522
+ skill: skillTitle && skillDescription ? { title: skillTitle, description: skillDescription } : void 0
6523
+ };
6524
+ if (jsonMode) {
6525
+ spinner.stop();
6526
+ outputSuccess(result);
6527
+ return;
6528
+ }
6529
+ spinner.stop();
6530
+ console.log();
6531
+ console.log(chalk10.bold(name));
6532
+ console.log();
6533
+ if (pkg2.source.type === "git") {
6534
+ console.log(` ${chalk10.dim("Source:")} ${pkg2.source.uri}`);
6535
+ console.log(` ${chalk10.dim("Ref:")} ${chalk10.cyan(pkg2.source.ref)}`);
6536
+ console.log(` ${chalk10.dim("Commit:")} ${chalk10.dim(pkg2.source.commit.slice(0, 7))}`);
6537
+ } else {
6538
+ console.log(
6539
+ ` ${chalk10.dim("Source:")} ${pkg2.source.hostname} ${chalk10.dim("[well-known]")}`
6540
+ );
6541
+ }
6542
+ console.log(
6543
+ ` ${chalk10.dim("Agents:")} ${pkg2.agents.length > 0 ? pkg2.agents.join(", ") : chalk10.dim("none")}`
6544
+ );
6545
+ console.log(` ${chalk10.dim("Installed:")} ${pkg2.installedAt}`);
6546
+ console.log(
6547
+ ` ${chalk10.dim("Modified:")} ${locallyModified ? chalk10.yellow("yes") : chalk10.green("no")}`
6548
+ );
6549
+ if (lockfileEntry?.integrity) {
6550
+ console.log(` ${chalk10.dim("Integrity:")} ${lockfileEntry.integrity}`);
6551
+ }
6552
+ console.log(
6553
+ ` ${chalk10.dim("Files:")} ${fileCount} file${fileCount !== 1 ? "s" : ""} (${formatBytes2(totalSize)})`
6554
+ );
6555
+ if (skillTitle) {
6556
+ console.log();
6557
+ console.log(` ${chalk10.dim("Skill:")} ${skillTitle}`);
6558
+ if (skillDescription) {
6559
+ console.log(` ${chalk10.dim("Description:")} ${skillDescription}`);
6560
+ }
6561
+ }
6562
+ console.log();
6563
+ });
6564
+ }
6565
+
5764
6566
  // src/commands/init.ts
5765
- import { existsSync as existsSync9, mkdirSync as mkdirSync7, writeFileSync as writeFileSync6 } from "fs";
5766
- import { join as join11 } from "path";
5767
- import chalk7 from "chalk";
6567
+ import { existsSync as existsSync11, mkdirSync as mkdirSync7, writeFileSync as writeFileSync6 } from "fs";
6568
+ import { join as join14 } from "path";
6569
+ import chalk11 from "chalk";
5768
6570
  import prompts from "prompts";
5769
6571
  var TOKEN_BUDGET = 5e3;
5770
6572
  function estimateTokens(content) {
@@ -5774,11 +6576,11 @@ function warnIfOverBudget(filePath, content) {
5774
6576
  const tokens = estimateTokens(content);
5775
6577
  if (tokens > TOKEN_BUDGET) {
5776
6578
  console.log(
5777
- chalk7.yellow(`
6579
+ chalk11.yellow(`
5778
6580
  Warning: ${filePath} is ~${tokens} tokens (recommended < ${TOKEN_BUDGET}).`)
5779
6581
  );
5780
6582
  console.log(
5781
- chalk7.yellow(" Move detailed content to docs/ or examples/ for progressive disclosure.")
6583
+ chalk11.yellow(" Move detailed content to docs/ or examples/ for progressive disclosure.")
5782
6584
  );
5783
6585
  }
5784
6586
  }
@@ -6007,7 +6809,7 @@ agentver install github.com/YOUR_ORG/YOUR_REPO@main
6007
6809
  }
6008
6810
  function createGitkeep(dirPath) {
6009
6811
  mkdirSync7(dirPath, { recursive: true });
6010
- writeFileSync6(join11(dirPath, ".gitkeep"), "", "utf-8");
6812
+ writeFileSync6(join14(dirPath, ".gitkeep"), "", "utf-8");
6011
6813
  }
6012
6814
  function registerInitCommand(program2) {
6013
6815
  program2.command("init").description("Scaffold a new package").option("--type <type>", "Package type: skill, agent, plugin, script, prompt", "skill").option("--repo", "Scaffold in a Git-repo-friendly structure").option("--name <name>", "Package name (required in JSON mode)").option("--description <desc>", "Package description").action(
@@ -6060,13 +6862,13 @@ function registerInitCommand(program2) {
6060
6862
  description = response.description ?? "";
6061
6863
  author = response.author ?? "";
6062
6864
  }
6063
- const dir = join11(process.cwd(), packageName);
6064
- if (existsSync9(dir)) {
6865
+ const dir = join14(process.cwd(), packageName);
6866
+ if (existsSync11(dir)) {
6065
6867
  if (isJSONMode()) {
6066
6868
  outputError("ALREADY_EXISTS", `Directory "${packageName}" already exists.`);
6067
6869
  process.exit(1);
6068
6870
  }
6069
- console.error(chalk7.red(`Directory "${packageName}" already exists.`));
6871
+ console.error(chalk11.red(`Directory "${packageName}" already exists.`));
6070
6872
  process.exit(1);
6071
6873
  }
6072
6874
  mkdirSync7(dir, { recursive: true });
@@ -6077,14 +6879,14 @@ function registerInitCommand(program2) {
6077
6879
  case "skill": {
6078
6880
  fileName = "SKILL.md";
6079
6881
  const content = applyReplacements(SKILL_TEMPLATE);
6080
- writeFileSync6(join11(dir, fileName), content, "utf-8");
6882
+ writeFileSync6(join14(dir, fileName), content, "utf-8");
6081
6883
  createdFiles.push(fileName);
6082
6884
  if (!options.repo) {
6083
- mkdirSync7(join11(dir, "examples"), { recursive: true });
6084
- writeFileSync6(join11(dir, "examples", "README.md"), EXAMPLES_README, "utf-8");
6885
+ mkdirSync7(join14(dir, "examples"), { recursive: true });
6886
+ writeFileSync6(join14(dir, "examples", "README.md"), EXAMPLES_README, "utf-8");
6085
6887
  createdFiles.push("examples/README.md");
6086
- mkdirSync7(join11(dir, "docs"), { recursive: true });
6087
- writeFileSync6(join11(dir, "docs", "README.md"), DOCS_README, "utf-8");
6888
+ mkdirSync7(join14(dir, "docs"), { recursive: true });
6889
+ writeFileSync6(join14(dir, "docs", "README.md"), DOCS_README, "utf-8");
6088
6890
  createdFiles.push("docs/README.md");
6089
6891
  }
6090
6892
  if (!isJSONMode()) {
@@ -6095,29 +6897,29 @@ function registerInitCommand(program2) {
6095
6897
  case "agent": {
6096
6898
  fileName = "CLAUDE.md";
6097
6899
  const content = applyReplacements(AGENT_CONFIG_TEMPLATE);
6098
- writeFileSync6(join11(dir, fileName), content, "utf-8");
6900
+ writeFileSync6(join14(dir, fileName), content, "utf-8");
6099
6901
  createdFiles.push(fileName);
6100
6902
  if (!options.repo) {
6101
- mkdirSync7(join11(dir, "rules"), { recursive: true });
6903
+ mkdirSync7(join14(dir, "rules"), { recursive: true });
6102
6904
  }
6103
6905
  break;
6104
6906
  }
6105
6907
  case "plugin": {
6106
6908
  fileName = "plugin.json";
6107
- writeFileSync6(join11(dir, fileName), applyReplacements(PLUGIN_TEMPLATE), "utf-8");
6909
+ writeFileSync6(join14(dir, fileName), applyReplacements(PLUGIN_TEMPLATE), "utf-8");
6108
6910
  createdFiles.push(fileName);
6109
6911
  if (!options.repo) {
6110
- mkdirSync7(join11(dir, "scripts"), { recursive: true });
6912
+ mkdirSync7(join14(dir, "scripts"), { recursive: true });
6111
6913
  }
6112
6914
  break;
6113
6915
  }
6114
6916
  case "script": {
6115
6917
  fileName = "script.json";
6116
- writeFileSync6(join11(dir, fileName), applyReplacements(SCRIPT_TEMPLATE), "utf-8");
6918
+ writeFileSync6(join14(dir, fileName), applyReplacements(SCRIPT_TEMPLATE), "utf-8");
6117
6919
  createdFiles.push(fileName);
6118
- mkdirSync7(join11(dir, "src"), { recursive: true });
6920
+ mkdirSync7(join14(dir, "src"), { recursive: true });
6119
6921
  writeFileSync6(
6120
- join11(dir, "src", "index.ts"),
6922
+ join14(dir, "src", "index.ts"),
6121
6923
  applyReplacements(SCRIPT_ENTRY_TEMPLATE),
6122
6924
  "utf-8"
6123
6925
  );
@@ -6127,10 +6929,10 @@ function registerInitCommand(program2) {
6127
6929
  case "prompt": {
6128
6930
  fileName = "PROMPT.md";
6129
6931
  const content = applyReplacements(PROMPT_TEMPLATE);
6130
- writeFileSync6(join11(dir, fileName), content, "utf-8");
6932
+ writeFileSync6(join14(dir, fileName), content, "utf-8");
6131
6933
  createdFiles.push(fileName);
6132
6934
  if (!options.repo) {
6133
- mkdirSync7(join11(dir, "variants"), { recursive: true });
6935
+ mkdirSync7(join14(dir, "variants"), { recursive: true });
6134
6936
  }
6135
6937
  if (!isJSONMode()) {
6136
6938
  warnIfOverBudget(fileName, content);
@@ -6142,28 +6944,28 @@ function registerInitCommand(program2) {
6142
6944
  outputError("VALIDATION_ERROR", `Unknown package type: "${options.type}"`);
6143
6945
  process.exit(1);
6144
6946
  }
6145
- console.error(chalk7.red(`Unknown package type: "${options.type}"`));
6947
+ console.error(chalk11.red(`Unknown package type: "${options.type}"`));
6146
6948
  process.exit(1);
6147
6949
  }
6148
6950
  }
6149
6951
  if (options.repo) {
6150
- const skillsDir = join11(dir, "skills", "example-skill");
6952
+ const skillsDir = join14(dir, "skills", "example-skill");
6151
6953
  mkdirSync7(skillsDir, { recursive: true });
6152
- writeFileSync6(join11(skillsDir, "SKILL.md"), EXAMPLE_SKILL_TEMPLATE, "utf-8");
6954
+ writeFileSync6(join14(skillsDir, "SKILL.md"), EXAMPLE_SKILL_TEMPLATE, "utf-8");
6153
6955
  createdFiles.push("skills/example-skill/SKILL.md");
6154
- mkdirSync7(join11(skillsDir, "examples"), { recursive: true });
6155
- writeFileSync6(join11(skillsDir, "examples", "README.md"), EXAMPLES_README, "utf-8");
6956
+ mkdirSync7(join14(skillsDir, "examples"), { recursive: true });
6957
+ writeFileSync6(join14(skillsDir, "examples", "README.md"), EXAMPLES_README, "utf-8");
6156
6958
  createdFiles.push("skills/example-skill/examples/README.md");
6157
- mkdirSync7(join11(skillsDir, "docs"), { recursive: true });
6158
- writeFileSync6(join11(skillsDir, "docs", "README.md"), DOCS_README, "utf-8");
6959
+ mkdirSync7(join14(skillsDir, "docs"), { recursive: true });
6960
+ writeFileSync6(join14(skillsDir, "docs", "README.md"), DOCS_README, "utf-8");
6159
6961
  createdFiles.push("skills/example-skill/docs/README.md");
6160
- createGitkeep(join11(dir, "configs"));
6962
+ createGitkeep(join14(dir, "configs"));
6161
6963
  createdFiles.push("configs/.gitkeep");
6162
- createGitkeep(join11(dir, "prompts"));
6964
+ createGitkeep(join14(dir, "prompts"));
6163
6965
  createdFiles.push("prompts/.gitkeep");
6164
- writeFileSync6(join11(dir, "README.md"), buildReadme(packageName, description), "utf-8");
6966
+ writeFileSync6(join14(dir, "README.md"), buildReadme(packageName, description), "utf-8");
6165
6967
  createdFiles.push("README.md");
6166
- writeFileSync6(join11(dir, ".agentverignore"), AGENTVERIGNORE_CONTENT, "utf-8");
6968
+ writeFileSync6(join14(dir, ".agentverignore"), AGENTVERIGNORE_CONTENT, "utf-8");
6167
6969
  createdFiles.push(".agentverignore");
6168
6970
  }
6169
6971
  if (isJSONMode()) {
@@ -6175,25 +6977,25 @@ function registerInitCommand(program2) {
6175
6977
  });
6176
6978
  return;
6177
6979
  }
6178
- console.log(chalk7.green(`
6980
+ console.log(chalk11.green(`
6179
6981
  Created ${fileName} in ./${packageName}/`));
6180
6982
  if (options.repo) {
6181
- console.log(chalk7.dim("Repo structure created with skills/, configs/, prompts/"));
6983
+ console.log(chalk11.dim("Repo structure created with skills/, configs/, prompts/"));
6182
6984
  console.log(
6183
- chalk7.dim(`Install with: agentver install github.com/YOUR_ORG/YOUR_REPO@main`)
6985
+ chalk11.dim(`Install with: agentver install github.com/YOUR_ORG/YOUR_REPO@main`)
6184
6986
  );
6185
6987
  } else {
6186
- console.log(chalk7.dim(`Edit the file, then run: agentver publish ./${packageName}`));
6988
+ console.log(chalk11.dim(`Edit the file, then run: agentver publish ./${packageName}`));
6187
6989
  }
6188
6990
  }
6189
6991
  );
6190
6992
  }
6191
6993
 
6192
6994
  // src/commands/install.ts
6193
- import { existsSync as existsSync10, mkdirSync as mkdirSync8, readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
6194
- import { homedir as homedir6 } from "os";
6195
- import { dirname as dirname4, join as join12, relative as relative2, resolve } from "path";
6196
- import chalk8 from "chalk";
6995
+ import { existsSync as existsSync12, mkdirSync as mkdirSync8, readFileSync as readFileSync11, writeFileSync as writeFileSync7 } from "fs";
6996
+ import { homedir as homedir7 } from "os";
6997
+ import { dirname as dirname5, join as join15, relative as relative2, resolve } from "path";
6998
+ import chalk12 from "chalk";
6197
6999
  import prompts2 from "prompts";
6198
7000
 
6199
7001
  // src/registry/reporter.ts
@@ -6502,19 +7304,19 @@ async function installFromWellKnown(source, options) {
6502
7304
  process.exit(1);
6503
7305
  }
6504
7306
  spinner.stop();
6505
- process.stdout.write(chalk8.bold(`
7307
+ process.stdout.write(chalk12.bold(`
6506
7308
  Multiple skills available at ${hostname3}:
6507
7309
 
6508
7310
  `));
6509
7311
  for (const skill of index.skills) {
6510
7312
  process.stdout.write(
6511
- ` ${chalk8.green(skill.name)} ${chalk8.dim(`\u2014 ${skill.description}`)}
7313
+ ` ${chalk12.green(skill.name)} ${chalk12.dim(`\u2014 ${skill.description}`)}
6512
7314
  `
6513
7315
  );
6514
7316
  }
6515
7317
  process.stdout.write(
6516
7318
  `
6517
- ${chalk8.dim("Specify a skill:")} ${chalk8.white(`agentver install ${hostname3}/<skill-name>`)}
7319
+ ${chalk12.dim("Specify a skill:")} ${chalk12.white(`agentver install ${hostname3}/<skill-name>`)}
6518
7320
  `
6519
7321
  );
6520
7322
  process.exit(1);
@@ -6631,7 +7433,7 @@ ${chalk8.dim("Specify a skill:")} ${chalk8.white(`agentver install ${hostname3}/
6631
7433
  });
6632
7434
  } else {
6633
7435
  spinner.succeed(
6634
- `Installed ${chalk8.green(selectedEntry.name)} from ${chalk8.dim(hostname3)} ${chalk8.dim("(well-known)")} to ${target}`
7436
+ `Installed ${chalk12.green(selectedEntry.name)} from ${chalk12.dim(hostname3)} ${chalk12.dim("(well-known)")} to ${target}`
6635
7437
  );
6636
7438
  }
6637
7439
  return { name: selectedEntry.name, ref: "well-known", commitSha: "", agents };
@@ -6695,14 +7497,14 @@ async function installPackage(source, options) {
6695
7497
  initial: false
6696
7498
  });
6697
7499
  if (!proceed) {
6698
- console.log(chalk8.dim("Installation cancelled."));
7500
+ console.log(chalk12.dim("Installation cancelled."));
6699
7501
  process.exit(0);
6700
7502
  }
6701
7503
  spinner.start("Continuing installation...");
6702
7504
  }
6703
7505
  } else {
6704
7506
  if (!jsonMode) {
6705
- spinner.succeed(chalk8.green("Security scan passed"));
7507
+ spinner.succeed(chalk12.green("Security scan passed"));
6706
7508
  spinner.start("Installing...");
6707
7509
  }
6708
7510
  }
@@ -6810,7 +7612,7 @@ async function installPackage(source, options) {
6810
7612
  );
6811
7613
  } else {
6812
7614
  spinner.succeed(
6813
- `Installed ${chalk8.green(shortName)} from ${chalk8.dim(formatSource(gitSource))} ${chalk8.cyan(`@${gitSource.ref}`)} ${chalk8.dim(`(${resolved.commitSha.slice(0, 7)})`)} to ${target}`
7615
+ `Installed ${chalk12.green(shortName)} from ${chalk12.dim(formatSource(gitSource))} ${chalk12.cyan(`@${gitSource.ref}`)} ${chalk12.dim(`(${resolved.commitSha.slice(0, 7)})`)} to ${target}`
6814
7616
  );
6815
7617
  }
6816
7618
  return { name: shortName, ref: gitSource.ref, commitSha: resolved.commitSha, agents };
@@ -6857,7 +7659,7 @@ async function installAgentConfig(name, files, agents, options, spinner) {
6857
7659
  const projectRoot = process.cwd();
6858
7660
  if (options.dryRun) {
6859
7661
  spinner.info(
6860
- `${chalk8.yellow("[dry-run]")} Would install agent config ${chalk8.green(name)} to ${agents.join(", ")}`
7662
+ `${chalk12.yellow("[dry-run]")} Would install agent config ${chalk12.green(name)} to ${agents.join(", ")}`
6861
7663
  );
6862
7664
  return;
6863
7665
  }
@@ -6873,14 +7675,14 @@ async function installAgentConfig(name, files, agents, options, spinner) {
6873
7675
  for (const agentId of agents) {
6874
7676
  const configPath = getConfigFilePath(agentId, name);
6875
7677
  if (!configPath) continue;
6876
- const fullConfigPath = options.global ? configPath.replace("~", homedir6()) : join12(projectRoot, configPath);
6877
- const configDir = join12(fullConfigPath, "..");
6878
- if (!existsSync10(configDir)) {
7678
+ const fullConfigPath = options.global ? configPath.replace("~", homedir7()) : join15(projectRoot, configPath);
7679
+ const configDir = join15(fullConfigPath, "..");
7680
+ if (!existsSync12(configDir)) {
6879
7681
  mkdirSync8(configDir, { recursive: true });
6880
7682
  }
6881
7683
  let finalContent = configContent;
6882
- if (existsSync10(fullConfigPath)) {
6883
- const existingContent = readFileSync8(fullConfigPath, "utf-8");
7684
+ if (existsSync12(fullConfigPath)) {
7685
+ const existingContent = readFileSync11(fullConfigPath, "utf-8");
6884
7686
  if (isComposedConfig(existingContent)) {
6885
7687
  const existingSections = parseComposedSections(existingContent);
6886
7688
  const alreadyPresent = existingSections.some((s) => s.packageName === name);
@@ -6909,13 +7711,13 @@ async function installToCustomPath(name, files, options, spinner) {
6909
7711
  const targetPath = resolve(process.cwd(), options.path);
6910
7712
  if (options.dryRun) {
6911
7713
  spinner.info(
6912
- `${chalk8.yellow("[dry-run]")} Would install ${chalk8.green(name)} to ${chalk8.dim(targetPath)}`
7714
+ `${chalk12.yellow("[dry-run]")} Would install ${chalk12.green(name)} to ${chalk12.dim(targetPath)}`
6913
7715
  );
6914
- console.log(chalk8.dim(` Files: ${files.map((f) => f.path).join(", ")}`));
7716
+ console.log(chalk12.dim(` Files: ${files.map((f) => f.path).join(", ")}`));
6915
7717
  return;
6916
7718
  }
6917
7719
  spinner.text = `Installing to ${targetPath}...`;
6918
- if (!existsSync10(targetPath)) {
7720
+ if (!existsSync12(targetPath)) {
6919
7721
  mkdirSync8(targetPath, { recursive: true });
6920
7722
  }
6921
7723
  for (const file of files) {
@@ -6924,8 +7726,8 @@ async function installToCustomPath(name, files, options, spinner) {
6924
7726
  if (relativePath.startsWith("..") || resolve(resolvedFilePath) !== resolvedFilePath) {
6925
7727
  continue;
6926
7728
  }
6927
- const dir = join12(resolvedFilePath, "..");
6928
- if (!existsSync10(dir)) {
7729
+ const dir = join15(resolvedFilePath, "..");
7730
+ if (!existsSync12(dir)) {
6929
7731
  mkdirSync8(dir, { recursive: true });
6930
7732
  }
6931
7733
  writeFileSync7(resolvedFilePath, file.content, "utf-8");
@@ -6937,15 +7739,15 @@ async function installStandardPackage(name, files, agents, options, spinner) {
6937
7739
  if (options.dryRun) {
6938
7740
  const canonicalPath2 = getCanonicalSkillPath(projectRoot, name, scope);
6939
7741
  spinner.info(
6940
- `${chalk8.yellow("[dry-run]")} Would install ${chalk8.green(name)} to ${chalk8.dim(canonicalPath2)}`
7742
+ `${chalk12.yellow("[dry-run]")} Would install ${chalk12.green(name)} to ${chalk12.dim(canonicalPath2)}`
6941
7743
  );
6942
- console.log(chalk8.dim(` Files: ${files.map((f) => f.path).join(", ")}`));
6943
- console.log(chalk8.dim(` Symlinks: ${agents.join(", ")}`));
7744
+ console.log(chalk12.dim(` Files: ${files.map((f) => f.path).join(", ")}`));
7745
+ console.log(chalk12.dim(` Symlinks: ${agents.join(", ")}`));
6944
7746
  return;
6945
7747
  }
6946
7748
  spinner.text = `Installing to canonical path and symlinking to ${agents.length} agent(s)...`;
6947
7749
  const canonicalPath = getCanonicalSkillPath(projectRoot, name, scope);
6948
- if (!existsSync10(canonicalPath)) {
7750
+ if (!existsSync12(canonicalPath)) {
6949
7751
  mkdirSync8(canonicalPath, { recursive: true });
6950
7752
  }
6951
7753
  for (const file of files) {
@@ -6954,8 +7756,8 @@ async function installStandardPackage(name, files, agents, options, spinner) {
6954
7756
  if (relativePath.startsWith("..") || resolve(resolvedFilePath) !== resolvedFilePath) {
6955
7757
  continue;
6956
7758
  }
6957
- const dir = dirname4(resolvedFilePath);
6958
- if (!existsSync10(dir)) {
7759
+ const dir = dirname5(resolvedFilePath);
7760
+ if (!existsSync12(dir)) {
6959
7761
  mkdirSync8(dir, { recursive: true });
6960
7762
  }
6961
7763
  writeFileSync7(resolvedFilePath, file.content, "utf-8");
@@ -6969,7 +7771,7 @@ function registerInstallCommand(program2) {
6969
7771
  }
6970
7772
 
6971
7773
  // src/commands/list.ts
6972
- import chalk9 from "chalk";
7774
+ import chalk13 from "chalk";
6973
7775
  function registerListCommand(program2) {
6974
7776
  program2.command("list").description("Show installed packages").option("--json", "Output as JSON").action(() => {
6975
7777
  const jsonMode = isJSONMode();
@@ -6980,24 +7782,25 @@ function registerListCommand(program2) {
6980
7782
  return;
6981
7783
  }
6982
7784
  if (entries.length === 0) {
6983
- console.log(chalk9.dim("No packages installed."));
7785
+ console.log(chalk13.dim("No packages installed."));
6984
7786
  return;
6985
7787
  }
6986
- console.log(chalk9.bold(`
7788
+ console.log(chalk13.bold(`
6987
7789
  Installed packages (${entries.length}):
6988
7790
  `));
6989
7791
  for (const [name, pkg2] of entries) {
6990
- const agents = pkg2.agents.length > 0 ? chalk9.dim(` [${pkg2.agents.join(", ")}]`) : "";
7792
+ const agents = pkg2.agents.length > 0 ? chalk13.dim(` [${pkg2.agents.join(", ")}]`) : "";
7793
+ const pinned = pkg2.pinned === true ? chalk13.yellow(" [pinned]") : "";
6991
7794
  if (pkg2.source.type === "git") {
6992
7795
  const ref = pkg2.source.ref;
6993
7796
  const commit = pkg2.source.commit.slice(0, 7);
6994
7797
  console.log(
6995
- ` ${chalk9.green(name)}@${chalk9.cyan(ref)} ${chalk9.dim(`(${commit})`)}${agents}`
7798
+ ` ${chalk13.green(name)}@${chalk13.cyan(ref)} ${chalk13.dim(`(${commit})`)}${pinned}${agents}`
6996
7799
  );
6997
7800
  } else {
6998
7801
  const hostname3 = pkg2.source.hostname;
6999
7802
  console.log(
7000
- ` ${chalk9.green(name)} ${chalk9.dim(`(${hostname3})`)} ${chalk9.dim("[well-known]")}${agents}`
7803
+ ` ${chalk13.green(name)} ${chalk13.dim(`(${hostname3})`)} ${chalk13.dim("[well-known]")}${pinned}${agents}`
7001
7804
  );
7002
7805
  }
7003
7806
  }
@@ -7006,9 +7809,9 @@ Installed packages (${entries.length}):
7006
7809
  }
7007
7810
 
7008
7811
  // src/commands/log.ts
7009
- import { existsSync as existsSync11, readFileSync as readFileSync9 } from "fs";
7010
- import { basename as basename3, join as join13 } from "path";
7011
- import chalk10 from "chalk";
7812
+ import { existsSync as existsSync13, readFileSync as readFileSync12 } from "fs";
7813
+ import { basename as basename3, join as join16 } from "path";
7814
+ import chalk14 from "chalk";
7012
7815
  import ora3 from "ora";
7013
7816
  function resolveSkillIdentity2(nameArg) {
7014
7817
  const cwd = process.cwd();
@@ -7024,10 +7827,10 @@ function resolveSkillIdentity2(nameArg) {
7024
7827
  }
7025
7828
  return null;
7026
7829
  }
7027
- const skillMdPath = join13(cwd, "SKILL.md");
7830
+ const skillMdPath = join16(cwd, "SKILL.md");
7028
7831
  let skillName = null;
7029
- if (existsSync11(skillMdPath)) {
7030
- const content = readFileSync9(skillMdPath, "utf-8");
7832
+ if (existsSync13(skillMdPath)) {
7833
+ const content = readFileSync12(skillMdPath, "utf-8");
7031
7834
  const nameMatch = content.match(/^name:\s*(.+)$/m);
7032
7835
  skillName = nameMatch?.[1]?.trim() ?? basename3(cwd);
7033
7836
  }
@@ -7067,7 +7870,7 @@ function registerLogCommand(program2) {
7067
7870
  if (!identity) {
7068
7871
  const target = nameArg ?? "current directory";
7069
7872
  process.stderr.write(
7070
- chalk10.red(
7873
+ chalk14.red(
7071
7874
  `Could not determine skill identity for "${target}". Provide a skill name or run from a skill directory.
7072
7875
  `
7073
7876
  )
@@ -7076,7 +7879,7 @@ function registerLogCommand(program2) {
7076
7879
  }
7077
7880
  const limit = Number.parseInt(options.limit ?? "20", 10);
7078
7881
  if (Number.isNaN(limit) || limit < 1) {
7079
- process.stderr.write(chalk10.red("Limit must be a positive number.\n"));
7882
+ process.stderr.write(chalk14.red("Limit must be a positive number.\n"));
7080
7883
  process.exit(1);
7081
7884
  }
7082
7885
  const spinner = ora3("Fetching history...").start();
@@ -7091,10 +7894,10 @@ function registerLogCommand(program2) {
7091
7894
  return;
7092
7895
  }
7093
7896
  if (commits.length === 0) {
7094
- process.stdout.write(chalk10.dim("No commits found.\n"));
7897
+ process.stdout.write(chalk14.dim("No commits found.\n"));
7095
7898
  return;
7096
7899
  }
7097
- process.stdout.write(chalk10.bold(`
7900
+ process.stdout.write(chalk14.bold(`
7098
7901
  History for @${identity.org}/${identity.name}:
7099
7902
 
7100
7903
  `));
@@ -7103,7 +7906,7 @@ History for @${identity.org}/${identity.name}:
7103
7906
  const date = formatDate(commit.author.date || commit.createdAt);
7104
7907
  const firstLine = commit.message.split("\n")[0] ?? commit.message;
7105
7908
  process.stdout.write(
7106
- ` ${chalk10.yellow(shortSha)} ${chalk10.dim("|")} ${chalk10.dim(date)} ${chalk10.dim("|")} ${firstLine}
7909
+ ` ${chalk14.yellow(shortSha)} ${chalk14.dim("|")} ${chalk14.dim(date)} ${chalk14.dim("|")} ${firstLine}
7107
7910
  `
7108
7911
  );
7109
7912
  }
@@ -7121,31 +7924,14 @@ History for @${identity.org}/${identity.name}:
7121
7924
  import { createHash as createHash3, randomBytes } from "crypto";
7122
7925
  import { createServer } from "http";
7123
7926
  import { URL as URL2 } from "url";
7124
- import chalk12 from "chalk";
7927
+ import chalk16 from "chalk";
7125
7928
  import open from "open";
7126
7929
 
7127
7930
  // src/registry/client.ts
7128
7931
  var DEFAULT_REGISTRY = "https://app.agentver.com/api/v1";
7129
- var REQUEST_TIMEOUT_MS = 3e4;
7130
- var MAX_RETRY_ATTEMPTS = 3;
7131
- var RETRY_BASE_DELAY_MS = 1e3;
7132
- var RegistryTimeoutError = class extends Error {
7133
- constructor() {
7134
- super("Registry request timed out. The service may be experiencing issues.");
7135
- this.name = "RegistryTimeoutError";
7136
- }
7137
- };
7138
- function getRegistryUrl() {
7139
- return process.env.AGENTVER_REGISTRY ?? DEFAULT_REGISTRY;
7140
- }
7141
- function isRetryable(error, response) {
7142
- if (error instanceof RegistryTimeoutError) return false;
7143
- if (error instanceof DOMException && error.name === "AbortError") return false;
7144
- if (!response) return true;
7145
- return response.status >= 500;
7146
- }
7147
- function delay(ms) {
7148
- return new Promise((resolve4) => setTimeout(resolve4, ms));
7932
+ var REQUEST_TIMEOUT_MS2 = 3e4;
7933
+ function getRegistryUrl() {
7934
+ return process.env.AGENTVER_REGISTRY ?? DEFAULT_REGISTRY;
7149
7935
  }
7150
7936
  async function registryFetch(path, options = {}) {
7151
7937
  const credentials = await getCredentials();
@@ -7159,57 +7945,23 @@ async function registryFetch(path, options = {}) {
7159
7945
  } else if (credentials?.apiKey) {
7160
7946
  headers["X-API-Key"] = credentials.apiKey;
7161
7947
  }
7162
- let lastError;
7163
- let lastResponse;
7164
- for (let attempt = 1; attempt <= MAX_RETRY_ATTEMPTS; attempt++) {
7165
- const controller = new AbortController();
7166
- const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
7167
- try {
7168
- const response = await fetch(url, {
7169
- method: options.method ?? "GET",
7170
- headers,
7171
- body: options.body ? JSON.stringify(options.body) : void 0,
7172
- signal: controller.signal
7173
- });
7174
- clearTimeout(timeoutId);
7175
- if (response.ok) {
7176
- return response.json();
7177
- }
7178
- lastResponse = response;
7179
- lastError = new Error(
7180
- `Registry error (${response.status}): ${await response.text().catch(() => "Unknown error")}`
7181
- );
7182
- if (!isRetryable(void 0, response)) {
7183
- throw lastError;
7184
- }
7185
- } catch (error) {
7186
- clearTimeout(timeoutId);
7187
- if (error instanceof DOMException && error.name === "AbortError") {
7188
- throw new RegistryTimeoutError();
7189
- }
7190
- lastError = error;
7191
- lastResponse = void 0;
7192
- if (!isRetryable(error)) {
7193
- throw error;
7194
- }
7195
- }
7196
- if (attempt < MAX_RETRY_ATTEMPTS) {
7197
- const retryDelay = RETRY_BASE_DELAY_MS * 2 ** (attempt - 1);
7198
- process.stderr.write(
7199
- `Registry request failed (attempt ${attempt}/${MAX_RETRY_ATTEMPTS}), retrying in ${retryDelay / 1e3}s...
7200
- `
7201
- );
7202
- await delay(retryDelay);
7948
+ return fetchWithRetry({
7949
+ label: "Registry",
7950
+ timeoutMs: REQUEST_TIMEOUT_MS2,
7951
+ buildRequest: () => ({
7952
+ url,
7953
+ method: options.method ?? "GET",
7954
+ headers,
7955
+ body: options.body ? JSON.stringify(options.body) : void 0
7956
+ }),
7957
+ onAuthExpired: () => {
7958
+ throw new Error("Authentication expired. Run `agentver login` to re-authenticate.");
7203
7959
  }
7204
- }
7205
- if (lastResponse && !lastResponse.ok) {
7206
- throw lastError;
7207
- }
7208
- throw lastError;
7960
+ });
7209
7961
  }
7210
7962
 
7211
7963
  // src/utils/network.ts
7212
- import chalk11 from "chalk";
7964
+ import chalk15 from "chalk";
7213
7965
  var ONLINE_CHECK_TIMEOUT_MS = 3e3;
7214
7966
  async function checkOnline() {
7215
7967
  const registryUrl = getRegistryUrl();
@@ -7229,10 +7981,10 @@ async function checkOnline() {
7229
7981
  }
7230
7982
  function showOfflineError() {
7231
7983
  console.error(
7232
- chalk11.red("Unable to reach the Agentver registry.") + " Please check your internet connection.\n"
7984
+ chalk15.red("Unable to reach the Agentver registry.") + " Please check your internet connection.\n"
7233
7985
  );
7234
7986
  console.error(
7235
- chalk11.dim(
7987
+ chalk15.dim(
7236
7988
  `If you're behind a proxy, set the HTTPS_PROXY environment variable.
7237
7989
  If the registry is down, try again later.
7238
7990
 
@@ -7369,9 +8121,9 @@ function registerLoginCommand(program2) {
7369
8121
  });
7370
8122
  return;
7371
8123
  }
7372
- console.log(chalk12.green("Saved API key. You are now authenticated."));
8124
+ console.log(chalk16.green("Saved API key. You are now authenticated."));
7373
8125
  if (target) {
7374
- console.log(chalk12.dim(`Connected to ${target}`));
8126
+ console.log(chalk16.dim(`Connected to ${target}`));
7375
8127
  }
7376
8128
  return;
7377
8129
  }
@@ -7411,7 +8163,7 @@ function registerLoginCommand(program2) {
7411
8163
  const redirectUri = `http://localhost:${port}/callback`;
7412
8164
  const authUrl = `${baseUrl}/auth/cli?code_challenge=${encodeURIComponent(codeChallenge)}&state=${encodeURIComponent(state)}&redirect_uri=${encodeURIComponent(redirectUri)}`;
7413
8165
  spinner.text = "Opening browser for authentication...";
7414
- console.log(chalk12.dim(`
8166
+ console.log(chalk16.dim(`
7415
8167
  If the browser doesn't open, visit:
7416
8168
  ${authUrl}
7417
8169
  `));
@@ -7431,7 +8183,7 @@ function registerLoginCommand(program2) {
7431
8183
  spinner.succeed("Authenticated successfully.");
7432
8184
  const connectedUrl = url ?? getPlatformUrl();
7433
8185
  if (connectedUrl) {
7434
- console.log(chalk12.dim(`Connected to ${connectedUrl}`));
8186
+ console.log(chalk16.dim(`Connected to ${connectedUrl}`));
7435
8187
  }
7436
8188
  } catch (error) {
7437
8189
  const message = error instanceof Error ? error.message : String(error);
@@ -7444,7 +8196,7 @@ function registerLoginCommand(program2) {
7444
8196
  }
7445
8197
 
7446
8198
  // src/commands/logout.ts
7447
- import chalk13 from "chalk";
8199
+ import chalk17 from "chalk";
7448
8200
  function registerLogoutCommand(program2) {
7449
8201
  program2.command("logout").description("Log out from the Agentver registry").action(async () => {
7450
8202
  if (!await isAuthenticated()) {
@@ -7452,7 +8204,7 @@ function registerLogoutCommand(program2) {
7452
8204
  outputSuccess({ cleared: true });
7453
8205
  return;
7454
8206
  }
7455
- console.log(chalk13.dim("You are not currently logged in."));
8207
+ console.log(chalk17.dim("You are not currently logged in."));
7456
8208
  return;
7457
8209
  }
7458
8210
  const platformUrl = getPlatformUrl();
@@ -7467,19 +8219,72 @@ function registerLogoutCommand(program2) {
7467
8219
  return;
7468
8220
  }
7469
8221
  if (platformUrl) {
7470
- console.log(`${chalk13.green("Logged out successfully.")} Disconnected from ${platformUrl}`);
8222
+ console.log(`${chalk17.green("Logged out successfully.")} Disconnected from ${platformUrl}`);
7471
8223
  } else {
7472
8224
  console.log(
7473
- `${chalk13.green("Logged out successfully.")} Run \`agentver login\` to sign in again.`
8225
+ `${chalk17.green("Logged out successfully.")} Run \`agentver login\` to sign in again.`
7474
8226
  );
7475
8227
  }
7476
8228
  });
7477
8229
  }
7478
8230
 
8231
+ // src/commands/pin.ts
8232
+ import chalk18 from "chalk";
8233
+ function registerPinCommand(program2) {
8234
+ program2.command("pin <name>").description("Pin a package to skip it during updates").action((name) => {
8235
+ const jsonMode = isJSONMode();
8236
+ const projectRoot = process.cwd();
8237
+ const manifest = readManifest(projectRoot);
8238
+ const pkg2 = manifest.packages[name];
8239
+ if (!pkg2) {
8240
+ if (jsonMode) {
8241
+ outputError("NOT_FOUND", `Package "${name}" is not installed.`);
8242
+ } else {
8243
+ console.error(chalk18.red(`Package "${name}" is not installed.`));
8244
+ }
8245
+ process.exit(1);
8246
+ }
8247
+ pkg2.pinned = true;
8248
+ writeManifest(projectRoot, manifest);
8249
+ if (jsonMode) {
8250
+ outputSuccess({ name, pinned: true });
8251
+ return;
8252
+ }
8253
+ console.log(
8254
+ chalk18.green(`Pinned ${name}`) + chalk18.dim(" \u2014 this package will be skipped during updates")
8255
+ );
8256
+ });
8257
+ }
8258
+ function registerUnpinCommand(program2) {
8259
+ program2.command("unpin <name>").description("Unpin a package so it is included in updates").action((name) => {
8260
+ const jsonMode = isJSONMode();
8261
+ const projectRoot = process.cwd();
8262
+ const manifest = readManifest(projectRoot);
8263
+ const pkg2 = manifest.packages[name];
8264
+ if (!pkg2) {
8265
+ if (jsonMode) {
8266
+ outputError("NOT_FOUND", `Package "${name}" is not installed.`);
8267
+ } else {
8268
+ console.error(chalk18.red(`Package "${name}" is not installed.`));
8269
+ }
8270
+ process.exit(1);
8271
+ }
8272
+ delete pkg2.pinned;
8273
+ writeManifest(projectRoot, manifest);
8274
+ if (jsonMode) {
8275
+ outputSuccess({ name, pinned: false });
8276
+ return;
8277
+ }
8278
+ console.log(
8279
+ chalk18.green(`Unpinned ${name}`) + chalk18.dim(" \u2014 this package will be included in updates")
8280
+ );
8281
+ });
8282
+ }
8283
+
7479
8284
  // src/commands/publish.ts
7480
- import { existsSync as existsSync12, readFileSync as readFileSync10 } from "fs";
7481
- import { basename as basename4, join as join14, resolve as resolve2 } from "path";
7482
- import chalk14 from "chalk";
8285
+ import { existsSync as existsSync14, readFileSync as readFileSync13 } from "fs";
8286
+ import { basename as basename4, join as join17, resolve as resolve2 } from "path";
8287
+ import chalk19 from "chalk";
7483
8288
  import ora4 from "ora";
7484
8289
  var SEMVER_REGEX = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
7485
8290
  function parseFrontmatter2(content) {
@@ -7506,9 +8311,9 @@ function parseFrontmatter2(content) {
7506
8311
  };
7507
8312
  }
7508
8313
  function detectNamespace(skillDir) {
7509
- const skillMdPath = join14(skillDir, "SKILL.md");
7510
- if (!existsSync12(skillMdPath)) return null;
7511
- const content = readFileSync10(skillMdPath, "utf-8");
8314
+ const skillMdPath = join17(skillDir, "SKILL.md");
8315
+ if (!existsSync14(skillMdPath)) return null;
8316
+ const content = readFileSync13(skillMdPath, "utf-8");
7512
8317
  const fm = parseFrontmatter2(content);
7513
8318
  if (!fm) return null;
7514
8319
  const parts = skillDir.split("/");
@@ -7522,16 +8327,16 @@ function detectNamespace(skillDir) {
7522
8327
  function registerPublishCommand(program2) {
7523
8328
  program2.command("publish [path]").description("Publish a skill to the registry").option("--version <semver>", "Version to publish (uses frontmatter version if omitted)").option("--dry-run", "Validate without publishing").option("--skip-audit", "Skip security scan").option("--json", "Output as JSON").action(async (pathArg, options) => {
7524
8329
  const skillDir = pathArg ? resolve2(process.cwd(), pathArg) : process.cwd();
7525
- if (!existsSync12(join14(skillDir, "SKILL.md"))) {
8330
+ if (!existsSync14(join17(skillDir, "SKILL.md"))) {
7526
8331
  process.stderr.write(
7527
- chalk14.red(`No SKILL.md found in ${skillDir}. Cannot publish without a skill manifest.
8332
+ chalk19.red(`No SKILL.md found in ${skillDir}. Cannot publish without a skill manifest.
7528
8333
  `)
7529
8334
  );
7530
8335
  process.exit(1);
7531
8336
  }
7532
8337
  const spinner = ora4("Reading skill metadata...").start();
7533
8338
  try {
7534
- const skillMdContent = readFileSync10(join14(skillDir, "SKILL.md"), "utf-8");
8339
+ const skillMdContent = readFileSync13(join17(skillDir, "SKILL.md"), "utf-8");
7535
8340
  const frontmatter = parseFrontmatter2(skillMdContent);
7536
8341
  if (!frontmatter) {
7537
8342
  spinner.fail(
@@ -7573,7 +8378,7 @@ function registerPublishCommand(program2) {
7573
8378
  spinner.fail("Security audit failed. Fix the issues before publishing.");
7574
8379
  for (const finding of scanResult.findings) {
7575
8380
  process.stderr.write(
7576
- ` ${chalk14.red("BLOCK")} ${finding.file}:${String(finding.line ?? "?")} \u2014 ${finding.message}
8381
+ ` ${chalk19.red("BLOCK")} ${finding.file}:${String(finding.line ?? "?")} \u2014 ${finding.message}
7577
8382
  `
7578
8383
  );
7579
8384
  }
@@ -7583,7 +8388,7 @@ function registerPublishCommand(program2) {
7583
8388
  spinner.warn("Security audit warnings found:");
7584
8389
  for (const finding of scanResult.findings) {
7585
8390
  process.stderr.write(
7586
- ` ${chalk14.yellow("WARN")} ${finding.file}:${String(finding.line ?? "?")} \u2014 ${finding.message}
8391
+ ` ${chalk19.yellow("WARN")} ${finding.file}:${String(finding.line ?? "?")} \u2014 ${finding.message}
7587
8392
  `
7588
8393
  );
7589
8394
  }
@@ -7612,13 +8417,13 @@ function registerPublishCommand(program2) {
7612
8417
  );
7613
8418
  } else {
7614
8419
  process.stdout.write(
7615
- chalk14.yellow("[dry-run]") + ` Would publish ${chalk14.green(frontmatter.name)}@${chalk14.cyan(version)}
8420
+ chalk19.yellow("[dry-run]") + ` Would publish ${chalk19.green(frontmatter.name)}@${chalk19.cyan(version)}
7616
8421
  `
7617
8422
  );
7618
- process.stdout.write(chalk14.dim(` Namespace: @${namespace.org}/${namespace.name}
8423
+ process.stdout.write(chalk19.dim(` Namespace: @${namespace.org}/${namespace.name}
7619
8424
  `));
7620
8425
  process.stdout.write(
7621
- chalk14.dim(
8426
+ chalk19.dim(
7622
8427
  ` Files (${filesToPublish.length}): ${filesToPublish.map((f) => f.path).join(", ")}
7623
8428
  `
7624
8429
  )
@@ -7651,7 +8456,7 @@ function registerPublishCommand(program2) {
7651
8456
  );
7652
8457
  } else {
7653
8458
  spinner.succeed(
7654
- `Published ${chalk14.green(frontmatter.name)}@${chalk14.cyan(result.version)} ${chalk14.dim(`(${result.commitSha.slice(0, 7)})`)}`
8459
+ `Published ${chalk19.green(frontmatter.name)}@${chalk19.cyan(result.version)} ${chalk19.dim(`(${result.commitSha.slice(0, 7)})`)}`
7655
8460
  );
7656
8461
  }
7657
8462
  } catch (error) {
@@ -7662,11 +8467,11 @@ function registerPublishCommand(program2) {
7662
8467
  }
7663
8468
 
7664
8469
  // src/commands/remove.ts
7665
- import { existsSync as existsSync13, lstatSync as lstatSync2, rmSync as rmSync2 } from "fs";
7666
- import { join as join15 } from "path";
7667
- import chalk15 from "chalk";
8470
+ import { existsSync as existsSync15, lstatSync as lstatSync3, rmSync as rmSync2 } from "fs";
8471
+ import { join as join18 } from "path";
8472
+ import chalk20 from "chalk";
7668
8473
  function registerRemoveCommand(program2) {
7669
- program2.command("remove <name>").description("Remove an installed package").option("--dry-run", "Show what would be removed without making changes").action(async (name, options) => {
8474
+ program2.command("remove <name>").alias("uninstall").description("Remove an installed package").option("--dry-run", "Show what would be removed without making changes").action(async (name, options) => {
7670
8475
  const jsonMode = isJSONMode();
7671
8476
  const projectRoot = process.cwd();
7672
8477
  const manifest = readManifest(projectRoot);
@@ -7676,7 +8481,7 @@ function registerRemoveCommand(program2) {
7676
8481
  outputError("NOT_FOUND", `Package "${name}" is not installed.`);
7677
8482
  process.exit(1);
7678
8483
  }
7679
- console.error(chalk15.red(`Package "${name}" is not installed.`));
8484
+ console.error(chalk20.red(`Package "${name}" is not installed.`));
7680
8485
  process.exit(1);
7681
8486
  }
7682
8487
  const shortName = name.split("/").pop();
@@ -7688,15 +8493,15 @@ function registerRemoveCommand(program2) {
7688
8493
  for (const agentId of pkg2.agents) {
7689
8494
  const placementPath = getSkillPlacementPath(agentId, shortName, "project");
7690
8495
  if (placementPath) {
7691
- removedPaths.push(join15(projectRoot, placementPath));
8496
+ removedPaths.push(join18(projectRoot, placementPath));
7692
8497
  }
7693
8498
  }
7694
8499
  } else {
7695
8500
  for (const agentId of pkg2.agents) {
7696
8501
  const placementPath = getSkillPlacementPath(agentId, shortName, "project");
7697
8502
  if (!placementPath) continue;
7698
- const fullPath = join15(projectRoot, placementPath);
7699
- if (existsSync13(fullPath)) {
8503
+ const fullPath = join18(projectRoot, placementPath);
8504
+ if (existsSync15(fullPath)) {
7700
8505
  removedPaths.push(fullPath);
7701
8506
  }
7702
8507
  }
@@ -7710,28 +8515,28 @@ function registerRemoveCommand(program2) {
7710
8515
  });
7711
8516
  return;
7712
8517
  }
7713
- console.log(`${chalk15.yellow("[dry-run]")} Would remove ${chalk15.green(name)}`);
8518
+ console.log(`${chalk20.yellow("[dry-run]")} Would remove ${chalk20.green(name)}`);
7714
8519
  if (hasCanonical) {
7715
8520
  const canonicalPath = getCanonicalSkillPath(projectRoot, shortName, "project");
7716
- console.log(chalk15.dim(" Canonical path to remove:"));
7717
- console.log(chalk15.dim(` ${canonicalPath}`));
7718
- console.log(chalk15.dim(" Agent symlinks to remove:"));
8521
+ console.log(chalk20.dim(" Canonical path to remove:"));
8522
+ console.log(chalk20.dim(` ${canonicalPath}`));
8523
+ console.log(chalk20.dim(" Agent symlinks to remove:"));
7719
8524
  for (const agentId of pkg2.agents) {
7720
8525
  const placementPath = getSkillPlacementPath(agentId, shortName, "project");
7721
8526
  if (placementPath) {
7722
- console.log(chalk15.dim(` ${join15(projectRoot, placementPath)}`));
8527
+ console.log(chalk20.dim(` ${join18(projectRoot, placementPath)}`));
7723
8528
  }
7724
8529
  }
7725
8530
  } else {
7726
- const pathsToRemove = removedPaths.filter((p) => existsSync13(p));
8531
+ const pathsToRemove = removedPaths.filter((p) => existsSync15(p));
7727
8532
  if (pathsToRemove.length > 0) {
7728
- console.log(chalk15.dim(" Paths to remove:"));
8533
+ console.log(chalk20.dim(" Paths to remove:"));
7729
8534
  for (const p of pathsToRemove) {
7730
- console.log(chalk15.dim(` ${p}`));
8535
+ console.log(chalk20.dim(` ${p}`));
7731
8536
  }
7732
8537
  }
7733
8538
  }
7734
- console.log(chalk15.dim(" Would update manifest and lockfile"));
8539
+ console.log(chalk20.dim(" Would update manifest and lockfile"));
7735
8540
  return;
7736
8541
  }
7737
8542
  const spinner = createSpinner(`Removing ${name}...`).start();
@@ -7742,8 +8547,8 @@ function registerRemoveCommand(program2) {
7742
8547
  for (const agentId of pkg2.agents) {
7743
8548
  const placementPath = getSkillPlacementPath(agentId, shortName, "project");
7744
8549
  if (!placementPath) continue;
7745
- const fullPath = join15(projectRoot, placementPath);
7746
- if (existsSync13(fullPath) || isSymlinkPath(fullPath)) {
8550
+ const fullPath = join18(projectRoot, placementPath);
8551
+ if (existsSync15(fullPath) || isSymlinkPath(fullPath)) {
7747
8552
  rmSync2(fullPath, { recursive: true, force: true });
7748
8553
  }
7749
8554
  }
@@ -7761,35 +8566,35 @@ function registerRemoveCommand(program2) {
7761
8566
  paths: removedPaths
7762
8567
  });
7763
8568
  } else {
7764
- spinner.succeed(`Removed ${chalk15.green(name)}`);
8569
+ spinner.succeed(`Removed ${chalk20.green(name)}`);
7765
8570
  }
7766
8571
  });
7767
8572
  }
7768
8573
  function isSymlinkPath(filePath) {
7769
8574
  try {
7770
- return lstatSync2(filePath).isSymbolicLink();
8575
+ return lstatSync3(filePath).isSymbolicLink();
7771
8576
  } catch {
7772
8577
  return false;
7773
8578
  }
7774
8579
  }
7775
8580
 
7776
8581
  // src/commands/save.ts
7777
- import { existsSync as existsSync14, readFileSync as readFileSync11 } from "fs";
7778
- import { basename as basename5, join as join16, resolve as resolve3 } from "path";
7779
- import chalk16 from "chalk";
8582
+ import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
8583
+ import { basename as basename5, join as join19, resolve as resolve3 } from "path";
8584
+ import chalk21 from "chalk";
7780
8585
  import ora5 from "ora";
7781
8586
  function detectSkillName(skillDir) {
7782
- const skillMdPath = join16(skillDir, "SKILL.md");
7783
- if (!existsSync14(skillMdPath)) {
8587
+ const skillMdPath = join19(skillDir, "SKILL.md");
8588
+ if (!existsSync16(skillMdPath)) {
7784
8589
  return null;
7785
8590
  }
7786
- const content = readFileSync11(skillMdPath, "utf-8");
8591
+ const content = readFileSync14(skillMdPath, "utf-8");
7787
8592
  const nameMatch = content.match(/^name:\s*(.+)$/m);
7788
8593
  return nameMatch?.[1]?.trim() ?? basename5(skillDir);
7789
8594
  }
7790
8595
  function resolveSkillContext(options) {
7791
8596
  const skillDir = options.path ? resolve3(process.cwd(), options.path) : process.cwd();
7792
- if (!existsSync14(skillDir)) {
8597
+ if (!existsSync16(skillDir)) {
7793
8598
  return null;
7794
8599
  }
7795
8600
  const skillName = detectSkillName(skillDir);
@@ -7815,7 +8620,7 @@ function registerSaveCommand(program2) {
7815
8620
  if (!context) {
7816
8621
  const target = options.path ?? process.cwd();
7817
8622
  process.stderr.write(
7818
- chalk16.red(`No SKILL.md found in ${target}. Run this from a skill directory.
8623
+ chalk21.red(`No SKILL.md found in ${target}. Run this from a skill directory.
7819
8624
  `)
7820
8625
  );
7821
8626
  process.exit(1);
@@ -7825,7 +8630,7 @@ function registerSaveCommand(program2) {
7825
8630
  const namespace = findNamespace(projectRoot, skillName);
7826
8631
  if (!namespace) {
7827
8632
  process.stderr.write(
7828
- chalk16.red(
8633
+ chalk21.red(
7829
8634
  `Skill "${skillName}" not found in manifest. Install it first or check the directory.
7830
8635
  `
7831
8636
  )
@@ -7861,13 +8666,13 @@ function registerSaveCommand(program2) {
7861
8666
  );
7862
8667
  } else {
7863
8668
  process.stdout.write(
7864
- chalk16.yellow("[dry-run]") + ` Would save ${chalk16.green(skillName)} to @${namespace.org}/${namespace.name}
8669
+ chalk21.yellow("[dry-run]") + ` Would save ${chalk21.green(skillName)} to @${namespace.org}/${namespace.name}
7865
8670
  `
7866
8671
  );
7867
- process.stdout.write(chalk16.dim(` Message: ${commitMessage}
8672
+ process.stdout.write(chalk21.dim(` Message: ${commitMessage}
7868
8673
  `));
7869
8674
  process.stdout.write(
7870
- chalk16.dim(` Files: ${filesToSave.map((f) => f.path).join(", ")}
8675
+ chalk21.dim(` Files: ${filesToSave.map((f) => f.path).join(", ")}
7871
8676
  `)
7872
8677
  );
7873
8678
  }
@@ -7904,7 +8709,7 @@ function registerSaveCommand(program2) {
7904
8709
  );
7905
8710
  } else {
7906
8711
  spinner.succeed(
7907
- `Saved ${chalk16.green(skillName)} ${chalk16.dim(`(${result.commitSha.slice(0, 7)})`)}`
8712
+ `Saved ${chalk21.green(skillName)} ${chalk21.dim(`(${result.commitSha.slice(0, 7)})`)}`
7908
8713
  );
7909
8714
  }
7910
8715
  } catch (error) {
@@ -7915,19 +8720,19 @@ function registerSaveCommand(program2) {
7915
8720
  }
7916
8721
 
7917
8722
  // src/commands/scan.ts
7918
- import { readFileSync as readFileSync12 } from "fs";
7919
- import { homedir as homedir7 } from "os";
7920
- import chalk17 from "chalk";
8723
+ import { readFileSync as readFileSync15 } from "fs";
8724
+ import { homedir as homedir8 } from "os";
8725
+ import chalk22 from "chalk";
7921
8726
  function registerScanCommand(program2) {
7922
8727
  program2.command("scan [path]").description("Scan directory for agent configs and skills").action(async (path) => {
7923
8728
  const jsonMode = isJSONMode();
7924
8729
  const targetPath = path ?? process.cwd();
7925
8730
  const projectAgents = detectInstalledAgents(targetPath);
7926
- const globalAgents = detectGlobalAgents(homedir7());
8731
+ const globalAgents = detectGlobalAgents(homedir8());
7927
8732
  const seenIds = new Set(projectAgents.map((a) => a.id));
7928
8733
  const agents = [...projectAgents, ...globalAgents.filter((a) => !seenIds.has(a.id))];
7929
8734
  const projectFiles = scanForSkillFiles(targetPath);
7930
- const globalFiles = scanGlobalSkillFiles(homedir7());
8735
+ const globalFiles = scanGlobalSkillFiles(homedir8());
7931
8736
  const seenPaths = new Set(projectFiles.map((f) => f.path));
7932
8737
  const files = [...projectFiles, ...globalFiles.filter((f) => !seenPaths.has(f.path))];
7933
8738
  if (jsonMode) {
@@ -7946,58 +8751,58 @@ function registerScanCommand(program2) {
7946
8751
  outputSuccess(result);
7947
8752
  return;
7948
8753
  }
7949
- console.log(chalk17.bold("\nDetected agents:\n"));
8754
+ console.log(chalk22.bold("\nDetected agents:\n"));
7950
8755
  if (agents.length === 0) {
7951
- console.log(chalk17.dim(" No agents detected."));
8756
+ console.log(chalk22.dim(" No agents detected."));
7952
8757
  } else {
7953
8758
  for (const agent of agents) {
7954
- console.log(` ${chalk17.green(agent.name)} ${chalk17.dim(agent.configPath)}`);
8759
+ console.log(` ${chalk22.green(agent.name)} ${chalk22.dim(agent.configPath)}`);
7955
8760
  }
7956
8761
  }
7957
- console.log(chalk17.bold("\nDiscovered files:\n"));
8762
+ console.log(chalk22.bold("\nDiscovered files:\n"));
7958
8763
  if (files.length === 0) {
7959
- console.log(chalk17.dim(" No skill or config files found."));
8764
+ console.log(chalk22.dim(" No skill or config files found."));
7960
8765
  } else {
7961
8766
  for (const file of files) {
7962
- const typeLabel = chalk17.dim(`[${file.detectedType}]`);
7963
- const agentLabel = chalk17.cyan(`(${file.agentId})`);
7964
- console.log(` ${typeLabel} ${agentLabel} ${file.name} ${chalk17.dim(file.path)}`);
8767
+ const typeLabel = chalk22.dim(`[${file.detectedType}]`);
8768
+ const agentLabel = chalk22.cyan(`(${file.agentId})`);
8769
+ console.log(` ${typeLabel} ${agentLabel} ${file.name} ${chalk22.dim(file.path)}`);
7965
8770
  }
7966
8771
  }
7967
8772
  const skillFiles = files.filter((f) => f.detectedType === "SKILL");
7968
8773
  if (skillFiles.length > 0) {
7969
- console.log(chalk17.bold("\nSkill spec validation:\n"));
8774
+ console.log(chalk22.bold("\nSkill spec validation:\n"));
7970
8775
  for (const file of skillFiles) {
7971
8776
  let content;
7972
8777
  try {
7973
- content = readFileSync12(file.path, "utf-8");
8778
+ content = readFileSync15(file.path, "utf-8");
7974
8779
  } catch {
7975
- console.log(` ${chalk17.red("\u2717")} ${file.name} ${chalk17.dim("Could not read file")}`);
8780
+ console.log(` ${chalk22.red("\u2717")} ${file.name} ${chalk22.dim("Could not read file")}`);
7976
8781
  continue;
7977
8782
  }
7978
8783
  const result = validateSkillMd(content);
7979
8784
  if (result.valid && result.specCompliant) {
7980
8785
  console.log(
7981
- ` ${chalk17.green("\u2713")} ${file.name} ${chalk17.green("Agent Skills spec compliant")}`
8786
+ ` ${chalk22.green("\u2713")} ${file.name} ${chalk22.green("Agent Skills spec compliant")}`
7982
8787
  );
7983
8788
  } else if (result.valid && !result.specCompliant) {
7984
8789
  console.log(
7985
- ` ${chalk17.yellow("\u2713")} ${file.name} ${chalk17.yellow("Valid (Agentver extended)")}`
8790
+ ` ${chalk22.yellow("\u2713")} ${file.name} ${chalk22.yellow("Valid (Agentver extended)")}`
7986
8791
  );
7987
8792
  } else {
7988
- console.log(` ${chalk17.red("\u2717")} ${file.name} ${chalk17.red("Invalid")}`);
8793
+ console.log(` ${chalk22.red("\u2717")} ${file.name} ${chalk22.red("Invalid")}`);
7989
8794
  for (const error of result.errors) {
7990
- console.log(` ${chalk17.red(`\u2514 ${error}`)}`);
8795
+ console.log(` ${chalk22.red(`\u2514 ${error}`)}`);
7991
8796
  }
7992
8797
  }
7993
8798
  if (result.warnings.length > 0) {
7994
8799
  for (const warning of result.warnings) {
7995
- console.log(` ${chalk17.yellow(`\u26A0 ${warning}`)}`);
8800
+ console.log(` ${chalk22.yellow(`\u26A0 ${warning}`)}`);
7996
8801
  }
7997
8802
  }
7998
8803
  if (result.agentverExtensions.length > 0) {
7999
8804
  console.log(
8000
- ` ${chalk17.dim(`Agentver extensions: ${result.agentverExtensions.join(", ")}`)}`
8805
+ ` ${chalk22.dim(`Agentver extensions: ${result.agentverExtensions.join(", ")}`)}`
8001
8806
  );
8002
8807
  }
8003
8808
  }
@@ -8005,7 +8810,7 @@ function registerScanCommand(program2) {
8005
8810
  const manifest = readManifest(targetPath);
8006
8811
  const manifestEntries = Object.entries(manifest.packages);
8007
8812
  if (manifestEntries.length > 0) {
8008
- console.log(chalk17.bold(`
8813
+ console.log(chalk22.bold(`
8009
8814
  Installed skills (${manifestEntries.length}):
8010
8815
  `));
8011
8816
  for (const [name, pkg2] of manifestEntries) {
@@ -8016,12 +8821,12 @@ Installed skills (${manifestEntries.length}):
8016
8821
  const ref = `@${source.ref}`;
8017
8822
  const commit = `(${source.commit.slice(0, 7)})`;
8018
8823
  console.log(
8019
- ` ${chalk17.green(name.padEnd(18))} ${chalk17.dim(sourcePath.padEnd(40))} ${chalk17.cyan(ref.padEnd(10))} ${chalk17.dim(commit)} ${chalk17.dim(agentList)}`
8824
+ ` ${chalk22.green(name.padEnd(18))} ${chalk22.dim(sourcePath.padEnd(40))} ${chalk22.cyan(ref.padEnd(10))} ${chalk22.dim(commit)} ${chalk22.dim(agentList)}`
8020
8825
  );
8021
8826
  } else {
8022
8827
  const sourceLabel = `${source.hostname} (well-known)`;
8023
8828
  console.log(
8024
- ` ${chalk17.green(name.padEnd(18))} ${chalk17.dim(sourceLabel.padEnd(40))} ${chalk17.dim("[well-known]").padEnd(10)} ${chalk17.dim(agentList)}`
8829
+ ` ${chalk22.green(name.padEnd(18))} ${chalk22.dim(sourceLabel.padEnd(40))} ${chalk22.dim("[well-known]").padEnd(10)} ${chalk22.dim(agentList)}`
8025
8830
  );
8026
8831
  }
8027
8832
  }
@@ -8031,7 +8836,7 @@ Installed skills (${manifestEntries.length}):
8031
8836
  }
8032
8837
 
8033
8838
  // src/commands/search.ts
8034
- import chalk18 from "chalk";
8839
+ import chalk23 from "chalk";
8035
8840
  import ora6 from "ora";
8036
8841
 
8037
8842
  // src/registry/skills-sh.ts
@@ -8109,60 +8914,60 @@ function formatInstallCount(count) {
8109
8914
  }
8110
8915
  function renderPlatformResults(results, total) {
8111
8916
  if (results.length === 0) return;
8112
- process.stdout.write(chalk18.bold(`
8917
+ process.stdout.write(chalk23.bold(`
8113
8918
  Platform results (${total}):
8114
8919
 
8115
8920
  `));
8116
8921
  for (const result of results) {
8117
- const desc = result.description ? chalk18.dim(` \u2014 ${result.description}`) : "";
8118
- const stars = result.starCount > 0 ? chalk18.yellow(` \u2605 ${result.starCount}`) : "";
8119
- const installs = result.installCount > 0 ? chalk18.cyan(` \u2193 ${formatInstallCount(result.installCount)}`) : "";
8120
- const cats = result.categories.length > 0 ? chalk18.dim(` [${result.categories.map((c) => c.name).join(", ")}]`) : "";
8121
- process.stdout.write(` ${chalk18.green(result.slug)}${stars}${installs}${cats}${desc}
8922
+ const desc = result.description ? chalk23.dim(` \u2014 ${result.description}`) : "";
8923
+ const stars = result.starCount > 0 ? chalk23.yellow(` \u2605 ${result.starCount}`) : "";
8924
+ const installs = result.installCount > 0 ? chalk23.cyan(` \u2193 ${formatInstallCount(result.installCount)}`) : "";
8925
+ const cats = result.categories.length > 0 ? chalk23.dim(` [${result.categories.map((c) => c.name).join(", ")}]`) : "";
8926
+ process.stdout.write(` ${chalk23.green(result.slug)}${stars}${installs}${cats}${desc}
8122
8927
  `);
8123
8928
  }
8124
8929
  process.stdout.write("\n");
8125
8930
  }
8126
8931
  function renderCommunityResults(results) {
8127
8932
  if (results.length === 0) return;
8128
- process.stdout.write(chalk18.bold(`
8933
+ process.stdout.write(chalk23.bold(`
8129
8934
  Skills from skills.sh:
8130
8935
 
8131
8936
  `));
8132
8937
  for (const result of results) {
8133
- const nameCol = chalk18.green(result.name);
8134
- const sourceCol = chalk18.dim(`(${result.source})`);
8135
- const installCol = chalk18.cyan(`\u2193 ${formatInstallCount(result.installCount)}`);
8938
+ const nameCol = chalk23.green(result.name);
8939
+ const sourceCol = chalk23.dim(`(${result.source})`);
8940
+ const installCol = chalk23.cyan(`\u2193 ${formatInstallCount(result.installCount)}`);
8136
8941
  process.stdout.write(` ${nameCol} ${sourceCol} ${installCol}
8137
8942
  `);
8138
8943
  if (result.description) {
8139
- process.stdout.write(` ${chalk18.dim(result.description)}
8944
+ process.stdout.write(` ${chalk23.dim(result.description)}
8140
8945
  `);
8141
8946
  }
8142
8947
  process.stdout.write("\n");
8143
8948
  }
8144
8949
  process.stdout.write(
8145
- chalk18.dim(" Install with: ") + chalk18.white("agentver install github.com/{source}/{name}") + "\n\n"
8950
+ chalk23.dim(" Install with: ") + chalk23.white("agentver install github.com/{source}/{name}") + "\n\n"
8146
8951
  );
8147
8952
  }
8148
8953
  function renderWellKnownResults(hostname3, skills) {
8149
8954
  if (skills.length === 0) return;
8150
- process.stdout.write(chalk18.bold(`
8955
+ process.stdout.write(chalk23.bold(`
8151
8956
  Skills from ${hostname3}:
8152
8957
 
8153
8958
  `));
8154
8959
  for (const skill of skills) {
8155
- process.stdout.write(` ${chalk18.green(skill.name)} ${chalk18.dim(`\u2014 ${skill.description}`)}
8960
+ process.stdout.write(` ${chalk23.green(skill.name)} ${chalk23.dim(`\u2014 ${skill.description}`)}
8156
8961
  `);
8157
8962
  process.stdout.write(
8158
- ` ${chalk18.dim("Install:")} ${chalk18.white(`agentver install ${hostname3}/${skill.name}`)}
8963
+ ` ${chalk23.dim("Install:")} ${chalk23.white(`agentver install ${hostname3}/${skill.name}`)}
8159
8964
  `
8160
8965
  );
8161
8966
  process.stdout.write("\n");
8162
8967
  }
8163
8968
  }
8164
8969
  function renderNoResults(query) {
8165
- process.stdout.write(chalk18.dim(`No results for "${query}"
8970
+ process.stdout.write(chalk23.dim(`No results for "${query}"
8166
8971
  `));
8167
8972
  }
8168
8973
  function registerSearchCommand(program2) {
@@ -8177,7 +8982,7 @@ function registerSearchCommand(program2) {
8177
8982
  if (requestedSource) {
8178
8983
  if (!["platform", "community", "well-known", "all"].includes(requestedSource)) {
8179
8984
  process.stderr.write(
8180
- chalk18.red(
8985
+ chalk23.red(
8181
8986
  `Invalid source "${requestedSource}". Use: platform, community, well-known, or all
8182
8987
  `
8183
8988
  )
@@ -8187,7 +8992,7 @@ function registerSearchCommand(program2) {
8187
8992
  source = requestedSource;
8188
8993
  if (source === "platform" && !connected) {
8189
8994
  process.stderr.write(
8190
- chalk18.red("Not connected to a platform. Run `agentver login <url>` to connect.\n")
8995
+ chalk23.red("Not connected to a platform. Run `agentver login <url>` to connect.\n")
8191
8996
  );
8192
8997
  process.exit(1);
8193
8998
  }
@@ -8255,7 +9060,7 @@ function registerSearchCommand(program2) {
8255
9060
  if (communityResults.length > 0) {
8256
9061
  const example = communityResults[0];
8257
9062
  process.stdout.write(
8258
- chalk18.dim(" Example: ") + chalk18.white(`agentver install ${toGitInstallSource(example)}`) + "\n"
9063
+ chalk23.dim(" Example: ") + chalk23.white(`agentver install ${toGitInstallSource(example)}`) + "\n"
8259
9064
  );
8260
9065
  }
8261
9066
  } catch (error) {
@@ -8267,13 +9072,13 @@ function registerSearchCommand(program2) {
8267
9072
  }
8268
9073
 
8269
9074
  // src/commands/status.ts
8270
- import chalk19 from "chalk";
9075
+ import chalk24 from "chalk";
8271
9076
  var STATUS_SYMBOLS = {
8272
- "up-to-date": chalk19.green("\u2713"),
8273
- modified: chalk19.yellow("M"),
8274
- upstream: chalk19.cyan("U"),
8275
- both: chalk19.red("MU"),
8276
- unknown: chalk19.dim("?")
9077
+ "up-to-date": chalk24.green("\u2713"),
9078
+ modified: chalk24.yellow("M"),
9079
+ upstream: chalk24.cyan("U"),
9080
+ both: chalk24.red("MU"),
9081
+ unknown: chalk24.dim("?")
8277
9082
  };
8278
9083
  function parseManifestUri2(uri) {
8279
9084
  const parts = uri.split("/");
@@ -8295,7 +9100,7 @@ async function readLocalFiles2(projectRoot, packageName, agents) {
8295
9100
  return [];
8296
9101
  }
8297
9102
  async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileIntegrity, offline) {
8298
- const { source, agents } = manifestEntry;
9103
+ const { source, agents, pinned } = manifestEntry;
8299
9104
  if (source.type === "well-known") {
8300
9105
  let locallyModified2 = false;
8301
9106
  try {
@@ -8313,7 +9118,8 @@ async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileInte
8313
9118
  sourceUri: source.hostname,
8314
9119
  ref: "well-known",
8315
9120
  commit: "",
8316
- agents
9121
+ agents,
9122
+ pinned: pinned || void 0
8317
9123
  };
8318
9124
  }
8319
9125
  if (source.uri === "unknown") {
@@ -8323,7 +9129,8 @@ async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileInte
8323
9129
  sourceUri: source.uri,
8324
9130
  ref: source.ref,
8325
9131
  commit: source.commit,
8326
- agents
9132
+ agents,
9133
+ pinned: pinned || void 0
8327
9134
  };
8328
9135
  }
8329
9136
  let locallyModified = false;
@@ -8367,18 +9174,20 @@ async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileInte
8367
9174
  ref: source.ref,
8368
9175
  commit: source.commit,
8369
9176
  upstreamCommit: upstreamChanged ? upstreamCommit : void 0,
8370
- agents
9177
+ agents,
9178
+ pinned: pinned || void 0
8371
9179
  };
8372
9180
  }
8373
9181
  function formatStatusLine(status) {
8374
9182
  const symbol = STATUS_SYMBOLS[status.category];
8375
9183
  const padding = status.category === "both" ? "" : " ";
8376
9184
  if (status.category === "unknown") {
8377
- return ` ${symbol} ${chalk19.white(status.name)} ${chalk19.dim("unknown source")}`;
9185
+ return ` ${symbol} ${chalk24.white(status.name)} ${chalk24.dim("unknown source")}`;
8378
9186
  }
8379
9187
  const shortCommit = status.commit.slice(0, 7);
8380
- const upstream = status.upstreamCommit ? ` ${chalk19.dim("\u2192")} ${chalk19.cyan(`upstream: ${status.upstreamCommit.slice(0, 7)}`)}` : "";
8381
- return ` ${symbol}${padding} ${chalk19.white(status.name)} ${chalk19.dim(status.sourceUri)} ${chalk19.cyan(`@${status.ref}`)} ${chalk19.dim(`(${shortCommit})`)}${upstream}`;
9188
+ const upstream = status.upstreamCommit ? ` ${chalk24.dim("\u2192")} ${chalk24.cyan(`upstream: ${status.upstreamCommit.slice(0, 7)}`)}` : "";
9189
+ const pinned = status.pinned ? chalk24.yellow(" [pinned]") : "";
9190
+ return ` ${symbol}${padding} ${chalk24.white(status.name)}${pinned} ${chalk24.dim(status.sourceUri)} ${chalk24.cyan(`@${status.ref}`)} ${chalk24.dim(`(${shortCommit})`)}${upstream}`;
8382
9191
  }
8383
9192
  function buildStatusOutput(statuses) {
8384
9193
  return {
@@ -8396,7 +9205,8 @@ function toStatusResult(output) {
8396
9205
  name: p.name,
8397
9206
  status: p.category,
8398
9207
  modified: p.category === "modified" || p.category === "both",
8399
- upstream: p.category === "upstream" || p.category === "both"
9208
+ upstream: p.category === "upstream" || p.category === "both",
9209
+ pinned: p.pinned || void 0
8400
9210
  })),
8401
9211
  summary: {
8402
9212
  total: output.total,
@@ -8418,7 +9228,7 @@ function registerStatusCommand(program2) {
8418
9228
  if (jsonMode) {
8419
9229
  outputSuccess(toStatusResult(buildStatusOutput([])));
8420
9230
  } else {
8421
- console.log(chalk19.dim("No packages installed."));
9231
+ console.log(chalk24.dim("No packages installed."));
8422
9232
  }
8423
9233
  return;
8424
9234
  }
@@ -8441,7 +9251,7 @@ function registerStatusCommand(program2) {
8441
9251
  outputSuccess(toStatusResult(buildStatusOutput(statuses)));
8442
9252
  return;
8443
9253
  }
8444
- console.log(chalk19.bold(`
9254
+ console.log(chalk24.bold(`
8445
9255
  Installed skills (${statuses.length}):
8446
9256
  `));
8447
9257
  for (const status of statuses) {
@@ -8452,16 +9262,16 @@ Installed skills (${statuses.length}):
8452
9262
  }
8453
9263
 
8454
9264
  // src/commands/suggest.ts
8455
- import { existsSync as existsSync15 } from "fs";
8456
- import { join as join17 } from "path";
8457
- import chalk20 from "chalk";
9265
+ import { existsSync as existsSync17 } from "fs";
9266
+ import { join as join20 } from "path";
9267
+ import chalk25 from "chalk";
8458
9268
  var HTTP_TIMEOUT_MS2 = 15e3;
8459
9269
  async function readLocalFiles3(projectRoot, packageName, agents) {
8460
9270
  for (const agentId of agents) {
8461
9271
  const placementPath = getSkillPlacementPath(agentId, packageName, "project");
8462
9272
  if (!placementPath) continue;
8463
- const fullPath = join17(projectRoot, placementPath);
8464
- if (!existsSync15(fullPath)) continue;
9273
+ const fullPath = join20(projectRoot, placementPath);
9274
+ if (!existsSync17(fullPath)) continue;
8465
9275
  const files = await readFilesFromDirectory(fullPath);
8466
9276
  return files.map((f) => ({ path: f.path, content: f.content }));
8467
9277
  }
@@ -8509,141 +9319,211 @@ async function postToPlatform(path, body) {
8509
9319
  throw error;
8510
9320
  }
8511
9321
  }
9322
+ function buildEndpoint(manifestEntry, packageName) {
9323
+ if (manifestEntry.source.type !== "git") return "";
9324
+ const orgSlug = manifestEntry.source.uri.split("/")[1] ?? "";
9325
+ return `/skills/@${orgSlug}/${packageName}/suggestions`;
9326
+ }
9327
+ async function submitSuggestion(projectRoot, packageName, manifestEntry, title, description) {
9328
+ const localFiles = await readLocalFiles3(projectRoot, packageName, manifestEntry.agents);
9329
+ if (localFiles.length === 0) {
9330
+ throw new Error(`No local files found for "${packageName}".`);
9331
+ }
9332
+ const endpoint = buildEndpoint(manifestEntry, packageName);
9333
+ const requestBody = {
9334
+ title,
9335
+ description,
9336
+ files: localFiles
9337
+ };
9338
+ const result = await postToPlatform(endpoint, requestBody);
9339
+ return { localFiles, result };
9340
+ }
8512
9341
  function registerSuggestCommand(program2) {
8513
- program2.command("suggest <title>").alias("propose").description("Create a suggestion from local modifications (requires platform connection)").option("-d, --description <text>", "Suggestion description").option("--dry-run", "Show what would be suggested without submitting").action(async (title, options) => {
8514
- const json = isJSONMode();
8515
- const platformUrl = getPlatformUrl();
8516
- const creds = await getCredentials();
8517
- if (!options.dryRun && (!platformUrl || !creds?.token && !creds?.apiKey)) {
8518
- if (json) {
8519
- outputError(
8520
- "AUTH_REQUIRED",
8521
- "Not connected to a platform. Run `agentver login <url>` first."
8522
- );
9342
+ program2.command("suggest <title>").alias("propose").description("Create a suggestion from local modifications (requires platform connection)").option("-d, --description <text>", "Suggestion description").option("--name <name>", "Target a specific modified package by name").option("--dry-run", "Show what would be suggested without submitting").action(
9343
+ async (title, options) => {
9344
+ const json = isJSONMode();
9345
+ const platformUrl = getPlatformUrl();
9346
+ const creds = await getCredentials();
9347
+ if (!options.dryRun && (!platformUrl || !creds?.token && !creds?.apiKey)) {
9348
+ if (json) {
9349
+ outputError(
9350
+ "AUTH_REQUIRED",
9351
+ "Not connected to a platform. Run `agentver login <url>` first."
9352
+ );
9353
+ process.exit(1);
9354
+ }
9355
+ console.error(chalk25.red("Not connected to a platform. Run `agentver login <url>` first."));
8523
9356
  process.exit(1);
8524
9357
  }
8525
- console.error(chalk20.red("Not connected to a platform. Run `agentver login <url>` first."));
8526
- process.exit(1);
8527
- }
8528
- const projectRoot = process.cwd();
8529
- const manifest = readManifest(projectRoot);
8530
- const lockfile = readLockfile(projectRoot);
8531
- const modifiedPackages = [];
8532
- for (const [name, manifestEntry2] of Object.entries(manifest.packages)) {
8533
- const lockfileEntry = lockfile.packages[name];
8534
- if (!lockfileEntry) continue;
8535
- const { agents: agents2 } = manifestEntry2;
8536
- const localFiles = await readLocalFiles3(projectRoot, name, agents2);
8537
- if (localFiles.length === 0) continue;
8538
- const currentIntegrity = computeSha256FromFiles(localFiles);
8539
- if (currentIntegrity !== lockfileEntry.integrity) {
8540
- modifiedPackages.push(name);
8541
- }
8542
- }
8543
- if (modifiedPackages.length === 0) {
8544
- if (json) {
8545
- outputError("NO_CHANGES", "No modified packages detected.");
8546
- process.exit(1);
9358
+ const projectRoot = process.cwd();
9359
+ const manifest = readManifest(projectRoot);
9360
+ const lockfile = readLockfile(projectRoot);
9361
+ const modifiedPackages = [];
9362
+ for (const [name, manifestEntry] of Object.entries(manifest.packages)) {
9363
+ const lockfileEntry = lockfile.packages[name];
9364
+ if (!lockfileEntry) continue;
9365
+ const { agents } = manifestEntry;
9366
+ const localFiles = await readLocalFiles3(projectRoot, name, agents);
9367
+ if (localFiles.length === 0) continue;
9368
+ const currentIntegrity = computeSha256FromFiles(localFiles);
9369
+ if (currentIntegrity !== lockfileEntry.integrity) {
9370
+ modifiedPackages.push(name);
9371
+ }
8547
9372
  }
8548
- console.log(chalk20.dim("No modified packages detected."));
8549
- return;
8550
- }
8551
- const targetName = modifiedPackages[0];
8552
- const manifestEntry = manifest.packages[targetName];
8553
- const { source, agents } = manifestEntry;
8554
- if (source.type === "well-known") {
8555
- if (json) {
8556
- outputError(
8557
- "UNSUPPORTED_SOURCE",
8558
- `Package "${targetName}" was installed from a well-known source. Suggestions are not supported.`
8559
- );
8560
- } else {
8561
- console.error(
8562
- chalk20.red(
8563
- `Package "${targetName}" was installed from a well-known source (${source.hostname}).`
8564
- )
8565
- );
8566
- console.error(chalk20.dim("Suggestions are not supported for well-known sources."));
9373
+ if (modifiedPackages.length === 0) {
9374
+ if (json) {
9375
+ outputError("NO_CHANGES", "No modified packages detected.");
9376
+ process.exit(1);
9377
+ }
9378
+ console.log(chalk25.dim("No modified packages detected."));
9379
+ return;
8567
9380
  }
8568
- process.exit(1);
8569
- }
8570
- const spinner = createSpinner("Reading local files...").start();
8571
- try {
8572
- const localFiles = await readLocalFiles3(projectRoot, targetName, agents);
8573
- if (localFiles.length === 0) {
8574
- spinner.fail(`No local files found for "${targetName}".`);
9381
+ const targets = options.name ? modifiedPackages.filter((n) => n === options.name) : modifiedPackages;
9382
+ if (targets.length === 0 && options.name) {
9383
+ const message = `Package "${options.name}" is not in the modified list. Modified: ${modifiedPackages.join(", ")}`;
8575
9384
  if (json) {
8576
- outputError("NOT_FOUND", `No local files found for "${targetName}".`);
9385
+ outputError("NOT_FOUND", message);
9386
+ process.exit(1);
9387
+ }
9388
+ console.error(chalk25.red(message));
9389
+ process.exit(1);
9390
+ }
9391
+ const unsupportedTargets = targets.filter(
9392
+ (name) => manifest.packages[name]?.source.type === "well-known"
9393
+ );
9394
+ if (unsupportedTargets.length > 0) {
9395
+ for (const name of unsupportedTargets) {
9396
+ const source = manifest.packages[name].source;
9397
+ if (json) {
9398
+ outputError(
9399
+ "UNSUPPORTED_SOURCE",
9400
+ `Package "${name}" was installed from a well-known source. Suggestions are not supported.`
9401
+ );
9402
+ } else {
9403
+ console.error(
9404
+ chalk25.red(
9405
+ `Package "${name}" was installed from a well-known source (${source.type === "well-known" ? source.hostname : "unknown"}).`
9406
+ )
9407
+ );
9408
+ console.error(chalk25.dim("Suggestions are not supported for well-known sources."));
9409
+ }
8577
9410
  }
9411
+ }
9412
+ const validTargets = targets.filter((n) => !unsupportedTargets.includes(n));
9413
+ if (validTargets.length === 0) {
8578
9414
  process.exit(1);
8579
9415
  }
8580
- const orgSlug = source.uri.split("/")[1] ?? "";
8581
- const pkgName = targetName;
8582
9416
  if (options.dryRun) {
8583
- const dryRunResult = {
8584
- package: targetName,
8585
- title,
8586
- description: options.description,
8587
- files: localFiles.map((f) => ({
8588
- path: f.path,
8589
- contentLength: f.content.length
8590
- })),
8591
- endpoint: `/api/v1/skills/@${orgSlug}/${pkgName}/suggestions`
8592
- };
8593
- spinner.stop();
9417
+ const dryRunResults = [];
9418
+ for (const targetName of validTargets) {
9419
+ const manifestEntry = manifest.packages[targetName];
9420
+ const localFiles = await readLocalFiles3(projectRoot, targetName, manifestEntry.agents);
9421
+ const endpoint = `/api/v1${buildEndpoint(manifestEntry, targetName)}`;
9422
+ dryRunResults.push({
9423
+ package: targetName,
9424
+ title,
9425
+ description: options.description,
9426
+ files: localFiles.map((f) => ({
9427
+ path: f.path,
9428
+ contentLength: f.content.length
9429
+ })),
9430
+ endpoint
9431
+ });
9432
+ }
8594
9433
  if (json) {
8595
- outputSuccess(dryRunResult);
9434
+ outputSuccess(dryRunResults);
8596
9435
  } else {
8597
- console.log(chalk20.bold("\nDry run \u2014 suggestion preview:\n"));
8598
- console.log(` ${chalk20.dim("Package:")} ${targetName}`);
8599
- console.log(` ${chalk20.dim("Title:")} ${title}`);
8600
- if (options.description) {
8601
- console.log(` ${chalk20.dim("Desc:")} ${options.description}`);
8602
- }
8603
- console.log(` ${chalk20.dim("Files:")}`);
8604
- for (const f of dryRunResult.files) {
8605
- console.log(` ${chalk20.cyan(f.path)} (${f.contentLength} bytes)`);
9436
+ console.log(chalk25.bold("\nDry run \u2014 suggestion preview:\n"));
9437
+ for (const entry of dryRunResults) {
9438
+ console.log(` ${chalk25.dim("Package:")} ${entry.package}`);
9439
+ console.log(` ${chalk25.dim("Title:")} ${entry.title}`);
9440
+ if (entry.description) {
9441
+ console.log(` ${chalk25.dim("Desc:")} ${entry.description}`);
9442
+ }
9443
+ console.log(` ${chalk25.dim("Files:")}`);
9444
+ for (const f of entry.files) {
9445
+ console.log(` ${chalk25.cyan(f.path)} (${f.contentLength} bytes)`);
9446
+ }
9447
+ console.log(` ${chalk25.dim("Endpoint:")} ${entry.endpoint}`);
9448
+ console.log();
8606
9449
  }
8607
- console.log(` ${chalk20.dim("Endpoint:")} ${dryRunResult.endpoint}`);
8608
- console.log();
9450
+ console.log(
9451
+ chalk25.dim(
9452
+ `${dryRunResults.length} package${dryRunResults.length === 1 ? "" : "s"} would get suggestions.`
9453
+ )
9454
+ );
8609
9455
  }
8610
9456
  return;
8611
9457
  }
8612
- spinner.text = "Submitting suggestion...";
8613
- const requestBody = {
8614
- title,
8615
- description: options.description,
8616
- files: localFiles
8617
- };
8618
- const result = await postToPlatform(
8619
- `/skills/@${orgSlug}/${pkgName}/suggestions`,
8620
- requestBody
8621
- );
8622
- if (json) {
8623
- outputSuccess({
8624
- proposalId: result.id,
8625
- title: result.title ?? title,
8626
- url: result.url ?? ""
8627
- });
8628
- return;
8629
- }
8630
- spinner.succeed(`Suggestion created: ${chalk20.bold(result.title ?? title)}`);
8631
- if (result.url) {
8632
- console.log(chalk20.dim(` ${result.url}`));
9458
+ const outcomes = [];
9459
+ for (const targetName of validTargets) {
9460
+ const manifestEntry = manifest.packages[targetName];
9461
+ const spinner = createSpinner(`Creating suggestion for ${targetName}...`).start();
9462
+ try {
9463
+ const { result } = await submitSuggestion(
9464
+ projectRoot,
9465
+ targetName,
9466
+ manifestEntry,
9467
+ title,
9468
+ options.description
9469
+ );
9470
+ const proposeResult = {
9471
+ proposalId: result.id,
9472
+ title: result.title ?? title,
9473
+ url: result.url ?? ""
9474
+ };
9475
+ outcomes.push({ package: targetName, success: true, result: proposeResult });
9476
+ if (!json) {
9477
+ spinner.succeed(
9478
+ `Created suggestion for ${chalk25.bold(targetName)}: ${chalk25.bold(proposeResult.title)}`
9479
+ );
9480
+ if (result.url) {
9481
+ console.log(chalk25.dim(` ${result.url}`));
9482
+ }
9483
+ } else {
9484
+ spinner.stop();
9485
+ }
9486
+ } catch (error) {
9487
+ const message = error instanceof Error ? error.message : String(error);
9488
+ outcomes.push({ package: targetName, success: false, error: message });
9489
+ if (!json) {
9490
+ spinner.fail(`Failed to create suggestion for ${chalk25.bold(targetName)}: ${message}`);
9491
+ } else {
9492
+ spinner.stop();
9493
+ }
9494
+ }
8633
9495
  }
8634
- } catch (error) {
8635
- const message = error instanceof Error ? error.message : String(error);
8636
- spinner.fail(`Failed to create suggestion: ${message}`);
9496
+ const succeeded = outcomes.filter((o) => o.success);
9497
+ const failed = outcomes.filter((o) => !o.success);
8637
9498
  if (json) {
8638
- outputError("SUGGEST_FAILED", message);
9499
+ if (validTargets.length === 1) {
9500
+ const outcome = outcomes[0];
9501
+ if (outcome.success) {
9502
+ outputSuccess(outcome.result);
9503
+ } else {
9504
+ outputError("SUGGEST_FAILED", outcome.error);
9505
+ process.exit(1);
9506
+ }
9507
+ } else {
9508
+ outputSuccess(outcomes);
9509
+ }
9510
+ } else if (validTargets.length > 1) {
9511
+ console.log();
9512
+ console.log(
9513
+ chalk25.bold(
9514
+ `Created ${succeeded.length} suggestion${succeeded.length === 1 ? "" : "s"}` + (failed.length > 0 ? ` (${failed.length} failed)` : "")
9515
+ )
9516
+ );
9517
+ }
9518
+ if (failed.length > 0 && succeeded.length === 0) {
9519
+ process.exit(1);
8639
9520
  }
8640
- process.exit(1);
8641
9521
  }
8642
- });
9522
+ );
8643
9523
  }
8644
9524
 
8645
9525
  // src/commands/suggestions.ts
8646
- import chalk21 from "chalk";
9526
+ import chalk26 from "chalk";
8647
9527
  var HTTP_TIMEOUT_MS3 = 15e3;
8648
9528
  async function getFromPlatform(path) {
8649
9529
  const platformUrl = getPlatformUrl();
@@ -8698,21 +9578,21 @@ function formatDate2(isoDate) {
8698
9578
  }
8699
9579
  }
8700
9580
  var STATUS_COLOURS = {
8701
- OPEN: chalk21.green,
8702
- IN_REVIEW: chalk21.yellow,
8703
- APPROVED: chalk21.blue,
8704
- MERGED: chalk21.magenta,
8705
- REJECTED: chalk21.red,
8706
- CLOSED: chalk21.dim
9581
+ OPEN: chalk26.green,
9582
+ IN_REVIEW: chalk26.yellow,
9583
+ APPROVED: chalk26.blue,
9584
+ MERGED: chalk26.magenta,
9585
+ REJECTED: chalk26.red,
9586
+ CLOSED: chalk26.dim
8707
9587
  };
8708
9588
  function formatSuggestionRow(suggestion, idWidth, titleWidth, slugWidth, authorWidth) {
8709
- const id = chalk21.dim(`#${suggestion.id}`.padEnd(idWidth + 1));
9589
+ const id = chalk26.dim(`#${suggestion.id}`.padEnd(idWidth + 1));
8710
9590
  const title = suggestion.title.padEnd(titleWidth);
8711
- const slug = chalk21.cyan(suggestion.packageSlug.padEnd(slugWidth));
8712
- const statusFn = STATUS_COLOURS[suggestion.status] ?? chalk21.dim;
9591
+ const slug = chalk26.cyan(suggestion.packageSlug.padEnd(slugWidth));
9592
+ const statusFn = STATUS_COLOURS[suggestion.status] ?? chalk26.dim;
8713
9593
  const status = statusFn(suggestion.status.padEnd(11));
8714
- const author = chalk21.dim(suggestion.author.padEnd(authorWidth));
8715
- const date = chalk21.dim(formatDate2(suggestion.createdAt));
9594
+ const author = chalk26.dim(suggestion.author.padEnd(authorWidth));
9595
+ const date = chalk26.dim(formatDate2(suggestion.createdAt));
8716
9596
  return ` ${id} ${title} ${slug} ${status} ${author} ${date}`;
8717
9597
  }
8718
9598
  function registerSuggestionsCommand(program2) {
@@ -8728,7 +9608,7 @@ function registerSuggestionsCommand(program2) {
8728
9608
  );
8729
9609
  process.exit(1);
8730
9610
  }
8731
- console.error(chalk21.red("Not connected to a platform. Run `agentver login <url>` first."));
9611
+ console.error(chalk26.red("Not connected to a platform. Run `agentver login <url>` first."));
8732
9612
  process.exit(1);
8733
9613
  }
8734
9614
  const spinner = createSpinner("Fetching suggestions...").start();
@@ -8760,7 +9640,7 @@ function registerSuggestionsCommand(program2) {
8760
9640
  }
8761
9641
  if (suggestions.length === 0) {
8762
9642
  const filterLabel = statusFilter === "ALL" ? "" : ` ${options.status}`;
8763
- console.log(chalk21.dim(`No${filterLabel} suggestions found.`));
9643
+ console.log(chalk26.dim(`No${filterLabel} suggestions found.`));
8764
9644
  return;
8765
9645
  }
8766
9646
  const idWidth = Math.max(...suggestions.map((s) => `#${s.id}`.length));
@@ -8768,7 +9648,7 @@ function registerSuggestionsCommand(program2) {
8768
9648
  const slugWidth = Math.max(...suggestions.map((s) => s.packageSlug.length));
8769
9649
  const authorWidth = Math.max(...suggestions.map((s) => s.author.length));
8770
9650
  const heading = statusFilter === "ALL" ? `Suggestions (${suggestions.length})` : `${options.status.charAt(0).toUpperCase() + options.status.slice(1)} suggestions (${suggestions.length})`;
8771
- console.log(chalk21.bold(`
9651
+ console.log(chalk26.bold(`
8772
9652
  ${heading}:
8773
9653
  `));
8774
9654
  for (const suggestion of suggestions) {
@@ -8789,7 +9669,7 @@ ${heading}:
8789
9669
  // src/commands/sync.ts
8790
9670
  import { createHash as createHash4 } from "crypto";
8791
9671
  import { hostname as hostname2 } from "os";
8792
- import chalk22 from "chalk";
9672
+ import chalk27 from "chalk";
8793
9673
  var SYNC_TIMEOUT_MS = 3e4;
8794
9674
  function getMachineId2() {
8795
9675
  return createHash4("sha256").update(hostname2()).digest("hex");
@@ -8806,7 +9686,7 @@ function registerSyncCommand(program2) {
8806
9686
  process.exit(1);
8807
9687
  }
8808
9688
  console.error(
8809
- chalk22.red("Not connected to a platform.") + " Run " + chalk22.cyan("`agentver login <url>`") + " first."
9689
+ chalk27.red("Not connected to a platform.") + " Run " + chalk27.cyan("`agentver login <url>`") + " first."
8810
9690
  );
8811
9691
  process.exit(1);
8812
9692
  }
@@ -8820,7 +9700,7 @@ function registerSyncCommand(program2) {
8820
9700
  process.exit(1);
8821
9701
  }
8822
9702
  console.error(
8823
- chalk22.red("Not connected to a platform.") + " Run " + chalk22.cyan("`agentver login <url>`") + " first."
9703
+ chalk27.red("Not connected to a platform.") + " Run " + chalk27.cyan("`agentver login <url>`") + " first."
8824
9704
  );
8825
9705
  process.exit(1);
8826
9706
  }
@@ -8892,7 +9772,7 @@ function registerSyncCommand(program2) {
8892
9772
  return;
8893
9773
  }
8894
9774
  spinner.succeed(
8895
- `Synced ${chalk22.green(String(result.synced))} skill${result.synced === 1 ? "" : "s"} to platform` + (result.removed > 0 ? chalk22.dim(` (${result.removed} removed)`) : "")
9775
+ `Synced ${chalk27.green(String(result.synced))} skill${result.synced === 1 ? "" : "s"} to platform` + (result.removed > 0 ? chalk27.dim(` (${result.removed} removed)`) : "")
8896
9776
  );
8897
9777
  } catch (error) {
8898
9778
  if (error instanceof DOMException && error.name === "AbortError") {
@@ -8916,23 +9796,23 @@ function registerSyncCommand(program2) {
8916
9796
  }
8917
9797
 
8918
9798
  // src/commands/update.ts
8919
- import { join as join20 } from "path";
8920
- import chalk23 from "chalk";
9799
+ import { join as join23 } from "path";
9800
+ import chalk28 from "chalk";
8921
9801
  import ora7 from "ora";
8922
9802
  import prompts3 from "prompts";
8923
9803
 
8924
9804
  // src/storage/patches.ts
8925
- import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync13, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "fs";
8926
- import { join as join18 } from "path";
9805
+ import { existsSync as existsSync18, mkdirSync as mkdirSync9, readFileSync as readFileSync16, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "fs";
9806
+ import { join as join21 } from "path";
8927
9807
  var PATCHES_DIR = ".agentver/patches";
8928
9808
  var CONTEXT_LINES2 = 3;
8929
9809
  function getPatchPath(projectRoot, packageName) {
8930
- return join18(projectRoot, PATCHES_DIR, `${packageName}.patch`);
9810
+ return join21(projectRoot, PATCHES_DIR, `${packageName}.patch`);
8931
9811
  }
8932
9812
  function savePatch(projectRoot, packageName, patchContent) {
8933
9813
  const patchPath = getPatchPath(projectRoot, packageName);
8934
- const dir = join18(projectRoot, PATCHES_DIR);
8935
- if (!existsSync16(dir)) {
9814
+ const dir = join21(projectRoot, PATCHES_DIR);
9815
+ if (!existsSync18(dir)) {
8936
9816
  mkdirSync9(dir, { recursive: true });
8937
9817
  }
8938
9818
  writeFileSync8(patchPath, patchContent, "utf-8");
@@ -8940,7 +9820,7 @@ function savePatch(projectRoot, packageName, patchContent) {
8940
9820
  }
8941
9821
  function removePatch(projectRoot, packageName) {
8942
9822
  const patchPath = getPatchPath(projectRoot, packageName);
8943
- if (existsSync16(patchPath)) {
9823
+ if (existsSync18(patchPath)) {
8944
9824
  rmSync3(patchPath);
8945
9825
  }
8946
9826
  }
@@ -8987,30 +9867,30 @@ function applyPatch(projectRoot, patchContent) {
8987
9867
  };
8988
9868
  }
8989
9869
  function applyFilePatch(projectRoot, filePatch) {
8990
- const fullPath = join18(projectRoot, filePatch.filePath);
9870
+ const fullPath = join21(projectRoot, filePatch.filePath);
8991
9871
  const hasOnlyAdditions = filePatch.hunks.every(
8992
9872
  (h) => h.lines.every((l) => l.startsWith("+") || l.startsWith(" "))
8993
9873
  );
8994
9874
  const hasOnlyDeletions = filePatch.hunks.every(
8995
9875
  (h) => h.lines.every((l) => l.startsWith("-") || l.startsWith(" "))
8996
9876
  );
8997
- if (hasOnlyAdditions && !existsSync16(fullPath)) {
9877
+ if (hasOnlyAdditions && !existsSync18(fullPath)) {
8998
9878
  const content = filePatch.hunks.flatMap((h) => h.lines.filter((l) => l.startsWith("+")).map((l) => l.slice(1))).join("\n");
8999
- const dir = join18(fullPath, "..");
9000
- if (!existsSync16(dir)) {
9879
+ const dir = join21(fullPath, "..");
9880
+ if (!existsSync18(dir)) {
9001
9881
  mkdirSync9(dir, { recursive: true });
9002
9882
  }
9003
9883
  writeFileSync8(fullPath, content, "utf-8");
9004
9884
  return true;
9005
9885
  }
9006
- if (hasOnlyDeletions && existsSync16(fullPath)) {
9886
+ if (hasOnlyDeletions && existsSync18(fullPath)) {
9007
9887
  rmSync3(fullPath);
9008
9888
  return true;
9009
9889
  }
9010
- if (!existsSync16(fullPath)) {
9890
+ if (!existsSync18(fullPath)) {
9011
9891
  return false;
9012
9892
  }
9013
- const currentContent = readFileSync13(fullPath, "utf-8");
9893
+ const currentContent = readFileSync16(fullPath, "utf-8");
9014
9894
  const currentLines = currentContent.split("\n");
9015
9895
  let offset = 0;
9016
9896
  for (const hunk of filePatch.hunks) {
@@ -9294,17 +10174,17 @@ function backtrackMyers(trace, oldLines, newLines, finalD, max) {
9294
10174
  }
9295
10175
 
9296
10176
  // src/utils/backup.ts
9297
- import { cpSync, existsSync as existsSync17, mkdirSync as mkdirSync10, mkdtempSync, rmSync as rmSync4 } from "fs";
10177
+ import { cpSync, existsSync as existsSync19, mkdirSync as mkdirSync10, mkdtempSync, rmSync as rmSync4 } from "fs";
9298
10178
  import { tmpdir as tmpdir2 } from "os";
9299
- import { join as join19 } from "path";
10179
+ import { join as join22 } from "path";
9300
10180
  function createBackup(packageName, projectRoot, skillDir) {
9301
- const tempDir = mkdtempSync(join19(tmpdir2(), "agentver-backup-"));
10181
+ const tempDir = mkdtempSync(join22(tmpdir2(), "agentver-backup-"));
9302
10182
  const manifest = readManifest(projectRoot);
9303
10183
  const manifestEntry = manifest.packages[packageName] ?? null;
9304
10184
  const lockfile = readLockfile(projectRoot);
9305
10185
  const lockfileEntry = lockfile.packages[packageName] ?? null;
9306
- if (skillDir && existsSync17(skillDir)) {
9307
- const backupSkillDir = join19(tempDir, "files");
10186
+ if (skillDir && existsSync19(skillDir)) {
10187
+ const backupSkillDir = join22(tempDir, "files");
9308
10188
  mkdirSync10(backupSkillDir, { recursive: true });
9309
10189
  cpSync(skillDir, backupSkillDir, { recursive: true });
9310
10190
  }
@@ -9319,9 +10199,9 @@ function createBackup(packageName, projectRoot, skillDir) {
9319
10199
  }
9320
10200
  function restoreBackup(backup) {
9321
10201
  if (backup.skillDir) {
9322
- const backupSkillDir = join19(backup.tempDir, "files");
9323
- if (existsSync17(backupSkillDir)) {
9324
- if (existsSync17(backup.skillDir)) {
10202
+ const backupSkillDir = join22(backup.tempDir, "files");
10203
+ if (existsSync19(backupSkillDir)) {
10204
+ if (existsSync19(backup.skillDir)) {
9325
10205
  rmSync4(backup.skillDir, { recursive: true, force: true });
9326
10206
  }
9327
10207
  mkdirSync10(backup.skillDir, { recursive: true });
@@ -9344,7 +10224,7 @@ function restoreBackup(backup) {
9344
10224
  writeLockfile(backup.projectRoot, lockfile);
9345
10225
  }
9346
10226
  function cleanupBackup(backup) {
9347
- if (existsSync17(backup.tempDir)) {
10227
+ if (existsSync19(backup.tempDir)) {
9348
10228
  rmSync4(backup.tempDir, { recursive: true, force: true });
9349
10229
  }
9350
10230
  }
@@ -9450,13 +10330,13 @@ async function handlePatchUpdate(update, projectRoot, agents, spinner) {
9450
10330
  const applyResult = applyPatch(projectRoot, patchContent);
9451
10331
  if (applyResult.applied) {
9452
10332
  removePatch(projectRoot, update.name);
9453
- spinner.succeed(`${chalk23.green(update.name)}: updated and local patch reapplied successfully`);
10333
+ spinner.succeed(`${chalk28.green(update.name)}: updated and local patch reapplied successfully`);
9454
10334
  } else {
9455
10335
  spinner.warn(
9456
- `${chalk23.yellow(update.name)}: updated but patch had conflicts in: ${applyResult.conflicts.join(", ")}`
10336
+ `${chalk28.yellow(update.name)}: updated but patch had conflicts in: ${applyResult.conflicts.join(", ")}`
9457
10337
  );
9458
- console.log(chalk23.dim(` Patch saved at: ${patchPath}`));
9459
- console.log(chalk23.dim(" Review the patch file and apply remaining changes manually."));
10338
+ console.log(chalk28.dim(` Patch saved at: ${patchPath}`));
10339
+ console.log(chalk28.dim(" Review the patch file and apply remaining changes manually."));
9460
10340
  }
9461
10341
  return { commitSha: result.commitSha };
9462
10342
  }
@@ -9473,27 +10353,43 @@ function registerUpdateCommand(program2) {
9473
10353
  return;
9474
10354
  }
9475
10355
  console.log(
9476
- chalk23.dim(name ? `Package "${name}" is not installed.` : "No packages installed.")
10356
+ chalk28.dim(name ? `Package "${name}" is not installed.` : "No packages installed.")
9477
10357
  );
9478
10358
  return;
9479
10359
  }
10360
+ const pinnedNames = [];
9480
10361
  const updatable = packageNames.filter((n) => {
9481
10362
  const pkg2 = packages[n];
9482
- return pkg2 && pkg2.source.type === "git" && pkg2.source.uri !== "unknown";
10363
+ if (!pkg2) return false;
10364
+ if (pkg2.pinned === true) {
10365
+ pinnedNames.push(n);
10366
+ return false;
10367
+ }
10368
+ return pkg2.source.type === "git" && pkg2.source.uri !== "unknown";
9483
10369
  });
10370
+ if (pinnedNames.length > 0 && !jsonMode) {
10371
+ for (const pinnedName of pinnedNames) {
10372
+ console.log(chalk28.dim(`Skipping ${pinnedName} (pinned)`));
10373
+ }
10374
+ }
9484
10375
  if (updatable.length === 0) {
9485
10376
  if (jsonMode) {
9486
10377
  outputSuccess({
9487
10378
  updated: [],
9488
- skipped: packageNames.map((n) => ({ name: n, reason: "No known Git source" }))
10379
+ skipped: [
10380
+ ...pinnedNames.map((n) => ({ name: n, reason: "pinned" })),
10381
+ ...packageNames.filter((n) => !pinnedNames.includes(n)).map((n) => ({ name: n, reason: "No known Git source" }))
10382
+ ]
9489
10383
  });
9490
10384
  return;
9491
10385
  }
9492
- console.log(
9493
- chalk23.dim(
9494
- "No packages with known Git sources. Reinstall packages using Git source URLs to enable updates."
9495
- )
9496
- );
10386
+ if (pinnedNames.length === 0) {
10387
+ console.log(
10388
+ chalk28.dim(
10389
+ "No packages with known Git sources. Reinstall packages using Git source URLs to enable updates."
10390
+ )
10391
+ );
10392
+ }
9497
10393
  return;
9498
10394
  }
9499
10395
  const spinner = createSpinner("Checking for upstream changes...").start();
@@ -9533,17 +10429,17 @@ function registerUpdateCommand(program2) {
9533
10429
  outputSuccess({ updated: [], skipped: [] });
9534
10430
  return;
9535
10431
  }
9536
- console.log(chalk23.green("All packages are up to date."));
10432
+ console.log(chalk28.green("All packages are up to date."));
9537
10433
  return;
9538
10434
  }
9539
10435
  if (!jsonMode) {
9540
- console.log(chalk23.bold(`
10436
+ console.log(chalk28.bold(`
9541
10437
  Upstream changes available (${updates.length}):
9542
10438
  `));
9543
10439
  for (const update of updates) {
9544
- const modifiedIndicator = update.locallyModified ? ` ${chalk23.yellow("\u26A0 locally modified")}` : "";
10440
+ const modifiedIndicator = update.locallyModified ? ` ${chalk28.yellow("\u26A0 locally modified")}` : "";
9545
10441
  console.log(
9546
- ` ${chalk23.green(update.name)}: ${chalk23.dim(update.currentCommit.slice(0, 7))} \u2192 ${chalk23.cyan(update.latestCommit.slice(0, 7))} ${chalk23.dim(`(${update.ref})`)}${modifiedIndicator}`
10442
+ ` ${chalk28.green(update.name)}: ${chalk28.dim(update.currentCommit.slice(0, 7))} \u2192 ${chalk28.cyan(update.latestCommit.slice(0, 7))} ${chalk28.dim(`(${update.ref})`)}${modifiedIndicator}`
9547
10443
  );
9548
10444
  }
9549
10445
  console.log();
@@ -9556,7 +10452,7 @@ Upstream changes available (${updates.length}):
9556
10452
  });
9557
10453
  return;
9558
10454
  }
9559
- console.log(`${chalk23.yellow("[dry-run]")} No changes made.`);
10455
+ console.log(`${chalk28.yellow("[dry-run]")} No changes made.`);
9560
10456
  return;
9561
10457
  }
9562
10458
  if (!jsonMode) {
@@ -9567,7 +10463,7 @@ Upstream changes available (${updates.length}):
9567
10463
  initial: true
9568
10464
  });
9569
10465
  if (!confirmed) {
9570
- console.log(chalk23.dim("Update cancelled."));
10466
+ console.log(chalk28.dim("Update cancelled."));
9571
10467
  return;
9572
10468
  }
9573
10469
  }
@@ -9633,7 +10529,7 @@ Upstream changes available (${updates.length}):
9633
10529
  }
9634
10530
  }
9635
10531
  const shortName = update.name.split("/").pop();
9636
- const skillDir = resolveReadPath(projectRoot, shortName, agents) ?? (agentId ? join20(
10532
+ const skillDir = resolveReadPath(projectRoot, shortName, agents) ?? (agentId ? join23(
9637
10533
  projectRoot,
9638
10534
  getSkillPlacementPath(agentId, shortName, "project") ?? ""
9639
10535
  ) : null);
@@ -9675,25 +10571,25 @@ Upstream changes available (${updates.length}):
9675
10571
  if (jsonMode) {
9676
10572
  outputSuccess({
9677
10573
  updated: jsonUpdated,
9678
- skipped: jsonSkipped
10574
+ skipped: [...pinnedNames.map((n) => ({ name: n, reason: "pinned" })), ...jsonSkipped]
9679
10575
  });
9680
10576
  return;
9681
10577
  }
9682
- console.log(chalk23.bold("\nUpdate summary:\n"));
10578
+ console.log(chalk28.bold("\nUpdate summary:\n"));
9683
10579
  for (const result of results) {
9684
- const patchNote = result.patched ? chalk23.dim(" (patch reapplied)") : "";
10580
+ const patchNote = result.patched ? chalk28.dim(" (patch reapplied)") : "";
9685
10581
  console.log(
9686
- ` ${chalk23.green("\u2713")} ${result.name}: ${chalk23.dim(result.from)} \u2192 ${chalk23.cyan(result.to)}${patchNote}`
10582
+ ` ${chalk28.green("\u2713")} ${result.name}: ${chalk28.dim(result.from)} \u2192 ${chalk28.cyan(result.to)}${patchNote}`
9687
10583
  );
9688
10584
  }
9689
10585
  for (const skippedName of skipped) {
9690
- console.log(` ${chalk23.dim("\u2013")} ${skippedName}: ${chalk23.dim("skipped")}`);
10586
+ console.log(` ${chalk28.dim("\u2013")} ${skippedName}: ${chalk28.dim("skipped")}`);
9691
10587
  }
9692
10588
  for (const failure of failures) {
9693
- console.log(` ${chalk23.red("\u2717")} ${failure.name}: ${failure.error}`);
10589
+ console.log(` ${chalk28.red("\u2717")} ${failure.name}: ${failure.error}`);
9694
10590
  }
9695
10591
  if (failures.length > 0) {
9696
- console.log(chalk23.dim("\nFailed packages were rolled back to their previous versions."));
10592
+ console.log(chalk28.dim("\nFailed packages were rolled back to their previous versions."));
9697
10593
  }
9698
10594
  console.log();
9699
10595
  } catch (error) {
@@ -9712,16 +10608,16 @@ Upstream changes available (${updates.length}):
9712
10608
  // src/commands/upgrade.ts
9713
10609
  import { execFile as execFile2 } from "child_process";
9714
10610
  import { createRequire } from "module";
9715
- import { dirname as dirname5, join as join21 } from "path";
10611
+ import { dirname as dirname6, join as join24 } from "path";
9716
10612
  import { fileURLToPath } from "url";
9717
10613
  import { promisify as promisify2 } from "util";
9718
- import chalk24 from "chalk";
10614
+ import chalk29 from "chalk";
9719
10615
  var execFileAsync2 = promisify2(execFile2);
9720
10616
  var PACKAGE_NAME = "@agentver/cli";
9721
10617
  function getCurrentVersion() {
9722
- const __dirname2 = dirname5(fileURLToPath(import.meta.url));
10618
+ const __dirname2 = dirname6(fileURLToPath(import.meta.url));
9723
10619
  const require3 = createRequire(import.meta.url);
9724
- const pkg2 = require3(join21(__dirname2, "..", "package.json"));
10620
+ const pkg2 = require3(join24(__dirname2, "..", "package.json"));
9725
10621
  return pkg2.version;
9726
10622
  }
9727
10623
  async function getLatestVersion() {
@@ -9777,11 +10673,11 @@ function registerUpgradeCommand(program2) {
9777
10673
  if (json) {
9778
10674
  outputSuccess({ current: currentVersion, latest: latestVersion, upToDate: true });
9779
10675
  } else {
9780
- spinner.succeed(`Already on the latest version ${chalk24.green(`v${currentVersion}`)}`);
10676
+ spinner.succeed(`Already on the latest version ${chalk29.green(`v${currentVersion}`)}`);
9781
10677
  }
9782
10678
  return;
9783
10679
  }
9784
- spinner.text = `Upgrading ${chalk24.dim(`v${currentVersion}`)} \u2192 ${chalk24.green(`v${latestVersion}`)}\u2026`;
10680
+ spinner.text = `Upgrading ${chalk29.dim(`v${currentVersion}`)} \u2192 ${chalk29.green(`v${latestVersion}`)}\u2026`;
9785
10681
  const pm = await detectPackageManager();
9786
10682
  const args = getInstallArgs(pm);
9787
10683
  await execFileAsync2(pm, args, { timeout: 6e4 });
@@ -9794,7 +10690,7 @@ function registerUpgradeCommand(program2) {
9794
10690
  outputSuccess(result);
9795
10691
  } else {
9796
10692
  spinner.succeed(
9797
- `Upgraded ${chalk24.green(`v${currentVersion}`)} \u2192 ${chalk24.green(`v${latestVersion}`)} via ${pm}`
10693
+ `Upgraded ${chalk29.green(`v${currentVersion}`)} \u2192 ${chalk29.green(`v${latestVersion}`)} via ${pm}`
9798
10694
  );
9799
10695
  }
9800
10696
  } catch (error) {
@@ -9811,7 +10707,7 @@ function registerUpgradeCommand(program2) {
9811
10707
  }
9812
10708
 
9813
10709
  // src/commands/verify.ts
9814
- import chalk25 from "chalk";
10710
+ import chalk30 from "chalk";
9815
10711
  var FALLBACK_SOURCE2 = {
9816
10712
  host: "github.com",
9817
10713
  owner: "local",
@@ -9878,8 +10774,8 @@ function registerVerifyCommand(program2) {
9878
10774
  outputError("NO_SKILL", "No skill name provided and no packages installed");
9879
10775
  return;
9880
10776
  }
9881
- process.stderr.write(chalk25.red("No skill name provided and no packages installed.\n"));
9882
- process.stderr.write(chalk25.dim("Usage: agentver verify @org/skill-name\n"));
10777
+ process.stderr.write(chalk30.red("No skill name provided and no packages installed.\n"));
10778
+ process.stderr.write(chalk30.dim("Usage: agentver verify @org/skill-name\n"));
9883
10779
  process.exitCode = 1;
9884
10780
  return;
9885
10781
  }
@@ -9894,10 +10790,10 @@ function registerVerifyCommand(program2) {
9894
10790
  return;
9895
10791
  }
9896
10792
  process.stderr.write(
9897
- chalk25.red("Multiple packages installed. Please specify which to verify:\n")
10793
+ chalk30.red("Multiple packages installed. Please specify which to verify:\n")
9898
10794
  );
9899
10795
  for (const pkg2 of packageNames) {
9900
- process.stderr.write(` ${chalk25.cyan(pkg2)}
10796
+ process.stderr.write(` ${chalk30.cyan(pkg2)}
9901
10797
  `);
9902
10798
  }
9903
10799
  process.exitCode = 1;
@@ -9914,7 +10810,7 @@ function registerVerifyCommand(program2) {
9914
10810
  return;
9915
10811
  }
9916
10812
  process.stderr.write(
9917
- chalk25.red(`Invalid skill name "${skillName}". Expected format: @org/skill-name
10813
+ chalk30.red(`Invalid skill name "${skillName}". Expected format: @org/skill-name
9918
10814
  `)
9919
10815
  );
9920
10816
  process.exitCode = 1;
@@ -9922,7 +10818,7 @@ function registerVerifyCommand(program2) {
9922
10818
  }
9923
10819
  if (!jsonMode) {
9924
10820
  process.stderr.write(`
9925
- ${chalk25.bold(`Verifying @${parsed.org}/${parsed.skill}...`)}
10821
+ ${chalk30.bold(`Verifying @${parsed.org}/${parsed.skill}...`)}
9926
10822
 
9927
10823
  `);
9928
10824
  }
@@ -10064,26 +10960,26 @@ ${chalk25.bold(`Verifying @${parsed.org}/${parsed.skill}...`)}
10064
10960
  }
10065
10961
  process.stderr.write("\n");
10066
10962
  if (overallPassed) {
10067
- process.stderr.write(chalk25.green.bold("Skill is verified and safe to use.\n"));
10963
+ process.stderr.write(chalk30.green.bold("Skill is verified and safe to use.\n"));
10068
10964
  } else {
10069
- process.stderr.write(chalk25.red.bold("Skill verification failed.\n"));
10965
+ process.stderr.write(chalk30.red.bold("Skill verification failed.\n"));
10070
10966
  process.exitCode = 1;
10071
10967
  }
10072
10968
  });
10073
10969
  }
10074
10970
 
10075
10971
  // src/commands/version.ts
10076
- import { existsSync as existsSync18, readFileSync as readFileSync14 } from "fs";
10077
- import { basename as basename6, join as join22 } from "path";
10078
- import chalk26 from "chalk";
10972
+ import { existsSync as existsSync20, readFileSync as readFileSync17 } from "fs";
10973
+ import { basename as basename6, join as join25 } from "path";
10974
+ import chalk31 from "chalk";
10079
10975
  import ora8 from "ora";
10080
10976
  var SEMVER_REGEX2 = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
10081
10977
  function resolveSkillIdentity3() {
10082
10978
  const cwd = process.cwd();
10083
- const skillMdPath = join22(cwd, "SKILL.md");
10979
+ const skillMdPath = join25(cwd, "SKILL.md");
10084
10980
  let skillName = null;
10085
- if (existsSync18(skillMdPath)) {
10086
- const content = readFileSync14(skillMdPath, "utf-8");
10981
+ if (existsSync20(skillMdPath)) {
10982
+ const content = readFileSync17(skillMdPath, "utf-8");
10087
10983
  const nameMatch = content.match(/^name:\s*(.+)$/m);
10088
10984
  skillName = nameMatch?.[1]?.trim() ?? basename6(cwd);
10089
10985
  }
@@ -10111,7 +11007,7 @@ function registerVersionCommand(program2) {
10111
11007
  version.command("create <semver>").description("Create a version tag for the current skill").option("--notes <text>", "Release notes").option("--json", "Output as JSON").action(async (semver, options) => {
10112
11008
  if (!SEMVER_REGEX2.test(semver)) {
10113
11009
  process.stderr.write(
10114
- chalk26.red(`Invalid semver "${semver}". Expected format: 1.0.0 or 1.0.0-beta.1
11010
+ chalk31.red(`Invalid semver "${semver}". Expected format: 1.0.0 or 1.0.0-beta.1
10115
11011
  `)
10116
11012
  );
10117
11013
  process.exit(1);
@@ -10119,7 +11015,7 @@ function registerVersionCommand(program2) {
10119
11015
  const identity = resolveSkillIdentity3();
10120
11016
  if (!identity) {
10121
11017
  process.stderr.write(
10122
- chalk26.red("Could not determine skill identity. Run this from a skill directory.\n")
11018
+ chalk31.red("Could not determine skill identity. Run this from a skill directory.\n")
10123
11019
  );
10124
11020
  process.exit(1);
10125
11021
  }
@@ -10127,7 +11023,7 @@ function registerVersionCommand(program2) {
10127
11023
  const lockEntry = lockfile.packages[identity.name];
10128
11024
  const commitSha = lockEntry?.source.type === "git" ? lockEntry.source.commit : void 0;
10129
11025
  if (!commitSha || commitSha === "unknown") {
10130
- process.stderr.write(chalk26.red("No commit SHA found in lockfile. Save changes first.\n"));
11026
+ process.stderr.write(chalk31.red("No commit SHA found in lockfile. Save changes first.\n"));
10131
11027
  process.exit(1);
10132
11028
  }
10133
11029
  const spinner = ora8(`Creating version ${semver}...`).start();
@@ -10159,7 +11055,7 @@ function registerVersionCommand(program2) {
10159
11055
  );
10160
11056
  } else {
10161
11057
  spinner.succeed(
10162
- `Version ${chalk26.cyan(semver)} created ${chalk26.dim(`(${result.commitSha.slice(0, 7)})`)}`
11058
+ `Version ${chalk31.cyan(semver)} created ${chalk31.dim(`(${result.commitSha.slice(0, 7)})`)}`
10163
11059
  );
10164
11060
  }
10165
11061
  } catch (error) {
@@ -10173,7 +11069,7 @@ function registerVersionCommand(program2) {
10173
11069
  const identity = resolveSkillIdentity3();
10174
11070
  if (!identity) {
10175
11071
  process.stderr.write(
10176
- chalk26.red("Could not determine skill identity. Run this from a skill directory.\n")
11072
+ chalk31.red("Could not determine skill identity. Run this from a skill directory.\n")
10177
11073
  );
10178
11074
  process.exit(1);
10179
11075
  }
@@ -10188,16 +11084,16 @@ function registerVersionCommand(program2) {
10188
11084
  return;
10189
11085
  }
10190
11086
  if (versions.length === 0) {
10191
- process.stdout.write(chalk26.dim("No versions found.\n"));
11087
+ process.stdout.write(chalk31.dim("No versions found.\n"));
10192
11088
  return;
10193
11089
  }
10194
- process.stdout.write(chalk26.bold(`
11090
+ process.stdout.write(chalk31.bold(`
10195
11091
  Versions for @${identity.org}/${identity.name}:
10196
11092
 
10197
11093
  `));
10198
11094
  for (const v of versions) {
10199
11095
  process.stdout.write(
10200
- ` ${chalk26.cyan(v.name)} ${chalk26.dim(`(${v.commitSha.slice(0, 7)})`)} ${chalk26.dim(v.message)}
11096
+ ` ${chalk31.cyan(v.name)} ${chalk31.dim(`(${v.commitSha.slice(0, 7)})`)} ${chalk31.dim(v.message)}
10201
11097
  `
10202
11098
  );
10203
11099
  }
@@ -10212,7 +11108,7 @@ Versions for @${identity.org}/${identity.name}:
10212
11108
  }
10213
11109
 
10214
11110
  // src/commands/whoami.ts
10215
- import chalk27 from "chalk";
11111
+ import chalk32 from "chalk";
10216
11112
  function registerWhoamiCommand(program2) {
10217
11113
  program2.command("whoami").description("Show authentication state").action(async () => {
10218
11114
  const credentials = await getCredentials();
@@ -10221,15 +11117,15 @@ function registerWhoamiCommand(program2) {
10221
11117
  outputSuccess({ authenticated: false });
10222
11118
  return;
10223
11119
  }
10224
- console.log(chalk27.dim("Not authenticated. Run `agentver login` to sign in."));
11120
+ console.log(chalk32.dim("Not authenticated. Run `agentver login` to sign in."));
10225
11121
  return;
10226
11122
  }
10227
11123
  if (!isJSONMode()) {
10228
11124
  if (credentials.apiKey) {
10229
11125
  const prefix = credentials.apiKey.slice(0, 8);
10230
- console.log(`Authenticated via API key: ${chalk27.green(`${prefix}...`)}`);
11126
+ console.log(`Authenticated via API key: ${chalk32.green(`${prefix}...`)}`);
10231
11127
  } else {
10232
- console.log(chalk27.green("Authenticated via OAuth."));
11128
+ console.log(chalk32.green("Authenticated via OAuth."));
10233
11129
  }
10234
11130
  }
10235
11131
  const platformUrl = getPlatformUrl();
@@ -10238,11 +11134,11 @@ function registerWhoamiCommand(program2) {
10238
11134
  outputSuccess({ authenticated: true });
10239
11135
  return;
10240
11136
  }
10241
- console.log(chalk27.dim("Platform: not connected (run `agentver login <url>` to connect)"));
11137
+ console.log(chalk32.dim("Platform: not connected (run `agentver login <url>` to connect)"));
10242
11138
  return;
10243
11139
  }
10244
11140
  if (!isJSONMode()) {
10245
- console.log(`Platform: ${chalk27.cyan(platformUrl)}`);
11141
+ console.log(`Platform: ${chalk32.cyan(platformUrl)}`);
10246
11142
  }
10247
11143
  const me = await platformFetchSilent("/me");
10248
11144
  if (isJSONMode()) {
@@ -10269,38 +11165,44 @@ function registerWhoamiCommand(program2) {
10269
11165
  }
10270
11166
 
10271
11167
  // bin/agentver.ts
10272
- var __dirname = dirname6(fileURLToPath2(import.meta.url));
11168
+ var __dirname = dirname7(fileURLToPath2(import.meta.url));
10273
11169
  var require2 = createRequire2(import.meta.url);
10274
- var pkg = require2(join23(__dirname, "..", "package.json"));
11170
+ var pkg = require2(join26(__dirname, "..", "package.json"));
10275
11171
  updateNotifier({ pkg }).notify({
10276
11172
  message: `Update available: {currentVersion} \u2192 {latestVersion}
10277
- Run ${chalk28.cyan("agentver upgrade")} to update`
11173
+ Run ${chalk33.cyan("agentver upgrade")} to update`
10278
11174
  });
10279
11175
  var program = new Command();
10280
11176
  program.name("agentver").description("Agent skill registry \u2014 store, version, and distribute AI agent skills").version(pkg.version).option("--json", "Output results as structured JSON");
10281
11177
  registerAdoptCommand(program);
10282
- registerInstallCommand(program);
10283
11178
  registerAuditCommand(program);
11179
+ registerCompletionCommand(program);
11180
+ registerConfigCommand(program);
11181
+ registerDiffCommand(program);
11182
+ registerDoctorCommand(program);
11183
+ registerDraftCommand(program);
11184
+ registerInfoCommand(program);
11185
+ registerInitCommand(program);
11186
+ registerInstallCommand(program);
11187
+ registerListCommand(program);
11188
+ registerLogCommand(program);
10284
11189
  registerLoginCommand(program);
10285
11190
  registerLogoutCommand(program);
10286
- registerListCommand(program);
10287
- registerSearchCommand(program);
10288
- registerUpdateCommand(program);
11191
+ registerPinCommand(program);
11192
+ registerPublishCommand(program);
10289
11193
  registerRemoveCommand(program);
10290
- registerInitCommand(program);
11194
+ registerSaveCommand(program);
10291
11195
  registerScanCommand(program);
10292
- registerWhoamiCommand(program);
11196
+ registerSearchCommand(program);
10293
11197
  registerStatusCommand(program);
10294
- registerDiffCommand(program);
10295
- registerSyncCommand(program);
10296
11198
  registerSuggestCommand(program);
10297
11199
  registerSuggestionsCommand(program);
10298
- registerSaveCommand(program);
10299
- registerPublishCommand(program);
10300
- registerDraftCommand(program);
11200
+ registerSyncCommand(program);
11201
+ registerUnpinCommand(program);
11202
+ registerUpdateCommand(program);
10301
11203
  registerUpgradeCommand(program);
10302
11204
  registerVerifyCommand(program);
10303
11205
  registerVersionCommand(program);
10304
- registerLogCommand(program);
11206
+ registerWhoamiCommand(program);
10305
11207
  program.parse();
10306
11208
  //# sourceMappingURL=agentver.js.map