tarsk 0.6.87 → 0.6.89

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 (255) hide show
  1. package/README.md +63 -24
  2. package/dist/bundled-skills/email-me/SKILL.md +15 -0
  3. package/dist/bundled-skills/email-me/scripts/__tests__/email_me.test.js +64 -0
  4. package/dist/bundled-skills/email-me/scripts/email_me.js +45 -0
  5. package/dist/bundled-skills/handoff/SKILL.md +19 -0
  6. package/dist/bundled-skills/tarsk-agent/SKILL.md +372 -0
  7. package/dist/bundled-skills/tarsk-ask-user/SKILL.md +18 -0
  8. package/dist/bundled-skills/tarsk-ask-user/scripts/ask_user.js +101 -0
  9. package/dist/bundled-skills/tarsk-bash/SKILL.md +17 -0
  10. package/dist/bundled-skills/tarsk-bash/scripts/bash.js +248 -0
  11. package/dist/bundled-skills/tarsk-browser/SKILL.md +17 -0
  12. package/dist/bundled-skills/tarsk-browser/scripts/browser.js +252 -0
  13. package/dist/bundled-skills/tarsk-chat-title/SKILL.md +14 -0
  14. package/dist/bundled-skills/tarsk-chat-title/scripts/chat_title.js +37 -0
  15. package/dist/bundled-skills/tarsk-connect-mcp/SKILL.md +23 -0
  16. package/dist/bundled-skills/tarsk-connect-mcp/scripts/__tests__/connect_mcp.test.js +68 -0
  17. package/dist/bundled-skills/tarsk-connect-mcp/scripts/connect_mcp.js +119 -0
  18. package/dist/bundled-skills/tarsk-create-project/SKILL.md +25 -0
  19. package/dist/bundled-skills/tarsk-create-project/scripts/__tests__/create_project.test.js +94 -0
  20. package/dist/bundled-skills/tarsk-create-project/scripts/create_project.js +88 -0
  21. package/dist/bundled-skills/tarsk-edit/SKILL.md +18 -0
  22. package/dist/bundled-skills/tarsk-edit/scripts/edit.js +118 -0
  23. package/dist/bundled-skills/tarsk-execute-skill-script/SKILL.md +19 -0
  24. package/dist/bundled-skills/tarsk-execute-skill-script/scripts/execute_skill_script.js +77 -0
  25. package/dist/bundled-skills/tarsk-fetch/SKILL.md +18 -0
  26. package/dist/bundled-skills/tarsk-fetch/scripts/fetch.js +38 -0
  27. package/dist/bundled-skills/tarsk-find/SKILL.md +16 -0
  28. package/dist/bundled-skills/tarsk-find/scripts/find.js +78 -0
  29. package/dist/bundled-skills/tarsk-find-images/SKILL.md +18 -0
  30. package/dist/bundled-skills/tarsk-find-images/scripts/find_images.js +78 -0
  31. package/dist/bundled-skills/tarsk-generate-image/SKILL.md +18 -0
  32. package/dist/bundled-skills/tarsk-generate-image/scripts/generate_image.js +55 -0
  33. package/dist/bundled-skills/tarsk-get-observation/SKILL.md +19 -0
  34. package/dist/bundled-skills/tarsk-get-observation/scripts/get_observation.js +293 -0
  35. package/dist/bundled-skills/tarsk-grep/SKILL.md +16 -0
  36. package/dist/bundled-skills/tarsk-grep/scripts/grep.js +174 -0
  37. package/dist/bundled-skills/tarsk-history/SKILL.md +15 -0
  38. package/dist/bundled-skills/tarsk-history/scripts/history.js +68 -0
  39. package/dist/bundled-skills/tarsk-improve/SKILL.md +232 -0
  40. package/dist/bundled-skills/tarsk-improve/references/signals.md +16 -0
  41. package/dist/bundled-skills/tarsk-improve/scripts/durable-runs.ts +635 -0
  42. package/dist/bundled-skills/tarsk-improve/scripts/ensure-exported.ts +238 -0
  43. package/dist/bundled-skills/tarsk-improve/scripts/export-tool-skills-lib.ts +299 -0
  44. package/dist/bundled-skills/tarsk-improve/scripts/summarize-session.ts +126 -0
  45. package/dist/bundled-skills/tarsk-jobs/SKILL.md +18 -0
  46. package/dist/bundled-skills/tarsk-jobs/scripts/job_kill.js +45 -0
  47. package/dist/bundled-skills/tarsk-jobs/scripts/job_list.js +64 -0
  48. package/dist/bundled-skills/tarsk-jobs/scripts/job_output.js +66 -0
  49. package/dist/bundled-skills/tarsk-notes/SKILL.md +17 -0
  50. package/dist/bundled-skills/tarsk-notes/scripts/notes.js +86 -0
  51. package/dist/bundled-skills/tarsk-projects/SKILL.md +18 -0
  52. package/dist/bundled-skills/tarsk-projects/scripts/projects.js +54 -0
  53. package/dist/bundled-skills/tarsk-prompt-project/SKILL.md +18 -0
  54. package/dist/bundled-skills/tarsk-prompt-project/scripts/prompt_project.js +58 -0
  55. package/dist/bundled-skills/tarsk-propose-branch/SKILL.md +16 -0
  56. package/dist/bundled-skills/tarsk-propose-branch/scripts/propose_branch.js +45 -0
  57. package/dist/bundled-skills/tarsk-read/SKILL.md +17 -0
  58. package/dist/bundled-skills/tarsk-read/scripts/read.js +331 -0
  59. package/dist/bundled-skills/tarsk-read-skill/SKILL.md +16 -0
  60. package/dist/bundled-skills/tarsk-read-skill/scripts/read_skill.js +37 -0
  61. package/dist/bundled-skills/tarsk-read-skill-reference/SKILL.md +19 -0
  62. package/dist/bundled-skills/tarsk-read-skill-reference/scripts/read_skill_reference.js +60 -0
  63. package/dist/bundled-skills/tarsk-run-js/SKILL.md +18 -0
  64. package/dist/bundled-skills/tarsk-run-js/scripts/run_js.js +192 -0
  65. package/dist/bundled-skills/tarsk-tasks/SKILL.md +18 -0
  66. package/dist/bundled-skills/tarsk-tasks/scripts/tasks.js +96 -0
  67. package/dist/bundled-skills/tarsk-todo/SKILL.md +16 -0
  68. package/dist/bundled-skills/tarsk-todo/scripts/todo.js +165 -0
  69. package/dist/bundled-skills/tarsk-web-search/SKILL.md +15 -0
  70. package/dist/bundled-skills/tarsk-web-search/scripts/web_search.js +120 -0
  71. package/dist/bundled-skills/tarsk-write/SKILL.md +16 -0
  72. package/dist/bundled-skills/tarsk-write/scripts/write.js +57 -0
  73. package/dist/index.js +217754 -211927
  74. package/dist/public/assets/{alert-dialog-DVaEQlVa.js → alert-dialog-BcZULJsX.js} +1 -1
  75. package/dist/public/assets/api-8Rp2LlXt.js +1 -0
  76. package/dist/public/assets/api-Cp9I7CxD.js +2 -0
  77. package/dist/public/assets/{async-error-boundary-DH6Sqgmt.js → async-error-boundary-CFVUPiuG.js} +1 -1
  78. package/dist/public/assets/browser-tab-CPPorbL6.js +12 -0
  79. package/dist/public/assets/button-DDaJhJP1.js +1 -0
  80. package/dist/public/assets/{card-BkOGFps5.js → card-DAc45J1v.js} +1 -1
  81. package/dist/public/assets/chat-dock-context-DbiJNr3O.js +1 -0
  82. package/dist/public/assets/chat-handlers-context-DYU2LQ5V.js +9 -0
  83. package/dist/public/assets/commit-dialog-DPaci3dp.js +1 -0
  84. package/dist/public/assets/{commit-error-dialog-D3S6kRVr.js → commit-error-dialog-Dnlkgb_H.js} +1 -1
  85. package/dist/public/assets/{commit-method-fields-BEKfSRyW.js → commit-method-fields-Xt3vbwUg.js} +1 -1
  86. package/dist/public/assets/conversation-history-view-CqIugfyO.js +1 -0
  87. package/dist/public/assets/{create-project-dialog-nquqlloK.js → create-project-dialog-DStWPoDE.js} +2 -2
  88. package/dist/public/assets/{create-project-workspace-C4tXAUWJ.js → create-project-workspace-CJ94yHAB.js} +2 -2
  89. package/dist/public/assets/create-repo-dialog-B_QiEz-v.js +1 -0
  90. package/dist/public/assets/{delete-confirm-dialog-SpYpU1AX.js → delete-confirm-dialog-D1N86piR.js} +1 -1
  91. package/dist/public/assets/dialog-D_12AsZd.js +1 -0
  92. package/dist/public/assets/diff-view-4koPcOcE.js +4 -0
  93. package/dist/public/assets/{dist-NcyjV9Gu.js → dist-2xH_pFmV.js} +1 -1
  94. package/dist/public/assets/{dist-BTu7PDzc.js → dist-AbkJBHH5.js} +1 -1
  95. package/dist/public/assets/{dist-lFBinzor.js → dist-B-h6Wj39.js} +1 -1
  96. package/dist/public/assets/dist-CgbWuuq4.js +1 -0
  97. package/dist/public/assets/{dist-f54JuzFV.js → dist-DOz2WXwX.js} +1 -1
  98. package/dist/public/assets/{dist-CqrmQxmV.js → dist-DfnQ9YJh.js} +1 -1
  99. package/dist/public/assets/{dist-BOfRC57H.js → dist-JGbQ_EJY.js} +1 -1
  100. package/dist/public/assets/{dist-ButPmyjr.js → dist-pCVg1Jdl.js} +1 -1
  101. package/dist/public/assets/dist-v_MvKS2-.js +2 -0
  102. package/dist/public/assets/{es2015-CE7VcoOH.js → es2015-eNVkKfFF.js} +1 -1
  103. package/dist/public/assets/{explorer-file-drop-CEbBlDEp.js → explorer-file-drop-DAP7ha-E.js} +1 -1
  104. package/dist/public/assets/{explorer-monaco-editor-Bgo9Y1cP.js → explorer-monaco-editor-ChJZBFy5.js} +1 -1
  105. package/dist/public/assets/explorer-tab-view-Bt9hRZUm.js +2 -0
  106. package/dist/public/assets/explorer-tree-CAs89lPz.js +1 -0
  107. package/dist/public/assets/{explorer-view-BuTa_0Uq.js → explorer-view-B1JuejkU.js} +3 -3
  108. package/dist/public/assets/git-history-dialog-Dqj1p35g.js +1 -0
  109. package/dist/public/assets/index-CcAwxnT5.js +97 -0
  110. package/dist/public/assets/index-dNrgKdYv.css +1 -0
  111. package/dist/public/assets/{label-C31qF5zZ.js → label-BCs5CZEs.js} +1 -1
  112. package/dist/public/assets/markdown-renderer-DQONI6WG.js +10 -0
  113. package/dist/public/assets/{mcp-manager-C3K_62H2.js → mcp-manager-D2FG-h2e.js} +1 -1
  114. package/dist/public/assets/{minus-l6BdrAEk.js → minus-CgQcbBQT.js} +1 -1
  115. package/dist/public/assets/{model-list-controls-DwW8S18v.js → model-list-controls-B6ofHWh3.js} +1 -1
  116. package/dist/public/assets/onboarding-dialog-DAut3X4K.js +1 -0
  117. package/dist/public/assets/{pill-tabs-CmvvHdKG.js → pill-tabs-BAhOHad7.js} +1 -1
  118. package/dist/public/assets/progress-indicator-hJ74ac5W.js +1 -0
  119. package/dist/public/assets/project-coding-view-B2FpHeiO.js +1 -0
  120. package/dist/public/assets/{project-danger-zone-view-D18k4pUF.js → project-danger-zone-view-BqP1dcRT.js} +1 -1
  121. package/dist/public/assets/{project-env-vars-view-BWFqoaFD.js → project-env-vars-view-zhigkQFG.js} +1 -1
  122. package/dist/public/assets/project-model-aliases-view-APAVFfym.js +1 -0
  123. package/dist/public/assets/project-settings-view-FnK-LRsv.js +1 -0
  124. package/dist/public/assets/project-tools-view-Dmp5ViRC.js +1 -0
  125. package/dist/public/assets/providers-list-view-Clbp73Hh.js +1 -0
  126. package/dist/public/assets/pull-request-dialog-D40BQPMk.js +1 -0
  127. package/dist/public/assets/pull-with-changes-dialog-pkXK-VP2.js +1 -0
  128. package/dist/public/assets/push-before-pr-dialog-DH91JHEC.js +1 -0
  129. package/dist/public/assets/query-keys-CcnonAAG.js +1 -0
  130. package/dist/public/assets/remote-media-url-C-GdJb-D.js +1 -0
  131. package/dist/public/assets/{scroll-area-BWc4OPsj.js → scroll-area-DGF9wUqQ.js} +1 -1
  132. package/dist/public/assets/{select-B6RizwDW.js → select-DMcNYwgt.js} +1 -1
  133. package/dist/public/assets/settings-general-tabs-view-DBZQbihJ.js +2 -0
  134. package/dist/public/assets/settings-general-view-0dhBET2R.js +1 -0
  135. package/dist/public/assets/{settings-list-D35rpAof.js → settings-list-Co3JPr9w.js} +1 -1
  136. package/dist/public/assets/settings-logs-view-DvHXUDko.js +5 -0
  137. package/dist/public/assets/settings-mcp-servers-view-414Dt5py.js +5 -0
  138. package/dist/public/assets/settings-models-view-ByeR7Enb.js +1 -0
  139. package/dist/public/assets/settings-plugins-view-8te2MPyh.js +2 -0
  140. package/dist/public/assets/settings-providers-view-BAuv9gam.js +2 -0
  141. package/dist/public/assets/settings-remote-machines-view-CHyywazU.js +1 -0
  142. package/dist/public/assets/settings-setup-view-Btp46Vh_.js +2 -0
  143. package/dist/public/assets/settings-skills-view-BNVx4bZl.js +2 -0
  144. package/dist/public/assets/{settings-slack-view-DkclyaBc.js → settings-slack-view-Caly5yGt.js} +1 -1
  145. package/dist/public/assets/settings-slash-commands-view-m6mp1knu.js +1 -0
  146. package/dist/public/assets/{settings-statistics-view-B03ZZjEy.js → settings-statistics-view-BnOxr4sZ.js} +1 -1
  147. package/dist/public/assets/settings-storage-view-Dg8xfpTG.js +1 -0
  148. package/dist/public/assets/settings-subagents-view-CucwEk2A.js +2 -0
  149. package/dist/public/assets/settings-system-prompt-view-CEDU2saT.js +1 -0
  150. package/dist/public/assets/{settings-tab-bar-ajzyt79U.js → settings-tab-bar-CdIbQ0WI.js} +1 -1
  151. package/dist/public/assets/settings-view-XcJhRclT.js +2 -0
  152. package/dist/public/assets/{slug-utils-D2jhPz-o.js → slug-utils-CO6nui1C.js} +1 -1
  153. package/dist/public/assets/square-CtxvwmM2.js +1 -0
  154. package/dist/public/assets/store-W78TGOIO.js +8 -0
  155. package/dist/public/assets/{table-C3Hc0Gwy.js → table-CQMqIW_-.js} +1 -1
  156. package/dist/public/assets/task-utils-Cnq9Eszt.js +1 -0
  157. package/dist/public/assets/tasks-view-B8_jkq_a.js +1 -0
  158. package/dist/public/assets/{terminal-panel-DCKqScJu.js → terminal-panel-xoLVfA-h.js} +2 -2
  159. package/dist/public/assets/{toggle-group-DqSxGqvP.js → toggle-group-CPmseZfb.js} +1 -1
  160. package/dist/public/assets/{tooltip-CJKJfu0l.js → tooltip-CqwCZ7wt.js} +1 -1
  161. package/dist/public/assets/{use-account-settings-query-AUeOqKvo.js → use-account-settings-query-D_qL1I4w.js} +1 -1
  162. package/dist/public/assets/{use-active-dock-panel-instance-BvAhUd_V.js → use-active-dock-panel-instance-kmJOnmL7.js} +1 -1
  163. package/dist/public/assets/use-browser-overlay-block-CO1pUEAZ.js +1 -0
  164. package/dist/public/assets/{use-git-check-B_5Jak2s.js → use-git-check-BD9gdXpK.js} +1 -1
  165. package/dist/public/assets/{use-installed-ai-files-iy_AB0dN.js → use-installed-ai-files-Nn-sN_V2.js} +1 -1
  166. package/dist/public/assets/use-open-chat-dock-panel-CXzpgxVs.js +1 -0
  167. package/dist/public/assets/{use-projects-BmhAMgxB.js → use-projects-B0xTjTaA.js} +2 -2
  168. package/dist/public/assets/utils-CqsIXqSC.js +1 -0
  169. package/dist/public/assets/web-BNWoiS4w.js +1 -0
  170. package/dist/public/assets/web-C1tBQoCB.js +1 -0
  171. package/dist/public/assets/web-Dlo3GwCf.js +1 -0
  172. package/dist/public/assets/web-cJXG33sT.js +1 -0
  173. package/dist/public/fonts/schibsted-grotesk-latin-ext-wght-normal.woff2 +0 -0
  174. package/dist/public/fonts/schibsted-grotesk-latin-wght-normal.woff2 +0 -0
  175. package/dist/public/index.html +46 -46
  176. package/package.json +9 -9
  177. package/dist/public/assets/account-view-5q3pHEHY.js +0 -1
  178. package/dist/public/assets/ai-spinner-DHwhlk4j.js +0 -1
  179. package/dist/public/assets/api-BdebJfuN.js +0 -1
  180. package/dist/public/assets/api-COO2LfdU.js +0 -2
  181. package/dist/public/assets/browser-overlay-block-CiDtkfup.js +0 -1
  182. package/dist/public/assets/browser-tab-CVdYLmW5.js +0 -12
  183. package/dist/public/assets/button-Dp5XDZNR.js +0 -1
  184. package/dist/public/assets/chat-dock-context-ymLoO90X.js +0 -1
  185. package/dist/public/assets/checkbox-D-BV8-Z_.js +0 -1
  186. package/dist/public/assets/commit-dialog-CEbCFh1x.js +0 -1
  187. package/dist/public/assets/conversation-history-view-CVMD8hUU.js +0 -1
  188. package/dist/public/assets/create-repo-dialog-B5IE3pUJ.js +0 -1
  189. package/dist/public/assets/dialog-pHPeIGaB.js +0 -1
  190. package/dist/public/assets/diff-view-Cy6nPdX-.js +0 -4
  191. package/dist/public/assets/dist-D5vgS4RP.js +0 -2
  192. package/dist/public/assets/explorer-tab-view-C-8QZO9S.js +0 -2
  193. package/dist/public/assets/explorer-tree-HrLSFgcI.js +0 -1
  194. package/dist/public/assets/git-history-dialog-ClfF5IOn.js +0 -1
  195. package/dist/public/assets/index-BBLA5zVt.css +0 -1
  196. package/dist/public/assets/index-CalVAwXj.js +0 -104
  197. package/dist/public/assets/markdown-renderer-DXRBG7uP.js +0 -10
  198. package/dist/public/assets/onboarding-dialog-BtLy0wjC.js +0 -1
  199. package/dist/public/assets/progress-indicator-4zQXqOqP.js +0 -1
  200. package/dist/public/assets/project-coding-view-CyJwnJes.js +0 -1
  201. package/dist/public/assets/project-model-aliases-view-D3tYNkkM.js +0 -1
  202. package/dist/public/assets/project-settings-view-0oN9vFvD.js +0 -1
  203. package/dist/public/assets/project-tools-view-DT87KPjE.js +0 -1
  204. package/dist/public/assets/providers-list-view-DCnh0W-5.js +0 -1
  205. package/dist/public/assets/pull-request-dialog-BdJxYQwu.js +0 -1
  206. package/dist/public/assets/pull-with-changes-dialog-Do9x9neW.js +0 -1
  207. package/dist/public/assets/push-before-pr-dialog-C-9z2O0-.js +0 -1
  208. package/dist/public/assets/query-keys-BwswkbMn.js +0 -1
  209. package/dist/public/assets/remote-media-url-B8OFqxOM.js +0 -1
  210. package/dist/public/assets/settings-general-tabs-view-Dcek-ysB.js +0 -2
  211. package/dist/public/assets/settings-general-view-DhA2N6G5.js +0 -1
  212. package/dist/public/assets/settings-logs-view-eEUTIMeb.js +0 -5
  213. package/dist/public/assets/settings-mcp-servers-view-_oeuVkUe.js +0 -5
  214. package/dist/public/assets/settings-models-view-DW-ZmVup.js +0 -1
  215. package/dist/public/assets/settings-plugins-view-DTooco_c.js +0 -2
  216. package/dist/public/assets/settings-providers-view-CEeJkhg9.js +0 -2
  217. package/dist/public/assets/settings-remote-machines-view--UB8GlCK.js +0 -1
  218. package/dist/public/assets/settings-setup-view-DFL6DlYS.js +0 -2
  219. package/dist/public/assets/settings-skills-view-xS569-Kb.js +0 -2
  220. package/dist/public/assets/settings-slash-commands-view-DrCiayfq.js +0 -1
  221. package/dist/public/assets/settings-storage-view-CQnaVOt_.js +0 -1
  222. package/dist/public/assets/settings-subagents-view-DIctUJcE.js +0 -2
  223. package/dist/public/assets/settings-system-prompt-view-BMDbrFRR.js +0 -1
  224. package/dist/public/assets/settings-view-8M6sbGiX.js +0 -2
  225. package/dist/public/assets/store-CxUwqrZ5.js +0 -8
  226. package/dist/public/assets/task-utils-WAei2PDi.js +0 -1
  227. package/dist/public/assets/tasks-view-DKyqgGdE.js +0 -1
  228. package/dist/public/assets/use-browser-overlay-block-z9imTmiZ.js +0 -1
  229. package/dist/public/assets/use-open-chat-dock-panel-w3hc5Vxn.js +0 -1
  230. package/dist/public/assets/utils-mYB1USG6.js +0 -1
  231. package/dist/public/assets/web-C6Gm4nQ0.js +0 -1
  232. package/dist/public/assets/web-DFlyNg8o.js +0 -1
  233. package/dist/public/assets/web-DlEPs8Xe.js +0 -1
  234. package/dist/public/assets/web-Gx3xReQH.js +0 -1
  235. package/dist/public/backgrounds/arctic-tundra.avif +0 -0
  236. package/dist/public/backgrounds/autumn-leaves.avif +0 -0
  237. package/dist/public/backgrounds/coastal-cliff.avif +0 -0
  238. package/dist/public/backgrounds/floating-waterfall.avif +0 -0
  239. package/dist/public/backgrounds/forest-path.avif +0 -0
  240. package/dist/public/backgrounds/garden-path.avif +0 -0
  241. package/dist/public/backgrounds/glow-marsh.avif +0 -0
  242. package/dist/public/backgrounds/golden-wheat.avif +0 -0
  243. package/dist/public/backgrounds/moon-desert.avif +0 -0
  244. package/dist/public/backgrounds/night-pond.avif +0 -0
  245. package/dist/public/backgrounds/prairie-grassland.avif +0 -0
  246. package/dist/public/backgrounds/river-winding.avif +0 -0
  247. package/dist/public/backgrounds/salt-flat.avif +0 -0
  248. package/dist/public/backgrounds/salt-marsh.avif +0 -0
  249. package/dist/public/backgrounds/sandy-beach.avif +0 -0
  250. package/dist/public/backgrounds/snow-river.avif +0 -0
  251. package/dist/public/backgrounds/sunset-pond.avif +0 -0
  252. package/dist/public/fonts/plus-jakarta-sans-cyrillic-ext-wght-normal.woff2 +0 -0
  253. package/dist/public/fonts/plus-jakarta-sans-latin-ext-wght-normal.woff2 +0 -0
  254. package/dist/public/fonts/plus-jakarta-sans-latin-wght-normal.woff2 +0 -0
  255. package/dist/public/fonts/plus-jakarta-sans-vietnamese-wght-normal.woff2 +0 -0
