@chankov/agent-skills 0.1.0 → 0.3.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 (328) hide show
  1. package/.claude/commands/{doctor.md → doctor-agent-skills.md} +1 -1
  2. package/.pi/extensions/agent-skills-update-check/README.md +58 -0
  3. package/.pi/extensions/agent-skills-update-check/index.ts +161 -0
  4. package/.pi/extensions/agent-skills-update-check/package.json +6 -0
  5. package/.pi/prompts/{doctor.md → doctor-agent-skills.md} +1 -1
  6. package/.versions/0.2.0/.claude/commands/build.md +18 -0
  7. package/.versions/0.2.0/.claude/commands/code-simplify.md +22 -0
  8. package/.versions/0.2.0/.claude/commands/design-agent.md +14 -0
  9. package/.versions/0.2.0/.claude/commands/doctor-agent-skills.md +13 -0
  10. package/.versions/0.2.0/.claude/commands/plan.md +16 -0
  11. package/.versions/0.2.0/.claude/commands/prime.md +22 -0
  12. package/.versions/0.2.0/.claude/commands/review.md +16 -0
  13. package/.versions/0.2.0/.claude/commands/setup-agent-skills.md +19 -0
  14. package/.versions/0.2.0/.claude/commands/ship.md +17 -0
  15. package/.versions/0.2.0/.claude/commands/spec.md +15 -0
  16. package/.versions/0.2.0/.claude/commands/test.md +19 -0
  17. package/.versions/0.2.0/.opencode/commands/as-build.md +17 -0
  18. package/.versions/0.2.0/.opencode/commands/as-code-simplify.md +16 -0
  19. package/.versions/0.2.0/.opencode/commands/as-design-agent.md +15 -0
  20. package/.versions/0.2.0/.opencode/commands/as-doctor-agent-skills.md +11 -0
  21. package/.versions/0.2.0/.opencode/commands/as-plan.md +16 -0
  22. package/.versions/0.2.0/.opencode/commands/as-prime.md +22 -0
  23. package/.versions/0.2.0/.opencode/commands/as-review.md +15 -0
  24. package/.versions/0.2.0/.opencode/commands/as-setup-agent-skills.md +11 -0
  25. package/.versions/0.2.0/.opencode/commands/as-ship.md +16 -0
  26. package/.versions/0.2.0/.opencode/commands/as-spec.md +16 -0
  27. package/.versions/0.2.0/.opencode/commands/as-test.md +21 -0
  28. package/.versions/0.2.0/.pi/agents/agent-chain.yaml +49 -0
  29. package/.versions/0.2.0/.pi/agents/bowser.md +19 -0
  30. package/.versions/0.2.0/.pi/agents/pi-pi/agent-expert.md +98 -0
  31. package/.versions/0.2.0/.pi/agents/pi-pi/cli-expert.md +41 -0
  32. package/.versions/0.2.0/.pi/agents/pi-pi/config-expert.md +63 -0
  33. package/.versions/0.2.0/.pi/agents/pi-pi/ext-expert.md +43 -0
  34. package/.versions/0.2.0/.pi/agents/pi-pi/keybinding-expert.md +134 -0
  35. package/.versions/0.2.0/.pi/agents/pi-pi/pi-orchestrator.md +57 -0
  36. package/.versions/0.2.0/.pi/agents/pi-pi/prompt-expert.md +70 -0
  37. package/.versions/0.2.0/.pi/agents/pi-pi/skill-expert.md +42 -0
  38. package/.versions/0.2.0/.pi/agents/pi-pi/theme-expert.md +40 -0
  39. package/.versions/0.2.0/.pi/agents/pi-pi/tui-expert.md +85 -0
  40. package/.versions/0.2.0/.pi/agents/teams.yaml +31 -0
  41. package/.versions/0.2.0/.pi/damage-control-rules.yaml +278 -0
  42. package/.versions/0.2.0/.pi/extensions/agent-skills-update-check/README.md +58 -0
  43. package/.versions/0.2.0/.pi/extensions/agent-skills-update-check/index.ts +161 -0
  44. package/.versions/0.2.0/.pi/extensions/agent-skills-update-check/package.json +6 -0
  45. package/.versions/0.2.0/.pi/extensions/chrome-devtools-mcp/README.md +39 -0
  46. package/.versions/0.2.0/.pi/extensions/chrome-devtools-mcp/index.ts +61 -0
  47. package/.versions/0.2.0/.pi/extensions/chrome-devtools-mcp/package.json +6 -0
  48. package/.versions/0.2.0/.pi/extensions/compact-and-continue/README.md +42 -0
  49. package/.versions/0.2.0/.pi/extensions/compact-and-continue/index.ts +120 -0
  50. package/.versions/0.2.0/.pi/extensions/compact-and-continue/package.json +6 -0
  51. package/.versions/0.2.0/.pi/extensions/mcp-bridge/README.md +46 -0
  52. package/.versions/0.2.0/.pi/extensions/mcp-bridge/index.ts +206 -0
  53. package/.versions/0.2.0/.pi/extensions/mcp-bridge/package.json +6 -0
  54. package/.versions/0.2.0/.pi/extensions/package-lock.json +1143 -0
  55. package/.versions/0.2.0/.pi/extensions/package.json +9 -0
  56. package/.versions/0.2.0/.pi/harnesses/agent-chain/README.md +37 -0
  57. package/.versions/0.2.0/.pi/harnesses/agent-chain/index.ts +795 -0
  58. package/.versions/0.2.0/.pi/harnesses/agent-chain/package.json +6 -0
  59. package/.versions/0.2.0/.pi/harnesses/agent-team/README.md +38 -0
  60. package/.versions/0.2.0/.pi/harnesses/agent-team/index.ts +732 -0
  61. package/.versions/0.2.0/.pi/harnesses/agent-team/package.json +6 -0
  62. package/.versions/0.2.0/.pi/harnesses/coms/README.md +36 -0
  63. package/.versions/0.2.0/.pi/harnesses/coms/index.ts +1595 -0
  64. package/.versions/0.2.0/.pi/harnesses/coms/package.json +6 -0
  65. package/.versions/0.2.0/.pi/harnesses/coms-net/README.md +46 -0
  66. package/.versions/0.2.0/.pi/harnesses/coms-net/index.ts +1637 -0
  67. package/.versions/0.2.0/.pi/harnesses/coms-net/package.json +6 -0
  68. package/.versions/0.2.0/.pi/harnesses/damage-control/README.md +38 -0
  69. package/.versions/0.2.0/.pi/harnesses/damage-control/index.ts +207 -0
  70. package/.versions/0.2.0/.pi/harnesses/damage-control/package.json +6 -0
  71. package/.versions/0.2.0/.pi/harnesses/damage-control-continue/README.md +37 -0
  72. package/.versions/0.2.0/.pi/harnesses/damage-control-continue/index.ts +234 -0
  73. package/.versions/0.2.0/.pi/harnesses/damage-control-continue/package.json +6 -0
  74. package/.versions/0.2.0/.pi/harnesses/minimal/README.md +27 -0
  75. package/.versions/0.2.0/.pi/harnesses/minimal/index.ts +32 -0
  76. package/.versions/0.2.0/.pi/harnesses/minimal/package.json +6 -0
  77. package/.versions/0.2.0/.pi/harnesses/package-lock.json +35 -0
  78. package/.versions/0.2.0/.pi/harnesses/package.json +9 -0
  79. package/.versions/0.2.0/.pi/harnesses/pi-pi/README.md +39 -0
  80. package/.versions/0.2.0/.pi/harnesses/pi-pi/index.ts +631 -0
  81. package/.versions/0.2.0/.pi/harnesses/pi-pi/package.json +6 -0
  82. package/.versions/0.2.0/.pi/harnesses/purpose-gate/README.md +27 -0
  83. package/.versions/0.2.0/.pi/harnesses/purpose-gate/index.ts +82 -0
  84. package/.versions/0.2.0/.pi/harnesses/purpose-gate/package.json +6 -0
  85. package/.versions/0.2.0/.pi/harnesses/session-replay/README.md +28 -0
  86. package/.versions/0.2.0/.pi/harnesses/session-replay/index.ts +214 -0
  87. package/.versions/0.2.0/.pi/harnesses/session-replay/package.json +6 -0
  88. package/.versions/0.2.0/.pi/harnesses/subagent-widget/README.md +36 -0
  89. package/.versions/0.2.0/.pi/harnesses/subagent-widget/index.ts +479 -0
  90. package/.versions/0.2.0/.pi/harnesses/subagent-widget/package.json +6 -0
  91. package/.versions/0.2.0/.pi/harnesses/system-select/README.md +39 -0
  92. package/.versions/0.2.0/.pi/harnesses/system-select/index.ts +165 -0
  93. package/.versions/0.2.0/.pi/harnesses/system-select/package.json +6 -0
  94. package/.versions/0.2.0/.pi/harnesses/tilldone/README.md +35 -0
  95. package/.versions/0.2.0/.pi/harnesses/tilldone/index.ts +724 -0
  96. package/.versions/0.2.0/.pi/harnesses/tilldone/package.json +6 -0
  97. package/.versions/0.2.0/.pi/harnesses/tool-counter/README.md +31 -0
  98. package/.versions/0.2.0/.pi/harnesses/tool-counter/index.ts +100 -0
  99. package/.versions/0.2.0/.pi/harnesses/tool-counter/package.json +6 -0
  100. package/.versions/0.2.0/.pi/harnesses/tool-counter-widget/README.md +27 -0
  101. package/.versions/0.2.0/.pi/harnesses/tool-counter-widget/index.ts +66 -0
  102. package/.versions/0.2.0/.pi/harnesses/tool-counter-widget/package.json +6 -0
  103. package/.versions/0.2.0/.pi/prompts/build.md +24 -0
  104. package/.versions/0.2.0/.pi/prompts/code-simplify.md +22 -0
  105. package/.versions/0.2.0/.pi/prompts/doctor-agent-skills.md +13 -0
  106. package/.versions/0.2.0/.pi/prompts/plan.md +16 -0
  107. package/.versions/0.2.0/.pi/prompts/review.md +16 -0
  108. package/.versions/0.2.0/.pi/prompts/setup-agent-skills.md +19 -0
  109. package/.versions/0.2.0/.pi/prompts/ship.md +17 -0
  110. package/.versions/0.2.0/.pi/prompts/spec.md +15 -0
  111. package/.versions/0.2.0/.pi/prompts/test.md +19 -0
  112. package/.versions/0.2.0/.pi/skills/bowser/SKILL.md +114 -0
  113. package/.versions/0.2.0/.version +1 -0
  114. package/.versions/0.2.0/agents/builder.md +6 -0
  115. package/.versions/0.2.0/agents/code-reviewer.md +93 -0
  116. package/.versions/0.2.0/agents/documenter.md +6 -0
  117. package/.versions/0.2.0/agents/plan-reviewer.md +22 -0
  118. package/.versions/0.2.0/agents/planner.md +6 -0
  119. package/.versions/0.2.0/agents/scout.md +6 -0
  120. package/.versions/0.2.0/agents/security-auditor.md +97 -0
  121. package/.versions/0.2.0/agents/test-engineer.md +89 -0
  122. package/.versions/0.2.0/hooks/SIMPLIFY-IGNORE.md +90 -0
  123. package/.versions/0.2.0/hooks/hooks.json +14 -0
  124. package/.versions/0.2.0/hooks/session-start.sh +74 -0
  125. package/.versions/0.2.0/hooks/simplify-ignore-test.sh +247 -0
  126. package/.versions/0.2.0/hooks/simplify-ignore.sh +302 -0
  127. package/.versions/0.2.0/references/accessibility-checklist.md +159 -0
  128. package/.versions/0.2.0/references/performance-checklist.md +121 -0
  129. package/.versions/0.2.0/references/prompting-patterns.md +380 -0
  130. package/.versions/0.2.0/references/security-checklist.md +134 -0
  131. package/.versions/0.2.0/references/testing-patterns.md +236 -0
  132. package/.versions/0.2.0/skills/api-and-interface-design/SKILL.md +294 -0
  133. package/.versions/0.2.0/skills/browser-testing-with-devtools/SKILL.md +335 -0
  134. package/.versions/0.2.0/skills/ci-cd-and-automation/SKILL.md +390 -0
  135. package/.versions/0.2.0/skills/code-review-and-quality/SKILL.md +347 -0
  136. package/.versions/0.2.0/skills/code-simplification/SKILL.md +331 -0
  137. package/.versions/0.2.0/skills/context-engineering/SKILL.md +291 -0
  138. package/.versions/0.2.0/skills/debugging-and-error-recovery/SKILL.md +300 -0
  139. package/.versions/0.2.0/skills/deprecation-and-migration/SKILL.md +206 -0
  140. package/.versions/0.2.0/skills/designing-agents/SKILL.md +394 -0
  141. package/.versions/0.2.0/skills/designing-agents/pi-harness-authoring.md +213 -0
  142. package/.versions/0.2.0/skills/documentation-and-adrs/SKILL.md +278 -0
  143. package/.versions/0.2.0/skills/frontend-ui-engineering/SKILL.md +322 -0
  144. package/.versions/0.2.0/skills/git-workflow-and-versioning/SKILL.md +316 -0
  145. package/.versions/0.2.0/skills/guided-workspace-setup/SKILL.md +331 -0
  146. package/.versions/0.2.0/skills/idea-refine/SKILL.md +178 -0
  147. package/.versions/0.2.0/skills/idea-refine/examples.md +238 -0
  148. package/.versions/0.2.0/skills/idea-refine/frameworks.md +99 -0
  149. package/.versions/0.2.0/skills/idea-refine/refinement-criteria.md +113 -0
  150. package/.versions/0.2.0/skills/idea-refine/scripts/idea-refine.sh +15 -0
  151. package/.versions/0.2.0/skills/incremental-implementation/SKILL.md +279 -0
  152. package/.versions/0.2.0/skills/performance-optimization/SKILL.md +350 -0
  153. package/.versions/0.2.0/skills/planning-and-task-breakdown/SKILL.md +237 -0
  154. package/.versions/0.2.0/skills/security-and-hardening/SKILL.md +349 -0
  155. package/.versions/0.2.0/skills/shipping-and-launch/SKILL.md +309 -0
  156. package/.versions/0.2.0/skills/source-driven-development/SKILL.md +194 -0
  157. package/.versions/0.2.0/skills/spec-driven-development/SKILL.md +237 -0
  158. package/.versions/0.2.0/skills/test-driven-development/SKILL.md +379 -0
  159. package/.versions/0.2.0/skills/using-agent-skills/SKILL.md +176 -0
  160. package/.versions/0.3.0/.claude/commands/build.md +18 -0
  161. package/.versions/0.3.0/.claude/commands/code-simplify.md +22 -0
  162. package/.versions/0.3.0/.claude/commands/design-agent.md +14 -0
  163. package/.versions/0.3.0/.claude/commands/doctor-agent-skills.md +13 -0
  164. package/.versions/0.3.0/.claude/commands/plan.md +16 -0
  165. package/.versions/0.3.0/.claude/commands/prime.md +22 -0
  166. package/.versions/0.3.0/.claude/commands/review.md +16 -0
  167. package/.versions/0.3.0/.claude/commands/setup-agent-skills.md +19 -0
  168. package/.versions/0.3.0/.claude/commands/ship.md +17 -0
  169. package/.versions/0.3.0/.claude/commands/spec.md +15 -0
  170. package/.versions/0.3.0/.claude/commands/test.md +19 -0
  171. package/.versions/0.3.0/.opencode/commands/as-build.md +17 -0
  172. package/.versions/0.3.0/.opencode/commands/as-code-simplify.md +16 -0
  173. package/.versions/0.3.0/.opencode/commands/as-design-agent.md +15 -0
  174. package/.versions/0.3.0/.opencode/commands/as-doctor-agent-skills.md +11 -0
  175. package/.versions/0.3.0/.opencode/commands/as-plan.md +16 -0
  176. package/.versions/0.3.0/.opencode/commands/as-prime.md +22 -0
  177. package/.versions/0.3.0/.opencode/commands/as-review.md +15 -0
  178. package/.versions/0.3.0/.opencode/commands/as-setup-agent-skills.md +11 -0
  179. package/.versions/0.3.0/.opencode/commands/as-ship.md +16 -0
  180. package/.versions/0.3.0/.opencode/commands/as-spec.md +16 -0
  181. package/.versions/0.3.0/.opencode/commands/as-test.md +21 -0
  182. package/.versions/0.3.0/.pi/agents/agent-chain.yaml +49 -0
  183. package/.versions/0.3.0/.pi/agents/bowser.md +19 -0
  184. package/.versions/0.3.0/.pi/agents/pi-pi/agent-expert.md +98 -0
  185. package/.versions/0.3.0/.pi/agents/pi-pi/cli-expert.md +41 -0
  186. package/.versions/0.3.0/.pi/agents/pi-pi/config-expert.md +63 -0
  187. package/.versions/0.3.0/.pi/agents/pi-pi/ext-expert.md +43 -0
  188. package/.versions/0.3.0/.pi/agents/pi-pi/keybinding-expert.md +134 -0
  189. package/.versions/0.3.0/.pi/agents/pi-pi/pi-orchestrator.md +57 -0
  190. package/.versions/0.3.0/.pi/agents/pi-pi/prompt-expert.md +70 -0
  191. package/.versions/0.3.0/.pi/agents/pi-pi/skill-expert.md +42 -0
  192. package/.versions/0.3.0/.pi/agents/pi-pi/theme-expert.md +40 -0
  193. package/.versions/0.3.0/.pi/agents/pi-pi/tui-expert.md +85 -0
  194. package/.versions/0.3.0/.pi/agents/teams.yaml +31 -0
  195. package/.versions/0.3.0/.pi/damage-control-rules.yaml +278 -0
  196. package/.versions/0.3.0/.pi/extensions/agent-skills-update-check/README.md +58 -0
  197. package/.versions/0.3.0/.pi/extensions/agent-skills-update-check/index.ts +161 -0
  198. package/.versions/0.3.0/.pi/extensions/agent-skills-update-check/package.json +6 -0
  199. package/.versions/0.3.0/.pi/extensions/chrome-devtools-mcp/README.md +39 -0
  200. package/.versions/0.3.0/.pi/extensions/chrome-devtools-mcp/index.ts +61 -0
  201. package/.versions/0.3.0/.pi/extensions/chrome-devtools-mcp/package.json +6 -0
  202. package/.versions/0.3.0/.pi/extensions/compact-and-continue/README.md +42 -0
  203. package/.versions/0.3.0/.pi/extensions/compact-and-continue/index.ts +120 -0
  204. package/.versions/0.3.0/.pi/extensions/compact-and-continue/package.json +6 -0
  205. package/.versions/0.3.0/.pi/extensions/mcp-bridge/README.md +46 -0
  206. package/.versions/0.3.0/.pi/extensions/mcp-bridge/index.ts +206 -0
  207. package/.versions/0.3.0/.pi/extensions/mcp-bridge/package.json +6 -0
  208. package/.versions/0.3.0/.pi/extensions/package-lock.json +1143 -0
  209. package/.versions/0.3.0/.pi/extensions/package.json +9 -0
  210. package/.versions/0.3.0/.pi/harnesses/agent-chain/README.md +37 -0
  211. package/.versions/0.3.0/.pi/harnesses/agent-chain/index.ts +795 -0
  212. package/.versions/0.3.0/.pi/harnesses/agent-chain/package.json +6 -0
  213. package/.versions/0.3.0/.pi/harnesses/agent-team/README.md +38 -0
  214. package/.versions/0.3.0/.pi/harnesses/agent-team/index.ts +732 -0
  215. package/.versions/0.3.0/.pi/harnesses/agent-team/package.json +6 -0
  216. package/.versions/0.3.0/.pi/harnesses/coms/README.md +36 -0
  217. package/.versions/0.3.0/.pi/harnesses/coms/index.ts +1595 -0
  218. package/.versions/0.3.0/.pi/harnesses/coms/package.json +6 -0
  219. package/.versions/0.3.0/.pi/harnesses/coms-net/README.md +46 -0
  220. package/.versions/0.3.0/.pi/harnesses/coms-net/index.ts +1637 -0
  221. package/.versions/0.3.0/.pi/harnesses/coms-net/package.json +6 -0
  222. package/.versions/0.3.0/.pi/harnesses/damage-control/README.md +38 -0
  223. package/.versions/0.3.0/.pi/harnesses/damage-control/index.ts +207 -0
  224. package/.versions/0.3.0/.pi/harnesses/damage-control/package.json +6 -0
  225. package/.versions/0.3.0/.pi/harnesses/damage-control-continue/README.md +37 -0
  226. package/.versions/0.3.0/.pi/harnesses/damage-control-continue/index.ts +234 -0
  227. package/.versions/0.3.0/.pi/harnesses/damage-control-continue/package.json +6 -0
  228. package/.versions/0.3.0/.pi/harnesses/minimal/README.md +27 -0
  229. package/.versions/0.3.0/.pi/harnesses/minimal/index.ts +32 -0
  230. package/.versions/0.3.0/.pi/harnesses/minimal/package.json +6 -0
  231. package/.versions/0.3.0/.pi/harnesses/package-lock.json +35 -0
  232. package/.versions/0.3.0/.pi/harnesses/package.json +9 -0
  233. package/.versions/0.3.0/.pi/harnesses/pi-pi/README.md +39 -0
  234. package/.versions/0.3.0/.pi/harnesses/pi-pi/index.ts +631 -0
  235. package/.versions/0.3.0/.pi/harnesses/pi-pi/package.json +6 -0
  236. package/.versions/0.3.0/.pi/harnesses/purpose-gate/README.md +27 -0
  237. package/.versions/0.3.0/.pi/harnesses/purpose-gate/index.ts +82 -0
  238. package/.versions/0.3.0/.pi/harnesses/purpose-gate/package.json +6 -0
  239. package/.versions/0.3.0/.pi/harnesses/session-replay/README.md +28 -0
  240. package/.versions/0.3.0/.pi/harnesses/session-replay/index.ts +214 -0
  241. package/.versions/0.3.0/.pi/harnesses/session-replay/package.json +6 -0
  242. package/.versions/0.3.0/.pi/harnesses/subagent-widget/README.md +36 -0
  243. package/.versions/0.3.0/.pi/harnesses/subagent-widget/index.ts +479 -0
  244. package/.versions/0.3.0/.pi/harnesses/subagent-widget/package.json +6 -0
  245. package/.versions/0.3.0/.pi/harnesses/system-select/README.md +39 -0
  246. package/.versions/0.3.0/.pi/harnesses/system-select/index.ts +165 -0
  247. package/.versions/0.3.0/.pi/harnesses/system-select/package.json +6 -0
  248. package/.versions/0.3.0/.pi/harnesses/tilldone/README.md +35 -0
  249. package/.versions/0.3.0/.pi/harnesses/tilldone/index.ts +724 -0
  250. package/.versions/0.3.0/.pi/harnesses/tilldone/package.json +6 -0
  251. package/.versions/0.3.0/.pi/harnesses/tool-counter/README.md +31 -0
  252. package/.versions/0.3.0/.pi/harnesses/tool-counter/index.ts +100 -0
  253. package/.versions/0.3.0/.pi/harnesses/tool-counter/package.json +6 -0
  254. package/.versions/0.3.0/.pi/harnesses/tool-counter-widget/README.md +27 -0
  255. package/.versions/0.3.0/.pi/harnesses/tool-counter-widget/index.ts +66 -0
  256. package/.versions/0.3.0/.pi/harnesses/tool-counter-widget/package.json +6 -0
  257. package/.versions/0.3.0/.pi/prompts/build.md +24 -0
  258. package/.versions/0.3.0/.pi/prompts/code-simplify.md +22 -0
  259. package/.versions/0.3.0/.pi/prompts/doctor-agent-skills.md +13 -0
  260. package/.versions/0.3.0/.pi/prompts/plan.md +16 -0
  261. package/.versions/0.3.0/.pi/prompts/review.md +16 -0
  262. package/.versions/0.3.0/.pi/prompts/setup-agent-skills.md +19 -0
  263. package/.versions/0.3.0/.pi/prompts/ship.md +17 -0
  264. package/.versions/0.3.0/.pi/prompts/spec.md +15 -0
  265. package/.versions/0.3.0/.pi/prompts/test.md +19 -0
  266. package/.versions/0.3.0/.pi/skills/bowser/SKILL.md +114 -0
  267. package/.versions/0.3.0/.version +1 -0
  268. package/.versions/0.3.0/agents/builder.md +6 -0
  269. package/.versions/0.3.0/agents/code-reviewer.md +93 -0
  270. package/.versions/0.3.0/agents/documenter.md +6 -0
  271. package/.versions/0.3.0/agents/plan-reviewer.md +22 -0
  272. package/.versions/0.3.0/agents/planner.md +6 -0
  273. package/.versions/0.3.0/agents/scout.md +6 -0
  274. package/.versions/0.3.0/agents/security-auditor.md +97 -0
  275. package/.versions/0.3.0/agents/test-engineer.md +89 -0
  276. package/.versions/0.3.0/hooks/SIMPLIFY-IGNORE.md +90 -0
  277. package/.versions/0.3.0/hooks/hooks.json +14 -0
  278. package/.versions/0.3.0/hooks/session-start.sh +74 -0
  279. package/.versions/0.3.0/hooks/simplify-ignore-test.sh +247 -0
  280. package/.versions/0.3.0/hooks/simplify-ignore.sh +302 -0
  281. package/.versions/0.3.0/references/accessibility-checklist.md +159 -0
  282. package/.versions/0.3.0/references/performance-checklist.md +121 -0
  283. package/.versions/0.3.0/references/prompting-patterns.md +380 -0
  284. package/.versions/0.3.0/references/security-checklist.md +134 -0
  285. package/.versions/0.3.0/references/testing-patterns.md +236 -0
  286. package/.versions/0.3.0/skills/api-and-interface-design/SKILL.md +294 -0
  287. package/.versions/0.3.0/skills/browser-testing-with-devtools/SKILL.md +335 -0
  288. package/.versions/0.3.0/skills/ci-cd-and-automation/SKILL.md +390 -0
  289. package/.versions/0.3.0/skills/code-review-and-quality/SKILL.md +347 -0
  290. package/.versions/0.3.0/skills/code-simplification/SKILL.md +331 -0
  291. package/.versions/0.3.0/skills/context-engineering/SKILL.md +291 -0
  292. package/.versions/0.3.0/skills/debugging-and-error-recovery/SKILL.md +300 -0
  293. package/.versions/0.3.0/skills/deprecation-and-migration/SKILL.md +206 -0
  294. package/.versions/0.3.0/skills/designing-agents/SKILL.md +394 -0
  295. package/.versions/0.3.0/skills/designing-agents/pi-harness-authoring.md +213 -0
  296. package/.versions/0.3.0/skills/documentation-and-adrs/SKILL.md +278 -0
  297. package/.versions/0.3.0/skills/frontend-ui-engineering/SKILL.md +322 -0
  298. package/.versions/0.3.0/skills/git-workflow-and-versioning/SKILL.md +316 -0
  299. package/.versions/0.3.0/skills/guided-workspace-setup/SKILL.md +331 -0
  300. package/.versions/0.3.0/skills/idea-refine/SKILL.md +178 -0
  301. package/.versions/0.3.0/skills/idea-refine/examples.md +238 -0
  302. package/.versions/0.3.0/skills/idea-refine/frameworks.md +99 -0
  303. package/.versions/0.3.0/skills/idea-refine/refinement-criteria.md +113 -0
  304. package/.versions/0.3.0/skills/idea-refine/scripts/idea-refine.sh +15 -0
  305. package/.versions/0.3.0/skills/incremental-implementation/SKILL.md +279 -0
  306. package/.versions/0.3.0/skills/performance-optimization/SKILL.md +350 -0
  307. package/.versions/0.3.0/skills/planning-and-task-breakdown/SKILL.md +237 -0
  308. package/.versions/0.3.0/skills/security-and-hardening/SKILL.md +349 -0
  309. package/.versions/0.3.0/skills/shipping-and-launch/SKILL.md +309 -0
  310. package/.versions/0.3.0/skills/source-driven-development/SKILL.md +194 -0
  311. package/.versions/0.3.0/skills/spec-driven-development/SKILL.md +237 -0
  312. package/.versions/0.3.0/skills/test-driven-development/SKILL.md +379 -0
  313. package/.versions/0.3.0/skills/using-agent-skills/SKILL.md +176 -0
  314. package/CHANGELOG.md +108 -0
  315. package/README.md +5 -5
  316. package/bin/cli.js +133 -22
  317. package/bin/lib/bootstrap.js +254 -0
  318. package/bin/lib/doctor.js +1 -1
  319. package/bin/lib/update-notifier.js +195 -0
  320. package/docs/getting-started.md +2 -2
  321. package/docs/npm-install.md +91 -8
  322. package/hooks/session-start.sh +66 -12
  323. package/package.json +1 -1
  324. package/skills/guided-workspace-setup/SKILL.md +41 -3
  325. /package/.claude/commands/{setup.md → setup-agent-skills.md} +0 -0
  326. /package/.opencode/commands/{as-doctor.md → as-doctor-agent-skills.md} +0 -0
  327. /package/.opencode/commands/{as-setup.md → as-setup-agent-skills.md} +0 -0
  328. /package/.pi/prompts/{setup.md → setup-agent-skills.md} +0 -0
