@agentver/cli 0.1.3 → 0.2.1

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
 
@@ -7305,6 +8057,7 @@ function startCallbackServer(expectedState) {
7305
8057
  port: address.port,
7306
8058
  waitForCallback: () => callbackPromise,
7307
8059
  close: () => {
8060
+ server.closeAllConnections();
7308
8061
  server.close();
7309
8062
  }
7310
8063
  });
@@ -7369,9 +8122,9 @@ function registerLoginCommand(program2) {
7369
8122
  });
7370
8123
  return;
7371
8124
  }
7372
- console.log(chalk12.green("Saved API key. You are now authenticated."));
8125
+ console.log(chalk16.green("Saved API key. You are now authenticated."));
7373
8126
  if (target) {
7374
- console.log(chalk12.dim(`Connected to ${target}`));
8127
+ console.log(chalk16.dim(`Connected to ${target}`));
7375
8128
  }
7376
8129
  return;
7377
8130
  }
@@ -7411,28 +8164,31 @@ function registerLoginCommand(program2) {
7411
8164
  const redirectUri = `http://localhost:${port}/callback`;
7412
8165
  const authUrl = `${baseUrl}/auth/cli?code_challenge=${encodeURIComponent(codeChallenge)}&state=${encodeURIComponent(state)}&redirect_uri=${encodeURIComponent(redirectUri)}`;
7413
8166
  spinner.text = "Opening browser for authentication...";
7414
- console.log(chalk12.dim(`
8167
+ console.log(chalk16.dim(`
7415
8168
  If the browser doesn't open, visit:
7416
8169
  ${authUrl}
7417
8170
  `));
7418
8171
  await open(authUrl);
7419
8172
  spinner.text = "Waiting for authentication in browser...";
8173
+ let authTimeout;
7420
8174
  const { code } = await Promise.race([
7421
8175
  callbackServer.waitForCallback(),
7422
8176
  new Promise((_resolve, reject) => {
7423
- setTimeout(() => {
8177
+ authTimeout = setTimeout(() => {
7424
8178
  reject(new Error("Authentication timed out after 120 seconds"));
7425
8179
  }, AUTH_TIMEOUT_MS);
7426
8180
  })
7427
8181
  ]);
8182
+ clearTimeout(authTimeout);
7428
8183
  spinner.text = "Exchanging authorisation code for token...";
7429
8184
  const tokenResponse = await exchangeCodeForToken(apiUrl, code, codeVerifier, redirectUri);
7430
8185
  saveCredentials({ token: tokenResponse.access_token });
7431
8186
  spinner.succeed("Authenticated successfully.");
7432
8187
  const connectedUrl = url ?? getPlatformUrl();
7433
8188
  if (connectedUrl) {
7434
- console.log(chalk12.dim(`Connected to ${connectedUrl}`));
8189
+ console.log(chalk16.dim(`Connected to ${connectedUrl}`));
7435
8190
  }
8191
+ process.exit(0);
7436
8192
  } catch (error) {
7437
8193
  const message = error instanceof Error ? error.message : String(error);
7438
8194
  spinner.fail(`Authentication failed: ${message}`);
@@ -7444,7 +8200,7 @@ function registerLoginCommand(program2) {
7444
8200
  }
7445
8201
 
7446
8202
  // src/commands/logout.ts
7447
- import chalk13 from "chalk";
8203
+ import chalk17 from "chalk";
7448
8204
  function registerLogoutCommand(program2) {
7449
8205
  program2.command("logout").description("Log out from the Agentver registry").action(async () => {
7450
8206
  if (!await isAuthenticated()) {
@@ -7452,7 +8208,7 @@ function registerLogoutCommand(program2) {
7452
8208
  outputSuccess({ cleared: true });
7453
8209
  return;
7454
8210
  }
7455
- console.log(chalk13.dim("You are not currently logged in."));
8211
+ console.log(chalk17.dim("You are not currently logged in."));
7456
8212
  return;
7457
8213
  }
7458
8214
  const platformUrl = getPlatformUrl();
@@ -7467,19 +8223,72 @@ function registerLogoutCommand(program2) {
7467
8223
  return;
7468
8224
  }
7469
8225
  if (platformUrl) {
7470
- console.log(`${chalk13.green("Logged out successfully.")} Disconnected from ${platformUrl}`);
8226
+ console.log(`${chalk17.green("Logged out successfully.")} Disconnected from ${platformUrl}`);
7471
8227
  } else {
7472
8228
  console.log(
7473
- `${chalk13.green("Logged out successfully.")} Run \`agentver login\` to sign in again.`
8229
+ `${chalk17.green("Logged out successfully.")} Run \`agentver login\` to sign in again.`
7474
8230
  );
7475
8231
  }
7476
8232
  });
7477
8233
  }
7478
8234
 
8235
+ // src/commands/pin.ts
8236
+ import chalk18 from "chalk";
8237
+ function registerPinCommand(program2) {
8238
+ program2.command("pin <name>").description("Pin a package to skip it during updates").action((name) => {
8239
+ const jsonMode = isJSONMode();
8240
+ const projectRoot = process.cwd();
8241
+ const manifest = readManifest(projectRoot);
8242
+ const pkg2 = manifest.packages[name];
8243
+ if (!pkg2) {
8244
+ if (jsonMode) {
8245
+ outputError("NOT_FOUND", `Package "${name}" is not installed.`);
8246
+ } else {
8247
+ console.error(chalk18.red(`Package "${name}" is not installed.`));
8248
+ }
8249
+ process.exit(1);
8250
+ }
8251
+ pkg2.pinned = true;
8252
+ writeManifest(projectRoot, manifest);
8253
+ if (jsonMode) {
8254
+ outputSuccess({ name, pinned: true });
8255
+ return;
8256
+ }
8257
+ console.log(
8258
+ chalk18.green(`Pinned ${name}`) + chalk18.dim(" \u2014 this package will be skipped during updates")
8259
+ );
8260
+ });
8261
+ }
8262
+ function registerUnpinCommand(program2) {
8263
+ program2.command("unpin <name>").description("Unpin a package so it is included in updates").action((name) => {
8264
+ const jsonMode = isJSONMode();
8265
+ const projectRoot = process.cwd();
8266
+ const manifest = readManifest(projectRoot);
8267
+ const pkg2 = manifest.packages[name];
8268
+ if (!pkg2) {
8269
+ if (jsonMode) {
8270
+ outputError("NOT_FOUND", `Package "${name}" is not installed.`);
8271
+ } else {
8272
+ console.error(chalk18.red(`Package "${name}" is not installed.`));
8273
+ }
8274
+ process.exit(1);
8275
+ }
8276
+ delete pkg2.pinned;
8277
+ writeManifest(projectRoot, manifest);
8278
+ if (jsonMode) {
8279
+ outputSuccess({ name, pinned: false });
8280
+ return;
8281
+ }
8282
+ console.log(
8283
+ chalk18.green(`Unpinned ${name}`) + chalk18.dim(" \u2014 this package will be included in updates")
8284
+ );
8285
+ });
8286
+ }
8287
+
7479
8288
  // 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";
8289
+ import { existsSync as existsSync14, readFileSync as readFileSync13 } from "fs";
8290
+ import { basename as basename4, join as join17, resolve as resolve2 } from "path";
8291
+ import chalk19 from "chalk";
7483
8292
  import ora4 from "ora";
7484
8293
  var SEMVER_REGEX = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
7485
8294
  function parseFrontmatter2(content) {
@@ -7506,9 +8315,9 @@ function parseFrontmatter2(content) {
7506
8315
  };
7507
8316
  }
