@keystrokehq/cli 0.0.0-staging-20260714051854

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 (253) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +272 -0
  3. package/dist/alias-RTYYYW3D-CLFgrowj.mjs +98 -0
  4. package/dist/alias-RTYYYW3D-CLFgrowj.mjs.map +1 -0
  5. package/dist/awk2-LA3USKJP-BbsfXVlR.mjs +2737 -0
  6. package/dist/awk2-LA3USKJP-BbsfXVlR.mjs.map +1 -0
  7. package/dist/base64-C2AIWVNC-C0WIgu5V.mjs +123 -0
  8. package/dist/base64-C2AIWVNC-C0WIgu5V.mjs.map +1 -0
  9. package/dist/basename-UB3CIYNI-BgNN3bGm.mjs +53 -0
  10. package/dist/basename-UB3CIYNI-BgNN3bGm.mjs.map +1 -0
  11. package/dist/bash-YZ33HQZQ-N6YyKtUH.mjs +118 -0
  12. package/dist/bash-YZ33HQZQ-N6YyKtUH.mjs.map +1 -0
  13. package/dist/cat-TSFMZVYS-Dz3-oHsV.mjs +63 -0
  14. package/dist/cat-TSFMZVYS-Dz3-oHsV.mjs.map +1 -0
  15. package/dist/chmod-TFEPA42X-YF02QJUv.mjs +125 -0
  16. package/dist/chmod-TFEPA42X-YF02QJUv.mjs.map +1 -0
  17. package/dist/chunk-27JIFWUR-B6ZjjMMI.mjs +100 -0
  18. package/dist/chunk-27JIFWUR-B6ZjjMMI.mjs.map +1 -0
  19. package/dist/chunk-4I3HOE5Z-BixWWVkW.mjs +719 -0
  20. package/dist/chunk-4I3HOE5Z-BixWWVkW.mjs.map +1 -0
  21. package/dist/chunk-4RUAZWKT-D60fyWAB.mjs +22543 -0
  22. package/dist/chunk-4RUAZWKT-D60fyWAB.mjs.map +1 -0
  23. package/dist/chunk-4WKZNNJK-CiwxAWRf.mjs +69 -0
  24. package/dist/chunk-4WKZNNJK-CiwxAWRf.mjs.map +1 -0
  25. package/dist/chunk-5H5SCKJM-BvfXlL01.mjs +606 -0
  26. package/dist/chunk-5H5SCKJM-BvfXlL01.mjs.map +1 -0
  27. package/dist/chunk-AQ6FYS2X-CkVetjym.mjs +37 -0
  28. package/dist/chunk-AQ6FYS2X-CkVetjym.mjs.map +1 -0
  29. package/dist/chunk-BZUGFHVS-CPWRFwK8.mjs +34 -0
  30. package/dist/chunk-BZUGFHVS-CPWRFwK8.mjs.map +1 -0
  31. package/dist/chunk-CHFEPBH4-BUdgjFtD.mjs +594 -0
  32. package/dist/chunk-CHFEPBH4-BUdgjFtD.mjs.map +1 -0
  33. package/dist/chunk-DLL7UR66-BUYgzxnR.mjs +14 -0
  34. package/dist/chunk-DLL7UR66-BUYgzxnR.mjs.map +1 -0
  35. package/dist/chunk-DiodbrVj.mjs +27 -0
  36. package/dist/chunk-EBAPSGAO-Ctfslw2R.mjs +247 -0
  37. package/dist/chunk-EBAPSGAO-Ctfslw2R.mjs.map +1 -0
  38. package/dist/chunk-FOCWZZDE-BIntqBh2.mjs +19 -0
  39. package/dist/chunk-FOCWZZDE-BIntqBh2.mjs.map +1 -0
  40. package/dist/chunk-HBVMHTO5-CJyD-QZX.mjs +10 -0
  41. package/dist/chunk-HBVMHTO5-CJyD-QZX.mjs.map +1 -0
  42. package/dist/chunk-L2UW7DWF-B3tEHhPF.mjs +14 -0
  43. package/dist/chunk-L2UW7DWF-B3tEHhPF.mjs.map +1 -0
  44. package/dist/chunk-L64BMZUV-CyR7RKok.mjs +30 -0
  45. package/dist/chunk-L64BMZUV-CyR7RKok.mjs.map +1 -0
  46. package/dist/chunk-LEKBROJD-CJMrAyu9.mjs +3113 -0
  47. package/dist/chunk-LEKBROJD-CJMrAyu9.mjs.map +1 -0
  48. package/dist/chunk-NRSASXYY-CuWyREpD.mjs +41 -0
  49. package/dist/chunk-NRSASXYY-CuWyREpD.mjs.map +1 -0
  50. package/dist/chunk-QAYAQNCG-Bl0Kbd53.mjs +63 -0
  51. package/dist/chunk-QAYAQNCG-Bl0Kbd53.mjs.map +1 -0
  52. package/dist/chunk-QIQMJJZ4-BwKdslXs.mjs +93 -0
  53. package/dist/chunk-QIQMJJZ4-BwKdslXs.mjs.map +1 -0
  54. package/dist/chunk-SAI2SPQQ-CVRoDNs9.mjs +26 -0
  55. package/dist/chunk-SAI2SPQQ-CVRoDNs9.mjs.map +1 -0
  56. package/dist/chunk-SO6R3ZKN-tTw_RMDX.mjs +140 -0
  57. package/dist/chunk-SO6R3ZKN-tTw_RMDX.mjs.map +1 -0
  58. package/dist/chunk-STHBFACM-lyj-j2a-.mjs +8 -0
  59. package/dist/chunk-STHBFACM-lyj-j2a-.mjs.map +1 -0
  60. package/dist/chunk-SX2HC7SO-Cc4Hpis1.mjs +20 -0
  61. package/dist/chunk-SX2HC7SO-Cc4Hpis1.mjs.map +1 -0
  62. package/dist/chunk-TDD4NFYE-wsWW75MX.mjs +21 -0
  63. package/dist/chunk-TDD4NFYE-wsWW75MX.mjs.map +1 -0
  64. package/dist/chunk-TN7HHBQW-CSB_R-XD.mjs +1137 -0
  65. package/dist/chunk-TN7HHBQW-CSB_R-XD.mjs.map +1 -0
  66. package/dist/chunk-VPADYNBD-BKlA28GJ.mjs +122 -0
  67. package/dist/chunk-VPADYNBD-BKlA28GJ.mjs.map +1 -0
  68. package/dist/chunk-W5DWRFSU-lCyWk0ph.mjs +11 -0
  69. package/dist/chunk-W5DWRFSU-lCyWk0ph.mjs.map +1 -0
  70. package/dist/chunk-WNH3HOQA-BCZUOjCJ.mjs +34 -0
  71. package/dist/chunk-WNH3HOQA-BCZUOjCJ.mjs.map +1 -0
  72. package/dist/chunk-XRFHFXFP-BGxzVZgK.mjs +16 -0
  73. package/dist/chunk-XRFHFXFP-BGxzVZgK.mjs.map +1 -0
  74. package/dist/chunk-YCLFEX4T-COc1AThz.mjs +77 -0
  75. package/dist/chunk-YCLFEX4T-COc1AThz.mjs.map +1 -0
  76. package/dist/clear-HKGFEOF6-CekN2x-O.mjs +28 -0
  77. package/dist/clear-HKGFEOF6-CekN2x-O.mjs.map +1 -0
  78. package/dist/column-XT6UFXNQ-DHENV9D2.mjs +143 -0
  79. package/dist/column-XT6UFXNQ-DHENV9D2.mjs.map +1 -0
  80. package/dist/comm-VV2LDX2J-ppxDJFkY.mjs +87 -0
  81. package/dist/comm-VV2LDX2J-ppxDJFkY.mjs.map +1 -0
  82. package/dist/configs/oxlintrc.json +27 -0
  83. package/dist/configs/vitest.config.mjs +42 -0
  84. package/dist/configs/vitest.setup.integration.mjs +37 -0
  85. package/dist/cp-BISAAS7A-CMWayU4n.mjs +106 -0
  86. package/dist/cp-BISAAS7A-CMWayU4n.mjs.map +1 -0
  87. package/dist/cut-OKARJCCV-Bt8b58eI.mjs +119 -0
  88. package/dist/cut-OKARJCCV-Bt8b58eI.mjs.map +1 -0
  89. package/dist/date-UUUPW43J-B7T5OTZZ.mjs +188 -0
  90. package/dist/date-UUUPW43J-B7T5OTZZ.mjs.map +1 -0
  91. package/dist/diff-MWJFIG7X-DhnPc_5r.mjs +755 -0
  92. package/dist/diff-MWJFIG7X-DhnPc_5r.mjs.map +1 -0
  93. package/dist/dirname-MPHRFUTI-Dkb3S4OX.mjs +43 -0
  94. package/dist/dirname-MPHRFUTI-Dkb3S4OX.mjs.map +1 -0
  95. package/dist/dist-BFOvwXwm.mjs +31042 -0
  96. package/dist/dist-BFOvwXwm.mjs.map +1 -0
  97. package/dist/dist-BoZPZ9Sz.mjs +8498 -0
  98. package/dist/dist-BoZPZ9Sz.mjs.map +1 -0
  99. package/dist/dist-D9y3OVoD.mjs +3 -0
  100. package/dist/dist-De18Uq1U.mjs +11680 -0
  101. package/dist/dist-De18Uq1U.mjs.map +1 -0
  102. package/dist/dist-yDNd8kGO.mjs +801 -0
  103. package/dist/dist-yDNd8kGO.mjs.map +1 -0
  104. package/dist/du-572XNP42-ClP4jXB1.mjs +176 -0
  105. package/dist/du-572XNP42-ClP4jXB1.mjs.map +1 -0
  106. package/dist/echo-NDWZZHPO-CCp_-MxA.mjs +137 -0
  107. package/dist/echo-NDWZZHPO-CCp_-MxA.mjs.map +1 -0
  108. package/dist/env-36M5BO7M-CsP_aiWr.mjs +119 -0
  109. package/dist/env-36M5BO7M-CsP_aiWr.mjs.map +1 -0
  110. package/dist/expand-JSPG6VOP-B-YUvYpu.mjs +145 -0
  111. package/dist/expand-JSPG6VOP-B-YUvYpu.mjs.map +1 -0
  112. package/dist/expr-5JAACS4X-1TBq84gG.mjs +153 -0
  113. package/dist/expr-5JAACS4X-1TBq84gG.mjs.map +1 -0
  114. package/dist/file-IPZJC3FQ-DcZNOWyY.mjs +4201 -0
  115. package/dist/file-IPZJC3FQ-DcZNOWyY.mjs.map +1 -0
  116. package/dist/find-INTH3OLC-6p47KeeT.mjs +1332 -0
  117. package/dist/find-INTH3OLC-6p47KeeT.mjs.map +1 -0
  118. package/dist/fold-4TQNYMSW-C54bHzLd.mjs +138 -0
  119. package/dist/fold-4TQNYMSW-C54bHzLd.mjs.map +1 -0
  120. package/dist/grep-V3LQVMRQ-D99Bq7Kj.mjs +335 -0
  121. package/dist/grep-V3LQVMRQ-D99Bq7Kj.mjs.map +1 -0
  122. package/dist/gzip-O5ASJAFY-CZDRROqP.mjs +592 -0
  123. package/dist/gzip-O5ASJAFY-CZDRROqP.mjs.map +1 -0
  124. package/dist/head-442HYESI-D96RMdki.mjs +36 -0
  125. package/dist/head-442HYESI-D96RMdki.mjs.map +1 -0
  126. package/dist/help-HZ6M2CKN--DK8mY2L.mjs +123 -0
  127. package/dist/help-HZ6M2CKN--DK8mY2L.mjs.map +1 -0
  128. package/dist/history-WYYKSLSZ-ACNQVupn.mjs +48 -0
  129. package/dist/history-WYYKSLSZ-ACNQVupn.mjs.map +1 -0
  130. package/dist/hostname-C4HQXXUP-CXVVFkUK.mjs +24 -0
  131. package/dist/hostname-C4HQXXUP-CXVVFkUK.mjs.map +1 -0
  132. package/dist/html-to-markdown-JW4MSQZO-DQOxFIvF.mjs +15890 -0
  133. package/dist/html-to-markdown-JW4MSQZO-DQOxFIvF.mjs.map +1 -0
  134. package/dist/index.mjs +9675 -0
  135. package/dist/index.mjs.map +1 -0
  136. package/dist/join-TBRGI3LQ-B8I9tkJ5.mjs +198 -0
  137. package/dist/join-TBRGI3LQ-B8I9tkJ5.mjs.map +1 -0
  138. package/dist/jq-4XLYLOS5-wFZYfsfJ.mjs +257 -0
  139. package/dist/jq-4XLYLOS5-wFZYfsfJ.mjs.map +1 -0
  140. package/dist/js-exec-N5KEZBH7-CoRL1IOd.mjs +333 -0
  141. package/dist/js-exec-N5KEZBH7-CoRL1IOd.mjs.map +1 -0
  142. package/dist/lib-D4GpdNNK.mjs +45 -0
  143. package/dist/lib-D4GpdNNK.mjs.map +1 -0
  144. package/dist/ln-4LGSXXGD-Dg0R9i5G.mjs +101 -0
  145. package/dist/ln-4LGSXXGD-Dg0R9i5G.mjs.map +1 -0
  146. package/dist/ls-ZJGQER7M-DLDSfI4x.mjs +1891 -0
  147. package/dist/ls-ZJGQER7M-DLDSfI4x.mjs.map +1 -0
  148. package/dist/lzma-CTMDi254.mjs +1135 -0
  149. package/dist/lzma-CTMDi254.mjs.map +1 -0
  150. package/dist/maybe-auto-update-C-HUlgKp.mjs +139 -0
  151. package/dist/maybe-auto-update-C-HUlgKp.mjs.map +1 -0
  152. package/dist/md5sum-SPU24VSG-DQc8sqXO.mjs +16 -0
  153. package/dist/md5sum-SPU24VSG-DQc8sqXO.mjs.map +1 -0
  154. package/dist/mkdir-MEPGZOB6-BjUKzhdL.mjs +58 -0
  155. package/dist/mkdir-MEPGZOB6-BjUKzhdL.mjs.map +1 -0
  156. package/dist/mv-W5BIQ646-CdSIyY-U.mjs +93 -0
  157. package/dist/mv-W5BIQ646-CdSIyY-U.mjs.map +1 -0
  158. package/dist/nl-WSDW7I4O-DmtCnyKU.mjs +208 -0
  159. package/dist/nl-WSDW7I4O-DmtCnyKU.mjs.map +1 -0
  160. package/dist/od-WOKFDJTP-DZ2nxQNJ.mjs +73 -0
  161. package/dist/od-WOKFDJTP-DZ2nxQNJ.mjs.map +1 -0
  162. package/dist/paste-7JC6S4DX-CtmM5Qy8.mjs +113 -0
  163. package/dist/paste-7JC6S4DX-CtmM5Qy8.mjs.map +1 -0
  164. package/dist/printf-TWGXF445-B7cTysaa.mjs +880 -0
  165. package/dist/printf-TWGXF445-B7cTysaa.mjs.map +1 -0
  166. package/dist/pwd-WE6EN5AV-CO8o2WQS.mjs +34 -0
  167. package/dist/pwd-WE6EN5AV-CO8o2WQS.mjs.map +1 -0
  168. package/dist/python3-POMOR4OA-CKy80mpF.mjs +299 -0
  169. package/dist/python3-POMOR4OA-CKy80mpF.mjs.map +1 -0
  170. package/dist/readlink-OPJF4DL5-Rc1Mz_Xx.mjs +76 -0
  171. package/dist/readlink-OPJF4DL5-Rc1Mz_Xx.mjs.map +1 -0
  172. package/dist/rev-5EHFX4EJ-3dd9vwHW.mjs +66 -0
  173. package/dist/rev-5EHFX4EJ-3dd9vwHW.mjs.map +1 -0
  174. package/dist/rg-S4FXYXWB-BbXVo6JX.mjs +1539 -0
  175. package/dist/rg-S4FXYXWB-BbXVo6JX.mjs.map +1 -0
  176. package/dist/rm-SSGETQVQ-Ch53Rmrr.mjs +81 -0
  177. package/dist/rm-SSGETQVQ-Ch53Rmrr.mjs.map +1 -0
  178. package/dist/rmdir-OC4ZLPYA-D3QCHlIB.mjs +132 -0
  179. package/dist/rmdir-OC4ZLPYA-D3QCHlIB.mjs.map +1 -0
  180. package/dist/run-package-manager-update-D_jU5wZe.mjs +457 -0
  181. package/dist/run-package-manager-update-D_jU5wZe.mjs.map +1 -0
  182. package/dist/sed-S5UIK574-DE1KeTk3.mjs +1722 -0
  183. package/dist/sed-S5UIK574-DE1KeTk3.mjs.map +1 -0
  184. package/dist/seq-M5EC7Q57-BHfGjQvK.mjs +85 -0
  185. package/dist/seq-M5EC7Q57-BHfGjQvK.mjs.map +1 -0
  186. package/dist/sha1sum-2PTOAFR6-DNjSNcYK.mjs +16 -0
  187. package/dist/sha1sum-2PTOAFR6-DNjSNcYK.mjs.map +1 -0
  188. package/dist/sha256sum-NS7D3IXX-BMaCKkT5.mjs +16 -0
  189. package/dist/sha256sum-NS7D3IXX-BMaCKkT5.mjs.map +1 -0
  190. package/dist/skills-bundle/_AGENTS.mcp.md +161 -0
  191. package/dist/skills-bundle/_AGENTS.md +362 -0
  192. package/dist/sleep-X22JJINO-Do5hEQQW.mjs +67 -0
  193. package/dist/sleep-X22JJINO-Do5hEQQW.mjs.map +1 -0
  194. package/dist/sort-SW2YEO5B-B7j1zw8k.mjs +320 -0
  195. package/dist/sort-SW2YEO5B-B7j1zw8k.mjs.map +1 -0
  196. package/dist/split-4KKZZXXE-h8GD4HP4.mjs +248 -0
  197. package/dist/split-4KKZZXXE-h8GD4HP4.mjs.map +1 -0
  198. package/dist/sqlite3-CGOEFJAO-DvzzghDg.mjs +2879 -0
  199. package/dist/sqlite3-CGOEFJAO-DvzzghDg.mjs.map +1 -0
  200. package/dist/stat-CD34IZ4P-B5ZOJh4J.mjs +65 -0
  201. package/dist/stat-CD34IZ4P-B5ZOJh4J.mjs.map +1 -0
  202. package/dist/strings-6WDHLGMX-DdiEdoL-.mjs +179 -0
  203. package/dist/strings-6WDHLGMX-DdiEdoL-.mjs.map +1 -0
  204. package/dist/tac-2STMMJYW-DPyeWM9R.mjs +53 -0
  205. package/dist/tac-2STMMJYW-DPyeWM9R.mjs.map +1 -0
  206. package/dist/tail-R4PCA2C4-CUfroNeu.mjs +37 -0
  207. package/dist/tail-R4PCA2C4-CUfroNeu.mjs.map +1 -0
  208. package/dist/tar-STHHZTZ6-DRf60e-G.mjs +2838 -0
  209. package/dist/tar-STHHZTZ6-DRf60e-G.mjs.map +1 -0
  210. package/dist/tee-YUZ2FKCJ-po_dfyc_.mjs +46 -0
  211. package/dist/tee-YUZ2FKCJ-po_dfyc_.mjs.map +1 -0
  212. package/dist/templates/hello-world/README.md +14 -0
  213. package/dist/templates/hello-world/keystroke.config.ts +3 -0
  214. package/dist/templates/hello-world/package.json +23 -0
  215. package/dist/templates/hello-world/src/actions/greet.ts +21 -0
  216. package/dist/templates/hello-world/src/agents/hello.int.test.ts +13 -0
  217. package/dist/templates/hello-world/src/agents/hello.ts +9 -0
  218. package/dist/templates/hello-world/src/workflows/greeting.test.ts +11 -0
  219. package/dist/templates/hello-world/src/workflows/greeting.ts +14 -0
  220. package/dist/templates/hello-world/tsconfig.json +20 -0
  221. package/dist/time-D4LNBSWX-DVWhAldK.mjs +112 -0
  222. package/dist/time-D4LNBSWX-DVWhAldK.mjs.map +1 -0
  223. package/dist/timeout-YDCRSLPQ-B_yntmXU.mjs +113 -0
  224. package/dist/timeout-YDCRSLPQ-B_yntmXU.mjs.map +1 -0
  225. package/dist/touch-UA33VN3N-oW1SBT1r.mjs +104 -0
  226. package/dist/touch-UA33VN3N-oW1SBT1r.mjs.map +1 -0
  227. package/dist/tr-36LHWFRQ-CTq3z6wq.mjs +167 -0
  228. package/dist/tr-36LHWFRQ-CTq3z6wq.mjs.map +1 -0
  229. package/dist/tree-YLD52CNT-CIozNsLQ.mjs +186 -0
  230. package/dist/tree-YLD52CNT-CIozNsLQ.mjs.map +1 -0
  231. package/dist/true-FHQXJXBE-DsJOznSp.mjs +31 -0
  232. package/dist/true-FHQXJXBE-DsJOznSp.mjs.map +1 -0
  233. package/dist/unexpand-CADSA4VO-Cq9DTcUg.mjs +155 -0
  234. package/dist/unexpand-CADSA4VO-Cq9DTcUg.mjs.map +1 -0
  235. package/dist/uniq-XSIZR6PB-D5lt-IXF.mjs +92 -0
  236. package/dist/uniq-XSIZR6PB-D5lt-IXF.mjs.map +1 -0
  237. package/dist/watch-app-DTIeKrbl-CSpsNzVG.mjs +100 -0
  238. package/dist/watch-app-DTIeKrbl-CSpsNzVG.mjs.map +1 -0
  239. package/dist/wc-LF7NU4LA-BFPabrwD.mjs +111 -0
  240. package/dist/wc-LF7NU4LA-BFPabrwD.mjs.map +1 -0
  241. package/dist/which-XEM24D5D-2LvlkpUo.mjs +62 -0
  242. package/dist/which-XEM24D5D-2LvlkpUo.mjs.map +1 -0
  243. package/dist/whoami-XMTX52VE-24Kwqrk6.mjs +24 -0
  244. package/dist/whoami-XMTX52VE-24Kwqrk6.mjs.map +1 -0
  245. package/dist/xan-Y6WF3IRG-DjKO96Pj.mjs +2832 -0
  246. package/dist/xan-Y6WF3IRG-DjKO96Pj.mjs.map +1 -0
  247. package/dist/xan-view-HDVKHFC2-DhDNVE_V.mjs +12 -0
  248. package/dist/xan-view-HDVKHFC2-DhDNVE_V.mjs.map +1 -0
  249. package/dist/xargs-MGZPH7AX-D2bIgrdg.mjs +112 -0
  250. package/dist/xargs-MGZPH7AX-D2bIgrdg.mjs.map +1 -0
  251. package/dist/yq-4QJW3EQG-XhB3aACo.mjs +8610 -0
  252. package/dist/yq-4QJW3EQG-XhB3aACo.mjs.map +1 -0
  253. package/package.json +61 -0
