@opendirectory.dev/skills 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (212) hide show
  1. package/.claude/skills/claude-md-generator/.env.example +7 -0
  2. package/.claude/skills/claude-md-generator/README.md +78 -0
  3. package/.claude/skills/claude-md-generator/SKILL.md +248 -0
  4. package/.claude/skills/claude-md-generator/evals/evals.json +35 -0
  5. package/.claude/skills/claude-md-generator/references/section-guide.md +175 -0
  6. package/dist/e2e.test.d.ts +1 -0
  7. package/dist/e2e.test.js +62 -0
  8. package/dist/fs-adapters.d.ts +4 -0
  9. package/dist/fs-adapters.js +101 -0
  10. package/dist/fs-adapters.test.d.ts +1 -0
  11. package/dist/fs-adapters.test.js +108 -0
  12. package/dist/index.d.ts +2 -0
  13. package/dist/index.js +211 -0
  14. package/dist/transformers.d.ts +6 -0
  15. package/dist/transformers.js +2 -0
  16. package/package.json +25 -0
  17. package/registry.json +226 -0
  18. package/skills/blog-cover-image-cli/.github/workflows/publish.yml +19 -0
  19. package/skills/blog-cover-image-cli/LICENSE +15 -0
  20. package/skills/blog-cover-image-cli/README.md +126 -0
  21. package/skills/blog-cover-image-cli/SKILL.md +7 -0
  22. package/skills/blog-cover-image-cli/agent-skill/blog-cover-generator/README.md +30 -0
  23. package/skills/blog-cover-image-cli/agent-skill/blog-cover-generator/SKILL.md +72 -0
  24. package/skills/blog-cover-image-cli/bin/cli.js +226 -0
  25. package/skills/blog-cover-image-cli/examples/100x_UX_Research_AI_Agent.png +0 -0
  26. package/skills/blog-cover-image-cli/examples/Firecrawl-supabase-bolt.png +0 -0
  27. package/skills/blog-cover-image-cli/examples/Git-City_Case_study_Cover_Image.jpg +0 -0
  28. package/skills/blog-cover-image-cli/examples/THE DISTRIBUTION LAYER (2).png +0 -0
  29. package/skills/blog-cover-image-cli/examples/canva-perplexity-duolingo-cover-image.png +0 -0
  30. package/skills/blog-cover-image-cli/examples/gamma-mistral-veed.png +0 -0
  31. package/skills/blog-cover-image-cli/examples/server-survival-case-study-cover-image(1).png +0 -0
  32. package/skills/blog-cover-image-cli/examples/viral-meme-automation.png +0 -0
  33. package/skills/blog-cover-image-cli/index.js +2 -0
  34. package/skills/blog-cover-image-cli/package-lock.json +2238 -0
  35. package/skills/blog-cover-image-cli/package.json +37 -0
  36. package/skills/blog-cover-image-cli/src/geminiGenerator.js +126 -0
  37. package/skills/blog-cover-image-cli/src/imageValidator.js +54 -0
  38. package/skills/blog-cover-image-cli/src/logoFetcher.js +86 -0
  39. package/skills/claude-md-generator/.env.example +7 -0
  40. package/skills/claude-md-generator/README.md +78 -0
  41. package/skills/claude-md-generator/SKILL.md +254 -0
  42. package/skills/claude-md-generator/evals/evals.json +35 -0
  43. package/skills/claude-md-generator/references/section-guide.md +175 -0
  44. package/skills/cook-the-blog/README.md +86 -0
  45. package/skills/cook-the-blog/SKILL.md +130 -0
  46. package/skills/dependency-update-bot/.env.example +13 -0
  47. package/skills/dependency-update-bot/README.md +101 -0
  48. package/skills/dependency-update-bot/SKILL.md +376 -0
  49. package/skills/dependency-update-bot/evals/evals.json +45 -0
  50. package/skills/dependency-update-bot/references/changelog-patterns.md +201 -0
  51. package/skills/docs-from-code/.env.example +13 -0
  52. package/skills/docs-from-code/README.md +97 -0
  53. package/skills/docs-from-code/SKILL.md +160 -0
  54. package/skills/docs-from-code/evals/evals.json +29 -0
  55. package/skills/docs-from-code/references/extraction-guide.md +174 -0
  56. package/skills/docs-from-code/references/output-template.md +135 -0
  57. package/skills/docs-from-code/scripts/extract_py.py +238 -0
  58. package/skills/docs-from-code/scripts/extract_ts.ts +284 -0
  59. package/skills/docs-from-code/scripts/package.json +18 -0
  60. package/skills/explain-this-pr/README.md +74 -0
  61. package/skills/explain-this-pr/SKILL.md +130 -0
  62. package/skills/explain-this-pr/evals/evals.json +35 -0
  63. package/skills/google-trends-api-skills/README.md +78 -0
  64. package/skills/google-trends-api-skills/SKILL.md +7 -0
  65. package/skills/google-trends-api-skills/google-trends-api/SKILL.md +163 -0
  66. package/skills/google-trends-api-skills/google-trends-api/references/api-responses.md +188 -0
  67. package/skills/google-trends-api-skills/google-trends-api/scripts/discover_keywords.py +344 -0
  68. package/skills/google-trends-api-skills/seo-keyword-research/SKILL.md +205 -0
  69. package/skills/google-trends-api-skills/seo-keyword-research/references/keyword-placement-guide.md +89 -0
  70. package/skills/google-trends-api-skills/seo-keyword-research/references/tech-blog-examples.md +207 -0
  71. package/skills/google-trends-api-skills/seo-keyword-research/scripts/blog_seo_research.py +373 -0
  72. package/skills/hackernews-intel/.env.example +33 -0
  73. package/skills/hackernews-intel/README.md +161 -0
  74. package/skills/hackernews-intel/SKILL.md +156 -0
  75. package/skills/hackernews-intel/evals/evals.json +35 -0
  76. package/skills/hackernews-intel/package.json +15 -0
  77. package/skills/hackernews-intel/scripts/monitor-hn.js +258 -0
  78. package/skills/kill-the-standup/.env.example +22 -0
  79. package/skills/kill-the-standup/README.md +84 -0
  80. package/skills/kill-the-standup/SKILL.md +169 -0
  81. package/skills/kill-the-standup/evals/evals.json +35 -0
  82. package/skills/kill-the-standup/references/standup-format.md +102 -0
  83. package/skills/linkedin-post-generator/.env.example +14 -0
  84. package/skills/linkedin-post-generator/README.md +107 -0
  85. package/skills/linkedin-post-generator/SKILL.md +228 -0
  86. package/skills/linkedin-post-generator/evals/evals.json +35 -0
  87. package/skills/linkedin-post-generator/references/linkedin-format.md +216 -0
  88. package/skills/linkedin-post-generator/references/output-template.md +154 -0
  89. package/skills/llms-txt-generator/.env.example +18 -0
  90. package/skills/llms-txt-generator/README.md +142 -0
  91. package/skills/llms-txt-generator/SKILL.md +176 -0
  92. package/skills/llms-txt-generator/evals/evals.json +35 -0
  93. package/skills/llms-txt-generator/references/llms-txt-spec.md +88 -0
  94. package/skills/llms-txt-generator/references/output-template.md +76 -0
  95. package/skills/llms-txt-generator/test-output/genzcareer.in/llms.txt +31 -0
  96. package/skills/luma-attendees-scraper/README.md +170 -0
  97. package/skills/luma-attendees-scraper/SKILL.md +7 -0
  98. package/skills/luma-attendees-scraper/luma_attendees_export.js +223 -0
  99. package/skills/meeting-brief-generator/.env.example +21 -0
  100. package/skills/meeting-brief-generator/README.md +90 -0
  101. package/skills/meeting-brief-generator/SKILL.md +275 -0
  102. package/skills/meeting-brief-generator/evals/evals.json +35 -0
  103. package/skills/meeting-brief-generator/references/brief-format.md +114 -0
  104. package/skills/meeting-brief-generator/references/output-template.md +150 -0
  105. package/skills/meta-ads-skill/README.md +100 -0
  106. package/skills/meta-ads-skill/SKILL.md +7 -0
  107. package/skills/meta-ads-skill/meta-ads-skill/SKILL.md +41 -0
  108. package/skills/meta-ads-skill/meta-ads-skill/references/report_templates.md +47 -0
  109. package/skills/meta-ads-skill/meta-ads-skill/references/workflows.md +51 -0
  110. package/skills/meta-ads-skill/meta-ads-skill/scripts/auth_check.py +22 -0
  111. package/skills/meta-ads-skill/meta-ads-skill/scripts/formatters.py +46 -0
  112. package/skills/newsletter-digest/.env.example +20 -0
  113. package/skills/newsletter-digest/README.md +147 -0
  114. package/skills/newsletter-digest/SKILL.md +221 -0
  115. package/skills/newsletter-digest/evals/evals.json +35 -0
  116. package/skills/newsletter-digest/feeds.json +7 -0
  117. package/skills/newsletter-digest/package.json +15 -0
  118. package/skills/newsletter-digest/references/digest-format.md +123 -0
  119. package/skills/newsletter-digest/references/output-template.md +136 -0
  120. package/skills/newsletter-digest/scripts/fetch-feeds.js +141 -0
  121. package/skills/newsletter-digest/scripts/ghost-publish.js +147 -0
  122. package/skills/noise2blog/.env.example +16 -0
  123. package/skills/noise2blog/README.md +107 -0
  124. package/skills/noise2blog/SKILL.md +229 -0
  125. package/skills/noise2blog/evals/evals.json +35 -0
  126. package/skills/noise2blog/references/blog-format.md +188 -0
  127. package/skills/noise2blog/references/output-template.md +184 -0
  128. package/skills/outreach-sequence-builder/.env.example +12 -0
  129. package/skills/outreach-sequence-builder/README.md +108 -0
  130. package/skills/outreach-sequence-builder/SKILL.md +248 -0
  131. package/skills/outreach-sequence-builder/evals/evals.json +36 -0
  132. package/skills/outreach-sequence-builder/references/output-template.md +171 -0
  133. package/skills/outreach-sequence-builder/references/sequence-format.md +167 -0
  134. package/skills/outreach-sequence-builder/references/signal-playbook.md +117 -0
  135. package/skills/position-me/README.md +71 -0
  136. package/skills/position-me/SKILL.md +7 -0
  137. package/skills/position-me/position-me/SKILL.md +50 -0
  138. package/skills/position-me/position-me/references/EVALUATION_SOP.md +40 -0
  139. package/skills/position-me/position-me/references/REPORT_TEMPLATE.md +58 -0
  140. package/skills/position-me/position-me/scripts/extract_links.py +49 -0
  141. package/skills/pr-description-writer/README.md +81 -0
  142. package/skills/pr-description-writer/SKILL.md +141 -0
  143. package/skills/pr-description-writer/evals/evals.json +35 -0
  144. package/skills/pr-description-writer/references/pr-format-guide.md +145 -0
  145. package/skills/producthunt-launch-kit/.env.example +7 -0
  146. package/skills/producthunt-launch-kit/README.md +95 -0
  147. package/skills/producthunt-launch-kit/SKILL.md +380 -0
  148. package/skills/producthunt-launch-kit/evals/evals.json +35 -0
  149. package/skills/producthunt-launch-kit/references/copy-rules.md +124 -0
  150. package/skills/reddit-icp-monitor/.env.example +16 -0
  151. package/skills/reddit-icp-monitor/README.md +117 -0
  152. package/skills/reddit-icp-monitor/SKILL.md +271 -0
  153. package/skills/reddit-icp-monitor/evals/evals.json +40 -0
  154. package/skills/reddit-icp-monitor/references/icp-format.md +131 -0
  155. package/skills/reddit-icp-monitor/references/reply-rules.md +110 -0
  156. package/skills/reddit-post-engine/.env.example +13 -0
  157. package/skills/reddit-post-engine/README.md +103 -0
  158. package/skills/reddit-post-engine/SKILL.md +303 -0
  159. package/skills/reddit-post-engine/evals/evals.json +35 -0
  160. package/skills/reddit-post-engine/references/subreddit-playbook.md +156 -0
  161. package/skills/schema-markup-generator/.env.example +19 -0
  162. package/skills/schema-markup-generator/README.md +114 -0
  163. package/skills/schema-markup-generator/SKILL.md +192 -0
  164. package/skills/schema-markup-generator/evals/evals.json +35 -0
  165. package/skills/schema-markup-generator/references/json-ld-spec.md +263 -0
  166. package/skills/schema-markup-generator/references/output-template.md +556 -0
  167. package/skills/show-hn-writer/.env.example +14 -0
  168. package/skills/show-hn-writer/README.md +88 -0
  169. package/skills/show-hn-writer/SKILL.md +303 -0
  170. package/skills/show-hn-writer/evals/evals.json +35 -0
  171. package/skills/show-hn-writer/references/hn-rules.md +74 -0
  172. package/skills/show-hn-writer/references/title-formulas.md +93 -0
  173. package/skills/stargazer/README.md +79 -0
  174. package/skills/stargazer/SKILL.md +7 -0
  175. package/skills/stargazer/stargazer-skill/SKILL.md +58 -0
  176. package/skills/stargazer/stargazer-skill/assets/.env.example +18 -0
  177. package/skills/stargazer/stargazer-skill/scripts/convert_to_csv.py +63 -0
  178. package/skills/stargazer/stargazer-skill/scripts/count_emails.py +52 -0
  179. package/skills/stargazer/stargazer-skill/scripts/stargazer_deep_extractor.py +450 -0
  180. package/skills/tweet-thread-from-blog/.env.example +14 -0
  181. package/skills/tweet-thread-from-blog/README.md +109 -0
  182. package/skills/tweet-thread-from-blog/SKILL.md +177 -0
  183. package/skills/tweet-thread-from-blog/evals/evals.json +35 -0
  184. package/skills/tweet-thread-from-blog/references/output-template.md +193 -0
  185. package/skills/tweet-thread-from-blog/references/thread-format.md +107 -0
  186. package/skills/twitter-GTM-find-skill/README.md +43 -0
  187. package/skills/twitter-GTM-find-skill/SKILL.md +7 -0
  188. package/skills/twitter-GTM-find-skill/twitter-GTM-find/SKILL.md +37 -0
  189. package/skills/twitter-GTM-find-skill/twitter-GTM-find/references/icp-checklist.md +35 -0
  190. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/package.json +23 -0
  191. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/run_pipeline.sh +8 -0
  192. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/debug.ts +23 -0
  193. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/extractor.ts +79 -0
  194. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/icp-filter.ts +87 -0
  195. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/index.ts +94 -0
  196. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/src/scraper.ts +41 -0
  197. package/skills/twitter-GTM-find-skill/twitter-GTM-find/scripts/tsconfig.json +13 -0
  198. package/skills/yc-intent-radar-skill/README.md +39 -0
  199. package/skills/yc-intent-radar-skill/SKILL.md +7 -0
  200. package/skills/yc-intent-radar-skill/yc-jobs-scraper/SKILL.md +59 -0
  201. package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/auth.js +29 -0
  202. package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/db.js +62 -0
  203. package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/export_radar_candidates.js +40 -0
  204. package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/package-lock.json +1525 -0
  205. package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/package.json +12 -0
  206. package/skills/yc-intent-radar-skill/yc-jobs-scraper/scripts/scraper.js +217 -0
  207. package/src/e2e.test.ts +35 -0
  208. package/src/fs-adapters.test.ts +91 -0
  209. package/src/fs-adapters.ts +65 -0
  210. package/src/index.ts +182 -0
  211. package/src/transformers.ts +6 -0
  212. package/tsconfig.json +8 -0
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.resolvePath = resolvePath;
37
+ exports.safeWriteFile = safeWriteFile;
38
+ exports.safeAppendFile = safeAppendFile;
39
+ exports.updateHermesConfig = updateHermesConfig;
40
+ const fs = __importStar(require("node:fs/promises"));
41
+ const path = __importStar(require("node:path"));
42
+ const os = __importStar(require("node:os"));
43
+ function resolvePath(p) {
44
+ if (p.startsWith('~/') || p === '~') {
45
+ return path.resolve(p.replace(/^~/, os.homedir()));
46
+ }
47
+ return path.resolve(p);
48
+ }
49
+ async function safeWriteFile(filePath, content) {
50
+ const resolvedPath = resolvePath(filePath);
51
+ const dir = path.dirname(resolvedPath);
52
+ await fs.mkdir(dir, { recursive: true });
53
+ await fs.writeFile(resolvedPath, content, 'utf-8');
54
+ }
55
+ async function safeAppendFile(filePath, content) {
56
+ const resolvedPath = resolvePath(filePath);
57
+ const dir = path.dirname(resolvedPath);
58
+ await fs.mkdir(dir, { recursive: true });
59
+ try {
60
+ const existingContent = await fs.readFile(resolvedPath, 'utf-8');
61
+ if (existingContent.includes(content)) {
62
+ return;
63
+ }
64
+ const prefix = existingContent.length > 0 && !existingContent.endsWith('\n') ? '\n' : '';
65
+ await fs.appendFile(resolvedPath, prefix + content, 'utf-8');
66
+ }
67
+ catch (error) {
68
+ if (error.code === 'ENOENT') {
69
+ await fs.writeFile(resolvedPath, content, 'utf-8');
70
+ }
71
+ else {
72
+ throw error;
73
+ }
74
+ }
75
+ }
76
+ async function updateHermesConfig() {
77
+ const configPath = resolvePath('~/.hermes/config.yaml');
78
+ try {
79
+ let content = await fs.readFile(configPath, 'utf-8');
80
+ if (!content.includes('skills:')) {
81
+ const prefix = content.length > 0 && !content.endsWith('\n') ? '\n' : '';
82
+ content += prefix + 'skills:\n external_dirs:\n - "./.hermes/skills"\n';
83
+ }
84
+ else if (!content.includes('external_dirs:')) {
85
+ content = content.replace(/(skills:\s*\n)/, '$1 external_dirs:\n - "./.hermes/skills"\n');
86
+ }
87
+ else if (!content.includes('./.hermes/skills')) {
88
+ content = content.replace(/(external_dirs:\s*\n)/, '$1 - "./.hermes/skills"\n');
89
+ }
90
+ await fs.writeFile(configPath, content, 'utf-8');
91
+ }
92
+ catch (error) {
93
+ if (error.code === 'ENOENT') {
94
+ const initialContent = `skills:\n external_dirs:\n - "./.hermes/skills"\n`;
95
+ await safeWriteFile('~/.hermes/config.yaml', initialContent);
96
+ }
97
+ else {
98
+ throw error;
99
+ }
100
+ }
101
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ const vitest_1 = require("vitest");
37
+ const fs = __importStar(require("node:fs/promises"));
38
+ const path = __importStar(require("node:path"));
39
+ const os = __importStar(require("node:os"));
40
+ const fs_adapters_1 = require("./fs-adapters");
41
+ (0, vitest_1.describe)('fs-adapters', () => {
42
+ let tempDir;
43
+ (0, vitest_1.beforeEach)(async () => {
44
+ tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'fs-adapters-test-'));
45
+ });
46
+ (0, vitest_1.afterEach)(async () => {
47
+ await fs.rm(tempDir, { recursive: true, force: true });
48
+ });
49
+ (0, vitest_1.describe)('resolvePath', () => {
50
+ (0, vitest_1.it)('should resolve ~ to home directory', () => {
51
+ const home = os.homedir();
52
+ (0, vitest_1.expect)((0, fs_adapters_1.resolvePath)('~/foo/bar')).toBe(path.join(home, 'foo/bar'));
53
+ (0, vitest_1.expect)((0, fs_adapters_1.resolvePath)('~')).toBe(home);
54
+ });
55
+ (0, vitest_1.it)('should resolve absolute paths', () => {
56
+ const absPath = path.resolve('/foo/bar');
57
+ (0, vitest_1.expect)((0, fs_adapters_1.resolvePath)('/foo/bar')).toBe(absPath);
58
+ });
59
+ (0, vitest_1.it)('should resolve relative paths', () => {
60
+ const relPath = path.resolve('foo/bar');
61
+ (0, vitest_1.expect)((0, fs_adapters_1.resolvePath)('foo/bar')).toBe(relPath);
62
+ });
63
+ });
64
+ (0, vitest_1.describe)('safeWriteFile', () => {
65
+ (0, vitest_1.it)('should create directory and write file', async () => {
66
+ const filePath = path.join(tempDir, 'nested', 'dir', 'test.txt');
67
+ await (0, fs_adapters_1.safeWriteFile)(filePath, 'hello world');
68
+ const content = await fs.readFile(filePath, 'utf-8');
69
+ (0, vitest_1.expect)(content).toBe('hello world');
70
+ });
71
+ (0, vitest_1.it)('should overwrite existing file', async () => {
72
+ const filePath = path.join(tempDir, 'test.txt');
73
+ await (0, fs_adapters_1.safeWriteFile)(filePath, 'hello world');
74
+ await (0, fs_adapters_1.safeWriteFile)(filePath, 'new content');
75
+ const content = await fs.readFile(filePath, 'utf-8');
76
+ (0, vitest_1.expect)(content).toBe('new content');
77
+ });
78
+ });
79
+ (0, vitest_1.describe)('safeAppendFile', () => {
80
+ (0, vitest_1.it)('should create file if it does not exist', async () => {
81
+ const filePath = path.join(tempDir, 'nested', 'test.txt');
82
+ await (0, fs_adapters_1.safeAppendFile)(filePath, 'hello world');
83
+ const content = await fs.readFile(filePath, 'utf-8');
84
+ (0, vitest_1.expect)(content).toBe('hello world');
85
+ });
86
+ (0, vitest_1.it)('should append to existing file', async () => {
87
+ const filePath = path.join(tempDir, 'test.txt');
88
+ await (0, fs_adapters_1.safeWriteFile)(filePath, 'line 1\n');
89
+ await (0, fs_adapters_1.safeAppendFile)(filePath, 'line 2');
90
+ const content = await fs.readFile(filePath, 'utf-8');
91
+ (0, vitest_1.expect)(content).toBe('line 1\nline 2');
92
+ });
93
+ (0, vitest_1.it)('should add newline if existing file does not end with one', async () => {
94
+ const filePath = path.join(tempDir, 'test.txt');
95
+ await (0, fs_adapters_1.safeWriteFile)(filePath, 'line 1');
96
+ await (0, fs_adapters_1.safeAppendFile)(filePath, 'line 2');
97
+ const content = await fs.readFile(filePath, 'utf-8');
98
+ (0, vitest_1.expect)(content).toBe('line 1\nline 2');
99
+ });
100
+ (0, vitest_1.it)('should not append if content already exists', async () => {
101
+ const filePath = path.join(tempDir, 'test.txt');
102
+ await (0, fs_adapters_1.safeWriteFile)(filePath, 'existing content\nmore stuff');
103
+ await (0, fs_adapters_1.safeAppendFile)(filePath, 'existing content');
104
+ const content = await fs.readFile(filePath, 'utf-8');
105
+ (0, vitest_1.expect)(content).toBe('existing content\nmore stuff');
106
+ });
107
+ });
108
+ });
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,211 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ var __importDefault = (this && this.__importDefault) || function (mod) {
37
+ return (mod && mod.__esModule) ? mod : { "default": mod };
38
+ };
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ const commander_1 = require("commander");
41
+ const fs = __importStar(require("node:fs/promises"));
42
+ const path = __importStar(require("node:path"));
43
+ const chalk_1 = __importDefault(require("chalk"));
44
+ const ora_1 = __importDefault(require("ora"));
45
+ const cli_table3_1 = __importDefault(require("cli-table3"));
46
+ const program = new commander_1.Command();
47
+ program
48
+ .name('@opendirectory.dev/cli')
49
+ .description(chalk_1.default.blue.bold('CLI to install OpenDirectory skills'))
50
+ .version('0.1.0');
51
+ const getProjectRoot = () => {
52
+ return path.resolve(__dirname, '..');
53
+ };
54
+ program
55
+ .command('list')
56
+ .description('List available skills in the Open Directory registry')
57
+ .action(async () => {
58
+ const spinner = (0, ora_1.default)('Fetching available skills...').start();
59
+ try {
60
+ const root = getProjectRoot();
61
+ const registryPath = path.join(root, 'registry.json');
62
+ let skills = [];
63
+ try {
64
+ const registryContent = await fs.readFile(registryPath, 'utf-8');
65
+ skills = JSON.parse(registryContent);
66
+ }
67
+ catch (e) {
68
+ const skillsDir = path.join(root, 'skills');
69
+ const entries = await fs.readdir(skillsDir, { withFileTypes: true });
70
+ skills = entries
71
+ .filter(entry => entry.isDirectory())
72
+ .map(entry => ({ name: entry.name, description: `Skill: ${entry.name}` }));
73
+ }
74
+ spinner.stop();
75
+ console.log(chalk_1.default.green('Successfully loaded Open Directory registry!\n'));
76
+ const table = new cli_table3_1.default({
77
+ head: [chalk_1.default.cyan.bold('Skill Name'), chalk_1.default.cyan.bold('Description')],
78
+ colWidths: [35, 75],
79
+ wordWrap: true
80
+ });
81
+ for (const skill of skills) {
82
+ let desc = skill.description || '';
83
+ desc = desc.replace(/<img[^>]*>/g, '').trim();
84
+ if (desc.length > 100)
85
+ desc = desc.substring(0, 97) + '...';
86
+ table.push([chalk_1.default.yellow(skill.name), desc]);
87
+ }
88
+ console.log(table.toString());
89
+ console.log(chalk_1.default.gray(`\nRun \`${chalk_1.default.white('npx @opendirectory.dev/cli install <skill-name> --target <agent>')}\` to install a skill.`));
90
+ }
91
+ catch (error) {
92
+ spinner.stop();
93
+ console.error(chalk_1.default.red('Failed to list skills.'));
94
+ console.error(error);
95
+ }
96
+ });
97
+ program
98
+ .command('install <skill>')
99
+ .description('Install a skill for your AI agent')
100
+ .requiredOption('-t, --target <tool>', 'Target agent (opencode, claude, codex, gemini, anti-gravity, openclaw, hermes)')
101
+ .option('-g, --global', 'Install globally for all projects')
102
+ .action(async (skillName, options) => {
103
+ const spinner = (0, ora_1.default)(`Installing ${chalk_1.default.yellow(skillName)}...`).start();
104
+ try {
105
+ const root = getProjectRoot();
106
+ const repoDir = path.join(root, 'skills', skillName);
107
+ let skillDir = repoDir;
108
+ let skillMdPath = path.join(skillDir, 'SKILL.md');
109
+ try {
110
+ await fs.access(skillMdPath);
111
+ }
112
+ catch (e) {
113
+ try {
114
+ const entries = await fs.readdir(repoDir, { withFileTypes: true });
115
+ for (const entry of entries) {
116
+ if (entry.isDirectory()) {
117
+ const possiblePath = path.join(repoDir, entry.name, 'SKILL.md');
118
+ try {
119
+ await fs.access(possiblePath);
120
+ skillDir = path.join(repoDir, entry.name);
121
+ skillMdPath = possiblePath;
122
+ break;
123
+ }
124
+ catch (err) { }
125
+ }
126
+ }
127
+ if (skillDir === repoDir) {
128
+ for (const entry of entries) {
129
+ if (entry.isDirectory() && entry.name !== 'node_modules' && entry.name !== '.git') {
130
+ const subDir = path.join(repoDir, entry.name);
131
+ const subEntries = await fs.readdir(subDir, { withFileTypes: true });
132
+ for (const subEntry of subEntries) {
133
+ if (subEntry.isDirectory()) {
134
+ const possiblePath = path.join(subDir, subEntry.name, 'SKILL.md');
135
+ try {
136
+ await fs.access(possiblePath);
137
+ skillDir = path.join(subDir, subEntry.name);
138
+ skillMdPath = possiblePath;
139
+ break;
140
+ }
141
+ catch (err) { }
142
+ }
143
+ }
144
+ }
145
+ }
146
+ }
147
+ }
148
+ catch (dirErr) {
149
+ spinner.stop();
150
+ console.error(chalk_1.default.red(`Error: Repository '${skillName}' not found.`));
151
+ console.log(chalk_1.default.gray(`Try running \`${chalk_1.default.white('npx @opendirectory.dev/cli list')}\` to see available skills.`));
152
+ process.exit(1);
153
+ }
154
+ }
155
+ try {
156
+ await fs.access(skillMdPath);
157
+ }
158
+ catch (e) {
159
+ spinner.stop();
160
+ console.error(chalk_1.default.red(`Error: Skill '${skillName}' missing SKILL.md in registry.`));
161
+ process.exit(1);
162
+ }
163
+ const actualSkillFolderName = path.basename(skillDir);
164
+ const finalSkillName = actualSkillFolderName === skillName ? skillName : actualSkillFolderName;
165
+ const target = options.target.toLowerCase();
166
+ const isGlobal = options.global;
167
+ const validTargets = ['opencode', 'claude', 'codex', 'gemini', 'anti-gravity', 'openclaw', 'hermes'];
168
+ if (validTargets.includes(target)) {
169
+ let targetFolder = '';
170
+ if (target === 'opencode')
171
+ targetFolder = isGlobal ? `~/.config/opencode/skills/${finalSkillName}` : `./.opencode/skills/${finalSkillName}`;
172
+ if (target === 'claude')
173
+ targetFolder = isGlobal ? `~/.claude/skills/${finalSkillName}` : `./.claude/skills/${finalSkillName}`;
174
+ if (target === 'codex')
175
+ targetFolder = isGlobal ? `~/.codex/skills/${finalSkillName}` : `./.codex/skills/${finalSkillName}`;
176
+ if (target === 'gemini')
177
+ targetFolder = isGlobal ? `~/.gemini/skills/${finalSkillName}` : `./.gemini/skills/${finalSkillName}`;
178
+ if (target === 'anti-gravity')
179
+ targetFolder = isGlobal ? `~/.gemini/antigravity/skills/${finalSkillName}` : `./.agent/skills/${finalSkillName}`;
180
+ if (target === 'openclaw')
181
+ targetFolder = isGlobal ? `~/.openclaw/skills/${finalSkillName}` : `./.openclaw/skills/${finalSkillName}`;
182
+ if (target === 'hermes')
183
+ targetFolder = isGlobal ? `~/.hermes/skills/${finalSkillName}` : `./.hermes/skills/${finalSkillName}`;
184
+ const { resolvePath, updateHermesConfig } = require('./fs-adapters');
185
+ const resolvedDest = resolvePath(targetFolder);
186
+ await fs.mkdir(resolvedDest, { recursive: true });
187
+ await fs.cp(skillDir, resolvedDest, { recursive: true });
188
+ if (target === 'hermes' && !isGlobal) {
189
+ await updateHermesConfig();
190
+ }
191
+ spinner.stop();
192
+ console.log(chalk_1.default.green(`Successfully installed ${chalk_1.default.bold(finalSkillName)}!`));
193
+ console.log(`\n ${chalk_1.default.cyan('Agent:')} ${target}`);
194
+ console.log(` ${chalk_1.default.cyan('Scope:')} ${isGlobal ? 'Global' : 'Local Project'}`);
195
+ console.log(` ${chalk_1.default.cyan('Path:')} ${targetFolder}\n`);
196
+ }
197
+ else {
198
+ spinner.stop();
199
+ console.error(chalk_1.default.red(`Error: Unsupported target '${target}'.`));
200
+ console.log(chalk_1.default.gray(`Supported targets: ${validTargets.join(', ')}`));
201
+ process.exit(1);
202
+ }
203
+ }
204
+ catch (error) {
205
+ spinner.stop();
206
+ console.error(chalk_1.default.red('Failed to install skill.'));
207
+ console.error(error);
208
+ process.exit(1);
209
+ }
210
+ });
211
+ program.parse();
@@ -0,0 +1,6 @@
1
+ export interface Skill {
2
+ name: string;
3
+ description: string;
4
+ content: string;
5
+ globs?: string;
6
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@opendirectory.dev/skills",
3
+ "version": "0.1.0",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "bin": {
7
+ "opendirectory": "dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc && node -e \"require('fs').cpSync('../../skills', './skills', {recursive: true})\"",
11
+ "dev": "tsc -w",
12
+ "test:e2e": "vitest run src/e2e.test.ts"
13
+ },
14
+ "dependencies": {
15
+ "chalk": "^4.1.2",
16
+ "cli-table3": "^0.6.5",
17
+ "commander": "^14.0.3",
18
+ "ora": "^5.4.1"
19
+ },
20
+ "devDependencies": {
21
+ "@types/ora": "^3.2.0",
22
+ "typescript": "^5.0.0",
23
+ "vitest": "^1.6.1"
24
+ }
25
+ }