foliko 1.1.36 → 1.1.39

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 (168) hide show
  1. package/.agent/agents/network-requester.md +44 -0
  2. package/.agent/agents/poster-designer.md +52 -0
  3. package/.agent/agents/ui-designer.md +1 -1
  4. package/.agent/data/default.json +23 -407
  5. package/.agent/data/email/processed-emails.json +1 -0
  6. package/.agent/data/plugins-state.json +103 -200
  7. package/.agent/data/scheduler/tasks.json +1 -86
  8. package/.agent/data/web/web-config.json +5 -0
  9. package/.agent/data/weixin/images/file_1776188148383jpg +0 -0
  10. package/.agent/data/weixin/images/file_1776188458326.jpg +0 -0
  11. package/.agent/data/weixin/images/file_1776188689423.jpg +0 -0
  12. package/.agent/data/weixin/images/file_1776188813604.jpg +0 -0
  13. package/.agent/data/weixin/images/file_1776189097450.jpg +0 -0
  14. package/.agent/data/weixin/videos/file_1776188318431.mp4 +0 -0
  15. package/.agent/mcp_config.json +4 -17
  16. package/.agent/memory/user/mof6gk94-kneeuh.md +9 -0
  17. package/.agent/package.json +8 -0
  18. package/.agent/plugins/marknative/README.md +134 -0
  19. package/.agent/plugins/marknative/fonts/SegoeUI Emoji.ttf +0 -0
  20. package/.agent/plugins/marknative/fonts.zip +0 -0
  21. package/.agent/plugins/marknative/index.js +256 -0
  22. package/.agent/plugins/marknative/package.json +12 -0
  23. package/.agent/plugins/test-plugin.py +99 -0
  24. package/.agent/plugins.json +11 -5
  25. package/.agent/python-scripts/test_sample.py +24 -0
  26. package/.agent/sessions/cli_default.json +2415 -349
  27. package/.agent/sessions/default.json +82 -0
  28. package/.agent/sessions/qq_c2c_D960F12877541624D7B2C836110B3D0F.json +25 -0
  29. package/.agent/sessions/test-clean.json +26 -0
  30. package/.agent/sessions/test-compress.json +1462 -0
  31. package/.agent/sessions/test-session.json +13 -0
  32. package/.agent/sessions/weixin_test.json +22 -0
  33. package/.agent/sessions/weixin_test_user_123.json +11 -0
  34. package/.agent/skills/agent-browser/SKILL.md +311 -0
  35. package/.agent/skills/agent-browser/TEST_PLAN.md +200 -0
  36. package/.agent/skills/sysinfo/SKILL.md +38 -0
  37. package/.agent/skills/sysinfo/system-info.sh +130 -0
  38. package/.agent/skills/workflow/SKILL.md +324 -0
  39. package/.agent/test-agent.js +35 -0
  40. package/.agent/weixin.json +6 -0
  41. package/.agent/workflows/email-digest.json +50 -0
  42. package/.agent/workflows/file-backup.json +21 -0
  43. package/.agent/workflows/get-ip-notify.json +32 -0
  44. package/.agent/workflows/news-aggregator.json +93 -0
  45. package/.agent/workflows/news-dashboard-v2.json +94 -0
  46. package/.agent/workflows/notification-batch.json +32 -0
  47. package/.claude/settings.local.json +2 -1
  48. package/.env.example +56 -56
  49. package/README.md +441 -441
  50. package/cli/src/utils/debounce.js +6 -3
  51. package/docs/qq-bot.md +976 -0
  52. package/package.json +3 -1
  53. package/plugins/qq-plugin.js +939 -0
  54. package/plugins/scheduler-plugin.js +17 -17
  55. package/skills/find-skills/AGENTS.md +162 -162
  56. package/skills/find-skills/SKILL.md +133 -133
  57. package/src/core/agent-chat.js +11 -6
  58. package/temp_img.md +1 -0
  59. package/website_v2/styles/animations.css +7 -7
  60. package/.agent/.shared/ui-ux-pro-max/data/charts.csv +0 -26
  61. package/.agent/.shared/ui-ux-pro-max/data/colors.csv +0 -97
  62. package/.agent/.shared/ui-ux-pro-max/data/icons.csv +0 -101
  63. package/.agent/.shared/ui-ux-pro-max/data/landing.csv +0 -31
  64. package/.agent/.shared/ui-ux-pro-max/data/products.csv +0 -97
  65. package/.agent/.shared/ui-ux-pro-max/data/prompts.csv +0 -24
  66. package/.agent/.shared/ui-ux-pro-max/data/react-performance.csv +0 -45
  67. package/.agent/.shared/ui-ux-pro-max/data/stacks/flutter.csv +0 -53
  68. package/.agent/.shared/ui-ux-pro-max/data/stacks/html-tailwind.csv +0 -56
  69. package/.agent/.shared/ui-ux-pro-max/data/stacks/jetpack-compose.csv +0 -53
  70. package/.agent/.shared/ui-ux-pro-max/data/stacks/nextjs.csv +0 -53
  71. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxt-ui.csv +0 -51
  72. package/.agent/.shared/ui-ux-pro-max/data/stacks/nuxtjs.csv +0 -59
  73. package/.agent/.shared/ui-ux-pro-max/data/stacks/react-native.csv +0 -52
  74. package/.agent/.shared/ui-ux-pro-max/data/stacks/react.csv +0 -54
  75. package/.agent/.shared/ui-ux-pro-max/data/stacks/shadcn.csv +0 -61
  76. package/.agent/.shared/ui-ux-pro-max/data/stacks/svelte.csv +0 -54
  77. package/.agent/.shared/ui-ux-pro-max/data/stacks/swiftui.csv +0 -51
  78. package/.agent/.shared/ui-ux-pro-max/data/stacks/vue.csv +0 -50
  79. package/.agent/.shared/ui-ux-pro-max/data/styles.csv +0 -59
  80. package/.agent/.shared/ui-ux-pro-max/data/typography.csv +0 -58
  81. package/.agent/.shared/ui-ux-pro-max/data/ui-reasoning.csv +0 -101
  82. package/.agent/.shared/ui-ux-pro-max/data/ux-guidelines.csv +0 -100
  83. package/.agent/.shared/ui-ux-pro-max/data/web-interface.csv +0 -31
  84. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/core.cpython-313.pyc +0 -0
  85. package/.agent/.shared/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-313.pyc +0 -0
  86. package/.agent/.shared/ui-ux-pro-max/scripts/core.py +0 -258
  87. package/.agent/.shared/ui-ux-pro-max/scripts/design_system.py +0 -1067
  88. package/.agent/.shared/ui-ux-pro-max/scripts/search.py +0 -106
  89. package/.agent/ARCHITECTURE.md +0 -288
  90. package/.agent/data/ambient/goals.json +0 -1
  91. package/.agent/data/puppeteer-sessions/undefined.json +0 -6
  92. package/.agent/data/weixin-media/2026-04-08/img_1775618677512.jpg +0 -0
  93. package/.agent/data/weixin-media/2026-04-08/img_1775619073340.jpg +0 -0
  94. package/.agent/data/weixin-media/2026-04-08/img_1775619097536.jpg +0 -0
  95. package/.agent/data/weixin-media/2026-04-08/img_1775619209388.jpg +0 -0
  96. package/.agent/memory/feedback/mnygjgox-ualjip.md +0 -11
  97. package/.agent/memory/feedback/mnzugpej-esdwsr.md +0 -9
  98. package/.agent/memory/feedback/mo2quxke-saxs56.md +0 -9
  99. package/.agent/memory/feedback/mo9l6nw9-sm1ye2.md +0 -13
  100. package/.agent/memory/feedback/mo9uxkb3-bbxz3x.md +0 -9
  101. package/.agent/memory/feedback/mo9wpqy0-ftsez9.md +0 -13
  102. package/.agent/memory/feedback/mo9x2ps4-p7huqq.md +0 -11
  103. package/.agent/memory/feedback/mo9x2uay-z7ndjn.md +0 -9
  104. package/.agent/memory/feedback/mo9x2y7d-9wecyx.md +0 -9
  105. package/.agent/memory/feedback/mo9x39q3-nn7myt.md +0 -9
  106. package/.agent/memory/feedback/mo9xfir9-4g8a8j.md +0 -9
  107. package/.agent/memory/feedback/mo9xfui8-ujqrc6.md +0 -9
  108. package/.agent/memory/feedback/mocnx1wx-qtxxlh.md +0 -9
  109. package/.agent/memory/project/mnqx54u5-loqtoe.md +0 -9
  110. package/.agent/memory/project/mnqx84cv-mx6dmd.md +0 -9
  111. package/.agent/memory/project/mnsacuyr-hgtk5n.md +0 -20
  112. package/.agent/memory/project/mnu5hy2x-bjsg7u.md +0 -9
  113. package/.agent/memory/project/mny28ot4-8qe9au.md +0 -9
  114. package/.agent/memory/project/mnztftxj-af82rh.md +0 -9
  115. package/.agent/memory/project/mo0y04d0-bmaefl.md +0 -9
  116. package/.agent/memory/project/mo2iztxb-3c7v81.md +0 -9
  117. package/.agent/memory/project/mo2ssa5x-tpi1p3.md +0 -9
  118. package/.agent/memory/reference/mnre3cww-penbo1.md +0 -9
  119. package/.agent/memory/reference/mns9wn48-luerua.md +0 -14
  120. package/.agent/memory/reference/mns9yz5c-thc2s0.md +0 -16
  121. package/.agent/memory/reference/mnsfy4um-910f1o.md +0 -23
  122. package/.agent/memory/reference/mnsg37dp-lmfj18.md +0 -32
  123. package/.agent/memory/reference/mnsll60q-0j911u.md +0 -36
  124. package/.agent/memory/reference/mnsmlb5y-nej31u.md +0 -16
  125. package/.agent/memory/reference/mnssle72-yrot96.md +0 -9
  126. package/.agent/memory/reference/mnygj8nb-bjthmc.md +0 -20
  127. package/.agent/memory/reference/mnzfvs4m-ufyg9a.md +0 -12
  128. package/.agent/memory/user/mnsfuon6-l416q1.md +0 -21
  129. package/.agent/memory/user/mnsg9kut-95m7rf.md +0 -20
  130. package/.agent/memory/user/mnu2eo1v-yy6fhe.md +0 -9
  131. package/.agent/memory/user/mnu2etuo-8u8jk8.md +0 -9
  132. package/.agent/memory/user/mnx0rk6g-gsznjj.md +0 -9
  133. package/.agent/memory/user/mnyf1riz-4yo5yz.md +0 -9
  134. package/.agent/memory/user/mnzuh4cw-zvee8w.md +0 -13
  135. package/.agent/memory/user/mnzvewyj-jl67cq.md +0 -9
  136. package/.agent/memory/user/mnzwh9xo-43ys3f.md +0 -9
  137. package/.agent/memory/user/mo0ycvpn-eebsxc.md +0 -9
  138. package/.agent/memory/user/mo2k8c8n-132r2u.md +0 -9
  139. package/.agent/memory/user/mo6y2dei-5cf537.md +0 -13
  140. package/.agent/memory/user/mo9xsdo6-8vylww.md +0 -13
  141. package/.agent/plugins/puppeteer-plugin/README.md +0 -147
  142. package/.agent/plugins/puppeteer-plugin/index.js +0 -1422
  143. package/.agent/plugins/puppeteer-plugin/package.json +0 -9
  144. package/.agent/rules/GEMINI.md +0 -273
  145. package/.agent/rules/allow-rule.md +0 -77
  146. package/.agent/rules/log-rule.md +0 -83
  147. package/.agent/rules/security-rule.md +0 -93
  148. package/.agent/scripts/auto_preview.py +0 -148
  149. package/.agent/scripts/checklist.py +0 -217
  150. package/.agent/scripts/session_manager.py +0 -120
  151. package/.agent/scripts/verify_all.py +0 -327
  152. package/.agent/skills/doc.md +0 -177
  153. package/.agent/skills/fk-poster/SKILL.md +0 -1129
  154. package/.agent/skills/fkbuilder/SKILL.md +0 -730
  155. package/.agent/skills/mmx-cli/SKILL.md +0 -431
  156. package/.agent/workflows/brainstorm.md +0 -113
  157. package/.agent/workflows/create.md +0 -59
  158. package/.agent/workflows/debug.md +0 -103
  159. package/.agent/workflows/deploy.md +0 -176
  160. package/.agent/workflows/enhance.md +0 -63
  161. package/.agent/workflows/orchestrate.md +0 -237
  162. package/.agent/workflows/plan.md +0 -89
  163. package/.agent/workflows/preview.md +0 -81
  164. package/.agent/workflows/simple-test.md +0 -42
  165. package/.agent/workflows/status.md +0 -86
  166. package/.agent/workflows/structured-orchestrate.md +0 -180
  167. package/.agent/workflows/test.md +0 -144
  168. package/.agent/workflows/ui-ux-pro-max.md +0 -296
