@jcheesepkg/nanobot 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 (130) hide show
  1. package/README.md +139 -0
  2. package/dist/_virtual/_rolldown/runtime.mjs +40 -0
  3. package/dist/agent/context.d.mts +44 -0
  4. package/dist/agent/context.d.mts.map +1 -0
  5. package/dist/agent/context.mjs +153 -0
  6. package/dist/agent/context.mjs.map +1 -0
  7. package/dist/agent/loop.d.mts +56 -0
  8. package/dist/agent/loop.d.mts.map +1 -0
  9. package/dist/agent/loop.mjs +232 -0
  10. package/dist/agent/loop.mjs.map +1 -0
  11. package/dist/agent/memory.d.mts +30 -0
  12. package/dist/agent/memory.d.mts.map +1 -0
  13. package/dist/agent/memory.mjs +77 -0
  14. package/dist/agent/memory.mjs.map +1 -0
  15. package/dist/agent/skills.d.mts +43 -0
  16. package/dist/agent/skills.d.mts.map +1 -0
  17. package/dist/agent/skills.mjs +159 -0
  18. package/dist/agent/skills.mjs.map +1 -0
  19. package/dist/agent/subagent.d.mts +39 -0
  20. package/dist/agent/subagent.d.mts.map +1 -0
  21. package/dist/agent/subagent.mjs +167 -0
  22. package/dist/agent/subagent.mjs.map +1 -0
  23. package/dist/agent/tools/base.d.mts +16 -0
  24. package/dist/agent/tools/base.d.mts.map +1 -0
  25. package/dist/agent/tools/base.mjs +19 -0
  26. package/dist/agent/tools/base.mjs.map +1 -0
  27. package/dist/agent/tools/cron.d.mts +49 -0
  28. package/dist/agent/tools/cron.d.mts.map +1 -0
  29. package/dist/agent/tools/cron.mjs +101 -0
  30. package/dist/agent/tools/cron.mjs.map +1 -0
  31. package/dist/agent/tools/filesystem.d.mts +87 -0
  32. package/dist/agent/tools/filesystem.d.mts.map +1 -0
  33. package/dist/agent/tools/filesystem.mjs +145 -0
  34. package/dist/agent/tools/filesystem.mjs.map +1 -0
  35. package/dist/agent/tools/message.d.mts +44 -0
  36. package/dist/agent/tools/message.d.mts.map +1 -0
  37. package/dist/agent/tools/message.mjs +68 -0
  38. package/dist/agent/tools/message.mjs.map +1 -0
  39. package/dist/agent/tools/registry.d.mts +29 -0
  40. package/dist/agent/tools/registry.d.mts.map +1 -0
  41. package/dist/agent/tools/registry.mjs +49 -0
  42. package/dist/agent/tools/registry.mjs.map +1 -0
  43. package/dist/agent/tools/shell.d.mts +36 -0
  44. package/dist/agent/tools/shell.d.mts.map +1 -0
  45. package/dist/agent/tools/shell.mjs +73 -0
  46. package/dist/agent/tools/shell.mjs.map +1 -0
  47. package/dist/agent/tools/spawn.d.mts +35 -0
  48. package/dist/agent/tools/spawn.d.mts.map +1 -0
  49. package/dist/agent/tools/spawn.mjs +50 -0
  50. package/dist/agent/tools/spawn.mjs.map +1 -0
  51. package/dist/agent/tools/web.d.mts +63 -0
  52. package/dist/agent/tools/web.d.mts.map +1 -0
  53. package/dist/agent/tools/web.mjs +195 -0
  54. package/dist/agent/tools/web.mjs.map +1 -0
  55. package/dist/bus/events.d.mts +29 -0
  56. package/dist/bus/events.d.mts.map +1 -0
  57. package/dist/bus/events.mjs +30 -0
  58. package/dist/bus/events.mjs.map +1 -0
  59. package/dist/bus/queue.d.mts +38 -0
  60. package/dist/bus/queue.d.mts.map +1 -0
  61. package/dist/bus/queue.mjs +90 -0
  62. package/dist/bus/queue.mjs.map +1 -0
  63. package/dist/channels/base.d.mts +31 -0
  64. package/dist/channels/base.d.mts.map +1 -0
  65. package/dist/channels/base.mjs +49 -0
  66. package/dist/channels/base.mjs.map +1 -0
  67. package/dist/channels/manager.d.mts +30 -0
  68. package/dist/channels/manager.d.mts.map +1 -0
  69. package/dist/channels/manager.mjs +100 -0
  70. package/dist/channels/manager.mjs.map +1 -0
  71. package/dist/channels/telegram.d.mts +23 -0
  72. package/dist/channels/telegram.d.mts.map +1 -0
  73. package/dist/channels/telegram.mjs +161 -0
  74. package/dist/channels/telegram.mjs.map +1 -0
  75. package/dist/cli/index.d.mts +1 -0
  76. package/dist/cli/index.mjs +337 -0
  77. package/dist/cli/index.mjs.map +1 -0
  78. package/dist/config/loader.d.mts +14 -0
  79. package/dist/config/loader.d.mts.map +1 -0
  80. package/dist/config/loader.mjs +40 -0
  81. package/dist/config/loader.mjs.map +1 -0
  82. package/dist/config/schema.d.mts +724 -0
  83. package/dist/config/schema.d.mts.map +1 -0
  84. package/dist/config/schema.mjs +123 -0
  85. package/dist/config/schema.mjs.map +1 -0
  86. package/dist/cron/service.d.mts +42 -0
  87. package/dist/cron/service.d.mts.map +1 -0
  88. package/dist/cron/service.mjs +256 -0
  89. package/dist/cron/service.mjs.map +1 -0
  90. package/dist/cron/types.d.mts +55 -0
  91. package/dist/cron/types.d.mts.map +1 -0
  92. package/dist/cron/types.mjs +30 -0
  93. package/dist/cron/types.mjs.map +1 -0
  94. package/dist/heartbeat/service.d.mts +29 -0
  95. package/dist/heartbeat/service.d.mts.map +1 -0
  96. package/dist/heartbeat/service.mjs +96 -0
  97. package/dist/heartbeat/service.mjs.map +1 -0
  98. package/dist/index.d.mts +23 -0
  99. package/dist/index.d.mts.map +1 -0
  100. package/dist/index.mjs +23 -0
  101. package/dist/index.mjs.map +1 -0
  102. package/dist/providers/base.d.mts +65 -0
  103. package/dist/providers/base.d.mts.map +1 -0
  104. package/dist/providers/base.mjs +1 -0
  105. package/dist/providers/openai-provider.d.mts +27 -0
  106. package/dist/providers/openai-provider.d.mts.map +1 -0
  107. package/dist/providers/openai-provider.mjs +67 -0
  108. package/dist/providers/openai-provider.mjs.map +1 -0
  109. package/dist/providers/transcription.d.mts +14 -0
  110. package/dist/providers/transcription.d.mts.map +1 -0
  111. package/dist/providers/transcription.mjs +46 -0
  112. package/dist/providers/transcription.mjs.map +1 -0
  113. package/dist/session/manager.d.mts +56 -0
  114. package/dist/session/manager.d.mts.map +1 -0
  115. package/dist/session/manager.mjs +144 -0
  116. package/dist/session/manager.mjs.map +1 -0
  117. package/dist/utils/helpers.d.mts +26 -0
  118. package/dist/utils/helpers.d.mts.map +1 -0
  119. package/dist/utils/helpers.mjs +60 -0
  120. package/dist/utils/helpers.mjs.map +1 -0
  121. package/dist/utils/which.d.mts +6 -0
  122. package/dist/utils/which.d.mts.map +1 -0
  123. package/dist/utils/which.mjs +20 -0
  124. package/dist/utils/which.mjs.map +1 -0
  125. package/package.json +45 -0
  126. package/skills/cron/SKILL.md +40 -0
  127. package/skills/github/SKILL.md +48 -0
  128. package/skills/skill-creator/SKILL.md +73 -0
  129. package/skills/summarize/SKILL.md +47 -0
  130. package/skills/weather/SKILL.md +43 -0
