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.
- package/README.md +63 -24
- package/dist/bundled-skills/email-me/SKILL.md +15 -0
- package/dist/bundled-skills/email-me/scripts/__tests__/email_me.test.js +64 -0
- package/dist/bundled-skills/email-me/scripts/email_me.js +45 -0
- package/dist/bundled-skills/handoff/SKILL.md +19 -0
- package/dist/bundled-skills/tarsk-agent/SKILL.md +372 -0
- package/dist/bundled-skills/tarsk-ask-user/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-ask-user/scripts/ask_user.js +101 -0
- package/dist/bundled-skills/tarsk-bash/SKILL.md +17 -0
- package/dist/bundled-skills/tarsk-bash/scripts/bash.js +248 -0
- package/dist/bundled-skills/tarsk-browser/SKILL.md +17 -0
- package/dist/bundled-skills/tarsk-browser/scripts/browser.js +252 -0
- package/dist/bundled-skills/tarsk-chat-title/SKILL.md +14 -0
- package/dist/bundled-skills/tarsk-chat-title/scripts/chat_title.js +37 -0
- package/dist/bundled-skills/tarsk-connect-mcp/SKILL.md +23 -0
- package/dist/bundled-skills/tarsk-connect-mcp/scripts/__tests__/connect_mcp.test.js +68 -0
- package/dist/bundled-skills/tarsk-connect-mcp/scripts/connect_mcp.js +119 -0
- package/dist/bundled-skills/tarsk-create-project/SKILL.md +25 -0
- package/dist/bundled-skills/tarsk-create-project/scripts/__tests__/create_project.test.js +94 -0
- package/dist/bundled-skills/tarsk-create-project/scripts/create_project.js +88 -0
- package/dist/bundled-skills/tarsk-edit/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-edit/scripts/edit.js +118 -0
- package/dist/bundled-skills/tarsk-execute-skill-script/SKILL.md +19 -0
- package/dist/bundled-skills/tarsk-execute-skill-script/scripts/execute_skill_script.js +77 -0
- package/dist/bundled-skills/tarsk-fetch/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-fetch/scripts/fetch.js +38 -0
- package/dist/bundled-skills/tarsk-find/SKILL.md +16 -0
- package/dist/bundled-skills/tarsk-find/scripts/find.js +78 -0
- package/dist/bundled-skills/tarsk-find-images/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-find-images/scripts/find_images.js +78 -0
- package/dist/bundled-skills/tarsk-generate-image/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-generate-image/scripts/generate_image.js +55 -0
- package/dist/bundled-skills/tarsk-get-observation/SKILL.md +19 -0
- package/dist/bundled-skills/tarsk-get-observation/scripts/get_observation.js +293 -0
- package/dist/bundled-skills/tarsk-grep/SKILL.md +16 -0
- package/dist/bundled-skills/tarsk-grep/scripts/grep.js +174 -0
- package/dist/bundled-skills/tarsk-history/SKILL.md +15 -0
- package/dist/bundled-skills/tarsk-history/scripts/history.js +68 -0
- package/dist/bundled-skills/tarsk-improve/SKILL.md +232 -0
- package/dist/bundled-skills/tarsk-improve/references/signals.md +16 -0
- package/dist/bundled-skills/tarsk-improve/scripts/durable-runs.ts +635 -0
- package/dist/bundled-skills/tarsk-improve/scripts/ensure-exported.ts +238 -0
- package/dist/bundled-skills/tarsk-improve/scripts/export-tool-skills-lib.ts +299 -0
- package/dist/bundled-skills/tarsk-improve/scripts/summarize-session.ts +126 -0
- package/dist/bundled-skills/tarsk-jobs/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-jobs/scripts/job_kill.js +45 -0
- package/dist/bundled-skills/tarsk-jobs/scripts/job_list.js +64 -0
- package/dist/bundled-skills/tarsk-jobs/scripts/job_output.js +66 -0
- package/dist/bundled-skills/tarsk-notes/SKILL.md +17 -0
- package/dist/bundled-skills/tarsk-notes/scripts/notes.js +86 -0
- package/dist/bundled-skills/tarsk-projects/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-projects/scripts/projects.js +54 -0
- package/dist/bundled-skills/tarsk-prompt-project/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-prompt-project/scripts/prompt_project.js +58 -0
- package/dist/bundled-skills/tarsk-propose-branch/SKILL.md +16 -0
- package/dist/bundled-skills/tarsk-propose-branch/scripts/propose_branch.js +45 -0
- package/dist/bundled-skills/tarsk-read/SKILL.md +17 -0
- package/dist/bundled-skills/tarsk-read/scripts/read.js +331 -0
- package/dist/bundled-skills/tarsk-read-skill/SKILL.md +16 -0
- package/dist/bundled-skills/tarsk-read-skill/scripts/read_skill.js +37 -0
- package/dist/bundled-skills/tarsk-read-skill-reference/SKILL.md +19 -0
- package/dist/bundled-skills/tarsk-read-skill-reference/scripts/read_skill_reference.js +60 -0
- package/dist/bundled-skills/tarsk-run-js/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-run-js/scripts/run_js.js +192 -0
- package/dist/bundled-skills/tarsk-tasks/SKILL.md +18 -0
- package/dist/bundled-skills/tarsk-tasks/scripts/tasks.js +96 -0
- package/dist/bundled-skills/tarsk-todo/SKILL.md +16 -0
- package/dist/bundled-skills/tarsk-todo/scripts/todo.js +165 -0
- package/dist/bundled-skills/tarsk-web-search/SKILL.md +15 -0
- package/dist/bundled-skills/tarsk-web-search/scripts/web_search.js +120 -0
- package/dist/bundled-skills/tarsk-write/SKILL.md +16 -0
- package/dist/bundled-skills/tarsk-write/scripts/write.js +57 -0
- package/dist/index.js +217754 -211927
- package/dist/public/assets/{alert-dialog-DVaEQlVa.js → alert-dialog-BcZULJsX.js} +1 -1
- package/dist/public/assets/api-8Rp2LlXt.js +1 -0
- package/dist/public/assets/api-Cp9I7CxD.js +2 -0
- package/dist/public/assets/{async-error-boundary-DH6Sqgmt.js → async-error-boundary-CFVUPiuG.js} +1 -1
- package/dist/public/assets/browser-tab-CPPorbL6.js +12 -0
- package/dist/public/assets/button-DDaJhJP1.js +1 -0
- package/dist/public/assets/{card-BkOGFps5.js → card-DAc45J1v.js} +1 -1
- package/dist/public/assets/chat-dock-context-DbiJNr3O.js +1 -0
- package/dist/public/assets/chat-handlers-context-DYU2LQ5V.js +9 -0
- package/dist/public/assets/commit-dialog-DPaci3dp.js +1 -0
- package/dist/public/assets/{commit-error-dialog-D3S6kRVr.js → commit-error-dialog-Dnlkgb_H.js} +1 -1
- package/dist/public/assets/{commit-method-fields-BEKfSRyW.js → commit-method-fields-Xt3vbwUg.js} +1 -1
- package/dist/public/assets/conversation-history-view-CqIugfyO.js +1 -0
- package/dist/public/assets/{create-project-dialog-nquqlloK.js → create-project-dialog-DStWPoDE.js} +2 -2
- package/dist/public/assets/{create-project-workspace-C4tXAUWJ.js → create-project-workspace-CJ94yHAB.js} +2 -2
- package/dist/public/assets/create-repo-dialog-B_QiEz-v.js +1 -0
- package/dist/public/assets/{delete-confirm-dialog-SpYpU1AX.js → delete-confirm-dialog-D1N86piR.js} +1 -1
- package/dist/public/assets/dialog-D_12AsZd.js +1 -0
- package/dist/public/assets/diff-view-4koPcOcE.js +4 -0
- package/dist/public/assets/{dist-NcyjV9Gu.js → dist-2xH_pFmV.js} +1 -1
- package/dist/public/assets/{dist-BTu7PDzc.js → dist-AbkJBHH5.js} +1 -1
- package/dist/public/assets/{dist-lFBinzor.js → dist-B-h6Wj39.js} +1 -1
- package/dist/public/assets/dist-CgbWuuq4.js +1 -0
- package/dist/public/assets/{dist-f54JuzFV.js → dist-DOz2WXwX.js} +1 -1
- package/dist/public/assets/{dist-CqrmQxmV.js → dist-DfnQ9YJh.js} +1 -1
- package/dist/public/assets/{dist-BOfRC57H.js → dist-JGbQ_EJY.js} +1 -1
- package/dist/public/assets/{dist-ButPmyjr.js → dist-pCVg1Jdl.js} +1 -1
- package/dist/public/assets/dist-v_MvKS2-.js +2 -0
- package/dist/public/assets/{es2015-CE7VcoOH.js → es2015-eNVkKfFF.js} +1 -1
- package/dist/public/assets/{explorer-file-drop-CEbBlDEp.js → explorer-file-drop-DAP7ha-E.js} +1 -1
- package/dist/public/assets/{explorer-monaco-editor-Bgo9Y1cP.js → explorer-monaco-editor-ChJZBFy5.js} +1 -1
- package/dist/public/assets/explorer-tab-view-Bt9hRZUm.js +2 -0
- package/dist/public/assets/explorer-tree-CAs89lPz.js +1 -0
- package/dist/public/assets/{explorer-view-BuTa_0Uq.js → explorer-view-B1JuejkU.js} +3 -3
- package/dist/public/assets/git-history-dialog-Dqj1p35g.js +1 -0
- package/dist/public/assets/index-CcAwxnT5.js +97 -0
- package/dist/public/assets/index-dNrgKdYv.css +1 -0
- package/dist/public/assets/{label-C31qF5zZ.js → label-BCs5CZEs.js} +1 -1
- package/dist/public/assets/markdown-renderer-DQONI6WG.js +10 -0
- package/dist/public/assets/{mcp-manager-C3K_62H2.js → mcp-manager-D2FG-h2e.js} +1 -1
- package/dist/public/assets/{minus-l6BdrAEk.js → minus-CgQcbBQT.js} +1 -1
- package/dist/public/assets/{model-list-controls-DwW8S18v.js → model-list-controls-B6ofHWh3.js} +1 -1
- package/dist/public/assets/onboarding-dialog-DAut3X4K.js +1 -0
- package/dist/public/assets/{pill-tabs-CmvvHdKG.js → pill-tabs-BAhOHad7.js} +1 -1
- package/dist/public/assets/progress-indicator-hJ74ac5W.js +1 -0
- package/dist/public/assets/project-coding-view-B2FpHeiO.js +1 -0
- package/dist/public/assets/{project-danger-zone-view-D18k4pUF.js → project-danger-zone-view-BqP1dcRT.js} +1 -1
- package/dist/public/assets/{project-env-vars-view-BWFqoaFD.js → project-env-vars-view-zhigkQFG.js} +1 -1
- package/dist/public/assets/project-model-aliases-view-APAVFfym.js +1 -0
- package/dist/public/assets/project-settings-view-FnK-LRsv.js +1 -0
- package/dist/public/assets/project-tools-view-Dmp5ViRC.js +1 -0
- package/dist/public/assets/providers-list-view-Clbp73Hh.js +1 -0
- package/dist/public/assets/pull-request-dialog-D40BQPMk.js +1 -0
- package/dist/public/assets/pull-with-changes-dialog-pkXK-VP2.js +1 -0
- package/dist/public/assets/push-before-pr-dialog-DH91JHEC.js +1 -0
- package/dist/public/assets/query-keys-CcnonAAG.js +1 -0
- package/dist/public/assets/remote-media-url-C-GdJb-D.js +1 -0
- package/dist/public/assets/{scroll-area-BWc4OPsj.js → scroll-area-DGF9wUqQ.js} +1 -1
- package/dist/public/assets/{select-B6RizwDW.js → select-DMcNYwgt.js} +1 -1
- package/dist/public/assets/settings-general-tabs-view-DBZQbihJ.js +2 -0
- package/dist/public/assets/settings-general-view-0dhBET2R.js +1 -0
- package/dist/public/assets/{settings-list-D35rpAof.js → settings-list-Co3JPr9w.js} +1 -1
- package/dist/public/assets/settings-logs-view-DvHXUDko.js +5 -0
- package/dist/public/assets/settings-mcp-servers-view-414Dt5py.js +5 -0
- package/dist/public/assets/settings-models-view-ByeR7Enb.js +1 -0
- package/dist/public/assets/settings-plugins-view-8te2MPyh.js +2 -0
- package/dist/public/assets/settings-providers-view-BAuv9gam.js +2 -0
- package/dist/public/assets/settings-remote-machines-view-CHyywazU.js +1 -0
- package/dist/public/assets/settings-setup-view-Btp46Vh_.js +2 -0
- package/dist/public/assets/settings-skills-view-BNVx4bZl.js +2 -0
- package/dist/public/assets/{settings-slack-view-DkclyaBc.js → settings-slack-view-Caly5yGt.js} +1 -1
- package/dist/public/assets/settings-slash-commands-view-m6mp1knu.js +1 -0
- package/dist/public/assets/{settings-statistics-view-B03ZZjEy.js → settings-statistics-view-BnOxr4sZ.js} +1 -1
- package/dist/public/assets/settings-storage-view-Dg8xfpTG.js +1 -0
- package/dist/public/assets/settings-subagents-view-CucwEk2A.js +2 -0
- package/dist/public/assets/settings-system-prompt-view-CEDU2saT.js +1 -0
- package/dist/public/assets/{settings-tab-bar-ajzyt79U.js → settings-tab-bar-CdIbQ0WI.js} +1 -1
- package/dist/public/assets/settings-view-XcJhRclT.js +2 -0
- package/dist/public/assets/{slug-utils-D2jhPz-o.js → slug-utils-CO6nui1C.js} +1 -1
- package/dist/public/assets/square-CtxvwmM2.js +1 -0
- package/dist/public/assets/store-W78TGOIO.js +8 -0
- package/dist/public/assets/{table-C3Hc0Gwy.js → table-CQMqIW_-.js} +1 -1
- package/dist/public/assets/task-utils-Cnq9Eszt.js +1 -0
- package/dist/public/assets/tasks-view-B8_jkq_a.js +1 -0
- package/dist/public/assets/{terminal-panel-DCKqScJu.js → terminal-panel-xoLVfA-h.js} +2 -2
- package/dist/public/assets/{toggle-group-DqSxGqvP.js → toggle-group-CPmseZfb.js} +1 -1
- package/dist/public/assets/{tooltip-CJKJfu0l.js → tooltip-CqwCZ7wt.js} +1 -1
- package/dist/public/assets/{use-account-settings-query-AUeOqKvo.js → use-account-settings-query-D_qL1I4w.js} +1 -1
- package/dist/public/assets/{use-active-dock-panel-instance-BvAhUd_V.js → use-active-dock-panel-instance-kmJOnmL7.js} +1 -1
- package/dist/public/assets/use-browser-overlay-block-CO1pUEAZ.js +1 -0
- package/dist/public/assets/{use-git-check-B_5Jak2s.js → use-git-check-BD9gdXpK.js} +1 -1
- package/dist/public/assets/{use-installed-ai-files-iy_AB0dN.js → use-installed-ai-files-Nn-sN_V2.js} +1 -1
- package/dist/public/assets/use-open-chat-dock-panel-CXzpgxVs.js +1 -0
- package/dist/public/assets/{use-projects-BmhAMgxB.js → use-projects-B0xTjTaA.js} +2 -2
- package/dist/public/assets/utils-CqsIXqSC.js +1 -0
- package/dist/public/assets/web-BNWoiS4w.js +1 -0
- package/dist/public/assets/web-C1tBQoCB.js +1 -0
- package/dist/public/assets/web-Dlo3GwCf.js +1 -0
- package/dist/public/assets/web-cJXG33sT.js +1 -0
- package/dist/public/fonts/schibsted-grotesk-latin-ext-wght-normal.woff2 +0 -0
- package/dist/public/fonts/schibsted-grotesk-latin-wght-normal.woff2 +0 -0
- package/dist/public/index.html +46 -46
- package/package.json +9 -9
- package/dist/public/assets/account-view-5q3pHEHY.js +0 -1
- package/dist/public/assets/ai-spinner-DHwhlk4j.js +0 -1
- package/dist/public/assets/api-BdebJfuN.js +0 -1
- package/dist/public/assets/api-COO2LfdU.js +0 -2
- package/dist/public/assets/browser-overlay-block-CiDtkfup.js +0 -1
- package/dist/public/assets/browser-tab-CVdYLmW5.js +0 -12
- package/dist/public/assets/button-Dp5XDZNR.js +0 -1
- package/dist/public/assets/chat-dock-context-ymLoO90X.js +0 -1
- package/dist/public/assets/checkbox-D-BV8-Z_.js +0 -1
- package/dist/public/assets/commit-dialog-CEbCFh1x.js +0 -1
- package/dist/public/assets/conversation-history-view-CVMD8hUU.js +0 -1
- package/dist/public/assets/create-repo-dialog-B5IE3pUJ.js +0 -1
- package/dist/public/assets/dialog-pHPeIGaB.js +0 -1
- package/dist/public/assets/diff-view-Cy6nPdX-.js +0 -4
- package/dist/public/assets/dist-D5vgS4RP.js +0 -2
- package/dist/public/assets/explorer-tab-view-C-8QZO9S.js +0 -2
- package/dist/public/assets/explorer-tree-HrLSFgcI.js +0 -1
- package/dist/public/assets/git-history-dialog-ClfF5IOn.js +0 -1
- package/dist/public/assets/index-BBLA5zVt.css +0 -1
- package/dist/public/assets/index-CalVAwXj.js +0 -104
- package/dist/public/assets/markdown-renderer-DXRBG7uP.js +0 -10
- package/dist/public/assets/onboarding-dialog-BtLy0wjC.js +0 -1
- package/dist/public/assets/progress-indicator-4zQXqOqP.js +0 -1
- package/dist/public/assets/project-coding-view-CyJwnJes.js +0 -1
- package/dist/public/assets/project-model-aliases-view-D3tYNkkM.js +0 -1
- package/dist/public/assets/project-settings-view-0oN9vFvD.js +0 -1
- package/dist/public/assets/project-tools-view-DT87KPjE.js +0 -1
- package/dist/public/assets/providers-list-view-DCnh0W-5.js +0 -1
- package/dist/public/assets/pull-request-dialog-BdJxYQwu.js +0 -1
- package/dist/public/assets/pull-with-changes-dialog-Do9x9neW.js +0 -1
- package/dist/public/assets/push-before-pr-dialog-C-9z2O0-.js +0 -1
- package/dist/public/assets/query-keys-BwswkbMn.js +0 -1
- package/dist/public/assets/remote-media-url-B8OFqxOM.js +0 -1
- package/dist/public/assets/settings-general-tabs-view-Dcek-ysB.js +0 -2
- package/dist/public/assets/settings-general-view-DhA2N6G5.js +0 -1
- package/dist/public/assets/settings-logs-view-eEUTIMeb.js +0 -5
- package/dist/public/assets/settings-mcp-servers-view-_oeuVkUe.js +0 -5
- package/dist/public/assets/settings-models-view-DW-ZmVup.js +0 -1
- package/dist/public/assets/settings-plugins-view-DTooco_c.js +0 -2
- package/dist/public/assets/settings-providers-view-CEeJkhg9.js +0 -2
- package/dist/public/assets/settings-remote-machines-view--UB8GlCK.js +0 -1
- package/dist/public/assets/settings-setup-view-DFL6DlYS.js +0 -2
- package/dist/public/assets/settings-skills-view-xS569-Kb.js +0 -2
- package/dist/public/assets/settings-slash-commands-view-DrCiayfq.js +0 -1
- package/dist/public/assets/settings-storage-view-CQnaVOt_.js +0 -1
- package/dist/public/assets/settings-subagents-view-DIctUJcE.js +0 -2
- package/dist/public/assets/settings-system-prompt-view-BMDbrFRR.js +0 -1
- package/dist/public/assets/settings-view-8M6sbGiX.js +0 -2
- package/dist/public/assets/store-CxUwqrZ5.js +0 -8
- package/dist/public/assets/task-utils-WAei2PDi.js +0 -1
- package/dist/public/assets/tasks-view-DKyqgGdE.js +0 -1
- package/dist/public/assets/use-browser-overlay-block-z9imTmiZ.js +0 -1
- package/dist/public/assets/use-open-chat-dock-panel-w3hc5Vxn.js +0 -1
- package/dist/public/assets/utils-mYB1USG6.js +0 -1
- package/dist/public/assets/web-C6Gm4nQ0.js +0 -1
- package/dist/public/assets/web-DFlyNg8o.js +0 -1
- package/dist/public/assets/web-DlEPs8Xe.js +0 -1
- package/dist/public/assets/web-Gx3xReQH.js +0 -1
- package/dist/public/backgrounds/arctic-tundra.avif +0 -0
- package/dist/public/backgrounds/autumn-leaves.avif +0 -0
- package/dist/public/backgrounds/coastal-cliff.avif +0 -0
- package/dist/public/backgrounds/floating-waterfall.avif +0 -0
- package/dist/public/backgrounds/forest-path.avif +0 -0
- package/dist/public/backgrounds/garden-path.avif +0 -0
- package/dist/public/backgrounds/glow-marsh.avif +0 -0
- package/dist/public/backgrounds/golden-wheat.avif +0 -0
- package/dist/public/backgrounds/moon-desert.avif +0 -0
- package/dist/public/backgrounds/night-pond.avif +0 -0
- package/dist/public/backgrounds/prairie-grassland.avif +0 -0
- package/dist/public/backgrounds/river-winding.avif +0 -0
- package/dist/public/backgrounds/salt-flat.avif +0 -0
- package/dist/public/backgrounds/salt-marsh.avif +0 -0
- package/dist/public/backgrounds/sandy-beach.avif +0 -0
- package/dist/public/backgrounds/snow-river.avif +0 -0
- package/dist/public/backgrounds/sunset-pond.avif +0 -0
- package/dist/public/fonts/plus-jakarta-sans-cyrillic-ext-wght-normal.woff2 +0 -0
- package/dist/public/fonts/plus-jakarta-sans-latin-ext-wght-normal.woff2 +0 -0
- package/dist/public/fonts/plus-jakarta-sans-latin-wght-normal.woff2 +0 -0
- 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
|
-
- **
|
|
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
|
|
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`
|
|
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`
|
|
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
|
|
63
|
-
|
|
|
64
|
-
| **git**
|
|
65
|
-
| **Node.js 18+** or **Bun** | Required for `npx tarsk`.
|
|
66
|
-
| **gh CLI** (optional)
|
|
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
|
|
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
|
-
|
|
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
|
|
92
|
+
Inside the application support directory:
|
|
79
93
|
|
|
80
|
-
- `tarsk.db` — SQLite database (projects, threads, conversations, settings)
|
|
81
|
-
- `data/{
|
|
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).
|