gsd-pi 2.28.0-dev.e19bf89 → 2.29.0-dev.2ccf3fb

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 (256) hide show
  1. package/README.md +24 -17
  2. package/dist/cli.js +15 -9
  3. package/dist/resource-loader.js +80 -8
  4. package/dist/resources/extensions/bg-shell/process-manager.ts +13 -0
  5. package/dist/resources/extensions/gsd/auto-dashboard.ts +186 -65
  6. package/dist/resources/extensions/gsd/auto-post-unit.ts +14 -6
  7. package/dist/resources/extensions/gsd/auto-recovery.ts +33 -23
  8. package/dist/resources/extensions/gsd/auto-start.ts +25 -10
  9. package/dist/resources/extensions/gsd/auto-verification.ts +41 -7
  10. package/dist/resources/extensions/gsd/auto-worktree-sync.ts +21 -6
  11. package/dist/resources/extensions/gsd/auto.ts +67 -22
  12. package/dist/resources/extensions/gsd/commands-handlers.ts +3 -11
  13. package/dist/resources/extensions/gsd/commands-logs.ts +536 -0
  14. package/dist/resources/extensions/gsd/commands-prefs-wizard.ts +90 -47
  15. package/dist/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
  16. package/dist/resources/extensions/gsd/commands.ts +75 -29
  17. package/dist/resources/extensions/gsd/dashboard-overlay.ts +2 -1
  18. package/dist/resources/extensions/gsd/doctor-types.ts +13 -0
  19. package/dist/resources/extensions/gsd/doctor.ts +2 -6
  20. package/dist/resources/extensions/gsd/export.ts +28 -2
  21. package/dist/resources/extensions/gsd/gsd-db.ts +19 -0
  22. package/dist/resources/extensions/gsd/index.ts +2 -1
  23. package/dist/resources/extensions/gsd/json-persistence.ts +67 -0
  24. package/dist/resources/extensions/gsd/metrics.ts +17 -31
  25. package/dist/resources/extensions/gsd/paths.ts +0 -8
  26. package/dist/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  27. package/dist/resources/extensions/gsd/prompts/workflow-start.md +28 -0
  28. package/dist/resources/extensions/gsd/queue-order.ts +10 -11
  29. package/dist/resources/extensions/gsd/routing-history.ts +13 -17
  30. package/dist/resources/extensions/gsd/session-lock.ts +284 -0
  31. package/dist/resources/extensions/gsd/session-status-io.ts +23 -41
  32. package/dist/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
  33. package/dist/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
  34. package/dist/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
  35. package/dist/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
  36. package/dist/resources/extensions/gsd/tests/gsd-inspect.test.ts +1 -1
  37. package/dist/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
  38. package/dist/resources/extensions/gsd/tests/session-lock.test.ts +315 -0
  39. package/dist/resources/extensions/gsd/tests/validate-milestone.test.ts +55 -0
  40. package/dist/resources/extensions/gsd/tests/verification-evidence.test.ts +26 -24
  41. package/dist/resources/extensions/gsd/tests/verification-gate.test.ts +136 -7
  42. package/dist/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
  43. package/dist/resources/extensions/gsd/types.ts +1 -0
  44. package/dist/resources/extensions/gsd/unit-runtime.ts +16 -13
  45. package/dist/resources/extensions/gsd/verification-evidence.ts +2 -0
  46. package/dist/resources/extensions/gsd/verification-gate.ts +13 -2
  47. package/dist/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
  48. package/dist/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
  49. package/dist/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
  50. package/dist/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
  51. package/dist/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
  52. package/dist/resources/extensions/gsd/workflow-templates/registry.json +85 -0
  53. package/dist/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
  54. package/dist/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
  55. package/dist/resources/extensions/gsd/workflow-templates/spike.md +69 -0
  56. package/dist/resources/extensions/gsd/workflow-templates.ts +241 -0
  57. package/dist/resources/extensions/mcp-client/index.ts +459 -0
  58. package/dist/resources/extensions/remote-questions/discord-adapter.ts +9 -20
  59. package/dist/resources/extensions/remote-questions/http-client.ts +76 -0
  60. package/dist/resources/extensions/remote-questions/notify.ts +1 -2
  61. package/dist/resources/extensions/remote-questions/slack-adapter.ts +11 -18
  62. package/dist/resources/extensions/remote-questions/telegram-adapter.ts +8 -20
  63. package/dist/resources/extensions/remote-questions/types.ts +3 -0
  64. package/dist/resources/extensions/shared/mod.ts +3 -0
  65. package/dist/resources/skills/create-gsd-extension/SKILL.md +87 -0
  66. package/dist/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
  67. package/dist/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
  68. package/dist/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
  69. package/dist/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
  70. package/dist/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
  71. package/dist/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
  72. package/dist/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
  73. package/dist/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
  74. package/dist/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
  75. package/dist/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
  76. package/dist/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
  77. package/dist/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
  78. package/dist/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
  79. package/dist/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
  80. package/dist/resources/skills/create-gsd-extension/references/state-management.md +70 -0
  81. package/dist/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
  82. package/dist/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
  83. package/dist/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
  84. package/dist/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
  85. package/dist/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
  86. package/dist/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
  87. package/dist/resources/skills/create-skill/SKILL.md +184 -0
  88. package/dist/resources/skills/create-skill/references/api-security.md +226 -0
  89. package/dist/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
  90. package/dist/resources/skills/create-skill/references/common-patterns.md +595 -0
  91. package/dist/resources/skills/create-skill/references/core-principles.md +437 -0
  92. package/dist/resources/skills/create-skill/references/executable-code.md +175 -0
  93. package/dist/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
  94. package/dist/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
  95. package/dist/resources/skills/create-skill/references/recommended-structure.md +168 -0
  96. package/dist/resources/skills/create-skill/references/skill-structure.md +372 -0
  97. package/dist/resources/skills/create-skill/references/use-xml-tags.md +466 -0
  98. package/dist/resources/skills/create-skill/references/using-scripts.md +113 -0
  99. package/dist/resources/skills/create-skill/references/using-templates.md +112 -0
  100. package/dist/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
  101. package/dist/resources/skills/create-skill/templates/router-skill.md +73 -0
  102. package/dist/resources/skills/create-skill/templates/simple-skill.md +33 -0
  103. package/dist/resources/skills/create-skill/workflows/add-reference.md +96 -0
  104. package/dist/resources/skills/create-skill/workflows/add-script.md +93 -0
  105. package/dist/resources/skills/create-skill/workflows/add-template.md +74 -0
  106. package/dist/resources/skills/create-skill/workflows/add-workflow.md +120 -0
  107. package/dist/resources/skills/create-skill/workflows/audit-skill.md +148 -0
  108. package/dist/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
  109. package/dist/resources/skills/create-skill/workflows/get-guidance.md +121 -0
  110. package/dist/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
  111. package/dist/resources/skills/create-skill/workflows/verify-skill.md +204 -0
  112. package/package.json +6 -3
  113. package/packages/native/dist/native.d.ts +2 -0
  114. package/packages/native/dist/native.js +19 -5
  115. package/packages/native/src/native.ts +23 -9
  116. package/packages/pi-coding-agent/dist/core/extensions/loader.d.ts.map +1 -1
  117. package/packages/pi-coding-agent/dist/core/extensions/loader.js +13 -0
  118. package/packages/pi-coding-agent/dist/core/extensions/loader.js.map +1 -1
  119. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts +3 -0
  120. package/packages/pi-coding-agent/dist/core/settings-manager.d.ts.map +1 -1
  121. package/packages/pi-coding-agent/dist/core/settings-manager.js +8 -0
  122. package/packages/pi-coding-agent/dist/core/settings-manager.js.map +1 -1
  123. package/packages/pi-coding-agent/dist/core/system-prompt.d.ts.map +1 -1
  124. package/packages/pi-coding-agent/dist/core/system-prompt.js +10 -0
  125. package/packages/pi-coding-agent/dist/core/system-prompt.js.map +1 -1
  126. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  127. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js +4 -1
  128. package/packages/pi-coding-agent/dist/modes/interactive/interactive-mode.js.map +1 -1
  129. package/packages/pi-coding-agent/package.json +1 -1
  130. package/packages/pi-coding-agent/scripts/copy-assets.cjs +39 -8
  131. package/packages/pi-coding-agent/src/core/extensions/loader.ts +13 -0
  132. package/packages/pi-coding-agent/src/core/settings-manager.ts +11 -0
  133. package/packages/pi-coding-agent/src/core/system-prompt.ts +11 -0
  134. package/packages/pi-coding-agent/src/modes/interactive/interactive-mode.ts +4 -1
  135. package/packages/pi-tui/dist/autocomplete.d.ts +3 -0
  136. package/packages/pi-tui/dist/autocomplete.d.ts.map +1 -1
  137. package/packages/pi-tui/dist/autocomplete.js +14 -0
  138. package/packages/pi-tui/dist/autocomplete.js.map +1 -1
  139. package/packages/pi-tui/src/autocomplete.ts +19 -1
  140. package/pkg/package.json +1 -1
  141. package/src/resources/extensions/bg-shell/process-manager.ts +13 -0
  142. package/src/resources/extensions/gsd/auto-dashboard.ts +186 -65
  143. package/src/resources/extensions/gsd/auto-post-unit.ts +14 -6
  144. package/src/resources/extensions/gsd/auto-recovery.ts +33 -23
  145. package/src/resources/extensions/gsd/auto-start.ts +25 -10
  146. package/src/resources/extensions/gsd/auto-verification.ts +41 -7
  147. package/src/resources/extensions/gsd/auto-worktree-sync.ts +21 -6
  148. package/src/resources/extensions/gsd/auto.ts +67 -22
  149. package/src/resources/extensions/gsd/commands-handlers.ts +3 -11
  150. package/src/resources/extensions/gsd/commands-logs.ts +536 -0
  151. package/src/resources/extensions/gsd/commands-prefs-wizard.ts +90 -47
  152. package/src/resources/extensions/gsd/commands-workflow-templates.ts +544 -0
  153. package/src/resources/extensions/gsd/commands.ts +75 -29
  154. package/src/resources/extensions/gsd/dashboard-overlay.ts +2 -1
  155. package/src/resources/extensions/gsd/doctor-types.ts +13 -0
  156. package/src/resources/extensions/gsd/doctor.ts +2 -6
  157. package/src/resources/extensions/gsd/export.ts +28 -2
  158. package/src/resources/extensions/gsd/gsd-db.ts +19 -0
  159. package/src/resources/extensions/gsd/index.ts +2 -1
  160. package/src/resources/extensions/gsd/json-persistence.ts +67 -0
  161. package/src/resources/extensions/gsd/metrics.ts +17 -31
  162. package/src/resources/extensions/gsd/paths.ts +0 -8
  163. package/src/resources/extensions/gsd/prompts/guided-discuss-milestone.md +1 -1
  164. package/src/resources/extensions/gsd/prompts/workflow-start.md +28 -0
  165. package/src/resources/extensions/gsd/queue-order.ts +10 -11
  166. package/src/resources/extensions/gsd/routing-history.ts +13 -17
  167. package/src/resources/extensions/gsd/session-lock.ts +284 -0
  168. package/src/resources/extensions/gsd/session-status-io.ts +23 -41
  169. package/src/resources/extensions/gsd/tests/auto-budget-alerts.test.ts +1 -1
  170. package/src/resources/extensions/gsd/tests/auto-skip-loop.test.ts +1 -1
  171. package/src/resources/extensions/gsd/tests/commands-logs.test.ts +241 -0
  172. package/src/resources/extensions/gsd/tests/extension-selector-separator.test.ts +60 -38
  173. package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +1 -1
  174. package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +1 -1
  175. package/src/resources/extensions/gsd/tests/session-lock.test.ts +315 -0
  176. package/src/resources/extensions/gsd/tests/validate-milestone.test.ts +55 -0
  177. package/src/resources/extensions/gsd/tests/verification-evidence.test.ts +26 -24
  178. package/src/resources/extensions/gsd/tests/verification-gate.test.ts +136 -7
  179. package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +173 -0
  180. package/src/resources/extensions/gsd/types.ts +1 -0
  181. package/src/resources/extensions/gsd/unit-runtime.ts +16 -13
  182. package/src/resources/extensions/gsd/verification-evidence.ts +2 -0
  183. package/src/resources/extensions/gsd/verification-gate.ts +13 -2
  184. package/src/resources/extensions/gsd/workflow-templates/bugfix.md +87 -0
  185. package/src/resources/extensions/gsd/workflow-templates/dep-upgrade.md +74 -0
  186. package/src/resources/extensions/gsd/workflow-templates/full-project.md +41 -0
  187. package/src/resources/extensions/gsd/workflow-templates/hotfix.md +45 -0
  188. package/src/resources/extensions/gsd/workflow-templates/refactor.md +83 -0
  189. package/src/resources/extensions/gsd/workflow-templates/registry.json +85 -0
  190. package/src/resources/extensions/gsd/workflow-templates/security-audit.md +73 -0
  191. package/src/resources/extensions/gsd/workflow-templates/small-feature.md +81 -0
  192. package/src/resources/extensions/gsd/workflow-templates/spike.md +69 -0
  193. package/src/resources/extensions/gsd/workflow-templates.ts +241 -0
  194. package/src/resources/extensions/mcp-client/index.ts +459 -0
  195. package/src/resources/extensions/remote-questions/discord-adapter.ts +9 -20
  196. package/src/resources/extensions/remote-questions/http-client.ts +76 -0
  197. package/src/resources/extensions/remote-questions/notify.ts +1 -2
  198. package/src/resources/extensions/remote-questions/slack-adapter.ts +11 -18
  199. package/src/resources/extensions/remote-questions/telegram-adapter.ts +8 -20
  200. package/src/resources/extensions/remote-questions/types.ts +3 -0
  201. package/src/resources/extensions/shared/mod.ts +3 -0
  202. package/src/resources/skills/create-gsd-extension/SKILL.md +87 -0
  203. package/src/resources/skills/create-gsd-extension/references/compaction-session-control.md +77 -0
  204. package/src/resources/skills/create-gsd-extension/references/custom-commands.md +139 -0
  205. package/src/resources/skills/create-gsd-extension/references/custom-rendering.md +108 -0
  206. package/src/resources/skills/create-gsd-extension/references/custom-tools.md +183 -0
  207. package/src/resources/skills/create-gsd-extension/references/custom-ui.md +490 -0
  208. package/src/resources/skills/create-gsd-extension/references/events-reference.md +126 -0
  209. package/src/resources/skills/create-gsd-extension/references/extension-lifecycle.md +64 -0
  210. package/src/resources/skills/create-gsd-extension/references/extensionapi-reference.md +75 -0
  211. package/src/resources/skills/create-gsd-extension/references/extensioncontext-reference.md +53 -0
  212. package/src/resources/skills/create-gsd-extension/references/key-rules-gotchas.md +36 -0
  213. package/src/resources/skills/create-gsd-extension/references/mode-behavior.md +32 -0
  214. package/src/resources/skills/create-gsd-extension/references/model-provider-management.md +89 -0
  215. package/src/resources/skills/create-gsd-extension/references/packaging-distribution.md +55 -0
  216. package/src/resources/skills/create-gsd-extension/references/remote-execution-overrides.md +90 -0
  217. package/src/resources/skills/create-gsd-extension/references/state-management.md +70 -0
  218. package/src/resources/skills/create-gsd-extension/references/system-prompt-modification.md +52 -0
  219. package/src/resources/skills/create-gsd-extension/templates/extension-skeleton.ts +51 -0
  220. package/src/resources/skills/create-gsd-extension/templates/stateful-tool-skeleton.ts +143 -0
  221. package/src/resources/skills/create-gsd-extension/workflows/add-capability.md +57 -0
  222. package/src/resources/skills/create-gsd-extension/workflows/create-extension.md +156 -0
  223. package/src/resources/skills/create-gsd-extension/workflows/debug-extension.md +74 -0
  224. package/src/resources/skills/create-skill/SKILL.md +184 -0
  225. package/src/resources/skills/create-skill/references/api-security.md +226 -0
  226. package/src/resources/skills/create-skill/references/be-clear-and-direct.md +531 -0
  227. package/src/resources/skills/create-skill/references/common-patterns.md +595 -0
  228. package/src/resources/skills/create-skill/references/core-principles.md +437 -0
  229. package/src/resources/skills/create-skill/references/executable-code.md +175 -0
  230. package/src/resources/skills/create-skill/references/gsd-skill-ecosystem.md +68 -0
  231. package/src/resources/skills/create-skill/references/iteration-and-testing.md +474 -0
  232. package/src/resources/skills/create-skill/references/recommended-structure.md +168 -0
  233. package/src/resources/skills/create-skill/references/skill-structure.md +372 -0
  234. package/src/resources/skills/create-skill/references/use-xml-tags.md +466 -0
  235. package/src/resources/skills/create-skill/references/using-scripts.md +113 -0
  236. package/src/resources/skills/create-skill/references/using-templates.md +112 -0
  237. package/src/resources/skills/create-skill/references/workflows-and-validation.md +510 -0
  238. package/src/resources/skills/create-skill/templates/router-skill.md +73 -0
  239. package/src/resources/skills/create-skill/templates/simple-skill.md +33 -0
  240. package/src/resources/skills/create-skill/workflows/add-reference.md +96 -0
  241. package/src/resources/skills/create-skill/workflows/add-script.md +93 -0
  242. package/src/resources/skills/create-skill/workflows/add-template.md +74 -0
  243. package/src/resources/skills/create-skill/workflows/add-workflow.md +120 -0
  244. package/src/resources/skills/create-skill/workflows/audit-skill.md +148 -0
  245. package/src/resources/skills/create-skill/workflows/create-new-skill.md +196 -0
  246. package/src/resources/skills/create-skill/workflows/get-guidance.md +121 -0
  247. package/src/resources/skills/create-skill/workflows/upgrade-to-router.md +161 -0
  248. package/src/resources/skills/create-skill/workflows/verify-skill.md +204 -0
  249. package/dist/resources/extensions/gsd/preferences-hooks.ts +0 -10
  250. package/dist/resources/extensions/mcporter/index.ts +0 -525
  251. package/dist/resources/extensions/shared/progress-widget.ts +0 -282
  252. package/dist/resources/extensions/shared/thinking-widget.ts +0 -107
  253. package/src/resources/extensions/gsd/preferences-hooks.ts +0 -10
  254. package/src/resources/extensions/mcporter/index.ts +0 -525
  255. package/src/resources/extensions/shared/progress-widget.ts +0 -282
  256. package/src/resources/extensions/shared/thinking-widget.ts +0 -107