@@ -0,0 +1,26 @@
1
+ //#region src/utils/helpers.d.ts
2
+ /** Ensure a directory exists, creating it if necessary. */
3
+ declare function ensureDir(dirPath: string): string;
4
+ /** Get the nanobot data directory (~/.nanobot). */
5
+ declare function getDataPath(): string;
6
+ /** Get the workspace path. Defaults to ~/.nanobot/workspace. */
7
+ declare function getWorkspacePath(workspace?: string): string;
8
+ /** Get the sessions storage directory. */
9
+ declare function getSessionsPath(): string;
10
+ /** Get the memory directory within the workspace. */
11
+ declare function getMemoryPath(workspace?: string): string;
12
+ /** Get the skills directory within the workspace. */
13
+ declare function getSkillsPath(workspace?: string): string;
14
+ /** Get today's date in YYYY-MM-DD format. */
15
+ declare function todayDate(): string;
16
+ /** Get current timestamp in ISO format. */
17
+ declare function timestamp(): string;
18
+ /** Truncate a string to max length, adding suffix if truncated. */
19
+ declare function truncateString(s: string, maxLen?: number, suffix?: string): string;
20
+ /** Convert a string to a safe filename. */
21
+ declare function safeFilename(name: string): string;
22
+ /** Parse a session key into channel and chat_id. */
23
+ declare function parseSessionKey(key: string): [string, string];
24
+ //#endregion
25
+ export { ensureDir, getDataPath, getMemoryPath, getSessionsPath, getSkillsPath, getWorkspacePath, parseSessionKey, safeFilename, timestamp, todayDate, truncateString };
26
+ //# sourceMappingURL=helpers.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.mts","names":[],"sources":["../../src/utils/helpers.ts"],"mappings":";;iBAKgB,SAAA,CAAU,OAAA;;iBAQV,WAAA,CAAA;;iBAKA,gBAAA,CAAiB,SAAA;AALjC;AAAA,iBAagB,eAAA,CAAA;;iBAKA,aAAA,CAAc,SAAA;;iBAMd,aAAA,CAAc,SAAA;;iBAMd,SAAA,CAAA;;iBAKA,SAAA,CAAA;AAtBhB;AAAA,iBA2BgB,cAAA,CACd,CAAA,UACA,MAAA,WACA,MAAA;;iBAOc,YAAA,CAAa,IAAA;;iBAUb,eAAA,CAAgB,GAAA"}
@@ -0,0 +1,60 @@
1
+ import { existsSync, mkdirSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir } from "node:os";
4
+
5
+ //#region src/utils/helpers.ts
6
+ /** Ensure a directory exists, creating it if necessary. */
7
+ function ensureDir(dirPath) {
8
+ if (!existsSync(dirPath)) mkdirSync(dirPath, { recursive: true });
9
+ return dirPath;
10
+ }
11
+ /** Get the nanobot data directory (~/.nanobot). */
12
+ function getDataPath() {
13
+ return ensureDir(join(homedir(), ".nanobot"));
14
+ }
15
+ /** Get the workspace path. Defaults to ~/.nanobot/workspace. */
16
+ function getWorkspacePath(workspace) {
17
+ return ensureDir(workspace ? workspace.replace(/^~/, homedir()) : join(homedir(), ".nanobot", "workspace"));
18
+ }
19
+ /** Get the sessions storage directory. */
20
+ function getSessionsPath() {
21
+ return ensureDir(join(getDataPath(), "sessions"));
22
+ }
23
+ /** Get the memory directory within the workspace. */
24
+ function getMemoryPath(workspace) {
25
+ return ensureDir(join(workspace ?? getWorkspacePath(), "memory"));
26
+ }
27
+ /** Get the skills directory within the workspace. */
28
+ function getSkillsPath(workspace) {
29
+ return ensureDir(join(workspace ?? getWorkspacePath(), "skills"));
30
+ }
31
+ /** Get today's date in YYYY-MM-DD format. */
32
+ function todayDate() {
33
+ return (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
34
+ }
35
+ /** Get current timestamp in ISO format. */
36
+ function timestamp() {
37
+ return (/* @__PURE__ */ new Date()).toISOString();
38
+ }
39
+ /** Truncate a string to max length, adding suffix if truncated. */
40
+ function truncateString(s, maxLen = 100, suffix = "...") {
41
+ if (s.length <= maxLen) return s;
42
+ return s.slice(0, maxLen - suffix.length) + suffix;
43
+ }
44
+ /** Convert a string to a safe filename. */
45
+ function safeFilename(name) {
46
+ const unsafe = "<>:\"/\\|?*";
47
+ let result = name;
48
+ for (const char of unsafe) result = result.replaceAll(char, "_");
49
+ return result.trim();
50
+ }
51
+ /** Parse a session key into channel and chat_id. */
52
+ function parseSessionKey(key) {
53
+ const idx = key.indexOf(":");
54
+ if (idx === -1) throw new Error(`Invalid session key: ${key}`);
55
+ return [key.slice(0, idx), key.slice(idx + 1)];
56
+ }
57
+
58
+ //#endregion
59
+ export { ensureDir, getDataPath, getMemoryPath, getSessionsPath, getSkillsPath, getWorkspacePath, parseSessionKey, safeFilename, timestamp, todayDate, truncateString };
60
+ //# sourceMappingURL=helpers.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.mjs","names":[],"sources":["../../src/utils/helpers.ts"],"sourcesContent":["import { mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\n\n/** Ensure a directory exists, creating it if necessary. */\nexport function ensureDir(dirPath: string): string {\n if (!existsSync(dirPath)) {\n mkdirSync(dirPath, { recursive: true });\n }\n return dirPath;\n}\n\n/** Get the nanobot data directory (~/.nanobot). */\nexport function getDataPath(): string {\n return ensureDir(join(homedir(), \".nanobot\"));\n}\n\n/** Get the workspace path. Defaults to ~/.nanobot/workspace. */\nexport function getWorkspacePath(workspace?: string): string {\n const resolved = workspace\n ? workspace.replace(/^~/, homedir())\n : join(homedir(), \".nanobot\", \"workspace\");\n return ensureDir(resolved);\n}\n\n/** Get the sessions storage directory. */\nexport function getSessionsPath(): string {\n return ensureDir(join(getDataPath(), \"sessions\"));\n}\n\n/** Get the memory directory within the workspace. */\nexport function getMemoryPath(workspace?: string): string {\n const ws = workspace ?? getWorkspacePath();\n return ensureDir(join(ws, \"memory\"));\n}\n\n/** Get the skills directory within the workspace. */\nexport function getSkillsPath(workspace?: string): string {\n const ws = workspace ?? getWorkspacePath();\n return ensureDir(join(ws, \"skills\"));\n}\n\n/** Get today's date in YYYY-MM-DD format. */\nexport function todayDate(): string {\n return new Date().toISOString().slice(0, 10);\n}\n\n/** Get current timestamp in ISO format. */\nexport function timestamp(): string {\n return new Date().toISOString();\n}\n\n/** Truncate a string to max length, adding suffix if truncated. */\nexport function truncateString(\n s: string,\n maxLen = 100,\n suffix = \"...\",\n): string {\n if (s.length <= maxLen) return s;\n return s.slice(0, maxLen - suffix.length) + suffix;\n}\n\n/** Convert a string to a safe filename. */\nexport function safeFilename(name: string): string {\n const unsafe = '<>:\"/\\\\|?*';\n let result = name;\n for (const char of unsafe) {\n result = result.replaceAll(char, \"_\");\n }\n return result.trim();\n}\n\n/** Parse a session key into channel and chat_id. */\nexport function parseSessionKey(key: string): [string, string] {\n const idx = key.indexOf(\":\");\n if (idx === -1) {\n throw new Error(`Invalid session key: ${key}`);\n }\n return [key.slice(0, idx), key.slice(idx + 1)];\n}\n"],"mappings":";;;;;;AAKA,SAAgB,UAAU,SAAyB;AACjD,KAAI,CAAC,WAAW,QAAQ,CACtB,WAAU,SAAS,EAAE,WAAW,MAAM,CAAC;AAEzC,QAAO;;;AAIT,SAAgB,cAAsB;AACpC,QAAO,UAAU,KAAK,SAAS,EAAE,WAAW,CAAC;;;AAI/C,SAAgB,iBAAiB,WAA4B;AAI3D,QAAO,UAHU,YACb,UAAU,QAAQ,MAAM,SAAS,CAAC,GAClC,KAAK,SAAS,EAAE,YAAY,YAAY,CAClB;;;AAI5B,SAAgB,kBAA0B;AACxC,QAAO,UAAU,KAAK,aAAa,EAAE,WAAW,CAAC;;;AAInD,SAAgB,cAAc,WAA4B;AAExD,QAAO,UAAU,KADN,aAAa,kBAAkB,EAChB,SAAS,CAAC;;;AAItC,SAAgB,cAAc,WAA4B;AAExD,QAAO,UAAU,KADN,aAAa,kBAAkB,EAChB,SAAS,CAAC;;;AAItC,SAAgB,YAAoB;AAClC,yBAAO,IAAI,MAAM,EAAC,aAAa,CAAC,MAAM,GAAG,GAAG;;;AAI9C,SAAgB,YAAoB;AAClC,yBAAO,IAAI,MAAM,EAAC,aAAa;;;AAIjC,SAAgB,eACd,GACA,SAAS,KACT,SAAS,OACD;AACR,KAAI,EAAE,UAAU,OAAQ,QAAO;AAC/B,QAAO,EAAE,MAAM,GAAG,SAAS,OAAO,OAAO,GAAG;;;AAI9C,SAAgB,aAAa,MAAsB;CACjD,MAAM,SAAS;CACf,IAAI,SAAS;AACb,MAAK,MAAM,QAAQ,OACjB,UAAS,OAAO,WAAW,MAAM,IAAI;AAEvC,QAAO,OAAO,MAAM;;;AAItB,SAAgB,gBAAgB,KAA+B;CAC7D,MAAM,MAAM,IAAI,QAAQ,IAAI;AAC5B,KAAI,QAAQ,GACV,OAAM,IAAI,MAAM,wBAAwB,MAAM;AAEhD,QAAO,CAAC,IAAI,MAAM,GAAG,IAAI,EAAE,IAAI,MAAM,MAAM,EAAE,CAAC"}
@@ -0,0 +1,6 @@
1
+ //#region src/utils/which.d.ts
2
+ /** Simple `which` implementation - find a binary in PATH. */
3
+ declare function which(name: string): string | null;
4
+ //#endregion
5
+ export { which };
6
+ //# sourceMappingURL=which.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"which.d.mts","names":[],"sources":["../../src/utils/which.ts"],"mappings":";;iBAIgB,KAAA,CAAM,IAAA"}
@@ -0,0 +1,20 @@
1
+ import { accessSync, constants } from "node:fs";
2
+ import { join } from "node:path";
3
+
4
+ //#region src/utils/which.ts
5
+ /** Simple `which` implementation - find a binary in PATH. */
6
+ function which(name) {
7
+ const pathDirs = (process.env.PATH ?? "").split(":");
8
+ for (const dir of pathDirs) {
9
+ const fullPath = join(dir, name);
10
+ try {
11
+ accessSync(fullPath, constants.X_OK);
12
+ return fullPath;
13
+ } catch {}
14
+ }
15
+ return null;
16
+ }
17
+
18
+ //#endregion
19
+ export { which };
20
+ //# sourceMappingURL=which.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"which.mjs","names":[],"sources":["../../src/utils/which.ts"],"sourcesContent":["import { existsSync, accessSync, constants } from \"node:fs\";\nimport { join } from \"node:path\";\n\n/** Simple `which` implementation - find a binary in PATH. */\nexport function which(name: string): string | null {\n const pathDirs = (process.env.PATH ?? \"\").split(\":\");\n for (const dir of pathDirs) {\n const fullPath = join(dir, name);\n try {\n accessSync(fullPath, constants.X_OK);\n return fullPath;\n } catch {\n // not found in this dir\n }\n }\n return null;\n}\n"],"mappings":";;;;;AAIA,SAAgB,MAAM,MAA6B;CACjD,MAAM,YAAY,QAAQ,IAAI,QAAQ,IAAI,MAAM,IAAI;AACpD,MAAK,MAAM,OAAO,UAAU;EAC1B,MAAM,WAAW,KAAK,KAAK,KAAK;AAChC,MAAI;AACF,cAAW,UAAU,UAAU,KAAK;AACpC,UAAO;UACD;;AAIV,QAAO"}
package/package.json ADDED
@@ -0,0 +1,45 @@
1
+ {
2
+ "name": "@jcheesepkg/nanobot",
3
+ "version": "0.1.0",
4
+ "description": "Lightweight AI assistant - TypeScript port",
5
+ "type": "module",
6
+ "main": "dist/index.mjs",
7
+ "types": "dist/index.d.mts",
8
+ "bin": {
9
+ "nanobot": "dist/cli/index.mjs"
10
+ },
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.mts",
14
+ "import": "./dist/index.mjs"
15
+ }
16
+ },
17
+ "scripts": {
18
+ "build": "tsdown",
19
+ "dev": "tsx src/cli/index.ts",
20
+ "start": "node dist/cli/index.mjs",
21
+ "typecheck": "tsc --noEmit"
22
+ },
23
+ "dependencies": {
24
+ "commander": "^12.1.0",
25
+ "cron-parser": "^4.9.0",
26
+ "grammy": "^1.30.0",
27
+ "openai": "^4.73.0",
28
+ "zod": "^3.23.0"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^22.0.0",
32
+ "tsdown": "^0.20.3",
33
+ "tsx": "^4.19.0",
34
+ "typescript": "^5.6.0"
35
+ },
36
+ "engines": {
37
+ "node": ">=18.0.0"
38
+ },
39
+ "files": [
40
+ "dist",
41
+ "skills",
42
+ "workspace"
43
+ ],
44
+ "license": "MIT"
45
+ }
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: cron
3
+ description: Schedule reminders and recurring tasks.
4
+ ---
5
+
6
+ # Cron
7
+
8
+ Use the `cron` tool to schedule reminders or recurring tasks.
9
+
10
+ ## Two Modes
11
+
12
+ 1. **Reminder** - message is sent directly to user
13
+ 2. **Task** - message is a task description, agent executes and sends result
14
+
15
+ ## Examples
16
+
17
+ Fixed reminder:
18
+ ```
19
+ cron(action="add", message="Time to take a break!", every_seconds=1200)
20
+ ```
21
+
22
+ Dynamic task (agent executes each time):
23
+ ```
24
+ cron(action="add", message="Check HKUDS/nanobot GitHub stars and report", every_seconds=600)
25
+ ```
26
+
27
+ List/remove:
28
+ ```
29
+ cron(action="list")
30
+ cron(action="remove", job_id="abc123")
31
+ ```
32
+
33
+ ## Time Expressions
34
+
35
+ | User says | Parameters |
36
+ |-----------|------------|
37
+ | every 20 minutes | every_seconds: 1200 |
38
+ | every hour | every_seconds: 3600 |
39
+ | every day at 8am | cron_expr: "0 8 * * *" |
40
+ | weekdays at 5pm | cron_expr: "0 17 * * 1-5" |
@@ -0,0 +1,48 @@
1
+ ---
2
+ name: github
3
+ description: "Interact with GitHub using the `gh` CLI. Use `gh issue`, `gh pr`, `gh run`, and `gh api` for issues, PRs, CI runs, and advanced queries."
4
+ metadata: {"nanobot":{"emoji":"octopus","requires":{"bins":["gh"]}}}
5
+ ---
6
+
7
+ # GitHub Skill
8
+
9
+ Use the `gh` CLI to interact with GitHub. Always specify `--repo owner/repo` when not in a git directory, or use URLs directly.
10
+
11
+ ## Pull Requests
12
+
13
+ Check CI status on a PR:
14
+ ```bash
15
+ gh pr checks 55 --repo owner/repo
16
+ ```
17
+
18
+ List recent workflow runs:
19
+ ```bash
20
+ gh run list --repo owner/repo --limit 10
21
+ ```
22
+
23
+ View a run and see which steps failed:
24
+ ```bash
25
+ gh run view <run-id> --repo owner/repo
26
+ ```
27
+
28
+ View logs for failed steps only:
29
+ ```bash
30
+ gh run view <run-id> --repo owner/repo --log-failed
31
+ ```
32
+
33
+ ## API for Advanced Queries
34
+
35
+ The `gh api` command is useful for accessing data not available through other subcommands.
36
+
37
+ Get PR with specific fields:
38
+ ```bash
39
+ gh api repos/owner/repo/pulls/55 --jq '.title, .state, .user.login'
40
+ ```
41
+
42
+ ## JSON Output
43
+
44
+ Most commands support `--json` for structured output. You can use `--jq` to filter:
45
+
46
+ ```bash
47
+ gh issue list --repo owner/repo --json number,title --jq '.[] | "\(.number): \(.title)"'
48
+ ```
@@ -0,0 +1,73 @@
1
+ ---
2
+ name: skill-creator
3
+ description: Create or update AgentSkills. Use when designing, structuring, or packaging skills with scripts, references, and assets.
4
+ ---
5
+
6
+ # Skill Creator
7
+
8
+ This skill provides guidance for creating effective skills.
9
+
10
+ ## About Skills
11
+
12
+ Skills are modular, self-contained packages that extend the agent's capabilities by providing
13
+ specialized knowledge, workflows, and tools. They transform the agent from a general-purpose
14
+ assistant into a specialized one equipped with procedural knowledge.
15
+
16
+ ### What Skills Provide
17
+
18
+ 1. Specialized workflows - Multi-step procedures for specific domains
19
+ 2. Tool integrations - Instructions for working with specific file formats or APIs
20
+ 3. Domain expertise - Company-specific knowledge, schemas, business logic
21
+ 4. Bundled resources - Scripts, references, and assets for complex tasks
22
+
23
+ ## Core Principles
24
+
25
+ ### Concise is Key
26
+
27
+ The context window is a shared resource. Only add context the agent doesn't already have. Prefer concise examples over verbose explanations.
28
+
29
+ ### Anatomy of a Skill
30
+
31
+ ```
32
+ skill-name/
33
+ SKILL.md (required)
34
+ - YAML frontmatter: name, description
35
+ - Markdown instructions
36
+ scripts/ (optional) - Executable code
37
+ references/ (optional) - Documentation for context
38
+ assets/ (optional) - Files used in output
39
+ ```
40
+
41
+ #### SKILL.md
42
+
43
+ - **Frontmatter** (YAML): `name` and `description` fields. Description is the primary triggering mechanism.
44
+ - **Body** (Markdown): Instructions loaded after the skill triggers.
45
+
46
+ ### Progressive Disclosure
47
+
48
+ Skills use three-level loading:
49
+
50
+ 1. **Metadata (name + description)** - Always in context (~100 words)
51
+ 2. **SKILL.md body** - When skill triggers (<5k words)
52
+ 3. **Bundled resources** - As needed (unlimited)
53
+
54
+ ## Skill Creation Process
55
+
56
+ 1. Understand the skill with concrete examples
57
+ 2. Plan reusable contents (scripts, references, assets)
58
+ 3. Create SKILL.md with proper frontmatter
59
+ 4. Implement resources and instructions
60
+ 5. Test and iterate based on real usage
61
+
62
+ ### Naming
63
+
64
+ - Lowercase, digits, hyphens only
65
+ - Under 64 characters
66
+ - Prefer short, verb-led phrases
67
+ - Namespace by tool when helpful (e.g., `gh-address-comments`)
68
+
69
+ ### Frontmatter Guidelines
70
+
71
+ - `name`: The skill name
72
+ - `description`: What the skill does AND when to use it. Include trigger contexts.
73
+ All "when to use" info goes here since the body only loads after triggering.
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: summarize
3
+ description: Summarize or extract text/transcripts from URLs, podcasts, and local files (great fallback for "transcribe this YouTube/video").
4
+ ---
5
+
6
+ # Summarize
7
+
8
+ Fast CLI to summarize URLs, local files, and YouTube links.
9
+
10
+ ## When to use (trigger phrases)
11
+
12
+ Use this skill immediately when the user asks any of:
13
+ - "what's this link/video about?"
14
+ - "summarize this URL/article"
15
+ - "transcribe this YouTube/video" (best-effort transcript extraction)
16
+
17
+ ## Quick start
18
+
19
+ ```bash
20
+ summarize "https://example.com" --model google/gemini-3-flash-preview
21
+ summarize "/path/to/file.pdf" --model google/gemini-3-flash-preview
22
+ summarize "https://youtu.be/dQw4w9WgXcQ" --youtube auto
23
+ ```
24
+
25
+ ## YouTube: summary vs transcript
26
+
27
+ Best-effort transcript (URLs only):
28
+
29
+ ```bash
30
+ summarize "https://youtu.be/dQw4w9WgXcQ" --youtube auto --extract-only
31
+ ```
32
+
33
+ If the user asked for a transcript but it's huge, return a tight summary first, then ask which section/time range to expand.
34
+
35
+ ## Model + keys
36
+
37
+ Set the API key for your chosen provider:
38
+ - OpenAI: `OPENAI_API_KEY`
39
+ - Anthropic: `ANTHROPIC_API_KEY`
40
+ - Google: `GEMINI_API_KEY`
41
+
42
+ ## Useful flags
43
+
44
+ - `--length short|medium|long|xl|xxl|<chars>`
45
+ - `--max-output-tokens <count>`
46
+ - `--extract-only` (URLs only)
47
+ - `--json` (machine readable)
@@ -0,0 +1,43 @@
1
+ ---
2
+ name: weather
3
+ description: Get current weather and forecasts (no API key required).
4
+ ---
5
+
6
+ # Weather
7
+
8
+ Two free services, no API keys needed.
9
+
10
+ ## wttr.in (primary)
11
+
12
+ Quick one-liner:
13
+ ```bash
14
+ curl -s "wttr.in/London?format=3"
15
+ # Output: London: +8C
16
+ ```
17
+
18
+ Compact format:
19
+ ```bash
20
+ curl -s "wttr.in/London?format=%l:+%c+%t+%h+%w"
21
+ ```
22
+
23
+ Full forecast:
24
+ ```bash
25
+ curl -s "wttr.in/London?T"
26
+ ```
27
+
28
+ Format codes: `%c` condition, `%t` temp, `%h` humidity, `%w` wind, `%l` location, `%m` moon
29
+
30
+ Tips:
31
+ - URL-encode spaces: `wttr.in/New+York`
32
+ - Airport codes: `wttr.in/JFK`
33
+ - Units: `?m` (metric) `?u` (USCS)
34
+ - Today only: `?1` / Current only: `?0`
35
+
36
+ ## Open-Meteo (fallback, JSON)
37
+
38
+ Free, no key, good for programmatic use:
39
+ ```bash
40
+ curl -s "https://api.open-meteo.com/v1/forecast?latitude=51.5&longitude=-0.12&current_weather=true"
41
+ ```
42
+
43
+ Find coordinates for a city, then query. Returns JSON with temp, windspeed, weathercode.