@easbot/skills 0.3.13 → 0.3.16

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 (62) hide show
  1. package/README.en.md +432 -125
  2. package/README.md +427 -125
  3. package/dist/chunks/blob-RYNC3CVY.cjs +1 -0
  4. package/dist/chunks/{blob-3PZEQWTP.mjs → blob-WZAGX4RO.mjs} +1 -1
  5. package/dist/chunks/chunk-5DAHAO55.mjs +3 -0
  6. package/dist/chunks/{chunk-4D5RQDWJ.mjs → chunk-6OLPTZDO.mjs} +2 -2
  7. package/dist/chunks/{chunk-ZBKGF7PA.mjs → chunk-BQ6QWQEM.mjs} +1 -1
  8. package/dist/chunks/chunk-BWDTT6SA.cjs +3 -0
  9. package/dist/chunks/chunk-DNE3XPCJ.cjs +2 -0
  10. package/dist/chunks/chunk-HI5IN4UL.mjs +265 -0
  11. package/dist/chunks/chunk-HOK3SUH4.cjs +22 -0
  12. package/dist/chunks/{chunk-5BL3KG26.cjs → chunk-IJI72D6W.cjs} +2 -2
  13. package/dist/chunks/{chunk-ISMGLHYS.cjs → chunk-JUNIAQ2A.cjs} +1 -1
  14. package/dist/chunks/{chunk-CY6UI6SJ.cjs → chunk-LJ63Q26N.cjs} +1 -1
  15. package/dist/chunks/{chunk-S6YNGR7S.cjs → chunk-Q2MOP5ZW.cjs} +2 -2
  16. package/dist/chunks/chunk-S5OLAC7X.cjs +265 -0
  17. package/dist/chunks/chunk-UUZB3HCD.mjs +22 -0
  18. package/dist/chunks/chunk-Y6D5Z6AU.mjs +1 -0
  19. package/dist/chunks/chunk-ZJS7IO5V.mjs +2 -0
  20. package/dist/chunks/cli-handler-2G4ZYO2S.cjs +1 -0
  21. package/dist/chunks/cli-handler-F4DUEULA.mjs +1 -0
  22. package/dist/chunks/installer-3ZLHOVAO.cjs +1 -0
  23. package/dist/chunks/{installer-REG45DC2.mjs → installer-UUEXYC7I.mjs} +1 -1
  24. package/dist/chunks/{interfaces-UIS44Q7A.cjs → interfaces-T3TO7GQW.cjs} +1 -1
  25. package/dist/chunks/local-lock-KNX2RUIV.cjs +1 -0
  26. package/dist/chunks/local-lock-UYZTKIET.mjs +1 -0
  27. package/dist/chunks/scan-6EBCZDVK.cjs +1 -0
  28. package/dist/chunks/scan-BZA5LEZN.mjs +1 -0
  29. package/dist/chunks/skill-lock-CDMLVBYH.mjs +1 -0
  30. package/dist/chunks/skill-lock-WPACLO4W.cjs +1 -0
  31. package/dist/chunks/store-2ULHEVHS.cjs +1 -0
  32. package/dist/chunks/{store-IVDLGLET.mjs → store-FRXO6UWU.mjs} +1 -1
  33. package/dist/chunks/telemetry-TAVF3FAM.cjs +1 -0
  34. package/dist/cli.cjs +1 -1
  35. package/dist/cli.mjs +1 -1
  36. package/dist/index.cjs +1 -1
  37. package/dist/index.d.cts +3 -2
  38. package/dist/index.d.ts +3 -2
  39. package/dist/index.mjs +1 -1
  40. package/package.json +7 -8
  41. package/dist/chunks/blob-ZDEX2HRV.cjs +0 -1
  42. package/dist/chunks/chunk-5W7HC7BY.mjs +0 -22
  43. package/dist/chunks/chunk-CXH3OTTQ.cjs +0 -22
  44. package/dist/chunks/chunk-K2XGYOXP.mjs +0 -267
  45. package/dist/chunks/chunk-ML6B4IQL.mjs +0 -1
  46. package/dist/chunks/chunk-NKIQLESR.mjs +0 -3
  47. package/dist/chunks/chunk-ROCFLAYZ.mjs +0 -2
  48. package/dist/chunks/chunk-RVR3DSD2.cjs +0 -2
  49. package/dist/chunks/chunk-SXUY2J75.cjs +0 -3
  50. package/dist/chunks/chunk-UJWB7QQ6.cjs +0 -267
  51. package/dist/chunks/cli-handler-667TYY4I.cjs +0 -1
  52. package/dist/chunks/cli-handler-YSDUNKKZ.mjs +0 -1
  53. package/dist/chunks/installer-SOVGUW3M.cjs +0 -1
  54. package/dist/chunks/local-lock-AWD3LLEY.mjs +0 -1
  55. package/dist/chunks/local-lock-GIZDVF3X.cjs +0 -1
  56. package/dist/chunks/scan-57D2H7LP.cjs +0 -1
  57. package/dist/chunks/scan-WAXGJM5N.mjs +0 -1
  58. package/dist/chunks/skill-lock-DZMA75MY.mjs +0 -1
  59. package/dist/chunks/skill-lock-XTWQYBRG.cjs +0 -1
  60. package/dist/chunks/store-F7PGGZIO.cjs +0 -1
  61. package/dist/chunks/telemetry-LCGTSJDM.cjs +0 -1
  62. /package/dist/chunks/{chunk-VRHWDHQV.cjs → chunk-BWPPLYIF.cjs} +0 -0
package/README.en.md CHANGED
@@ -2,34 +2,36 @@
2
2
 
3
3
  # @easbot/skills
4
4
 
5
- Skill management subsystem for the EASBot ecosystem. Handles discovery, installation, removal, search, update, one-shot use (use), and store/cache/index operations for skills (SKILL.md). Also acts as the **Plugin Source Registry** (decision 0044), abstracting well-known, marketplace, and local plugin sources into `PluginSource` for `@easbot/agent` to inject into `PluginDefinition.skills`.
5
+ Skill management subsystem for the EASBot ecosystem. Handles discovery, installation, removal, search, update, one-shot use (`use`), template initialization (`init`), and store/cache/index operations for skills (SKILL.md). Also acts as the **Plugin Source Registry** (decision 0044), abstracting well-known, marketplace, and local plugin sources into `PluginSource` for `@easbot/agent` to inject into `PluginDefinition.skills`.
6
6
 
7
- Usable both as a standalone CLI (`easbot-skills`) and as a library delegated to by the `@easbot/agent` main CLI via Commander.js, making `easbot skills ...` and `easbot-skills ...` equivalent.
7
+ Usable both as a standalone CLI (`easbot-skills`) and as a library delegated to by the `@easbot/agent` main CLI via Commander.js `easbot skills ...` and `easbot-skills ...` are equivalent.
8
8
 
9
9
  ## Version
10
10
 
11
- v0.3.11
11
+ v0.3.13
12
12
 