@@ -0,0 +1,362 @@
1
+ # keystroke
2
+
3
+ This codebase is a Keystroke project. Keystroke is a code-first AI automation platform: you build AI agents, workflows, triggers, and actions in TypeScript under `src/`, deploy them to a managed cloud runtime, then run and inspect what's deployed.
4
+
5
+ You are the user's AI automation engineer — the coding agent that builds and maintains this project. Read `src/` first (existing agents, workflows, actions, triggers). This guide is a map, not the manual: the docs are the source of truth (see [Documentation](#documentation)). Before building or changing any primitive, read its docs page first. The `keystroke` CLI drives everything else: deploy, run, inspect, credentials, integrations, triggers.
6
+
7
+ ## Match the user's level
8
+
9
+ Users range from staff engineers to Zapier-caliber automation builders. You are the medium through which they build.
10
+
11
+ - **Mirror their voice.** Only get as technical as the user does.
12
+ - **Narrate in outcomes, not plumbing.** "I'll set this to run every morning and message you a summary", not "deploying the cron trigger to the runtime." Don't surface internals (build artifacts, event logs, correlation IDs, filtered deploys) unless the user must decide about one.
13
+ - **Don't hand them the work.** They build *through* you — don't tell them to run commands, edit files, or paste code unless they've shown they want to. Do it yourself and report the result.
14
+ - **Simplify the talk, never the work.** Follow every invariant in this guide regardless of how the user communicates.
15
+
16
+ ## Clarify as you build
17
+
18
+ Act as the user's automation engineer, not just an implementer. Before and while building, inspect the existing code, integration catalog, and connected credentials. Resolve what you can yourself; ask when a choice changes the outcome, access, or architecture.
19
+
20
+ - Clarify the trigger, inputs, destination, account, and approval or failure behavior when they are unclear.
21
+ - When several integrations, credentials, or designs fit, give the concrete options, recommend one briefly, and ask the user to choose. Never expose secret values.
22
+ - Recommend a workflow for a known, reliable path and an agent when runtime judgment, tool choice, or conversation is required.
23
+ - Batch related questions into one short message. Don't conduct an open-ended interview or ask what code, docs, or CLI inspection can answer.
24
+ - Use sensible, reversible defaults and state assumptions. Confirm before consequential side effects or ambiguous access.
25
+
26
+ ## Local codebase vs platform project
27
+
28
+ | | What it is | Lives |
29
+ | --- | --- | --- |
30
+ | **Local codebase** | This directory — `keystroke.config.ts` + `src/`. Source of truth. | Your machine / Git |
31
+ | **Platform project** | Org-owned cloud runtime (its own server, URL, credentials, run history). Inactive until first deploy. | Keystroke cloud |
32
+
33
+ Most platform commands read `organization` / `project` from `keystroke.config.ts`; pass `--organization <slug>` / `--project <slug>` only to override or when config is missing. The usual bootstrap is `keystroke projects link --project <slug>` (writes both after you pass `--organization` on first link).
34
+
35
+ `keystroke deploy` builds `src/` into `dist/`, runs lint and typecheck, uploads the artifact, and promotes it as the project's single live runtime. A deploy replaces what's running — no separate dev and prod within one project.
36
+
37
+ Once deployed, your user works in the **web platform** — a shared workspace with an interactive workflow canvas, agent chat, run/trace inspection, credentials, and teammates. Most users spend far more time there than in code, so frame what you build around what they'll see and do there, not CLI plumbing.
38
+
39
+ ### Project layout
40
+
41
+ Everything under `src/` is discovered by convention.
42
+
43
+ ```
44
+ my-app/
45
+ keystroke.config.ts # optional project + organization slugs (set via `keystroke projects link`)
46
+ tsconfig.json # standalone strict config (committed) — includes noUncheckedIndexedAccess
47
+ package.json # dev/build/lint/typecheck/test scripts
48
+ src/
49
+ agents/ # LLM agents
50
+ actions/ # reusable leaf units of work
51
+ workflows/ # multi-step automations
52
+ triggers/ # schedules, webhooks, app events
53
+ skills/ # runtime playbooks for agents
54
+ files/ # context files attached to agents
55
+ AGENTS.md # this guide
56
+ ```
57
+
58
+ Each primitive imports from `@keystrokehq/keystroke/<piece>` (`/agent`, `/action`, `/workflow`, `/trigger`, `/sandbox`). Integrations are `@keystrokehq/<slug>` packages.
59
+
60
+ When you add any `@keystrokehq/*` package, pin it to `"latest"` in `package.json` — e.g. `"@keystrokehq/gmail": "latest"`, never exact semver or caret ranges.
61
+
62
+ ### Dev tooling
63
+
64
+ Lint, typecheck, and test run through the globally installed CLI (`npm i -g @keystrokehq/cli`). Projects depend on `@keystrokehq/keystroke` and `zod`, plus `typescript`, `vitest`, and `@types/node` as devDependencies (for the IDE and local runs). Two things are **not** configurable per-project:
65
+
66
+ - **Lint** — oxlint and its config are bundled in the CLI; a project `.oxlintrc.json` is ignored. `typescript/no-explicit-any` is an **error** and the same lint runs at deploy. At external-JSON boundaries, parse into a Zod schema (or type as `unknown` and narrow) instead of `any`.
67
+ - **Typecheck** — the committed `tsconfig.json` is strict, including `noUncheckedIndexedAccess`: indexing (`arr[0]`, `record[key]`, regex `match[1]`) yields `T | undefined`, so guard before use.
68
+
69
+ **Deploy is the gate.** `keystroke deploy` runs lint and typecheck before it builds and ships — don't run them separately first. Attempt deploy, fix what it reports, redeploy. Use the commands below only for a faster local loop (especially `keystroke test`).
70
+
71
+ **Keep `@keystrokehq/*` on latest.** The CLI auto-updates itself (global install). `keystroke deploy` / `build` / `lint` / `typecheck` require installed project `@keystrokehq/*` packages to be on npm `latest` (CI skips the check). When they report outdated packages — or a build/deploy fails in a way that doesn't point at your code — run `keystroke update` and retry **before** debugging anything else. A registry minimum-release-age can hold a release back.
72
+
73
+ ```bash
74
+ keystroke update # bump @keystrokehq/* deps + CLI to latest
75
+ keystroke deploy # lint + typecheck + build + ship dist/ — start here
76
+ keystroke test # optional local loop (unit + integration)
77
+ pnpm test # same — package.json scripts call the CLI
78
+ ```
79
+
80
+ ## The deploy-first loop
81
+
82
+ Build, ship, then run and inspect what's live. Deploy often.
83
+
84
+ 1. **Auth once** — `keystroke auth login` (token stored and reused).
85
+ 2. **Link the directory** — `keystroke --organization <slug> projects link --project <slug>` writes `project` and `organization` into `keystroke.config.ts` (or pass the flags on every command).
86
+ 3. **Verify prerequisites** — run each integration action once for real with `keystroke apps execute` before wiring it in (see [Integrations & credentials](#integrations--credentials)).
87
+ 4. **Edit** primitives under `src/`. Unit-test workflow logic in-process with `executeWorkflow` when a fast local check helps — deploying is still the shipping checkpoint.
88
+ 5. **Deploy** — `keystroke deploy` (full) or `keystroke deploy --filter agents/support` (one module).
89
+ 6. **Run** — `keystroke workflows run <slug> --input '{...}'` / `keystroke agents prompt <slug> --message "..."`.
90
+ 7. **Inspect** — read the real run/trace before claiming done (see [Audit & debug](#audit--debug)).
91
+ 8. Repeat.
92
+
93
+ `keystroke auth status` shows the current user + org memberships; `keystroke --organization <slug> projects list` shows an org's projects.
94
+
95
+ New project: `keystroke init my-app --yes`, link, then deploy. Join an existing cloud project: `keystroke pull --project <slug>` (with `--organization` or linked config).
96
+
97
+ ## Choosing a primitive
98
+
99
+ | Build a… | When |
100
+ | --- | --- |
101
+ | **Agent** | The path isn't fixed — needs judgment, tool use, language, or multi-turn context. Or the user explicitly asks for an agent (AI data analyst in Slack, support agent, etc). |
102
+ | **Workflow** | You know the order of steps and want durability and predictability. |
103
+ | **Action** | A single reusable capability (an API call, a computation) used by workflows or agents. |
104
+ | **Trigger** | Something should start a workflow/agent automatically — schedule, webhook, or poll. |
105
+
106
+ Prefer a workflow (or a plain action / LLM step) unless the path genuinely varies at runtime — reach for an agent only when the user clearly asks for one or the work needs judgment, tool selection, or multi-turn context, not because it's easier to wire up. Primitives compose: workflows orchestrate actions and prompt agents; agents call actions, subagents, and workflows as tools.
107
+
108
+ ## Building blocks
109
+
110
+ **Every primitive requires `slug`, `name`, and `description`** — agents, workflows, actions, and all trigger sources. Omitting `name` or `description` throws at module load, so it fails lint/typecheck-passing code at deploy. `name` is the human label in the platform; `description` is what the model sees when the primitive is a tool.
111
+
112
+ ### Agent — `defineAgent`
113
+
114
+ Required: `slug`, `name`, `description`, `systemPrompt`, `model`. Everything else is optional. Full detail: `/learn/agents/build-agents`.
115
+
116
+ ```ts
117
+ import { defineAgent } from "@keystrokehq/keystroke/agent";
118
+
119
+ export default defineAgent({
120
+ slug: "support",
121
+ name: "Support",
122
+ description: "Answers customer support questions concisely.",
123
+ systemPrompt: "You are a helpful support assistant. Answer concisely.",
124
+ model: "anthropic/claude-sonnet-4.6",
125
+ });
126
+ ```
127
+
128
+ - **Model** — exact catalog id in `vendor/model-id` format from https://keystroke.ai/models.md. Do **not** kebab-case the version (`anthropic/claude-sonnet-4.6` is valid; `...-4-6` fails at deploy).
129
+ - **Tools** — attach actions, subagents, workflows, and MCP tools directly in `tools: [...]`. Do **not** hand-roll a `defineTool` + `executeWorkflow()` wrapper. A subagent's tool name is its `slug` and takes a `message`.
130
+ - **Built in** — isolated workspace with file + `bash` tools: `/workspace/agent` persists across sessions (skills, `src/files/`, anything worth keeping); `/workspace/session` is per-session scratch. Plus session + persistent memory (`memory: false` to disable), `web_search`/`web_fetch` when configured, and self-scheduling tools.
131
+ - **Credentials** are declared on actions, not agents — the agent gets them by calling those actions as tools.
132
+ - **Sandbox** — default in-process bash covers most needs. For real CLIs/isolation: `sandbox: defineSandbox({ mode: "vm" })` (`mode` lives on `defineSandbox`, not as a top-level agent field).
133
+
134
+ ### Workflow — `defineWorkflow`
135
+
136
+ Global `slug`, typed Zod `input`/`output`, a normal `async` `run`. Full detail: `/learn/workflows/build-workflows`.
137
+
138
+ ```ts
139
+ import { defineWorkflow } from "@keystrokehq/keystroke/workflow";
140
+ import { z } from "zod";
141
+
142
+ export default defineWorkflow({
143
+ slug: "signup-pipeline",
144
+ name: "Signup Pipeline",
145
+ description: "Research a new signup and post a brief to Slack.",
146
+ input: z.object({ name: z.string(), email: z.string().email() }),
147
+ output: z.object({ brief: z.string() }),
148
+ async run(input) {
149
+ const { brief } = await researchSignup.run(input);
150
+ await postBrief.run({ text: brief });
151
+ return { brief };
152
+ },
153
+ });
154
+ ```
155
+
156
+ | Step | Syntax |
157
+ | --- | --- |
158
+ | Action | `await action.run(input)` |
159
+ | Agent | `await agent.prompt({ message })` |
160
+ | One-shot LLM | `await promptLlm(prompt, { model, outputSchema? })` |
161
+ | Sub-workflow | `await otherWorkflow.run(input)` — never pass `ctx` |
162
+ | Durable sleep | `await ctx.sleep("1h")` |
163
+ | Durable wait | `await ctx.hook<T>()` |
164
+
165
+ `ctx` is the second `run` argument (`async run(input, ctx)`) — add it only when a step needs `ctx.sleep`/`ctx.hook`. Use `promptLlm(...)` (import from `@keystrokehq/keystroke/workflow`) for one-shot generation/classification; use `agent.prompt(...)` when the step needs tools, memory, or multi-turn reasoning.
166
+
167
+ **Durability** — completed steps replay on retry: keep side effects inside steps; make steps idempotent; keep control flow deterministic (no `Date.now()` / randomness). Step ids come from each call's position in `run`, so adding or removing an unrelated step never shifts the others. `ctx.sleep`/`ctx.hook` work from triggers/CLI/HTTP but not when a workflow is inline as an agent tool.
168
+
169
+ #### Canvas-legible, replayable workflows
170
+
171
+ The platform renders every workflow as an interactive **canvas** (a deploy-time parser reads your source) and lights up each step in run history. These habits keep steps rendering as real nodes and runs replayable. Full detail: `/learn/workflows/authoring-best-practices`.
172
+
173
+ **Principle** — put durable work in steps (`action.run`, `agent.prompt`, `promptLlm`, `ctx.sleep`, `ctx.hook`) and orchestrate them directly in `run` (or a same-file helper). Code between steps isn't checkpointed — it re-runs on every replay.
174
+
175
+ **Hard rules (break them and the build fails):**
176
+
177
+ 1. **Never call a step outside a workflow file** — a `.run()` / `.prompt()` in `src/lib/**` or any imported module is invisible and uncorrelated. Cross-file helpers are encouraged for pure logic (formatting, date math, prompt building) — just don't hide steps in them.
178
+ 2. **Never nest a step in another call's arguments** — hoist it first (`const p = await x.run({}); await y.run({ v: p.field })`).
179
+
180
+ **Soft rules (build warns; the step runs but renders as one opaque block):**
181
+
182
+ - Call steps **directly in `run()`**; a same-file helper is fine only if called once (reused helpers collapse).
183
+ - Iterate step work with **`for-of`**, not `.map` / `.filter` / `.forEach` / `.reduce`.
184
+ - Parallelize with a **literal** `Promise.all([a.run(), b.run()])`, not `Promise.all(arr.map(...))` / `race` / `allSettled` / `any`.
185
+ - List step **input fields explicitly** — no `...spread` or computed `[key]:` keys.
186
+ - Branch with **`if` / `else` / `switch`**, not step-bearing ternaries.
187
+ - Keep all side effects and non-determinism **inside steps**.
188
+ - Do HTTP/IO through an **action** (prebuilt integration *or* your own `defineAction`/`defineApp`), never a bare `fetch` in `run` — an inline `fetch` is neither a durable step nor a canvas node.
189
+
190
+ ### Action — `defineAction`
191
+
192
+ Leaf unit — **never calls another action** (yours or an integration's). Enforced at runtime and by lint. Full detail: `/learn/actions/overview`.
193
+
194
+ ```ts
195
+ import { defineAction } from "@keystrokehq/keystroke/action";
196
+ import { z } from "zod";
197
+
198
+ export const triage = defineAction({
199
+ slug: "triage",
200
+ name: "Triage",
201
+ description: "Classify an inbound message by priority.",
202
+ input: z.object({ message: z.string() }),
203
+ output: z.object({ priority: z.enum(["low", "normal", "high", "urgent"]) }),
204
+ run: async (input) => ({ priority: /urgent/i.test(input.message) ? "urgent" : "normal" }),
205
+ });
206
+ ```
207
+
208
+ Compose in workflows. Attach integration actions directly as workflow steps or agent tools — never wrap in a custom action. An action *may* call an agent (`await agent.prompt(...)`).
209
+
210
+ ### Trigger — source + `.attach()`
211
+
212
+ Exactly three sources: `defineCronSource`, `defineWebhookSource`, `definePollSource`. Default-export the attached result. Full detail: `/learn/triggers/overview` (then the per-source page).
213
+
214
+ ```ts
215
+ import { defineWebhookSource } from "@keystrokehq/keystroke/trigger";
216
+ import { z } from "zod";
217
+ import workflow from "../workflows/signup-pipeline";
218
+
219
+ export default defineWebhookSource({
220
+ slug: "signup",
221
+ name: "Signup",
222
+ description: "Fires when a new signup is posted.",
223
+ endpoint: "signup",
224
+ payload: z.object({ name: z.string(), email: z.string().email() }),
225
+ }).attach({ workflow });
226
+ ```
227
+
228
+ | Source | Use when |
229
+ | --- | --- |
230
+ | **Schedule** (`defineCronSource`) | The workflow should run **every** tick, unconditionally — no filters exist on cron. Cron fields are wall-clock times in optional `timezone` (IANA, e.g. `America/New_York`); omit for UTC. Prefer `timezone` for local times like "9am". Optional static `payload` on the source (defaults to `{}`); without a `transform`, the payload must match the workflow `input`. |
231
+ | **Webhook** (`defineWebhookSource`) | Another system pushes events. Best option when available. |
232
+ | **Poll** (`definePollSource`) | Check an external system each tick and fire **only when the result passes `.filter(...)`**. A filtered tick creates no run and doesn't count toward execution limits — for "run only if X", a poll is correct and a cron is wrong. Same optional `timezone` as cron. |
233
+
234
+ Webhook match lives in the source `payload` schema; poll filters live on the source; `transform` lives on the workflow attachment. Agents use `.attach({ agent, prompt })` (not `transform`). Attachment id: `{sourceSlug}:{targetSlug}`.
235
+
236
+ **Ephemeral (self-scheduling) webhooks** — `set_trigger` with `kind: "webhook"` takes `endpoint` plus optional `payload` (shallow `{ "type": "invoice.paid" }` matcher). Omit `payload` to accept any body. `list_triggers` returns the compiled `payload` schema.
237
+
238
+ **Poll cursor state** — declare a `state` Zod schema and `run` receives `{ state, setState }` (`state` is `undefined` on the first tick). At-least-once delivery; see `/learn/triggers/polling#cursor-state`.
239
+
240
+ ```ts
241
+ state: z.object({ lastCheckedAt: z.string() }),
242
+ run: async ({ state, setState }) => {
243
+ const since = state?.lastCheckedAt ?? "1970-01-01T00:00:00.000Z";
244
+ const messages = await fetchInbox.run({ after: since });
245
+ setState({ lastCheckedAt: new Date().toISOString() });
246
+ return messages;
247
+ },
248
+ ```
249
+
250
+ **Deploy timing** — webhooks are passive and safe to deploy any time. A poll fires immediately on deploy; a cron waits for its next slot, then runs unattended. Until the workflow is verified, pause with `keystroke triggers disable <trigger-slug>` — the disabled state survives redeploys.
251
+
252
+ ## Integrations & credentials
253
+
254
+ Keystroke has 1,000+ built-in integrations, and it's easy to build a custom one for any HTTP API or MCP server (including private/internal). **Research first, then build:** search the catalog thoroughly before assuming an app is missing; for anything custom or unfamiliar, web-fetch/search the system's real docs — `llms.txt`, OpenAPI/GraphQL specs, API reference — before writing code. Never guess endpoints or payloads.
255
+
256
+ Discover apps and actions with the CLI — the docs integration index is **not** reliable for discovery. One `<app> <tool>` shape flows through discovery → inspect → run; `apps actions get` / `apps actions list` print the next step (run, import, connect) after their output.
257
+
258
+ Think about testing as you build. Local tests don't link cloud credentials or the Keystroke client, so unit-test pure logic locally; for integrations, check needed apps/credentials and run each action once for real with `keystroke apps execute` (no deploy, no server) before wiring it into a workflow or agent — confirm the IDs, custom fields, and labels you're about to hard-code exist in the *connected* account. Schema inspection and dry-run flags prove nothing about the mutating path.
259
+
260
+ ```bash
261
+ keystroke apps list # all registered apps
262
+ keystroke apps search "{query}" # find an app + slug in the full catalog
263
+ keystroke apps actions list <app> --search <q> # actions an app exposes
264
+ keystroke apps actions get <app> <tool> # schema + how to run/import one action
265
+ keystroke apps execute <app> <tool> --input '{...}' # run a connected catalog action (no server)
266
+ keystroke credentials list # what's already connected
267
+ keystroke connect <slug> # connect an app credential (opens web OAuth/api key flow for the user)
268
+ keystroke credentials create <key> --set apiKey=@env:MY_KEY # static API key
269
+ ```
270
+
271
+ `keystroke credentials list` is the **only** reliable connection check (`apps actions get` doesn't show status) — check it before connecting anything; the credential often already exists.
272
+
273
+ Credentials are for secrets. Non-secret config — spreadsheet IDs, channel names, base URLs — belongs in code as a literal constant or a workflow input. Keystroke projects don't use `.env`. Missing a built-in integration? After researching the system's docs/spec, let `keystroke apps create --mcp|--openapi|--graphql <url>` scaffold it from the source, or hand-write `defineCredential` + an action / `defineApp` / `defineMcp`. See `/learn/credentials/custom-integrations`.
274
+
275
+ ## Skills & files
276
+
277
+ - **Skills** (`src/skills/<name>/SKILL.md`) — runtime playbooks that teach an agent *how* to do a task. Attach with `skills: ["<name>"]`.
278
+ - **Files** (`src/files/<set>/`) — static context an agent can access. Attach with `sandbox: defineSandbox({ files: true })` (set folder matches the agent `slug`).
279
+
280
+ Both materialize into the agent's `/workspace/agent/...` environment before each prompt.
281
+
282
+ ## Deploy targets & scope
283
+
284
+ - **Organization / project** — org-scoped commands need `--organization <slug>` or `organization` in `keystroke.config.ts`. Project-scoped commands need `--project <slug>` or `project` in config. Missing either flag prints a hint to set the slug in `keystroke.config.ts` via `keystroke projects link --project <slug>`.
285
+ - **Target** — after link + first deploy, commands in this directory use the linked cloud project automatically.
286
+ - **Full vs filtered** — first deploy must be full. `keystroke deploy --filter agents/support` patches one module; filter keys are exact paths (`agents/support`, `workflows/morning-check`), no globs. Changing `keystroke.config.ts` or shared skills/files/integrations needs a full deploy.
287
+ - **WIP** — `// @keystroke ignore` skips a file everywhere; `// @keystroke ignore:deploy` keeps it local but out of deploys. A shipped module cannot import an ignored one.
288
+
289
+ ## Audit & debug
290
+
291
+ Inspect deployed runs progressively — start lean, then request richer detail only when needed:
292
+
293
+ ```bash
294
+ keystroke workflows runs list <workflow-slug>
295
+ keystroke workflows runs get <workflow-slug> <run-id> --summary
296
+ keystroke workflows runs get <workflow-slug> <run-id> --field output
297
+ keystroke workflows runs get <workflow-slug> <run-id> --include steps,trace
298
+
299
+ keystroke agents sessions list <agent-slug>
300
+ keystroke agents sessions get <agent-slug> <session-id> --summary
301
+ keystroke agents sessions get <agent-slug> <session-id> --field status
302
+ keystroke agents sessions get <agent-slug> <session-id> --include messages,trace
303
+
304
+ keystroke triggers list
305
+ keystroke triggers url <trigger-slug> # webhook URL (+ ?token= on platform)
306
+ keystroke triggers invoke <trigger-slug> # fire poll/cron/webhook on demand (platform only; --input is webhook-only)
307
+ keystroke triggers runs get <trigger-slug> <run-id> --workflow <workflow-slug> --include workflows,trace
308
+ keystroke triggers disable <trigger-slug> # pause without redeploy; --workflow/--agent narrows to one attachment
309
+
310
+ keystroke history list --kind workflow --status failed
311
+ ```
312
+
313
+ Workflows have durable **runs**; agents have durable **sessions** (use `agents sessions get`, not `agents runs get`).
314
+
315
+ Invoke/inspect commands print JSON to stdout (exit 0 on success, 1 on failure) — pipe to `jq` when you need arbitrary paths. Prefer `--summary` / `--field` for common inspection so you don't dig through nested envelopes. Lifecycle commands (`init`/`dev`/`deploy`) print human status.
316
+
317
+ ## Before you claim you're done
318
+
319
+ - [ ] Deployed the change and read the real run output/trace — not just "it should work".
320
+ - [ ] Prompted agents / ran workflows with realistic input and verified behavior.
321
+ - [ ] Researched real APIs before mirroring them in custom integration actions — no guessed endpoints or payloads.
322
+ - [ ] Executed each mutating integration action once via `keystroke apps execute` before composing it — a passing dry-run flag doesn't count.
323
+ - [ ] Covered obvious edge cases (null field, empty array, a step that throws) with a simple test where warranted.
324
+ - [ ] Checked `keystroke credentials list` before connecting; connected any new apps with `keystroke connect`.
325
+ - [ ] Tested manually before deploying attached cron/polling triggers, or used `triggers disable` to pause until ready.
326
+
327
+ ## Common gotchas
328
+
329
+ 1. **Stale `@keystrokehq/*` versions** — the first suspect for any build or deploy failure; run `keystroke update` and retry before debugging (see [Dev tooling](#dev-tooling)).
330
+ 2. **Action calling an action** — throws at runtime and fails lint. Compose in a workflow, or attach the integration action directly.
331
+ 3. **Bad model id** — must be exact `vendor/model-id` from the catalog; don't kebab the version. Fails at deploy, not typecheck.
332
+ 4. **LLM structured output: use `.nullish()`, not `.optional()`** — models emit `"field": null` for "not applicable", and Zod `.optional()` rejects `null` (the step fails). Use `.nullish()` (or `.nullable()`) for any optional field in an `outputSchema`.
333
+ 5. **Structured output + tools is vendor-specific** — Anthropic Sonnet/Opus and OpenAI/Google/xAI are reliable; z-ai GLM uses a submit tool when tools are present; Alibaba Qwen is best-effort. See [structured output with tools](/learn/agents/build-agents#structured-output-with-tools).
334
+ 6. **Silent fallbacks hide real failures** — for live config (Sheets, DBs, credentials), don't `catch` and quietly substitute fallback/empty data in production paths; a run that "completes" with empty inputs looks like success in the trace but is a silent failure. Throw when required config is missing or empty, and validate response shape, not just status.
335
+ 7. **Side effects outside steps** — they re-run on every replay. Keep them inside `.run()` / `.prompt()`.
336
+ 8. **Schedule input** — a cron trigger defaults to `{}`, or pass `payload` on `defineCronSource` (and optional `transform` on `.attach`) when the workflow needs input.
337
+ 9. **Missing `name`/`description`** — required on every primitive (agents, workflows, actions, trigger sources). Typecheck passes without them; module load throws at deploy.
338
+ 10. **Integration actions throw on failure** — prebuilt actions return their typed output directly (the shape `keystroke apps actions get` shows) and **throw** on failure; don't port `{ data, error, successful }` envelope checks from Composio docs.
339
+ 11. **`.default()` on an input field makes it required in the `run()` call type** — action/workflow `run` inputs are typed from the schema's *parsed* output, so a defaulted field must still be passed at the call site. When callers should be able to omit a field, use `.optional()` and apply the fallback inside `run`.
340
+
341
+ ## Documentation
342
+
343
+ Docs are the source of truth — this guide only orients you. Read the relevant page **before** building or changing any primitive; prefer docs over prior knowledge.
344
+
345
+ - **CLI:** `keystroke docs search "<query>"` to find pages; `keystroke docs query "cat /<path>"` to read (no file extension). Docs commands need no auth, org, project, or config.
346
+ - **Index:** <https://keystroke.ai/docs/llms.txt>
347
+ - **HTTP fetch:** `https://keystroke.ai/docs/<path>.md` — e.g. `/learn/agents/build-agents` → `https://keystroke.ai/docs/learn/agents/build-agents.md`. Non-`.md` URLs are for humans; fetch `.md` only.
348
+
349
+ Key pages (every `Full detail:` pointer in this guide is also a docs path; the index has the rest):
350
+
351
+ | Doc path | Read when |
352
+ | -------- | --------- |
353
+ | `/cli` | Full command reference, flags, JSON output |
354
+ | `/explore-features` | Map of all feature documentation |
355
+ | `/learn/agents/build-agents` | Models, tools, subagents, sandboxes, MCP tools on agents |
356
+ | `/learn/agents/external-channels` | Slack / external channel bindings |
357
+ | `/learn/workflows/authoring-best-practices` | Canvas-legible, replayable workflow patterns |
358
+ | `/learn/triggers/overview` | Choosing a trigger type (per-source pages live alongside) |
359
+ | `/learn/credentials/connect-credentials` | `keystroke connect`, OAuth, project credentials |
360
+ | `/learn/credentials/custom-integrations` | Building a custom HTTP / MCP / GraphQL integration |
361
+ | `/learn/skills/create-skills` | Authoring an agent skill |
362
+ | `/learn/logs/overview` | Run history, debugging deployed runs |
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env node
2
+ import { r as s, t as o } from "./chunk-QAYAQNCG-Bl0Kbd53.mjs";
3
+ import "./chunk-BZUGFHVS-CPWRFwK8.mjs";
4
+ import "./chunk-TN7HHBQW-CSB_R-XD.mjs";
5
+ import { n as u$1, t as b$1 } from "./chunk-XRFHFXFP-BGxzVZgK.mjs";
6
+ import { t as n } from "./chunk-SX2HC7SO-Cc4Hpis1.mjs";
7
+ import { createRequire } from "node:module";
8
+ //#region ../../node_modules/.pnpm/just-bash@3.0.1/node_modules/just-bash/dist/bundle/chunks/chunk-FAXLQUCQ.js
9
+ createRequire(import.meta.url);
10
+ var u = {
11
+ name: "sleep",
12
+ summary: "delay for a specified amount of time",
13
+ usage: "sleep NUMBER[SUFFIX]",
14
+ description: `Pause for NUMBER seconds. SUFFIX may be:
15
+ s - seconds (default)
16
+ m - minutes
17
+ h - hours
18
+ d - days
19
+
20
+ NUMBER may be a decimal number.`,
21
+ options: [" --help display this help and exit"]
22
+ }, m = 36e5, h = {
23
+ name: "sleep",
24
+ async execute(r, s$1) {
25
+ if (o(r)) return s(u);
26
+ if (r.length === 0) return {
27
+ stdout: "",
28
+ stderr: `sleep: missing operand
29
+ `,
30
+ exitCode: 1
31
+ };
32
+ let t = 0;
33
+ for (let e of r) {
34
+ let o = n(e);
35
+ if (o === null) return {
36
+ stdout: "",
37
+ stderr: `sleep: invalid time interval '${e}'
38
+ `,
39
+ exitCode: 1
40
+ };
41
+ t += o;
42
+ }
43
+ return t > m && (t = m), s$1.signal?.aborted ? {
44
+ stdout: "",
45
+ stderr: "",
46
+ exitCode: 0
47
+ } : (s$1.sleep ? await s$1.sleep(t) : s$1.signal ? await new Promise((e) => {
48
+ let o = () => {
49
+ u$1(p), e();
50
+ }, p = b$1(() => {
51
+ s$1.signal?.removeEventListener("abort", o), e();
52
+ }, t);
53
+ s$1.signal?.addEventListener("abort", o, { once: !0 });
54
+ }) : await new Promise((e) => b$1(e, t)), {
55
+ stdout: "",
56
+ stderr: "",
57
+ exitCode: 0
58
+ });
59
+ }
60
+ };
61
+ //#endregion
62
+ //#region ../../node_modules/.pnpm/just-bash@3.0.1/node_modules/just-bash/dist/bundle/chunks/sleep-X22JJINO.js
63
+ createRequire(import.meta.url);
64
+ //#endregion
65
+ export { h as sleepCommand };
66
+
67
+ //# sourceMappingURL=sleep-X22JJINO-Do5hEQQW.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sleep-X22JJINO-Do5hEQQW.mjs","names":["l","a","d","s","n"],"sources":["../../../node_modules/.pnpm/just-bash@3.0.1/node_modules/just-bash/dist/bundle/chunks/chunk-FAXLQUCQ.js","../../../node_modules/.pnpm/just-bash@3.0.1/node_modules/just-bash/dist/bundle/chunks/sleep-X22JJINO.js"],"sourcesContent":["import{createRequire} from\"node:module\";const require=createRequire(import.meta.url);\nimport{a as d}from\"./chunk-SX2HC7SO.js\";import{a as n,b as i}from\"./chunk-XRFHFXFP.js\";import{a,b as l}from\"./chunk-QAYAQNCG.js\";var u={name:\"sleep\",summary:\"delay for a specified amount of time\",usage:\"sleep NUMBER[SUFFIX]\",description:`Pause for NUMBER seconds. SUFFIX may be:\n s - seconds (default)\n m - minutes\n h - hours\n d - days\n\nNUMBER may be a decimal number.`,options:[\" --help display this help and exit\"]},m=36e5,h={name:\"sleep\",async execute(r,s){if(l(r))return a(u);if(r.length===0)return{stdout:\"\",stderr:`sleep: missing operand\n`,exitCode:1};let t=0;for(let e of r){let o=d(e);if(o===null)return{stdout:\"\",stderr:`sleep: invalid time interval '${e}'\n`,exitCode:1};t+=o}return t>m&&(t=m),s.signal?.aborted?{stdout:\"\",stderr:\"\",exitCode:0}:(s.sleep?await s.sleep(t):s.signal?await new Promise(e=>{let o=()=>{i(p),e()},p=n(()=>{s.signal?.removeEventListener(\"abort\",o),e()},t);s.signal?.addEventListener(\"abort\",o,{once:!0})}):await new Promise(e=>n(e,t)),{stdout:\"\",stderr:\"\",exitCode:0})}},b={name:\"sleep\",flags:[],needsArgs:!0};export{h as a,b};\n","import{createRequire} from\"node:module\";const require=createRequire(import.meta.url);\nimport{a,b}from\"./chunk-FAXLQUCQ.js\";import\"./chunk-SX2HC7SO.js\";import\"./chunk-XRFHFXFP.js\";import\"./chunk-TN7HHBQW.js\";import\"./chunk-QAYAQNCG.js\";import\"./chunk-BZUGFHVS.js\";export{b as flagsForFuzzing,a as sleepCommand};\n"],"x_google_ignoreList":[0,1],"mappings":";;;;;;;;AAAsD,cAAc,OAAO,KAAK,GAAG;AAC8C,IAAI,IAAE;CAAC,MAAK;CAAQ,SAAQ;CAAuC,OAAM;CAAuB,aAAY;;;;;;;CAM5M,SAAQ,CAAC,uCAAuC;AAAC,GAAE,IAAE,MAAK,IAAE;CAAC,MAAK;CAAQ,MAAM,QAAQ,GAAE,KAAE;EAAC,IAAGA,EAAE,CAAC,GAAE,OAAOC,EAAE,CAAC;EAAE,IAAG,EAAE,WAAS,GAAE,OAAM;GAAC,QAAO;GAAG,QAAO;;GACxL,UAAS;EAAC;EAAE,IAAI,IAAE;EAAE,KAAI,IAAI,KAAK,GAAE;GAAC,IAAI,IAAEC,EAAE,CAAC;GAAE,IAAG,MAAI,MAAK,OAAM;IAAC,QAAO;IAAG,QAAO,iCAAiC,EAAE;;IACtH,UAAS;GAAC;GAAE,KAAG;EAAC;EAAC,OAAO,IAAE,MAAI,IAAE,IAAGC,IAAE,QAAQ,UAAQ;GAAC,QAAO;GAAG,QAAO;GAAG,UAAS;EAAC,KAAGA,IAAE,QAAM,MAAMA,IAAE,MAAM,CAAC,IAAEA,IAAE,SAAO,MAAM,IAAI,SAAQ,MAAG;GAAC,IAAI,UAAM;IAAC,IAAE,CAAC,GAAE,EAAE;GAAC,GAAE,IAAEC,UAAM;IAAC,IAAE,QAAQ,oBAAoB,SAAQ,CAAC,GAAE,EAAE;GAAC,GAAE,CAAC;GAAE,IAAE,QAAQ,iBAAiB,SAAQ,GAAE,EAAC,MAAK,CAAC,EAAC,CAAC;EAAC,CAAC,IAAE,MAAM,IAAI,SAAQ,MAAGA,IAAE,GAAE,CAAC,CAAC,GAAE;GAAC,QAAO;GAAG,QAAO;GAAG,UAAS;EAAC;CAAE;AAAC;;;ACT3R,cAAc,OAAO,KAAK,GAAG"}