@kevlns/v-cli 0.2.0-beta.1 → 0.2.0-beta.2

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/AGENTS.md CHANGED
@@ -7,10 +7,12 @@
7
7
 
8
8
  ## 核心约定(v-cli 本体)
9
9
 
10
- - 环境要求 Node.js >= 20;v-cli 版本 @kevlns/v-cli@0.2.0-beta.1
10
+ - 环境要求 Node.js >= 20;v-cli 版本 @kevlns/v-cli@0.2.0-beta.2
11
11
  - 命令分三类:builtin(内置)、local(~/.v-cli/commands/ 下的本地插件)、official(官方插件白名单);
12
12
  **最新、live 的命令集合以实际发现为准**:先运行 `v-cli agent index --json` 获取全部命令与 agent 元数据
13
13
  - 单个命令的完整元数据用 `v-cli agent describe <命令名> --json` 查看
14
+ - AI Agent 引导文档:`v-cli agent docs` 输出本文件原文(`--json` 含 sha256/content);
15
+ `v-cli agent init .` 把它写入工作区(已存在默认拒绝,`--force` 覆盖,`--dry-run` 预览;符号链接目标 fail-closed)
14
16
  - 官方插件命令(`v-cli xlmerge …`、`v-cli unity …`)在子进程中运行(stdio 继承):v-cli 只做路由,
15
17
  不解析、不改写插件的 stdout/stderr;插件 `--help`/`--json` 等参数由插件自己消费
16
18
  - 插件对 worktree 的写入/提交行为以插件清单 v-cli.plugin.json 的 `agent.safety` 为准:
package/README.md CHANGED
@@ -26,7 +26,7 @@ v-cli 让你**用一个命令沉淀所有个人小工具**,而不用为每个
26
26
  - **官方插件白名单** - `@kevlns/xlmerge`(`xlmerge`)与 `@kevlns/u-cli-mod`(`unity`)是唯一被路由的官方插件,安装后在子进程中运行
27
27
  - **容错加载** - 单个插件语法错误、契约不符或注册异常只会被跳过并报告,绝不阻断其他命令
28
28
  - **双通道输出** - 结果走 stdout(可管道、可脚本化),诊断走 stderr
29
- - **agent 友好** - `agent index/describe` 输出统一索引与完整元数据;仓库内 AGENTS.md 自动生成并有漂移检查
29
+ - **agent 友好** - `agent docs`/`agent init` 让 AI Agent 自举读取引导文档;`agent index/describe` 输出统一索引与完整元数据;仓库内 AGENTS.md 自动生成并有漂移检查
30
30
  - **TypeScript-first** - 严格类型编写,tsup 将核心逻辑打包为单文件 ESM,仅保留 `commander` 运行依赖
31
31
 
32
32
  ## Getting started
@@ -51,10 +51,33 @@ npm install -g git+https://github.com/kevlns/v-cli.git
51
51
  v-cli doctor # 环境体检:node/版本、主目录、配置、官方/本地插件状态
52
52
  v-cli plugin list # 列出内置命令、本地插件与官方插件状态
53
53
  v-cli ts 1710000000 # 时间戳互转
54
+ v-cli agent docs # 输出当前安装包内置 AGENTS.md 原文(AI Agent 引导文档)
54
55
  v-cli agent index # 命令 + agent 元数据索引(--json 输出机器可读)
55
56
  v-cli agent describe xlmerge --json
57
+ v-cli agent init . # (可选)把 AGENTS.md 初始化到当前目录
56
58
  ```
57
59
 
60
+ ### AI Agent 快速开始
61
+
62
+ v-cli 内置 AGENTS.md 随包发布,AI Agent 可自行发现并读取引导文档,无需人工粘贴:
63
+
64
+ ```bash
65
+ v-cli agent docs # 读当前包内置 AGENTS.md 原文(--json 拿 package/version/sha256/content)
66
+ v-cli agent index --json # 枚举全部命令 + 元数据(builtin/local/official,live 发现)
67
+ v-cli agent describe <name> --json # 单命令:用法/参数/选项/输出/退出码/安全标签
68
+ v-cli agent init . # (可选)把 AGENTS.md 写入工作区,AI Agent 自动读取
69
+ ```
70
+
71
+ `agent docs` 文本模式逐字节输出内置 AGENTS.md,`--json` 输出稳定对象
72
+ `{ package, version, sha256, content }`。
73
+
74
+ `agent init [directory]`(默认当前目录;目录必须已存在且为目录):
75
+
76
+ - 已存在 AGENTS.md 时**默认拒绝并退出 1,绝不改动现有文件**(`--force` 才原子覆盖);
77
+ - `--dry-run` 只报告目标与将执行的动作,不写入任何文件;
78
+ - 符号链接目标一律 fail-closed 拒绝(不跟随、不覆盖链接目标);
79
+ - `--json` 输出稳定结果(`ok/dryRun/action/directory/target/sha256/bytes/…`)。
80
+
58
81
  ### 控制器命令(官方插件)
59
82
 
60
83
  ```bash
@@ -106,7 +129,7 @@ v-cli --json ts 1710000000 | jq .seconds # 前置全局 --json 同样生效
106
129
  ## `--json` 语义(v-cli 0.2)
107
130
 
108
131
  - **前置全局**:`v-cli --json <cmd> …` —— `--json` 出现在首个命令词之前时被 v-cli 消费,`ctx.json` 为真
109
- - **命令自有**:`<cmd> --json …` —— 属于该命令:内置命令(`ts`、`doctor`、`plugin list`、`agent index`、`agent describe`)各自声明 `--json` 并消费;官方插件命令则**原样转发**给插件
132
+ - **命令自有**:`<cmd> --json …` —— 属于该命令:内置命令(`ts`、`doctor`、`plugin list`、`agent index`、`agent describe`、`agent docs`、`agent init`)各自声明 `--json` 并消费;官方插件命令则**原样转发**给插件
110
133
  - 其他中间位置(如 `v-cli plugin --json list`)不承诺 JSON 输出
111
134
  - 插件转发示例:`v-cli xlmerge detect --json` 会把 `--json` 转给 xlmerge;`v-cli --json xlmerge detect` 则消费掉全局 `--json`、只转发 `detect`
112
135
 
@@ -122,6 +145,8 @@ v-cli --json ts 1710000000 | jq .seconds # 前置全局 --json 同样生效
122
145
  | `v-cli ts [value]` | 无参=当前时间;数字(秒/毫秒自动识别)=转可读时间;日期串=转时间戳 |