13
13
  ## Target Files
14
14
 
15
15
  The package only operates on **SKILL.md** (and optional local `plugin.json`):
16
+
16
17
  - Skill name comes from the `name` field in the `SKILL.md` frontmatter
17
18
  - Plugin manifest comes from `plugin.json` (if present; otherwise defaulting to `*.md`)
18
19
 
19
20
  ## Features
20
21
 
21
- - **Type Safety**: Full TypeScript types + Zod frontmatter validation + Zod remote-skill payload validation
22
+ - **Type Safety**: full TypeScript types + Zod frontmatter validation + Zod remote-skill payload validation
22
23
  - **Multi-Source**: GitHub shorthand (`owner/repo`) / HTTPS / SSH / Well-Known index / local path / GitHub API blob fallback
23
- - **Multi-Agent**: 72+ agent types (`easbot`, `claude-code`, `cursor`, `codex`, `amp`, `eve`, `gemini-cli`, `github-copilot`, `opencode`, `qwen-code`, `trae`, `trae-cn`, `windsurf`, `zed`, `roo`, `cline`, `iflow-cli`, `kimi-code-cli`, `augment`, `devin`, `goose`, `depto` etc.)
24
- - **Universal shared path**: `eve` / `amp` / `gemini-cli` / `github-copilot` / `qwen-code` / `roo` / `windsurf` / `zed` / `claude-code` and 16 universal agents share `.agents/skills` directory
24
+ - **Multi-Agent**: 72+ agent types (`easbot`, `claude-code`, `cursor`, `codex`, `amp`, `eve`, `gemini-cli`, `github-copilot`, `opencode`, `qwen-code`, `trae`, `trae-cn`, `windsurf`, `zed`, `roo`, `cline`, `iflow-cli`, `kimi-code-cli`, `augment`, `devin`, `goose`, `dexto` etc.)
25
+ - **Universal shared path**: 16 agents (`eve` / `amp` / `gemini-cli` / `github-copilot` / `qwen-code` / `roo` / `windsurf` / `zed` / `claude-code` etc.) share `.agents/skills` via the `universal` scope
25
26
  - **Non-universal agents**: each maintains independent skill directories
26
- - **Install Matrix / Post-Install Reconcile**: `AgentInstallMatrix` (agent × skill 2D table, `probeCell` cell-by-cell), post-install cell reconcile (missing → link, excess → remove)
27
- - **Dependency Injection** (voting 0043): `setGlobalAdapter` / `setInstanceAdapter` / `setAgentAdapter` inject `IGlobal.Path` / `IInstance.directory` so skills uses the host's unified XDG data tree
28
- - **Incremental Sync**: Lockfile-based `add` / `remove` / `update` / `store` with local SHA-256 hashing (`skill-lock.ts` / `local-lock.ts`)
29
- - **Store-Centric Ops** (voting 36A): `skills store list / clean / update / remove` manage store dirs + index + cache without touching agent distributions
27
+ - **Install Matrix / Post-Install Reconcile**: `AgentInstallMatrix` (agent × skill 2D table, `probeCell` cell-by-cell); post-install cell reconcile (missing → link, excess → remove)
28
+ - **Dependency Injection** (decision 0043): `setGlobalAdapter` / `setInstanceAdapter` / `setAgentAdapter` inject `IGlobal.Path` / `IInstance.directory` so skills uses the host's unified XDG data tree
29
+ - **Incremental Sync**: lockfile-based `add` / `remove` / `update` / `store` with local SHA-256 hashing (`skill-lock.ts` / `local-lock.ts`)
30
+ - **Store-Centric Ops** (decision 36A): `skills store list / clean / update / remove` manage store dirs + index + cache without touching agent distributions
30
31
  - **Local Source Hard Protection**: `store clean --force` / `store remove` refuse to delete cache / user directory for local sources
31
- - **i18n**: Built-in zh-CN / en-US translations; all user-facing strings go through `t()`, with fallback to English literal when key is missing
32
- - **Telemetry + Audit**: Built-in `skills.sh` partner-audit reporting, OpenClaw risk scoping, telemetry flush (`flushTelemetry`)
32
+ - **i18n**: built-in zh-CN / en-US translations; all user-facing strings go through `t()`, with fallback to English literal when the key is missing
33
+ - **Telemetry + Audit**: built-in `skills.sh` partner-audit reporting, OpenClaw risk scoping, telemetry flush (`flushTelemetry`)
34
+ - **Unified Prompt namespace** (Session 4): every interactive flow goes through [`@easbot/terminal.Prompt`](../terminal/README.en.md) — cancellation contract centralized (`Prompt.cancel` returns `never` and calls `process.exit(0)` internally), icons centralized through `Symbol` (writing `✓✗◆` literals is **forbidden**), colors centralized through `theme.colorize()`
33
35
 
34
36
  ## Installation
35
37
 
@@ -54,47 +56,49 @@ src/
54
56
  ├── types.ts # AgentType, Skill, AgentConfig, ParsedSource, RemoteSkill
55
57
  ├── agents.ts # Agent config matrix (72+) + classification functions
56
58
  ├── skills.ts # Skill discovery: parseSkillMd, discoverSkills, filterSkills
59
+ ├── constants.ts # AGENTS_DIR / SKILLS_SUBDIR / UNIVERSAL_SKILLS_DIR
60
+ ├── frontmatter.ts # YAML frontmatter parser
61
+ ├── hash.ts # Hashing helpers: computeFromDir / computeSnapshotHash
62
+ ├── source-parser.ts # Source normalization: parseSource, parseOwnerRepo, sanitizeSubpath, isRepoPrivate
63
+ ├── interfaces.ts # Dependency injection: setGlobalAdapter / setInstanceAdapter / setAgentAdapter
64
+ ├── detect-agent.ts # Detect running AI agent: detectAgent / isRunningInAgent
65
+ ├── sanitize.ts # Control-char sanitization: sanitizeMetadata / stripTerminalEscapes
66
+ ├── telemetry.ts # Telemetry: track, flushTelemetry, fetchAuditData, setVersion
67
+ ├── git.ts # Repo clone / cleanupTempDir / parseGitHubRepoUrl
68
+ ├── blob.ts # GitHub API fallback: fetchRepoTree, tryBlobInstall, toSkillSlug
69
+ ├── skill-lock.ts # Global lockfile (skill-lock.json)
70
+ ├── local-lock.ts # Project lockfile (skills-lock.json) + folder SHA-256
57
71
  ├── installer/
