tsugite-cli 0.9.4__tar.gz → 0.11.0__tar.gz

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 (352) hide show
  1. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/.gitignore +4 -1
  2. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/PKG-INFO +103 -114
  3. tsugite_cli-0.11.0/README.md +148 -0
  4. tsugite_cli-0.11.0/docs/agents.md +273 -0
  5. tsugite_cli-0.11.0/docs/secrets.md +136 -0
  6. tsugite_cli-0.11.0/docs/test_agents/prefresh_readme.md +16 -0
  7. tsugite_cli-0.11.0/docs/test_agents/template_test.md +14 -0
  8. tsugite_cli-0.11.0/docs/test_agents/test_agent.md +15 -0
  9. tsugite_cli-0.11.0/docs/test_agents/test_steps.md +8 -0
  10. tsugite_cli-0.11.0/mise.toml +22 -0
  11. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/pyproject.toml +8 -4
  12. tsugite_cli-0.11.0/scripts/backfill_usage.py +98 -0
  13. tsugite_cli-0.11.0/scripts/update_model_registry.py +189 -0
  14. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/conftest.py +39 -29
  15. tsugite_cli-0.11.0/tests/core/test_agent.py +732 -0
  16. tsugite_cli-0.11.0/tests/core/test_agent_context_tokens.py +188 -0
  17. tsugite_cli-0.11.0/tests/core/test_agent_ui_events.py +421 -0
  18. tsugite_cli-0.11.0/tests/core/test_content_blocks.py +269 -0
  19. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/daemon/test_http_adapter.py +120 -40
  20. tsugite_cli-0.11.0/tests/daemon/test_session_metadata_api.py +221 -0
  21. tsugite_cli-0.11.0/tests/e2e/conftest.py +162 -0
  22. tsugite_cli-0.11.0/tests/e2e/test_auth.py +27 -0
  23. tsugite_cli-0.11.0/tests/e2e/test_chat.py +69 -0
  24. tsugite_cli-0.11.0/tests/e2e/test_context_bar.py +30 -0
  25. tsugite_cli-0.11.0/tests/e2e/test_history.py +148 -0
  26. tsugite_cli-0.11.0/tests/e2e/test_page_load.py +37 -0
  27. tsugite_cli-0.11.0/tests/e2e/test_prompt_inspector.py +53 -0
  28. tsugite_cli-0.11.0/tests/e2e/test_sessions.py +41 -0
  29. tsugite_cli-0.11.0/tests/e2e/test_sidebar_redesign.py +73 -0
  30. tsugite_cli-0.11.0/tests/e2e/test_sse_metadata.py +31 -0
  31. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_builtin_agent_paths.py +14 -0
  32. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_cache_control.py +1 -4
  33. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_chat_cli.py +23 -5
  34. tsugite_cli-0.11.0/tests/test_claude_code_attachments.py +83 -0
  35. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_claude_code_provider.py +38 -108
  36. tsugite_cli-0.11.0/tests/test_completion_callbacks.py +479 -0
  37. tsugite_cli-0.11.0/tests/test_daemon_auth.py +199 -0
  38. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_compaction_scheduler.py +10 -27
  39. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_history_persistence.py +1 -1
  40. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_memory.py +74 -58
  41. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_history.py +25 -0
  42. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_history_models.py +25 -0
  43. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_hooks.py +3 -10
  44. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_http_tools.py +130 -2
  45. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_kvstore.py +1 -0
  46. tsugite_cli-0.11.0/tests/test_model_registry.py +26 -0
  47. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_models.py +24 -1
  48. tsugite_cli-0.11.0/tests/test_prompt_snapshot.py +127 -0
  49. tsugite_cli-0.11.0/tests/test_provider_registry.py +53 -0
  50. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_reasoning_models.py +16 -29
  51. tsugite_cli-0.11.0/tests/test_secret_access_event.py +69 -0
  52. tsugite_cli-0.11.0/tests/test_secrets.py +450 -0
  53. tsugite_cli-0.11.0/tests/test_session_metadata.py +270 -0
  54. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_session_orchestrator_tools.py +8 -6
  55. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_tmux_tools.py +1 -3
  56. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/__init__.py +0 -4
  57. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_preparation.py +17 -10
  58. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_runner/__init__.py +4 -0
  59. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_runner/helpers.py +10 -0
  60. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_runner/history_integration.py +12 -12
  61. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_runner/models.py +2 -3
  62. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_runner/runner.py +61 -34
  63. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_runner/validation.py +1 -0
  64. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/url.py +2 -12
  65. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_agents/default.md +38 -0
  66. tsugite_cli-0.11.0/tsugite/builtin_skills/.gitkeep +0 -0
  67. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/__init__.py +6 -0
  68. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/chat.py +5 -0
  69. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/config.py +0 -1
  70. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/daemon.py +57 -0
  71. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/history.py +3 -1
  72. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/init.py +16 -47
  73. tsugite_cli-0.11.0/tsugite/cli/models.py +80 -0
  74. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/run.py +17 -4
  75. tsugite_cli-0.11.0/tsugite/cli/secrets.py +51 -0
  76. tsugite_cli-0.11.0/tsugite/cli/usage.py +134 -0
  77. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/validate.py +1 -1
  78. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/config.py +10 -0
  79. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/__init__.py +1 -1
  80. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/agent.py +245 -331
  81. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/claude_code.py +1 -1
  82. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/executor.py +9 -5
  83. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/adapters/base.py +93 -56
  84. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/adapters/discord.py +38 -6
  85. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/adapters/http.py +418 -43
  86. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/adapters/scheduler_adapter.py +114 -6
  87. tsugite_cli-0.11.0/tsugite/daemon/auth.py +150 -0
  88. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/commands.py +35 -2
  89. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/compaction_scheduler.py +1 -1
  90. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/config.py +0 -5
  91. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/gateway.py +43 -12
  92. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/memory.py +22 -60
  93. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/scheduler.py +4 -0
  94. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/session_runner.py +90 -11
  95. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/session_store.py +172 -29
  96. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/css/responsive.css +25 -0
  97. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/css/styles.css +84 -2
  98. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/index.html +445 -97
  99. tsugite_cli-0.11.0/tsugite/daemon/web/js/api.js +97 -0
  100. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/app.js +58 -25
  101. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/utils.js +20 -2
  102. tsugite_cli-0.11.0/tsugite/daemon/web/js/views/conversation/attachments.js +96 -0
  103. tsugite_cli-0.11.0/tsugite/daemon/web/js/views/conversation/history.js +173 -0
  104. tsugite_cli-0.11.0/tsugite/daemon/web/js/views/conversation/input.js +143 -0
  105. tsugite_cli-0.11.0/tsugite/daemon/web/js/views/conversation/sessions.js +198 -0
  106. tsugite_cli-0.11.0/tsugite/daemon/web/js/views/conversation/streaming.js +255 -0
  107. tsugite_cli-0.11.0/tsugite/daemon/web/js/views/conversations.js +268 -0
  108. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/views/schedules.js +29 -9
  109. tsugite_cli-0.11.0/tsugite/daemon/web/js/views/usage.js +65 -0
  110. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/events/__init__.py +5 -0
  111. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/events/base.py +6 -0
  112. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/events/events.py +21 -1
  113. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/events/helpers.py +11 -0
  114. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/history/models.py +4 -3
  115. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/history/storage.py +8 -2
  116. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/kvstore/__init__.py +1 -0
  117. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/md_agents.py +14 -3
  118. tsugite_cli-0.11.0/tsugite/models.py +158 -0
  119. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/plugins.py +3 -1
  120. tsugite_cli-0.11.0/tsugite/providers/__init__.py +100 -0
  121. tsugite_cli-0.11.0/tsugite/providers/anthropic.py +301 -0
  122. tsugite_cli-0.11.0/tsugite/providers/base.py +92 -0
  123. tsugite_cli-0.11.0/tsugite/providers/claude_code.py +257 -0
  124. tsugite_cli-0.11.0/tsugite/providers/model_cache.py +126 -0
  125. tsugite_cli-0.11.0/tsugite/providers/model_registry.py +46 -0
  126. tsugite_cli-0.11.0/tsugite/providers/ollama.py +76 -0
  127. tsugite_cli-0.11.0/tsugite/providers/openai_compat.py +314 -0
  128. tsugite_cli-0.11.0/tsugite/providers/openrouter.py +69 -0
  129. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/schemas/agent.schema.json +16 -2
  130. tsugite_cli-0.11.0/tsugite/secrets/__init__.py +82 -0
  131. tsugite_cli-0.11.0/tsugite/secrets/backend.py +11 -0
  132. tsugite_cli-0.11.0/tsugite/secrets/env.py +25 -0
  133. tsugite_cli-0.11.0/tsugite/secrets/exec.py +75 -0
  134. tsugite_cli-0.11.0/tsugite/secrets/file.py +43 -0
  135. tsugite_cli-0.11.0/tsugite/secrets/masking.py +31 -0
  136. tsugite_cli-0.11.0/tsugite/secrets/registry.py +62 -0
  137. tsugite_cli-0.11.0/tsugite/secrets/sqlite.py +121 -0
  138. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/__init__.py +8 -6
  139. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/http.py +28 -4
  140. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/kv.py +5 -0
  141. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/schedule.py +16 -0
  142. tsugite_cli-0.11.0/tsugite/tools/scratchpad.py +101 -0
  143. tsugite_cli-0.11.0/tsugite/tools/secrets.py +53 -0
  144. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/sessions.py +46 -10
  145. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/skills.py +5 -2
  146. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/tmux.py +2 -7
  147. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/chat.py +5 -2
  148. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/jsonl.py +11 -0
  149. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/repl_chat.py +17 -4
  150. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/repl_commands.py +1 -0
  151. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/repl_handler.py +15 -10
  152. tsugite_cli-0.11.0/tsugite/usage/__init__.py +5 -0
  153. tsugite_cli-0.11.0/tsugite/usage/store.py +222 -0
  154. tsugite_cli-0.11.0/tsugite/user_agent.py +38 -0
  155. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/utils.py +20 -1
  156. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/uv.lock +218 -333
  157. tsugite_cli-0.9.4/README.md +0 -161
  158. tsugite_cli-0.9.4/tests/core/test_agent.py +0 -782
  159. tsugite_cli-0.9.4/tests/core/test_agent_ui_events.py +0 -434
  160. tsugite_cli-0.9.4/tests/core/test_content_blocks.py +0 -340
  161. tsugite_cli-0.9.4/tests/test_claude_code_attachments.py +0 -245
  162. tsugite_cli-0.9.4/tsugite/daemon/web/js/api.js +0 -54
  163. tsugite_cli-0.9.4/tsugite/daemon/web/js/views/conversations.js +0 -987
  164. tsugite_cli-0.9.4/tsugite/models.py +0 -282
  165. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/.github/copilot-instructions.md +0 -0
  166. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/.github/workflows/ci.yml +0 -0
  167. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/.github/workflows/docker-publish.yml +0 -0
  168. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/.github/workflows/pypi-publish.yml +0 -0
  169. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/AGENTS.md +0 -0
  170. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/CLAUDE.md +0 -0
  171. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/LICENSE +0 -0
  172. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/scripts/regenerate_schema.py +0 -0
  173. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/README.md +0 -0
  174. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/__init__.py +0 -0
  175. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/core/__init__.py +0 -0
  176. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/core/test_executor.py +0 -0
  177. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/core/test_memory.py +0 -0
  178. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/core/test_proxy.py +0 -0
  179. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/core/test_sandbox.py +0 -0
  180. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/core/test_subprocess_executor.py +0 -0
  181. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/core/test_tools.py +0 -0
  182. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/daemon/__init__.py +0 -0
  183. /tsugite_cli-0.9.4/tsugite/builtin_agents/.gitkeep → /tsugite_cli-0.11.0/tests/e2e/__init__.py +0 -0
  184. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/events/test_event_consolidation.py +0 -0
  185. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/smoke_test.sh +0 -0
  186. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_agent_file_hot_loading.py +0 -0
  187. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_agent_inheritance.py +0 -0
  188. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_agent_parser.py +0 -0
  189. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_agent_sessions.py +0 -0
  190. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_agent_skills.py +0 -0
  191. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_agent_utils.py +0 -0
  192. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_agents_tool.py +0 -0
  193. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_attachment_deduplication.py +0 -0
  194. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_attachments.py +0 -0
  195. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_auto_context_handler.py +0 -0
  196. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_auto_discovery.py +0 -0
  197. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_background_task_status.py +0 -0
  198. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_background_tasks.py +0 -0
  199. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_builtin_agents.py +0 -0
  200. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_chat_error_handling.py +0 -0
  201. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_cli.py +0 -0
  202. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_cli_arguments.py +0 -0
  203. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_cli_rendering.py +0 -0
  204. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_cli_subcommands.py +0 -0
  205. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_config.py +0 -0
  206. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_continuation.py +0 -0
  207. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_custom_shell_tools.py +0 -0
  208. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_custom_ui.py +0 -0
  209. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_config.py +0 -0
  210. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_push.py +0 -0
  211. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_scheduler.py +0 -0
  212. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_session_isolation.py +0 -0
  213. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_daemon_unified_sessions.py +0 -0
  214. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_discord_progress.py +0 -0
  215. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_error_display.py +0 -0
  216. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_file_references.py +0 -0
  217. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_file_tools.py +0 -0
  218. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_history_integration.py +0 -0
  219. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_history_performance.py +0 -0
  220. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_history_tools.py +0 -0
  221. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_interaction_backends.py +0 -0
  222. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_interactive_context.py +0 -0
  223. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_interactive_tool.py +0 -0
  224. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_jsonl_ui.py +0 -0
  225. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_list_agents_tool.py +0 -0
  226. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_mcp_client.py +0 -0
  227. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_mcp_server.py +0 -0
  228. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_multi_agent.py +0 -0
  229. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_multistep_agents.py +0 -0
  230. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_orchestrator_heartbeat.py +0 -0
  231. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_plugins.py +0 -0
  232. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_renderer.py +0 -0
  233. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_rendering_scenarios.py +0 -0
  234. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_repl_commands.py +0 -0
  235. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_repl_completer.py +0 -0
  236. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_repl_handler.py +0 -0
  237. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_retry_system.py +0 -0
  238. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_run_if.py +0 -0
  239. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_schedule_model_override.py +0 -0
  240. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_scheduler_history_injection.py +0 -0
  241. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_schema.py +0 -0
  242. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_security_phase1.py +0 -0
  243. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_send_message.py +0 -0
  244. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_skill_discovery.py +0 -0
  245. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_skill_tools.py +0 -0
  246. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_stdin.py +0 -0
  247. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_subagent_subprocess.py +0 -0
  248. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_tool_directives.py +0 -0
  249. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_tool_registry.py +0 -0
  250. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_workspace_auto_continue.py +0 -0
  251. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_workspace_cwd.py +0 -0
  252. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tests/test_workspace_discovery.py +0 -0
  253. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_inheritance.py +0 -0
  254. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_runner/metrics.py +0 -0
  255. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/agent_utils.py +0 -0
  256. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/__init__.py +0 -0
  257. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/auto_context.py +0 -0
  258. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/base.py +0 -0
  259. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/file.py +0 -0
  260. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/inline.py +0 -0
  261. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/storage.py +0 -0
  262. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/attachments/youtube.py +0 -0
  263. {tsugite_cli-0.9.4/tsugite/builtin_skills → tsugite_cli-0.11.0/tsugite/builtin_agents}/.gitkeep +0 -0
  264. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_agents/code_searcher.md +0 -0
  265. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_agents/file_searcher.md +0 -0
  266. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_agents/onboard.md +0 -0
  267. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/codebase_exploration.md +0 -0
  268. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/python_math.md +0 -0
  269. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/response_patterns.md +0 -0
  270. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/scheduling.md +0 -0
  271. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/skill_authoring.md +0 -0
  272. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/tsugite_agent_basics.md +0 -0
  273. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/tsugite_jinja_reference.md +0 -0
  274. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/builtin_skills/tsugite_skill_basics.md +0 -0
  275. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cache.py +0 -0
  276. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/agents.py +0 -0
  277. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/attachments.py +0 -0
  278. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/cache.py +0 -0
  279. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/helpers.py +0 -0
  280. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/mcp.py +0 -0
  281. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/plugins.py +0 -0
  282. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/render.py +0 -0
  283. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/serve.py +0 -0
  284. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/tools.py +0 -0
  285. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/cli/workspace.py +0 -0
  286. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/console.py +0 -0
  287. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/constants.py +0 -0
  288. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/content_blocks.py +0 -0
  289. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/memory.py +0 -0
  290. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/proxy.py +0 -0
  291. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/sandbox.py +0 -0
  292. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/subprocess_executor.py +0 -0
  293. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/core/tools.py +0 -0
  294. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/__init__.py +0 -0
  295. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/adapters/__init__.py +0 -0
  296. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/push.py +0 -0
  297. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/css/theme.css +0 -0
  298. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/icons/icon-192.png +0 -0
  299. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/icons/icon-512-maskable.png +0 -0
  300. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/icons/icon-512.png +0 -0
  301. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/icons/screenshot-narrow.png +0 -0
  302. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/icons/screenshot-wide.png +0 -0
  303. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/views/dashboard.js +0 -0
  304. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/views/file-editor.js +0 -0
  305. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/views/kvstore.js +0 -0
  306. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/views/webhooks.js +0 -0
  307. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/js/views/workspace.js +0 -0
  308. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/manifest.json +0 -0
  309. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/web/sw.js +0 -0
  310. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/daemon/webhook_store.py +0 -0
  311. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/events/bus.py +0 -0
  312. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/exceptions.py +0 -0
  313. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/history/__init__.py +0 -0
  314. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/history/reconstruction.py +0 -0
  315. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/hooks.py +0 -0
  316. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/interaction.py +0 -0
  317. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/kvstore/backend.py +0 -0
  318. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/kvstore/sqlite.py +0 -0
  319. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/mcp_client.py +0 -0
  320. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/mcp_config.py +0 -0
  321. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/mcp_server.py +0 -0
  322. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/options.py +0 -0
  323. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/renderer.py +0 -0
  324. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/schemas/__init__.py +0 -0
  325. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/shell_tool_config.py +0 -0
  326. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/skill_discovery.py +0 -0
  327. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/templates/AGENTS.md +0 -0
  328. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/templates/IDENTITY.md +0 -0
  329. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/templates/MEMORY.md +0 -0
  330. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/templates/USER.md +0 -0
  331. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/templates/personas/casual-technical.md +0 -0
  332. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/templates/personas/marvin.md +0 -0
  333. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/templates/personas/minimal.md +0 -0
  334. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/agents.py +0 -0
  335. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/fs.py +0 -0
  336. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/history.py +0 -0
  337. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/interactive.py +0 -0
  338. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/notify.py +0 -0
  339. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/shell.py +0 -0
  340. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tools/shell_tools.py +0 -0
  341. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/tsugite.py +0 -0
  342. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/__init__.py +0 -0
  343. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/base.py +0 -0
  344. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/helpers.py +0 -0
  345. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/plain.py +0 -0
  346. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui/repl_completer.py +0 -0
  347. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/ui_context.py +0 -0
  348. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/workspace/__init__.py +0 -0
  349. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/workspace/context.py +0 -0
  350. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/workspace/models.py +0 -0
  351. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/workspace/session.py +0 -0
  352. {tsugite_cli-0.9.4 → tsugite_cli-0.11.0}/tsugite/workspace/templates.py +0 -0
