@foxian/esl 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/LICENSE +21 -0
  2. package/dist/api-error.d.ts +13 -0
  3. package/dist/api-error.js +31 -0
  4. package/dist/bin/esl.d.ts +35 -0
  5. package/dist/bin/esl.js +1033 -0
  6. package/dist/builtin/builtin-packages.json +11 -0
  7. package/dist/builtin/esl-operator/SKILL.md +65 -0
  8. package/dist/builtin/esl-operator/references/agent-interaction.md +110 -0
  9. package/dist/builtin/esl-operator/references/author.md +98 -0
  10. package/dist/builtin/esl-operator/references/consumer.md +109 -0
  11. package/dist/builtin/esl-operator/references/setup.md +41 -0
  12. package/dist/builtin/esl-operator/skill.json +7 -0
  13. package/dist/builtin-dir.d.ts +1 -0
  14. package/dist/builtin-dir.js +11 -0
  15. package/dist/commands/adapt.d.ts +8 -0
  16. package/dist/commands/adapt.js +27 -0
  17. package/dist/commands/admin.d.ts +11 -0
  18. package/dist/commands/admin.js +96 -0
  19. package/dist/commands/clone.d.ts +10 -0
  20. package/dist/commands/clone.js +21 -0
  21. package/dist/commands/config.d.ts +8 -0
  22. package/dist/commands/config.js +19 -0
  23. package/dist/commands/delete.d.ts +13 -0
  24. package/dist/commands/delete.js +51 -0
  25. package/dist/commands/deprecate.d.ts +16 -0
  26. package/dist/commands/deprecate.js +29 -0
  27. package/dist/commands/import.d.ts +14 -0
  28. package/dist/commands/import.js +21 -0
  29. package/dist/commands/info.d.ts +28 -0
  30. package/dist/commands/info.js +69 -0
  31. package/dist/commands/init.d.ts +28 -0
  32. package/dist/commands/init.js +252 -0
  33. package/dist/commands/install.d.ts +17 -0
  34. package/dist/commands/install.js +435 -0
  35. package/dist/commands/link.d.ts +11 -0
  36. package/dist/commands/link.js +170 -0
  37. package/dist/commands/list.d.ts +6 -0
  38. package/dist/commands/list.js +7 -0
  39. package/dist/commands/login.d.ts +20 -0
  40. package/dist/commands/login.js +132 -0
  41. package/dist/commands/logout.d.ts +6 -0
  42. package/dist/commands/logout.js +18 -0
  43. package/dist/commands/network-options.d.ts +27 -0
  44. package/dist/commands/network-options.js +133 -0
  45. package/dist/commands/notes.d.ts +10 -0
  46. package/dist/commands/notes.js +24 -0
  47. package/dist/commands/publish.d.ts +19 -0
  48. package/dist/commands/publish.js +271 -0
  49. package/dist/commands/release-delete.d.ts +21 -0
  50. package/dist/commands/release-delete.js +34 -0
  51. package/dist/commands/release-manifest.d.ts +5 -0
  52. package/dist/commands/release-manifest.js +23 -0
  53. package/dist/commands/rename.d.ts +5 -0
  54. package/dist/commands/rename.js +25 -0
  55. package/dist/commands/repair-tag.d.ts +5 -0
  56. package/dist/commands/repair-tag.js +14 -0
  57. package/dist/commands/reset-source.d.ts +16 -0
  58. package/dist/commands/reset-source.js +71 -0
  59. package/dist/commands/resolve-unlink-identity.d.ts +14 -0
  60. package/dist/commands/resolve-unlink-identity.js +47 -0
  61. package/dist/commands/search.d.ts +19 -0
  62. package/dist/commands/search.js +33 -0
  63. package/dist/commands/share.d.ts +17 -0
  64. package/dist/commands/share.js +56 -0
  65. package/dist/commands/source.d.ts +10 -0
  66. package/dist/commands/source.js +34 -0
  67. package/dist/commands/status.d.ts +16 -0
  68. package/dist/commands/status.js +77 -0
  69. package/dist/commands/sync-builtin.d.ts +10 -0
  70. package/dist/commands/sync-builtin.js +68 -0
  71. package/dist/commands/tools.d.ts +19 -0
  72. package/dist/commands/tools.js +73 -0
  73. package/dist/commands/uninstall.d.ts +19 -0
  74. package/dist/commands/uninstall.js +75 -0
  75. package/dist/commands/unlink.d.ts +14 -0
  76. package/dist/commands/unlink.js +108 -0
  77. package/dist/commands/update.d.ts +18 -0
  78. package/dist/commands/update.js +176 -0
  79. package/dist/commands/upload.d.ts +27 -0
  80. package/dist/commands/upload.js +446 -0
  81. package/dist/commands/use.d.ts +9 -0
  82. package/dist/commands/use.js +51 -0
  83. package/dist/commands/validate.d.ts +4 -0
  84. package/dist/commands/validate.js +8 -0
  85. package/dist/commands/version.d.ts +16 -0
  86. package/dist/commands/version.js +147 -0
  87. package/dist/commands/whoami.d.ts +14 -0
  88. package/dist/commands/whoami.js +54 -0
  89. package/dist/index.d.ts +24 -0
  90. package/dist/index.js +24 -0
  91. package/dist/output.d.ts +1 -0
  92. package/dist/output.js +3 -0
  93. package/dist/postinstall.d.ts +1 -0
  94. package/dist/postinstall.js +8 -0
  95. package/dist/prompt.d.ts +9 -0
  96. package/dist/prompt.js +24 -0
  97. package/dist/vendor/core/adapt/adapt-engine.d.ts +24 -0
  98. package/dist/vendor/core/adapt/adapt-engine.js +99 -0
  99. package/dist/vendor/core/adapt/adapted-skill-copy.d.ts +2 -0
  100. package/dist/vendor/core/adapt/adapted-skill-copy.js +17 -0
  101. package/dist/vendor/core/adapt/claude-adapter.d.ts +8 -0
  102. package/dist/vendor/core/adapt/claude-adapter.js +19 -0
  103. package/dist/vendor/core/adapt/codex-adapter.d.ts +8 -0
  104. package/dist/vendor/core/adapt/codex-adapter.js +19 -0
  105. package/dist/vendor/core/adapt/index.d.ts +2 -0
  106. package/dist/vendor/core/adapt/index.js +2 -0
  107. package/dist/vendor/core/adapt/tool-adapter.d.ts +12 -0
  108. package/dist/vendor/core/adapt/tool-adapter.js +1 -0
  109. package/dist/vendor/core/adapt/trae-adapter.d.ts +8 -0
  110. package/dist/vendor/core/adapt/trae-adapter.js +19 -0
  111. package/dist/vendor/core/adapt/trae-cn-adapter.d.ts +8 -0
  112. package/dist/vendor/core/adapt/trae-cn-adapter.js +19 -0
  113. package/dist/vendor/core/agent-interaction.d.ts +58 -0
  114. package/dist/vendor/core/agent-interaction.js +58 -0
  115. package/dist/vendor/core/command-params.d.ts +5 -0
  116. package/dist/vendor/core/command-params.js +46 -0
  117. package/dist/vendor/core/index.d.ts +22 -0
  118. package/dist/vendor/core/index.js +22 -0
  119. package/dist/vendor/core/link/skill-links.d.ts +38 -0
  120. package/dist/vendor/core/link/skill-links.js +245 -0
  121. package/dist/vendor/core/link/tool-links.d.ts +83 -0
  122. package/dist/vendor/core/link/tool-links.js +376 -0
  123. package/dist/vendor/core/org/account-policy.d.ts +8 -0
  124. package/dist/vendor/core/org/account-policy.js +57 -0
  125. package/dist/vendor/core/org/org-name.d.ts +2 -0
  126. package/dist/vendor/core/org/org-name.js +22 -0
  127. package/dist/vendor/core/org/standing-teams.d.ts +10 -0
  128. package/dist/vendor/core/org/standing-teams.js +27 -0
  129. package/dist/vendor/core/schema/compatibility.d.ts +17 -0
  130. package/dist/vendor/core/schema/compatibility.js +45 -0
  131. package/dist/vendor/core/schema/release-manifest.d.ts +88 -0
  132. package/dist/vendor/core/schema/release-manifest.js +161 -0
  133. package/dist/vendor/core/schema/skill-json.d.ts +61 -0
  134. package/dist/vendor/core/schema/skill-json.js +47 -0
  135. package/dist/vendor/core/schema/validation-result.d.ts +7 -0
  136. package/dist/vendor/core/schema/validation-result.js +1 -0
  137. package/dist/vendor/core/skill/builtin-package.d.ts +32 -0
  138. package/dist/vendor/core/skill/builtin-package.js +143 -0
  139. package/dist/vendor/core/skill/directory-validator.d.ts +9 -0
  140. package/dist/vendor/core/skill/directory-validator.js +72 -0
  141. package/dist/vendor/core/skill/import-skill.d.ts +10 -0
  142. package/dist/vendor/core/skill/import-skill.js +68 -0
  143. package/dist/vendor/core/skill/published-package.d.ts +1 -0
  144. package/dist/vendor/core/skill/published-package.js +9 -0
  145. package/dist/vendor/core/skill/skill-md.d.ts +15 -0
  146. package/dist/vendor/core/skill/skill-md.js +32 -0
  147. package/dist/vendor/core/store/file-copy.d.ts +3 -0
  148. package/dist/vendor/core/store/file-copy.js +102 -0
  149. package/dist/vendor/core/store/local-store.d.ts +43 -0
  150. package/dist/vendor/core/store/local-store.js +104 -0
  151. package/dist/vendor/core/store/skill-store.d.ts +24 -0
  152. package/dist/vendor/core/store/skill-store.js +41 -0
  153. package/dist/vendor/core/store/skills-json.d.ts +34 -0
  154. package/dist/vendor/core/store/skills-json.js +146 -0
  155. package/dist/vendor/core/version/select-version.d.ts +16 -0
  156. package/dist/vendor/core/version/select-version.js +34 -0
  157. package/dist/vendor/core/version/version.d.ts +2 -0
  158. package/dist/vendor/core/version/version.js +25 -0
  159. package/dist/vendor/i18n/api-errors.d.ts +121 -0
  160. package/dist/vendor/i18n/api-errors.js +240 -0
  161. package/dist/vendor/i18n/i18n-runtime.d.ts +4 -0
  162. package/dist/vendor/i18n/i18n-runtime.js +16 -0
  163. package/dist/vendor/i18n/index.d.ts +5 -0
  164. package/dist/vendor/i18n/index.js +5 -0
  165. package/dist/vendor/i18n/locales.d.ts +9 -0
  166. package/dist/vendor/i18n/locales.js +33 -0
  167. package/dist/vendor/i18n/resources.d.ts +11 -0
  168. package/dist/vendor/i18n/resources.js +925 -0
  169. package/dist/vendor/i18n/translate-api-error.d.ts +8 -0
  170. package/dist/vendor/i18n/translate-api-error.js +12 -0
  171. package/dist/version.d.ts +1 -0
  172. package/dist/version.js +24 -0
  173. package/package.json +46 -0