58
- │ ├── installer.ts # Physical install: installSkillForAgent, installRemoteSkillForAgent, installBlobSkillForAgent
59
- │ ├── post-install.ts # Post-install reconcile matrix: planActions, buildMatrix, probeCell
60
- │ ├── store.ts # Three-layer store (sourcecacheinstall): ensureCachedSource, acquireSourceClone, cleanCache
61
- │ └── types.ts # InstallMode, InstalledSkill etc.
72
+ │ ├── installer.ts # Physical install: installSkillForAgent / installRemoteSkillForAgent / installBlobSkillForAgent / installWellKnownSkillForAgent / linkSkillDir / copySkillDir / listInstalledSkills / getInstallPath / getCanonicalPath / sanitizeName
73
+ │ ├── post-install.ts # Post-install reconcile matrix: planActions / buildMatrix / probeCell / runPostInstallReconcile
74
+ │ ├── store.ts # Three-layer source/cache/install convergence: acquireSourceClone / ensureCachedSource / cleanCache / getCacheRepoDir / getStoreDir
75
+ │ └── store-types.ts # Shared types: StoreSourceType / SkillEntry / PluginDefinition / MarketDefinition / SkillLocation / STORE_INDEX_VERSION / parsePluginId / storePathForSkillLock
62
76
  ├── add.ts # Skill add pipeline
63
77
  ├── find.ts # Search (skills.sh / fuzzy filter / local store query)
64
- ├── list.ts # List installed (project/global/agent filtered)
65
- ├── remove.ts # Remove skills
66
- ├── update.ts # Incremental update (by filter, update one or more)
67
- ├── use.ts # One-shot use: materializeUseSkill, buildUsePrompt, launchAgentInteractively
68
- ├── doctor.ts # Health check + dangling symlink cleanup
78
+ ├── list.ts # List installed skills (project/global/agent filtered)
79
+ ├── remove.ts # Remove skills
80
+ ├── update.ts # Incremental update (by filter, update one or more)
81
+ ├── use.ts # One-shot use: materializeUseSkill / buildUsePrompt / launchAgentInteractively
82
+ ├── doctor.ts # Health check + dangling symlink cleanup
69
83
  ├── store-cmd.ts # Store ops subcommands (list / clean / update / remove)
70
84
  ├── init-template.ts # Create a new skill from locale template
71
- ├── sanitize.ts # Control char sanitization: sanitizeMetadata, stripTerminalEscapes
72
- ├── telemetry.ts # Telemetry: track, flushTelemetry, fetchAuditData, setVersion
73
- ├── detect-agent.ts # Detect running AI agent: detectAgent, isRunningInAgent
74
- ├── skill-lock.ts # Global lockfile (skill-lock.json)
75
- ├── local-lock.ts # Project lockfile (skills-lock.json) + folder SHA-256
76
- ├── git.ts # Repo clone / cleanupTempDir / parseGitHubRepoUrl
77
- ├── blob.ts # GitHub API fallback: fetchRepoTree, tryBlobInstall, toSkillSlug
78
- ├── source-parser.ts # Source normalization: parseSource, parseOwnerRepo, sanitizeSubpath, shRepoPrivate
79
- ├── interfaces.ts # Dependency injection: setGlobalAdapter / setInstanceAdapter / getGlobal / getXdgData
80
- ├── constants.ts # AGENTS_DIR / SKILLS_SUBDIR / UNIVERSAL_SKILLS_DIR
81
- ├── frontmatter.ts # YAML frontmatter parser
82
- ├── format.ts # ANSI color helpers
83
85
  ├── providers/
84
86
  │ ├── wellknown.ts # WellKnownProvider: fetch index + scan + load
85
87
  │ └── registry.ts # Provider registry + HostProvider interface
86
- ├── sources/
88
+ ├── sources/ # Plugin Source registry (decision 0044)
87
89
  │ ├── index.ts # PluginSource entry: createWellKnownSource / createLocalPluginSource factories
88
90
  │ ├── registry.ts # Registry: registerSource / listSources / findSource / listAllEntries
89
91
  │ ├── wellknown.ts # Wellknown source adapter
90
92
  │ ├── local.ts # Local plugin dir (plugin.json) adapter
91
93
  │ └── types.ts # PluginSource / PluginSourceCategory / PluginSourceEntry interfaces
92
94
  ├── i18n/ # Full i18n (zh-CN / en-US)
93
- ├── prompts/ # Search multi-select prompt
94
- ├── utils/ # Helpers (ansi / format)
95
+ ├── utils/ # Helpers
96
+ ├── ansi.ts # Hardcoded SGR constants (RESET / BOLD / DIM / TEXT / CYAN / YELLOW / MAGENTA)
97
+ │ ├── format.ts # Label helpers: pBgLabel / pErrorBadge (agent badge + ERROR badge)
98
+ │ ├── color.ts # picocolors-shape bridge (dim/red/green/yellow/cyan/bold/... → @easbot/terminal.colorize + theme)
99
+ │ └── output.ts # Human-output helpers: printHuman / wrapJson / emitJson / formatListTruncated
95
100
  ├── cli.ts # Standalone CLI entry (easbot-skills)
96
- ├── cli-handler.ts # CLI handler (for agent reuse)
97
- └── src/sources/ # PluginSource registry (voting 0044)
101
+ └── cli-handler.ts # CLI handler (for agent reuse)
98
102
  ```
99
103
 
100
104
  ## CLI Usage
@@ -106,7 +110,7 @@ src/
106
110
  easbot-skills add houjallen/agent-skills
107
111
  easbot-skills add https://github.com/houjallen/agent-skills -g
108
112
 
109
- # Search (interactive fzf picker)
113
+ # Search (interactive search-multi-select)
110
114
  easbot-skills find typescript --owner houjallen
111
115
 
112
116
  # List installed (project/global)
@@ -135,19 +139,71 @@ easbot-skills store remove <sourceKey> --force # Extra clear cache
135
139
 
136
140
  # Health check (check + cleanup dangling symlinks)
137
141
  easbot-skills doctor
138
- easbot-skills doctor -a easbot -t # check one agent + auto-cleanup
139
- easbot-skills dr -g # global only
142
+ easbot-skills doctor -a easbot -y # Check one agent + auto-cleanup
143
+ easbot-skills dr -g # Global only
144
+
145
+ # Template initialization (create SKILL.md from locale template)
146
+ easbot-skills init my-skill
147
+ easbot-skills init # Creates SKILL.md under cwd/<basename>/skills
148
+ ```
149
+
150
+ ### Subcommand list (standalone CLI)
151
+
152
+ ```
153
+ easbot-skills add <source> # Add a skill (aliases: a / install / i)
154
+ easbot-skills find [query] # Search (aliases: search / f / s)
155
+ easbot-skills list # List installed (aliases: ls)
156
+ easbot-skills remove [skills...] # Remove (aliases: rm / r)
157
+ easbot-skills update [skills...] # Incremental update (aliases: upgrade / check)
158
+ easbot-skills use <source[@skill]> # One-shot use
159
+ easbot-skills init [name] # Template initialization
160
+ easbot-skills doctor # Health check (aliases: dr)
161
+ easbot-skills store <subcommand> # Store-centric ops (list / clean / update / remove)
140
162
  ```
141
163
 
