@rbbtsn0w/adg 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +308 -0
  3. package/bin/adg.ts +758 -0
  4. package/docs/agents-spec.md +132 -0
  5. package/docs/authoring.md +352 -0
  6. package/package.json +50 -0
  7. package/schemas/adg-plugin.schema.json +77 -0
  8. package/schemas/marketplace.schema.json +86 -0
  9. package/schemas/plugin-lock.schema.json +90 -0
  10. package/src/adapters/anthropic.ts +54 -0
  11. package/src/adapters/index.ts +24 -0
  12. package/src/adapters/openai.ts +37 -0
  13. package/src/adapters/reverse.ts +60 -0
  14. package/src/agents/claude.ts +124 -0
  15. package/src/agents/codex.ts +67 -0
  16. package/src/agents/index.ts +12 -0
  17. package/src/agents/registry.ts +30 -0
  18. package/src/agents/types.ts +47 -0
  19. package/src/commands/adapt.ts +36 -0
  20. package/src/commands/import.ts +69 -0
  21. package/src/commands/init.ts +146 -0
  22. package/src/commands/install.ts +411 -0
  23. package/src/commands/link.ts +61 -0
  24. package/src/commands/list.ts +28 -0
  25. package/src/commands/marketplace.ts +198 -0
  26. package/src/commands/migrate.ts +84 -0
  27. package/src/commands/multiselect-skills.ts +137 -0
  28. package/src/commands/remove.ts +136 -0
  29. package/src/commands/select-agents.ts +45 -0
  30. package/src/commands/select-components.ts +66 -0
  31. package/src/commands/select-plugins.ts +28 -0
  32. package/src/commands/select-scope.ts +21 -0
  33. package/src/commands/update.ts +85 -0
  34. package/src/commands/validate.ts +57 -0
  35. package/src/components.ts +90 -0
  36. package/src/deps.ts +64 -0
  37. package/src/fsutil.ts +38 -0
  38. package/src/hash.ts +61 -0
  39. package/src/lock.ts +57 -0
  40. package/src/manifest.ts +113 -0
  41. package/src/marketplace.ts +41 -0
  42. package/src/package.ts +74 -0
  43. package/src/paths.ts +129 -0
  44. package/src/semver.ts +67 -0
  45. package/src/skills.ts +88 -0
  46. package/src/sources.ts +159 -0
  47. package/src/types.ts +140 -0
  48. package/vendor/skills/LICENSE +29 -0
  49. package/vendor/skills/PROVENANCE.md +60 -0
  50. package/vendor/skills/ThirdPartyNoticeText.txt +117 -0
  51. package/vendor/skills/package.json +143 -0
  52. package/vendor/skills/src/add.ts +1999 -0
  53. package/vendor/skills/src/agents.ts +755 -0
  54. package/vendor/skills/src/blob.ts +567 -0
  55. package/vendor/skills/src/cli.ts +387 -0
  56. package/vendor/skills/src/constants.ts +3 -0
  57. package/vendor/skills/src/detect-agent.ts +62 -0
  58. package/vendor/skills/src/find.ts +357 -0
  59. package/vendor/skills/src/frontmatter.ts +16 -0
  60. package/vendor/skills/src/git-tree.ts +36 -0
  61. package/vendor/skills/src/git.ts +277 -0
  62. package/vendor/skills/src/install.ts +91 -0
  63. package/vendor/skills/src/installer.ts +1097 -0
  64. package/vendor/skills/src/list.ts +231 -0
  65. package/vendor/skills/src/local-lock.ts +182 -0
  66. package/vendor/skills/src/plugin-manifest.ts +183 -0
  67. package/vendor/skills/src/prompts/search-multiselect.ts +387 -0
  68. package/vendor/skills/src/providers/index.ts +14 -0
  69. package/vendor/skills/src/providers/registry.ts +51 -0
  70. package/vendor/skills/src/providers/types.ts +97 -0
  71. package/vendor/skills/src/providers/wellknown.ts +804 -0
  72. package/vendor/skills/src/remove.ts +323 -0
  73. package/vendor/skills/src/sanitize.ts +65 -0
  74. package/vendor/skills/src/self-cli.ts +20 -0
  75. package/vendor/skills/src/skill-lock.ts +329 -0
  76. package/vendor/skills/src/skills.ts +316 -0
  77. package/vendor/skills/src/source-parser.ts +438 -0
  78. package/vendor/skills/src/sync.ts +478 -0
  79. package/vendor/skills/src/telemetry.ts +186 -0
  80. package/vendor/skills/src/test-utils.ts +73 -0
  81. package/vendor/skills/src/types.ts +128 -0
  82. package/vendor/skills/src/update-source.ts +90 -0
  83. package/vendor/skills/src/update.ts +749 -0
  84. package/vendor/skills/src/use.ts +675 -0