@@ -0,0 +1,732 @@
1
+ /**
2
+ * Agent Team — Dispatcher-only orchestrator with grid dashboard
3
+ *
4
+ * The primary Pi agent has NO codebase tools. It can ONLY delegate work
5
+ * to specialist agents via the `dispatch_agent` tool. Each specialist
6
+ * maintains its own Pi session for cross-invocation memory.
7
+ *
8
+ * Loads agent definitions from agents/*.md, .claude/agents/*.md, .pi/agents/*.md.
9
+ * Teams are defined in .pi/agents/teams.yaml — on boot a select dialog lets
10
+ * you pick which team to work with. Only team members are available for dispatch.
11
+ *
12
+ * Commands:
13
+ * /agents-team — switch active team
14
+ * /agents-list — list loaded agents
15
+ * /agents-grid N — set column count (default 2)
16
+ *
17
+ * Usage: pi -e extensions/agent-team.ts
18
+ */
19
+
20
+ import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
21
+ import { Type } from "@sinclair/typebox";
22
+ import { Text, type AutocompleteItem, truncateToWidth, visibleWidth } from "@mariozechner/pi-tui";
23
+ import { spawn } from "child_process";
24
+ import { readdirSync, readFileSync, existsSync, mkdirSync, unlinkSync } from "fs";
25
+ import { join, resolve } from "path";
26
+
27
+ // ── Types ────────────────────────────────────────
28
+
29
+ interface AgentDef {
30
+ name: string;
31
+ description: string;
32
+ tools: string;
33
+ systemPrompt: string;
34
+ file: string;
35
+ }
36
+
37
+ interface AgentState {
38
+ def: AgentDef;
39
+ status: "idle" | "running" | "done" | "error";
40
+ task: string;
41
+ toolCount: number;
42
+ elapsed: number;
43
+ lastWork: string;
44
+ contextPct: number;
45
+ sessionFile: string | null;
46
+ runCount: number;
47
+ timer?: ReturnType<typeof setInterval>;
48
+ }
49
+
50
+ // ── Display Name Helper ──────────────────────────
51
+
52
+ function displayName(name: string): string {
53
+ return name.split("-").map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
54
+ }
55
+
56
+ // ── Teams YAML Parser ────────────────────────────
57
+
58
+ function parseTeamsYaml(raw: string): Record<string, string[]> {
59
+ const teams: Record<string, string[]> = {};
60
+ let current: string | null = null;
61
+ for (const line of raw.split("\n")) {
62
+ const teamMatch = line.match(/^(\S[^:]*):$/);
63
+ if (teamMatch) {
64
+ current = teamMatch[1].trim();
65
+ teams[current] = [];
66
+ continue;
67
+ }
68
+ const itemMatch = line.match(/^\s+-\s+(.+)$/);
69
+ if (itemMatch && current) {
70
+ teams[current].push(itemMatch[1].trim());
71
+ }
72
+ }
73
+ return teams;
74
+ }
75
+
76
+ // ── Frontmatter Parser ───────────────────────────
77
+
78
+ function parseAgentFile(filePath: string): AgentDef | null {
79
+ try {
80
+ const raw = readFileSync(filePath, "utf-8");
81
+ const match = raw.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
82
+ if (!match) return null;
83
+
84
+ const frontmatter: Record<string, string> = {};
85
+ for (const line of match[1].split("\n")) {
86
+ const idx = line.indexOf(":");
87
+ if (idx > 0) {
88
+ frontmatter[line.slice(0, idx).trim()] = line.slice(idx + 1).trim();
89
+ }
90
+ }
91
+
92
+ if (!frontmatter.name) return null;
93
+
94
+ return {
95
+ name: frontmatter.name,
96
+ description: frontmatter.description || "",
97
+ tools: frontmatter.tools || "read,grep,find,ls",
98
+ systemPrompt: match[2].trim(),
99
+ file: filePath,
100
+ };
101
+ } catch {
102
+ return null;
103
+ }
104
+ }
105
+
106
+ function scanAgentDirs(cwd: string): AgentDef[] {
107
+ const dirs = [
108
+ join(cwd, "agents"),
109
+ join(cwd, ".claude", "agents"),
110
+ join(cwd, ".pi", "agents"),
111
+ ];
112
+
113
+ const agents: AgentDef[] = [];
114
+ const seen = new Set<string>();
115
+
116
+ for (const dir of dirs) {
117
+ if (!existsSync(dir)) continue;
118
+ try {
119
+ for (const file of readdirSync(dir)) {
120
+ if (!file.endsWith(".md")) continue;
121
+ const fullPath = resolve(dir, file);
122
+ const def = parseAgentFile(fullPath);
123
+ if (def && !seen.has(def.name.toLowerCase())) {
124
+ seen.add(def.name.toLowerCase());
125
+ agents.push(def);
126
+ }
127
+ }
128
+ } catch {}
129
+ }
130
+
131
+ return agents;
132
+ }
133
+
134
+ // ── Extension ────────────────────────────────────
135
+
136
+ export default function (pi: ExtensionAPI) {
137
+ const agentStates: Map<string, AgentState> = new Map();
138
+ let allAgentDefs: AgentDef[] = [];
139
+ let teams: Record<string, string[]> = {};
140
+ let activeTeamName = "";
141
+ let gridCols = 2;
142
+ let widgetCtx: any;
143
+ let sessionDir = "";
144
+ let contextWindow = 0;
145
+
146
+ function loadAgents(cwd: string) {
147
+ // Create session storage dir
148
+ sessionDir = join(cwd, ".pi", "agent-sessions");
149
+ if (!existsSync(sessionDir)) {
150
+ mkdirSync(sessionDir, { recursive: true });
151
+ }
152
+
153
+ // Load all agent definitions
154
+ allAgentDefs = scanAgentDirs(cwd);
155
+
156
+ // Load teams from .pi/agents/teams.yaml
157
+ const teamsPath = join(cwd, ".pi", "agents", "teams.yaml");
158
+ if (existsSync(teamsPath)) {
159
+ try {
160
+ teams = parseTeamsYaml(readFileSync(teamsPath, "utf-8"));
161
+ } catch {
162
+ teams = {};
163
+ }
164
+ } else {
165
+ teams = {};
166
+ }
167
+
168
+ // If no teams defined, create a default "all" team
169
+ if (Object.keys(teams).length === 0) {
170
+ teams = { all: allAgentDefs.map(d => d.name) };
171
+ }
172
+ }
173
+
174
+ function activateTeam(teamName: string) {
175
+ activeTeamName = teamName;
176
+ const members = teams[teamName] || [];
177
+ const defsByName = new Map(allAgentDefs.map(d => [d.name.toLowerCase(), d]));
178
+
179
+ agentStates.clear();
180
+ for (const member of members) {
181
+ const def = defsByName.get(member.toLowerCase());
182
+ if (!def) continue;
183
+ const key = def.name.toLowerCase().replace(/\s+/g, "-");
184
+ const sessionFile = join(sessionDir, `${key}.json`);
185
+ agentStates.set(def.name.toLowerCase(), {
186
+ def,
187
+ status: "idle",
188
+ task: "",
189
+ toolCount: 0,
190
+ elapsed: 0,
191
+ lastWork: "",
192
+ contextPct: 0,
193
+ sessionFile: existsSync(sessionFile) ? sessionFile : null,
194
+ runCount: 0,
195
+ });
196
+ }
197
+
198
+ // Auto-size grid columns based on team size
199
+ const size = agentStates.size;
200
+ gridCols = size <= 3 ? size : size === 4 ? 2 : 3;
201
+ }
202
+
203
+ // ── Grid Rendering ───────────────────────────
204
+
205
+ function renderCard(state: AgentState, colWidth: number, theme: any): string[] {
206
+ const w = colWidth - 2;
207
+ const truncate = (s: string, max: number) => s.length > max ? s.slice(0, max - 3) + "..." : s;
208
+
209
+ const statusColor = state.status === "idle" ? "dim"
210
+ : state.status === "running" ? "accent"
211
+ : state.status === "done" ? "success" : "error";
212
+ const statusIcon = state.status === "idle" ? "○"
213
+ : state.status === "running" ? "●"
214
+ : state.status === "done" ? "✓" : "✗";
215
+
216
+ const name = displayName(state.def.name);
217
+ const nameStr = theme.fg("accent", theme.bold(truncate(name, w)));
218
+ const nameVisible = Math.min(name.length, w);
219
+
220
+ const statusStr = `${statusIcon} ${state.status}`;
221
+ const timeStr = state.status !== "idle" ? ` ${Math.round(state.elapsed / 1000)}s` : "";
222
+ const statusLine = theme.fg(statusColor, statusStr + timeStr);
223
+ const statusVisible = statusStr.length + timeStr.length;
224
+
225
+ // Context bar: 5 blocks + percent
226
+ const filled = Math.ceil(state.contextPct / 20);
227
+ const bar = "#".repeat(filled) + "-".repeat(5 - filled);
228
+ const ctxStr = `[${bar}] ${Math.ceil(state.contextPct)}%`;
229
+ const ctxLine = theme.fg("dim", ctxStr);
230
+ const ctxVisible = ctxStr.length;
231
+
232
+ const workRaw = state.task
233
+ ? (state.lastWork || state.task)
234
+ : state.def.description;
235
+ const workText = truncate(workRaw, Math.min(50, w - 1));
236
+ const workLine = theme.fg("muted", workText);
237
+ const workVisible = workText.length;
238
+
239
+ const top = "┌" + "─".repeat(w) + "┐";
240
+ const bot = "└" + "─".repeat(w) + "┘";
241
+ const border = (content: string, visLen: number) =>
242
+ theme.fg("dim", "│") + content + " ".repeat(Math.max(0, w - visLen)) + theme.fg("dim", "│");
243
+
244
+ return [
245
+ theme.fg("dim", top),
246
+ border(" " + nameStr, 1 + nameVisible),
247
+ border(" " + statusLine, 1 + statusVisible),
248
+ border(" " + ctxLine, 1 + ctxVisible),
249
+ border(" " + workLine, 1 + workVisible),
250
+ theme.fg("dim", bot),
251
+ ];
252
+ }
253
+
254
+ function updateWidget() {
255
+ if (!widgetCtx) return;
256
+
257
+ widgetCtx.ui.setWidget("agent-team", (_tui: any, theme: any) => {
258
+ const text = new Text("", 0, 1);
259
+
260
+ return {
261
+ render(width: number): string[] {
262
+ if (agentStates.size === 0) {
263
+ text.setText(theme.fg("dim", "No agents found. Add .md files to agents/"));
264
+ return text.render(width);
265
+ }
266
+
267
+ const cols = Math.min(gridCols, agentStates.size);
268
+ const gap = 1;
269
+ const colWidth = Math.floor((width - gap * (cols - 1)) / cols);
270
+ const agents = Array.from(agentStates.values());
271
+ const rows: string[][] = [];
272
+
273
+ for (let i = 0; i < agents.length; i += cols) {
274
+ const rowAgents = agents.slice(i, i + cols);
275
+ const cards = rowAgents.map(a => renderCard(a, colWidth, theme));
276
+
277
+ while (cards.length < cols) {
278
+ cards.push(Array(6).fill(" ".repeat(colWidth)));
279
+ }
280
+
281
+ const cardHeight = cards[0].length;
282
+ for (let line = 0; line < cardHeight; line++) {
283
+ rows.push(cards.map(card => card[line] || ""));
284
+ }
285
+ }
286
+
287
+ const output = rows.map(cols => cols.join(" ".repeat(gap)));
288
+ text.setText(output.join("\n"));
289
+ return text.render(width);
290
+ },
291
+ invalidate() {
292
+ text.invalidate();
293
+ },
294
+ };
295
+ });
296
+ }
297
+
298
+ // ── Dispatch Agent (returns Promise) ─────────
299
+
300
+ function dispatchAgent(
301
+ agentName: string,
302
+ task: string,
303
+ ctx: any,
304
+ ): Promise<{ output: string; exitCode: number; elapsed: number }> {
305
+ const key = agentName.toLowerCase();
306
+ const state = agentStates.get(key);
307
+ if (!state) {
308
+ return Promise.resolve({
309
+ output: `Agent "${agentName}" not found. Available: ${Array.from(agentStates.values()).map(s => displayName(s.def.name)).join(", ")}`,
310
+ exitCode: 1,
311
+ elapsed: 0,
312
+ });
313
+ }
314
+
315
+ if (state.status === "running") {
316
+ return Promise.resolve({
317
+ output: `Agent "${displayName(state.def.name)}" is already running. Wait for it to finish.`,
318
+ exitCode: 1,
319
+ elapsed: 0,
320
+ });
321
+ }
322
+
323
+ state.status = "running";
324
+ state.task = task;
325
+ state.toolCount = 0;
326
+ state.elapsed = 0;
327
+ state.lastWork = "";
328
+ state.runCount++;
329
+ updateWidget();
330
+
331
+ const startTime = Date.now();
332
+ state.timer = setInterval(() => {
333
+ state.elapsed = Date.now() - startTime;
334
+ updateWidget();
335
+ }, 1000);
336
+
337
+ const model = ctx.model
338
+ ? `${ctx.model.provider}/${ctx.model.id}`
339
+ : "openrouter/google/gemini-3-flash-preview";
340
+
341
+ // Session file for this agent
342
+ const agentKey = state.def.name.toLowerCase().replace(/\s+/g, "-");
343
+ const agentSessionFile = join(sessionDir, `${agentKey}.json`);
344
+
345
+ // Build args — first run creates session, subsequent runs resume
346
+ const args = [
347
+ "--mode", "json",
348
+ "-p",
349
+ "--no-extensions",
350
+ "--model", model,
351
+ "--tools", state.def.tools,
352
+ "--thinking", "off",
353
+ "--append-system-prompt", state.def.systemPrompt,
354
+ "--session", agentSessionFile,
355
+ ];
356
+
357
+ // Continue existing session if we have one
358
+ if (state.sessionFile) {
359
+ args.push("-c");
360
+ }
361
+
362
+ args.push(task);
363
+
364
+ const textChunks: string[] = [];
365
+
366
+ return new Promise((resolve) => {
367
+ const proc = spawn("pi", args, {
368
+ stdio: ["ignore", "pipe", "pipe"],
369
+ env: { ...process.env },
370
+ });
371
+
372
+ let buffer = "";
373
+
374
+ proc.stdout!.setEncoding("utf-8");
375
+ proc.stdout!.on("data", (chunk: string) => {
376
+ buffer += chunk;
377
+ const lines = buffer.split("\n");
378
+ buffer = lines.pop() || "";
379
+ for (const line of lines) {
380
+ if (!line.trim()) continue;
381
+ try {
382
+ const event = JSON.parse(line);
383
+ if (event.type === "message_update") {
384
+ const delta = event.assistantMessageEvent;
385
+ if (delta?.type === "text_delta") {
386
+ textChunks.push(delta.delta || "");
387
+ const full = textChunks.join("");
388
+ const last = full.split("\n").filter((l: string) => l.trim()).pop() || "";
389
+ state.lastWork = last;
390
+ updateWidget();
391
+ }
392
+ } else if (event.type === "tool_execution_start") {
393
+ state.toolCount++;
394
+ updateWidget();
395
+ } else if (event.type === "message_end") {
396
+ const msg = event.message;
397
+ if (msg?.usage && contextWindow > 0) {
398
+ state.contextPct = ((msg.usage.input || 0) / contextWindow) * 100;
399
+ updateWidget();
400
+ }
401
+ } else if (event.type === "agent_end") {
402
+ const msgs = event.messages || [];
403
+ const last = [...msgs].reverse().find((m: any) => m.role === "assistant");
404
+ if (last?.usage && contextWindow > 0) {
405
+ state.contextPct = ((last.usage.input || 0) / contextWindow) * 100;
406
+ updateWidget();
407
+ }
408
+ }
409
+ } catch {}
410
+ }
411
+ });
412
+
413
+ proc.stderr!.setEncoding("utf-8");
414
+ proc.stderr!.on("data", () => {});
415
+
416
+ proc.on("close", (code) => {
417
+ if (buffer.trim()) {
418
+ try {
419
+ const event = JSON.parse(buffer);
420
+ if (event.type === "message_update") {
421
+ const delta = event.assistantMessageEvent;
422
+ if (delta?.type === "text_delta") textChunks.push(delta.delta || "");
423
+ }
424
+ } catch {}
425
+ }
426
+
427
+ clearInterval(state.timer);
428
+ state.elapsed = Date.now() - startTime;
429
+ state.status = code === 0 ? "done" : "error";
430
+
431
+ // Mark session file as available for resume
432
+ if (code === 0) {
433
+ state.sessionFile = agentSessionFile;
434
+ }
435
+
436
+ const full = textChunks.join("");
437
+ state.lastWork = full.split("\n").filter((l: string) => l.trim()).pop() || "";
438
+ updateWidget();
439
+
440
+ ctx.ui.notify(
441
+ `${displayName(state.def.name)} ${state.status} in ${Math.round(state.elapsed / 1000)}s`,
442
+ state.status === "done" ? "success" : "error"
443
+ );
444
+
445
+ resolve({
446
+ output: full,
447
+ exitCode: code ?? 1,
448
+ elapsed: state.elapsed,
449
+ });
450
+ });
451
+
452
+ proc.on("error", (err) => {
453
+ clearInterval(state.timer);
454
+ state.status = "error";
455
+ state.lastWork = `Error: ${err.message}`;
456
+ updateWidget();
457
+ resolve({
458
+ output: `Error spawning agent: ${err.message}`,
459
+ exitCode: 1,
460
+ elapsed: Date.now() - startTime,
461
+ });
462
+ });
463
+ });
464
+ }
465
+
466
+ // ── dispatch_agent Tool (registered at top level) ──
467
+
468
+ pi.registerTool({
469
+ name: "dispatch_agent",
470
+ label: "Dispatch Agent",
471
+ description: "Dispatch a task to a specialist agent. The agent will execute the task and return the result. Use the system prompt to see available agent names.",
472
+ parameters: Type.Object({
473
+ agent: Type.String({ description: "Agent name (case-insensitive)" }),
474
+ task: Type.String({ description: "Task description for the agent to execute" }),
475
+ }),
476
+
477
+ async execute(_toolCallId, params, _signal, onUpdate, ctx) {
478
+ const { agent, task } = params as { agent: string; task: string };
479
+
480
+ try {
481
+ if (onUpdate) {
482
+ onUpdate({
483
+ content: [{ type: "text", text: `Dispatching to ${agent}...` }],
484
+ details: { agent, task, status: "dispatching" },
485
+ });
486
+ }
487
+
488
+ const result = await dispatchAgent(agent, task, ctx);
489
+
490
+ const truncated = result.output.length > 8000
491
+ ? result.output.slice(0, 8000) + "\n\n... [truncated]"
492
+ : result.output;
493
+
494
+ const status = result.exitCode === 0 ? "done" : "error";
495
+ const summary = `[${agent}] ${status} in ${Math.round(result.elapsed / 1000)}s`;
496
+
497
+ return {
498
+ content: [{ type: "text", text: `${summary}\n\n${truncated}` }],
499
+ details: {
500
+ agent,
501
+ task,
502
+ status,
503
+ elapsed: result.elapsed,
504
+ exitCode: result.exitCode,
505
+ fullOutput: result.output,
506
+ },
507
+ };
508
+ } catch (err: any) {
509
+ return {
510
+ content: [{ type: "text", text: `Error dispatching to ${agent}: ${err?.message || err}` }],
511
+ details: { agent, task, status: "error", elapsed: 0, exitCode: 1, fullOutput: "" },
512
+ };
513
+ }
514
+ },
515
+
516
+ renderCall(args, theme) {
517
+ const agentName = (args as any).agent || "?";
518
+ const task = (args as any).task || "";
519
+ const preview = task.length > 60 ? task.slice(0, 57) + "..." : task;
520
+ return new Text(
521
+ theme.fg("toolTitle", theme.bold("dispatch_agent ")) +
522
+ theme.fg("accent", agentName) +
523
+ theme.fg("dim", " — ") +
524
+ theme.fg("muted", preview),
525
+ 0, 0,
526
+ );
527
+ },
528
+
529
+ renderResult(result, options, theme) {
530
+ const details = result.details as any;
531
+ if (!details) {
532
+ const text = result.content[0];
533
+ return new Text(text?.type === "text" ? text.text : "", 0, 0);
534
+ }
535
+
536
+ // Streaming/partial result while agent is still running
537
+ if (options.isPartial || details.status === "dispatching") {
538
+ return new Text(
539
+ theme.fg("accent", `● ${details.agent || "?"}`) +
540
+ theme.fg("dim", " working..."),
541
+ 0, 0,
542
+ );
543
+ }
544
+
545
+ const icon = details.status === "done" ? "✓" : "✗";
546
+ const color = details.status === "done" ? "success" : "error";
547
+ const elapsed = typeof details.elapsed === "number" ? Math.round(details.elapsed / 1000) : 0;
548
+ const header = theme.fg(color, `${icon} ${details.agent}`) +
549
+ theme.fg("dim", ` ${elapsed}s`);
550
+
551
+ if (options.expanded && details.fullOutput) {
552
+ const output = details.fullOutput.length > 4000
553
+ ? details.fullOutput.slice(0, 4000) + "\n... [truncated]"
554
+ : details.fullOutput;
555
+ return new Text(header + "\n" + theme.fg("muted", output), 0, 0);
556
+ }
557
+
558
+ return new Text(header, 0, 0);
559
+ },
560
+ });
561
+
562
+ // ── Commands ─────────────────────────────────
563
+
564
+ pi.registerCommand("agents-team", {
565
+ description: "Select a team to work with",
566
+ handler: async (_args, ctx) => {
567
+ widgetCtx = ctx;
568
+ const teamNames = Object.keys(teams);
569
+ if (teamNames.length === 0) {
570
+ ctx.ui.notify("No teams defined in .pi/agents/teams.yaml", "warning");
571
+ return;
572
+ }
573
+
574
+ const options = teamNames.map(name => {
575
+ const members = teams[name].map(m => displayName(m));
576
+ return `${name} — ${members.join(", ")}`;
577
+ });
578
+
579
+ const choice = await ctx.ui.select("Select Team", options);
580
+ if (choice === undefined) return;
581
+
582
+ const idx = options.indexOf(choice);
583
+ const name = teamNames[idx];
584
+ activateTeam(name);
585
+ updateWidget();
586
+ ctx.ui.setStatus("agent-team", `Team: ${name} (${agentStates.size})`);
587
+ ctx.ui.notify(`Team: ${name} — ${Array.from(agentStates.values()).map(s => displayName(s.def.name)).join(", ")}`, "info");
588
+ },
589
+ });
590
+
591
+ pi.registerCommand("agents-list", {
592
+ description: "List all loaded agents",
593
+ handler: async (_args, _ctx) => {
594
+ widgetCtx = _ctx;
595
+ const names = Array.from(agentStates.values())
596
+ .map(s => {
597
+ const session = s.sessionFile ? "resumed" : "new";
598
+ return `${displayName(s.def.name)} (${s.status}, ${session}, runs: ${s.runCount}): ${s.def.description}`;
599
+ })
600
+ .join("\n");
601
+ _ctx.ui.notify(names || "No agents loaded", "info");
602
+ },
603
+ });
604
+
605
+ pi.registerCommand("agents-grid", {
606
+ description: "Set grid columns: /agents-grid <1-6>",
607
+ getArgumentCompletions: (prefix: string): AutocompleteItem[] | null => {
608
+ const items = ["1", "2", "3", "4", "5", "6"].map(n => ({
609
+ value: n,
610
+ label: `${n} columns`,
611
+ }));
612
+ const filtered = items.filter(i => i.value.startsWith(prefix));
613
+ return filtered.length > 0 ? filtered : items;
614
+ },
615
+ handler: async (args, _ctx) => {
616
+ widgetCtx = _ctx;
617
+ const n = parseInt(args?.trim() || "", 10);
618
+ if (n >= 1 && n <= 6) {
619
+ gridCols = n;
620
+ _ctx.ui.notify(`Grid set to ${gridCols} columns`, "info");
621
+ updateWidget();
622
+ } else {
623
+ _ctx.ui.notify("Usage: /agents-grid <1-6>", "error");
624
+ }
625
+ },
626
+ });
627
+
628
+ // ── System Prompt Override ───────────────────
629
+
630
+ pi.on("before_agent_start", async (_event, _ctx) => {
631
+ // Build dynamic agent catalog from active team only
632
+ const agentCatalog = Array.from(agentStates.values())
633
+ .map(s => `### ${displayName(s.def.name)}\n**Dispatch as:** \`${s.def.name}\`\n${s.def.description}\n**Tools:** ${s.def.tools}`)
634
+ .join("\n\n");
635
+
636
+ const teamMembers = Array.from(agentStates.values()).map(s => displayName(s.def.name)).join(", ");
637
+
638
+ return {
639
+ systemPrompt: `You are a dispatcher agent. You coordinate specialist agents to accomplish tasks.
640
+ You do NOT have direct access to the codebase. You MUST delegate all work through
641
+ agents using the dispatch_agent tool.
642
+
643
+ ## Active Team: ${activeTeamName}
644
+ Members: ${teamMembers}
645
+ You can ONLY dispatch to agents listed below. Do not attempt to dispatch to agents outside this team.
646
+
647
+ ## How to Work
648
+ - Analyze the user's request and break it into clear sub-tasks
649
+ - Choose the right agent(s) for each sub-task
650
+ - Dispatch tasks using the dispatch_agent tool
651
+ - Review results and dispatch follow-up agents if needed
652
+ - If a task fails, try a different agent or adjust the task description
653
+ - Summarize the outcome for the user
654
+
655
+ ## Rules
656
+ - NEVER try to read, write, or execute code directly — you have no such tools
657
+ - ALWAYS use dispatch_agent to get work done
658
+ - You can chain agents: use scout to explore, then builder to implement
659
+ - You can dispatch the same agent multiple times with different tasks
660
+ - Keep tasks focused — one clear objective per dispatch
661
+
662
+ ## Agents
663
+
664
+ ${agentCatalog}`,
665
+ };
666
+ });
667
+
668
+ // ── Session Start ────────────────────────────
669
+
670
+ pi.on("session_start", async (_event, _ctx) => {
671
+ // Clear widgets from previous session
672
+ if (widgetCtx) {
673
+ widgetCtx.ui.setWidget("agent-team", undefined);
674
+ }
675
+ widgetCtx = _ctx;
676
+ contextWindow = _ctx.model?.contextWindow || 0;
677
+
678
+ // Wipe old agent session files so subagents start fresh
679
+ const sessDir = join(_ctx.cwd, ".pi", "agent-sessions");
680
+ if (existsSync(sessDir)) {
681
+ for (const f of readdirSync(sessDir)) {
682
+ if (f.endsWith(".json")) {
683
+ try { unlinkSync(join(sessDir, f)); } catch {}
684
+ }
685
+ }
686
+ }
687
+
688
+ loadAgents(_ctx.cwd);
689
+
690
+ // Default to first team — use /agents-team to switch
691
+ const teamNames = Object.keys(teams);
692
+ if (teamNames.length > 0) {
693
+ activateTeam(teamNames[0]);
694
+ }
695
+
696
+ // Lock down to dispatcher-only (tool already registered at top level)
697
+ pi.setActiveTools(["dispatch_agent"]);
698
+
699
+ _ctx.ui.setStatus("agent-team", `Team: ${activeTeamName} (${agentStates.size})`);
700
+ const members = Array.from(agentStates.values()).map(s => displayName(s.def.name)).join(", ");
701
+ _ctx.ui.notify(
702
+ `Team: ${activeTeamName} (${members})\n` +
703
+ `Team sets loaded from: .pi/agents/teams.yaml\n\n` +
704
+ `/agents-team Select a team\n` +
705
+ `/agents-list List active agents and status\n` +
706
+ `/agents-grid <1-6> Set grid column count`,
707
+ "info",
708
+ );
709
+ updateWidget();
710
+
711
+ // Footer: model | team | context bar
712
+ _ctx.ui.setFooter((_tui, theme, _footerData) => ({
713
+ dispose: () => {},
714
+ invalidate() {},
715
+ render(width: number): string[] {
716
+ const model = _ctx.model?.id || "no-model";
717
+ const usage = _ctx.getContextUsage();
718
+ const pct = usage ? usage.percent : 0;
719
+ const filled = Math.round(pct / 10);
720
+ const bar = "#".repeat(filled) + "-".repeat(10 - filled);
721
+
722
+ const left = theme.fg("dim", ` ${model}`) +
723
+ theme.fg("muted", " · ") +
724
+ theme.fg("accent", activeTeamName);
725
+ const right = theme.fg("dim", `[${bar}] ${Math.round(pct)}% `);
726
+ const pad = " ".repeat(Math.max(1, width - visibleWidth(left) - visibleWidth(right)));
727
+
728
+ return [truncateToWidth(left + pad + right, width)];
729
+ },
730
+ }));
731
+ });
732
+ }