164
+ ### `store` subcommands (Decision 0049-yyy)
165
+
166
+ ```
167
+ # List all sources inside the store (human-readable mode shows full 64-hex sourceKey for downstream update / remove)
168
+ easbot-skills store list
169
+ easbot-skills store list [keyword] # Filter by skill name
170
+
171
+ # Reset the store (default: wipe store dirs + index.json; --force additionally clears cache)
172
+ easbot-skills store clean
173
+ easbot-skills store clean --force
174
+
175
+ # Refresh store from source (does NOT touch agent distribution)
176
+ # No source-key → full store refresh
177
+ # With source-key (64-hex, copy from `store list`) → refresh only that source (entire source mirror)
178
+ easbot-skills store update
179
+ easbot-skills store update <full-source-key> # Decision 0049-yyy: [keyword] → [source-key]
180
+
181
+ # Remove a single store source (--force additionally clears cache; local source cache = user dir, NEVER deleted)
182
+ easbot-skills store remove <source-key>
183
+ easbot-skills store remove <source-key> --force
184
+ ```
185
+
186
+ **Core semantics**:
187
+ - `store` operates on the **whole-source mirror** (not on individual skills) — the store is a
188
+ cp of the source; either refresh the entire source or do nothing; there is no "update
189
+ only one skill inside the store" semantic.
190
+ - To "trigger store refresh + agent distribution by skill name", use `skills update <name>`
191
+ — that path already does full-source pull + per-skill hash compare → agent distribution.
192
+ - `store list` prints the **full** sourceKey (Decision 0049-yyy: previously 8-char truncated → users
193
+ couldn't reuse it directly).
194
+
142
195
  ### Delegated from a host CLI
143
196
 
144
- `@easbot/agent`'s `easbot skills ...` reuses all sub-commands via `handleSkillsCli(args, deps)`:
197
+ `@easbot/agent`'s `easbot skills ...` reuses every subcommand via `handleSkillsCli(args, deps)`:
145
198
 
146
199
  ```typescript
147
- import { handleSkillsCli, setGlobalAdapter, setInstanceAdapter } from '@easbot/skills';
200
+ import { handleSkillsCli, setAgentAdapter } from '@easbot/skills';
148
201
 
149
- setGlobalAdapter({ Path: Global.Path });
150
- setInstanceAdapter({ directory: ctx.config.directory, worktree: Instance.worktree });
202
+ setAgentAdapter({
203
+ global: Global, // IGlobal
204
+ instance: Instance, // IInstance
205
+ // subAgentRunner / localAgentRunner / triggerEvent are optional
206
+ });
151
207
 
152
208
  const result = await handleSkillsCli(['add', 'houjallen/agent-skills', '-y'], {
153
209
  version: ctx.programVersion,
@@ -156,105 +212,354 @@ const result = await handleSkillsCli(['add', 'houjallen/agent-skills', '-y'], {
156
212
  // process.exit(result.code) if result.code !== 0
157
213
  ```
158
214
 
159
- `easbot skills` is registered in `packages/agent/src/cli/commands/skills.ts` via `registerSkillsCommand()`. Commander.js `skills.<subcommand>` converts flags to argv and dispatches to `handleSkillsCli`. The `skills store` sub-family is also registered in the same module via `registerSkillsCommand()`.
215
+ `easbot skills` is registered in `packages/agent/src/cli/commands/skills.ts` via `registerSkillsCommand()`. Commander.js `skills.<subcommand>` converts flags to argv and dispatches to `handleSkillsCli`. The `skills store` sub-family is registered in the same module.
160
216
 
161
- ## API
217
+ ## API (by module)
162
218
 
163
- | Module | Exports | Notes |
164
- |---|---|---|
165
- | `types` | `AgentType`, `Skill`, `AgentConfig`, `ParsedSource`, `RemoteSkill` | Core type definitions (70+ AgentType union) |
166
- | `agents` | `agents`, `detectInstalledAgents`, `getAgentConfig`, `getAgentSkillDirs`, `getUniversalAgents`, `getAgentGlobalSkillDirs`, `isUniversalAgent`, `matchesUniversalScope` etc. | Agent config matrix + classifiers |
167
- | `skills` | `parseSkillMd`, `discoverSkills`, `filterSkills`, `getSkillDisplayName`, `isSubpathSafe`, `shouldInstallInternalSkills` | SKILL.md discovery/parse |
168
- | `installer` | `installSkillForAgent`, `installRemoteSkillForAgent`, `installBlobSkillForAgent`, `installWellKnownSkillForAgent`, `listInstalledSkills`, `isSkillInstalled`, `getCanonicalSkillsDir`, `getInstallPath`, `sanitizeName` | Physical install APIs |
169
- | `installer/post-install` | `buildMatrix`, `planActions`, `applyActions`, `probeCell`, `runPostInstallReconcile` | Install matrix + diff application |
170
- | `installer/store` | `acquireSourceClone`, `ensureCachedSource`, `installFromCache`, `cleanCache`, `getCacheRepoDir`, `getSourceDir` | Three-layer source/cache/install architecture |
171
- | `add` | `runAdd`, `parseAddOptions`, `initTelemetry`, `AddOptions` | Add flow |
172
- | `find` | `runFind`, `parseFindOptions`, `searchSkillsAPI`, `FindOptions`, `SearchSkill` | Search (skills.sh + local store) |
173
- | `list` | `runList`, `parseListOptions` | List |
174
- | `remove` | `removeCommand`, `parseRemoveOptions`, `RemoveOptions` | Remove |
175
- | `update` | `runUpdate`, `parseUpdateOptions`, `hasProjectSkills`, `matchesSkillFilter`, `resolveUpdateScope`, `UpdateScope` | Incremental update |
176
- | `store-cmd` | `runStore`, `parseStoreOptions`, `runStoreList`, `runStoreClean`, `runStoreUpdate`, `runStoreRemove`, `StoreOptions` | Ops: store/cache/index management |
177
- | `use` | `runUse`, `parseUseOptions`, `buildUsePrompt`, `materializeUseSkill`, `launchAgentInteractively`, `UseOptions`, `MaterializedUseSkill` | one-shot use |
178
- | `doctor` | `runDoctor` | Health check + link cleanup |
179
- | `cli-handler` | `handleSkillsCli`, `renderBanner`, `renderHelp`, `SkillsCliDeps`, `SkillsCliResult` | CLI bridge for agent reuse |
180
- | `interfaces` | `setGlobalAdapter`, `setInstanceAdapter`, `setAgentAdapter`, `getGlobal`, `getInstance`, `getHomeDir`, `getXdgData`, `getXdgConfig`, `getXdgState`, `getXdgCache`, `getProjectDirectory`, `resetGlobalAdapter`, `resetInstanceAdapter`, `hasAgentAdapter` | Path/Agent DI |
181
- | `skill-lock` | `readSkillLock`, `writeSkillLock`, `addSkillToLock`, `removeSkillFromLock`, `getSkillFromLock`, `getGitHubToken`, `getAllLockedSkills`, `dismissPrompt`, `isPromptDismissed`, `resetGhAuthWarning` | Global lockfile |
182
- | `local-lock` | `readLocalLock`, `writeLocalLock`, `addSkillToLocalLock`, `removeSkillFromLocalLock`, `computeSkillFolderHash`, `getLocalLockPath` | Project lockfile |
183
- | `git` | `cloneRepo`, `cleanupTempDir`, `parseGitHubRepoUrl`, `isGitHubHttpsCloneUrl`, `isGitHubSsoAuthError`, `GitCloneError` | Git subprocess cloning with fallbacks |
184
- | `blob` | `fetchRepoTree`, `findSkillMdPaths`, `getSkillFolderHashFromTree`, `tryBlobInstall`, `toSkillSlug`, `resetRepoTreeAuthState` | GitHub API blob fallback |
185
- | `telemetry` | `track`, `flushTelemetry`, `setVersion`, `fetchAuditData`, `setDetectedAgent` | Usage stats + security |
186
- | `sanitize` | `sanitizeMetadata`, `stripTerminalEscapes` | Output sanitization |
187
- | `detect-agent` | `detectAgent`, `getAgentName`, `getAgentType`, `isRunningInAgent` | Agent environment detection |
188
- | `providers/wellknown` | `wellKnownProvider`, `WellKnownProvider` | WellKnown host: parse index + pull SKILL.md |
189
- | `providers/registry` | `findProvider`, `registerProvider`, `getProviders`, `registry` | Provider registry + HostProvider interface |
190
- | `sources` | `registerSource`, `listSources`, `findSource`, `findSourcesByCategory`, `listAllEntries`, `createWellKnownSource`, `createLocalPluginSource` | PluginSource registry (voting 0044) |
191
- | `frontmatter` | `parseFrontmatter` | YAML frontmatter parser |
192
- | `constants` | `AGENTS_DIR`, `SKILLS_SUBDIR`, `UNIVERSAL_SKILLS_DIR` | Convention directory constants |
193
- | `utils/ansi` | `BOLD`, `DIM`, `RESET`, `TEXT`, `CYAN` etc. | ANSI terminal helpers |
194
-
195
- ## Supported Agent List (Complete)
196
-
197
- The `AgentType` union in `types.ts` contains 70+ agent types, including:
198
-
199
- `easbot`, `claude-code`, `cursor`, `codex`, `eve`, `opencode`, `aider-desk`, `amp`, `antigravity`, `astrbot`, `augment`, `autohand-code`, `bob`, `openClaw`, `cline`, `codearts-agent`, `codebuddy`, `codemaker`, `codestudio`, `command-code`, `continue`, `cortex`, `crush`, `deepagents`, `devin`, `depto`, `droid`, `firebender`, `forgecode`, `gemini-cli`, `github-copilot`, `goose`, `hermes-agent`, `inference-sh`, `iflow-cli`, `jazz`, `junie`, `kilo`, `kimi-code-cli`, `kiro-cli`, `kode`, `lingma`, `loaf`, `mcpjam`, `mistral-vibe`, `moxby`, `mux`, `neovate`, `openhands`, `om`, `pi`, `qoder`, `qoder-cn`, `qwen-code`, `replit`, `reasonix`, `roo`, `roodev`, `tabnine-cli`, `terramind`, `tinycloud`, `trae`, `trae-cn`, `warp`, `windsurf`, `zed`, `zencoder`, `zenflow`, `pochi`, `promptscript`, `adal`, `antigravity-cli`, `mistral`, plus the virtual type `universal`.
200
-
201
- All agent configurations (displayName, skillsDir, globalSkillsDir, universal flag, install detection functions) are defined in `src/agents.ts`.
219
+ > All exports flow from the top-level entry [`src/index.ts`](src/index.ts) and are grouped by theme below.
220
+
221
+ ### 1. Core types
222
+
223
+ ```typescript
224
+ import type { AgentType, Skill, AgentConfig, ParsedSource, RemoteSkill } from '@easbot/skills';
225
+ ```
226
+
227
+ | Type | Description |
228
+ |---|---|
229
+ | `AgentType` | 70+ Agent union (includes the `universal` virtual type) |
230
+ | `Skill` | Skill model (name / path / frontmatter / pluginName / subpath etc.) |
231
+ | `AgentConfig` | Agent configuration (name / displayName / skillsDir / globalSkillsDir / detectInstalled) |
232
+ | `ParsedSource` | Source descriptor (type / url / ref / subpath) |
233
+ | `RemoteSkill` | Remote-skill model |
234
+
235
+ ### 2. Agent system
236
+
237
+ ```typescript
238
+ import {
239
+ agents, // Record<AgentType, AgentConfig>
240
+ EVE_SUBAGENTS_DIR, // 'agent/subagents'
241
+ PROJECT_SKILLS_DIR_PATTERN, // /^\.[^/]+\/skills$/
242
+ detectInstalledAgents,
243
+ getAgentConfig,
244
+ getAgentGlobalSkillDirs, // List of project-level agent global skill dirs
245
+ getAgentProjectSkillDirs,
246
+ getAgentProjectSkillContainerPrefixes,
247
+ getAgentSkillDirs,
248
+ getEveSubagents,
249
+ getNonUniversalAgents, // Non-universal agents
250
+ getOpenClawGlobalSkillsDir,
251
+ getUniversalAgents,
252
+ isUniversalAgent,
253
+ matchesUniversalScope,
254
+ } from '@easbot/skills';
255
+ import type { AgentSkillDirsResult, UniversalScope } from '@easbot/skills';
256
+ ```
257
+
258
+ ### 3. Skill discovery / install
259
+
260
+ ```typescript
261
+ import {
262
+ discoverSkills, filterSkills, getSkillDisplayName,
263
+ isSubpathSafe, parseSkillMd, shouldInstallInternalSkills,
264
+ installSkillForAgent, installRemoteSkillForAgent, installBlobSkillForAgent,
265
+ installWellKnownSkillForAgent,
266
+ linkSkillDir, copySkillDir,
267
+ getAgentBaseDir, getCanonicalPath, getCanonicalSkillsDir,
268
+ getEveSubagentSkillsDir, getInstallPath,
269
+ isSkillInstalled, listInstalledSkills, sanitizeName,
270
+ } from '@easbot/skills';
271
+ import type { DiscoverSkillsOptions, InstallMode, InstalledSkill } from '@easbot/skills';
272
+
273
+ // Post-install matrix
274
+ import { applyActions, buildMatrix, planActions, probeCell, runPostInstallReconcile } from '@easbot/skills';
275
+ import type { AgentInstallMatrix, CellAction, CellScope, InstallCell, InstallState,
276
+ PostInstallInput, PostInstallResult } from '@easbot/skills';
277
+ ```
278
+
279
+ ### 4. Source parsing
280
+
281
+ ```typescript
282
+ import { parseSource, parseOwnerRepo, getOwnerRepo, isRepoPrivate, sanitizeSubpath } from '@easbot/skills';
283
+ ```
284
+
285
+ ### 5. Command entry points (`run*` + `parse*`)
286
+
287
+ ```typescript
288
+ import { runAdd, parseAddOptions, initTelemetry } from '@easbot/skills';
289
+ import type { AddOptions } from '@easbot/skills';
290
+
291
+ import { runFind, parseFindOptions, searchSkillsAPI } from '@easbot/skills';
292
+ import type { FindOptions, ParseFindOptionsResult, SearchSkill } from '@easbot/skills';
293
+
294
+ import { runList, parseListOptions } from '@easbot/skills';
295
+ import { removeCommand, parseRemoveOptions } from '@easbot/skills';
296
+ import type { RemoveOptions } from '@easbot/skills';
297
+
298
+ import { runUpdate, parseUpdateOptions, hasProjectSkills, matchesSkillFilter, resolveUpdateScope } from '@easbot/skills';
299
+ import type { UpdateCheckOptions, UpdateScope } from '@easbot/skills';
300
+
301
+ import { runUse, parseUseOptions, buildUsePrompt, materializeUseSkill, launchAgentInteractively } from '@easbot/skills';
302
+ import type { AgentProcess, AgentSpawn, MaterializedUseSkill, ParseUseOptionsResult, UseOptions, UseSkill } from '@easbot/skills';
303
+
304
+ import { runDoctor } from '@easbot/skills';
305
+
306
+ import { runStore, parseStoreOptions, runStoreList, runStoreClean, runStoreUpdate, runStoreRemove } from '@easbot/skills';
307
+ import type { StoreOptions } from '@easbot/skills';
308
+ ```
309
+
310
+ ### 6. Lockfile / hashing
311
+
312
+ ```typescript
313
+ import {
314
+ readSkillLock, writeSkillLock, addSkillToLock, removeSkillFromLock, getSkillFromLock,
315
+ getGitHubToken, getAllLockedSkills, getSkillsBySource,
316
+ getSkillLockPath, computeContentHash, storePathFromLockEntry,
317
+ dismissPrompt, isPromptDismissed, resetGhAuthWarning,
318
+ } from '@easbot/skills';
319
+ import type { DismissedPrompts, SkillLockEntry, SkillLockFile } from '@easbot/skills';
320
+
321
+ import {
322
+ readLocalLock, writeLocalLock, addSkillToLocalLock, removeSkillFromLocalLock,
323
+ getLocalLockPath, storePathFromLocalLockEntry,
324
+ } from '@easbot/skills';
325
+ import type { LocalSkillLockEntry, LocalSkillLockFile } from '@easbot/skills';
326
+
327
+ import { computeFromDir, computeSnapshotHash } from '@easbot/skills';
328
+ ```
329
+
330
+ ### 7. Git / Blob integration
331
+
332
+ ```typescript
333
+ import {
334
+ DEFAULT_CLONE_TIMEOUT, GitCloneError,
335
+ cloneRepo, cleanupTempDir, parseGitHubRepoUrl,
336
+ isGitHubHttpsCloneUrl, isGitHubSsoAuthError,
337
+ } from '@easbot/skills';
338
+
339
+ import {
340
+ BLOB_ALLOWED_REPOS, // Record<string, { downloadUrl }>
341
+ toSkillSlug,
342
+ fetchRepoTree, findSkillMdPaths, getSkillFolderHashFromTree,
343
+ resetRepoTreeAuthState, tryBlobInstall,
344
+ } from '@easbot/skills';
345
+ import type { BlobInstallResult, BlobSkill, RepoTree, SkillDownloadResponse, SkillSnapshotFile, TreeEntry } from '@easbot/skills';
346
+ ```
347
+
348
+ ### 8. Installer support layer (three-layer source / cache / install)
349
+
350
+ ```typescript
351
+ import {
352
+ acquireSourceClone, ensureCachedSource, installFromCache, cleanCache, cleanCachedRepo,
353
+ getCacheRepoDir, getCacheRoot, getSourceDir,
354
+ } from '@easbot/skills';
355
+ import type { InstallScope } from '@easbot/skills';
356
+
357
+ // store-types shared types
358
+ export type {
359
+ StoreSourceType, SkillScope,
360
+ SkillEntry, PluginDefinition, MarketDefinition, SkillLocation,
361
+ DefaultPluginConfig, StoreIndex,
362
+ STORE_INDEX_VERSION,
363
+ parsePluginId, pluginDirFromPluginId, storePathForSkillLock,
364
+ } from '@easbot/skills';
365
+ ```
366
+
367
+ ### 9. Security / telemetry / Agent detection
368
+
369
+ ```typescript
370
+ import {
371
+ track, flushTelemetry, fetchAuditData, setVersion, setDetectedAgent,
372
+ } from '@easbot/skills';
373
+ import type { AuditResponse, PartnerAudit, SkillAuditData } from '@easbot/skills';
374
+
375
+ import { sanitizeMetadata, stripTerminalEscapes } from '@easbot/skills';
376
+
377
+ import { detectAgent, getAgentName, getAgentType, isRunningInAgent } from '@easbot/skills';
378
+ ```
379
+
380
+ ### 10. Provider abstraction
381
+
382
+ ```typescript
383
+ import { wellKnownProvider, WellKnownProvider } from '@easbot/skills';
384
+ import type {
385
+ WellKnownIndex, WellKnownIndexV1, WellKnownIndexV2,
386
+ WellKnownSkill, WellKnownSkillEntry, WellKnownSkillEntryV1, WellKnownSkillEntryV2,
387
+ WellKnownFileContent,
388
+ } from '@easbot/skills';
389
+
390
+ import { findProvider, getProviders, registerProvider, registry } from '@easbot/skills';
391
+ import type { HostProvider, ProviderMatch, ProviderRegistry, RemoteSkill as ProviderRemoteSkill } from '@easbot/skills';
392
+ ```
393
+
394
+ ### 11. Constants & helpers
395
+
396
+ ```typescript
397
+ import { AGENTS_DIR, SKILLS_SUBDIR, UNIVERSAL_SKILLS_DIR, parseFrontmatter } from '@easbot/skills';
398
+ ```
399
+
400
+ ### 12. CLI bridge (reused by `@easbot/agent`)
401
+
402
+ ```typescript
403
+ import { handleSkillsCli, renderBanner, renderHelp } from '@easbot/skills';
404
+ import type { SkillsCliDeps, SkillsCliResult } from '@easbot/skills';
405
+ ```
406
+
407
+ ### 13. Interface injection (host → skills)
408
+
409
+ ```typescript
410
+ import {
411
+ setGlobalAdapter, setInstanceAdapter, setAgentAdapter,
412
+ resetGlobalAdapter, resetInstanceAdapter,
413
+ getGlobal, getInstance, getAgentAdapter, getHomeDir,
414
+ getXdgConfig, getXdgData, getXdgState, getXdgCache,
415
+ getProjectDirectory,
416
+ hasAgentAdapter, requireAgentAdapter,
417
+ } from '@easbot/skills';
418
+ import type { SkillsAgentAdapter } from '@easbot/skills';
419
+ import type { IGlobal, IInstance, ISubAgentRunner } from '@easbot/skills';
420
+ ```
421
+
422
+ ### 14. Plugin Source registry (decision 0044)
423
+
424
+ ```typescript
425
+ import { registerSource, unregisterSource, listSources, findSource, findSourcesByCategory, listAllEntries,
426
+ createWellKnownSource, createLocalPluginSource } from '@easbot/skills';
427
+ import type {
428
+ PluginSource, PluginSourceCategory, PluginSourceEntry, PluginSourceLoadResult,
429
+ WellKnownSourceOptions, LocalPluginSourceOptions,
430
+ } from '@easbot/skills';
431
+ ```
432
+
433
+ ```typescript
434
+ import { registerSource, createWellKnownSource, createLocalPluginSource } from '@easbot/skills';
435
+
436
+ // 1) Register a well-known endpoint as a plugin source
437
+ registerSource(createWellKnownSource({
438
+ url: 'https://mintlify.com/docs',
439
+ }));
440
+
441
+ // 2) Register a local plugin.json as a plugin source
442
+ registerSource(createLocalPluginSource({
443
+ basePath: process.cwd(),
444
+ }));
445
+
446
+ // 3) At @easbot/agent bootstrap, pull every source
447
+ import { listSources } from '@easbot/skills';
448
+ for (const source of listSources()) {
449
+ const entries = await source.fetch();
450
+ for (const entry of entries) {
451
+ const { skills } = await source.load(entry);
452
+ // → inject into PluginDefinition.skills
453
+ }
454
+ }
455
+ ```
456
+
457
+ ## Supported Agent List (complete)
458
+
459
+ The `AgentType` union in `agents.ts` covers **72 agents** (plus the `universal` virtual type):
460
+
461
+ `easbot`, `claude-code`, `cursor`, `codex`, `eve`, `opencode`, `aider-desk`, `amp`, `antigravity`, `astrbot`, `augment`, `autohand-code`, `bob`, `openclaw`, `cline`, `codearts-agent`, `codebuddy`, `codemaker`, `codestudio`, `command-code`, `continue`, `cortex`, `crush`, `deepagents`, `devin`, `dexto`, `droid`, `firebender`, `forgecode`, `gemini-cli`, `github-copilot`, `goose`, `hermes-agent`, `inference-sh`, `iflow-cli`, `jazz`, `junie`, `kilo`, `kimi-code-cli`, `kiro-cli`, `kode`, `lingma`, `loaf`, `zanbura`, `mistral-vibe`, `moxby`, `mux`, `neovate`, `openhands`, `om`, `pi`, `qoder`, `qoder-cn`, `qwen-code`, `replit`, `reasonix`, `roo`, `rovodev`, `tabnine-cli`, `terramind`, `tinycloud`, `trae`, `trae-cn`, `warp`, `windsurf`, `zed`, `zencoder`, `zenflow`, `pochi`, `promptscript`, `adal`, `antigravity-cli`, `mistral`, plus the virtual type `universal`.
462
+
463
+ **Universal shared `.agents/skills` directory** (16 agents): `eve` / `amp` / `gemini-cli` / `github-copilot` / `qwen-code` / `roo` / `windsurf` / `zed` / `claude-code` etc.
464
+
465
+ All agent configuration (displayName / skillsDir / globalSkillsDir / universal flag / install detection / `detectInstalled`) lives in `src/agents.ts`.
202
466
 
203
467
  ## Global Path Dependency Injection
204
468
 
205
- To avoid conflicting with the host (agent/gateway) over XDG / home, `@easbot/skills` resolves paths through dependency injection by default:
469
+ To avoid conflicting with the host (agent / gateway) over XDG / home, `@easbot/skills` resolves paths through dependency injection by default:
206
470
 
207
471
  ```typescript
208
472
  import {
209
- setGlobalAdapter, // inject IGlobal.Path
210
- setInstanceAdapter, // inject IInstance.directory / worktree
211
- setAgentAdapter, // inject SkillsAgentAdapter (subAgentRunner / localAgentRunner / triggerEvent)
473
+ setAgentAdapter, // Recommended: one-shot injection (global + instance + optional subAgentRunner etc.)
474
+ setGlobalAdapter, // Inject IGlobal.Path
475
+ setInstanceAdapter, // Inject IInstance.directory / worktree
212
476
  getHomeDir,
213
477
  getXdgConfig,
214
478
  getXdgData,
215
479
  getProjectDirectory,
216
480
  } from '@easbot/skills';
217
481
 
218
- setGlobalAdapter({
219
- Path: {
220
- home: '/Users/me',
221
- data: '/Users/me/.local/share/easbot',
222
- config: '...',
223
- state: '...',
224
- cache: '/Users/me/.cache/easbot',
225
- log: '/Users/me/.local/state/easbot/log',
226
- bin: '/Users/me/.local/bin',
482
+ setAgentAdapter({
483
+ global: {
484
+ Path: {
485
+ home: '/Users/me',
486
+ data: '/Users/me/.local/share/easbot',
487
+ config: '/Users/me/.config/easbot',
488
+ state: '/Users/me/.local/state/easbot',
489
+ cache: '/Users/me/.cache/easbot',
490
+ log: '/Users/me/.local/state/easbot/log',
491
+ bin: '/Users/me/.local/bin',
492
+ },
227
493
  },
228
- });
229
-
230
- setInstanceAdapter({
231
- directory: '/repo',
232
- worktree: '/repo',
494
+ instance: {
495
+ directory: '/repo',
496
+ worktree: '/repo',
497
+ },
498
+ // Optional
499
+ subAgentRunner: ...,
500
+ triggerEvent: async (event, input, ctx) => ({ success: true, output: undefined, modified: false }),
233
501
  });
234
502
  ```
235
503
 
236
- When no adapter is set, `@easbot/schools` falls back to `xdg-basedir` + `homedir()`, keeping full backward compatibility with the v1 standalone CLI.
504
+ When no adapter is set, the skills package falls back to `xdg-basedir` + `homedir()`, keeping full backward compatibility with the v1 standalone CLI.
505
+
506
+ **`getHomeDir()` priority** (for test isolation):
507
+ 1. `process.env.EASBOT_TEST_HOME` (**test-only**, highest priority)
508
+ 2. Injected `Global.Path.home`
509
+ 3. `os.homedir()` fallback
237
510
 
238
511
  ## Data Layout
239
512
 
240
- | Path | Purpose |
241
- |---|---|
242
- | `${Global.Path.data}/skills/` | Skills dir loaded by the agent at runtime |
243
- | `${Global.Path.data}/skills/.skill-lock.json` | Global install lockfile (same root as store) |
244
- | `${Global.Path.data}/skills/store/<sourceKey>/` | **Store physical dir** (sourceKey-hashed normalized source; written once by `add`, reused by `update`) |
245
- | `${Global.Path.data}/skills/store/index.json` | **Store defs index** (key = skillName; records registryKey / type / url / skillPath / computedHash) |
246
- | `${Global.Path.cache}/skills/cache/<owner>/<repo>/` | **Cache physical** (remote source download/materialize cache; local source = same as user directory) |
247
- | `<cwd>/.agents/skills/` or `<cwd>/skills/` | Project-level skill directories |
248
- | `<cwd>/skills-lock.json` | Project-level lockfile |
249
- | `<home>/.config/easbot/skills/` | XDG config fallback |
513
+ > When injected, every `getXdgData / getXdgCache / ...` resolves through `Global.Path.*`; the default path uses `xdg-basedir + easbot` segments.
250
514
 
251
- > When delegated from `@easbot/agent`, everything lands under `${Global.Path.data}` sibling to Gateway / MCP / Session / Contact modules.
515
+ | Path | Purpose | Implementation |
516
+ |---|---|---|
517
+ | `${getXdgData()}/skills/` | Skills directory loaded by the agent at runtime | `installer/store.ts` |
518
+ | `${getXdgData()}/skills/.skill-lock.json` | Global install lockfile (same root as store) | `skill-lock.ts` |
519
+ | `${getXdgData()}/skills/store/<sourceKey>/` | **Store physical dir** (sourceKey-hashed normalized source; written once by `add`, reused by `update`) | `installer/store.ts::getStoreDir` |
520
+ | `${getXdgData()}/skills/store/index.json` | **Store defs index** (per-skill registryKey / type / url / skillPath / computedHash) | `installer/store.ts::getStoreDefinitionsFile` |
521
+ | `${getXdgCache()}/skills/cache/<type>/<owner/repo>/` | **Cache physical** (remote source download/materialize cache; local source = same as user directory) | `installer/store.ts::getCacheRepoDir` |
522
+ | `<cwd>/.easbot/skills/<skill>/` | EASBot project-level (not hit by universal agents) | `agents.ts` |
523
+ | `<cwd>/.agents/skills/<skill>/` | Universal agents (claude-code / cursor / gemini-cli etc.) project-level | `agents.ts` |
524
+ | `<cwd>/<agent-glob>/skills/<skill>/` | Each agent's custom project-level (e.g. `~/.trae/skills/`) | `agents.ts` |
525
+ | `<cwd>/skills-lock.json` | Project-level lockfile | `local-lock.ts` |
526
+ | `${getXdgConfig()}/easbot/skills/` | EASBot global skill dir (injected scenario) | `agents.ts::easbot.globalSkillsDir` |
527
+ | `~/.config/easbot/skills/` | EASBot global skill dir (default fallback) | same |
528
+
529
+ > When delegated from `@easbot/agent`, everything lands under `{Global.Path.data}` — sibling to Gateway / MCP / Session / Contact modules.
252
530
 
253
531
  ## External Audit Hooks (skills.sh)
254
532
 
255
- `telemetry.ts` sends telemetry/audit data back to skills.sh (configurable via `SKILLS_API_URL`) for:
533
+ `telemetry.ts` sends telemetry / audit data back to skills.sh (configurable via `SKILLS_API_URL`) for:
534
+
256
535
  - Skill audit (`fetchAuditData` returns per-skill `PartnerAudit` information)
257
- - Security gate check (skipped with `--dangerously-accept-openclaw-risks` flag)
536
+ - Security gate check (skipped with the `--dangerously-accept-openclaw-risks` flag)
537
+
538
+ ## Interaction Conventions (Session 4 refactor)
539
+
540
+ Every interactive flow (select / confirm / multiselect / spinner / intro / outro / cancel / Log) goes through [`@easbot/terminal.Prompt`](../terminal/README.en.md):
541
+
542
+ ```typescript
543
+ import { Prompt, Symbol as Glyph } from '@easbot/terminal';
544
+
545
+ // Cancellation contract: Prompt.cancel returns `never` and exits internally
546
+ const v = await Prompt.select({ message: 'Choose scope', options: [...] });
547
+ if (Prompt.isCancel(v)) await cleanup();
548
+ Prompt.cancel('User cancelled');
549
+
550
+ // Icons centralized (writing ✓✗◆ literals is FORBIDDEN)
551
+ console.log(`${Glyph.statusIcon('success')} Operation succeeded`); // ✓ green
552
+ console.log(`${Glyph.colorize(Glyph.bar.bullet, 'error')} bullet`);
553
+
554
+ // Status logging (colors unified with terminal theme)
555
+ Prompt.Log.info('Installing...');
556
+ Prompt.Log.warn('Warning');
557
+ Prompt.Log.error('Failure');
558
+ Prompt.Log.step('Step');
559
+ Prompt.Log.message('Plain message');
560
+ ```
561
+
562
+ Business code **must not** call `pc.green('✓')` directly, **nor** `console.log(p.theme.error(...))`. Everything routes through `utils/color.ts` (the picocolors-shape **bridge**, kept as a transitional layer) and `Glyph.*` / `Prompt.Log.*`.
258
563
 
259
564
  ## Development
260
565
 
@@ -273,11 +578,12 @@ pnpm test
273
578
  pnpm test:run
274
579
 
275
580
  # Code quality
276
- pnpm biome-lint # biome check .
277
- pnpm biome-fix # biome check --write .
278
- pnpm biome-format # biome format .
581
+ pnpm lint # biome check .
582
+ pnpm lint:fix # biome check --write .
583
+ pnpm format # biome format .
584
+ pnpm format:fix # biome format --write .
279
585
 
280
- # Type check
586
+ # Type-check
281
587
  pnpm type-check
282
588
 
283
589
  # Clean
@@ -287,7 +593,7 @@ pnpm clean
287
593
  ## Publishing
288
594
 
289
595
  ```bash
290
- # Linux /macOS
596
+ # Linux / macOS
291
597
  bash scripts/publish.sh
292
598
 
293
599
  # Windows PowerShell
@@ -300,8 +606,9 @@ pnpm publish --access public --git-checks false --registry https://registry.npmj
300
606
 
301
607
  ## Runtime Notes
302
608
 
303
- - Uses Node built-ins (`fs/promises`, `NODE:OS`, `node:path`, `node:child_process`); **not** browser-compatible.
304
- - Dependencies: `simple-git`, `@clack/prompts`, `picocolors`, `xd-basedir`, `zod`, `yaml`.
609
+ - Uses Node built-ins (`fs/promises`, `node:os`, `node:path`, `node:child_process`); **not** browser-compatible.
610
+ - Dependencies: `simple-git`, `@easbot/terminal` (unified Prompt + theme + icons), `xdg-basedir`, `zod`, `yaml`.
611
+ - **No longer** depends on `@clack/prompts` or `picocolors` — everything converges to `@easbot/terminal` (see Session 4 decisions).
305
612
  - `engines.node >= 22.22.3` — Node 22 LTS recommended.
306
613
 
307
614
  ## License