@@ -0,0 +1,755 @@
1
+ import { homedir } from 'os';
2
+ import { join } from 'path';
3
+ import { existsSync } from 'fs';
4
+ import { xdgConfig } from 'xdg-basedir';
5
+ import type { AgentConfig, AgentType } from './types.ts';
6
+
7
+ const home = homedir();
8
+ // Use xdg-basedir (not env-paths) to match OpenCode/Amp/Goose behavior on all platforms.
9
+ const configHome = xdgConfig ?? join(home, '.config');
10
+ // ADG patch: the universal `.agents/` home. Mirrors getSkillLockPath() and ADG's
11
+ // globalPluginsDir() so the skills domain, its lock, and plugins all share one
12
+ // root: `$XDG_STATE_HOME/.agents` if set, else `~/.agents`. Upstream pointed the
13
+ // universal *global* dir at `$XDG_CONFIG_HOME/agents/skills`, which split the
14
+ // root from its own project dir (`.agents/skills`). See vendor/skills/PROVENANCE.md.
15
+ const agentsHome = join(process.env.XDG_STATE_HOME ?? home, '.agents');
16
+ const codexHome = process.env.CODEX_HOME?.trim() || join(home, '.codex');
17
+ const claudeHome = process.env.CLAUDE_CONFIG_DIR?.trim() || join(home, '.claude');
18
+ const vibeHome = process.env.VIBE_HOME?.trim() || join(home, '.vibe');
19
+ const hermesHome = process.env.HERMES_HOME?.trim() || join(home, '.hermes');
20
+ const autohandHome = process.env.AUTOHAND_HOME?.trim() || join(home, '.autohand');
21
+ const zedAppDataHome = process.env.APPDATA?.trim();
22
+ const zedFlatpakConfigHome = process.env.FLATPAK_XDG_CONFIG_HOME?.trim();
23
+
24
+ export function getOpenClawGlobalSkillsDir(
25
+ homeDir = home,
26
+ pathExists: (path: string) => boolean = existsSync
27
+ ) {
28
+ if (pathExists(join(homeDir, '.openclaw'))) {
29
+ return join(homeDir, '.openclaw/skills');
30
+ }
31
+ if (pathExists(join(homeDir, '.clawdbot'))) {
32
+ return join(homeDir, '.clawdbot/skills');
33
+ }
34
+ if (pathExists(join(homeDir, '.moltbot'))) {
35
+ return join(homeDir, '.moltbot/skills');
36
+ }
37
+ return join(homeDir, '.openclaw/skills');
38
+ }
39
+
40
+ export const agents: Record<AgentType, AgentConfig> = {
41
+ 'aider-desk': {
42
+ name: 'aider-desk',
43
+ displayName: 'AiderDesk',
44
+ skillsDir: '.aider-desk/skills',
45
+ globalSkillsDir: join(home, '.aider-desk/skills'),
46
+ detectInstalled: async () => {
47
+ return existsSync(join(home, '.aider-desk'));
48
+ },
49
+ },
50
+ amp: {
51
+ name: 'amp',
52
+ displayName: 'Amp',
53
+ skillsDir: '.agents/skills',
54
+ globalSkillsDir: join(configHome, 'agents/skills'),
55
+ detectInstalled: async () => {
56
+ return existsSync(join(configHome, 'amp'));
57
+ },
58
+ },
59
+ antigravity: {
60
+ name: 'antigravity',
61
+ displayName: 'Antigravity',
62
+ skillsDir: '.agents/skills',
63
+ globalSkillsDir: join(home, '.gemini/antigravity/skills'),
64
+ detectInstalled: async () => {
65
+ return existsSync(join(home, '.gemini/antigravity'));
66
+ },
67
+ },
68
+ 'antigravity-cli': {
69
+ name: 'antigravity-cli',
70
+ displayName: 'Antigravity CLI',
71
+ skillsDir: '.agents/skills',
72
+ globalSkillsDir: join(home, '.gemini/antigravity-cli/skills'),
73
+ detectInstalled: async () => {
74
+ return existsSync(join(home, '.gemini/antigravity-cli'));
75
+ },
76
+ },
77
+ astrbot: {
78
+ name: 'astrbot',
79
+ displayName: 'AstrBot',
80
+ skillsDir: 'data/skills',
81
+ globalSkillsDir: join(home, '.astrbot/data/skills'),
82
+ detectInstalled: async () => {
83
+ return existsSync(join(process.cwd(), 'data/skills')) || existsSync(join(home, '.astrbot'));
84
+ },
85
+ },
86
+ 'autohand-code': {
87
+ name: 'autohand-code',
88
+ displayName: 'Autohand Code CLI',
89
+ skillsDir: '.autohand/skills',
90
+ globalSkillsDir: join(autohandHome, 'skills'),
91
+ detectInstalled: async () => {
92
+ return existsSync(autohandHome);
93
+ },
94
+ },
95
+ augment: {
96
+ name: 'augment',
97
+ displayName: 'Augment',
98
+ skillsDir: '.augment/skills',
99
+ globalSkillsDir: join(home, '.augment/skills'),
100
+ detectInstalled: async () => {
101
+ return existsSync(join(home, '.augment'));
102
+ },
103
+ },
104
+ bob: {
105
+ name: 'bob',
106
+ displayName: 'IBM Bob',
107
+ skillsDir: '.bob/skills',
108
+ globalSkillsDir: join(home, '.bob/skills'),
109
+ detectInstalled: async () => {
110
+ return existsSync(join(home, '.bob'));
111
+ },
112
+ },
113
+ 'claude-code': {
114
+ name: 'claude-code',
115
+ displayName: 'Claude Code',
116
+ skillsDir: '.claude/skills',
117
+ globalSkillsDir: join(claudeHome, 'skills'),
118
+ detectInstalled: async () => {
119
+ return existsSync(claudeHome);
120
+ },
121
+ },
122
+ openclaw: {
123
+ name: 'openclaw',
124
+ displayName: 'OpenClaw',
125
+ skillsDir: 'skills',
126
+ globalSkillsDir: getOpenClawGlobalSkillsDir(),
127
+ detectInstalled: async () => {
128
+ return (
129
+ existsSync(join(home, '.openclaw')) ||
130
+ existsSync(join(home, '.clawdbot')) ||
131
+ existsSync(join(home, '.moltbot'))
132
+ );
133
+ },
134
+ },
135
+ cline: {
136
+ name: 'cline',
137
+ displayName: 'Cline',
138
+ skillsDir: '.agents/skills',
139
+ globalSkillsDir: join(home, '.agents', 'skills'),
140
+ detectInstalled: async () => {
141
+ return existsSync(join(home, '.cline'));
142
+ },
143
+ },
144
+ 'codearts-agent': {
145
+ name: 'codearts-agent',
146
+ displayName: 'CodeArts Agent',
147
+ skillsDir: '.codeartsdoer/skills',
148
+ globalSkillsDir: join(home, '.codeartsdoer/skills'),
149
+ detectInstalled: async () => {
150
+ return existsSync(join(home, '.codeartsdoer'));
151
+ },
152
+ },
153
+ codebuddy: {
154
+ name: 'codebuddy',
155
+ displayName: 'CodeBuddy',
156
+ skillsDir: '.codebuddy/skills',
157
+ globalSkillsDir: join(home, '.codebuddy/skills'),
158
+ detectInstalled: async () => {
159
+ return existsSync(join(process.cwd(), '.codebuddy')) || existsSync(join(home, '.codebuddy'));
160
+ },
161
+ },
162
+ codemaker: {
163
+ name: 'codemaker',
164
+ displayName: 'Codemaker',
165
+ skillsDir: '.codemaker/skills',
166
+ globalSkillsDir: join(home, '.codemaker/skills'),
167
+ detectInstalled: async () => {
168
+ return existsSync(join(home, '.codemaker'));
169
+ },
170
+ },
171
+ codestudio: {
172
+ name: 'codestudio',
173
+ displayName: 'Code Studio',
174
+ skillsDir: '.codestudio/skills',
175
+ globalSkillsDir: join(home, '.codestudio/skills'),
176
+ detectInstalled: async () => {
177
+ return existsSync(join(home, '.codestudio'));
178
+ },
179
+ },
180
+ codex: {
181
+ name: 'codex',
182
+ displayName: 'Codex',
183
+ skillsDir: '.agents/skills',
184
+ globalSkillsDir: join(codexHome, 'skills'),
185
+ detectInstalled: async () => {
186
+ return existsSync(codexHome) || existsSync('/etc/codex');
187
+ },
188
+ },
189
+ 'command-code': {
190
+ name: 'command-code',
191
+ displayName: 'Command Code',
192
+ skillsDir: '.commandcode/skills',
193
+ globalSkillsDir: join(home, '.commandcode/skills'),
194
+ detectInstalled: async () => {
195
+ return existsSync(join(home, '.commandcode'));
196
+ },
197
+ },
198
+ continue: {
199
+ name: 'continue',
200
+ displayName: 'Continue',
201
+ skillsDir: '.continue/skills',
202
+ globalSkillsDir: join(home, '.continue/skills'),
203
+ detectInstalled: async () => {
204
+ return existsSync(join(process.cwd(), '.continue')) || existsSync(join(home, '.continue'));
205
+ },
206
+ },
207
+ cortex: {
208
+ name: 'cortex',
209
+ displayName: 'Cortex Code',
210
+ skillsDir: '.cortex/skills',
211
+ globalSkillsDir: join(home, '.snowflake/cortex/skills'),
212
+ detectInstalled: async () => {
213
+ return existsSync(join(home, '.snowflake/cortex'));
214
+ },
215
+ },
216
+ crush: {
217
+ name: 'crush',
218
+ displayName: 'Crush',
219
+ skillsDir: '.crush/skills',
220
+ globalSkillsDir: join(home, '.config/crush/skills'),
221
+ detectInstalled: async () => {
222
+ return existsSync(join(home, '.config/crush'));
223
+ },
224
+ },
225
+ cursor: {
226
+ name: 'cursor',
227
+ displayName: 'Cursor',
228
+ skillsDir: '.agents/skills',
229
+ globalSkillsDir: join(home, '.cursor/skills'),
230
+ detectInstalled: async () => {
231
+ return existsSync(join(home, '.cursor'));
232
+ },
233
+ },
234
+ deepagents: {
235
+ name: 'deepagents',
236
+ displayName: 'Deep Agents',
237
+ skillsDir: '.agents/skills',
238
+ globalSkillsDir: join(home, '.deepagents/agent/skills'),
239
+ detectInstalled: async () => {
240
+ return existsSync(join(home, '.deepagents'));
241
+ },
242
+ },
243
+ devin: {
244
+ name: 'devin',
245
+ displayName: 'Devin for Terminal',
246
+ skillsDir: '.devin/skills',
247
+ globalSkillsDir: join(configHome, 'devin/skills'),
248
+ detectInstalled: async () => {
249
+ return existsSync(join(configHome, 'devin'));
250
+ },
251
+ },
252
+ dexto: {
253
+ name: 'dexto',
254
+ displayName: 'Dexto',
255
+ skillsDir: '.agents/skills',
256
+ globalSkillsDir: join(home, '.agents/skills'),
257
+ showInUniversalPrompt: false,
258
+ detectInstalled: async () => {
259
+ return existsSync(join(home, '.dexto'));
260
+ },
261
+ },
262
+ droid: {
263
+ name: 'droid',
264
+ displayName: 'Droid',
265
+ skillsDir: '.factory/skills',
266
+ globalSkillsDir: join(home, '.factory/skills'),
267
+ detectInstalled: async () => {
268
+ return existsSync(join(home, '.factory'));
269
+ },
270
+ },
271
+ firebender: {
272
+ name: 'firebender',
273
+ displayName: 'Firebender',
274
+ skillsDir: '.agents/skills',
275
+ globalSkillsDir: join(home, '.firebender/skills'),
276
+ showInUniversalPrompt: false,
277
+ detectInstalled: async () => {
278
+ return existsSync(join(home, '.firebender'));
279
+ },
280
+ },
281
+ forgecode: {
282
+ name: 'forgecode',
283
+ displayName: 'ForgeCode',
284
+ skillsDir: '.forge/skills',
285
+ globalSkillsDir: join(home, '.forge/skills'),
286
+ detectInstalled: async () => {
287
+ return existsSync(join(home, '.forge'));
288
+ },
289
+ },
290
+ 'gemini-cli': {
291
+ name: 'gemini-cli',
292
+ displayName: 'Gemini CLI',
293
+ skillsDir: '.agents/skills',
294
+ globalSkillsDir: join(home, '.gemini/skills'),
295
+ detectInstalled: async () => {
296
+ return existsSync(join(home, '.gemini'));
297
+ },
298
+ },
299
+ 'github-copilot': {
300
+ name: 'github-copilot',
301
+ displayName: 'GitHub Copilot',
302
+ skillsDir: '.agents/skills',
303
+ globalSkillsDir: join(home, '.copilot/skills'),
304
+ detectInstalled: async () => {
305
+ return existsSync(join(home, '.copilot'));
306
+ },
307
+ },
308
+ goose: {
309
+ name: 'goose',
310
+ displayName: 'Goose',
311
+ skillsDir: '.goose/skills',
312
+ globalSkillsDir: join(configHome, 'goose/skills'),
313
+ detectInstalled: async () => {
314
+ return existsSync(join(configHome, 'goose'));
315
+ },
316
+ },
317
+ 'hermes-agent': {
318
+ name: 'hermes-agent',
319
+ displayName: 'Hermes Agent',
320
+ skillsDir: '.hermes/skills',
321
+ globalSkillsDir: join(hermesHome, 'skills'),
322
+ detectInstalled: async () => {
323
+ return existsSync(hermesHome);
324
+ },
325
+ },
326
+ 'inference-sh': {
327
+ name: 'inference-sh',
328
+ displayName: 'inference.sh',
329
+ skillsDir: '.inferencesh/skills',
330
+ globalSkillsDir: join(home, '.inferencesh/skills'),
331
+ detectInstalled: async () => {
332
+ return existsSync(join(home, '.inferencesh'));
333
+ },
334
+ },
335
+ jazz: {
336
+ name: 'jazz',
337
+ displayName: 'Jazz',
338
+ skillsDir: '.jazz/skills',
339
+ globalSkillsDir: join(home, '.jazz/skills'),
340
+ detectInstalled: async () => {
341
+ return existsSync(join(home, '.jazz')) || existsSync(join(process.cwd(), '.jazz'));
342
+ },
343
+ },
344
+ junie: {
345
+ name: 'junie',
346
+ displayName: 'Junie',
347
+ skillsDir: '.junie/skills',
348
+ globalSkillsDir: join(home, '.junie/skills'),
349
+ detectInstalled: async () => {
350
+ return existsSync(join(home, '.junie'));
351
+ },
352
+ },
353
+ 'iflow-cli': {
354
+ name: 'iflow-cli',
355
+ displayName: 'iFlow CLI',
356
+ skillsDir: '.iflow/skills',
357
+ globalSkillsDir: join(home, '.iflow/skills'),
358
+ detectInstalled: async () => {
359
+ return existsSync(join(home, '.iflow'));
360
+ },
361
+ },
362
+ kilo: {
363
+ name: 'kilo',
364
+ displayName: 'Kilo Code',
365
+ skillsDir: '.kilocode/skills',
366
+ globalSkillsDir: join(home, '.kilocode/skills'),
367
+ detectInstalled: async () => {
368
+ return existsSync(join(home, '.kilocode'));
369
+ },
370
+ },
371
+ 'kimi-code-cli': {
372
+ name: 'kimi-code-cli',
373
+ displayName: 'Kimi Code CLI',
374
+ skillsDir: '.agents/skills',
375
+ globalSkillsDir: join(home, '.agents/skills'),
376
+ detectInstalled: async () => {
377
+ return existsSync(join(home, '.kimi-code')) || existsSync(join(home, '.kimi'));
378
+ },
379
+ },
380
+ 'kiro-cli': {
381
+ name: 'kiro-cli',
382
+ displayName: 'Kiro CLI',
383
+ skillsDir: '.kiro/skills',
384
+ globalSkillsDir: join(home, '.kiro/skills'),
385
+ detectInstalled: async () => {
386
+ return existsSync(join(home, '.kiro'));
387
+ },
388
+ },
389
+ kode: {
390
+ name: 'kode',
391
+ displayName: 'Kode',
392
+ skillsDir: '.kode/skills',
393
+ globalSkillsDir: join(home, '.kode/skills'),
394
+ detectInstalled: async () => {
395
+ return existsSync(join(home, '.kode'));
396
+ },
397
+ },
398
+ lingma: {
399
+ name: 'lingma',
400
+ displayName: 'Lingma',
401
+ skillsDir: '.lingma/skills',
402
+ globalSkillsDir: join(home, '.lingma/skills'),
403
+ detectInstalled: async () => {
404
+ return existsSync(join(home, '.lingma'));
405
+ },
406
+ },
407
+ loaf: {
408
+ name: 'loaf',
409
+ displayName: 'Loaf',
410
+ skillsDir: '.agents/skills',
411
+ globalSkillsDir: join(home, '.agents/skills'),
412
+ showInUniversalPrompt: false,
413
+ detectInstalled: async () => {
414
+ return existsSync(join(home, '.loaf'));
415
+ },
416
+ },
417
+ mcpjam: {
418
+ name: 'mcpjam',
419
+ displayName: 'MCPJam',
420
+ skillsDir: '.mcpjam/skills',
421
+ globalSkillsDir: join(home, '.mcpjam/skills'),
422
+ detectInstalled: async () => {
423
+ return existsSync(join(home, '.mcpjam'));
424
+ },
425
+ },
426
+ 'mistral-vibe': {
427
+ name: 'mistral-vibe',
428
+ displayName: 'Mistral Vibe',
429
+ skillsDir: '.vibe/skills',
430
+ globalSkillsDir: join(vibeHome, 'skills'),
431
+ detectInstalled: async () => {
432
+ return existsSync(vibeHome);
433
+ },
434
+ },
435
+ moxby: {
436
+ name: 'moxby',
437
+ displayName: 'Moxby',
438
+ skillsDir: '.moxby/skills',
439
+ globalSkillsDir: join(home, '.moxby/skills'),
440
+ detectInstalled: async () => {
441
+ return existsSync(join(home, '.moxby'));
442
+ },
443
+ },
444
+ mux: {
445
+ name: 'mux',
446
+ displayName: 'Mux',
447
+ skillsDir: '.mux/skills',
448
+ globalSkillsDir: join(home, '.mux/skills'),
449
+ detectInstalled: async () => {
450
+ return existsSync(join(home, '.mux'));
451
+ },
452
+ },
453
+ opencode: {
454
+ name: 'opencode',
455
+ displayName: 'OpenCode',
456
+ skillsDir: '.agents/skills',
457
+ globalSkillsDir: join(configHome, 'opencode/skills'),
458
+ detectInstalled: async () => {
459
+ return existsSync(join(configHome, 'opencode'));
460
+ },
461
+ },
462
+ openhands: {
463
+ name: 'openhands',
464
+ displayName: 'OpenHands',
465
+ skillsDir: '.openhands/skills',
466
+ globalSkillsDir: join(home, '.openhands/skills'),
467
+ detectInstalled: async () => {
468
+ return existsSync(join(home, '.openhands'));
469
+ },
470
+ },
471
+ ona: {
472
+ name: 'ona',
473
+ displayName: 'Ona',
474
+ skillsDir: '.ona/skills',
475
+ globalSkillsDir: join(home, '.ona/skills'),
476
+ detectInstalled: async () => {
477
+ return existsSync(join(home, '.ona'));
478
+ },
479
+ },
480
+ pi: {
481
+ name: 'pi',
482
+ displayName: 'Pi',
483
+ skillsDir: '.pi/skills',
484
+ globalSkillsDir: join(home, '.pi/agent/skills'),
485
+ detectInstalled: async () => {
486
+ return existsSync(join(home, '.pi/agent'));
487
+ },
488
+ },
489
+ qoder: {
490
+ name: 'qoder',
491
+ displayName: 'Qoder',
492
+ skillsDir: '.qoder/skills',
493
+ globalSkillsDir: join(home, '.qoder/skills'),
494
+ detectInstalled: async () => {
495
+ return existsSync(join(home, '.qoder'));
496
+ },
497
+ },
498
+ 'qoder-cn': {
499
+ name: 'qoder-cn',
500
+ displayName: 'Qoder CN',
501
+ skillsDir: '.qoder/skills',
502
+ globalSkillsDir: join(home, '.qoder-cn/skills'),
503
+ detectInstalled: async () => {
504
+ return existsSync(join(home, '.qoder-cn'));
505
+ },
506
+ },
507
+ 'qwen-code': {
508
+ name: 'qwen-code',
509
+ displayName: 'Qwen Code',
510
+ skillsDir: '.qwen/skills',
511
+ globalSkillsDir: join(home, '.qwen/skills'),
512
+ detectInstalled: async () => {
513
+ return existsSync(join(home, '.qwen'));
514
+ },
515
+ },
516
+ replit: {
517
+ name: 'replit',
518
+ displayName: 'Replit',
519
+ skillsDir: '.agents/skills',
520
+ globalSkillsDir: join(configHome, 'agents/skills'),
521
+ showInUniversalList: false,
522
+ detectInstalled: async () => {
523
+ return existsSync(join(process.cwd(), '.replit'));
524
+ },
525
+ },
526
+ reasonix: {
527
+ name: 'reasonix',
528
+ displayName: 'Reasonix',
529
+ skillsDir: '.reasonix/skills',
530
+ globalSkillsDir: join(home, '.reasonix/skills'),
531
+ detectInstalled: async () => {
532
+ return existsSync(join(home, '.reasonix'));
533
+ },
534
+ },
535
+ rovodev: {
536
+ name: 'rovodev',
537
+ displayName: 'Rovo Dev',
538
+ skillsDir: '.rovodev/skills',
539
+ globalSkillsDir: join(home, '.rovodev/skills'),
540
+ detectInstalled: async () => {
541
+ return existsSync(join(home, '.rovodev'));
542
+ },
543
+ },
544
+ roo: {
545
+ name: 'roo',
546
+ displayName: 'Roo Code',
547
+ skillsDir: '.roo/skills',
548
+ globalSkillsDir: join(home, '.roo/skills'),
549
+ detectInstalled: async () => {
550
+ return existsSync(join(home, '.roo'));
551
+ },
552
+ },
553
+ 'tabnine-cli': {
554
+ name: 'tabnine-cli',
555
+ displayName: 'Tabnine CLI',
556
+ skillsDir: '.tabnine/agent/skills',
557
+ globalSkillsDir: join(home, '.tabnine/agent/skills'),
558
+ detectInstalled: async () => {
559
+ return existsSync(join(home, '.tabnine'));
560
+ },
561
+ },
562
+ terramind: {
563
+ name: 'terramind',
564
+ displayName: 'Terramind',
565
+ skillsDir: '.terramind/skills',
566
+ globalSkillsDir: join(home, '.terramind/skills'),
567
+ detectInstalled: async () => {
568
+ return existsSync(join(home, '.terramind'));
569
+ },
570
+ },
571
+ tinycloud: {
572
+ name: 'tinycloud',
573
+ displayName: 'Tinycloud',
574
+ skillsDir: '.tinycloud/skills',
575
+ globalSkillsDir: join(home, '.tinycloud/skills'),
576
+ detectInstalled: async () => {
577
+ return existsSync(join(home, '.tinycloud'));
578
+ },
579
+ },
580
+ trae: {
581
+ name: 'trae',
582
+ displayName: 'Trae',
583
+ skillsDir: '.trae/skills',
584
+ globalSkillsDir: join(home, '.trae/skills'),
585
+ detectInstalled: async () => {
586
+ return existsSync(join(home, '.trae'));
587
+ },
588
+ },
589
+ 'trae-cn': {
590
+ name: 'trae-cn',
591
+ displayName: 'Trae CN',
592
+ skillsDir: '.trae/skills',
593
+ globalSkillsDir: join(home, '.trae-cn/skills'),
594
+ detectInstalled: async () => {
595
+ return existsSync(join(home, '.trae-cn'));
596
+ },
597
+ },
598
+ warp: {
599
+ name: 'warp',
600
+ displayName: 'Warp',
601
+ skillsDir: '.agents/skills',
602
+ globalSkillsDir: join(home, '.agents/skills'),
603
+ detectInstalled: async () => {
604
+ return existsSync(join(home, '.warp'));
605
+ },
606
+ },
607
+ windsurf: {
608
+ name: 'windsurf',
609
+ displayName: 'Windsurf',
610
+ skillsDir: '.windsurf/skills',
611
+ globalSkillsDir: join(home, '.codeium/windsurf/skills'),
612
+ detectInstalled: async () => {
613
+ return existsSync(join(home, '.codeium/windsurf'));
614
+ },
615
+ },
616
+ zed: {
617
+ name: 'zed',
618
+ displayName: 'Zed',
619
+ skillsDir: '.agents/skills',
620
+ globalSkillsDir: join(home, '.agents/skills'),
621
+ detectInstalled: async () => {
622
+ // Per Zed's config_dir() in crates/paths/src/paths.rs.
623
+ return (
624
+ existsSync(join(configHome, 'zed')) ||
625
+ (!!zedAppDataHome && existsSync(join(zedAppDataHome, 'Zed'))) ||
626
+ (!!zedFlatpakConfigHome && existsSync(join(zedFlatpakConfigHome, 'zed')))
627
+ );
628
+ },
629
+ },
630
+ zencoder: {
631
+ name: 'zencoder',
632
+ displayName: 'Zencoder',
633
+ skillsDir: '.zencoder/skills',
634
+ globalSkillsDir: join(home, '.zencoder/skills'),
635
+ detectInstalled: async () => {
636
+ return existsSync(join(home, '.zencoder'));
637
+ },
638
+ },
639
+ zenflow: {
640
+ name: 'zenflow',
641
+ displayName: 'Zenflow',
642
+ skillsDir: '.zencoder/skills',
643
+ globalSkillsDir: join(home, '.zencoder/skills'),
644
+ detectInstalled: async () => {
645
+ return existsSync(join(home, '.zencoder'));
646
+ },
647
+ },
648
+ neovate: {
649
+ name: 'neovate',
650
+ displayName: 'Neovate',
651
+ skillsDir: '.neovate/skills',
652
+ globalSkillsDir: join(home, '.neovate/skills'),
653
+ detectInstalled: async () => {
654
+ return existsSync(join(home, '.neovate'));
655
+ },
656
+ },
657
+ pochi: {
658
+ name: 'pochi',
659
+ displayName: 'Pochi',
660
+ skillsDir: '.pochi/skills',
661
+ globalSkillsDir: join(home, '.pochi/skills'),
662
+ detectInstalled: async () => {
663
+ return existsSync(join(home, '.pochi'));
664
+ },
665
+ },
666
+ promptscript: {
667
+ name: 'promptscript',
668
+ displayName: 'PromptScript',
669
+ skillsDir: '.agents/skills',
670
+ globalSkillsDir: undefined,
671
+ showInUniversalPrompt: false,
672
+ detectInstalled: async () => {
673
+ return (
674
+ existsSync(join(process.cwd(), '.promptscript')) ||
675
+ existsSync(join(process.cwd(), 'promptscript.yaml'))
676
+ );
677
+ },
678
+ },
679
+ adal: {
680
+ name: 'adal',
681
+ displayName: 'AdaL',
682
+ skillsDir: '.adal/skills',
683
+ globalSkillsDir: join(home, '.adal/skills'),
684
+ detectInstalled: async () => {
685
+ return existsSync(join(home, '.adal'));
686
+ },
687
+ },
688
+ universal: {
689
+ name: 'universal',
690
+ displayName: 'Universal',
691
+ skillsDir: '.agents/skills',
692
+ globalSkillsDir: join(agentsHome, 'skills'), // ADG patch: was join(configHome, 'agents/skills')
693
+ showInUniversalList: false,
694
+ detectInstalled: async () => false,
695
+ },
696
+ };
697
+
698
+ export async function detectInstalledAgents(): Promise<AgentType[]> {
699
+ const results = await Promise.all(
700
+ Object.entries(agents).map(async ([type, config]) => ({
701
+ type: type as AgentType,
702
+ installed: await config.detectInstalled(),
703
+ }))
704
+ );
705
+ return results.filter((r) => r.installed).map((r) => r.type);
706
+ }
707
+
708
+ export function getAgentConfig(type: AgentType): AgentConfig {
709
+ return agents[type];
710
+ }
711
+
712
+ /**
713
+ * Returns agents that use the universal .agents/skills directory.
714
+ * These agents share a common skill location and don't need symlinks.
715
+ * Agents with showInUniversalList: false are excluded.
716
+ */
717
+ export function getUniversalAgents(): AgentType[] {
718
+ return (Object.entries(agents) as [AgentType, AgentConfig][])
719
+ .filter(
720
+ ([_, config]) => config.skillsDir === '.agents/skills' && config.showInUniversalList !== false
721
+ )
722
+ .map(([type]) => type);
723
+ }
724
+
725
+ /**
726
+ * Returns the subset of universal agents shown in the interactive locked section.
727
+ * All universal agents are still installed; this only keeps the prompt readable.
728
+ */
729
+ export function getVisibleUniversalAgents(): AgentType[] {
730
+ return (Object.entries(agents) as [AgentType, AgentConfig][])
731
+ .filter(
732
+ ([_, config]) =>
733
+ config.skillsDir === '.agents/skills' &&
734
+ config.showInUniversalList !== false &&
735
+ config.showInUniversalPrompt !== false
736
+ )
737
+ .map(([type]) => type);
738
+ }
739
+
740
+ /**
741
+ * Returns agents that use agent-specific skill directories (not universal).
742
+ * These agents need symlinks from the canonical .agents/skills location.
743
+ */
744
+ export function getNonUniversalAgents(): AgentType[] {
745
+ return (Object.entries(agents) as [AgentType, AgentConfig][])
746
+ .filter(([_, config]) => config.skillsDir !== '.agents/skills')
747
+ .map(([type]) => type);
748
+ }
749
+
750
+ /**
751
+ * Check if an agent uses the universal .agents/skills directory.
752
+ */
753
+ export function isUniversalAgent(type: AgentType): boolean {
754
+ return agents[type].skillsDir === '.agents/skills';
755
+ }