123
146
  | `v-cli agent index [--json]` | 全部命令的 agent 索引(builtin/local/official,含元数据状态) |
124
147
  | `v-cli agent describe <name> [--json]` | 单个命令的完整记录;未找到时 stderr 报错并退出 1 |
148
+ | `v-cli agent docs [--json]` | 输出当前包内置 AGENTS.md 原文;`--json` 输出 `{ package, version, sha256, content }`;缺失时退出 1 |
149
+ | `v-cli agent init [directory] [--force] [--dry-run] [--json]` | 把内置 AGENTS.md 写入目录(默认 cwd);已存在默认拒绝退出 1,`--force` 原子覆盖,`--dry-run` 只报告 |
125
150
 
126
151
  ### 插件契约 `CliCommand`(apiVersion 1)
127
152
 
@@ -191,7 +216,7 @@ kevlns 工具家族共享同一套发布约定(tag 驱动、CI 护栏、MIT)
191
216
 
192
217
  | Package | Purpose | Status |
193
218
  | --- | --- | --- |
194
- | [`v-cli`](https://github.com/kevlns/v-cli) | 个人工具箱 CLI(本仓库) | v0.2.0-beta.1 |
219
+ | [`v-cli`](https://github.com/kevlns/v-cli) | 个人工具箱 CLI(本仓库) | v0.2.0-beta.2 |
195
220
  | [`xlmerge`](https://github.com/kevlns/xlmerge) | Git 中 .xlsx/.xlsm 冲突可视化解决工具 | v1.2.1-beta.2 |
196
221
  | [`u-cli-mod`](https://github.com/kevlns/u-cli-mod) | Unity 精确版本路由 + CLI + pipeline 包(Windows-first) | v0.1.0-beta.2 |
197
222
 
package/dist/cli.mjs CHANGED
@@ -75,8 +75,8 @@ function defaultHomeDir() {
75
75
  }
76
76
 
77
77
  // src/core/loader.ts
78
- import fs4 from "fs";
79
- import path5 from "path";
78
+ import fs5 from "fs";
79
+ import path7 from "path";
80
80
  import { pathToFileURL } from "url";
81
81
 
82
82
  // src/core/official.ts
@@ -554,6 +554,27 @@ function validateAgentMeta(agent2, errors) {
554
554
  if (c.usage !== void 0 && typeof c.usage !== "string") {
555
555
  errors.push(`${at}.usage \u5FC5\u987B\u662F\u5B57\u7B26\u4E32`);
556
556
  }
557
+ if (c.arguments !== void 0) {
558
+ const bad = !Array.isArray(c.arguments) || c.arguments.some(
559
+ (a) => !isPlainObject3(a) || typeof a.name !== "string" || typeof a.required !== "boolean" || typeof a.description !== "string"
560
+ );
561
+ if (bad) errors.push(`${at}.arguments \u5FC5\u987B\u662F { name: string; required: boolean; description: string }[]`);
562
+ }
563
+ if (c.options !== void 0) {
564
+ const bad = !Array.isArray(c.options) || c.options.some((o) => !isPlainObject3(o) || typeof o.flags !== "string" || typeof o.description !== "string");
565
+ if (bad) errors.push(`${at}.options \u5FC5\u987B\u662F { flags: string; description: string }[]`);
566
+ }
567
+ if (c.output !== void 0) {
568
+ const bad = !isPlainObject3(c.output) || typeof c.output.format !== "string" || typeof c.output.description !== "string";
569
+ if (bad) errors.push(`${at}.output \u5FC5\u987B\u662F { format: string; description: string }`);
570
+ }
571
+ if (c.exitCodes !== void 0) {
572
+ const bad = !isPlainObject3(c.exitCodes) || Object.entries(c.exitCodes).some(([code, desc]) => typeof code !== "string" || typeof desc !== "string");
573
+ if (bad) errors.push(`${at}.exitCodes \u5FC5\u987B\u662F { [\u9000\u51FA\u7801: string]: string }`);
574
+ }
575
+ if (c.safety !== void 0 && !isStringArray2(c.safety)) {
576
+ errors.push(`${at}.safety \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u6570\u7EC4`);
577
+ }
557
578
  });
558
579
  }
559
580
  }
@@ -596,6 +617,193 @@ function validateLocalCommand(candidate, options = {}) {
596
617
  return { ok: true, command: candidate, errors: [] };
597
618
  }
598
619
 
620
+ // src/commands/agent.ts
621
+ import path5 from "path";
622
+
623
+ // src/core/agent-docs.ts
624
+ import fs3 from "fs";
625
+ import path4 from "path";
626
+ import { createHash, randomBytes } from "crypto";
627
+ import { fileURLToPath as fileURLToPath2 } from "url";
628
+
629
+ // src/version.ts
630
+ var VERSION = "0.2.0-beta.2";
631
+
632
+ // src/core/agent-docs.ts
633
+ var BUNDLED_DOCS_FILE = "AGENTS.md";
634
+ var BUNDLED_DOCS_PACKAGE = "@kevlns/v-cli";
635
+ function bundledCandidatePaths(moduleFile) {
636
+ const candidates = [];
637
+ const push = (p) => {
638
+ if (!candidates.includes(p)) candidates.push(p);
639
+ };
640
+ if (path4.basename(path4.dirname(moduleFile)) === "dist") {
641
+ push(path4.join(path4.dirname(path4.dirname(moduleFile)), BUNDLED_DOCS_FILE));
642
+ }
643
+ let dir = path4.dirname(moduleFile);
644
+ for (; ; ) {
645
+ if (pkgName(path4.join(dir, "package.json")) === BUNDLED_DOCS_PACKAGE) {
646
+ push(path4.join(dir, BUNDLED_DOCS_FILE));
647
+ break;
648
+ }
649
+ const nestedPkg = path4.join(dir, "node_modules", "@kevlns", "v-cli", "package.json");
650
+ if (pkgName(nestedPkg) === BUNDLED_DOCS_PACKAGE) {
651
+ push(path4.join(dir, "node_modules", "@kevlns", "v-cli", BUNDLED_DOCS_FILE));
652
+ break;
653
+ }
654
+ const parent = path4.dirname(dir);
655
+ if (parent === dir) break;
656
+ dir = parent;
657
+ }
658
+ return candidates;
659
+ }
660
+ function pkgName(pkgJsonPath) {
661
+ try {
662
+ const pkg = JSON.parse(fs3.readFileSync(pkgJsonPath, "utf-8"));
663
+ return typeof pkg.name === "string" ? pkg.name : void 0;
664
+ } catch {
665
+ return void 0;
666
+ }
667
+ }
668
+ function resolveBundledAgentsMd(opts = {}) {
669
+ const moduleFile = opts.base ?? fileURLToPath2(import.meta.url);
670
+ for (const candidate of bundledCandidatePaths(moduleFile)) {
671
+ try {
672
+ if (fs3.lstatSync(candidate).isFile()) return candidate;
673
+ } catch {
674
+ }
675
+ }
676
+ return void 0;
677
+ }
678
+ function readBundledAgentsMd(opts = {}) {
679
+ const file = resolveBundledAgentsMd(opts);
680
+ if (!file) {
681
+ const tried = bundledCandidatePaths(opts.base ?? fileURLToPath2(import.meta.url));
682
+ const lastTried = tried.length > 0 ? tried[tried.length - 1] : "\uFF08\u65E0\u5019\u9009\u4F4D\u7F6E\uFF09";
683
+ throw new Error(
684
+ `\u65E0\u6CD5\u5B9A\u4F4D ${BUNDLED_DOCS_PACKAGE} \u5185\u7F6E ${BUNDLED_DOCS_FILE}\uFF1A\u5DF2\u68C0\u67E5 ${tried.length} \u4E2A\u5019\u9009\u4F4D\u7F6E\u5747\u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u8BFB\uFF08\u6700\u540E\u68C0\u67E5: ${lastTried}\uFF09\u3002\u8BF7\u786E\u8BA4\u5B89\u88C5\u7684\u5305\u5185\u5305\u542B AGENTS.md\uFF08\u91CD\u65B0\u5B89\u88C5 @kevlns/v-cli \u540E\u91CD\u8BD5\uFF09\u3002`
685
+ );
686
+ }
687
+ let content;
688
+ try {
689
+ content = fs3.readFileSync(file, "utf-8");
690
+ } catch (err) {
691
+ throw new Error(
692
+ `\u65E0\u6CD5\u8BFB\u53D6 ${BUNDLED_DOCS_PACKAGE} \u5185\u7F6E ${BUNDLED_DOCS_FILE}\uFF08${file}\uFF09: ${err instanceof Error ? err.message : String(err)}`
693
+ );
694
+ }
695
+ return {
696
+ file,
697
+ content,
698
+ sha256: sha256Hex(content),
699
+ bytes: Buffer.byteLength(content, "utf-8")
700
+ };
701
+ }
702
+ function sha256Hex(content) {
703
+ return createHash("sha256").update(content, "utf-8").digest("hex");
704
+ }
705
+ function performAgentInit(opts) {
706
+ const { directory, docs, force = false, dryRun = false, explicitDirectory = false } = opts;
707
+ const target = path4.join(directory, BUNDLED_DOCS_FILE);
708
+ const base = {
709
+ ok: false,
710
+ dryRun,
711
+ action: "refused",
712
+ directory,
713
+ target,
714
+ package: BUNDLED_DOCS_PACKAGE,
715
+ version: VERSION,
716
+ sha256: docs.sha256,
717
+ bytes: docs.bytes
718
+ };
719
+ const refuse = (reason) => ({ ...base, ok: false, action: "refused", reason });
720
+ let dirStat;
721
+ try {
722
+ dirStat = fs3.statSync(directory);
723
+ } catch {
724
+ return refuse(`\u76EE\u6807\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u8BBF\u95EE: ${directory}`);
725
+ }
726
+ if (!dirStat.isDirectory()) {
727
+ return refuse(`\u76EE\u6807\u4E0D\u662F\u76EE\u5F55: ${directory}`);
728
+ }
729
+ if (explicitDirectory) {
730
+ let dirLstat;
731
+ try {
732
+ dirLstat = fs3.lstatSync(directory);
733
+ } catch {
734
+ }
735
+ if (dirLstat && dirLstat.isSymbolicLink()) {
736
+ return refuse(
737
+ `\u62D2\u7EDD\u5199\u5165\uFF1A\u76EE\u6807\u76EE\u5F55 ${directory} \u662F\u7B26\u53F7\u94FE\u63A5/\u8054\u63A5\u76EE\u5F55\uFF08fail-closed\uFF0C\u4E0D\u8DDF\u968F\uFF09\u3002\u8BF7\u4F20\u5165\u771F\u5B9E\u76EE\u5F55\u8DEF\u5F84\uFF0C\u6216\u7701\u7565\u53C2\u6570\u8BA9 v-cli \u4F7F\u7528\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55`
738
+ );
739
+ }
740
+ }
741
+ let targetStat;
742
+ try {
743
+ targetStat = fs3.lstatSync(target);
744
+ } catch {
745
+ targetStat = void 0;
746
+ }
747
+ if (targetStat) {
748
+ if (targetStat.isSymbolicLink()) {
749
+ return refuse(
750
+ `\u62D2\u7EDD\u5199\u5165 ${target}\uFF1A\u76EE\u6807\u662F\u7B26\u53F7\u94FE\u63A5\uFF08fail-closed\uFF0C\u4E0D\u8DDF\u968F\u3001\u4E0D\u8986\u76D6\u94FE\u63A5\u76EE\u6807\uFF09\u3002\u8BF7\u5148\u79FB\u9664\u94FE\u63A5\u6216\u9009\u62E9\u5176\u4ED6\u76EE\u5F55`
751
+ );
752
+ }
753
+ if (targetStat.isDirectory()) {
754
+ return refuse(`\u62D2\u7EDD\u5199\u5165 ${target}\uFF1A\u76EE\u6807\u662F\u4E00\u4E2A\u76EE\u5F55\uFF08\u65E0\u6CD5\u4EE5\u6587\u4EF6\u8986\u76D6\uFF09`);
755
+ }
756
+ if (!force) {
757
+ return refuse(
758
+ `${target} \u5DF2\u5B58\u5728\uFF0C\u9ED8\u8BA4\u62D2\u7EDD\u8986\u76D6\uFF08\u4E0D\u505A\u4EFB\u4F55\u6539\u52A8\uFF09\u3002\u5982\u9700\u8986\u76D6\u8BF7\u4F7F\u7528 --force\uFF1B\u5982\u9700\u9884\u89C8\u8BF7\u4F7F\u7528 --dry-run\uFF1B\u5982\u9700\u5148\u67E5\u770B\u5185\u5BB9\u8BF7\u8FD0\u884C v-cli agent docs`
759
+ );
760
+ }
761
+ }
762
+ const existed = targetStat !== void 0;
763
+ const action = existed ? dryRun ? "overwrite" : "overwritten" : dryRun ? "write" : "written";
764
+ if (dryRun) {
765
+ return { ...base, ok: true, action };
766
+ }
767
+ try {
768
+ atomicWrite(target, docs.content);
769
+ } catch (err) {
770
+ return refuse(`\u5199\u5165\u5931\u8D25 ${target}: ${err instanceof Error ? err.message : String(err)}`);
771
+ }
772
+ return { ...base, ok: true, action };
773
+ }
774
+ function isEexist(err) {
775
+ return typeof err === "object" && err !== null && err.code === "EEXIST";
776
+ }
777
+ var MAX_TMP_RETRIES = 5;
778
+ function atomicWrite(target, content) {
779
+ let lastError;
780
+ for (let attempt = 0; attempt < MAX_TMP_RETRIES; attempt++) {
781
+ const tmp = path4.join(
782
+ path4.dirname(target),
783
+ `.${BUNDLED_DOCS_FILE}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`
784
+ );
785
+ let created = false;
786
+ try {
787
+ fs3.writeFileSync(tmp, content, { encoding: "utf-8", flag: "wx", mode: 420 });
788
+ created = true;
789
+ fs3.renameSync(tmp, target);
790
+ return;
791
+ } catch (err) {
792
+ lastError = err;
793
+ if (created) {
794
+ try {
795
+ fs3.rmSync(tmp, { force: true });
796
+ } catch {
797
+ }
798
+ }
799
+ if (isEexist(err)) continue;
800
+ throw err;
801
+ }
802
+ }
803
+ const detail = lastError instanceof Error ? lastError.message : String(lastError ?? "\u672A\u77E5\u9519\u8BEF");
804
+ throw new Error(`\u539F\u5B50\u5199\u5165\u5931\u8D25\uFF08\u4E34\u65F6\u6587\u4EF6\u547D\u540D\u78B0\u649E\u91CD\u8BD5 ${MAX_TMP_RETRIES} \u6B21\u672A\u679C\uFF09: ${detail}`);
805
+ }
806
+
599
807
  // src/commands/agent.ts
600
808
  function buildAgentIndex(builtin, local, official) {
601
809
  const rows = [];
@@ -659,10 +867,153 @@ function rowToText(row) {
659
867
  const meta = row.metadataStatus === "full" ? "\u5B8C\u6574\u5143\u6570\u636E" : "\u6700\u5C0F\u5143\u6570\u636E";
660
868
  return `[${row.type}] ${row.name}${status}: ${row.description} (${meta})`;
661
869
  }
870
+ function describeCommandLine(c) {
871
+ const pathText = Array.isArray(c.path) ? c.path.join(" ") : "";
872
+ const argText = Array.isArray(c.arguments) && c.arguments.length > 0 ? ` \u53C2\u6570: ${c.arguments.map((a) => `${a.required ? `<${a.name}>` : `[${a.name}]`}`).join(", ")}` : "";
873
+ const optText = Array.isArray(c.options) && c.options.length > 0 ? ` \u9009\u9879: ${c.options.map((o) => o.flags).join(", ")}` : "";
874
+ const outputText = c.output && typeof c.output === "object" && typeof c.output.format === "string" ? ` \u8F93\u51FA: ${c.output.format}${c.output.description ? `\uFF08${c.output.description}\uFF09` : ""}` : "";
875
+ const exitText = c.exitCodes && typeof c.exitCodes === "object" && Object.keys(c.exitCodes).length > 0 ? ` \u9000\u51FA\u7801: ${Object.entries(c.exitCodes).map(([code, desc]) => `${code}=${desc}`).join(", ")}` : "";
876
+ const safeText = Array.isArray(c.safety) && c.safety.length > 0 ? ` \u5B89\u5168: ${c.safety.join("\uFF1B")}` : "";
877
+ return ` ${pathText} \u2014 ${c.description}${c.usage ? ` (\u7528\u6CD5: ${c.usage})` : ""}${argText}${optText}${outputText}${exitText}${safeText}`;
878
+ }
879
+ var AGENT_HELP_TEXT = [
880
+ "agent \u5B50\u547D\u4EE4\u4E00\u89C8\uFF1A",
881
+ " index \u5217\u51FA\u5168\u90E8\u547D\u4EE4\uFF08builtin/local/official\uFF09\u4E0E agent \u5143\u6570\u636E\uFF1B--json \u8F93\u51FA\u7A33\u5B9A JSON \u6570\u7EC4",
882
+ " describe \u67E5\u770B\u5355\u4E2A\u547D\u4EE4\u7684\u5B8C\u6574\u8BB0\u5F55\uFF08\u7528\u6CD5/\u53C2\u6570/\u9009\u9879/\u8F93\u51FA/\u9000\u51FA\u7801/\u5B89\u5168\u6807\u7B7E\uFF09\uFF1B--json \u8F93\u51FA\u5355\u6761\u8BB0\u5F55",
883
+ " docs \u8F93\u51FA\u5F53\u524D @kevlns/v-cli \u5305\u5185\u7F6E AGENTS.md \u539F\u6587\uFF1B--json \u8F93\u51FA { package, version, sha256, content }",
884
+ " init \u628A\u5185\u7F6E AGENTS.md \u5199\u5165\u5DE5\u4F5C\u533A\uFF08\u9ED8\u8BA4\u5F53\u524D\u76EE\u5F55\uFF09\uFF1B\u5DF2\u5B58\u5728\u9ED8\u8BA4\u62D2\u7EDD\uFF0C--force \u8986\u76D6\uFF0C--dry-run \u9884\u89C8",
885
+ "",
886
+ "JSON\uFF1A\u6240\u6709\u5B50\u547D\u4EE4\u652F\u6301 --json\uFF08\u6216\u524D\u7F6E\u5168\u5C40 --json\uFF0C\u5982 v-cli --json agent index\uFF09",
887
+ "",
888
+ "AI Agent \u5FEB\u901F\u5F00\u59CB\uFF08\u63A8\u8350\u987A\u5E8F\uFF09\uFF1A",
889
+ " 1. v-cli agent docs",
890
+ " 2. v-cli agent index --json",
891
+ " 3. v-cli agent describe <name> --json",
892
+ " 4. v-cli agent init . \uFF08\u53EF\u9009\uFF1A\u5199\u5165\u5DE5\u4F5C\u533A AGENTS.md\uFF0CAI Agent \u81EA\u52A8\u8BFB\u53D6\uFF09",
893
+ "",
894
+ "\u793A\u4F8B\uFF1A",
895
+ " v-cli agent index --json # \u5168\u91CF\u547D\u4EE4\u7D22\u5F15",
896
+ " v-cli agent describe ts --json # \u5355\u547D\u4EE4\u8BE6\u60C5",
897
+ " v-cli agent docs # \u5185\u7F6E\u5F15\u5BFC\u6587\u6863\u539F\u6587",
898
+ " v-cli agent init . --dry-run # \u9884\u89C8\u521D\u59CB\u5316\u76EE\u6807"
899
+ ].join("\n");
900
+ var DOCS_HELP_TEXT = [
901
+ "\u8F93\u51FA\u5F53\u524D\u5B89\u88C5\u7684 @kevlns/v-cli \u5305\u5185\u7F6E AGENTS.md \u539F\u6587\uFF08AI Agent \u5F15\u5BFC\u6587\u6863\uFF09\uFF0C\u9010\u5B57\u8282\u539F\u6837\u8F93\u51FA\u3001\u4E0D\u8FFD\u52A0\u6362\u884C\u3002",
902
+ "",
903
+ "JSON \u884C\u4E3A\uFF08--json \u6216\u524D\u7F6E\u5168\u5C40 --json\uFF09\uFF1A",
904
+ " \u6210\u529F\uFF1Astdout \u8F93\u51FA\u7A33\u5B9A\u5BF9\u8C61 { package, version, sha256, content }",
905
+ " package \u5305\u540D @kevlns/v-cli",
906
+ " version \u5F53\u524D\u5305\u7248\u672C",
907
+ " sha256 content \u7684 SHA-256\uFF08hex\uFF09\uFF0C\u53EF\u6821\u9A8C\u5F15\u5BFC\u6587\u6863\u672A\u88AB\u7BE1\u6539",
908
+ " content AGENTS.md \u539F\u6587",
909
+ " \u5931\u8D25\uFF1Astdout \u8F93\u51FA\u7A00\u758F\u5BF9\u8C61 { ok: false, error }\uFF0Cstderr \u518D\u8F93\u51FA\u540C\u4E00 error\uFF0C\u9000\u51FA\u7801 1",
910
+ "",
911
+ "\u9000\u51FA\u7801\uFF1A0 \u6210\u529F\uFF1B1 \u5185\u7F6E AGENTS.md \u7F3A\u5931/\u4E0D\u53EF\u8BFB",
912
+ "",
913
+ "\u793A\u4F8B\uFF1A",
914
+ " v-cli agent docs",
915
+ " v-cli agent docs --json"
916
+ ].join("\n");
917
+ var INIT_HELP_TEXT = [
918
+ "\u628A\u5F53\u524D @kevlns/v-cli \u5305\u5185\u7F6E AGENTS.md \u539F\u6837\u5199\u5165 <\u76EE\u5F55>/AGENTS.md\uFF0CAI Agent \u4F1A\u81EA\u52A8\u8BFB\u53D6\u5DE5\u4F5C\u533A\u6587\u6863\u3002",
919
+ "",
920
+ "\u53C2\u6570\uFF1A",
921
+ " [directory] \u76EE\u6807\u76EE\u5F55\uFF0C\u9ED8\u8BA4\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\uFF1B\u5FC5\u987B\u5DF2\u5B58\u5728\u4E14\u4E3A\u76EE\u5F55",
922
+ "",
923
+ "\u9ED8\u8BA4\u884C\u4E3A\uFF08\u65E0 --force\uFF09\uFF1A\u76EE\u6807\u5DF2\u5B58\u5728 AGENTS.md \u65F6\u62D2\u7EDD\u5E76\u9000\u51FA 1\uFF0C\u7EDD\u4E0D\u6539\u52A8\u73B0\u6709\u6587\u4EF6\u3002",
924
+ " --force \u8986\u76D6\u5DF2\u5B58\u5728\u7684 AGENTS.md\uFF08\u539F\u5B50\u5199\u5165\uFF1A\u540C\u76EE\u5F55\u4E34\u65F6\u6587\u4EF6 + rename\uFF09",
925
+ " --dry-run \u53EA\u62A5\u544A\u76EE\u6807\u4E0E\u5C06\u6267\u884C\u7684\u52A8\u4F5C\uFF0C\u4E0D\u5199\u5165\u4EFB\u4F55\u6587\u4EF6",
926
+ " --json \u6210\u529F/\u5E72\u8DD1\u8F93\u51FA\u7A33\u5B9A JSON { ok, dryRun, action, directory, target, package, version, sha256, bytes }\uFF1B",
927
+ ' \u62D2\u7EDD\uFF08\u5982\u5DF2\u5B58\u5728\u672A\u52A0 --force\uFF09\u8F93\u51FA { ok: false, action: "refused", reason, \u2026 } \u4E14\u9000\u51FA 1\uFF1B',
928
+ " \u5185\u7F6E\u6587\u6863\u7F3A\u5931\u65F6\u8F93\u51FA\u7A00\u758F { ok: false, error } \u4E14\u9000\u51FA 1",
929
+ " \u7B26\u53F7\u94FE\u63A5\u89C4\u5219\uFF1A\u76EE\u6807 AGENTS.md \u662F\u7B26\u53F7\u94FE\u63A5\u4E00\u5F8B\u62D2\u7EDD\uFF08fail-closed\uFF1A\u4E0D\u8DDF\u968F\u3001\u4E0D\u8986\u76D6\u94FE\u63A5\u76EE\u6807\uFF09\uFF1B",
930
+ " \u663E\u5F0F\u4F20\u5165\u7684\u76EE\u5F55\u672C\u8EAB\u662F\u7B26\u53F7\u94FE\u63A5/\u8054\u63A5\u76EE\u5F55\uFF08junction\uFF09\u4E5F\u62D2\u7EDD\uFF1B\u7701\u7565\u76EE\u5F55\u53C2\u6570\uFF08\u9ED8\u8BA4\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\uFF09\u4E0D\u53D7\u6B64\u9650\u5236",
931
+ "",
932
+ "\u9000\u51FA\u7801\uFF1A0 \u6210\u529F\u6216\u5E72\u8DD1\uFF1B1 \u76EE\u5F55\u65E0\u6548 / \u5DF2\u5B58\u5728\u672A\u52A0 --force / \u7B26\u53F7\u94FE\u63A5\u6216\u8054\u63A5\u76EE\u6807 / \u5185\u7F6E\u6587\u6863\u7F3A\u5931 / \u5199\u5165\u5931\u8D25",
933
+ "",
934
+ "\u793A\u4F8B\uFF1A",
935
+ " v-cli agent init",
936
+ " v-cli agent init ./myproj",
937
+ " v-cli agent init --dry-run",
938
+ " v-cli agent init --force",
939
+ " v-cli agent init --json"
940
+ ].join("\n");
662
941
  var agent = {
663
942
  name: "agent",
664
- description: "agent \u7D22\u5F15\uFF1Aindex \u5217\u51FA\u5168\u90E8\u547D\u4EE4\u53CA\u5143\u6570\u636E\uFF0Cdescribe \u67E5\u770B\u5355\u4E2A\u547D\u4EE4\u8BE6\u60C5",
943
+ description: "agent\uFF1Aindex \u547D\u4EE4\u7D22\u5F15\uFF0Cdescribe \u8BE6\u60C5\uFF0Cdocs \u5185\u7F6E AGENTS.md\uFF0Cinit \u5DE5\u4F5C\u533A\u5F15\u5BFC",
665
944
  apiVersion: 1,
945
+ agent: {
946
+ whenToUse: "\u5F53\u7528\u6237\u9700\u8981 AGENTS \u5F15\u5BFC\u6587\u6863\u3001\u547D\u4EE4\u53D1\u73B0\u6216\u4E3A AI Agent \u521D\u59CB\u5316\u5DE5\u4F5C\u533A\u65F6\uFF1A\u5148 `docs` \u8BFB\u5185\u7F6E AGENTS.md\uFF0C\u518D `index --json` \u679A\u4E3E\u5168\u90E8\u547D\u4EE4\u4E0E\u5143\u6570\u636E\uFF0C\u7528 `describe <name> --json` \u770B\u5355\u547D\u4EE4\u8BE6\u60C5\uFF0C\u6700\u540E\u53EF `init` \u628A AGENTS.md \u5199\u5165\u5DE5\u4F5C\u533A",
947
+ globalOptions: [
948
+ { flags: "-h, --help", description: "\u663E\u793A\u547D\u4EE4\u5E2E\u52A9" }
949
+ ],
950
+ commands: [
951
+ {
952
+ path: ["index"],
953
+ usage: "v-cli agent index [--json]",
954
+ description: "\u5217\u51FA\u5168\u90E8\u547D\u4EE4\uFF08builtin/local/official\uFF09\u4E0E agent \u5143\u6570\u636E",
955
+ arguments: [],
956
+ options: [{ flags: "--json", description: "\u8F93\u51FA\u673A\u5668\u53EF\u8BFB JSON" }],
957
+ output: {
958
+ format: "stdout",
959
+ description: "\u6B63\u6587\u8F93\u51FA\u5230 stdout\uFF1B--json \u65F6\u8F93\u51FA\u7A33\u5B9A JSON \u6570\u7EC4\uFF08name/type/description/metadataStatus/commands/\u2026\uFF09"
960
+ },
961
+ exitCodes: { "0": "\u6210\u529F" },
962
+ safety: ["read-only", "no-network"]
963
+ },
964
+ {
965
+ path: ["describe"],
966
+ usage: "v-cli agent describe <name> [--json]",
967
+ description: "\u67E5\u770B\u5355\u4E2A\u547D\u4EE4\u7684\u5B8C\u6574\u8BB0\u5F55",
968
+ arguments: [{ name: "name", required: true, description: "\u547D\u4EE4\u540D\uFF08builtin/local/official\uFF09" }],
969
+ options: [{ flags: "--json", description: "\u8F93\u51FA\u673A\u5668\u53EF\u8BFB JSON" }],
970
+ output: { format: "stdout", description: "\u6B63\u6587\u8F93\u51FA\u5230 stdout\uFF1B--json \u65F6\u8F93\u51FA\u5355\u6761\u7A33\u5B9A JSON \u5BF9\u8C61" },
971
+ exitCodes: { "0": "\u6210\u529F", "1": "\u672A\u627E\u5230\u547D\u4EE4\uFF08stderr \u8BF4\u660E\uFF09" },
972
+ safety: ["read-only"]
973
+ },
974
+ {
975
+ path: ["docs"],
976
+ usage: "v-cli agent docs [--json]",
977
+ description: "\u8F93\u51FA\u5F53\u524D @kevlns/v-cli \u5305\u5185\u7F6E AGENTS.md \u539F\u6587",
978
+ arguments: [],
979
+ options: [{ flags: "--json", description: "\u8F93\u51FA { package, version, sha256, content }" }],
980
+ output: {
981
+ format: "stdout",
982
+ description: "AGENTS.md \u539F\u6587\u9010\u5B57\u8282\u8F93\u51FA\u5230 stdout\uFF1B--json \u65F6\u8F93\u51FA\u542B sha256/content \u7684\u7A33\u5B9A JSON"
983
+ },
984
+ exitCodes: { "0": "\u6210\u529F", "1": "\u5185\u7F6E AGENTS.md \u7F3A\u5931/\u4E0D\u53EF\u8BFB" },
985
+ safety: ["read-only", "no-network"]
986
+ },
987
+ {
988
+ path: ["init"],
989
+ usage: "v-cli agent init [directory] [--force] [--dry-run] [--json]",
990
+ description: "\u628A\u5185\u7F6E AGENTS.md \u5199\u5165 <\u76EE\u5F55>/AGENTS.md\uFF1B\u9ED8\u8BA4\u5F53\u524D\u76EE\u5F55\uFF1B\u5DF2\u5B58\u5728\u9ED8\u8BA4\u62D2\u7EDD",
991
+ arguments: [
992
+ { name: "directory", required: false, description: "\u76EE\u6807\u76EE\u5F55\uFF08\u9ED8\u8BA4\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\uFF1B\u987B\u5DF2\u5B58\u5728\u4E14\u4E3A\u76EE\u5F55\uFF09" }
993
+ ],
994
+ options: [
995
+ { flags: "--force", description: "\u8986\u76D6\u5DF2\u5B58\u5728 AGENTS.md\uFF08\u539F\u5B50\u5199\u5165\uFF09" },
996
+ { flags: "--dry-run", description: "\u53EA\u62A5\u544A\u76EE\u6807\u4E0E\u52A8\u4F5C\uFF0C\u4E0D\u5199\u5165" },
997
+ { flags: "--json", description: "\u8F93\u51FA\u673A\u5668\u53EF\u8BFB\u7ED3\u679C" }
998
+ ],
999
+ output: {
1000
+ format: "stdout",
1001
+ description: "\u7ED3\u679C\u6587\u672C\u8F93\u51FA\u5230 stdout\uFF1B--json \u65F6\u8F93\u51FA\u7A33\u5B9A JSON\uFF08ok/dryRun/action/directory/target/package/version/sha256/bytes\uFF09"
1002
+ },
1003
+ exitCodes: {
1004
+ "0": "\u6210\u529F\u6216\u5E72\u8DD1",
1005
+ "1": "\u76EE\u5F55\u65E0\u6548 / \u5DF2\u5B58\u5728\u672A\u8986\u76D6 / \u7B26\u53F7\u94FE\u63A5\u6216\u8054\u63A5\u76EE\u6807 / \u6587\u6863\u7F3A\u5931 / \u5199\u5165\u5931\u8D25"
1006
+ },
1007
+ safety: [
1008
+ "writes-target-atomic",
1009
+ "refuses-existing",
1010
+ "fail-closed-symlink",
1011
+ "dry-run-supported",
1012
+ "no-commit"
1013
+ ]
1014
+ }
1015
+ ]
1016
+ },
666
1017
  register(program, ctx) {
667
1018
  program.command("index").description("\u5217\u51FA\u5168\u90E8\u547D\u4EE4\uFF08builtin/local/official\uFF09\u4E0E agent \u5143\u6570\u636E").option("--json", "\u8F93\u51FA\u673A\u5668\u53EF\u8BFB JSON").action(async (opts) => {
668
1019
  const json = ctx.json || opts.json;
@@ -704,27 +1055,82 @@ var agent = {
704
1055
  }
705
1056
  if (row.commands && row.commands.length > 0) {
706
1057
  lines.push("\u5B50\u547D\u4EE4:");
707
- for (const c of row.commands) {
708
- const pathText = Array.isArray(c.path) ? c.path.join(" ") : "";
709
- const optText = Array.isArray(c.options) && c.options.length > 0 ? ` \u9009\u9879: ${c.options.map((o) => o.flags).join(", ")}` : "";
710
- const safeText = Array.isArray(c.safety) && c.safety.length > 0 ? ` \u5B89\u5168: ${c.safety.join("\uFF1B")}` : "";
711
- lines.push(
712
- ` ${pathText} \u2014 ${c.description}${c.usage ? ` (\u7528\u6CD5: ${c.usage})` : ""}${optText}${safeText}`
713
- );
714
- }
1058
+ for (const c of row.commands) lines.push(describeCommandLine(c));
715
1059
  }
716
1060
  ctx.log.result(lines.join("\n"));
717
1061
  });
1062
+ program.command("docs").description("\u8F93\u51FA\u5F53\u524D @kevlns/v-cli \u5305\u5185\u7F6E AGENTS.md \u539F\u6587\uFF08AI Agent \u5F15\u5BFC\u6587\u6863\uFF09").option("--json", "\u8F93\u51FA\u673A\u5668\u53EF\u8BFB JSON\uFF08\u542B sha256/content\uFF09").addHelpText("after", DOCS_HELP_TEXT).action((opts) => {
1063
+ const json = ctx.json || opts.json;
1064
+ let docs;
1065
+ try {
1066
+ docs = readBundledAgentsMd();
1067
+ } catch (err) {
1068
+ const message = err instanceof Error ? err.message : String(err);
1069
+ if (json) ctx.log.result({ ok: false, error: message });
1070
+ ctx.log.error(message);
1071
+ process.exitCode = 1;
1072
+ return;
1073
+ }
1074
+ if (json) {
1075
+ ctx.log.result({
1076
+ package: BUNDLED_DOCS_PACKAGE,
1077
+ version: VERSION,
1078
+ sha256: docs.sha256,
1079
+ content: docs.content
1080
+ });
1081
+ return;
1082
+ }
1083
+ process.stdout.write(docs.content);
1084
+ });
1085
+ program.command("init").description("\u521D\u59CB\u5316 <\u76EE\u5F55>/AGENTS.md\uFF08\u9ED8\u8BA4\u5F53\u524D\u76EE\u5F55\uFF09\uFF1B\u5DF2\u5B58\u5728\u9ED8\u8BA4\u62D2\u7EDD\uFF0C--force \u8986\u76D6\uFF0C--dry-run \u9884\u89C8").argument("[directory]", "\u76EE\u6807\u76EE\u5F55\uFF08\u9ED8\u8BA4\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\uFF1B\u5FC5\u987B\u5DF2\u5B58\u5728\u4E14\u4E3A\u76EE\u5F55\uFF09").option("--force", "\u8986\u76D6\u5DF2\u5B58\u5728\u7684 AGENTS.md\uFF08\u539F\u5B50\u5199\u5165\uFF09").option("--dry-run", "\u53EA\u62A5\u544A\u76EE\u6807\u4E0E\u52A8\u4F5C\uFF0C\u4E0D\u5199\u5165\u4EFB\u4F55\u6587\u4EF6").option("--json", "\u8F93\u51FA\u673A\u5668\u53EF\u8BFB\u7ED3\u679C").addHelpText("after", INIT_HELP_TEXT).action(
1086
+ (directory, opts) => {
1087
+ const json = ctx.json || opts.json;
1088
+ let docs;
1089
+ try {
1090
+ docs = readBundledAgentsMd();
1091
+ } catch (err) {
1092
+ const message = err instanceof Error ? err.message : String(err);
1093
+ if (json) ctx.log.result({ ok: false, error: message });
1094
+ ctx.log.error(message);
1095
+ process.exitCode = 1;
1096
+ return;
1097
+ }
1098
+ const result = performAgentInit({
1099
+ directory: path5.resolve(directory ?? process.cwd()),
1100
+ docs,
1101
+ force: opts.force,
1102
+ dryRun: opts.dryRun,
1103
+ // 显式传入目录才做目录符号链接/联接 fail-closed;默认 cwd 不受限
1104
+ explicitDirectory: directory !== void 0
1105
+ });
1106
+ if (json) {
1107
+ ctx.log.result(result);
1108
+ if (!result.ok && result.reason) ctx.log.error(result.reason);
1109
+ if (!result.ok) process.exitCode = 1;
1110
+ return;
1111
+ }
1112
+ if (!result.ok) {
1113
+ if (result.reason) ctx.log.error(result.reason);
1114
+ process.exitCode = 1;
1115
+ return;
1116
+ }
1117
+ if (result.dryRun) {
1118
+ ctx.log.result(
1119
+ `[dry-run] \u5C06${result.action === "overwrite" ? "\u8986\u76D6" : "\u5199\u5165"} ${result.target}\uFF08${result.bytes} \u5B57\u8282\uFF09`
1120
+ );
1121
+ } else {
1122
+ ctx.log.result(
1123
+ `\u5DF2${result.action === "overwritten" ? "\u8986\u76D6" : "\u5199\u5165"} ${result.target}\uFF08${result.bytes} \u5B57\u8282\uFF0CSHA-256 ${result.sha256.slice(0, 12)}\u2026\uFF09`
1124
+ );
1125
+ }
1126
+ }
1127
+ );
1128
+ program.addHelpText("after", AGENT_HELP_TEXT);
718
1129
  }
719
1130
  };
720
1131
 
721
1132
  // src/commands/doctor.ts
722
- import fs3 from "fs";
723
-
724
- // src/version.ts
725
- var VERSION = "0.2.0-beta.1";
726
-
727
- // src/commands/doctor.ts
1133
+ import fs4 from "fs";
728
1134
  var doctor = {
729
1135
  name: "doctor",
730
1136
  description: "\u4F53\u68C0\uFF1Anode/v-cli \u7248\u672C\u3001homeDir\u3001config\u3001\u63D2\u4EF6\u72B6\u6001",
@@ -733,7 +1139,7 @@ var doctor = {
733
1139
  program.option("--json", "\u8F93\u51FA\u673A\u5668\u53EF\u8BFB JSON").action(async (opts) => {
734
1140
  const json = ctx.json || opts.json;
735
1141
  const homeDir = ctx.homeDir;
736
- const exists = fs3.existsSync(homeDir);
1142
+ const exists = fs4.existsSync(homeDir);
737
1143
  let configWritable = false;
738
1144
  try {
739
1145
  ctx.config.set((cfg) => cfg);
@@ -787,7 +1193,7 @@ var doctor = {
787
1193
  };
788
1194
 
789
1195
  // src/commands/plugin.ts
790
- import path4 from "path";
1196
+ import path6 from "path";
791
1197
  var plugin = {
792
1198
  name: "plugin",
793
1199
  description: "\u63D2\u4EF6\u7BA1\u7406\uFF1Alist \u5217\u51FA\u547D\u4EE4\uFF0Cpath \u663E\u793A\u672C\u5730\u63D2\u4EF6\u76EE\u5F55",
@@ -826,7 +1232,7 @@ var plugin = {
826
1232
  }
827
1233
  });
828
1234
  program.command("path").description("\u6253\u5370\u672C\u5730\u63D2\u4EF6\u76EE\u5F55\uFF08\u653E\u5165 .mjs \u6587\u4EF6\u5373\u751F\u6548\uFF09").option("--json", "\u8F93\u51FA\u673A\u5668\u53EF\u8BFB JSON").action((opts) => {
829
- const dir = path4.join(ctx.homeDir, "commands");
1235
+ const dir = path6.join(ctx.homeDir, "commands");
830
1236
  if (ctx.json || opts.json) {
831
1237
  ctx.log.result({ dir });
832
1238
  } else {
@@ -894,12 +1300,12 @@ async function loadBuiltinCommands() {
894
1300
  return builtinCommands.map((command) => ({ command, source: "builtin" }));
895
1301
  }
896
1302
  async function loadLocalPlugins(ctx) {
897
- const dir = path5.join(ctx.homeDir, "commands");
1303
+ const dir = path7.join(ctx.homeDir, "commands");
898
1304
  const loaded = [];
899
- if (!fs4.existsSync(dir)) return loaded;
900
- const files = fs4.readdirSync(dir).filter((f) => f.endsWith(".mjs")).sort();
1305
+ if (!fs5.existsSync(dir)) return loaded;
1306
+ const files = fs5.readdirSync(dir).filter((f) => f.endsWith(".mjs")).sort();
901
1307
  for (const file of files) {
902
- const abs = path5.join(dir, file);
1308
+ const abs = path7.join(dir, file);
903
1309
  try {
904
1310
  const mod = await import(
905
1311
  /* @vite-ignore */
@@ -1041,6 +1447,18 @@ async function main() {
1041
1447
  if (intercepted !== void 0) return intercepted;
1042
1448
  const program = new Command();
1043
1449
  program.name("v-cli").description("kevlns \u7684\u4E2A\u4EBA\u5DE5\u5177\u7BB1").version(VERSION).showHelpAfterError();
1450
+ program.addHelpText(
1451
+ "after",
1452
+ [
1453
+ "AI Agent \u5FEB\u901F\u5F00\u59CB\uFF08\u63A8\u8350\u987A\u5E8F\uFF09\uFF1A",
1454
+ " 1. v-cli agent docs",
1455
+ " 2. v-cli agent index --json",
1456
+ " 3. v-cli agent describe <name> --json",
1457
+ " 4. v-cli agent init . \uFF08\u53EF\u9009\uFF1A\u5199\u5165\u5DE5\u4F5C\u533A AGENTS.md\uFF0CAI Agent \u81EA\u52A8\u8BFB\u53D6\uFF09",
1458
+ "",
1459
+ "\u8BE6\u60C5\u89C1 `v-cli agent --help`\uFF1B\u5355\u547D\u4EE4\u8BF4\u660E\u4E66\uFF1A`v-cli agent docs --help` / `v-cli agent init --help`\u3002"
1460
+ ].join("\n")
1461
+ );
1044
1462
  const loaded = await loadAllCommands(ctx);
1045
1463
  for (const item of loaded) {
1046
1464
  if (!item.command) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kevlns/v-cli",
3
- "version": "0.2.0-beta.1",
3
+ "version": "0.2.0-beta.2",
4
4
  "description": "kevlns 的个人工具箱 CLI(插件化架构,内置 + 本地插件)+ doctor/plugin/ts 命令",
5
5
  "type": "module",
6
6
  "bin": {