@@ -167,13 +167,16 @@ cython_debug/
167
167
  benchmark_results/
168
168
  test_output/
169
169
  .claude/settings.local.json
170
+ std*.txt
171
+ secrets/*
170
172
 
171
173
 
172
174
  # TODO: temp - I need to clean up the docs
173
- docs/
175
+ docs-old/
174
176
  examples/
175
177
  agents/
176
178
  .claude/
177
179
  .tsugite/
178
180
  benchmarks/
181
+ docker-compose.test.yml
179
182
  #### TODO ^^^
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tsugite-cli
3
- Version: 0.9.4
3
+ Version: 0.11.0
4
4
  Summary: Micro-agent runner for task automation using markdown definitions
5
5
  Author: Justyn Shull
6
6
  License: GNU AFFERO GENERAL PUBLIC LICENSE
@@ -239,22 +239,24 @@ License: GNU AFFERO GENERAL PUBLIC LICENSE
239
239
 
240
240
  You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU AGPL, see <http://www.gnu.org/licenses/>.
241
241
  License-File: LICENSE
242
- Keywords: agents,automation,cli,jinja2,litellm
242
+ Keywords: agents,automation,cli,jinja2
243
243
  Requires-Python: >=3.11
244
+ Requires-Dist: cryptography>=46.0.5
244
245
  Requires-Dist: ddgs>=9.6.0
245
246
  Requires-Dist: html2text>=2020.1.16
246
247
  Requires-Dist: httpx>=0.25
247
248
  Requires-Dist: jinja2>=3.1
248
- Requires-Dist: litellm<1.82.7,>=1.77.7
249
249
  Requires-Dist: mcp>=1.0
250
- Requires-Dist: nest-asyncio>=1.6.0
250
+ Requires-Dist: nest-asyncio>=1.5.0
251
251
  Requires-Dist: pathspec>=0.11.0
252
252
  Requires-Dist: portalocker>=2.8.0
253
253
  Requires-Dist: prompt-toolkit>=3.0.43
254
254
  Requires-Dist: pydantic>=2.12.3
255
255
  Requires-Dist: pyyaml>=6.0
256
256
  Requires-Dist: questionary>=2.1.1
257
+ Requires-Dist: readability-lxml>=0.8
257
258
  Requires-Dist: rich>=13.0
259
+ Requires-Dist: tiktoken>=0.7.0
258
260
  Requires-Dist: typer>=0.12
259
261
  Requires-Dist: tzlocal>=5.3.1
260
262
  Requires-Dist: youtube-transcript-api>=0.6.0
@@ -269,162 +271,149 @@ Description-Content-Type: text/markdown
269
271
 
270
272
  # tsugite
271
273
 
272
- Tsugite (Japanese: 継ぎ手, the art of joinery in woodworking) is a developer-facing agentic CLI.
274
+ Tsugite (継ぎ手) is an agent framework where you define AI agents as markdown files and run them from the CLI, a web UI, or through scheduled tasks.
273
275
 
274
- Define AI agents as markdown files with YAML frontmatter. Chain multiple steps together, pass data between them, and use any LLM (OpenAI, Anthropic, Ollama, etc).
276
+ I built it because none of the existing agent frameworks did what I wanted. I needed something self-hosted, model-agnostic, and simple enough that an agent is just a text file I can edit and version control.
275
277
 
276
- ## Installation
278
+ Originally it was meant to be a framework for micro-agents inspired by [ESA](https://github.com/meain/esa), but has grown a lot since that goal.
277
279
 
278
- ```bash
279
- # Recommended: Install with uv
280
- uv tool install tsugite-cli
281
-
282
- # Alternative: Install with pipx
283
- pipx install tsugite-cli
284
-
285
- # Or with pip
286
- pip install tsugite-cli
287
- ```
288
-
289
- **Note:** The package name is `tsugite-cli`, but the command is `tsugite` (or `tsu` for short).
280
+ ## What an agent looks like
290
281
 
291
- ## Quick Start
282
+ A simple "hello world" agent looks like:
292
283
 
293
- ```bash
294
- # Run an agent
295
- tsugite run examples/simple_variable_injection.md "test it"
296
-
297
- # Create your own agent
298
- cat > my_agent.md << 'EOF'
284
+ ```markdown
299
285
  ---
300
- name: hello
301
- model: openai:gpt-4o-mini
286
+ name: morning-brief
287
+ model: anthropic:claude-sonnet-4-20250514
288
+ tools: [web_search, fetch_text, write_file, final_answer]
302
289
  ---
303
290
 
304
- Task: {{ user_prompt }}
291
+ You are a morning briefing assistant.
305
292
 
306
- Just say hello and use final_answer() to return your greeting.
307
- EOF
293
+ Current date: {{ now() }}
294
+ User location: {{ env("LOCATION", "unknown") }}
308
295
 
309
- tsugite run my_agent.md "greet the user"
296
+ Check the weather, scan top news, and write a short briefing.
297
+ Use final_answer() to return the result.
310
298
  ```
311
299
 
312
- ## Features
300
+ YAML frontmatter for config, markdown body for instructions, Jinja for dynamic context. Run it with:
313
301
 
314
- - **Multi-step workflows** - Chain steps with `<!-- tsu:step -->`, pass data between them
315
- - **Variable injection** - Step outputs automatically available as Python variables
316
- - **Multiple LLM providers** - OpenAI, Anthropic, Ollama, Google, GitHub Copilot
317
- - **MCP integration** - Connect to Model Context Protocol servers
318
- - **Temperature control** - Set per-step model parameters
319
- - **Copy-paste friendly output** - `--plain` flag or auto-detection for pipe/redirect
302
+ ```bash
303
+ tsu run +morning-brief "what's happening today"
304
+ ```
305
+
306
+ ## Key ideas
320
307
 
321
- ## CLI Options
308
+ - **Agents are markdown.** A basic agent is just markdown with yaml frontmatter. Advanced agents are still just markdown but can use jinja templating and a special `<!--tsu -->` syntax.
309
+ - **Code execution over tool-calling.** Inspired by [smolagents](https://github.com/huggingface/smolagents). Instead of using native tool calling, LLMs write python code. Tools are exposed as python functions.
310
+ - **Any LLM.** Plugin interface to add support for additional LLM providers. Built-in we have openai-compatible apis, ollama, anthropic, and claude code.
311
+ - **Workspaces.** Each workspace is a persistent directory with agents, skills, memory files, and config. The agent runs inside its workspace and can read/write files, spawn sub-agents, manage schedules, and persist state across conversations. Workspaces are entirely optional.
312
+ - **CLI and/or Daemon with a Web UI** Use `tsu run` commands for cli-only, or run `tsu daemon` for a daemon that supports scheduled tasks, a web ui, and some other neat things.
313
+
314
+ ## Install
322
315
 
323
316
  ```bash
324
- # Plain output (no box-drawing characters, copy-paste friendly)
325
- tsugite run +assistant "task" --plain
317
+ uv tool install tsugite-cli # recommended
318
+ pipx install tsugite-cli # alternative
319
+ pip install tsugite-cli # or plain pip
320
+ ```
326
321
 
327
- # Auto-detection: plain mode activates when piped or NO_COLOR is set
328
- tsugite run +assistant "task" | grep result
322
+ The package is `tsugite-cli`, the command is `tsugite` (or `tsu` for short).
329
323
 
330
- # Headless mode for scripts (result to stdout, progress to stderr)
331
- tsugite run +assistant "task" --headless
324
+ ## Quick start
332
325
 
333
- # Continue latest conversation (auto-detects agent)
334
- tsugite run --continue "follow-up prompt"
326
+ ```bash
327
+ # Initialize a workspace
328
+ tsu init my-workspace
329
+ cd my-workspace
330
+
331
+ # Run the built-in default agent
332
+ tsu run +default "summarize the files in this directory"
335
333
 
336
- # Continue specific conversation
337
- tsugite run --continue --conversation-id CONV_ID "follow-up prompt"
338
- tsugite chat --continue CONV_ID
334
+ # Run an agent file directly
335
+ tsu run my-agent.md "do the thing"
339
336
 
340
- # View conversation history
341
- tsugite history list
342
- tsugite history show CONV_ID
337
+ # Start the web UI
338
+ tsu serve
343
339
  ```
344
340
 
345
- ## Sandbox
341
+ ## Features
346
342
 
347
- Agent code can run inside a [bubblewrap](https://github.com/containers/bubblewrap) sandbox with filesystem and network isolation.
343
+ - **Multi-step workflows** with `<!-- tsu:step -->` to chain steps and pass data between them
344
+ - **Scheduling** built-in cron for recurring agent tasks (daily summaries, monitoring, etc.)
345
+ - **Web UI** for conversations, with Discord as an alternative interface
346
+ - **Sub-agents** that can spawn other agents for specific subtasks
347
+ - **Skills** reusable knowledge files agents can load on demand, mostly compatible with [agentskills.io](https://agentskills.io/)
348
+ - **Hooks** that fire shell commands on lifecycle events (post-tool, pre-message, pre/post-compact)
349
+ - **Sandbox** (linux only) via bubblewrap with filesystem and network isolation
350
+ - **KV store** for persistent agent state
351
+ - **MCP** integration for connecting to MCP servers
348
352
 
349
- ```bash
350
- # Sandbox with specific domains allowed
351
- tsu run +default "task" --sandbox --allow-domain "github.com" --allow-domain "*.openai.com"
353
+ ## Agents in more detail
352
354
 
353
- # Full network isolation
354
- tsu run +default "task" --sandbox --no-network
355
+ Agents support YAML frontmatter for configuration:
356
+
357
+ ```yaml
358
+ ---
359
+ name: code-reviewer
360
+ model: anthropic:claude-sonnet-4-20250514
361
+ max_turns: 15
362
+ tools: [read_file, list_files, web_search, final_answer]
363
+ auto_load_skills: [coding-standards]
364
+ ---
355
365
  ```
356
366
 
357
- **How it works:**
367
+ You can restrict which tools an agent has access to, set turn limits, auto-load skills, attach context files, and extend other agents. TODO: See `docs/` for the full spec.
358
368
 
359
- ```
360
- CLI --sandbox --allow-domain "*.github.com"
361
- └─ SubprocessExecutor writes harness script
362
- └─ bwrap --unshare-pid --unshare-net --die-with-parent ...
363
- └─ TCP↔UDS bridge (HTTP_PROXY → Unix socket)
364
- └─ ConnectProxy filters CONNECT requests by domain:port
365
- ```
369
+ Multi-step agents use `<!--tsu -->` comments as directives:
366
370
 
367
- **Default mounts:**
371
+ ```markdown
372
+ <!-- tsu:step name="research" model="openai:gpt-4o" -->
373
+ Research the topic and save findings to a variable.
368
374
 
369
- - Read-only: `/usr`, `/lib`, `/lib64`, `/bin`, `/sbin`, `/etc/ssl`, `/etc/resolv.conf`, CA certs, Python venv + `sys.path`
370
- - Read-write: workspace directory, internal state directory
371
- - Tmpfs: `/tmp` (fresh each run)
375
+ <!-- tsu:step name="write" -->
376
+ Using the research from the previous step, write a summary.
377
+ The variable `research` is available as a Python variable.
378
+ ```
372
379
 
373
- Extra bind mounts can be added programmatically via `SandboxConfig.extra_ro_binds` and `extra_rw_binds`, but these are not yet exposed through CLI flags or agent frontmatter.
380
+ For a complete example, check the built-in [default agent](tsugite/builtin_agents/default.md).
374
381
 
375
- **Network:**
376
- - Network is namespace-isolated; outbound HTTP/HTTPS goes through a filtering CONNECT proxy
377
- - Direct connections to bare IP addresses are always blocked
378
- - `--no-network` skips the proxy entirely — no connectivity at all
382
+ ## Sandbox
379
383
 
380
- **`--allow-domain` syntax:**
384
+ On Linux only (for now), agent code runs inside a [bubblewrap](https://github.com/containers/bubblewrap) sandbox when you pass `--sandbox`:
381
385
 
382
- | Pattern | Allows |
383
- |---|---|
384
- | `github.com` | ports 80, 443 |
385
- | `github.com:22` | port 22 only |
386
- | `*.github.com:8080` | port 8080 on subdomains |
387
- | `*:*` | all domains, all ports |
386
+ ```bash
387
+ tsu run +default "task" --sandbox --allow-domain "github.com"
388
+ tsu run +default "task" --sandbox --no-network
389
+ ```
388
390
 
389
- ## Hooks
391
+ Filesystem access is limited to the workspace. Network goes through a filtering proxy that only allows domains you specify.
390
392
 
391
- Hooks fire shell commands at lifecycle points. Configure in `.tsugite/hooks.yaml`:
393
+ ## Config and Data Directories
392
394
 
393
- ```yaml
394
- hooks:
395
- post_tool:
396
- - tools: [write_file]
397
- run: git add {{ path }}
398
- wait: true
399
-
400
- pre_message:
401
- - run: uridx search "{{ message }}" --limit 5
402
- capture_as: rag_context
403
- - run: cat memory/preferences.md
404
- capture_as: user_preferences
405
-
406
- pre_compact:
407
- - run: ./scripts/extract-facts.sh {{ turns_file }}
408
- wait: true
409
-
410
- post_compact:
411
- - run: echo "Compacted {{ turns_compacted }} turns"
412
- ```
395
+ All paths follow [XDG Base Directory](https://specifications.freedesktop.org/basedir-spec/latest/) conventions and can be overridden with the standard environment variables.
413
396
 
414
- **Hook fields:** `run` (Jinja2 shell command), `tools` (tool filter, `post_tool` only), `match` (Jinja2 condition), `wait` (block until done), `capture_as` (capture stdout into a template variable, implies `wait`).
397
+ | Path | Default | Contents |
398
+ |----------------------------------------|--------------------------------------|----------------------------------------------|
399
+ | `$XDG_CONFIG_HOME/tsugite/` | `~/.config/tsugite/` | `config.json`, `mcp.json`, `daemon.yaml` |
400
+ | `$XDG_DATA_HOME/tsugite/history/` | `~/.local/share/tsugite/history/` | Session history (JSONL per session) |
401
+ | `$XDG_DATA_HOME/tsugite/daemon/` | `~/.local/share/tsugite/daemon/` | Daemon state |
402
+ | `$XDG_DATA_HOME/tsugite/secrets/` | `~/.local/share/tsugite/secrets/` | Encrypted secrets (`secrets.db`) |
403
+ | `$XDG_DATA_HOME/tsugite/kvstore/` | `~/.local/share/tsugite/kvstore/` | Key-value store (`kv.db`) |
404
+ | `$XDG_DATA_HOME/tsugite/usage/` | `~/.local/share/tsugite/usage/` | Usage (cost and token) tracking (`usage.db`) |
405
+ | `$XDG_DATA_HOME/tsugite/workspaces/` | `~/.local/share/tsugite/workspaces/` | Workspace directories |
406
+ | `$XDG_CACHE_HOME/tsugite/attachments/` | `~/.cache/tsugite/attachments/` | Attachment cache |
415
407
 
416
- **Hook types:**
417
- - **`post_tool`** — After successful tool calls. Context: `tool`, plus tool arguments.
418
- - **`pre_message`** — Before agent execution. Context: `message`, `user_id`, `agent_name`. Use `capture_as` to inject results into agent templates as `{{ var_name }}`.
419
- - **`pre_compact`** / **`post_compact`** — Around session compaction. Context: `conversation_id`, `user_id`, `agent_name`, `turns_file`, `turn_count`.
420
408
 
421
409
  ## Development
422
410
 
423
411
  ```bash
424
- # Clone and install for development
425
412
  git clone https://github.com/justyns/tsugite.git
426
413
  cd tsugite
427
414
  uv sync --dev
428
415
  ```
429
416
 
430
- See `examples/` for working agents and `CLAUDE.md` for AI-generated documentation.
417
+ ## Status
418
+
419
+ This is a personal project I use daily. It works for my use cases but isn't polished for general consumption yet. Issues and PRs welcome, but set expectations accordingly. Documentation is very sparse because I keep changing things.
@@ -0,0 +1,148 @@
1
+ # tsugite
2
+
3
+ Tsugite (継ぎ手) is an agent framework where you define AI agents as markdown files and run them from the CLI, a web UI, or through scheduled tasks.
4
+
5
+ I built it because none of the existing agent frameworks did what I wanted. I needed something self-hosted, model-agnostic, and simple enough that an agent is just a text file I can edit and version control.
6
+
7
+ Originally it was meant to be a framework for micro-agents inspired by [ESA](https://github.com/meain/esa), but has grown a lot since that goal.
8
+
9
+ ## What an agent looks like
10
+
11
+ A simple "hello world" agent looks like:
12
+
13
+ ```markdown
14
+ ---
15
+ name: morning-brief
16
+ model: anthropic:claude-sonnet-4-20250514
17
+ tools: [web_search, fetch_text, write_file, final_answer]
18
+ ---
19
+
20
+ You are a morning briefing assistant.
21
+
22
+ Current date: {{ now() }}
23
+ User location: {{ env("LOCATION", "unknown") }}
24
+
25
+ Check the weather, scan top news, and write a short briefing.
26
+ Use final_answer() to return the result.
27
+ ```
28
+
29
+ YAML frontmatter for config, markdown body for instructions, Jinja for dynamic context. Run it with:
30
+
31
+ ```bash
32
+ tsu run +morning-brief "what's happening today"
33
+ ```
34
+
35
+ ## Key ideas
36
+
37
+ - **Agents are markdown.** A basic agent is just markdown with yaml frontmatter. Advanced agents are still just markdown but can use jinja templating and a special `<!--tsu -->` syntax.
38
+ - **Code execution over tool-calling.** Inspired by [smolagents](https://github.com/huggingface/smolagents). Instead of using native tool calling, LLMs write python code. Tools are exposed as python functions.
39
+ - **Any LLM.** Plugin interface to add support for additional LLM providers. Built-in we have openai-compatible apis, ollama, anthropic, and claude code.
40
+ - **Workspaces.** Each workspace is a persistent directory with agents, skills, memory files, and config. The agent runs inside its workspace and can read/write files, spawn sub-agents, manage schedules, and persist state across conversations. Workspaces are entirely optional.
41
+ - **CLI and/or Daemon with a Web UI** Use `tsu run` commands for cli-only, or run `tsu daemon` for a daemon that supports scheduled tasks, a web ui, and some other neat things.
42
+
43
+ ## Install
44
+
45
+ ```bash
46
+ uv tool install tsugite-cli # recommended
47
+ pipx install tsugite-cli # alternative
48
+ pip install tsugite-cli # or plain pip
49
+ ```
50
+
51
+ The package is `tsugite-cli`, the command is `tsugite` (or `tsu` for short).
52
+
53
+ ## Quick start
54
+
55
+ ```bash
56
+ # Initialize a workspace
57
+ tsu init my-workspace
58
+ cd my-workspace
59
+
60
+ # Run the built-in default agent
61
+ tsu run +default "summarize the files in this directory"
62
+
63
+ # Run an agent file directly
64
+ tsu run my-agent.md "do the thing"
65
+
66
+ # Start the web UI
67
+ tsu serve
68
+ ```
69
+
70
+ ## Features
71
+
72
+ - **Multi-step workflows** with `<!-- tsu:step -->` to chain steps and pass data between them
73
+ - **Scheduling** built-in cron for recurring agent tasks (daily summaries, monitoring, etc.)
74
+ - **Web UI** for conversations, with Discord as an alternative interface
75
+ - **Sub-agents** that can spawn other agents for specific subtasks
76
+ - **Skills** reusable knowledge files agents can load on demand, mostly compatible with [agentskills.io](https://agentskills.io/)
77
+ - **Hooks** that fire shell commands on lifecycle events (post-tool, pre-message, pre/post-compact)
78
+ - **Sandbox** (linux only) via bubblewrap with filesystem and network isolation
79
+ - **KV store** for persistent agent state
80
+ - **MCP** integration for connecting to MCP servers
81
+
82
+ ## Agents in more detail
83
+
84
+ Agents support YAML frontmatter for configuration:
85
+
86
+ ```yaml
87
+ ---
88
+ name: code-reviewer
89
+ model: anthropic:claude-sonnet-4-20250514
90
+ max_turns: 15
91
+ tools: [read_file, list_files, web_search, final_answer]
92
+ auto_load_skills: [coding-standards]
93
+ ---
94
+ ```
95
+
96
+ You can restrict which tools an agent has access to, set turn limits, auto-load skills, attach context files, and extend other agents. TODO: See `docs/` for the full spec.
97
+
98
+ Multi-step agents use `<!--tsu -->` comments as directives:
99
+
100
+ ```markdown
101
+ <!-- tsu:step name="research" model="openai:gpt-4o" -->
102
+ Research the topic and save findings to a variable.
103
+
104
+ <!-- tsu:step name="write" -->
105
+ Using the research from the previous step, write a summary.
106
+ The variable `research` is available as a Python variable.
107
+ ```
108
+
109
+ For a complete example, check the built-in [default agent](tsugite/builtin_agents/default.md).
110
+
111
+ ## Sandbox
112
+
113
+ On Linux only (for now), agent code runs inside a [bubblewrap](https://github.com/containers/bubblewrap) sandbox when you pass `--sandbox`:
114
+
115
+ ```bash
116
+ tsu run +default "task" --sandbox --allow-domain "github.com"
117
+ tsu run +default "task" --sandbox --no-network
118
+ ```
119
+
120
+ Filesystem access is limited to the workspace. Network goes through a filtering proxy that only allows domains you specify.
121
+
122
+ ## Config and Data Directories
123
+
124
+ All paths follow [XDG Base Directory](https://specifications.freedesktop.org/basedir-spec/latest/) conventions and can be overridden with the standard environment variables.
125
+
126
+ | Path | Default | Contents |
127
+ |----------------------------------------|--------------------------------------|----------------------------------------------|
128
+ | `$XDG_CONFIG_HOME/tsugite/` | `~/.config/tsugite/` | `config.json`, `mcp.json`, `daemon.yaml` |
129
+ | `$XDG_DATA_HOME/tsugite/history/` | `~/.local/share/tsugite/history/` | Session history (JSONL per session) |
130
+ | `$XDG_DATA_HOME/tsugite/daemon/` | `~/.local/share/tsugite/daemon/` | Daemon state |
131
+ | `$XDG_DATA_HOME/tsugite/secrets/` | `~/.local/share/tsugite/secrets/` | Encrypted secrets (`secrets.db`) |
132
+ | `$XDG_DATA_HOME/tsugite/kvstore/` | `~/.local/share/tsugite/kvstore/` | Key-value store (`kv.db`) |
133
+ | `$XDG_DATA_HOME/tsugite/usage/` | `~/.local/share/tsugite/usage/` | Usage (cost and token) tracking (`usage.db`) |
134
+ | `$XDG_DATA_HOME/tsugite/workspaces/` | `~/.local/share/tsugite/workspaces/` | Workspace directories |
135
+ | `$XDG_CACHE_HOME/tsugite/attachments/` | `~/.cache/tsugite/attachments/` | Attachment cache |
136
+
137
+
138
+ ## Development
139
+
140
+ ```bash
141
+ git clone https://github.com/justyns/tsugite.git
142
+ cd tsugite
143
+ uv sync --dev
144
+ ```
145
+
146
+ ## Status
147
+
148
+ This is a personal project I use daily. It works for my use cases but isn't polished for general consumption yet. Issues and PRs welcome, but set expectations accordingly. Documentation is very sparse because I keep changing things.