@@ -11,12 +11,12 @@ const { z } = require('zod')
11
11
  const fs = require('fs')
12
12
  const path = require('path')
13
13
 
14
- // 尝试加载 node-cron
15
- let cron = null
14
+ // 尝试加载 node-schedule
15
+ let schedule = null
16
16
  try {
17
- cron = require('node-cron')
17
+ schedule = require('node-schedule')
18
18
  } catch (e) {
19
- log.warn(' node-cron not installed, cron tasks will not work')
19
+ log.warn(' node-schedule not installed, cron tasks will not work')
20
20
  }
21
21
 
22
22
  // ============================================================================
@@ -200,8 +200,8 @@ class SchedulerPlugin extends Plugin {
200
200
  const isCron = /^[\d*,\/-\s]+$/.test(scheduleTime) && scheduleTime.split(' ').length >= 5
201
201
 
202
202
  if (isCron || repeat) {
203
- if (!cron) {
204
- return { success: false, error: 'node-cron not installed' }
203
+ if (!schedule) {
204
+ return { success: false, error: 'node-schedule not installed' }
205
205
  }
206
206
  const task = {
207
207
  id: taskId,
@@ -219,7 +219,7 @@ class SchedulerPlugin extends Plugin {
219
219
  shell,
220
220
  notify: args.notify !== false
221
221
  }
222
- task.cronTask = cron.schedule(task.cronExpression, async () => {
222
+ task.cronTask = schedule.scheduleJob(task.cronExpression, async () => {
223
223
  await this._executeTask(task)
224
224
  })
225
225
  this._tasks.set(task.id, task)
@@ -337,8 +337,8 @@ class SchedulerPlugin extends Plugin {
337
337
 
338
338
  if (isCron || repeat) {
339
339
  // Cron 任务
340
- if (!cron) {
341
- return { success: false, error: 'node-cron not installed' }
340
+ if (!schedule) {
341
+ return { success: false, error: 'node-schedule not installed' }
342
342
  }
343
343
  task = {
344
344
  id: taskId,
@@ -357,8 +357,8 @@ class SchedulerPlugin extends Plugin {
357
357
  notify: args.notify !== false // 默认发送通知
358
358
  }
359
359
 
360
- // 使用 node-cron 调度
361
- task.cronTask = cron.schedule(task.cronExpression, async () => {
360
+ // 使用 node-schedule 调度
361
+ task.cronTask = schedule.scheduleJob(task.cronExpression, async () => {
362
362
  await this._executeTask(task)
363
363
  })
364
364
  } else if (scheduleTime.includes(':')) {
@@ -586,9 +586,9 @@ class SchedulerPlugin extends Plugin {
586
586
  let task = { ...saved }
587
587
 
588
588
  // 重新调度 Cron 任务
589
- if (task.type === 'cron' && task.enabled && cron) {
589
+ if (task.type === 'cron' && task.enabled && schedule) {
590
590
  try {
591
- task.cronTask = cron.schedule(task.cronExpression, async () => {
591
+ task.cronTask = schedule.scheduleJob(task.cronExpression, async () => {
592
592
  await this._executeTask(task)
593
593
  })
594
594
  this._tasks.set(task.id, task)
@@ -599,9 +599,9 @@ class SchedulerPlugin extends Plugin {
599
599
  }
600
600
  }
601
601
  // 重新调度 Cron Shell 任务
602
- else if (task.type === 'shell' && task.enabled && task.cronExpression && cron) {
602
+ else if (task.type === 'shell' && task.enabled && task.cronExpression && schedule) {
603
603
  try {
604
- task.cronTask = cron.schedule(task.cronExpression, async () => {
604
+ task.cronTask = schedule.scheduleJob(task.cronExpression, async () => {
605
605
  await this._executeTask(task)
606
606
  })
607
607
  this._tasks.set(task.id, task)
@@ -651,7 +651,7 @@ class SchedulerPlugin extends Plugin {
651
651
  task.timer = null
652
652
  }
653
653
  if (task.cronTask) {
654
- task.cronTask.stop()
654
+ task.cronTask.cancel()
655
655
  task.cronTask = null
656
656
  }
657
657
  task.enabled = false
@@ -820,7 +820,7 @@ class SchedulerPlugin extends Plugin {
820
820
  task.timer = null
821
821
  }
822
822
  if (task.cronTask) {
823
- task.cronTask.stop()
823
+ task.cronTask.cancel()
824
824
  task.cronTask = null
825
825
  }
826
826
  this._tasks.delete(taskId)
@@ -1,162 +1,162 @@
1
- # AGENTS.md
2
-
3
- This file provides guidance to AI coding agents working on the `skills` CLI codebase.
4
-
5
- ## Project Overview
6
-
7
- `skills` is the CLI for the open agent skills ecosystem.
8
-
9
- ## Commands
10
-
11
- | Command | Description |
12
- | ----------------------------- | --------------------------------------------------- |
13
- | `skills` | Show banner with available commands |
14
- | `skills add <pkg>` | Install skills from git repos, URLs, or local paths |
15
- | `skills experimental_install` | Restore skills from skills-lock.json |
16
- | `skills experimental_sync` | Sync skills from node_modules into agent dirs |
17
- | `skills list` | List installed skills (alias: `ls`) |
18
- | `skills check` | Check for available skill updates |
19
- | `skills update` | Update all skills to latest versions |
20
- | `skills init [name]` | Create a new SKILL.md template |
21
-
22
- Aliases: `skills a` works for `add`. `skills i`, `skills install` (no args) restore from `skills-lock.json`. `skills ls` works for `list`. `skills experimental_install` restores from `skills-lock.json`. `skills experimental_sync` crawls `node_modules` for skills.
23
-
24
- ## Architecture
25
-
26
- ```
27
- src/
28
- ├── cli.ts # Main entry point, command routing, init/check/update
29
- ├── cli.test.ts # CLI tests
30
- ├── add.ts # Core add command logic
31
- ├── add.test.ts # Add command tests
32
- ├── list.ts # List installed skills command
33
- ├── list.test.ts # List command tests
34
- ├── agents.ts # Agent definitions and detection
35
- ├── installer.ts # Skill installation logic (symlink/copy) + listInstalledSkills
36
- ├── skills.ts # Skill discovery and parsing
37
- ├── skill-lock.ts # Global lock file management (~/.agents/.skill-lock.json)
38
- ├── local-lock.ts # Local lock file management (skills-lock.json, checked in)
39
- ├── sync.ts # Sync command - crawl node_modules for skills
40
- ├── source-parser.ts # Parse git URLs, GitHub shorthand, local paths
41
- ├── git.ts # Git clone operations
42
- ├── telemetry.ts # Anonymous usage tracking
43
- ├── types.ts # TypeScript types
44
- ├── mintlify.ts # Mintlify skill fetching (legacy)
45
- ├── providers/ # Remote skill providers (GitHub, HuggingFace, Mintlify)
46
- │ ├── index.ts
47
- │ ├── registry.ts
48
- │ ├── types.ts
49
- │ ├── huggingface.ts
50
- │ └── mintlify.ts
51
- ├── init.test.ts # Init command tests
52
- └── test-utils.ts # Test utilities
53
-
54
- tests/
55
- ├── sanitize-name.test.ts # Tests for sanitizeName (path traversal prevention)
56
- ├── skill-matching.test.ts # Tests for filterSkills (multi-word skill name matching)
57
- ├── source-parser.test.ts # Tests for URL/path parsing
58
- ├── installer-symlink.test.ts # Tests for symlink installation
59
- ├── list-installed.test.ts # Tests for listing installed skills
60
- ├── skill-path.test.ts # Tests for skill path handling
61
- ├── wellknown-provider.test.ts # Tests for well-known provider
62
- └── dist.test.ts # Tests for built distribution
63
- ```
64
-
65
- ## Update Checking System
66
-
67
- ### How `skills check` and `skills update` Work
68
-
69
- 1. Read `~/.agents/.skill-lock.json` for installed skills
70
- 2. For each skill, get `skillFolderHash` from lock file
71
- 3. POST to `https://add-skill.vercel.sh/check-updates` with:
72
- ```json
73
- {
74
- "skills": [{ "name": "...", "source": "...", "skillFolderHash": "..." }],
75
- "forceRefresh": true
76
- }
77
- ```
78
- 4. API fetches fresh content from GitHub, computes hash, compares
79
- 5. Returns list of skills with different hashes (updates available)
80
-
81
- ### Why `forceRefresh: true`?
82
-
83
- Both `check` and `update` always send `forceRefresh: true`. This ensures the API fetches fresh content from GitHub rather than using its Redis cache.
84
-
85
- **Without forceRefresh:** Users saw phantom "updates available" due to stale cached hashes. The fix was to always fetch fresh.
86
-
87
- **Tradeoff:** Slightly slower (GitHub API call per skill), but always accurate.
88
-
89
- ### Lock File Compatibility
90
-
91
- The lock file format is v3. Key field: `skillFolderHash` (GitHub tree SHA for the skill folder).
92
-
93
- If reading an older lock file version, it's wiped. Users must reinstall skills to populate the new format.
94
-
95
- ## Key Integration Points
96
-
97
- | Feature | Implementation |
98
- | -------------------------- | ------------------------------------------- |
99
- | `skills add` | `src/add.ts` - full implementation |
100
- | `skills experimental_sync` | `src/sync.ts` - crawl node_modules |
101
- | `skills check` | `POST /check-updates` API |
102
- | `skills update` | `POST /check-updates` + reinstall per skill |
103
-
104
- ## Development
105
-
106
- ```bash
107
- # Install dependencies
108
- pnpm install
109
-
110
- # Build
111
- pnpm build
112
-
113
- # Test locally
114
- pnpm dev add vercel-labs/agent-skills --list
115
- pnpm dev experimental_sync
116
- pnpm dev check
117
- pnpm dev update
118
- pnpm dev init my-skill
119
-
120
- # Run all tests
121
- pnpm test
122
-
123
- # Run specific test file(s)
124
- pnpm test tests/sanitize-name.test.ts
125
- pnpm test tests/skill-matching.test.ts tests/source-parser.test.ts
126
-
127
- # Type check
128
- pnpm type-check
129
-
130
- # Format code
131
- pnpm format
132
- ```
133
-
134
- ## Code Style
135
-
136
- This project uses Prettier for code formatting. **Always run `pnpm format` before committing changes** to ensure consistent formatting.
137
-
138
- ```bash
139
- # Format all files
140
- pnpm format
141
-
142
- # Check formatting without fixing
143
- pnpm prettier --check .
144
- ```
145
-
146
- CI will fail if code is not properly formatted.
147
-
148
- ## Publishing
149
-
150
- ```bash
151
- # 1. Bump version in package.json
152
- # 2. Build
153
- pnpm build
154
- # 3. Publish
155
- npm publish
156
- ```
157
-
158
- ## Adding a New Agent
159
-
160
- 1. Add the agent definition to `src/agents.ts`
161
- 2. Run `pnpm run -C scripts validate-agents.ts` to validate
162
- 3. Run `pnpm run -C scripts sync-agents.ts` to update README.md
1
+ # AGENTS.md
2
+
3
+ This file provides guidance to AI coding agents working on the `skills` CLI codebase.
4
+
5
+ ## Project Overview
6
+
7
+ `skills` is the CLI for the open agent skills ecosystem.
8
+
9
+ ## Commands
10
+
11
+ | Command | Description |
12
+ | ----------------------------- | --------------------------------------------------- |
13
+ | `skills` | Show banner with available commands |
14
+ | `skills add <pkg>` | Install skills from git repos, URLs, or local paths |
15
+ | `skills experimental_install` | Restore skills from skills-lock.json |
16
+ | `skills experimental_sync` | Sync skills from node_modules into agent dirs |
17
+ | `skills list` | List installed skills (alias: `ls`) |
18
+ | `skills check` | Check for available skill updates |
19
+ | `skills update` | Update all skills to latest versions |
20
+ | `skills init [name]` | Create a new SKILL.md template |
21
+
22
+ Aliases: `skills a` works for `add`. `skills i`, `skills install` (no args) restore from `skills-lock.json`. `skills ls` works for `list`. `skills experimental_install` restores from `skills-lock.json`. `skills experimental_sync` crawls `node_modules` for skills.
23
+
24
+ ## Architecture
25
+
26
+ ```
27
+ src/
28
+ ├── cli.ts # Main entry point, command routing, init/check/update
29
+ ├── cli.test.ts # CLI tests
30
+ ├── add.ts # Core add command logic
31
+ ├── add.test.ts # Add command tests
32
+ ├── list.ts # List installed skills command
33
+ ├── list.test.ts # List command tests
34
+ ├── agents.ts # Agent definitions and detection
35
+ ├── installer.ts # Skill installation logic (symlink/copy) + listInstalledSkills
36
+ ├── skills.ts # Skill discovery and parsing
37
+ ├── skill-lock.ts # Global lock file management (~/.agents/.skill-lock.json)
38
+ ├── local-lock.ts # Local lock file management (skills-lock.json, checked in)
39
+ ├── sync.ts # Sync command - crawl node_modules for skills
40
+ ├── source-parser.ts # Parse git URLs, GitHub shorthand, local paths
41
+ ├── git.ts # Git clone operations
42
+ ├── telemetry.ts # Anonymous usage tracking
43
+ ├── types.ts # TypeScript types
44
+ ├── mintlify.ts # Mintlify skill fetching (legacy)
45
+ ├── providers/ # Remote skill providers (GitHub, HuggingFace, Mintlify)
46
+ │ ├── index.ts
47
+ │ ├── registry.ts
48
+ │ ├── types.ts
49
+ │ ├── huggingface.ts
50
+ │ └── mintlify.ts
51
+ ├── init.test.ts # Init command tests
52
+ └── test-utils.ts # Test utilities
53
+
54
+ tests/
55
+ ├── sanitize-name.test.ts # Tests for sanitizeName (path traversal prevention)
56
+ ├── skill-matching.test.ts # Tests for filterSkills (multi-word skill name matching)
57
+ ├── source-parser.test.ts # Tests for URL/path parsing
58
+ ├── installer-symlink.test.ts # Tests for symlink installation
59
+ ├── list-installed.test.ts # Tests for listing installed skills
60
+ ├── skill-path.test.ts # Tests for skill path handling
61
+ ├── wellknown-provider.test.ts # Tests for well-known provider
62
+ └── dist.test.ts # Tests for built distribution
63
+ ```
64
+
65
+ ## Update Checking System
66
+
67
+ ### How `skills check` and `skills update` Work
68
+
69
+ 1. Read `~/.agents/.skill-lock.json` for installed skills
70
+ 2. For each skill, get `skillFolderHash` from lock file
71
+ 3. POST to `https://add-skill.vercel.sh/check-updates` with:
72
+ ```json
73
+ {
74
+ "skills": [{ "name": "...", "source": "...", "skillFolderHash": "..." }],
75
+ "forceRefresh": true
76
+ }
77
+ ```
78
+ 4. API fetches fresh content from GitHub, computes hash, compares
79
+ 5. Returns list of skills with different hashes (updates available)
80
+
81
+ ### Why `forceRefresh: true`?
82
+
83
+ Both `check` and `update` always send `forceRefresh: true`. This ensures the API fetches fresh content from GitHub rather than using its Redis cache.
84
+
85
+ **Without forceRefresh:** Users saw phantom "updates available" due to stale cached hashes. The fix was to always fetch fresh.
86
+
87
+ **Tradeoff:** Slightly slower (GitHub API call per skill), but always accurate.
88
+
89
+ ### Lock File Compatibility
90
+
91
+ The lock file format is v3. Key field: `skillFolderHash` (GitHub tree SHA for the skill folder).
92
+
93
+ If reading an older lock file version, it's wiped. Users must reinstall skills to populate the new format.
94
+
95
+ ## Key Integration Points
96
+
97
+ | Feature | Implementation |
98
+ | -------------------------- | ------------------------------------------- |
99
+ | `skills add` | `src/add.ts` - full implementation |
100
+ | `skills experimental_sync` | `src/sync.ts` - crawl node_modules |
101
+ | `skills check` | `POST /check-updates` API |
102
+ | `skills update` | `POST /check-updates` + reinstall per skill |
103
+
104
+ ## Development
105
+
106
+ ```bash
107
+ # Install dependencies
108
+ pnpm install
109
+
110
+ # Build
111
+ pnpm build
112
+
113
+ # Test locally
114
+ pnpm dev add vercel-labs/agent-skills --list
115
+ pnpm dev experimental_sync
116
+ pnpm dev check
117
+ pnpm dev update
118
+ pnpm dev init my-skill
119
+
120
+ # Run all tests
121
+ pnpm test
122
+
123
+ # Run specific test file(s)
124
+ pnpm test tests/sanitize-name.test.ts
125
+ pnpm test tests/skill-matching.test.ts tests/source-parser.test.ts
126
+
127
+ # Type check
128
+ pnpm type-check
129
+
130
+ # Format code
131
+ pnpm format
132
+ ```
133
+
134
+ ## Code Style
135
+
136
+ This project uses Prettier for code formatting. **Always run `pnpm format` before committing changes** to ensure consistent formatting.
137
+
138
+ ```bash
139
+ # Format all files
140
+ pnpm format
141
+
142
+ # Check formatting without fixing
143
+ pnpm prettier --check .
144
+ ```
145
+
146
+ CI will fail if code is not properly formatted.
147
+
148
+ ## Publishing
149
+
150
+ ```bash
151
+ # 1. Bump version in package.json
152
+ # 2. Build
153
+ pnpm build
154
+ # 3. Publish
155
+ npm publish
156
+ ```
157
+
158
+ ## Adding a New Agent
159
+
160
+ 1. Add the agent definition to `src/agents.ts`
161
+ 2. Run `pnpm run -C scripts validate-agents.ts` to validate
162
+ 3. Run `pnpm run -C scripts sync-agents.ts` to update README.md