package/README.md CHANGED
@@ -1,20 +1,22 @@
1
1
  # Tarsk CLI
2
2
 
3
- [Tarsk](https://tarsk.io) is an AI coding workspace for working with Git repositories in isolated threads. Each thread gets its own working copy, so you can explore ideas, run agents, review changes, and manage project work without disturbing your main branch.
3
+ [Tarsk](https://tarsk.io) is an AI coding and knowledge workspace for working with Git repositories in isolated threads. Each thread gets its own working copy, so you can explore ideas, run agents, review changes, and manage project work without disturbing your main branch.
4
4
 
5
- The CLI starts a local Bun-powered server that serves the [Tarsk](https://tarsk.io) app and exposes the API for repository management, agent execution, and project workflows.
5
+ The CLI starts a local Bun-powered server that serves the [Tarsk](https://tarsk.io) app and exposes the API for repository management, agent execution, and project workflows. The same server powers the macOS desktop app (Electrobun).
6
6
 
7
7
  ## Features
8
8
 
9
9
  - **Projects** — Connect an existing Git repository, open a local folder, or scaffold a new app from a template.
10
10
  - **Threads** — Create multiple isolated working copies per project for parallel experiments.
11
11
  - **AI agents** — Chat with agents that can read and modify code inside a thread, with diff review before accepting changes.
12
+ - **Goals** — Run long-lived objectives with `/goal` across verified rounds and fresh context.
12
13
  - **Tasks** — Plan work in the Tasks view and jump into threads from tasks.
13
14
  - **Providers and models** — Configure AI providers, models, and per-project model aliases.
14
15
  - **MCP servers** — Attach Model Context Protocol servers for extended agent tooling.
15
16
  - **Rules, skills, and slash commands** — Customize agent behavior with project rules, bundled skills, and reusable commands.
16
17
  - **Git workflows** — Inspect status, review diffs, create commits, and open pull requests from the UI.
17
- - **Browser and terminal** — Run project commands, open dev servers in an embedded browser, and use integrated terminals.
18
+ - **Slack** — Bind channels to projects and drive Tarsk from Slack (Socket Mode).
19
+ - **Browser and terminal** — Run project commands, open dev servers in an embedded browser (desktop), and use integrated terminals.
18
20
 
19
21
  ## Quick start
20
22
 
@@ -32,14 +34,18 @@ To always use the latest published version:
32
34
  npx tarsk@latest
33
35
  ```
34
36
 
35
- You can also download the macOS desktop app from [tarsk.io](https://tarsk.io/#download). The desktop app bundles its own runtime and does not require Node.js.
37
+ You can also download the macOS desktop app from [tarsk.io](https://tarsk.io/#download). The desktop app bundles its own runtime and does not require Node.js. Closing the window keeps the server running; quit from the menu bar tray.
36
38
 
37
39
  ## CLI options
38
40
 
39
- | Flag | Description |
40
- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
41
+ | Flag | Description |
42
+ | ---- | ----------- |
41
43
  | `--server` | Start the API server only. Do not open a browser tab. Useful for headless operation, remote access, or when another client (desktop app, mobile) connects to the server. |
42
- | `--debug` | Enable verbose logging. Runs the server on port **462** instead of **641**. |
44
+ | `--debug` | Enable verbose logging. Runs the server on port **462** instead of **641**. |
45
+ | `--port <n>` | Server port in normal mode (sets `PORT`; default **641**). Ignored when `--debug` is set. |
46
+ | `--open` | Open the browser even when `--server` is set. |
47
+ | `--data-dir <path>` | Override the data directory (sets `TARSK_DATA_DIR`). |
48
+ | `--assets-dir <path>` | Override companion server assets (`public/`, bundled skills, etc.; sets `TARSK_ASSETS_DIR`). |
43
49
 
44
50
  Examples:
45
51
 
@@ -47,41 +53,74 @@ Examples:
47
53
  npx tarsk --server # headless server
48
54
  npx tarsk --debug # troubleshoot with full logs
49
55
  npx tarsk --server --debug # headless server with verbose logging
56
+ npx tarsk --port 3000 # custom port (normal mode)
50
57
  ```
51
58
 
52
59
  ### Environment variables
53
60
 
54
- | Variable | Description |
55
- | -------- | ----------------------------------------------------------------------------------------------------- |
56
- | `PORT` | Server port in normal mode (default: `641`). Ignored when `--debug` is set (debug always uses `462`). |
61
+ | Variable | Description |
62
+ | -------- | ----------- |
63
+ | `PORT` | Server port in normal mode (default: `641`). Ignored when `--debug` is set (debug always uses `462`). |
64
+ | `TARSK_APP_SUPPORT_DIR` | Root application support directory (logs, `port.json`, default layout). |
65
+ | `TARSK_DATA_DIR` | Data directory (defaults to `<appSupport>/data`). Same effect as `--data-dir`. |
66
+ | `TARSK_ASSETS_DIR` | Directory with bundled server assets. Same effect as `--assets-dir`. |
67
+ | `MODE` | Set to `development` when running from the monorepo (`bun run web`); suppresses auto-open unless `--open` is passed. |
57
68
 
58
69
  If the default port is already in use, Tarsk tries the next available port and prints the URL it bound to.
59
70
 
60
71
  ## System requirements
61
72
 
62
- | Requirement | Notes |
63
- | -------------------------- | ---------------------------------------------------------------------------- |
64
- | **git** | Required. Tarsk uses git to clone repositories and manage branches. |
65
- | **Node.js 18+** or **Bun** | Required for `npx tarsk`. |
66
- | **gh CLI** (optional) | Needed for creating GitHub repositories and pull requests from within Tarsk. |
73
+ | Requirement | Notes |
74
+ | ----------- | ----- |
75
+ | **git** | Required. Tarsk uses git to clone repositories and manage branches. |
76
+ | **Node.js 18+** or **Bun** | Required for `npx tarsk`. |
77
+ | **gh CLI** (optional) | Needed for creating GitHub repositories and pull requests from within Tarsk. |
78
+
79
+ Tarsk checks for `git` during onboarding on first launch and surfaces a warning with a download link if it is missing.
67
80
 
68
81
  ## Where data is stored
69
82
 
70
- All Tarsk data lives in your user data directory:
83
+ All Tarsk data lives under your application support directory:
84
+
85
+ | Platform | Default path |
86
+ | -------- | ------------ |
87
+ | macOS | `~/Library/Application Support/Tarsk/` |
88
+ | Linux / Windows (CLI) | Same path under your home directory unless you override it (see below). |
71
89
 
72
- | Platform | Path |
73
- | -------- | -------------------------------------- |
74
- | macOS | `~/Library/Application Support/Tarsk/` |
75
- | Windows | `%APPDATA%\Tarsk\` |
76
- | Linux | `~/.config/Tarsk/` |
90
+ The desktop app and CLI share these defaults. Set `TARSK_APP_SUPPORT_DIR` to move the whole tree (logs, `port.json`, and `data/`). Use `--data-dir` or `TARSK_DATA_DIR` to relocate only the `data/` folder. On Linux or Windows, set `TARSK_APP_SUPPORT_DIR` if you want a conventional path such as `~/.config/Tarsk`.
77
91
 
78
- Inside this directory:
92
+ Inside the application support directory:
79
93
 
80
- - `tarsk.db` — SQLite database (projects, threads, conversations, settings)
81
- - `data/{threadId}/` — one directory per thread, containing the full git working copy for that thread
94
+ - `data/tarsk.db` — SQLite database (projects, threads, conversations, settings)
95
+ - `data/{repo-slug}/` — one directory per thread, each a full git working copy (for example `org-repo` from `https://github.com/org/repo`, with `-1`, `-2`, … when names collide)
96
+ - `port.json` — active server port (written when the server starts)
82
97
 
83
98
  Each thread is a real, independent filesystem copy of your repository.
84
99
 
100
+ ## Remote access
101
+
102
+ To use Tarsk from another device, sign in and enable **Mobile & Network Access** in **Settings → Remote Access**. Tarsk provisions a public address on tarsk.net; visitors must sign in as the same account. Restart Tarsk after changing this setting. See [Remote Access](https://tarsk.io/docs/settings/remote-machines/) in the product docs.
103
+
104
+ ## Developing from the monorepo
105
+
106
+ From the repository root, see [README.md](../README.md) for full monorepo setup, build order, and `check:all`.
107
+
108
+ Common workflows inside `cli/`:
109
+
110
+ | Command | Purpose |
111
+ | ------- | ------- |
112
+ | `bun run web` | Run the server in development mode (same as root `bun run dev:cli`). |
113
+ | `bun run dev` | Build frontend assets and launch the Electrobun desktop app in dev mode. |
114
+ | `bun run dev:web` | Debug API on **462** plus Vite on **8100** (hot reload). |
115
+ | `bun run build` | Production desktop build (codesigned when configured). |
116
+ | `bun run build:unsigned` | Desktop build without codesign/notarize (CI and sandboxes). |
117
+ | `bun run build:npm` | Server bundle only (published `npx tarsk` artifact). |
118
+ | `bun run test` | CLI tests (`vp test run`, not bare `bun test`). |
119
+
120
+ Implementation notes for contributors: [agents.md](agents.md) and [AGENTS.md](../AGENTS.md).
121
+
85
122
  ## Documentation
86
123
 
87
124
  - [tarsk.io/docs](https://tarsk.io/docs) — product documentation
125
+ - [Installation](https://tarsk.io/docs/getting-started/installation/) — flags, data paths, and requirements
126
+ - [README.md](../README.md) — monorepo layout and development
@@ -0,0 +1,15 @@
1
+ ---
2
+ name: email-me
3
+ description: Use when the user asks "email me".
4
+ version: 1.0.0
5
+ tools:
6
+ - email_me
7
+ ---
8
+ # Email me
9
+
10
+ Sends an email to the signed-in Tarsk user.
11
+
12
+ - Put the information the user wants into `body`. Keep `subject` short.
13
+ - Call `email_me` once, then report its answer.
14
+ - When it reports that no one is signed in, ask the user to log in to Tarsk.
15
+ Do not call the tool again until the user is signed in.
@@ -0,0 +1,64 @@
1
+ import assert from "node:assert/strict";
2
+ import test from "node:test";
3
+
4
+ import { execute } from "../email_me.js";
5
+
6
+ function contextReturning(result) {
7
+ const calls = [];
8
+ return {
9
+ calls,
10
+ email: {
11
+ async sendToSelf(message) {
12
+ calls.push(message);
13
+ return result;
14
+ },
15
+ },
16
+ };
17
+ }
18
+
19
+ void test("asks the user to log in to Tarsk when no account is signed in", async () => {
20
+ const context = contextReturning({ status: "not-signed-in" });
21
+
22
+ const result = await execute({ body: "The build is green." }, context);
23
+
24
+ assert.match(result.content[0].text, /log in to Tarsk/i);
25
+ assert.equal(context.calls.length, 1);
26
+ });
27
+
28
+ void test("sends the requested subject and body and names the address", async () => {
29
+ const context = contextReturning({ status: "sent", to: "owner@example.com" });
30
+
31
+ const result = await execute(
32
+ { subject: "Status", body: "The build is green." },
33
+ context,
34
+ );
35
+
36
+ assert.deepEqual(context.calls, [{ subject: "Status", body: "The build is green." }]);
37
+ assert.match(result.content[0].text, /owner@example\.com/);
38
+ });
39
+
40
+ void test("defaults the subject when none is given", async () => {
41
+ const context = contextReturning({ status: "sent", to: "owner@example.com" });
42
+
43
+ await execute({ body: "The build is green." }, context);
44
+
45
+ assert.equal(context.calls[0].subject, "Message from Tarsk");
46
+ });
47
+
48
+ void test("reports a failed send with the service message", async () => {
49
+ const context = contextReturning({ status: "failed", message: "rate limited" });
50
+
51
+ const result = await execute({ body: "The build is green." }, context);
52
+
53
+ assert.match(result.content[0].text, /rate limited/);
54
+ assert.equal(context.calls.length, 1);
55
+ });
56
+
57
+ void test("refuses an empty body without sending", async () => {
58
+ const context = contextReturning({ status: "sent", to: "owner@example.com" });
59
+
60
+ const result = await execute({ body: " " }, context);
61
+
62
+ assert.match(result.content[0].text, /body/i);
63
+ assert.equal(context.calls.length, 0);
64
+ });
@@ -0,0 +1,45 @@
1
+ export const description =
2
+ 'Send an email to the signed-in Tarsk user. Use when the user says "email me".';
3
+
4
+ export const parameters = {
5
+ type: "object",
6
+ properties: {
7
+ subject: { type: "string", description: "Short subject line for the email" },
8
+ body: {
9
+ type: "string",
10
+ description: "Email body: the information the user asked to include",
11
+ },
12
+ },
13
+ required: ["body"],
14
+ };
15
+
16
+ export async function execute(args, context) {
17
+ const subject = String(args.subject ?? "").trim() || "Message from Tarsk";
18
+ const body = String(args.body ?? "").trim();
19
+ if (!body) {
20
+ return {
21
+ content: [{ type: "text", text: "email_me: `body` is empty. Put the information to send in `body`." }],
22
+ };
23
+ }
24
+
25
+ const result = await context.email.sendToSelf({ subject, body });
26
+
27
+ if (result.status === "not-signed-in") {
28
+ return {
29
+ content: [
30
+ {
31
+ type: "text",
32
+ text: "No Tarsk account is signed in. Please log in to Tarsk and ask again.",
33
+ },
34
+ ],
35
+ };
36
+ }
37
+
38
+ if (result.status === "failed") {
39
+ return {
40
+ content: [{ type: "text", text: `The email was not sent: ${result.message}` }],
41
+ };
42
+ }
43
+
44
+ return { content: [{ type: "text", text: `Email sent to ${result.to}.` }] };
45
+ }
@@ -0,0 +1,19 @@
1
+ ---
2
+ name: handoff
3
+ description: use if user asks for handoff
4
+ argument-hint: "Optional focus for the new chat"
5
+ ---
6
+
7
+ # Handoff
8
+
9
+ When the user asks for a handoff or invokes this skill, create a new chat in the current project. Do not only write a summary or a temporary handoff file.
10
+
11
+ Prepare a concise, self-contained first message for the new chat. Include the original ask, decisions and constraints, relevant verified facts, completed work, current state, important paths or links, checks and their outcomes, and unfinished work. Keep details that the next agent needs; do not repeat artifacts that can be referenced by path or URL. Do not include secrets.
12
+
13
+ If the user provides a focus for the next chat, make it the new chat's primary task. Keep the prior task context that supports that focus, and distinguish facts from assumptions.
14
+
15
+ List the exact skill references that were used or referenced in this conversation under a "Skills carried forward" section in the first message. Use /name for project or global skills and //name for bundled skills. Do not invent references. The handoff operation copies the current chat's enabled and disabled skill settings and adds a link to the source chat; the listed references preserve explicit skill uses that are not part of those settings.
16
+
17
+ Choose a short title that describes the focus. Start the new chat by calling context.chat.startHandoff with the title, complete first-message prompt, and skill names. Use context.chat.normalizeTitle to normalize the title. Do not say the new chat started unless the call succeeds.
18
+
19
+ After success, give the user a markdown link to the new chat using the returned URL. If the launch fails after creating a chat, show the recovery link from the error and state that the first message did not start.
@@ -0,0 +1,372 @@
1
+ ---
2
+ name: tarsk-agent
3
+ description: >-
4
+ How to author, edit, and package Tarsk Tool skills: SKILL.md front matter,
5
+ scripts/{name}.js contract, Agent runtime (context), and export/resolution.
6
+ Use when creating or modifying a Tool skill, changing a tool
7
+ description/schema/execute, or asking what context.* APIs provide.
8
+ version: 2.0.1
9
+ when_to_use: >-
10
+ Before creating or editing any Skill under .agents/skills or cli/bundled-skills
11
+ that publishes tools, or when changing tool behavior, parameters, or descriptions.
12
+ Also when a tool repeatedly fails or a goal burned excessive turns/tokens due to
13
+ tool design (noisy output, missing select, serial multi-hop).
14
+ ---
15
+
16
+ # Agent runtime & Tool skills (`tarsk-agent`)
17
+
18
+ Read this before creating or editing a Tool skill. Tool skill scripts must not
19
+ import modules (no `import` / `require`). They receive a `context` object (the
20
+ Agent runtime) as the second argument to `execute`. Project scripts that import
21
+ are rejected at load; use only `context.*`.
22
+
23
+ ## When to update a Tool skill
24
+
25
+ Edit the project Tool skill (usually `.agents/skills/tarsk-<area>/`) when:
26
+
27
+ - The same tool call fails repeatedly for a fixable reason (bad defaults, weak
28
+ validation message, schema that invites wrong args, brittle formatting).
29
+ - Reaching the user's goal took excessive turns or tokens because of tool design
30
+ (dumping huge results instead of `select` / truncation, forcing grep→read
31
+ loops that belong in `run_js`, descriptions that send the model down a dead path).
32
+ - A description or parameter shape no longer matches how the tool should be used.
33
+
34
+ Prefer a small change to `description`, `parameters`, or `execute` over teaching
35
+ the model a one-off workaround in chat. After edit, the next tool load picks it
36
+ up. Do not invent host APIs — use `context.*` below.
37
+
38
+ ## Split of responsibility
39
+
40
+ | Lives in | Responsibility |
41
+ | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
42
+ | **Tool skill scripts** | Tool logic: description, parameters, orchestration, formatting, policy text the agent may edit |
43
+ | **CLI / Agent runtime** | Security and light host: cwd/path checks, permission gates, seatbelt, fetch allowlist, DB/network clients, truncate helpers, job registry |
44
+
45
+ Prefer implementing behavior in `scripts/{name}.js` using `context` primitives.
46
+ Heavy engines (edit matching, browser, shell spawn) stay behind dedicated
47
+ `context.*` host APIs — never import Node modules or `cli/src`.
48
+
49
+ ### What you can change
50
+
51
+ | Goal | How |
52
+ | ------------------------------------ | ------------------------------------------------------------------------ |
53
+ | Change Tool behavior the agent owns | Edit `execute` / `description` / `parameters` in the Skill script |
54
+ | Need filesystem/shell/network safely | Call the matching **secure or light** `context.*` API (documented below) |
55
+
56
+ ## Package layout
57
+
58
+ A Tool skill is a normal Skill whose front matter lists `tools`:
59
+
60
+ ```text
61
+ .agents/skills/my-notes/ # project copy (edit here)
62
+ SKILL.md
63
+ scripts/
64
+ notes.js # one file per name in tools:
65
+ ```
66
+
67
+ Tarsk-shipped defaults live under `cli/bundled-skills/tarsk-*`. To change one, **export**
68
+ it into the Project’s `.agents/skills` (`tarsk-improve`’s `ensure-exported.ts`) and
69
+ **edit the project copy** under `.agents/skills/…` so your changes stick. Chat load
70
+ never creates copies — it only **prunes** project copies that still match bundled — so
71
+ export before editing. The `tarsk-` prefix is a shipping convention for export only;
72
+ any Skill with a `tools` array publishes Tools.
73
+
74
+ ### Front matter
75
+
76
+ ```yaml
77
+ ---
78
+ name: my-notes # must match the directory name
79
+ description: Short trigger text for humans and skill discovery
80
+ version: 1.0.0 # semver; used by export
81
+ tools:
82
+ - notes # model-facing Tool name(s)
83
+ # deferred-tools: # optional; subset of tools → behind tool_search
84
+ # - notes
85
+ ---
86
+ ```
87
+
88
+ - `tools: [name, …]` — required for a Tool skill. Each name needs `scripts/{name}.js`.
89
+ Add the name here **before** creating the script: the write guard validates only
90
+ declared Tool scripts, so a file it does not know is an ordinary helper script
91
+ (it may import modules; it has no `description`/`parameters`/`execute` contract).
92
+ - `deferred-tools` — optional subset of `tools`; omitted means all eager. Prefer deferring
93
+ rare tools (browser, jobs, images, web, observations, …) so schemas stay out of every
94
+ request; keep the coding core eager.
95
+ - A deferred tool is reachable only through `tool_search`, which matches a tool's name and
96
+ `description` — never its `parameters`. Name every capability a model might search for
97
+ (for example `screenshot`, `capture`) in the script's `description`, or keyword search
98
+ cannot find the tool and the model concludes the capability does not exist.
99
+ - Host injects a shared `select` parameter for `read` and `bash` at load time — do not
100
+ duplicate that schema in the Skill script.
101
+ - Not the same as `allowed-tools` (that only restricts which existing Tools a Skill may use).
102
+ - Directory name must equal front matter `name`.
103
+
104
+ ### Script contract
105
+
106
+ Each `scripts/{name}.js` (or `.ts`) exports:
107
+
108
+ - `description` — string shown to the model for this Tool
109
+ - `parameters` — JSON Schema object for arguments
110
+ - `execute(args, context, options?)` — returns
111
+ `{ content: [{ type: "text", text }], details? }`
112
+ (throw or return an error text on failure)
113
+
114
+ The Tool **name** comes from the `tools` array, not from inside the file.
115
+ A script not listed in `tools` is an ordinary skill script (`execute_skill_script`),
116
+ not a model Tool.
117
+
118
+ `options` (third argument): `{ signal?, onUpdate? }` for abort and streaming
119
+ progress.
120
+
121
+ ## Where files live (export & resolution)
122
+
123
+ 1. **Resolution for a run:** Project `.agents/skills/<name>` if present, else
124
+ bundled `cli/bundled-skills/<name>`. Load never writes. Script imports are
125
+ cache-busted by mtime so edits apply on the next tool load. Project scripts
126
+ must not `import`/`require` modules (rejected at load).
127
+ 2. **Export (deliberate):** Run `tarsk-improve`’s `ensure-exported.ts` to copy
128
+ bundled Skills whose names start with `tarsk-` into `.agents/skills`:
129
+ - missing project copy → copy
130
+ - same `version` → leave
131
+ - bundled **major** > project major → overwrite
132
+ - otherwise (project ahead, or only minor/patch ahead) → leave project copy
133
+ Chat load never copies. It only **prunes** a project copy that is byte-identical
134
+ to bundled, so untouched packages never persist in the repo.
135
+ 3. **Where edits land:** in the Tarsk checkout the built-ins under
136
+ `cli/bundled-skills/tarsk-*` _are_ this repo's own files, so
137
+ `ensure-exported.ts` copies nothing and `.agents/skills/tarsk-*` stays absent —
138
+ edit `cli/bundled-skills/tarsk-*` directly. In any other repo do not hand-edit
139
+ `cli/bundled-skills/`; the project export is the edit surface.
140
+ 4. Bump `version` in front matter when you intentionally publish a new Skill
141
+ revision. A major bump on the bundled side can overwrite local copies.
142
+
143
+ ## Enable / disable
144
+
145
+ - Tool skills are **enabled by default**.
146
+ - Disabling the Skill (thread skill settings) hides every Tool in its `tools` array.
147
+ - Project `disabledTools` still hides individual Tool names.
148
+ - Disabling `tarsk-agent` does not remove Tools; the CLI always injects `context`.
149
+
150
+ ## `context` API
151
+
152
+ ### Identifiers
153
+
154
+ | Field | Meaning |
155
+ | ---------------- | --------------------------------- |
156
+ | `cwd` | Working directory for the run |
157
+ | `projectId` | Current Project id (may be empty) |
158
+ | `threadId` | Current Thread id |
159
+ | `conversationId` | Current Conversation id |
160
+ | `messageId` | Optional message id |
161
+ | `threadPath` | Optional Thread checkout path |
162
+
163
+ ### `context.notes`
164
+
165
+ Project-scoped durable notes:
166
+
167
+ - `list()` — note metadata
168
+ - `read(name, offset?)` — paged content, or `null` if missing
169
+ - `write(name, content)` — replace; empty content clears; metadata or `null` when cleared
170
+ - `append(name, content)` — append a record
171
+ - `search(query)` — name and content excerpts
172
+
173
+ ### `context.chat`
174
+
175
+ - `titleMaxLength` — max characters for a chat title
176
+ - `normalizeTitle(title)` — normalize a model-supplied title for storage
177
+
178
+ ### `context.mcp`
179
+
180
+ ```js
181
+ await context.mcp.connectRemoteServer(
182
+ { serverName, url, transport: "streamableHttp" | "sse", useOAuth },
183
+ options,
184
+ );
185
+ // → { serverName, state, tools, authenticated, error? }
186
+ ```
187
+
188
+ Saves and discovers a remote MCP server for the current project. The active run's tool set stays fixed; discovered MCP tools are available on the next message
189
+ in the same conversation. Use the deferred `connect_mcp` Skill instead of calling
190
+ this host API directly from user-facing replies. Never ask for bearer tokens.
191
+
192
+ ### `context.web`
193
+
194
+ ```js
195
+ await context.web.search({ query, numResults, type, includeDomains, excludeDomains, signal });
196
+ ```
197
+
198
+ ### `context.email`
199
+
200
+ ```js
201
+ await context.email.sendToSelf({ subject, body });
202
+ // → { status: "sent", to } | { status: "not-signed-in" } | { status: "failed", message }
203
+ ```
204
+
205
+ Sends an email to the signed-in Tarsk account (the auth service resolves the
206
+ recipient from the sign-in token, so the mail can only reach that user's own
207
+ address). The Skill formats every reply, including the signed-out "log in to
208
+ Tarsk" copy.
209
+
210
+ ### `context.util`
211
+
212
+ ```js
213
+ context.util.maxBytes;
214
+ context.util.formatSize(bytes);
215
+ context.util.truncateHead(text, { maxLines, maxBytes });
216
+ context.util.compressFindPaths(paths); // { text, applied, banner }
217
+ context.util.compressGrepContent(lines); // { text, applied, banner }
218
+ context.util.compressGrepCount(lines);
219
+ context.util.compressGrepFiles(lines);
220
+ context.util.compressUnifiedDiffPreservingFootnotes(text); // { text, applied }
221
+ await context.util.withAbort(signal, async (isAborted) => {
222
+ /* … */
223
+ });
224
+ ```
225
+
226
+ ### `context.history`
227
+
228
+ ```js
229
+ context.history.available
230
+ await context.history.search({ query, allConversations?, limit? })
231
+ await context.history.read({ entryId, allConversations?, offset? })
232
+ ```
233
+
234
+ ### `context.jobs`
235
+
236
+ Owner-scoped background jobs (bash `run_in_background`). Kill is a privileged host op.
237
+
238
+ ```js
239
+ context.jobs.available
240
+ context.jobs.list()
241
+ context.jobs.readOutput(jobId, { offsetLines?, limitLines? })
242
+ context.jobs.kill(jobId) // { ok, outcome, status, exitCode } | { ok: false }
243
+ ```
244
+
245
+ ### `context.todos`
246
+
247
+ Thread-scoped todos and progress.txt append:
248
+
249
+ ```js
250
+ await context.todos.list()
251
+ await context.todos.add(descriptions, assignedTo?)
252
+ await context.todos.update(ids, { status?, assignedTo?, passes? })
253
+ await context.todos.remove(ids)
254
+ await context.todos.appendLearnings(text)
255
+ ```
256
+
257
+ ### `context.fs`
258
+
259
+ Secure filesystem (cwd containment). Grow this as more file Tools migrate.
260
+
261
+ ```js
262
+ await context.fs.writeText(path, content, { signal? })
263
+ // → { path, absolutePath, previousBytes, nextBytes, supersession }
264
+ await context.fs.glob(pattern, { path?, limit?, signal? })
265
+ // → { paths, limit, resultLimitReached }
266
+ await context.fs.applyEdit(args, { signal? }) // structured; Skill formats copy
267
+ await context.fs.read(args, { signal?, onUpdate?, toolCallId? })
268
+ // → structured (text/directory/image/unchanged/raw); Skill formats copy
269
+ await context.fs.grep(args, { signal? })
270
+ // → structured rows; Skill formats banners / empty tips / pagination
271
+ ```
272
+
273
+ ### `context.shell` / `context.ask` / `context.web.fetch`
274
+
275
+ ```js
276
+ await context.shell.run(args, options)
277
+ // → structured (completed | background | preformatted); Skill formats notices
278
+ context.shell.resolveExit({
279
+ exitCode, executionCommand, outputText, fullOutput, threadId?,
280
+ }) // soft-success / soft-fail classification (policy stays in host)
281
+ context.ask.normalize(args); // coerce legacy ask_user shapes
282
+ await context.ask.wait(questions, options); // blocking gate + credentials; needs toolCallId
283
+ await context.web.fetch(args, options); // fetch (allowlist gate)
284
+ ```
285
+
286
+ ### `context.observations` (DB only)
287
+
288
+ ```js
289
+ context.observations.limits;
290
+ await context.observations.resolveId(rawId);
291
+ await context.observations.fetch(id); // { id, content, toolName } | null
292
+ await context.observations.recordRetrieved(bytes);
293
+ ```
294
+
295
+ Paging and model copy live in the `get_observation` Skill.
296
+
297
+ ### Other host executors
298
+
299
+ ```js
300
+ await context.images.searchAndSave(args, options); // structured; Skill formats
301
+ await context.images.generate(args, options); // structured; Skill formats
302
+ await context.projects.query(args); // structured; Skill formats
303
+ await context.projects.launch(args); // structured; Skill formats
304
+ await context.tasks.query(args); // structured; Skill formats
305
+ await context.browser.run(args, options); // structured payload; Skill formats
306
+ await context.js.run(args, options); // structured ok / trivial_read; Skill formats
307
+ await context.skillsCatalog.read(args); // structured; Skill formats
308
+ await context.skillsCatalog.executeScript(args, options); // structured; Skill formats
309
+ await context.skillsCatalog.readReference(args); // structured; Skill formats
310
+ ```
311
+
312
+ Every shipped Tool skill uses a dedicated API above (or pure script logic).
313
+ `propose_branch` is Slack plan-chat only.
314
+
315
+ ## Worked example (new Tool skill)
316
+
317
+ `.agents/skills/echo-tool/SKILL.md`:
318
+
319
+ ```yaml
320
+ ---
321
+ name: echo-tool
322
+ description: Echoes a message back via a small custom Tool.
323
+ version: 1.0.0
324
+ tools:
325
+ - echo_message
326
+ ---
327
+ # Echo
328
+
329
+ Publishes `echo_message`. See `tarsk-agent` for the runtime contract.
330
+ ```
331
+
332
+ `.agents/skills/echo-tool/scripts/echo_message.js`:
333
+
334
+ ```js
335
+ export const description =
336
+ "Echo a short message back to the conversation. Use for smoke-testing Tool skills.";
337
+
338
+ export const parameters = {
339
+ type: "object",
340
+ properties: {
341
+ message: { type: "string", description: "Text to echo" },
342
+ },
343
+ required: ["message"],
344
+ };
345
+
346
+ export async function execute(args, context) {
347
+ const text = String(args.message ?? "");
348
+ return {
349
+ content: [{ type: "text", text: `echo (${context.cwd}): ${text}` }],
350
+ details: undefined,
351
+ };
352
+ }
353
+ ```
354
+
355
+ ### Wrapping a host Tool (change description / formatting)
356
+
357
+ `.agents/skills/tarsk-bash/scripts/bash.js` (project override after export):
358
+
359
+ ```js
360
+ export const description = "/* your revised guidance for the model */";
361
+
362
+ export const parameters = {/* keep or tighten the JSON Schema */};
363
+
364
+ export async function execute(args, context, options) {
365
+ const structured = await context.shell.run(args, options);
366
+ // Format completed / background / preformatted + resolveExit — see bundled bash.js
367
+ // …
368
+ }
369
+ ```
370
+
371
+ After editing a project Tool skill, the next run reload picks it up (no restart
372
+ required beyond the next tool load for that chat).