7508
8317
  function detectNamespace(skillDir) {
7509
- const skillMdPath = join14(skillDir, "SKILL.md");
7510
- if (!existsSync12(skillMdPath)) return null;
7511
- const content = readFileSync10(skillMdPath, "utf-8");
8318
+ const skillMdPath = join17(skillDir, "SKILL.md");
8319
+ if (!existsSync14(skillMdPath)) return null;
8320
+ const content = readFileSync13(skillMdPath, "utf-8");
7512
8321
  const fm = parseFrontmatter2(content);
7513
8322
  if (!fm) return null;
7514
8323
  const parts = skillDir.split("/");
@@ -7522,16 +8331,16 @@ function detectNamespace(skillDir) {
7522
8331
  function registerPublishCommand(program2) {
7523
8332
  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
8333
  const skillDir = pathArg ? resolve2(process.cwd(), pathArg) : process.cwd();
7525
- if (!existsSync12(join14(skillDir, "SKILL.md"))) {
8334
+ if (!existsSync14(join17(skillDir, "SKILL.md"))) {
7526
8335
  process.stderr.write(
7527
- chalk14.red(`No SKILL.md found in ${skillDir}. Cannot publish without a skill manifest.
8336
+ chalk19.red(`No SKILL.md found in ${skillDir}. Cannot publish without a skill manifest.
7528
8337
  `)
7529
8338
  );
7530
8339
  process.exit(1);
7531
8340
  }
7532
8341
  const spinner = ora4("Reading skill metadata...").start();
7533
8342
  try {
7534
- const skillMdContent = readFileSync10(join14(skillDir, "SKILL.md"), "utf-8");
8343
+ const skillMdContent = readFileSync13(join17(skillDir, "SKILL.md"), "utf-8");
7535
8344
  const frontmatter = parseFrontmatter2(skillMdContent);
7536
8345
  if (!frontmatter) {
7537
8346
  spinner.fail(
@@ -7573,7 +8382,7 @@ function registerPublishCommand(program2) {
7573
8382
  spinner.fail("Security audit failed. Fix the issues before publishing.");
7574
8383
  for (const finding of scanResult.findings) {
7575
8384
  process.stderr.write(
7576
- ` ${chalk14.red("BLOCK")} ${finding.file}:${String(finding.line ?? "?")} \u2014 ${finding.message}
8385
+ ` ${chalk19.red("BLOCK")} ${finding.file}:${String(finding.line ?? "?")} \u2014 ${finding.message}
7577
8386
  `
7578
8387
  );
7579
8388
  }
@@ -7583,7 +8392,7 @@ function registerPublishCommand(program2) {
7583
8392
  spinner.warn("Security audit warnings found:");
7584
8393
  for (const finding of scanResult.findings) {
7585
8394
  process.stderr.write(
7586
- ` ${chalk14.yellow("WARN")} ${finding.file}:${String(finding.line ?? "?")} \u2014 ${finding.message}
8395
+ ` ${chalk19.yellow("WARN")} ${finding.file}:${String(finding.line ?? "?")} \u2014 ${finding.message}
7587
8396
  `
7588
8397
  );
7589
8398
  }
@@ -7612,13 +8421,13 @@ function registerPublishCommand(program2) {
7612
8421
  );
7613
8422
  } else {
7614
8423
  process.stdout.write(
7615
- chalk14.yellow("[dry-run]") + ` Would publish ${chalk14.green(frontmatter.name)}@${chalk14.cyan(version)}
8424
+ chalk19.yellow("[dry-run]") + ` Would publish ${chalk19.green(frontmatter.name)}@${chalk19.cyan(version)}
7616
8425
  `
7617
8426
  );
7618
- process.stdout.write(chalk14.dim(` Namespace: @${namespace.org}/${namespace.name}
8427
+ process.stdout.write(chalk19.dim(` Namespace: @${namespace.org}/${namespace.name}
7619
8428
  `));
7620
8429
  process.stdout.write(
7621
- chalk14.dim(
8430
+ chalk19.dim(
7622
8431
  ` Files (${filesToPublish.length}): ${filesToPublish.map((f) => f.path).join(", ")}
7623
8432
  `
7624
8433
  )
@@ -7651,7 +8460,7 @@ function registerPublishCommand(program2) {
7651
8460
  );
7652
8461
  } else {
7653
8462
  spinner.succeed(
7654
- `Published ${chalk14.green(frontmatter.name)}@${chalk14.cyan(result.version)} ${chalk14.dim(`(${result.commitSha.slice(0, 7)})`)}`
8463
+ `Published ${chalk19.green(frontmatter.name)}@${chalk19.cyan(result.version)} ${chalk19.dim(`(${result.commitSha.slice(0, 7)})`)}`
7655
8464
  );
7656
8465
  }
7657
8466
  } catch (error) {
@@ -7662,11 +8471,11 @@ function registerPublishCommand(program2) {
7662
8471
  }
7663
8472
 
7664
8473
  // 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";
8474
+ import { existsSync as existsSync15, lstatSync as lstatSync3, rmSync as rmSync2 } from "fs";
8475
+ import { join as join18 } from "path";
8476
+ import chalk20 from "chalk";
7668
8477
  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) => {
8478
+ 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
8479
  const jsonMode = isJSONMode();
7671
8480
  const projectRoot = process.cwd();
7672
8481
  const manifest = readManifest(projectRoot);
@@ -7676,7 +8485,7 @@ function registerRemoveCommand(program2) {
7676
8485
  outputError("NOT_FOUND", `Package "${name}" is not installed.`);
7677
8486
  process.exit(1);
7678
8487
  }
7679
- console.error(chalk15.red(`Package "${name}" is not installed.`));
8488
+ console.error(chalk20.red(`Package "${name}" is not installed.`));
7680
8489
  process.exit(1);
7681
8490
  }
7682
8491
  const shortName = name.split("/").pop();
@@ -7688,15 +8497,15 @@ function registerRemoveCommand(program2) {
7688
8497
  for (const agentId of pkg2.agents) {
7689
8498
  const placementPath = getSkillPlacementPath(agentId, shortName, "project");
7690
8499
  if (placementPath) {
7691
- removedPaths.push(join15(projectRoot, placementPath));
8500
+ removedPaths.push(join18(projectRoot, placementPath));
7692
8501
  }
7693
8502
  }
7694
8503
  } else {
7695
8504
  for (const agentId of pkg2.agents) {
7696
8505
  const placementPath = getSkillPlacementPath(agentId, shortName, "project");
7697
8506
  if (!placementPath) continue;
7698
- const fullPath = join15(projectRoot, placementPath);
7699
- if (existsSync13(fullPath)) {
8507
+ const fullPath = join18(projectRoot, placementPath);
8508
+ if (existsSync15(fullPath)) {
7700
8509
  removedPaths.push(fullPath);
7701
8510
  }
7702
8511
  }
@@ -7710,28 +8519,28 @@ function registerRemoveCommand(program2) {
7710
8519
  });
7711
8520
  return;
7712
8521
  }
7713
- console.log(`${chalk15.yellow("[dry-run]")} Would remove ${chalk15.green(name)}`);
8522
+ console.log(`${chalk20.yellow("[dry-run]")} Would remove ${chalk20.green(name)}`);
7714
8523
  if (hasCanonical) {
7715
8524
  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:"));
8525
+ console.log(chalk20.dim(" Canonical path to remove:"));
8526
+ console.log(chalk20.dim(` ${canonicalPath}`));
8527
+ console.log(chalk20.dim(" Agent symlinks to remove:"));
7719
8528
  for (const agentId of pkg2.agents) {
7720
8529
  const placementPath = getSkillPlacementPath(agentId, shortName, "project");
7721
8530
  if (placementPath) {
7722
- console.log(chalk15.dim(` ${join15(projectRoot, placementPath)}`));
8531
+ console.log(chalk20.dim(` ${join18(projectRoot, placementPath)}`));
7723
8532
  }
7724
8533
  }
7725
8534
  } else {
7726
- const pathsToRemove = removedPaths.filter((p) => existsSync13(p));
8535
+ const pathsToRemove = removedPaths.filter((p) => existsSync15(p));
7727
8536
  if (pathsToRemove.length > 0) {
7728
- console.log(chalk15.dim(" Paths to remove:"));
8537
+ console.log(chalk20.dim(" Paths to remove:"));
7729
8538
  for (const p of pathsToRemove) {
7730
- console.log(chalk15.dim(` ${p}`));
8539
+ console.log(chalk20.dim(` ${p}`));
7731
8540
  }
7732
8541
  }
7733
8542
  }
7734
- console.log(chalk15.dim(" Would update manifest and lockfile"));
8543
+ console.log(chalk20.dim(" Would update manifest and lockfile"));
7735
8544
  return;
7736
8545
  }
7737
8546
  const spinner = createSpinner(`Removing ${name}...`).start();
@@ -7742,8 +8551,8 @@ function registerRemoveCommand(program2) {
7742
8551
  for (const agentId of pkg2.agents) {
7743
8552
  const placementPath = getSkillPlacementPath(agentId, shortName, "project");
7744
8553
  if (!placementPath) continue;
7745
- const fullPath = join15(projectRoot, placementPath);
7746
- if (existsSync13(fullPath) || isSymlinkPath(fullPath)) {
8554
+ const fullPath = join18(projectRoot, placementPath);
8555
+ if (existsSync15(fullPath) || isSymlinkPath(fullPath)) {
7747
8556
  rmSync2(fullPath, { recursive: true, force: true });
7748
8557
  }
7749
8558
  }
@@ -7761,35 +8570,35 @@ function registerRemoveCommand(program2) {
7761
8570
  paths: removedPaths
7762
8571
  });
7763
8572
  } else {
7764
- spinner.succeed(`Removed ${chalk15.green(name)}`);
8573
+ spinner.succeed(`Removed ${chalk20.green(name)}`);
7765
8574
  }
7766
8575
  });
7767
8576
  }
7768
8577
  function isSymlinkPath(filePath) {
7769
8578
  try {
7770
- return lstatSync2(filePath).isSymbolicLink();
8579
+ return lstatSync3(filePath).isSymbolicLink();
7771
8580
  } catch {
7772
8581
  return false;
7773
8582
  }
7774
8583
  }
7775
8584
 
7776
8585
  // 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";
8586
+ import { existsSync as existsSync16, readFileSync as readFileSync14 } from "fs";
8587
+ import { basename as basename5, join as join19, resolve as resolve3 } from "path";
8588
+ import chalk21 from "chalk";
7780
8589
  import ora5 from "ora";
7781
8590
  function detectSkillName(skillDir) {
7782
- const skillMdPath = join16(skillDir, "SKILL.md");
7783
- if (!existsSync14(skillMdPath)) {
8591
+ const skillMdPath = join19(skillDir, "SKILL.md");
8592
+ if (!existsSync16(skillMdPath)) {
7784
8593
  return null;
7785
8594
  }
7786
- const content = readFileSync11(skillMdPath, "utf-8");
8595
+ const content = readFileSync14(skillMdPath, "utf-8");
7787
8596
  const nameMatch = content.match(/^name:\s*(.+)$/m);
7788
8597
  return nameMatch?.[1]?.trim() ?? basename5(skillDir);
7789
8598
  }
7790
8599
  function resolveSkillContext(options) {
7791
8600
  const skillDir = options.path ? resolve3(process.cwd(), options.path) : process.cwd();
7792
- if (!existsSync14(skillDir)) {
8601
+ if (!existsSync16(skillDir)) {
7793
8602
  return null;
7794
8603
  }
7795
8604
  const skillName = detectSkillName(skillDir);
@@ -7815,7 +8624,7 @@ function registerSaveCommand(program2) {
7815
8624
  if (!context) {
7816
8625
  const target = options.path ?? process.cwd();
7817
8626
  process.stderr.write(
7818
- chalk16.red(`No SKILL.md found in ${target}. Run this from a skill directory.
8627
+ chalk21.red(`No SKILL.md found in ${target}. Run this from a skill directory.
7819
8628
  `)
7820
8629
  );
7821
8630
  process.exit(1);
@@ -7825,7 +8634,7 @@ function registerSaveCommand(program2) {
7825
8634
  const namespace = findNamespace(projectRoot, skillName);
7826
8635
  if (!namespace) {
7827
8636
  process.stderr.write(
7828
- chalk16.red(
8637
+ chalk21.red(
7829
8638
  `Skill "${skillName}" not found in manifest. Install it first or check the directory.
7830
8639
  `
7831
8640
  )
@@ -7861,13 +8670,13 @@ function registerSaveCommand(program2) {
7861
8670
  );
7862
8671
  } else {
7863
8672
  process.stdout.write(
7864
- chalk16.yellow("[dry-run]") + ` Would save ${chalk16.green(skillName)} to @${namespace.org}/${namespace.name}
8673
+ chalk21.yellow("[dry-run]") + ` Would save ${chalk21.green(skillName)} to @${namespace.org}/${namespace.name}
7865
8674
  `
7866
8675
  );
7867
- process.stdout.write(chalk16.dim(` Message: ${commitMessage}
8676
+ process.stdout.write(chalk21.dim(` Message: ${commitMessage}
7868
8677
  `));
7869
8678
  process.stdout.write(
7870
- chalk16.dim(` Files: ${filesToSave.map((f) => f.path).join(", ")}
8679
+ chalk21.dim(` Files: ${filesToSave.map((f) => f.path).join(", ")}
7871
8680
  `)
7872
8681
  );
7873
8682
  }
@@ -7904,7 +8713,7 @@ function registerSaveCommand(program2) {
7904
8713
  );
7905
8714
  } else {
7906
8715
  spinner.succeed(
7907
- `Saved ${chalk16.green(skillName)} ${chalk16.dim(`(${result.commitSha.slice(0, 7)})`)}`
8716
+ `Saved ${chalk21.green(skillName)} ${chalk21.dim(`(${result.commitSha.slice(0, 7)})`)}`
7908
8717
  );
7909
8718
  }
7910
8719
  } catch (error) {
@@ -7915,19 +8724,19 @@ function registerSaveCommand(program2) {
7915
8724
  }
7916
8725
 
7917
8726
  // src/commands/scan.ts
7918
- import { readFileSync as readFileSync12 } from "fs";
7919
- import { homedir as homedir7 } from "os";
7920
- import chalk17 from "chalk";
8727
+ import { readFileSync as readFileSync15 } from "fs";
8728
+ import { homedir as homedir8 } from "os";
8729
+ import chalk22 from "chalk";
7921
8730
  function registerScanCommand(program2) {
7922
8731
  program2.command("scan [path]").description("Scan directory for agent configs and skills").action(async (path) => {
7923
8732
  const jsonMode = isJSONMode();
7924
8733
  const targetPath = path ?? process.cwd();
7925
8734
  const projectAgents = detectInstalledAgents(targetPath);
7926
- const globalAgents = detectGlobalAgents(homedir7());
8735
+ const globalAgents = detectGlobalAgents(homedir8());
7927
8736
  const seenIds = new Set(projectAgents.map((a) => a.id));
7928
8737
  const agents = [...projectAgents, ...globalAgents.filter((a) => !seenIds.has(a.id))];
7929
8738
  const projectFiles = scanForSkillFiles(targetPath);
7930
- const globalFiles = scanGlobalSkillFiles(homedir7());
8739
+ const globalFiles = scanGlobalSkillFiles(homedir8());
7931
8740
  const seenPaths = new Set(projectFiles.map((f) => f.path));
7932
8741
  const files = [...projectFiles, ...globalFiles.filter((f) => !seenPaths.has(f.path))];
7933
8742
  if (jsonMode) {
@@ -7946,58 +8755,58 @@ function registerScanCommand(program2) {
7946
8755
  outputSuccess(result);
7947
8756
  return;
7948
8757
  }
7949
- console.log(chalk17.bold("\nDetected agents:\n"));
8758
+ console.log(chalk22.bold("\nDetected agents:\n"));
7950
8759
  if (agents.length === 0) {
7951
- console.log(chalk17.dim(" No agents detected."));
8760
+ console.log(chalk22.dim(" No agents detected."));
7952
8761
  } else {
7953
8762
  for (const agent of agents) {
7954
- console.log(` ${chalk17.green(agent.name)} ${chalk17.dim(agent.configPath)}`);
8763
+ console.log(` ${chalk22.green(agent.name)} ${chalk22.dim(agent.configPath)}`);
7955
8764
  }
7956
8765
  }
7957
- console.log(chalk17.bold("\nDiscovered files:\n"));
8766
+ console.log(chalk22.bold("\nDiscovered files:\n"));
7958
8767
  if (files.length === 0) {
7959
- console.log(chalk17.dim(" No skill or config files found."));
8768
+ console.log(chalk22.dim(" No skill or config files found."));
7960
8769
  } else {
7961
8770
  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)}`);
8771
+ const typeLabel = chalk22.dim(`[${file.detectedType}]`);
8772
+ const agentLabel = chalk22.cyan(`(${file.agentId})`);
8773
+ console.log(` ${typeLabel} ${agentLabel} ${file.name} ${chalk22.dim(file.path)}`);
7965
8774
  }
7966
8775
  }
7967
8776
  const skillFiles = files.filter((f) => f.detectedType === "SKILL");
7968
8777
  if (skillFiles.length > 0) {
7969
- console.log(chalk17.bold("\nSkill spec validation:\n"));
8778
+ console.log(chalk22.bold("\nSkill spec validation:\n"));
7970
8779
  for (const file of skillFiles) {
7971
8780
  let content;
7972
8781
  try {
7973
- content = readFileSync12(file.path, "utf-8");
8782
+ content = readFileSync15(file.path, "utf-8");
7974
8783
  } catch {
7975
- console.log(` ${chalk17.red("\u2717")} ${file.name} ${chalk17.dim("Could not read file")}`);
8784
+ console.log(` ${chalk22.red("\u2717")} ${file.name} ${chalk22.dim("Could not read file")}`);
7976
8785
  continue;
7977
8786
  }
7978
8787
  const result = validateSkillMd(content);
7979
8788
  if (result.valid && result.specCompliant) {
7980
8789
  console.log(
7981
- ` ${chalk17.green("\u2713")} ${file.name} ${chalk17.green("Agent Skills spec compliant")}`
8790
+ ` ${chalk22.green("\u2713")} ${file.name} ${chalk22.green("Agent Skills spec compliant")}`
7982
8791
  );
7983
8792
  } else if (result.valid && !result.specCompliant) {
7984
8793
  console.log(
7985
- ` ${chalk17.yellow("\u2713")} ${file.name} ${chalk17.yellow("Valid (Agentver extended)")}`
8794
+ ` ${chalk22.yellow("\u2713")} ${file.name} ${chalk22.yellow("Valid (Agentver extended)")}`
7986
8795
  );
7987
8796
  } else {
7988
- console.log(` ${chalk17.red("\u2717")} ${file.name} ${chalk17.red("Invalid")}`);
8797
+ console.log(` ${chalk22.red("\u2717")} ${file.name} ${chalk22.red("Invalid")}`);
7989
8798
  for (const error of result.errors) {
7990
- console.log(` ${chalk17.red(`\u2514 ${error}`)}`);
8799
+ console.log(` ${chalk22.red(`\u2514 ${error}`)}`);
7991
8800
  }
7992
8801
  }
7993
8802
  if (result.warnings.length > 0) {
7994
8803
  for (const warning of result.warnings) {
7995
- console.log(` ${chalk17.yellow(`\u26A0 ${warning}`)}`);
8804
+ console.log(` ${chalk22.yellow(`\u26A0 ${warning}`)}`);
7996
8805
  }
7997
8806
  }
7998
8807
  if (result.agentverExtensions.length > 0) {
7999
8808
  console.log(
8000
- ` ${chalk17.dim(`Agentver extensions: ${result.agentverExtensions.join(", ")}`)}`
8809
+ ` ${chalk22.dim(`Agentver extensions: ${result.agentverExtensions.join(", ")}`)}`
8001
8810
  );
8002
8811
  }
8003
8812
  }
@@ -8005,7 +8814,7 @@ function registerScanCommand(program2) {
8005
8814
  const manifest = readManifest(targetPath);
8006
8815
  const manifestEntries = Object.entries(manifest.packages);
8007
8816
  if (manifestEntries.length > 0) {
8008
- console.log(chalk17.bold(`
8817
+ console.log(chalk22.bold(`
8009
8818
  Installed skills (${manifestEntries.length}):
8010
8819
  `));
8011
8820
  for (const [name, pkg2] of manifestEntries) {
@@ -8016,12 +8825,12 @@ Installed skills (${manifestEntries.length}):
8016
8825
  const ref = `@${source.ref}`;
8017
8826
  const commit = `(${source.commit.slice(0, 7)})`;
8018
8827
  console.log(
8019
- ` ${chalk17.green(name.padEnd(18))} ${chalk17.dim(sourcePath.padEnd(40))} ${chalk17.cyan(ref.padEnd(10))} ${chalk17.dim(commit)} ${chalk17.dim(agentList)}`
8828
+ ` ${chalk22.green(name.padEnd(18))} ${chalk22.dim(sourcePath.padEnd(40))} ${chalk22.cyan(ref.padEnd(10))} ${chalk22.dim(commit)} ${chalk22.dim(agentList)}`
8020
8829
  );
8021
8830
  } else {
8022
8831
  const sourceLabel = `${source.hostname} (well-known)`;
8023
8832
  console.log(
8024
- ` ${chalk17.green(name.padEnd(18))} ${chalk17.dim(sourceLabel.padEnd(40))} ${chalk17.dim("[well-known]").padEnd(10)} ${chalk17.dim(agentList)}`
8833
+ ` ${chalk22.green(name.padEnd(18))} ${chalk22.dim(sourceLabel.padEnd(40))} ${chalk22.dim("[well-known]").padEnd(10)} ${chalk22.dim(agentList)}`
8025
8834
  );
8026
8835
  }
8027
8836
  }
@@ -8031,7 +8840,7 @@ Installed skills (${manifestEntries.length}):
8031
8840
  }
8032
8841
 
8033
8842
  // src/commands/search.ts
8034
- import chalk18 from "chalk";
8843
+ import chalk23 from "chalk";
8035
8844
  import ora6 from "ora";
8036
8845
 
8037
8846
  // src/registry/skills-sh.ts
@@ -8109,60 +8918,60 @@ function formatInstallCount(count) {
8109
8918
  }
8110
8919
  function renderPlatformResults(results, total) {
8111
8920
  if (results.length === 0) return;
8112
- process.stdout.write(chalk18.bold(`
8921
+ process.stdout.write(chalk23.bold(`
8113
8922
  Platform results (${total}):
8114
8923
 
8115
8924
  `));
8116
8925
  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}
8926
+ const desc = result.description ? chalk23.dim(` \u2014 ${result.description}`) : "";
8927
+ const stars = result.starCount > 0 ? chalk23.yellow(` \u2605 ${result.starCount}`) : "";
8928
+ const installs = result.installCount > 0 ? chalk23.cyan(` \u2193 ${formatInstallCount(result.installCount)}`) : "";
8929
+ const cats = result.categories.length > 0 ? chalk23.dim(` [${result.categories.map((c) => c.name).join(", ")}]`) : "";
8930
+ process.stdout.write(` ${chalk23.green(result.slug)}${stars}${installs}${cats}${desc}
8122
8931
  `);
8123
8932
  }
8124
8933
  process.stdout.write("\n");
8125
8934
  }
8126
8935
  function renderCommunityResults(results) {
8127
8936
  if (results.length === 0) return;
8128
- process.stdout.write(chalk18.bold(`
8937
+ process.stdout.write(chalk23.bold(`
8129
8938
  Skills from skills.sh:
8130
8939
 
8131
8940
  `));
8132
8941
  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)}`);
8942
+ const nameCol = chalk23.green(result.name);
8943
+ const sourceCol = chalk23.dim(`(${result.source})`);
8944
+ const installCol = chalk23.cyan(`\u2193 ${formatInstallCount(result.installCount)}`);
8136
8945
  process.stdout.write(` ${nameCol} ${sourceCol} ${installCol}
8137
8946
  `);
8138
8947
  if (result.description) {
8139
- process.stdout.write(` ${chalk18.dim(result.description)}
8948
+ process.stdout.write(` ${chalk23.dim(result.description)}
8140
8949
  `);
8141
8950
  }
8142
8951
  process.stdout.write("\n");
8143
8952
  }
8144
8953
  process.stdout.write(
8145
- chalk18.dim(" Install with: ") + chalk18.white("agentver install github.com/{source}/{name}") + "\n\n"
8954
+ chalk23.dim(" Install with: ") + chalk23.white("agentver install github.com/{source}/{name}") + "\n\n"
8146
8955
  );
8147
8956
  }
8148
8957
  function renderWellKnownResults(hostname3, skills) {
8149
8958
  if (skills.length === 0) return;
8150
- process.stdout.write(chalk18.bold(`
8959
+ process.stdout.write(chalk23.bold(`
8151
8960
  Skills from ${hostname3}:
8152
8961
 
8153
8962
  `));
8154
8963
  for (const skill of skills) {
8155
- process.stdout.write(` ${chalk18.green(skill.name)} ${chalk18.dim(`\u2014 ${skill.description}`)}
8964
+ process.stdout.write(` ${chalk23.green(skill.name)} ${chalk23.dim(`\u2014 ${skill.description}`)}
8156
8965
  `);
8157
8966
  process.stdout.write(
8158
- ` ${chalk18.dim("Install:")} ${chalk18.white(`agentver install ${hostname3}/${skill.name}`)}
8967
+ ` ${chalk23.dim("Install:")} ${chalk23.white(`agentver install ${hostname3}/${skill.name}`)}
8159
8968
  `
8160
8969
  );
8161
8970
  process.stdout.write("\n");
8162
8971
  }
8163
8972
  }
8164
8973
  function renderNoResults(query) {
8165
- process.stdout.write(chalk18.dim(`No results for "${query}"
8974
+ process.stdout.write(chalk23.dim(`No results for "${query}"
8166
8975
  `));
8167
8976
  }
8168
8977
  function registerSearchCommand(program2) {
@@ -8177,7 +8986,7 @@ function registerSearchCommand(program2) {
8177
8986
  if (requestedSource) {
8178
8987
  if (!["platform", "community", "well-known", "all"].includes(requestedSource)) {
8179
8988
  process.stderr.write(
8180
- chalk18.red(
8989
+ chalk23.red(
8181
8990
  `Invalid source "${requestedSource}". Use: platform, community, well-known, or all
8182
8991
  `
8183
8992
  )
@@ -8187,7 +8996,7 @@ function registerSearchCommand(program2) {
8187
8996
  source = requestedSource;
8188
8997
  if (source === "platform" && !connected) {
8189
8998
  process.stderr.write(
8190
- chalk18.red("Not connected to a platform. Run `agentver login <url>` to connect.\n")
8999
+ chalk23.red("Not connected to a platform. Run `agentver login <url>` to connect.\n")
8191
9000
  );
8192
9001
  process.exit(1);
8193
9002
  }
@@ -8255,7 +9064,7 @@ function registerSearchCommand(program2) {
8255
9064
  if (communityResults.length > 0) {
8256
9065
  const example = communityResults[0];
8257
9066
  process.stdout.write(
8258
- chalk18.dim(" Example: ") + chalk18.white(`agentver install ${toGitInstallSource(example)}`) + "\n"
9067
+ chalk23.dim(" Example: ") + chalk23.white(`agentver install ${toGitInstallSource(example)}`) + "\n"
8259
9068
  );
8260
9069
  }
8261
9070
  } catch (error) {
@@ -8267,13 +9076,13 @@ function registerSearchCommand(program2) {
8267
9076
  }
8268
9077
 
8269
9078
  // src/commands/status.ts
8270
- import chalk19 from "chalk";
9079
+ import chalk24 from "chalk";
8271
9080
  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("?")
9081
+ "up-to-date": chalk24.green("\u2713"),
9082
+ modified: chalk24.yellow("M"),
9083
+ upstream: chalk24.cyan("U"),
9084
+ both: chalk24.red("MU"),
9085
+ unknown: chalk24.dim("?")
8277
9086
  };
8278
9087
  function parseManifestUri2(uri) {
8279
9088
  const parts = uri.split("/");
@@ -8295,7 +9104,7 @@ async function readLocalFiles2(projectRoot, packageName, agents) {
8295
9104
  return [];
8296
9105
  }
8297
9106
  async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileIntegrity, offline) {
8298
- const { source, agents } = manifestEntry;
9107
+ const { source, agents, pinned } = manifestEntry;
8299
9108
  if (source.type === "well-known") {
8300
9109
  let locallyModified2 = false;
8301
9110
  try {
@@ -8313,7 +9122,8 @@ async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileInte
8313
9122
  sourceUri: source.hostname,
8314
9123
  ref: "well-known",
8315
9124
  commit: "",
8316
- agents
9125
+ agents,
9126
+ pinned: pinned || void 0
8317
9127
  };
8318
9128
  }
8319
9129
  if (source.uri === "unknown") {
@@ -8323,7 +9133,8 @@ async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileInte
8323
9133
  sourceUri: source.uri,
8324
9134
  ref: source.ref,
8325
9135
  commit: source.commit,
8326
- agents
9136
+ agents,
9137
+ pinned: pinned || void 0
8327
9138
  };
8328
9139
  }
8329
9140
  let locallyModified = false;
@@ -8367,18 +9178,20 @@ async function checkPackageStatus(projectRoot, name, manifestEntry, lockfileInte
8367
9178
  ref: source.ref,
8368
9179
  commit: source.commit,
8369
9180
  upstreamCommit: upstreamChanged ? upstreamCommit : void 0,
8370
- agents
9181
+ agents,
9182
+ pinned: pinned || void 0
8371
9183
  };
8372
9184
  }
8373
9185
  function formatStatusLine(status) {
8374
9186
  const symbol = STATUS_SYMBOLS[status.category];
8375
9187
  const padding = status.category === "both" ? "" : " ";
8376
9188
  if (status.category === "unknown") {
8377
- return ` ${symbol} ${chalk19.white(status.name)} ${chalk19.dim("unknown source")}`;
9189
+ return ` ${symbol} ${chalk24.white(status.name)} ${chalk24.dim("unknown source")}`;
8378
9190
  }
8379
9191
  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}`;
9192
+ const upstream = status.upstreamCommit ? ` ${chalk24.dim("\u2192")} ${chalk24.cyan(`upstream: ${status.upstreamCommit.slice(0, 7)}`)}` : "";
9193
+ const pinned = status.pinned ? chalk24.yellow(" [pinned]") : "";
9194
+ return ` ${symbol}${padding} ${chalk24.white(status.name)}${pinned} ${chalk24.dim(status.sourceUri)} ${chalk24.cyan(`@${status.ref}`)} ${chalk24.dim(`(${shortCommit})`)}${upstream}`;
8382
9195
  }
8383
9196
  function buildStatusOutput(statuses) {
8384
9197
  return {
@@ -8396,7 +9209,8 @@ function toStatusResult(output) {
8396
9209
  name: p.name,
8397
9210
  status: p.category,
8398
9211
  modified: p.category === "modified" || p.category === "both",
8399
- upstream: p.category === "upstream" || p.category === "both"
9212
+ upstream: p.category === "upstream" || p.category === "both",
9213
+ pinned: p.pinned || void 0
8400
9214
  })),
8401
9215
  summary: {
8402
9216
  total: output.total,
@@ -8418,7 +9232,7 @@ function registerStatusCommand(program2) {
8418
9232
  if (jsonMode) {
8419
9233
  outputSuccess(toStatusResult(buildStatusOutput([])));
8420
9234
  } else {
8421
- console.log(chalk19.dim("No packages installed."));
9235
+ console.log(chalk24.dim("No packages installed."));
8422
9236
  }
8423
9237
  return;
8424
9238
  }
@@ -8441,7 +9255,7 @@ function registerStatusCommand(program2) {
8441
9255
  outputSuccess(toStatusResult(buildStatusOutput(statuses)));
8442
9256
  return;
8443
9257
  }
8444
- console.log(chalk19.bold(`
9258
+ console.log(chalk24.bold(`
8445
9259
  Installed skills (${statuses.length}):
8446
9260
  `));
8447
9261
  for (const status of statuses) {
@@ -8452,16 +9266,16 @@ Installed skills (${statuses.length}):
8452
9266
  }
8453
9267
 
8454
9268
  // src/commands/suggest.ts
8455
- import { existsSync as existsSync15 } from "fs";
8456
- import { join as join17 } from "path";
8457
- import chalk20 from "chalk";
9269
+ import { existsSync as existsSync17 } from "fs";
9270
+ import { join as join20 } from "path";
9271
+ import chalk25 from "chalk";
8458
9272
  var HTTP_TIMEOUT_MS2 = 15e3;
8459
9273
  async function readLocalFiles3(projectRoot, packageName, agents) {
8460
9274
  for (const agentId of agents) {
8461
9275
  const placementPath = getSkillPlacementPath(agentId, packageName, "project");
8462
9276
  if (!placementPath) continue;
8463
- const fullPath = join17(projectRoot, placementPath);
8464
- if (!existsSync15(fullPath)) continue;
9277
+ const fullPath = join20(projectRoot, placementPath);
9278
+ if (!existsSync17(fullPath)) continue;
8465
9279
  const files = await readFilesFromDirectory(fullPath);
8466
9280
  return files.map((f) => ({ path: f.path, content: f.content }));
8467
9281
  }
@@ -8509,141 +9323,211 @@ async function postToPlatform(path, body) {
8509
9323
  throw error;
8510
9324
  }
8511
9325
  }
9326
+ function buildEndpoint(manifestEntry, packageName) {
9327
+ if (manifestEntry.source.type !== "git") return "";
9328
+ const orgSlug = manifestEntry.source.uri.split("/")[1] ?? "";
9329
+ return `/skills/@${orgSlug}/${packageName}/suggestions`;
9330
+ }
9331
+ async function submitSuggestion(projectRoot, packageName, manifestEntry, title, description) {
9332
+ const localFiles = await readLocalFiles3(projectRoot, packageName, manifestEntry.agents);
9333
+ if (localFiles.length === 0) {
9334
+ throw new Error(`No local files found for "${packageName}".`);
9335
+ }
9336
+ const endpoint = buildEndpoint(manifestEntry, packageName);
9337
+ const requestBody = {
9338
+ title,
9339
+ description,
9340
+ files: localFiles
9341
+ };
9342
+ const result = await postToPlatform(endpoint, requestBody);
9343
+ return { localFiles, result };
9344
+ }
8512
9345
  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
- );
9346
+ 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(
9347
+ async (title, options) => {
9348
+ const json = isJSONMode();
9349
+ const platformUrl = getPlatformUrl();
9350
+ const creds = await getCredentials();
9351
+ if (!options.dryRun && (!platformUrl || !creds?.token && !creds?.apiKey)) {
9352
+ if (json) {
9353
+ outputError(
9354
+ "AUTH_REQUIRED",
9355
+ "Not connected to a platform. Run `agentver login <url>` first."
9356
+ );
9357
+ process.exit(1);
9358
+ }
9359
+ console.error(chalk25.red("Not connected to a platform. Run `agentver login <url>` first."));
8523
9360
  process.exit(1);
8524
9361
  }
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);
9362
+ const projectRoot = process.cwd();
9363
+ const manifest = readManifest(projectRoot);
9364
+ const lockfile = readLockfile(projectRoot);
9365
+ const modifiedPackages = [];
9366
+ for (const [name, manifestEntry] of Object.entries(manifest.packages)) {
9367
+ const lockfileEntry = lockfile.packages[name];
9368
+ if (!lockfileEntry) continue;
9369
+ const { agents } = manifestEntry;
9370
+ const localFiles = await readLocalFiles3(projectRoot, name, agents);
9371
+ if (localFiles.length === 0) continue;
9372
+ const currentIntegrity = computeSha256FromFiles(localFiles);
9373
+ if (currentIntegrity !== lockfileEntry.integrity) {
9374
+ modifiedPackages.push(name);
9375
+ }
8547
9376
  }
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."));
9377
+ if (modifiedPackages.length === 0) {
9378
+ if (json) {
9379
+ outputError("NO_CHANGES", "No modified packages detected.");
9380
+ process.exit(1);
9381
+ }
9382
+ console.log(chalk25.dim("No modified packages detected."));
9383
+ return;
8567
9384
  }
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}".`);
9385
+ const targets = options.name ? modifiedPackages.filter((n) => n === options.name) : modifiedPackages;
9386
+ if (targets.length === 0 && options.name) {
9387
+ const message = `Package "${options.name}" is not in the modified list. Modified: ${modifiedPackages.join(", ")}`;
8575
9388
  if (json) {
8576
- outputError("NOT_FOUND", `No local files found for "${targetName}".`);
9389
+ outputError("NOT_FOUND", message);
9390
+ process.exit(1);
9391
+ }
9392
+ console.error(chalk25.red(message));
9393
+ process.exit(1);
9394
+ }
9395
+ const unsupportedTargets = targets.filter(
9396
+ (name) => manifest.packages[name]?.source.type === "well-known"
9397
+ );
9398
+ if (unsupportedTargets.length > 0) {
9399
+ for (const name of unsupportedTargets) {
9400
+ const source = manifest.packages[name].source;
9401
+ if (json) {
9402
+ outputError(
9403
+ "UNSUPPORTED_SOURCE",
9404
+ `Package "${name}" was installed from a well-known source. Suggestions are not supported.`
9405
+ );
9406
+ } else {
9407
+ console.error(
9408
+ chalk25.red(
9409
+ `Package "${name}" was installed from a well-known source (${source.type === "well-known" ? source.hostname : "unknown"}).`
9410
+ )
9411
+ );
9412
+ console.error(chalk25.dim("Suggestions are not supported for well-known sources."));
9413
+ }
8577
9414
  }
9415
+ }
9416
+ const validTargets = targets.filter((n) => !unsupportedTargets.includes(n));
9417
+ if (validTargets.length === 0) {
8578
9418
  process.exit(1);
8579
9419
  }
8580
- const orgSlug = source.uri.split("/")[1] ?? "";
8581
- const pkgName = targetName;
8582
9420
  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();
9421
+ const dryRunResults = [];
9422
+ for (const targetName of validTargets) {
9423
+ const manifestEntry = manifest.packages[targetName];
9424
+ const localFiles = await readLocalFiles3(projectRoot, targetName, manifestEntry.agents);
9425
+ const endpoint = `/api/v1${buildEndpoint(manifestEntry, targetName)}`;
9426
+ dryRunResults.push({
9427
+ package: targetName,
9428
+ title,
9429
+ description: options.description,
9430
+ files: localFiles.map((f) => ({
9431
+ path: f.path,
9432
+ contentLength: f.content.length
9433
+ })),
9434
+ endpoint
9435
+ });
9436
+ }
8594
9437
  if (json) {
8595
- outputSuccess(dryRunResult);
9438
+ outputSuccess(dryRunResults);
8596
9439
  } 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)`);
9440
+ console.log(chalk25.bold("\nDry run \u2014 suggestion preview:\n"));
9441
+ for (const entry of dryRunResults) {
9442
+ console.log(` ${chalk25.dim("Package:")} ${entry.package}`);
9443
+ console.log(` ${chalk25.dim("Title:")} ${entry.title}`);
9444
+ if (entry.description) {
9445
+ console.log(` ${chalk25.dim("Desc:")} ${entry.description}`);
9446
+ }
9447
+ console.log(` ${chalk25.dim("Files:")}`);
9448
+ for (const f of entry.files) {
9449
+ console.log(` ${chalk25.cyan(f.path)} (${f.contentLength} bytes)`);
9450
+ }
9451
+ console.log(` ${chalk25.dim("Endpoint:")} ${entry.endpoint}`);
9452
+ console.log();
8606
9453
  }
8607
- console.log(` ${chalk20.dim("Endpoint:")} ${dryRunResult.endpoint}`);
8608
- console.log();
9454
+ console.log(
9455
+ chalk25.dim(
9456
+ `${dryRunResults.length} package${dryRunResults.length === 1 ? "" : "s"} would get suggestions.`
9457
+ )
9458
+ );
8609
9459
  }
8610
9460
  return;
8611
9461
  }
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}`));
9462
+ const outcomes = [];
9463
+ for (const targetName of validTargets) {
9464
+ const manifestEntry = manifest.packages[targetName];
9465
+ const spinner = createSpinner(`Creating suggestion for ${targetName}...`).start();
9466
+ try {
9467
+ const { result } = await submitSuggestion(
9468
+ projectRoot,
9469
+ targetName,
9470
+ manifestEntry,
9471
+ title,
9472
+ options.description
9473
+ );
9474
+ const proposeResult = {
9475
+ proposalId: result.id,
9476
+ title: result.title ?? title,
9477
+ url: result.url ?? ""
9478
+ };
9479
+ outcomes.push({ package: targetName, success: true, result: proposeResult });
9480
+ if (!json) {
9481
+ spinner.succeed(
9482
+ `Created suggestion for ${chalk25.bold(targetName)}: ${chalk25.bold(proposeResult.title)}`
9483
+ );
9484
+ if (result.url) {
9485
+ console.log(chalk25.dim(` ${result.url}`));
9486
+ }
9487
+ } else {
9488
+ spinner.stop();
9489
+ }
9490
+ } catch (error) {
9491
+ const message = error instanceof Error ? error.message : String(error);
9492
+ outcomes.push({ package: targetName, success: false, error: message });
9493
+ if (!json) {
9494
+ spinner.fail(`Failed to create suggestion for ${chalk25.bold(targetName)}: ${message}`);
9495
+ } else {
9496
+ spinner.stop();
9497
+ }
9498
+ }
8633
9499
  }
8634
- } catch (error) {
8635
- const message = error instanceof Error ? error.message : String(error);
8636
- spinner.fail(`Failed to create suggestion: ${message}`);
9500
+ const succeeded = outcomes.filter((o) => o.success);
9501
+ const failed = outcomes.filter((o) => !o.success);
8637
9502
  if (json) {
8638
- outputError("SUGGEST_FAILED", message);
9503
+ if (validTargets.length === 1) {
9504
+ const outcome = outcomes[0];
9505
+ if (outcome.success) {
9506
+ outputSuccess(outcome.result);
9507
+ } else {
9508
+ outputError("SUGGEST_FAILED", outcome.error);
9509
+ process.exit(1);
9510
+ }
9511
+ } else {
9512
+ outputSuccess(outcomes);
9513
+ }
9514
+ } else if (validTargets.length > 1) {
9515
+ console.log();
9516
+ console.log(
9517
+ chalk25.bold(
9518
+ `Created ${succeeded.length} suggestion${succeeded.length === 1 ? "" : "s"}` + (failed.length > 0 ? ` (${failed.length} failed)` : "")
9519
+ )
9520
+ );
9521
+ }
9522
+ if (failed.length > 0 && succeeded.length === 0) {
9523
+ process.exit(1);
8639
9524
  }
8640
- process.exit(1);
8641
9525
  }
8642
- });
9526
+ );
8643
9527
  }
8644
9528
 
8645
9529
  // src/commands/suggestions.ts
8646
- import chalk21 from "chalk";
9530
+ import chalk26 from "chalk";
8647
9531
  var HTTP_TIMEOUT_MS3 = 15e3;
8648
9532
  async function getFromPlatform(path) {
8649
9533
  const platformUrl = getPlatformUrl();
@@ -8698,21 +9582,21 @@ function formatDate2(isoDate) {
8698
9582
  }
8699
9583
  }
8700
9584
  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
9585
+ OPEN: chalk26.green,
9586
+ IN_REVIEW: chalk26.yellow,
9587
+ APPROVED: chalk26.blue,
9588
+ MERGED: chalk26.magenta,
9589
+ REJECTED: chalk26.red,
9590
+ CLOSED: chalk26.dim
8707
9591
  };
8708
9592
  function formatSuggestionRow(suggestion, idWidth, titleWidth, slugWidth, authorWidth) {
8709
- const id = chalk21.dim(`#${suggestion.id}`.padEnd(idWidth + 1));
9593
+ const id = chalk26.dim(`#${suggestion.id}`.padEnd(idWidth + 1));
8710
9594
  const title = suggestion.title.padEnd(titleWidth);
8711
- const slug = chalk21.cyan(suggestion.packageSlug.padEnd(slugWidth));
8712
- const statusFn = STATUS_COLOURS[suggestion.status] ?? chalk21.dim;
9595
+ const slug = chalk26.cyan(suggestion.packageSlug.padEnd(slugWidth));
9596
+ const statusFn = STATUS_COLOURS[suggestion.status] ?? chalk26.dim;
8713
9597
  const status = statusFn(suggestion.status.padEnd(11));
8714
- const author = chalk21.dim(suggestion.author.padEnd(authorWidth));
8715
- const date = chalk21.dim(formatDate2(suggestion.createdAt));
9598
+ const author = chalk26.dim(suggestion.author.padEnd(authorWidth));
9599
+ const date = chalk26.dim(formatDate2(suggestion.createdAt));
8716
9600
  return ` ${id} ${title} ${slug} ${status} ${author} ${date}`;
8717
9601
  }
8718
9602
  function registerSuggestionsCommand(program2) {
@@ -8728,7 +9612,7 @@ function registerSuggestionsCommand(program2) {
8728
9612
  );
8729
9613
  process.exit(1);
8730
9614
  }
8731
- console.error(chalk21.red("Not connected to a platform. Run `agentver login <url>` first."));
9615
+ console.error(chalk26.red("Not connected to a platform. Run `agentver login <url>` first."));
8732
9616
  process.exit(1);
8733
9617
  }
8734
9618
  const spinner = createSpinner("Fetching suggestions...").start();
@@ -8760,7 +9644,7 @@ function registerSuggestionsCommand(program2) {
8760
9644
  }
8761
9645
  if (suggestions.length === 0) {
8762
9646
  const filterLabel = statusFilter === "ALL" ? "" : ` ${options.status}`;
8763
- console.log(chalk21.dim(`No${filterLabel} suggestions found.`));
9647
+ console.log(chalk26.dim(`No${filterLabel} suggestions found.`));
8764
9648
  return;
8765
9649
  }
8766
9650
  const idWidth = Math.max(...suggestions.map((s) => `#${s.id}`.length));
@@ -8768,7 +9652,7 @@ function registerSuggestionsCommand(program2) {
8768
9652
  const slugWidth = Math.max(...suggestions.map((s) => s.packageSlug.length));
8769
9653
  const authorWidth = Math.max(...suggestions.map((s) => s.author.length));
8770
9654
  const heading = statusFilter === "ALL" ? `Suggestions (${suggestions.length})` : `${options.status.charAt(0).toUpperCase() + options.status.slice(1)} suggestions (${suggestions.length})`;
8771
- console.log(chalk21.bold(`
9655
+ console.log(chalk26.bold(`
8772
9656
  ${heading}:
8773
9657
  `));
8774
9658
  for (const suggestion of suggestions) {
@@ -8789,7 +9673,7 @@ ${heading}:
8789
9673
  // src/commands/sync.ts
8790
9674
  import { createHash as createHash4 } from "crypto";
8791
9675
  import { hostname as hostname2 } from "os";
8792
- import chalk22 from "chalk";
9676
+ import chalk27 from "chalk";
8793
9677
  var SYNC_TIMEOUT_MS = 3e4;
8794
9678
  function getMachineId2() {
8795
9679
  return createHash4("sha256").update(hostname2()).digest("hex");
@@ -8806,7 +9690,7 @@ function registerSyncCommand(program2) {
8806
9690
  process.exit(1);
8807
9691
  }
8808
9692
  console.error(
8809
- chalk22.red("Not connected to a platform.") + " Run " + chalk22.cyan("`agentver login <url>`") + " first."
9693
+ chalk27.red("Not connected to a platform.") + " Run " + chalk27.cyan("`agentver login <url>`") + " first."
8810
9694
  );
8811
9695
  process.exit(1);
8812
9696
  }
@@ -8820,7 +9704,7 @@ function registerSyncCommand(program2) {
8820
9704
  process.exit(1);
8821
9705
  }
8822
9706
  console.error(
8823
- chalk22.red("Not connected to a platform.") + " Run " + chalk22.cyan("`agentver login <url>`") + " first."
9707
+ chalk27.red("Not connected to a platform.") + " Run " + chalk27.cyan("`agentver login <url>`") + " first."
8824
9708
  );
8825
9709
  process.exit(1);
8826
9710
  }
@@ -8892,7 +9776,7 @@ function registerSyncCommand(program2) {
8892
9776
  return;
8893
9777
  }
8894
9778
  spinner.succeed(
8895
- `Synced ${chalk22.green(String(result.synced))} skill${result.synced === 1 ? "" : "s"} to platform` + (result.removed > 0 ? chalk22.dim(` (${result.removed} removed)`) : "")
9779
+ `Synced ${chalk27.green(String(result.synced))} skill${result.synced === 1 ? "" : "s"} to platform` + (result.removed > 0 ? chalk27.dim(` (${result.removed} removed)`) : "")
8896
9780
  );
8897
9781
  } catch (error) {
8898
9782
  if (error instanceof DOMException && error.name === "AbortError") {
@@ -8916,23 +9800,23 @@ function registerSyncCommand(program2) {
8916
9800
  }
8917
9801
 
8918
9802
  // src/commands/update.ts
8919
- import { join as join20 } from "path";
8920
- import chalk23 from "chalk";
9803
+ import { join as join23 } from "path";
9804
+ import chalk28 from "chalk";
8921
9805
  import ora7 from "ora";
8922
9806
  import prompts3 from "prompts";
8923
9807
 
8924
9808
  // 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";
9809
+ import { existsSync as existsSync18, mkdirSync as mkdirSync9, readFileSync as readFileSync16, rmSync as rmSync3, writeFileSync as writeFileSync8 } from "fs";
9810
+ import { join as join21 } from "path";
8927
9811
  var PATCHES_DIR = ".agentver/patches";
8928
9812
  var CONTEXT_LINES2 = 3;
8929
9813
  function getPatchPath(projectRoot, packageName) {
8930
- return join18(projectRoot, PATCHES_DIR, `${packageName}.patch`);
9814
+ return join21(projectRoot, PATCHES_DIR, `${packageName}.patch`);
8931
9815
  }
8932
9816
  function savePatch(projectRoot, packageName, patchContent) {
8933
9817
  const patchPath = getPatchPath(projectRoot, packageName);
8934
- const dir = join18(projectRoot, PATCHES_DIR);
8935
- if (!existsSync16(dir)) {
9818
+ const dir = join21(projectRoot, PATCHES_DIR);
9819
+ if (!existsSync18(dir)) {
8936
9820
  mkdirSync9(dir, { recursive: true });
8937
9821
  }
8938
9822
  writeFileSync8(patchPath, patchContent, "utf-8");
@@ -8940,7 +9824,7 @@ function savePatch(projectRoot, packageName, patchContent) {
8940
9824
  }
8941
9825
  function removePatch(projectRoot, packageName) {
8942
9826
  const patchPath = getPatchPath(projectRoot, packageName);
8943
- if (existsSync16(patchPath)) {
9827
+ if (existsSync18(patchPath)) {
8944
9828
  rmSync3(patchPath);
8945
9829
  }
8946
9830
  }
@@ -8987,30 +9871,30 @@ function applyPatch(projectRoot, patchContent) {
8987
9871
  };
8988
9872
  }
8989
9873
  function applyFilePatch(projectRoot, filePatch) {
8990
- const fullPath = join18(projectRoot, filePatch.filePath);
9874
+ const fullPath = join21(projectRoot, filePatch.filePath);
8991
9875
  const hasOnlyAdditions = filePatch.hunks.every(
8992
9876
  (h) => h.lines.every((l) => l.startsWith("+") || l.startsWith(" "))
8993
9877
  );
8994
9878
  const hasOnlyDeletions = filePatch.hunks.every(
8995
9879
  (h) => h.lines.every((l) => l.startsWith("-") || l.startsWith(" "))
8996
9880
  );
8997
- if (hasOnlyAdditions && !existsSync16(fullPath)) {
9881
+ if (hasOnlyAdditions && !existsSync18(fullPath)) {
8998
9882
  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)) {
9883
+ const dir = join21(fullPath, "..");
9884
+ if (!existsSync18(dir)) {
9001
9885
  mkdirSync9(dir, { recursive: true });
9002
9886
  }
9003
9887
  writeFileSync8(fullPath, content, "utf-8");
9004
9888
  return true;
9005
9889
  }
9006
- if (hasOnlyDeletions && existsSync16(fullPath)) {
9890
+ if (hasOnlyDeletions && existsSync18(fullPath)) {
9007
9891
  rmSync3(fullPath);
9008
9892
  return true;
9009
9893
  }
9010
- if (!existsSync16(fullPath)) {
9894
+ if (!existsSync18(fullPath)) {
9011
9895
  return false;
9012
9896
  }
9013
- const currentContent = readFileSync13(fullPath, "utf-8");
9897
+ const currentContent = readFileSync16(fullPath, "utf-8");
9014
9898
  const currentLines = currentContent.split("\n");
9015
9899
  let offset = 0;
9016
9900
  for (const hunk of filePatch.hunks) {
@@ -9294,17 +10178,17 @@ function backtrackMyers(trace, oldLines, newLines, finalD, max) {
9294
10178
  }
9295
10179
 
9296
10180
  // src/utils/backup.ts
9297
- import { cpSync, existsSync as existsSync17, mkdirSync as mkdirSync10, mkdtempSync, rmSync as rmSync4 } from "fs";
10181
+ import { cpSync, existsSync as existsSync19, mkdirSync as mkdirSync10, mkdtempSync, rmSync as rmSync4 } from "fs";
9298
10182
  import { tmpdir as tmpdir2 } from "os";
9299
- import { join as join19 } from "path";
10183
+ import { join as join22 } from "path";
9300
10184
  function createBackup(packageName, projectRoot, skillDir) {
9301
- const tempDir = mkdtempSync(join19(tmpdir2(), "agentver-backup-"));
10185
+ const tempDir = mkdtempSync(join22(tmpdir2(), "agentver-backup-"));
9302
10186
  const manifest = readManifest(projectRoot);
9303
10187
  const manifestEntry = manifest.packages[packageName] ?? null;
9304
10188
  const lockfile = readLockfile(projectRoot);
9305
10189
  const lockfileEntry = lockfile.packages[packageName] ?? null;
9306
- if (skillDir && existsSync17(skillDir)) {
9307
- const backupSkillDir = join19(tempDir, "files");
10190
+ if (skillDir && existsSync19(skillDir)) {
10191
+ const backupSkillDir = join22(tempDir, "files");
9308
10192
  mkdirSync10(backupSkillDir, { recursive: true });
9309
10193
  cpSync(skillDir, backupSkillDir, { recursive: true });
9310
10194
  }
@@ -9319,9 +10203,9 @@ function createBackup(packageName, projectRoot, skillDir) {
9319
10203
  }
9320
10204
  function restoreBackup(backup) {
9321
10205
  if (backup.skillDir) {
9322
- const backupSkillDir = join19(backup.tempDir, "files");
9323
- if (existsSync17(backupSkillDir)) {
9324
- if (existsSync17(backup.skillDir)) {
10206
+ const backupSkillDir = join22(backup.tempDir, "files");
10207
+ if (existsSync19(backupSkillDir)) {
10208
+ if (existsSync19(backup.skillDir)) {
9325
10209
  rmSync4(backup.skillDir, { recursive: true, force: true });
9326
10210
  }
9327
10211
  mkdirSync10(backup.skillDir, { recursive: true });
@@ -9344,7 +10228,7 @@ function restoreBackup(backup) {
9344
10228
  writeLockfile(backup.projectRoot, lockfile);
9345
10229
  }
9346
10230
  function cleanupBackup(backup) {
9347
- if (existsSync17(backup.tempDir)) {
10231
+ if (existsSync19(backup.tempDir)) {
9348
10232
  rmSync4(backup.tempDir, { recursive: true, force: true });
9349
10233
  }
9350
10234
  }
@@ -9450,13 +10334,13 @@ async function handlePatchUpdate(update, projectRoot, agents, spinner) {
9450
10334
  const applyResult = applyPatch(projectRoot, patchContent);
9451
10335
  if (applyResult.applied) {
9452
10336
  removePatch(projectRoot, update.name);
9453
- spinner.succeed(`${chalk23.green(update.name)}: updated and local patch reapplied successfully`);
10337
+ spinner.succeed(`${chalk28.green(update.name)}: updated and local patch reapplied successfully`);
9454
10338
  } else {
9455
10339
  spinner.warn(
9456
- `${chalk23.yellow(update.name)}: updated but patch had conflicts in: ${applyResult.conflicts.join(", ")}`
10340
+ `${chalk28.yellow(update.name)}: updated but patch had conflicts in: ${applyResult.conflicts.join(", ")}`
9457
10341
  );
9458
- console.log(chalk23.dim(` Patch saved at: ${patchPath}`));
9459
- console.log(chalk23.dim(" Review the patch file and apply remaining changes manually."));
10342
+ console.log(chalk28.dim(` Patch saved at: ${patchPath}`));
10343
+ console.log(chalk28.dim(" Review the patch file and apply remaining changes manually."));
9460
10344
  }
9461
10345
  return { commitSha: result.commitSha };
9462
10346
  }
@@ -9473,27 +10357,43 @@ function registerUpdateCommand(program2) {
9473
10357
  return;
9474
10358
  }
9475
10359
  console.log(
9476
- chalk23.dim(name ? `Package "${name}" is not installed.` : "No packages installed.")
10360
+ chalk28.dim(name ? `Package "${name}" is not installed.` : "No packages installed.")
9477
10361
  );
9478
10362
  return;
9479
10363
  }
10364
+ const pinnedNames = [];
9480
10365
  const updatable = packageNames.filter((n) => {
9481
10366
  const pkg2 = packages[n];
9482
- return pkg2 && pkg2.source.type === "git" && pkg2.source.uri !== "unknown";
10367
+ if (!pkg2) return false;
10368
+ if (pkg2.pinned === true) {
10369
+ pinnedNames.push(n);
10370
+ return false;
10371
+ }
10372
+ return pkg2.source.type === "git" && pkg2.source.uri !== "unknown";
9483
10373
  });
10374
+ if (pinnedNames.length > 0 && !jsonMode) {
10375
+ for (const pinnedName of pinnedNames) {
10376
+ console.log(chalk28.dim(`Skipping ${pinnedName} (pinned)`));
10377
+ }
10378
+ }
9484
10379
  if (updatable.length === 0) {
9485
10380
  if (jsonMode) {
9486
10381
  outputSuccess({
9487
10382
  updated: [],
9488
- skipped: packageNames.map((n) => ({ name: n, reason: "No known Git source" }))
10383
+ skipped: [
10384
+ ...pinnedNames.map((n) => ({ name: n, reason: "pinned" })),
10385
+ ...packageNames.filter((n) => !pinnedNames.includes(n)).map((n) => ({ name: n, reason: "No known Git source" }))
10386
+ ]
9489
10387
  });
9490
10388
  return;
9491
10389
  }
9492
- console.log(
9493
- chalk23.dim(
9494
- "No packages with known Git sources. Reinstall packages using Git source URLs to enable updates."
9495
- )
9496
- );
10390
+ if (pinnedNames.length === 0) {
10391
+ console.log(
10392
+ chalk28.dim(
10393
+ "No packages with known Git sources. Reinstall packages using Git source URLs to enable updates."
10394
+ )
10395
+ );
10396
+ }
9497
10397
  return;
9498
10398
  }
9499
10399
  const spinner = createSpinner("Checking for upstream changes...").start();
@@ -9533,17 +10433,17 @@ function registerUpdateCommand(program2) {
9533
10433
  outputSuccess({ updated: [], skipped: [] });
9534
10434
  return;
9535
10435
  }
9536
- console.log(chalk23.green("All packages are up to date."));
10436
+ console.log(chalk28.green("All packages are up to date."));
9537
10437
  return;
9538
10438
  }
9539
10439
  if (!jsonMode) {
9540
- console.log(chalk23.bold(`
10440
+ console.log(chalk28.bold(`
9541
10441
  Upstream changes available (${updates.length}):
9542
10442
  `));
9543
10443
  for (const update of updates) {
9544
- const modifiedIndicator = update.locallyModified ? ` ${chalk23.yellow("\u26A0 locally modified")}` : "";
10444
+ const modifiedIndicator = update.locallyModified ? ` ${chalk28.yellow("\u26A0 locally modified")}` : "";
9545
10445
  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}`
10446
+ ` ${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
10447
  );
9548
10448
  }
9549
10449
  console.log();
@@ -9556,7 +10456,7 @@ Upstream changes available (${updates.length}):
9556
10456
  });
9557
10457
  return;
9558
10458
  }
9559
- console.log(`${chalk23.yellow("[dry-run]")} No changes made.`);
10459
+ console.log(`${chalk28.yellow("[dry-run]")} No changes made.`);
9560
10460
  return;
9561
10461
  }
9562
10462
  if (!jsonMode) {
@@ -9567,7 +10467,7 @@ Upstream changes available (${updates.length}):
9567
10467
  initial: true
9568
10468
  });
9569
10469
  if (!confirmed) {
9570
- console.log(chalk23.dim("Update cancelled."));
10470
+ console.log(chalk28.dim("Update cancelled."));
9571
10471
  return;
9572
10472
  }
9573
10473
  }
@@ -9633,7 +10533,7 @@ Upstream changes available (${updates.length}):
9633
10533
  }
9634
10534
  }
9635
10535
  const shortName = update.name.split("/").pop();
9636
- const skillDir = resolveReadPath(projectRoot, shortName, agents) ?? (agentId ? join20(
10536
+ const skillDir = resolveReadPath(projectRoot, shortName, agents) ?? (agentId ? join23(
9637
10537
  projectRoot,
9638
10538
  getSkillPlacementPath(agentId, shortName, "project") ?? ""
9639
10539
  ) : null);
@@ -9675,25 +10575,25 @@ Upstream changes available (${updates.length}):
9675
10575
  if (jsonMode) {
9676
10576
  outputSuccess({
9677
10577
  updated: jsonUpdated,
9678
- skipped: jsonSkipped
10578
+ skipped: [...pinnedNames.map((n) => ({ name: n, reason: "pinned" })), ...jsonSkipped]
9679
10579
  });
9680
10580
  return;
9681
10581
  }
9682
- console.log(chalk23.bold("\nUpdate summary:\n"));
10582
+ console.log(chalk28.bold("\nUpdate summary:\n"));
9683
10583
  for (const result of results) {
9684
- const patchNote = result.patched ? chalk23.dim(" (patch reapplied)") : "";
10584
+ const patchNote = result.patched ? chalk28.dim(" (patch reapplied)") : "";
9685
10585
  console.log(
9686
- ` ${chalk23.green("\u2713")} ${result.name}: ${chalk23.dim(result.from)} \u2192 ${chalk23.cyan(result.to)}${patchNote}`
10586
+ ` ${chalk28.green("\u2713")} ${result.name}: ${chalk28.dim(result.from)} \u2192 ${chalk28.cyan(result.to)}${patchNote}`
9687
10587
  );
9688
10588
  }
9689
10589
  for (const skippedName of skipped) {
9690
- console.log(` ${chalk23.dim("\u2013")} ${skippedName}: ${chalk23.dim("skipped")}`);
10590
+ console.log(` ${chalk28.dim("\u2013")} ${skippedName}: ${chalk28.dim("skipped")}`);
9691
10591
  }
9692
10592
  for (const failure of failures) {
9693
- console.log(` ${chalk23.red("\u2717")} ${failure.name}: ${failure.error}`);
10593
+ console.log(` ${chalk28.red("\u2717")} ${failure.name}: ${failure.error}`);
9694
10594
  }
9695
10595
  if (failures.length > 0) {
9696
- console.log(chalk23.dim("\nFailed packages were rolled back to their previous versions."));
10596
+ console.log(chalk28.dim("\nFailed packages were rolled back to their previous versions."));
9697
10597
  }
9698
10598
  console.log();
9699
10599
  } catch (error) {
@@ -9712,16 +10612,16 @@ Upstream changes available (${updates.length}):
9712
10612
  // src/commands/upgrade.ts
9713
10613
  import { execFile as execFile2 } from "child_process";
9714
10614
  import { createRequire } from "module";
9715
- import { dirname as dirname5, join as join21 } from "path";
10615
+ import { dirname as dirname6, join as join24 } from "path";
9716
10616
  import { fileURLToPath } from "url";
9717
10617
  import { promisify as promisify2 } from "util";
9718
- import chalk24 from "chalk";
10618
+ import chalk29 from "chalk";
9719
10619
  var execFileAsync2 = promisify2(execFile2);
9720
10620
  var PACKAGE_NAME = "@agentver/cli";
9721
10621
  function getCurrentVersion() {
9722
- const __dirname2 = dirname5(fileURLToPath(import.meta.url));
10622
+ const __dirname2 = dirname6(fileURLToPath(import.meta.url));
9723
10623
  const require3 = createRequire(import.meta.url);
9724
- const pkg2 = require3(join21(__dirname2, "..", "package.json"));
10624
+ const pkg2 = require3(join24(__dirname2, "..", "package.json"));
9725
10625
  return pkg2.version;
9726
10626
  }
9727
10627
  async function getLatestVersion() {
@@ -9777,11 +10677,11 @@ function registerUpgradeCommand(program2) {
9777
10677
  if (json) {
9778
10678
  outputSuccess({ current: currentVersion, latest: latestVersion, upToDate: true });
9779
10679
  } else {
9780
- spinner.succeed(`Already on the latest version ${chalk24.green(`v${currentVersion}`)}`);
10680
+ spinner.succeed(`Already on the latest version ${chalk29.green(`v${currentVersion}`)}`);
9781
10681
  }
9782
10682
  return;
9783
10683
  }
9784
- spinner.text = `Upgrading ${chalk24.dim(`v${currentVersion}`)} \u2192 ${chalk24.green(`v${latestVersion}`)}\u2026`;
10684
+ spinner.text = `Upgrading ${chalk29.dim(`v${currentVersion}`)} \u2192 ${chalk29.green(`v${latestVersion}`)}\u2026`;
9785
10685
  const pm = await detectPackageManager();
9786
10686
  const args = getInstallArgs(pm);
9787
10687
  await execFileAsync2(pm, args, { timeout: 6e4 });
@@ -9794,7 +10694,7 @@ function registerUpgradeCommand(program2) {
9794
10694
  outputSuccess(result);
9795
10695
  } else {
9796
10696
  spinner.succeed(
9797
- `Upgraded ${chalk24.green(`v${currentVersion}`)} \u2192 ${chalk24.green(`v${latestVersion}`)} via ${pm}`
10697
+ `Upgraded ${chalk29.green(`v${currentVersion}`)} \u2192 ${chalk29.green(`v${latestVersion}`)} via ${pm}`
9798
10698
  );
9799
10699
  }
9800
10700
  } catch (error) {
@@ -9811,7 +10711,7 @@ function registerUpgradeCommand(program2) {
9811
10711
  }
9812
10712
 
9813
10713
  // src/commands/verify.ts
9814
- import chalk25 from "chalk";
10714
+ import chalk30 from "chalk";
9815
10715
  var FALLBACK_SOURCE2 = {
9816
10716
  host: "github.com",
9817
10717
  owner: "local",
@@ -9878,8 +10778,8 @@ function registerVerifyCommand(program2) {
9878
10778
  outputError("NO_SKILL", "No skill name provided and no packages installed");
9879
10779
  return;
9880
10780
  }
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"));
10781
+ process.stderr.write(chalk30.red("No skill name provided and no packages installed.\n"));
10782
+ process.stderr.write(chalk30.dim("Usage: agentver verify @org/skill-name\n"));
9883
10783
  process.exitCode = 1;
9884
10784
  return;
9885
10785
  }
@@ -9894,10 +10794,10 @@ function registerVerifyCommand(program2) {
9894
10794
  return;
9895
10795
  }
9896
10796
  process.stderr.write(
9897
- chalk25.red("Multiple packages installed. Please specify which to verify:\n")
10797
+ chalk30.red("Multiple packages installed. Please specify which to verify:\n")
9898
10798
  );
9899
10799
  for (const pkg2 of packageNames) {
9900
- process.stderr.write(` ${chalk25.cyan(pkg2)}
10800
+ process.stderr.write(` ${chalk30.cyan(pkg2)}
9901
10801
  `);
9902
10802
  }
9903
10803
  process.exitCode = 1;
@@ -9914,7 +10814,7 @@ function registerVerifyCommand(program2) {
9914
10814
  return;
9915
10815
  }
9916
10816
  process.stderr.write(
9917
- chalk25.red(`Invalid skill name "${skillName}". Expected format: @org/skill-name
10817
+ chalk30.red(`Invalid skill name "${skillName}". Expected format: @org/skill-name
9918
10818
  `)
9919
10819
  );
9920
10820
  process.exitCode = 1;
@@ -9922,7 +10822,7 @@ function registerVerifyCommand(program2) {
9922
10822
  }
9923
10823
  if (!jsonMode) {
9924
10824
  process.stderr.write(`
9925
- ${chalk25.bold(`Verifying @${parsed.org}/${parsed.skill}...`)}
10825
+ ${chalk30.bold(`Verifying @${parsed.org}/${parsed.skill}...`)}
9926
10826
 
9927
10827
  `);
9928
10828
  }
@@ -10064,26 +10964,26 @@ ${chalk25.bold(`Verifying @${parsed.org}/${parsed.skill}...`)}
10064
10964
  }
10065
10965
  process.stderr.write("\n");
10066
10966
  if (overallPassed) {
10067
- process.stderr.write(chalk25.green.bold("Skill is verified and safe to use.\n"));
10967
+ process.stderr.write(chalk30.green.bold("Skill is verified and safe to use.\n"));
10068
10968
  } else {
10069
- process.stderr.write(chalk25.red.bold("Skill verification failed.\n"));
10969
+ process.stderr.write(chalk30.red.bold("Skill verification failed.\n"));
10070
10970
  process.exitCode = 1;
10071
10971
  }
10072
10972
  });
10073
10973
  }
10074
10974
 
10075
10975
  // 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";
10976
+ import { existsSync as existsSync20, readFileSync as readFileSync17 } from "fs";
10977
+ import { basename as basename6, join as join25 } from "path";
10978
+ import chalk31 from "chalk";
10079
10979
  import ora8 from "ora";
10080
10980
  var SEMVER_REGEX2 = /^\d+\.\d+\.\d+(-[\w.]+)?$/;
10081
10981
  function resolveSkillIdentity3() {
10082
10982
  const cwd = process.cwd();
10083
- const skillMdPath = join22(cwd, "SKILL.md");
10983
+ const skillMdPath = join25(cwd, "SKILL.md");
10084
10984
  let skillName = null;
10085
- if (existsSync18(skillMdPath)) {
10086
- const content = readFileSync14(skillMdPath, "utf-8");
10985
+ if (existsSync20(skillMdPath)) {
10986
+ const content = readFileSync17(skillMdPath, "utf-8");
10087
10987
  const nameMatch = content.match(/^name:\s*(.+)$/m);
10088
10988
  skillName = nameMatch?.[1]?.trim() ?? basename6(cwd);
10089
10989
  }
@@ -10111,7 +11011,7 @@ function registerVersionCommand(program2) {
10111
11011
  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
11012
  if (!SEMVER_REGEX2.test(semver)) {
10113
11013
  process.stderr.write(
10114
- chalk26.red(`Invalid semver "${semver}". Expected format: 1.0.0 or 1.0.0-beta.1
11014
+ chalk31.red(`Invalid semver "${semver}". Expected format: 1.0.0 or 1.0.0-beta.1
10115
11015
  `)
10116
11016
  );
10117
11017
  process.exit(1);
@@ -10119,7 +11019,7 @@ function registerVersionCommand(program2) {
10119
11019
  const identity = resolveSkillIdentity3();
10120
11020
  if (!identity) {
10121
11021
  process.stderr.write(
10122
- chalk26.red("Could not determine skill identity. Run this from a skill directory.\n")
11022
+ chalk31.red("Could not determine skill identity. Run this from a skill directory.\n")
10123
11023
  );
10124
11024
  process.exit(1);
10125
11025
  }
@@ -10127,7 +11027,7 @@ function registerVersionCommand(program2) {
10127
11027
  const lockEntry = lockfile.packages[identity.name];
10128
11028
  const commitSha = lockEntry?.source.type === "git" ? lockEntry.source.commit : void 0;
10129
11029
  if (!commitSha || commitSha === "unknown") {
10130
- process.stderr.write(chalk26.red("No commit SHA found in lockfile. Save changes first.\n"));
11030
+ process.stderr.write(chalk31.red("No commit SHA found in lockfile. Save changes first.\n"));
10131
11031
  process.exit(1);
10132
11032
  }
10133
11033
  const spinner = ora8(`Creating version ${semver}...`).start();
@@ -10159,7 +11059,7 @@ function registerVersionCommand(program2) {
10159
11059
  );
10160
11060
  } else {
10161
11061
  spinner.succeed(
10162
- `Version ${chalk26.cyan(semver)} created ${chalk26.dim(`(${result.commitSha.slice(0, 7)})`)}`
11062
+ `Version ${chalk31.cyan(semver)} created ${chalk31.dim(`(${result.commitSha.slice(0, 7)})`)}`
10163
11063
  );
10164
11064
  }
10165
11065
  } catch (error) {
@@ -10173,7 +11073,7 @@ function registerVersionCommand(program2) {
10173
11073
  const identity = resolveSkillIdentity3();
10174
11074
  if (!identity) {
10175
11075
  process.stderr.write(
10176
- chalk26.red("Could not determine skill identity. Run this from a skill directory.\n")
11076
+ chalk31.red("Could not determine skill identity. Run this from a skill directory.\n")
10177
11077
  );
10178
11078
  process.exit(1);
10179
11079
  }
@@ -10188,16 +11088,16 @@ function registerVersionCommand(program2) {
10188
11088
  return;
10189
11089
  }
10190
11090
  if (versions.length === 0) {
10191
- process.stdout.write(chalk26.dim("No versions found.\n"));
11091
+ process.stdout.write(chalk31.dim("No versions found.\n"));
10192
11092
  return;
10193
11093
  }
10194
- process.stdout.write(chalk26.bold(`
11094
+ process.stdout.write(chalk31.bold(`
10195
11095
  Versions for @${identity.org}/${identity.name}:
10196
11096
 
10197
11097
  `));
10198
11098
  for (const v of versions) {
10199
11099
  process.stdout.write(
10200
- ` ${chalk26.cyan(v.name)} ${chalk26.dim(`(${v.commitSha.slice(0, 7)})`)} ${chalk26.dim(v.message)}
11100
+ ` ${chalk31.cyan(v.name)} ${chalk31.dim(`(${v.commitSha.slice(0, 7)})`)} ${chalk31.dim(v.message)}
10201
11101
  `
10202
11102
  );
10203
11103
  }
@@ -10212,7 +11112,7 @@ Versions for @${identity.org}/${identity.name}:
10212
11112
  }
10213
11113
 
10214
11114
  // src/commands/whoami.ts
10215
- import chalk27 from "chalk";
11115
+ import chalk32 from "chalk";
10216
11116
  function registerWhoamiCommand(program2) {
10217
11117
  program2.command("whoami").description("Show authentication state").action(async () => {
10218
11118
  const credentials = await getCredentials();
@@ -10221,15 +11121,15 @@ function registerWhoamiCommand(program2) {
10221
11121
  outputSuccess({ authenticated: false });
10222
11122
  return;
10223
11123
  }
10224
- console.log(chalk27.dim("Not authenticated. Run `agentver login` to sign in."));
11124
+ console.log(chalk32.dim("Not authenticated. Run `agentver login` to sign in."));
10225
11125
  return;
10226
11126
  }
10227
11127
  if (!isJSONMode()) {
10228
11128
  if (credentials.apiKey) {
10229
11129
  const prefix = credentials.apiKey.slice(0, 8);
10230
- console.log(`Authenticated via API key: ${chalk27.green(`${prefix}...`)}`);
11130
+ console.log(`Authenticated via API key: ${chalk32.green(`${prefix}...`)}`);
10231
11131
  } else {
10232
- console.log(chalk27.green("Authenticated via OAuth."));
11132
+ console.log(chalk32.green("Authenticated via OAuth."));
10233
11133
  }
10234
11134
  }
10235
11135
  const platformUrl = getPlatformUrl();
@@ -10238,11 +11138,11 @@ function registerWhoamiCommand(program2) {
10238
11138
  outputSuccess({ authenticated: true });
10239
11139
  return;
10240
11140
  }
10241
- console.log(chalk27.dim("Platform: not connected (run `agentver login <url>` to connect)"));
11141
+ console.log(chalk32.dim("Platform: not connected (run `agentver login <url>` to connect)"));
10242
11142
  return;
10243
11143
  }
10244
11144
  if (!isJSONMode()) {
10245
- console.log(`Platform: ${chalk27.cyan(platformUrl)}`);
11145
+ console.log(`Platform: ${chalk32.cyan(platformUrl)}`);
10246
11146
  }
10247
11147
  const me = await platformFetchSilent("/me");
10248
11148
  if (isJSONMode()) {
@@ -10269,38 +11169,44 @@ function registerWhoamiCommand(program2) {
10269
11169
  }
10270
11170
 
10271
11171
  // bin/agentver.ts
10272
- var __dirname = dirname6(fileURLToPath2(import.meta.url));
11172
+ var __dirname = dirname7(fileURLToPath2(import.meta.url));
10273
11173
  var require2 = createRequire2(import.meta.url);
10274
- var pkg = require2(join23(__dirname, "..", "package.json"));
11174
+ var pkg = require2(join26(__dirname, "..", "package.json"));
10275
11175
  updateNotifier({ pkg }).notify({
10276
11176
  message: `Update available: {currentVersion} \u2192 {latestVersion}
10277
- Run ${chalk28.cyan("agentver upgrade")} to update`
11177
+ Run ${chalk33.cyan("agentver upgrade")} to update`
10278
11178
  });
10279
11179
  var program = new Command();
10280
11180
  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
11181
  registerAdoptCommand(program);
10282
- registerInstallCommand(program);
10283
11182
  registerAuditCommand(program);
11183
+ registerCompletionCommand(program);
11184
+ registerConfigCommand(program);
11185
+ registerDiffCommand(program);
11186
+ registerDoctorCommand(program);
11187
+ registerDraftCommand(program);
11188
+ registerInfoCommand(program);
11189
+ registerInitCommand(program);
11190
+ registerInstallCommand(program);
11191
+ registerListCommand(program);
11192
+ registerLogCommand(program);
10284
11193
  registerLoginCommand(program);
10285
11194
  registerLogoutCommand(program);
10286
- registerListCommand(program);
10287
- registerSearchCommand(program);
10288
- registerUpdateCommand(program);
11195
+ registerPinCommand(program);
11196
+ registerPublishCommand(program);
10289
11197
  registerRemoveCommand(program);
10290
- registerInitCommand(program);
11198
+ registerSaveCommand(program);
10291
11199
  registerScanCommand(program);
10292
- registerWhoamiCommand(program);
11200
+ registerSearchCommand(program);
10293
11201
  registerStatusCommand(program);
10294
- registerDiffCommand(program);
10295
- registerSyncCommand(program);
10296
11202
  registerSuggestCommand(program);
10297
11203
  registerSuggestionsCommand(program);
10298
- registerSaveCommand(program);
10299
- registerPublishCommand(program);
10300
- registerDraftCommand(program);
11204
+ registerSyncCommand(program);
11205
+ registerUnpinCommand(program);
11206
+ registerUpdateCommand(program);
10301
11207
  registerUpgradeCommand(program);
10302
11208
  registerVerifyCommand(program);
10303
11209
  registerVersionCommand(program);
10304
- registerLogCommand(program);
11210
+ registerWhoamiCommand(program);
10305
11211
  program.parse();
10306
11212
  //# sourceMappingURL=agentver.js.map