@@ -0,0 +1,11 @@
1
+ {
2
+ "version": 1,
3
+ "packages": {
4
+ "@builtin/esl-operator": {
5
+ "name": "@builtin/esl-operator",
6
+ "version": "0.1.0",
7
+ "checksum": "sha256-72250c753955bf263be47e19f3651c626fb1609e66c9574530a1f36703e6ff09",
8
+ "shortName": "esl-operator"
9
+ }
10
+ }
11
+ }
@@ -0,0 +1,65 @@
1
+ ---
2
+ name: esl-operator
3
+ description: >
4
+ Operate the Enterprise Skill Library (ESL) CLI from natural language. Search, try, install, list, update, uninstall, link shared skills into AI tools, or link a local skill source into the Skill Store (Claude Code, Codex, Cursor, Trae, WorkBuddy, opencode, OpenClaw, Hermes); inspect or remove tool links; create, validate, version, publish, or clone the source of skills. Use whenever the user wants to find or use a shared skill, install/update skills (project or global), inspect which tools have which skills, author or publish a skill, pull someone's skill source for edits, or otherwise drive the `esl` command — even when they never say "esl". Routes login and server setup but never types passwords.
5
+ ---
6
+
7
+ # esl operator
8
+
9
+ ESL 是企业技能注册平台;`esl` 是它的 CLI。本技能让你(AI)听懂用户的自然语言意图后,用 bash 真跑 `esl` 命令——不重新实现 CLI 逻辑,只做"意图 → 命令 → 分级执行"的翻译。用户说"搜个 code-review 技能""把我写的技能发出去",你就知道跑哪条命令。
10
+
11
+ ## 怎么用这个技能
12
+
13
+ 先按下表把用户意图路由到对应 reference,再读那个文件拿到命令清单与旗标。只读命令可直接执行;写命令先回显完整命令、等用户确认再跑。
14
+
15
+ | 用户说了类似这些 | 读 |
16
+ |---|---|
17
+ | 登录 / 登出 / 换服务器 / 我是谁 / token 过期 / 没登录 | `references/setup.md` |
18
+ | 搜、找、有没有 X 技能 / 试用 / 装、安装 / link 本地源码、开发模式 / 列出已装 / 更新、升级 / 卸载 / unlink 源码 / 看哪些工具装了哪些技能 / 解除部分工具 link / 同步到工具 | `references/consumer.md` |
19
+ | 建、创建、初始化技能 / 校验 / 上传源码 / 发布 / 改版本号 / 拉别人源码、二次开发 | `references/author.md` |
20
+ | 执行已接入协议的写命令 / 看到 `questions` 交互负载 | `references/agent-interaction.md` |
21
+ | 仍含糊 | 问一个澄清问题(例:「从服务器装现成的,还是自己从零创建?」) |
22
+
23
+ **Agent Interaction 默认开启。** 本技能由 AI 执行 `esl init`,或执行不带版本参数的 `esl version` 时,命令一律追加
24
+ `--agent-interaction` 与 `--agent-tool <tool>`(按当前宿主传工具标识,如
25
+ Claude Code 传 `claude-code`、Codex 传 `codex`、Trae 国际版传 `trae-intl`、
26
+ Trae 国内版传 `trae-cn`;旧值 `claude` 仍兼容),并同时读取
27
+ `references/agent-interaction.md`。不要等用户明确要求选择框或输入框。
28
+
29
+ ## 三条不可妥协的规则
30
+
31
+ **1. 读写分级执行。** 这是核心安全契约。只读、非变更的命令——`search` `info` `use` `list/ls` `tools list` `whoami` `validate`——直接跑,跑完把结果给用户;其中 `search` 由 AI 调用时必须加 `--json`,避免进入人类专用 TTY 会话。会改状态或写盘的命令——`install` `link` `unlink` `update` `uninstall` `adapt` `tools remove` `init` `upload` `publish` `deprecate` `notes` `release-delete` `share` `version` `source` `reset-source` `login` `logout` `config set-server`——先把你**将要执行**的完整命令(含旗标)回显给用户,等用户明确同意后再跑。被拒绝就停,不要降级、不要换条路偷偷跑。
32
+
33
+ 为什么:`install` 会把远端内容拉进项目、`publish` 把东西推到全公司共享的服务器、`uninstall` 删东西——这些不可逆或会被别人看到,用户应当先看清要跑什么。只读命令无成本,直接跑才省事。
34
+
35
+ **2. 登录不碰密码。** ESL 的认证靠 `esl login` 拿 token。如果你跑 `esl whoami` 看到 `Not logged in`,或某条命令报 401/认证失败:把用户引到 `references/setup.md`。交互式 `esl login` 会提示输入密码——这步让用户自己跑,你不要替它键入密码。只有当用户已备好凭据文件时,你才可以执行 `esl login --username X --token-file ./f` 或 `--password-file ./f`。绝不在命令行里写明文密码或 token。状态不明就先跑 `esl whoami`。
36
+
37
+ 为什么:密码一旦被你经手(写进命令、落进会话历史或日志),泄露面就放大;让用户在自己终端输入,凭据只存在他本机的只读文件里。
38
+
39
+ **3. 身份语法别混。** 远端(Server-hosted)技能写全名 `@scope/skill-name`,其中 scope 即其 Namespace(如 `@cnfox/code-review`);本地草稿目录写相对路径 `./path`,身份走保留 Scope `local`(`@local/*`,系统拦截、无法 `publish`);内置技能走保留 Scope `builtin`(`@builtin/<skill-name>`,随 CLI 发行、不可 `upload` / `publish` / `source` / `version` / `rename`)。用户含糊地说"那个技能"时先确认是远端、本地草稿还是内置、是哪个 scope 与短名。**归属写在源码里**:`release.json` 的 `name` 是身份的唯一权威来源(v4,ADR-0032)——`@组织名/短名` 发到组织命名空间(需是该组织成员),裸短名或 `@自己的用户名/短名` 落在个人命名空间;`SKILL.md.name` 只写短名。`init` 默认选 personal、交互式展示编号列表、组织归属也可用 `--namespace <组织名>`;首次 `upload` 会要求确认身份且之后固定(ADR-0039),已托管源改 namespace 会被阻断,`publish` 只断言一致,改归属不得靠改 `name`。`displayName`(v4,ADR-0048)是纯展示标题(可含中文与空格),不参与身份与授权——搜索/列表的标题位优先显示名、`@scope/短名` 作技术名。
40
+
41
+ ## 输出与解析
42
+
43
+ - 要从结果里取字段、比对、或后续按数据决策时,加 `--json`(`search`/`info`/`list`/`tools list` 支持),你直接解析结构化数据。`search` 面向人类有 TTY 发现会话;Agent 一律用 `--json`。
44
+ - 给用户看时用人类可读的默认输出。
45
+ - `esl use` 只把技能 Prompt 文本打到 stdout、不改项目——适合"试用一下"。可管道传给 Agent:`esl use @ns/name | <agent>`。
46
+
47
+ ## Agent 交互
48
+
49
+ 本技能由 AI 驱动,因此对已支持交互协议的命令默认使用 `--agent-interaction`
50
+ 与 `--agent-tool <tool>`,并先读 `references/agent-interaction.md`。当前
51
+ `init` 与裸 `esl version` 已接入;其他命令按其 reference 或 `--help` 确认。不要让 CLI 在该模式
52
+ 下等待 stdin,也不要根据普通错误文本猜测是否需要弹窗。
53
+
54
+ 如果命令返回退出码 `2` 且 stdout 是 JSON,读取 `questions` 数组,按宿主
55
+ 自己的交互界面消费;`metadata.source` 标记来源为 `esl-cli`。
56
+
57
+ 收集后优先使用命令已有的专用 flag,复杂或动态参数使用 `--params-json` 重新
58
+ 执行同一命令。退出码 `0` 是成功,其他失败按普通错误处理。
59
+
60
+ ## 命令找不到 / 服务不通
61
+
62
+ - `esl: command not found`:别重试。告诉用户获取 CLI——本仓库可 `npm run build`(产出 `packages/cli/dist/bin/esl.js` 的 `esl`),或全局装 `@foxian/esl`;装好再继续。
63
+ - Server 不可达或连接失败:提示检查 `esl config set-server <url>`(本地默认 `http://localhost:3000`);本地开发环境指向 `docs/guides/local-development.md` 用 Docker 起 Server。
64
+
65
+ 现在,按上面的路由表读对应 reference。
@@ -0,0 +1,110 @@
1
+ # Agent 交互协议
2
+
3
+ 本文件说明 AI Agent 如何消费 ESL CLI 的 Agent Interaction Protocol。协议的权威
4
+ 设计记录是 `docs/adr/0043-agent-interaction-protocol.md`;本文件只保留执行时需要
5
+ 的路由和操作规则。
6
+
7
+ ## 触发
8
+
9
+ 本技能由 AI 驱动,默认对已支持协议的 CLI 命令添加:
10
+
11
+ ```bash
12
+ esl <command> --agent-interaction --agent-tool <tool>
13
+ ```
14
+
15
+ `--agent-tool` 可选,用于标记调用方(Claude Code 用 `claude-code`,兼容旧值
16
+ `claude`;Codex 用 `codex`,其余见 `--help`)。无论是否带
17
+ `--agent-tool`,stdout 都输出 AskUserQuestion 风格 JSON。只在该模式下处理
18
+ 结构化交互请求,不要等用户明确说“需要选择框”才添加。普通终端保持现有交互
19
+ 方式。当前 `init` 与裸 `esl version` 已接入该协议;其他命令先查看其
20
+ reference 或 `--help`。
21
+
22
+ ## 判断结果
23
+
24
+ - 退出码 `0`:命令成功,继续处理 stdout。
25
+ - 退出码 `2` 且 stdout 是 JSON:
26
+ - 读取 `questions` 数组,按宿主自己的交互界面消费,`metadata.source`
27
+ 标记来源为 `esl-cli`。
28
+ - 收集答案后重新执行同一命令。
29
+ - 退出码 `1` 或其他不符合协议的输出:按普通错误处理,不自动弹出控件。
30
+
31
+ stdout 只按 JSON 协议解析;stderr 只作为人类可读日志或诊断信息,不当作字段值。
32
+
33
+ ## AskUserQuestion 风格输出
34
+
35
+ stdout 直接输出与 Claude Code `AskUserQuestion` 工具输入一致的 JSON:
36
+
37
+ ```json
38
+ {
39
+ "questions": [
40
+ {
41
+ "question": "License",
42
+ "header": "License",
43
+ "options": [{ "label": "MIT", "description": "默认值" }],
44
+ "multiSelect": false
45
+ }
46
+ ],
47
+ "metadata": { "source": "esl-cli" }
48
+ }
49
+ ```
50
+
51
+ 字段映射规则:
52
+
53
+ - `select` / `multiselect`:`options` 取自字段 `options`;`multiSelect` 按字段
54
+ `kind` 设置。选项可包含 `{ label, description }`,Agent 应向用户同时展示。
55
+ - `confirm`:`options` 固定为 `yes` / `no`。
56
+ - `text` / `textarea` / `path`:把默认值作为唯一快捷选项(`description` 标记
57
+ “默认值”),自定义文本由用户走 Other 输入;没有默认值时不臆造选项。
58
+
59
+ 答案以 `question` 文本为键返回。对 `init`,问题按顺序对应参数
60
+ `description`、`license`、`keywords`、`namespace`:单选取所选 `label`;多选
61
+ (`keywords`)的多个 label 用逗号拼接;自由文本取用户输入。映射后重新执行同一
62
+ 命令。对裸 `esl version`,`Release type` 的 `patch` / `minor` / `major` 直接
63
+ 作为 `release` 参数;自定义 SemVer 走 Other,再作为 `release` 原样传回。
64
+
65
+ ## 传回参数
66
+
67
+ 固定字段优先使用命令自己的 flag:
68
+
69
+ ```bash
70
+ esl init ./my-skill --description "代码审查技能" --license MIT
71
+ ```
72
+
73
+ 多个或嵌套参数使用 `--params-json`:
74
+
75
+ ```bash
76
+ esl init ./my-skill --agent-interaction --agent-tool <tool> --params-json '{"description":"代码审查技能","license":"MIT","keywords":["git","review"],"display-name":"代码审查","namespace":"personal"}'
77
+ ```
78
+
79
+ 在 Claude Code、Codex 或 Trae 里运行 `init` 时命令要带对应的 `--agent-tool`,
80
+ 并按上面的 `AskUserQuestion` 风格输出处理。
81
+
82
+ 裸 `esl version` 的 Agent 回答示例:
83
+
84
+ ```bash
85
+ esl version --agent-interaction --agent-tool <tool> --params-json '{"release":"patch"}'
86
+ esl version --agent-interaction --agent-tool <tool> --params-json '{"release":"1.4.2"}'
87
+ ```
88
+
89
+ `--params-json` 的值必须是顶层 JSON object。只传命令支持的字段;不要把同一字段
90
+ 同时放进专用 flag 和 JSON。未知字段、重复字段或类型错误都应让 CLI 返回普通失败。
91
+
92
+ ## 字段类型
93
+
94
+ 根据 `kind` 渲染控件:
95
+
96
+ - `text`:单行输入;
97
+ - `textarea`:多行输入;
98
+ - `select`:单选;
99
+ - `multiselect`:多选;
100
+ - `confirm`:确认;
101
+ - `path`:文件或目录路径。
102
+
103
+ 使用 `id` 作为参数键,保留 `default` 和 `options` 的类型。用户未确认的默认值
104
+ 不能擅自提交。
105
+
106
+ ## 凭据安全
107
+
108
+ 密码、token 和其他秘密不通过 Agent Interaction Request 或 `--params-json` 传递。
109
+ 登录或改密时让用户在自己的终端完成隐藏输入,或使用 `--password-file`、
110
+ `--token-file`。不要把秘密写进命令、JSON、对话内容或日志。
@@ -0,0 +1,98 @@
1
+ # 作者工作流:建 / 校验 / 发布 / 升版 / 拉源码
2
+
3
+ 只读命令(直接跑):`validate`。
4
+ 写命令(先回显、确认再跑):`init` `version` `source` `reset-source` `upload` `publish` `deprecate` `notes` `release-delete` `share`。
5
+
6
+ ## 初始化新技能(就地补缺)
7
+ `esl init [./path] [--name <短名>] [--namespace <namespace>] [--license SPDX] [--description <text>] [--keywords a,b] [--display-name <显示名>] --agent-interaction --agent-tool <tool>` —— 把指定目录(默认当前目录,可用全局 `-C` 选定)就地初始化为技能源:**缺什么补什么,绝不覆盖已有文件**。没有 `SKILL.md` 则生成(frontmatter 只含短名与描述);没有 `release.json` 则补最小清单(`schemaVersion: 4`、`name`、`version: 0.1.0`、`license` 默认 `MIT`、`displayName` 默认按短名 Title Case)。**不生成 `skill.json`**——它是安装/发布包的生成物,不属于源码。本技能由 AI 执行,`--agent-interaction --agent-tool <tool>` 是固定组成,不等待终端输入;`<tool>` 按当前宿主传(Claude Code 用 `claude-code`,兼容旧值 `claude`)。
8
+
9
+ 短名权威顺序:已有 `SKILL.md.name` > `--name` > 目录 basename。已有 `SKILL.md` 时整个文件不动;frontmatter 只要包含合法的 `name` 和 `description` 即可,`metadata`、`allowed-tools` 等额外键会被接受并忽略。缺少必填字段或类型非法时,`init` 只补缺并打一行警告,严格校验交给 `esl validate`。目录已是 git 仓库(含父级)时跳过 `git init`。
10
+
11
+ 在终端里 `init` 会逐项询问仍缺失字段的 description、license、keywords、displayName、namespace(各带默认值,回车接受)。namespace 会优先显示编号列表(1 固定为 personal,其余是当前登录用户所在组织;登录态有效时向服务端取一次组织列表,失败则回退登录时缓存,无列表退回手输),非交互环境(管道、`--no-input`)跳过问答直接写模板。已经用旗标给出的字段不会再问,所以 `--license Apache-2.0` 仍会问 keywords、但已生成 SKILL.md 时不再问 description。**脚本化场景建议把五个字段都用旗标给全**,避免依赖问答。
12
+
13
+ `displayName` 是显示名(ADR-0048):`init` 自动把短名转成标题(`markdown-master` → `Markdown Master`)预填为种子;想用中文显示名直接删除种子输入中文即可,留空则生成 v4 清单时省略该字段。
14
+
15
+ AI Agent 必须运行 `esl init ./my-skill --agent-interaction --agent-tool <tool>`,
16
+ 让缺失输入以 JSON 返回(退出码 `2`);向用户收集后重跑同一命令。Claude Code、
17
+ Codex、Trae 国际版和 Trae 国内版分别传 `claude-code`、`codex`、`trae-intl`、
18
+ `trae-cn`;旧值 `claude` 仍兼容。stdout 直接给出 `AskUserQuestion` 风格 JSON(含 `questions` 数组,
19
+ `metadata.source` 为 `esl-cli`),按宿主的交互界面消费。不带
20
+ `--agent-tool` 时输出同一格式。简单字段优先用专用旗标,多个结构化字段可用
21
+ 一次 `--params-json`:
22
+
23
+ ```bash
24
+ esl init ./my-skill --agent-interaction --agent-tool claude-code --params-json '{"description":"代码审查技能","license":"MIT","keywords":["git","review"],"namespace":"personal"}'
25
+ ```
26
+
27
+ `--params-json` 只接受顶层 JSON object,未知字段、错误类型,或同一字段同时由
28
+ 专用旗标和 JSON 传入都会按普通参数错误失败。
29
+
30
+ 注意:`init` 的 `--name` 只接受**短名**;`--namespace` 接受 `personal`(默认)或组织名。归属写在 `release.json` 的 `name` 字段(v3,ADR-0032):个人归属写裸短名(如 `my-skill`,上传时按上传者解析个人命名空间);组织归属写 `@组织名/短名`。想发布到组织命名空间,用 `esl init --namespace <组织名>` 或把 `name` 改成 `@组织名/短名`——但**首次 `upload` 即固定身份**,之后改归属必须走正式流程,别指望靠改 `name` 迁移。
31
+
32
+ ## 选目录:全局 -C
33
+ `esl -C <dir> <命令>`(长写 `--cd <dir>`)—— 借鉴 npm:先把工作目录切到 `<dir>` 再执行命令,对所有命令生效,位置可写在子命令前或后。相对 `-C` 的路径按**切换前**的 cwd 解析;切进去之后所有位置路径参数按**切换后**的 cwd 解析,想覆盖 `-C` 的目录请给绝对路径。给目录类命令传技能目录的写法就两条:全局 `-C` 或命令自带的位置路径(`esl upload [./path]`);各命令的 `--directory` 选项已移除。
34
+
35
+ ## 校验
36
+ `esl validate ./path` —— 发布前检查目录结构与 `SKILL.md` frontmatter。frontmatter 要求合法且必填的 `name`、`description`;其他额外字段允许存在,但不参与 ESL 元数据。源码形态下,发布输入是 `SKILL.md` + `release.json`;`skill.json` 不在源码里,`validate` 不要求它。只读。校验失败把错误逐条对照修,别带 `--force` 跳过。
37
+
38
+ 注意:`validate` 只校验结构,**不拦 `@local/*` 保留 Scope**——`@local` 的发布拦截由 `publish` 阶段执行。所以你在提议 `publish` 前要自己复核技能身份不是 `@local/*`,别等 `validate` 通过就以为能发。
39
+
40
+ ## 上传源码(发布前必需)
41
+ `esl upload [./path] [--message|-m <text>] [--license SPDX] [--confirm-identity <技能名>]` —— 把本地源码目录首次创建为 Server-hosted Skill Source:生成 Skill ID 与服务器 Git 仓库,并把本地源码推上服务器(加 `esl` remote)。技能目录用位置路径(`esl upload ./markdown-master`,默认当前目录)或全局 `-C` 指定。发布前必须已有 `esl` remote 且 `HEAD` 已推上去。新技能从 `init` 之后,先 `upload` 再 `publish`。
42
+
43
+ - **技能描述随每次 upload 同步**:`upload` 始终以 `SKILL.md` frontmatter 的 description 为准,把技能描述登记/更新到服务器(首次注册随登记写入;已托管源的后续同步走独立的仅 Maintainer 可用的 description 更新)。描述更新失败不阻断源码同步,仅在输出中提示——看到提示可如实转述,不要重试整个 upload。管理后台的技能管理页面展示的就是这个「最近一次 upload 登记的描述」,改了 `SKILL.md` 的描述后要跑一次 `upload` 才会在线上生效。
44
+ - **显示名随每次 upload 同步**:`upload` 以 `release.json` 的 `displayName` 为准确认/更新服务器显示名(ADR-0048),与 description 一样走「最近一次 upload 登记的值」;已托管源的后续同步走独立的仅 Maintainer 可用的 display-name 更新。改了 `release.json` 的 `displayName` 后要跑一次 `upload` 才会在线上生效。
45
+
46
+ - **归属由 `release.json` 的 `name` 决定**(ADR-0032):`@组织名/短名` 要求上传者是该组织成员(任何成员都可直发新技能,上传者成为初始 Maintainer,无需组织管理员预授权);裸短名或 `@自己的用户名/短名` 落在个人命名空间。身份在**首次 upload 时固定**,之后 `publish` 只会断言 `name` 与既定身份一致——不一致直接报错,归属变更不得借发布顺车。
47
+ - **首次 upload 先确认身份**(ADR-0039):交互式终端会显示将要创建的完整技能身份并要求 `y/N` 确认;非交互模式必须传 `--confirm-identity <release.json.name>`,值要和清单里的 `name` 完全一致。确认错了就改 `release.json` 后再上传,别把错误归属注册成新源。
48
+ - **已托管源禁止跨 namespace 漂移**(ADR-0039):后续 `upload` 会在 fetch/rebase/push 前比对 `release.json` 声明的 namespace 与 `esl` remote 揭示的既有 namespace;不一致直接阻断。恢复 `release.json` 的原 namespace 后继续同步;确需其他归属,只能显式创建新源,不支持跨 namespace 迁移。
49
+ - 若目录缺 `release.json`,`upload` 会自动补最小清单(`schemaVersion: 4`、裸短名、`version: 0.1.0`、`license` 默认 `MIT`,可用 `--license` 覆盖),并落盘到源码目录,然后提示先 commit + push、再重跑 `upload`。
50
+ - **Server Origin 迁移自动重指**:ESL Server 换地址(数据整体迁移,如换域名/IP)后,已托管目录的 `esl` remote 仍指向旧地址;下次 `esl upload` 会检测到 origin 漂移,自动向当前服务器验证技能身份(含改名重定向)后把 remote 重指到新地址并继续上传,输出一行「re-homed the esl remote」提示——不需要手动 `git remote set-url`。若验证不过(技能在当前服务器不存在,或当前登录读不到),报错会区分「地址迁移未验证」与「账号/权限」,并给出与下条相同的两条出路。
51
+ - 已托管目录(有 `esl` remote)上 fetch 失败时,`upload` 先用 Registry API 做一次只读探测再报错(ADR-0027),按探测结果分三种文案:**① 技能身份在服务器可见但 Git 源同步不了**——凭据陈旧或缺仓库权限,提示用维护它的账号重新登录后再 `esl upload`;**② 身份可见但服务器 cloneUrl 与 remote 仓库路径不一致**——remote 指向陈旧路径(如改名后),提示核对后手动 `git remote remove esl` 再重新 `esl upload`;**③ 探测失败(不确定)**——降级为统一的两种可能文案(其他账号维护 或 源已不存在),出路上「切维护账号重登」或确认删除后手动 `git remote remove esl` 两步重建。push 失败走同一统一文案并附 `git push esl HEAD:main` 收尾提示。CLI 绝不自动删除 remote 重注册——看到这类报错别提议删 remote,先按文案里的探测结论引导:能确定「身份可见」就只查账号/权限,探测失败才让用户去确认服务器源是否还在。
52
+
53
+ ## 发布
54
+ `esl publish [./path] [--message|-m <text>] [--dry-run] [--force|-f] [--license SPDX]` —— 在技能目录内执行,把当前源码发布为 Skill Release。**版本号不是命令参数**:它取自被发布 commit 的 `release.json.version`,所以发新版前必须先 `esl version`(见下节)。要求目录含 `release.json`;若缺失会自动补最小清单(`schemaVersion: 4`、裸短名、`version: 0.1.0`、`license` 默认 `MIT`),落盘后**提示先 `esl version` 设定版本、再发布**(不会继续发布)。默认会先要你确认;`--force` 跳过确认;`--no-input` 在自动化里失败即止。
55
+
56
+ - **传版本号会被拒绝**:`esl publish 1.0.0` 不再兼容(会被识别为误传的版本参数并报错指路 `esl version`)。要发 1.0.0 就先 `esl version 1.0.0`(或 `esl version major`)。
57
+ - **自动同步源码**:对已托管源,`publish` 会 `fetch`、必要时 rebase 到 `esl/main`、并 push 本地领先的提交与 tag——忘记 push 不再阻断发布;rebase 冲突时保留现场,提示解决后重跑。
58
+ - **发布前校验 release tag**:`v<SemVer>` 必须存在且指向被发布的 commit;缺失或指向别处会报错并指路 `esl version`。
59
+ - **回迁守卫**:新版本低于服务器最高已发布版本时会被拒绝(防手滑烧号);确需回迁旧线时用 `--force` 越过。
60
+ - **`--dry-run` 预演**:跑完所有本地校验(源码合法、工作树干净、remote 与身份、tag 指针)并打印将要发布的内容(版本、commit、文件清单),**不接触服务端、不 push**。用户想先看清楚会发什么时用它。
61
+ - 若目录还没有 `esl` remote,`publish` 会报错并提示你先 `esl upload`;它不自动建仓、不隐式登记,也不替你推断发布身份。
62
+
63
+ 重要:`@local/*` 保留 Scope 被系统拦截、无法发布(保留名同理:`local`/`builtin`/`admin`/`api`/`git`/`system` 不能作 scope 或用户名)。**发布身份以 `release.json` 的 `name` 为准**(ADR-0032),`publish` 只断言它与首次 upload 固定的身份一致。跑完报告服务器返回的技能身份与 Release Tag(`v<SemVer>`)提示。
64
+
65
+ ## 升级版本号
66
+ 源码形态(`SKILL.md` + `release.json`)的版本号**存在 `release.json` 的 `version` 字段里**,随源码走 Git 历史。升版一律走 `esl version`:
67
+
68
+ - 裸 `esl version` —— 仅在交互式终端中显示选择器,列出 `patch`、`minor`、`major` 的实际目标版本和用途,也可输入自定义 SemVer。
69
+ - `esl version patch|minor|major` —— 按 SemVer 递增,改写 `release.json`、自动 commit、并创建 annotated tag `v<SemVer>`。
70
+ - `esl version <显式 SemVer>`(如 `esl version 1.4.2`)—— 直接设值;这也是旧 `schemaVersion: 1` 清单的迁移入口(用递增关键字会报错指路)。
71
+ - 非 TTY 或 `--no-input` 下不能省略版本参数;AI Agent 执行裸命令时使用 `--agent-interaction`,按返回的 `Release type` 问题收集答案,再用 `--params-json '{"release":"patch"}'` 重执行。
72
+ - **`esl version` 不 push**:推送归 `esl upload` 或下一次 `esl publish`(`publish` 会自动同步)。
73
+ - 工作树有未提交改动时拒绝执行——先提交或 stash,避免无关改动被卷进版本提交。
74
+ - 内置技能(`@builtin/*`)不可升版,其版本锁定在 ESL CLI 版本上。
75
+
76
+ 标准发版序列:改源码 → `git commit` → `esl version patch` → `esl publish`(必要时先 `esl publish --dry-run` 预演)。
77
+
78
+ ## 弃用与删除单个版本
79
+ 坏版本(安全缺陷、内容错误)发出后不可覆盖、不可重发同号,只能劝退或删除:
80
+
81
+ - `esl deprecate @ns/name <version> --message "说明"`(`-m` 等价) —— 标记为不推荐。安装该版本的人会看到这段说明,但**仍可安装**;弃用不改变版本解析(被弃用版本若仍是最高稳定版,默认安装依旧选中它)。传空 message 解除标记。需要技能管理权。
82
+ - `esl notes @ns/name <version> --message "..."`(`-m` 等价) —— 修订已发布版本的 release notes(元数据,不改发布包)。需要技能管理权。
83
+ - `esl release-delete @ns/name <version> --confirm <version>` —— 删除单个 Release,用于内容必须从服务器消失的场景(如误发密钥)。移除该版本的发布包、版本记录与 Release Tag,**保留源码 Git 历史、技能本身与其他版本**。必须用 `--confirm` 回显版本号(版本号烧毁、不可重发,所以要显式确认,别替用户省这一步)。
84
+ - 技能 Maintainer 可删自己技能的版本;若该版本被其他技能的 Release Dependency Lock 引用,服务端会拒绝并列出引用方,此时只有平台管理员能加 `--force` 强制删除(强制后相关技能的安装会因依赖缺失而失败——报错里会说明,别默认加 `--force`)。
85
+ - 想「劝退但不删除」用 `deprecate`;`release-delete` 只在内容必须消失时用。
86
+
87
+ ## 拉别人源码做二次开发
88
+ `esl source @ns/name [./dir]` —— 克隆远端 Git 源码到本地(默认当前目录),可改可修。这拿的是源码仓库,不是 Published Package。
89
+
90
+ ## 重置源链接(源已在服务器删除后重建)
91
+ `esl reset-source [./path] [-f]` —— 把一个已托管目录(有 `esl` remote)还原为未托管的本地源:删除 `esl` remote 并把 `release.json` 改名保留为 `release.json.before-reset`。**它只做本地脱管,绝不删服务器上任何东西,也不自动重新登记**——重传始终是下一条显式的 `esl upload`(将生成全新 Skill ID)。适用场景只有一个:确认服务器源已被删除、本地要按新源重建。执行前的守门:CLI 先向 Registry API 询问一次该身份是否还存在——**身份仍可见时直接拒绝执行**(服务器源还在,别拿它当删除手段;报错会给出两条正途:切维护账号重登后 `esl upload` 同步,或在 Web 技能生命周期页真正删除:未发布技能由 manage 权限持有者删除,已发布技能由平台管理员或组织所有者删除),只有 `--force` 能越过阻断;探测失败才对应「确实没删到」的场景静默通过。要求确认,非交互传 `--force`。重传后缺 `release.json` 会自动补最小清单,需要的字段可从 `.before-reset` 备份拷回。别在源只是「维护账号不对」时怂恿用户 `--force`——阻断报错就是在拦这种情况,先让用户去服务器核实。
92
+
93
+ ## 共享与权限
94
+ `esl share @ns/skill-name --all [--write]` —— 授权给组织常设团队:`--all` 为组织只读团队(全员可读),`--write` 为组织读写团队。
95
+ `esl share @ns/skill-name --team <team>` —— 按技能授权指定团队只读;追加 `--write` 为读写,追加 `--manage` 为管理。团队成员会按该技能的授权档位获得权限。
96
+ `esl share @ns/skill-name --user <username> [--write]` —— 授权给单个成员只读或读写。
97
+ `esl share @ns/skill-name --reset` —— 重置为仅自己可见(撤销全部团队挂载与协作者授权)。
98
+ 四个目标互斥,一次只能选一个;执行前按写命令规则先回显完整命令、等用户确认。只有技能 Owner 或组织管理员能改权限,403 时提示无权而非重试。
@@ -0,0 +1,109 @@
1
+ # 消费者工作流:找 / 装 / 链 / 看 / 更 / 卸
2
+
3
+ 只读命令(直接跑):`search` `info` `use` `list` `tools list`。
4
+ 写命令(先回显、确认再跑):`install` `link` `unlink` `update` `uninstall` `adapt` `tools remove`。
5
+
6
+ ## 搜索
7
+ `esl search [query] [--namespace <org>] [--keyword <text>] [--visibility public|private] [--limit <n>] [--json]` —— 列出或查询 ESL Server 上**已发布且当前可安装**的技能。
8
+
9
+ - 不传 `query` 就是浏览全部可见技能;query 会匹配 Identity、描述、显示名(`displayName`,ADR-0048)和 keywords,`@scope/短名` 作技术名。
10
+ - `--namespace` 收窄组织/命名空间;`--keyword` 做硬过滤;`--visibility` 可选 `public` / `private`;`--limit` 控制条数(默认 50)。
11
+ - 匿名只能看到 public;登录后结果会附加用户有权读取的 private。匿名传 `--visibility private` 会明确报错并要求 `esl login`。
12
+ - 结果包含 `name`、`displayName`、`description`、`latestStableVersion`(不含 prerelease)和 `visibility`;`--json` 返回结构化数据。
13
+ - **AI/Agent 必须加 `--json`**,不要让 CLI 进入交互式 TTY 会话;拿到候选后按需用 `info` 复核,安装仍走 `install` 并遵守确认规则。
14
+ - 人类在交互式终端可不带 `--json` 使用 search:箭头选择技能、调整筛选、看详情;安装前 CLI 会回显完整 `esl install …` 并要求确认。`install` 本身不做远端目录浏览。
15
+
16
+ ## 查看详情
17
+ `esl info @scope/skill-name [--json]` —— 技能的元数据、版本、源码信息;对外显示名(`displayName`,ADR-0048)也随详情返回。已登录时请求会带上当前 Skill User Token:private 技能对其维护账号与有权限成员可见;未登录只能看到 public 技能。
18
+
19
+ ## 免安装试用
20
+ `esl use @scope/skill-name|./path [--version V]` —— 把技能 Prompt 文本打到 stdout,不安装、不改项目。可管道:`esl use @scope/skill-name | <agent>`。
21
+
22
+ ## 安装
23
+ `esl install @scope/skill-name|./path [--version V] [--global|-g] [--tools all|工具列表] [--no-tools] [--force]`
24
+
25
+ - 从 Server 装最新或指定版本;`./path` 装本地草稿。来源由参数自动判断:`@scope/name` 走 Server、`@builtin/*` 走内置、`./path` 走本地路径。
26
+ - 本地 `./path` 的安装身份固定为 `@local/<name>`(保留 Scope,不可发布);安装时在 Store 副本里补 `skill.json`,源目录不动。
27
+ - 项目级技能源写入 `<project>/.eslib/skills/@<scope>/<skill>/`;全局级写入 `~/.eslib/skills/@<scope>/<skill>/`。
28
+ - 项目根 `.skills.json` 是直接依赖声明;`.skills-lock.json` 是完整依赖图和精确版本锁。`.eslib/` 是本机状态,应保持 gitignore。
29
+ - 每个被选工具得到单技能目录 link,link 名使用 `<scope>_<skill>`,指向 `.eslib` 中的 `@<scope>/<skill>` 源;不复制技能,也不链接整个工具 skills 根目录。
30
+ - `--tools all` 选择全部九个工具;`--tools claude-code,codex` 选择指定工具;`--no-tools` 只装源、不建 link;`--force` 只能替换 ESL 记录的异常 link,不能覆盖非 ESL 内容。
31
+ - 未传 `--tools` 时优先级是:项目 `.skills.json` 的 `tools` > 全局配置的 `tools` > 交互 checkbox(至少选择一个工具)。非交互环境或 `--no-input` 没有可用选择时,命令必须报错而不要等待输入。
32
+ - 重复安装是幂等的:正确 link 保持;缺少的补齐;冲突报告且不覆盖;未列出的已有工具 link 不删除。
33
+ - 部分工具发生冲突或 link 创建失败时,已经写入的源和其他成功 link 保留,但命令以失败状态结束并给出冲突详情。
34
+ - 安装报 403(`Forbidden: read access required`)时:说明该 private 技能可能由**其他账号/组织**维护。让用户切换到维护账号后重登,不要盲目重试。
35
+
36
+ ## 本地源码开发链接
37
+
38
+ `esl link [./path] [--global|-g] [--identity @namespace] [--tools all|工具列表] [--no-tools] [--force]`
39
+
40
+ - 把本地技能源码目录链入 Skill Store:Store 位置指向源码,已有 Tool Link 继续指向 Store,形成“工具目录 → Skill Store → 本地源码”的两层链路。
41
+ - 身份来自 `release.json`:完整 `@scope/name` 原样使用;裸短名默认 `@local/<name>`;`--identity` 只能补 namespace 或给出短名一致的完整身份。
42
+ - `link` 不读取、不写入、不生成源码目录里的 `skill.json`;link 元数据记录在安装状态中。
43
+ - Store 中已有普通安装副本时默认拒绝;`--force` 把原副本移入 `.eslib/link-staging/` 再指向源码。源码修改后,所有已链接工具立即看到。
44
+ - 同一源重复 link 是幂等的;换成另一个源必须 `--force`。
45
+ - 未传 `--tools` 时按默认配置或交互 checkbox 选择;非交互环境或 `--no-input` 必须显式传 `--tools` 或 `--no-tools`。
46
+
47
+ `esl unlink [@scope/skill-name|./path] [--global|-g]`
48
+
49
+ - 解除 Skill Source Link。有 staging 时纯本地恢复原副本和依赖/锁/安装状态;无 staging 时移除 link 和记录。
50
+ - staging 缺失或损坏时报错并保留 link 状态,不尝试联网恢复。
51
+ - **主推:** 显式 `@scope/skill-name`;已在技能目录且当初是 **global** link 时,可 `esl unlink --global`(省略身份,读当前目录 `release.json`)。
52
+ - **项目级:** 在**项目根**执行 `esl unlink ./相对路径`,或显式传身份。不承诺「cd 进技能子目录后做项目级裸 unlink」能找对 Store(CLI 不以技能目录向上查找 `.eslib`)。
53
+ - 非 `@` 参数一律视为路径。裸短名 `release.json.name` 按 `@local/<短名>` 推导。
54
+ - 若目录推出的身份与真实已 link 身份不一致,报错并列出真实身份;请改传显式 `@identity`。
55
+ - 进阶:`esl unlink -C <项目根> ./skills/foo`(`-C` 只改工作目录 / 项目根,位置路径决定读哪个技能目录)。
56
+
57
+ `esl uninstall` 对 link 技能只删除 Skill Store link、记录、Tool Link 和 staging,不会递归删除本地源码目录;`esl update` 会跳过 link 技能并报告 skipped。
58
+ `esl list` / `esl ls [--global|-g] [--json]` —— 当前项目或全局 Skill Store 中已安装的技能。
59
+
60
+ ## 查看工具 link
61
+ `esl tools list [--tool <列表>] [--skill <列表>] [--global|-g|--project] [--managed|--unmanaged] [--status <状态列表>] [--json]`
62
+
63
+ - `linked`:link 存在且正确指向 Skill Store 源。
64
+ - `broken`:manifest 有记录,但 link 缺失或目标源不存在。
65
+ - `conflict`:目标存在,但不是预期的正确 ESL link。
66
+ - `source-only`:技能只在 Skill Store 中,没有工具 link。
67
+ - `unmanaged`:工具目录中存在,但不由 ESL manifest 管理。
68
+ - `--tool` 和 `--skill` 支持逗号分隔列表;`--status` 支持 `linked,broken,conflict,source-only,unmanaged`。
69
+ - 这个命令只读,直接运行;删除未管理内容仍必须由用户手工处理,ESL 不提供对应删除命令。
70
+
71
+ ## 手动建立或检查 link
72
+ `esl adapt [--global|-g]` —— 根据工具配置检查并建立已安装技能的 link。它只处理 Skill Store 中已安装的技能,遇到非 ESL 内容报告冲突。
73
+
74
+ 工具标识与目录:
75
+
76
+ | 工具 | 项目级 | 全局 |
77
+ |---|---|---|
78
+ | `claude`(输入别名 `claude-code`) | `.claude/skills/` | `~/.claude/skills/` |
79
+ | `codex` | `.codex/skills/` | `~/.codex/skills/` |
80
+ | `cursor` | `.cursor/skills/` | `~/.cursor/skills/` |
81
+ | `trae-intl` | `.trae/skills/` | `~/.trae/skills/` |
82
+ | `trae-cn` | `.trae/skills/` | `~/.trae-cn/skills/` |
83
+ | `workbuddy` | `.workbuddy/skills/` | `~/.workbuddy/skills/` |
84
+ | `opencode` | `.opencode/skills/` | `~/.config/opencode/skills/` |
85
+ | `openclaw` | `skills/` | `~/.openclaw/skills/` |
86
+ | `hermes` | `.hermes/skills/` | `~/.hermes/skills/` |
87
+
88
+ `trae` 是旧标识,不要在新命令中使用;规范标识是 `trae-intl`。
89
+
90
+ ## 更新
91
+ `esl update [@scope/skill-name] [--global|-g] [--tools <工具列表>] [--force]`
92
+
93
+ - 默认更新 Skill Store 中的源和锁文件;已有正确 link 自动看到新内容,不复制、不重建。Skill Source Link 不被 registry 版本替换,输出为 linked (skipped)。
94
+ - 默认不新增工具 link。传 `--tools` 时才确保指定工具存在正确 link。
95
+ - `--force` 只能替换 ESL 记录的旧 link;断链、错误链接或非 ESL 目录默认只报告。
96
+ - 不指定技能名则更新当前作用域全部已装技能。
97
+ - 某项报 403 时,update 会跳过它继续更新其余技能并逐项报告失败原因;已安装源和其他工具 link 不受影响。
98
+
99
+ ## 卸载
100
+ `esl uninstall @scope/skill-name [--global|-g]` —— 删除该作用域的技能源、依赖/锁/安装记录,以及该技能的全部 ESL 管理 link。普通安装删除 Store 副本;Skill Source Link 删除 Store 链接、记录和 staging,但保留本地源码目录。未管理内容不会被删除。
101
+
102
+ ## 只解除部分工具 link
103
+ `esl tools remove @scope/skill-name --tools claude-code,cursor [--global|-g]`
104
+
105
+ - 只删除 manifest 记录的指定工具 link,保留 Skill Store 源。
106
+ - 目标已被替换成普通目录、文件或错误链接时报告冲突并保留记录。
107
+ - Trae 国际版与国内版在项目级共享同一物理 link;只移除其中一个工具时 link 保留给另一个工具,移除最后一个引用时才删除物理 link。
108
+ - 未传 `--tools` 时按交互 checkbox 选择;非交互环境或 `--no-input` 必须显式传 `--tools`。
109
+ - `claude-code` 是 Claude Code 的输入别名,CLI 会归一化为兼容标识 `claude`;已有 manifest、`.skills.json` 和工具目录不需要迁移。
@@ -0,0 +1,41 @@
1
+ # 登录与环境准备
2
+
3
+ ## 配置 Server 地址(一次性)
4
+
5
+ ## 语言偏好
6
+ 登录响应会把账户的 `locale` 保存到本机 CLI 配置;后续命令默认按该语言输出。任意命令可用 `--locale zh-CN` 或 `--locale en-US` 做单次覆盖,但不会写回账户偏好。账户偏好本身在 Web 设置中管理。
7
+
8
+ `esl config set-server <url>` —— 设 ESL Server 地址。本地 Docker 默认 `http://localhost:3000`。设一次后所有命令都用它,不必每次带 `--server`。
9
+
10
+ ## Server Origin 迁移(服务器换地址)
11
+ ESL Server 换域名/IP 且**数据整体迁移**(技能、版本、Release 原样保留)时,改完 `esl config set-server <新地址>` 后:
12
+
13
+ - **消费端自动跟随**:install/update/use/source 每次从服务器现取地址,无需额外操作。
14
+ - **已托管源目录自动重指**:之前 `upload` 过的目录(带 `esl` remote)在下一次 `esl upload` 时自动验证技能身份并把 remote 重指到新地址,输出一行「re-homed the esl remote」提示;`esl status` 在这类目录只读提示 origin 漂移(ahead/behind 在重指前可能过期),不改任何配置。不需要也不建议手动 `git remote set-url`。
15
+ - **upload 报「地址迁移未验证」时**:报错说明 esl remote 指向旧地址而配置是新地址、但技能身份在当前服务器验证不过——先让用户确认当前登录账号能否读到该技能(换维护账号重登再 `upload`);只有确认服务器上确实没有该源时,才走手动 `git remote remove esl` + 重新 `upload`(按新技能重建,历史 Release 不回来)。绝不主动提议删 remote。
16
+
17
+ ## 查看登录状态
18
+ `esl whoami` —— 输出当前用户名 / Organization memberships(组织成员关系列表)/ Server / 登录时间 / 过期时间 / 状态(`active` / `expired` / `Not logged in`)。只读,可直接跑。状态不明时先跑它。
19
+ (全局身份模型:一条凭据走遍个人命名空间与所有所在组织,组织列表由服务端按 Git Backend 成员关系派生。旧版配置带 `org`/`role` 字段时输出一行重新登录提示。)
20
+
21
+ ## 登录
22
+ `esl login` —— 交互式(推荐):依次提示 `Username:` 与隐藏的密码(**无组织输入**)。登录成功后 token 写入本机所有者只读文件,默认 30 天有效;可用环境变量 `ESL_LOGIN_TTL_HOURS`(单位:小时)调整 TTL。
23
+
24
+ 旗标:
25
+ - `--username <name>`:指定用户名(仍会交互提示密码)
26
+ - `--server <url>`:本次覆盖已配置地址(也可用环境变量 `ESL_SERVER`)
27
+ - `--token-file <path>`:用用户 token 文件登录(离线,不换取身份;组织列表留空)
28
+ - `--password-file <path>`:用密码文件登录(脚本 / CI)
29
+
30
+ 账号是全局的:注册后即拥有个人命名空间 `@用户名`,被拉入组织后同样一份凭据即可访问组织命名空间,无需按组织分别登录。平台管理员不通过 CLI 登录——打开管理后台(`http://<server>/admin/`),用 `GITEA_ADMIN_USERNAME` 账号(默认 `eslroot`)与密码登录。
31
+
32
+ ## 登出
33
+ `esl logout` —— 清除本机凭据(token 与登录时间戳),保留 server / 组织 / 工具配置。幂等:未登录时执行也成功。登出后 `esl whoami` 显示 `Not logged in`,需要登录态的命令(install/update/upload 等)会提示先 `esl login`;离线命令(`adapt`/`list`/`validate`)与已安装技能的本地使用不受影响。用户想在共享机器上清除凭据、或要换一个组织账号登录时,提议它。写命令,先回显再执行。
34
+
35
+ ## AI 行为(重要)
36
+ - **交互式密码登录让用户自己跑**:`esl login` 会在它自己的终端提示输入密码,你替它跑反而会卡住或把密码暴露给会话。引导用户在自己的终端执行。
37
+ - 可以由你执行的登录形式:用户已把凭据备成文件——`esl login --username X --token-file ./f` 或 `--password-file ./f`。凭据从文件读、不进命令行,安全。执行前按写命令规则先回显、等用户确认。
38
+ - 绝不在命令行里写明文密码或 token;CLI 本身也不接受命令行明文凭据。
39
+
40
+ ## Token 过期
41
+ `whoami` 显示 `expired`,或某条命令报 401 → 让用户重新 `esl login`;可提一句 `ESL_LOGIN_TTL_HOURS` 调 TTL。
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "@builtin/esl-operator",
3
+ "version": "0.1.0",
4
+ "description": "Operate the Enterprise Skill Library (ESL) CLI from natural language. Search, try, install, list, update, uninstall, link shared skills into AI tools, or link a local skill source into the Skill Store (Claude Code, Codex, Cursor, Trae, WorkBuddy, opencode, OpenClaw, Hermes); inspect or remove tool links; create, validate, version, publish, or clone the source of skills. Use whenever the user wants to find or use a shared skill, install/update skills (project or global), inspect which tools have which skills, author or publish a skill, pull someone's skill source for edits, or otherwise drive the `esl` command — even when they never say \"esl\". Routes login and server setup but never types passwords.\n",
5
+ "author": "@foxian/esl",
6
+ "keywords": []
7
+ }
@@ -0,0 +1 @@
1
+ export declare function resolveBuiltinDir(): string;
@@ -0,0 +1,11 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ export function resolveBuiltinDir() {
5
+ const moduleDir = path.dirname(fileURLToPath(import.meta.url));
6
+ const candidate = path.resolve(moduleDir, '..', 'builtin');
7
+ if (fs.existsSync(candidate)) {
8
+ return candidate;
9
+ }
10
+ return path.resolve(moduleDir, '..', 'dist', 'builtin');
11
+ }
@@ -0,0 +1,8 @@
1
+ import { type AdaptResult } from '@esl/core';
2
+ export interface AdaptCommandOptions {
3
+ global?: boolean;
4
+ directory?: string;
5
+ homeDir?: string;
6
+ }
7
+ export declare function executeAdapt(options?: AdaptCommandOptions): Promise<AdaptResult[]>;
8
+ export declare function formatAdaptResults(results: AdaptResult[]): string[];
@@ -0,0 +1,27 @@
1
+ import { adaptGlobal, adaptProject } from '../vendor/core/index.js';
2
+ export async function executeAdapt(options = {}) {
3
+ if (options.global) {
4
+ return adaptGlobal({ homeDir: options.homeDir });
5
+ }
6
+ const projectRoot = options.directory ?? process.cwd();
7
+ return adaptProject(projectRoot, { homeDir: options.homeDir });
8
+ }
9
+ export function formatAdaptResults(results) {
10
+ return results.map((result) => {
11
+ const mappings = result.skills.map((skill) => `${skill.identity} -> ${skill.directoryName}`).join(', ');
12
+ const details = [
13
+ mappings,
14
+ formatOutcome('adopted', result.adopted),
15
+ formatOutcome('skipped', result.skipped),
16
+ formatOutcome('conflicts', result.conflicts),
17
+ formatOutcome('failed', result.failed)
18
+ ].filter(Boolean).join('; ');
19
+ return `${result.tool}: ${result.skills.length} skill(s) synced${details ? ` (${details})` : ''}`;
20
+ });
21
+ }
22
+ function formatOutcome(label, skills) {
23
+ if (skills.length === 0) {
24
+ return '';
25
+ }
26
+ return `${label}: ${skills.map((skill) => `${skill.identity} -> ${skill.directoryName}`).join(', ')}`;
27
+ }
@@ -0,0 +1,11 @@
1
+ import { type NetworkCommandOptions } from './network-options.js';
2
+ export interface ChangePasswordOptions extends NetworkCommandOptions {
3
+ passwordFile?: string;
4
+ noInput?: boolean;
5
+ readInput?: () => Promise<string>;
6
+ readPassword?: (prompt: string) => Promise<string>;
7
+ }
8
+ export interface ChangeOwnPasswordOptions extends ChangePasswordOptions {
9
+ currentPasswordFile?: string;
10
+ }
11
+ export declare function executeChangeOwnPassword(options: ChangeOwnPasswordOptions): Promise<void>;