@@ -0,0 +1,126 @@
1
+ <overview>
2
+ Complete event reference with handler signatures, return types, and type narrowing utilities.
3
+ </overview>
4
+
5
+ <event_categories>
6
+
7
+ **Session events:** `session_start`, `session_before_switch`, `session_switch`, `session_before_fork`, `session_fork`, `session_before_compact`, `session_compact`, `session_before_tree`, `session_tree`, `session_shutdown`
8
+
9
+ **Agent events:** `before_agent_start`, `agent_start`, `agent_end`, `turn_start`, `turn_end`, `context`, `before_provider_request`, `message_start`, `message_update`, `message_end`
10
+
11
+ **Tool events:** `tool_call`, `tool_execution_start`, `tool_execution_update`, `tool_execution_end`, `tool_result`
12
+
13
+ **Input events:** `input`
14
+
15
+ **Model events:** `model_select`
16
+
17
+ **User bash events:** `user_bash`
18
+
19
+ **Special:** `session_directory` (CLI startup only, no `ctx` — receives only event)
20
+
21
+ </event_categories>
22
+
23
+ <handler_signature>
24
+ ```typescript
25
+ pi.on("event_name", async (event, ctx: ExtensionContext) => {
26
+ // event — typed payload for this event
27
+ // ctx — access to UI, session, model, control flow
28
+ // Return undefined for no action, or a typed response
29
+ });
30
+ ```
31
+ </handler_signature>
32
+
33
+ <key_events>
34
+
35
+ **before_agent_start** — Fired after user prompt, before agent loop. Primary hook for context injection and system prompt modification.
36
+ ```typescript
37
+ pi.on("before_agent_start", async (event, ctx) => {
38
+ // event.prompt — user's prompt text
39
+ // event.images — attached images
40
+ // event.systemPrompt — current system prompt
41
+ return {
42
+ message: { customType: "my-ext", content: "Extra context", display: true },
43
+ systemPrompt: event.systemPrompt + "\n\nExtra instructions...",
44
+ };
45
+ });
46
+ ```
47
+
48
+ **tool_call** — Fired before tool executes. Can block.
49
+ ```typescript
50
+ import { isToolCallEventType } from "@mariozechner/pi-coding-agent";
51
+
52
+ pi.on("tool_call", async (event, ctx) => {
53
+ if (isToolCallEventType("bash", event)) {
54
+ // event.input is typed as { command: string; timeout?: number }
55
+ if (event.input.command.includes("rm -rf")) {
56
+ return { block: true, reason: "Dangerous command" };
57
+ }
58
+ }
59
+ });
60
+ ```
61
+
62
+ **tool_result** — Fired after tool executes. Can modify result. Handlers chain like middleware.
63
+ ```typescript
64
+ import { isBashToolResult } from "@mariozechner/pi-coding-agent";
65
+
66
+ pi.on("tool_result", async (event, ctx) => {
67
+ if (isBashToolResult(event)) {
68
+ // event.details is typed as BashToolDetails
69
+ }
70
+ // Return partial patch: { content, details, isError }
71
+ // Omitted fields keep current values
72
+ });
73
+ ```
74
+
75
+ **context** — Fired before each LLM call. Modify messages non-destructively.
76
+ ```typescript
77
+ pi.on("context", async (event, ctx) => {
78
+ // event.messages is a deep copy — safe to modify
79
+ const filtered = event.messages.filter(m => !shouldPrune(m));
80
+ return { messages: filtered };
81
+ });
82
+ ```
83
+
84
+ **input** — Fired when user input is received, before skill/template expansion.
85
+ ```typescript
86
+ pi.on("input", async (event, ctx) => {
87
+ // event.text — raw input
88
+ // event.source — "interactive", "rpc", or "extension"
89
+ if (event.text.startsWith("?quick "))
90
+ return { action: "transform", text: `Respond briefly: ${event.text.slice(7)}` };
91
+ return { action: "continue" };
92
+ });
93
+ ```
94
+
95
+ **model_select** — Fired when model changes.
96
+ ```typescript
97
+ pi.on("model_select", async (event, ctx) => {
98
+ // event.model, event.previousModel, event.source ("set"|"cycle"|"restore")
99
+ });
100
+ ```
101
+
102
+ </key_events>
103
+
104
+ <type_narrowing>
105
+ Built-in type guards for tool events:
106
+
107
+ ```typescript
108
+ import { isToolCallEventType, isBashToolResult } from "@mariozechner/pi-coding-agent";
109
+
110
+ // Tool calls — narrows event.input type
111
+ if (isToolCallEventType("bash", event)) { /* event.input: { command, timeout? } */ }
112
+ if (isToolCallEventType("read", event)) { /* event.input: { path, offset?, limit? } */ }
113
+ if (isToolCallEventType("write", event)) { /* event.input: { path, content } */ }
114
+ if (isToolCallEventType("edit", event)) { /* event.input: { path, oldText, newText } */ }
115
+
116
+ // Tool results — narrows event.details type
117
+ if (isBashToolResult(event)) { /* event.details: BashToolDetails */ }
118
+ ```
119
+
120
+ For custom tools, export your input type and use explicit type params:
121
+ ```typescript
122
+ if (isToolCallEventType<"my_tool", MyToolInput>("my_tool", event)) {
123
+ event.input.action; // typed
124
+ }
125
+ ```
126
+ </type_narrowing>
@@ -0,0 +1,64 @@
1
+ <overview>
2
+ The extension lifecycle from load to shutdown, including the full event flow.
3
+ </overview>
4
+
5
+ <loading>
6
+ Extensions load when GSD starts (or on `/reload`). The default export function runs synchronously — subscribe to events and register tools/commands during this call.
7
+
8
+ ```
9
+ GSD starts
10
+ └─► Extension default function runs
11
+ ├── pi.on("event", handler) ← Subscribe
12
+ ├── pi.registerTool({...}) ← Register tools
13
+ ├── pi.registerCommand(...) ← Register commands
14
+ └── pi.registerShortcut(...) ← Register shortcuts
15
+ └─► session_start fires
16
+ ```
17
+ </loading>
18
+
19
+ <event_flow>
20
+ Full event flow per user prompt:
21
+
22
+ ```
23
+ user sends prompt
24
+ ├─► Extension commands checked (bypass if match)
25
+ ├─► input event (can intercept/transform/handle)
26
+ ├─► Skill/template expansion
27
+ ├─► before_agent_start (inject message, modify system prompt)
28
+ ├─► agent_start
29
+
30
+ │ ┌── Turn loop (repeats while LLM calls tools) ──┐
31
+ │ │ turn_start │
32
+ │ │ context (can modify messages sent to LLM) │
33
+ │ │ before_provider_request (inspect/replace payload)│
34
+ │ │ LLM responds → may call tools: │
35
+ │ │ tool_call (can BLOCK) │
36
+ │ │ tool_execution_start/update/end │
37
+ │ │ tool_result (can MODIFY) │
38
+ │ │ turn_end │
39
+ │ └────────────────────────────────────────────────┘
40
+
41
+ └─► agent_end
42
+ ```
43
+ </event_flow>
44
+
45
+ <session_events>
46
+ | Event | When | Can Return |
47
+ |-------|------|------------|
48
+ | `session_start` | Session loads | — |
49
+ | `session_before_switch` | Before `/new` or `/resume` | `{ cancel: true }` |
50
+ | `session_switch` | After switch | — |
51
+ | `session_before_fork` | Before `/fork` | `{ cancel: true }`, `{ skipConversationRestore: true }` |
52
+ | `session_fork` | After fork | — |
53
+ | `session_before_compact` | Before compaction | `{ cancel: true }`, `{ compaction: {...} }` |
54
+ | `session_compact` | After compaction | — |
55
+ | `session_shutdown` | On exit | — |
56
+ </session_events>
57
+
58
+ <hot_reload>
59
+ Extensions in auto-discovered locations hot-reload with `/reload`:
60
+ - `session_shutdown` fires for old runtime
61
+ - Resources re-scanned
62
+ - `session_start` fires for new runtime
63
+ - Code after `await ctx.reload()` still runs from the pre-reload version — treat as terminal
64
+ </hot_reload>
@@ -0,0 +1,75 @@
1
+ <overview>
2
+ ExtensionAPI methods — the `pi` object received in the default export function.
3
+ </overview>
4
+
5
+ <core_registration>
6
+ | Method | Purpose |
7
+ |--------|---------|
8
+ | `pi.on(event, handler)` | Subscribe to events |
9
+ | `pi.registerTool(definition)` | Register LLM-callable tool |
10
+ | `pi.registerCommand(name, options)` | Register `/command` |
11
+ | `pi.registerShortcut(key, options)` | Register keyboard shortcut |
12
+ | `pi.registerFlag(name, options)` | Register CLI flag |
13
+ | `pi.registerMessageRenderer(customType, renderer)` | Custom message rendering |
14
+ | `pi.registerProvider(name, config)` | Register/override model provider |
15
+ | `pi.unregisterProvider(name)` | Remove a provider |
16
+ </core_registration>
17
+
18
+ <messaging>
19
+ | Method | Purpose |
20
+ |--------|---------|
21
+ | `pi.sendMessage(message, options?)` | Inject custom message into session |
22
+ | `pi.sendUserMessage(content, options?)` | Send user message (triggers turn) |
23
+
24
+ **Delivery modes for `sendMessage`:**
25
+ - `"steer"` (default) — Interrupts streaming after current tool
26
+ - `"followUp"` — Waits for agent to finish all tools
27
+ - `"nextTurn"` — Queued for next user prompt
28
+
29
+ ```typescript
30
+ pi.sendMessage({
31
+ customType: "my-extension",
32
+ content: "Additional context",
33
+ display: true,
34
+ details: { ... },
35
+ }, { deliverAs: "steer", triggerTurn: true });
36
+ ```
37
+ </messaging>
38
+
39
+ <state_session>
40
+ | Method | Purpose |
41
+ |--------|---------|
42
+ | `pi.appendEntry(customType, data?)` | Persist state (NOT sent to LLM) |
43
+ | `pi.setSessionName(name)` | Set session display name |
44
+ | `pi.getSessionName()` | Get session name |
45
+ | `pi.setLabel(entryId, label)` | Bookmark entry for `/tree` |
46
+ </state_session>
47
+
48
+ <tool_management>
49
+ ```typescript
50
+ const active = pi.getActiveTools(); // ["read", "bash", "edit", "write"]
51
+ const all = pi.getAllTools(); // [{ name, description }, ...]
52
+ pi.setActiveTools(["read", "bash"]); // Enable/disable tools
53
+ ```
54
+ </tool_management>
55
+
56
+ <model_management>
57
+ ```typescript
58
+ const model = ctx.modelRegistry.find("anthropic", "claude-sonnet-4-5");
59
+ if (model) {
60
+ const success = await pi.setModel(model); // Returns false if no API key
61
+ }
62
+
63
+ pi.getThinkingLevel(); // "off" | "minimal" | "low" | "medium" | "high" | "xhigh"
64
+ pi.setThinkingLevel("high");
65
+ ```
66
+ </model_management>
67
+
68
+ <utilities>
69
+ | Method | Purpose |
70
+ |--------|---------|
71
+ | `pi.exec(cmd, args, opts?)` | Shell command (prefer over child_process) |
72
+ | `pi.events` | Shared event bus for inter-extension communication |
73
+ | `pi.getFlag(name)` | Get CLI flag value |
74
+ | `pi.getCommands()` | All available slash commands |
75
+ </utilities>
@@ -0,0 +1,53 @@
1
+ <overview>
2
+ ExtensionContext (`ctx`) — available in all event handlers (except `session_directory`).
3
+ </overview>
4
+
5
+ <ui_methods>
6
+ **Dialogs (blocking — wait for user response):**
7
+ ```typescript
8
+ const choice = await ctx.ui.select("Pick one:", ["A", "B", "C"]);
9
+ const ok = await ctx.ui.confirm("Delete?", "This cannot be undone");
10
+ const name = await ctx.ui.input("Name:", "placeholder");
11
+ const text = await ctx.ui.editor("Edit:", "prefilled text");
12
+
13
+ // Timed dialog — auto-dismiss after timeout
14
+ const ok = await ctx.ui.confirm("Auto-confirm?", "Proceeds in 5s", { timeout: 5000 });
15
+ ```
16
+
17
+ **Non-blocking UI:**
18
+ ```typescript
19
+ ctx.ui.notify("Done!", "info"); // Toast: "info" | "warning" | "error"
20
+ ctx.ui.setStatus("my-ext", "● Active"); // Footer status
21
+ ctx.ui.setStatus("my-ext", undefined); // Clear
22
+ ctx.ui.setWidget("my-id", ["Line 1", "Line 2"]); // Widget above editor
23
+ ctx.ui.setWidget("my-id", ["Below!"], { placement: "belowEditor" });
24
+ ctx.ui.setTitle("gsd - my project"); // Terminal title
25
+ ctx.ui.setEditorText("Prefill"); // Set editor content
26
+ ctx.ui.setWorkingMessage("Analyzing..."); // Working message during streaming
27
+ ctx.ui.setToolsExpanded(true); // Expand tool output
28
+ ```
29
+ </ui_methods>
30
+
31
+ <ctx_properties>
32
+ | Property/Method | Purpose |
33
+ |----------------|---------|
34
+ | `ctx.hasUI` | `false` in print/JSON mode — check before dialogs |
35
+ | `ctx.cwd` | Current working directory |
36
+ | `ctx.sessionManager` | Read-only session state |
37
+ | `ctx.modelRegistry` / `ctx.model` | Model access |
38
+ | `ctx.isIdle()` / `ctx.abort()` / `ctx.hasPendingMessages()` | Agent state |
39
+ | `ctx.shutdown()` | Request graceful exit (deferred until idle) |
40
+ | `ctx.getContextUsage()` | Current context token usage |
41
+ | `ctx.compact(options?)` | Trigger compaction |
42
+ | `ctx.getSystemPrompt()` | Current effective system prompt |
43
+ </ctx_properties>
44
+
45
+ <session_manager>
46
+ ```typescript
47
+ ctx.sessionManager.getEntries() // All entries
48
+ ctx.sessionManager.getBranch() // Current branch
49
+ ctx.sessionManager.getLeafId() // Current leaf entry ID
50
+ ctx.sessionManager.getSessionFile() // Session JSONL path
51
+ ctx.sessionManager.getLabel(entryId) // Entry label
52
+ ```
53
+ </session_manager>
@@ -0,0 +1,36 @@
1
+ <overview>
2
+ Non-negotiable rules and common gotchas when building GSD extensions.
3
+ </overview>
4
+
5
+ <must_follow>
6
+ 1. **Use `StringEnum` for string enums** — `Type.Union`/`Type.Literal` breaks Google's API.
7
+ 2. **Truncate tool output** — Large output causes context overflow, compaction failures, degraded performance. Limit: 50KB / 2000 lines.
8
+ 3. **Use theme from callback** — Don't import theme directly. Use the `theme` parameter from `ctx.ui.custom()` or render functions.
9
+ 4. **`DynamicBorder` color param** — Type as `(s: string) => theme.fg("accent", s)`.
10
+ 5. **Call `tui.requestRender()` after state changes** in `handleInput`.
11
+ 6. **Return `{ render, invalidate, handleInput }`** from custom components.
12
+ 7. **Lines must not exceed `width`** in `render()` — use `truncateToWidth()`.
13
+ 8. **Session control methods ONLY in commands** — `waitForIdle()`, `newSession()`, `fork()`, `navigateTree()`, `reload()` will **deadlock** in event handlers.
14
+ 9. **Strip leading `@` from path arguments** — some models add it.
15
+ 10. **Store state in tool result `details`** for proper branching support.
16
+ </must_follow>
17
+
18
+ <common_patterns>
19
+ - Rebuild component on `invalidate()` when pre-baking theme colors
20
+ - Check `signal?.aborted` in long-running tool executions
21
+ - Use `pi.exec()` instead of `child_process` for shell commands
22
+ - Overlay components are **disposed when closed** — create fresh instances each time
23
+ - Treat `ctx.reload()` as terminal — code after runs from pre-reload version
24
+ - Check `ctx.hasUI` before dialog methods (false in print/JSON mode)
25
+ - Extension errors are logged but don't crash GSD — tool_call handler errors fail-safe (block the tool)
26
+ </common_patterns>
27
+
28
+ <gsd_paths>
29
+ **GSD extension paths:**
30
+ - Global: `~/.gsd/agent/extensions/*.ts`
31
+ - Global (subdir): `~/.gsd/agent/extensions/*/index.ts`
32
+ - Project-local: `.gsd/extensions/*.ts`
33
+ - Project-local (subdir): `.gsd/extensions/*/index.ts`
34
+
35
+ The upstream pi docs reference `~/.pi` paths — GSD uses `~/.gsd` everywhere instead.
36
+ </gsd_paths>
@@ -0,0 +1,32 @@
1
+ <overview>
2
+ Mode behavior determines which UI methods work. Extensions may run in non-interactive modes where dialogs are unavailable.
3
+ </overview>
4
+
5
+ <mode_table>
6
+ | Mode | UI Methods | Notes |
7
+ |------|-----------|-------|
8
+ | **Interactive** (default) | Full TUI | Normal operation — all UI works |
9
+ | **RPC** (`--mode rpc`) | JSON protocol | Host handles UI, dialogs work via sub-protocol |
10
+ | **JSON** (`--mode json`) | No-op | Event stream to stdout, no UI |
11
+ | **Print** (`-p`) | No-op | Extensions run but can't prompt users |
12
+ </mode_table>
13
+
14
+ <checking_ui>
15
+ **Always check `ctx.hasUI`** before calling dialog methods:
16
+
17
+ ```typescript
18
+ if (ctx.hasUI) {
19
+ const ok = await ctx.ui.confirm("Delete?", "Sure?");
20
+ if (!ok) return;
21
+ } else {
22
+ // Default behavior for non-interactive mode
23
+ // Or just proceed without confirmation
24
+ }
25
+ ```
26
+
27
+ `ctx.hasUI` is `false` in print mode (`-p`) and JSON mode. `true` in interactive and RPC mode.
28
+ </checking_ui>
29
+
30
+ <fire_and_forget>
31
+ Non-blocking methods (`notify`, `setStatus`, `setWidget`, `setTitle`, `setEditorText`) are safe in all modes — they're no-ops when no UI is available.
32
+ </fire_and_forget>
@@ -0,0 +1,89 @@
1
+ <overview>
2
+ Model and provider management — switching models, registering custom providers with OAuth, and reacting to model changes.
3
+ </overview>
4
+
5
+ <switching_models>
6
+ ```typescript
7
+ const model = ctx.modelRegistry.find("anthropic", "claude-sonnet-4-5");
8
+ if (model) {
9
+ const success = await pi.setModel(model);
10
+ if (!success) ctx.ui.notify("No API key for this model", "error");
11
+ }
12
+
13
+ // Thinking level
14
+ pi.getThinkingLevel(); // "off" | "minimal" | "low" | "medium" | "high" | "xhigh"
15
+ pi.setThinkingLevel("high"); // Clamped to model capabilities
16
+ ```
17
+ </switching_models>
18
+
19
+ <register_provider>
20
+ ```typescript
21
+ pi.registerProvider("my-proxy", {
22
+ baseUrl: "https://proxy.example.com",
23
+ apiKey: "PROXY_API_KEY", // Env var name or literal
24
+ api: "anthropic-messages", // or "openai-completions", "openai-responses"
25
+ headers: { "X-Custom": "value" }, // Optional custom headers
26
+ authHeader: true, // Auto-add Authorization: Bearer header
27
+ models: [
28
+ {
29
+ id: "claude-sonnet-4-20250514",
30
+ name: "Claude 4 Sonnet (proxy)",
31
+ reasoning: false,
32
+ input: ["text", "image"],
33
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
34
+ contextWindow: 200000,
35
+ maxTokens: 16384,
36
+ }
37
+ ],
38
+ });
39
+
40
+ // Override just baseUrl for an existing provider (keeps all models)
41
+ pi.registerProvider("anthropic", {
42
+ baseUrl: "https://proxy.example.com",
43
+ });
44
+
45
+ // Remove a provider (restores any overridden built-in models)
46
+ pi.unregisterProvider("my-proxy");
47
+ ```
48
+
49
+ Takes effect immediately after initial load phase — no `/reload` required.
50
+ </register_provider>
51
+
52
+ <oauth_provider>
53
+ Register a provider with OAuth support for `/login`:
54
+
55
+ ```typescript
56
+ pi.registerProvider("corporate-ai", {
57
+ baseUrl: "https://ai.corp.com",
58
+ api: "openai-responses",
59
+ models: [/* ... */],
60
+ oauth: {
61
+ name: "Corporate AI (SSO)",
62
+ async login(callbacks) {
63
+ callbacks.onAuth({ url: "https://sso.corp.com/..." });
64
+ const code = await callbacks.onPrompt({ message: "Enter code:" });
65
+ return { refresh: code, access: code, expires: Date.now() + 3600000 };
66
+ },
67
+ async refreshToken(credentials) {
68
+ return credentials; // Refresh logic
69
+ },
70
+ getApiKey(credentials) {
71
+ return credentials.access;
72
+ },
73
+ },
74
+ });
75
+ ```
76
+ </oauth_provider>
77
+
78
+ <model_events>
79
+ React to model changes:
80
+
81
+ ```typescript
82
+ pi.on("model_select", async (event, ctx) => {
83
+ // event.model — newly selected model
84
+ // event.previousModel — previous model (undefined if first)
85
+ // event.source — "set" | "cycle" | "restore"
86
+ ctx.ui.setStatus("model", `${event.model.provider}/${event.model.id}`);
87
+ });
88
+ ```
89
+ </model_events>
@@ -0,0 +1,55 @@
1
+ <overview>
2
+ Packaging extensions for distribution via npm, git, or local paths. Creating GSD/pi packages.
3
+ </overview>
4
+
5
+ <package_manifest>
6
+ Add a `pi` manifest to `package.json`:
7
+
8
+ ```json
9
+ {
10
+ "name": "my-gsd-package",
11
+ "keywords": ["pi-package"],
12
+ "pi": {
13
+ "extensions": ["./extensions"],
14
+ "skills": ["./skills"],
15
+ "prompts": ["./prompts"],
16
+ "themes": ["./themes"]
17
+ }
18
+ }
19
+ ```
20
+ </package_manifest>
21
+
22
+ <installing>
23
+ ```bash
24
+ gsd install npm:@foo/bar@1.0.0
25
+ gsd install git:github.com/user/repo@v1
26
+ gsd install ./local/path
27
+
28
+ # Try without installing:
29
+ gsd -e npm:@foo/bar
30
+ ```
31
+ </installing>
32
+
33
+ <convention_directories>
34
+ If no `pi` manifest exists, auto-discovers:
35
+ - `extensions/` → `.ts` and `.js` files
36
+ - `skills/` → `SKILL.md` folders
37
+ - `prompts/` → `.md` files
38
+ - `themes/` → `.json` files
39
+ </convention_directories>
40
+
41
+ <dependencies>
42
+ - List `@mariozechner/pi-ai`, `@mariozechner/pi-coding-agent`, `@mariozechner/pi-tui`, `@sinclair/typebox` in `peerDependencies` with `"*"` — they're bundled by the runtime.
43
+ - Other npm deps go in `dependencies`. The runtime runs `npm install` on package installation.
44
+ </dependencies>
45
+
46
+ <gallery_metadata>
47
+ ```json
48
+ {
49
+ "pi": {
50
+ "video": "https://example.com/demo.mp4",
51
+ "image": "https://example.com/screenshot.png"
52
+ }
53
+ }
54
+ ```
55
+ </gallery_metadata>
@@ -0,0 +1,90 @@
1
+ <overview>
2
+ Remote execution via pluggable operations, spawnHook for bash, and tool override patterns.
3
+ </overview>
4
+
5
+ <pluggable_operations>
6
+ Built-in tools support pluggable operations for SSH, containers, etc.:
7
+
8
+ ```typescript
9
+ import { createReadTool, createBashTool, createWriteTool } from "@mariozechner/pi-coding-agent";
10
+
11
+ // Create tool with custom remote operations
12
+ const remoteBash = createBashTool(cwd, {
13
+ operations: {
14
+ execute: (cmd) => sshExec(remote, cmd),
15
+ },
16
+ });
17
+ ```
18
+
19
+ **Operations interfaces:** `ReadOperations`, `WriteOperations`, `EditOperations`, `BashOperations`, `LsOperations`, `GrepOperations`, `FindOperations`
20
+ </pluggable_operations>
21
+
22
+ <spawn_hook>
23
+ The bash tool supports a `spawnHook` to modify commands before execution:
24
+
25
+ ```typescript
26
+ const bashTool = createBashTool(cwd, {
27
+ spawnHook: ({ command, cwd, env }) => ({
28
+ command: `source ~/.profile\n${command}`,
29
+ cwd: `/mnt/sandbox${cwd}`,
30
+ env: { ...env, CI: "1" },
31
+ }),
32
+ });
33
+ ```
34
+ </spawn_hook>
35
+
36
+ <ssh_pattern>
37
+ Full SSH pattern with flag-based switching:
38
+
39
+ ```typescript
40
+ import { createBashTool, type ExtensionAPI } from "@mariozechner/pi-coding-agent";
41
+
42
+ export default function (pi: ExtensionAPI) {
43
+ pi.registerFlag("ssh", { description: "SSH target", type: "string" });
44
+
45
+ const localBash = createBashTool(process.cwd());
46
+
47
+ pi.registerTool({
48
+ ...localBash,
49
+ async execute(id, params, signal, onUpdate, ctx) {
50
+ const sshTarget = pi.getFlag("--ssh");
51
+ if (sshTarget) {
52
+ const remoteBash = createBashTool(process.cwd(), {
53
+ operations: createSSHOperations(sshTarget),
54
+ });
55
+ return remoteBash.execute(id, params, signal, onUpdate);
56
+ }
57
+ return localBash.execute(id, params, signal, onUpdate);
58
+ },
59
+ });
60
+ }
61
+ ```
62
+ </ssh_pattern>
63
+
64
+ <tool_override_pattern>
65
+ Override built-in tools for logging/access control — omit renderCall/renderResult to keep built-in rendering:
66
+
67
+ ```typescript
68
+ import { createReadTool } from "@mariozechner/pi-coding-agent";
69
+ import { Type } from "@sinclair/typebox";
70
+
71
+ pi.registerTool({
72
+ name: "read", // Same name = overrides built-in
73
+ label: "Read (Logged)",
74
+ description: "Read file contents with logging",
75
+ parameters: Type.Object({
76
+ path: Type.String(),
77
+ offset: Type.Optional(Type.Number()),
78
+ limit: Type.Optional(Type.Number()),
79
+ }),
80
+ async execute(toolCallId, params, signal, onUpdate, ctx) {
81
+ console.log(`[AUDIT] Reading: ${params.path}`);
82
+ const builtIn = createReadTool(ctx.cwd);
83
+ return builtIn.execute(toolCallId, params, signal, onUpdate);
84
+ },
85
+ // Omit renderCall/renderResult → built-in renderer used automatically
86
+ });
87
+ ```
88
+
89
+ **Must match exact result shape** including `details` type.
90
+ </tool_override_pattern>