tsugite-cli 0.9.4__tar.gz → 0.10.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.
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/.gitignore +4 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/PKG-INFO +101 -114
- tsugite_cli-0.10.0/README.md +148 -0
- tsugite_cli-0.10.0/docs/agents.md +273 -0
- tsugite_cli-0.10.0/docs/secrets.md +136 -0
- tsugite_cli-0.10.0/docs/test_agents/prefresh_readme.md +16 -0
- tsugite_cli-0.10.0/docs/test_agents/template_test.md +14 -0
- tsugite_cli-0.10.0/docs/test_agents/test_agent.md +15 -0
- tsugite_cli-0.10.0/docs/test_agents/test_steps.md +8 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/pyproject.toml +4 -4
- tsugite_cli-0.10.0/scripts/backfill_usage.py +98 -0
- tsugite_cli-0.10.0/scripts/update_model_registry.py +189 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/conftest.py +39 -29
- tsugite_cli-0.10.0/tests/core/test_agent.py +677 -0
- tsugite_cli-0.10.0/tests/core/test_agent_ui_events.py +419 -0
- tsugite_cli-0.10.0/tests/core/test_content_blocks.py +269 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_builtin_agent_paths.py +14 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_cache_control.py +1 -4
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_chat_cli.py +23 -5
- tsugite_cli-0.10.0/tests/test_claude_code_attachments.py +83 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_claude_code_provider.py +38 -108
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_daemon_compaction_scheduler.py +10 -27
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_daemon_history_persistence.py +1 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_daemon_memory.py +74 -58
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_history.py +25 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_history_models.py +25 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_hooks.py +3 -10
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_kvstore.py +1 -0
- tsugite_cli-0.10.0/tests/test_model_registry.py +26 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_models.py +24 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_reasoning_models.py +16 -29
- tsugite_cli-0.10.0/tests/test_secrets.py +450 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_session_orchestrator_tools.py +8 -6
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_tmux_tools.py +1 -3
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/__init__.py +0 -4
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/agent_runner/__init__.py +4 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/agent_runner/helpers.py +10 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/agent_runner/history_integration.py +12 -12
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/agent_runner/models.py +1 -3
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/agent_runner/runner.py +29 -15
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/agent_runner/validation.py +1 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/builtin_agents/default.md +19 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/__init__.py +6 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/chat.py +5 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/config.py +0 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/history.py +3 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/init.py +16 -47
- tsugite_cli-0.10.0/tsugite/cli/models.py +80 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/run.py +17 -4
- tsugite_cli-0.10.0/tsugite/cli/secrets.py +51 -0
- tsugite_cli-0.10.0/tsugite/cli/usage.py +134 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/validate.py +1 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/config.py +9 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/core/__init__.py +1 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/core/agent.py +89 -323
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/core/executor.py +9 -5
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/adapters/base.py +52 -31
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/adapters/discord.py +7 -2
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/adapters/http.py +133 -25
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/commands.py +4 -2
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/compaction_scheduler.py +1 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/gateway.py +7 -8
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/memory.py +22 -60
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/session_runner.py +2 -2
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/session_store.py +56 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/index.html +129 -7
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/js/app.js +3 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/js/utils.js +20 -2
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/js/views/conversations.js +5 -1
- tsugite_cli-0.10.0/tsugite/daemon/web/js/views/usage.js +65 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/history/models.py +4 -3
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/history/storage.py +8 -2
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/kvstore/__init__.py +1 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/md_agents.py +12 -1
- tsugite_cli-0.10.0/tsugite/models.py +158 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/plugins.py +3 -1
- tsugite_cli-0.10.0/tsugite/providers/__init__.py +97 -0
- tsugite_cli-0.10.0/tsugite/providers/anthropic.py +298 -0
- tsugite_cli-0.10.0/tsugite/providers/base.py +91 -0
- tsugite_cli-0.10.0/tsugite/providers/claude_code.py +255 -0
- tsugite_cli-0.10.0/tsugite/providers/model_cache.py +126 -0
- tsugite_cli-0.10.0/tsugite/providers/model_registry.py +46 -0
- tsugite_cli-0.10.0/tsugite/providers/ollama.py +76 -0
- tsugite_cli-0.10.0/tsugite/providers/openai_compat.py +304 -0
- tsugite_cli-0.10.0/tsugite/providers/openrouter.py +69 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/schemas/agent.schema.json +16 -2
- tsugite_cli-0.10.0/tsugite/secrets/__init__.py +82 -0
- tsugite_cli-0.10.0/tsugite/secrets/backend.py +11 -0
- tsugite_cli-0.10.0/tsugite/secrets/env.py +25 -0
- tsugite_cli-0.10.0/tsugite/secrets/exec.py +75 -0
- tsugite_cli-0.10.0/tsugite/secrets/file.py +43 -0
- tsugite_cli-0.10.0/tsugite/secrets/masking.py +31 -0
- tsugite_cli-0.10.0/tsugite/secrets/registry.py +62 -0
- tsugite_cli-0.10.0/tsugite/secrets/sqlite.py +121 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tools/__init__.py +7 -6
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tools/kv.py +5 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tools/schedule.py +1 -0
- tsugite_cli-0.10.0/tsugite/tools/secrets.py +48 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tools/tmux.py +2 -7
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/ui/chat.py +5 -2
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/ui/repl_chat.py +17 -4
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/ui/repl_commands.py +1 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/ui/repl_handler.py +15 -10
- tsugite_cli-0.10.0/tsugite/usage/__init__.py +5 -0
- tsugite_cli-0.10.0/tsugite/usage/store.py +222 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/utils.py +3 -1
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/uv.lock +5 -340
- tsugite_cli-0.9.4/README.md +0 -161
- tsugite_cli-0.9.4/tests/core/test_agent.py +0 -782
- tsugite_cli-0.9.4/tests/core/test_agent_ui_events.py +0 -434
- tsugite_cli-0.9.4/tests/core/test_content_blocks.py +0 -340
- tsugite_cli-0.9.4/tests/test_claude_code_attachments.py +0 -245
- tsugite_cli-0.9.4/tsugite/models.py +0 -282
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/.github/copilot-instructions.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/.github/workflows/ci.yml +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/.github/workflows/docker-publish.yml +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/.github/workflows/pypi-publish.yml +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/AGENTS.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/CLAUDE.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/LICENSE +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/scripts/regenerate_schema.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/README.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/core/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/core/test_executor.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/core/test_memory.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/core/test_proxy.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/core/test_sandbox.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/core/test_subprocess_executor.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/core/test_tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/daemon/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/daemon/test_http_adapter.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/events/test_event_consolidation.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/smoke_test.sh +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_agent_file_hot_loading.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_agent_inheritance.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_agent_parser.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_agent_sessions.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_agent_skills.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_agent_utils.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_agents_tool.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_attachment_deduplication.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_attachments.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_auto_context_handler.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_auto_discovery.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_background_task_status.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_background_tasks.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_builtin_agents.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_chat_error_handling.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_cli.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_cli_arguments.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_cli_rendering.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_cli_subcommands.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_config.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_continuation.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_custom_shell_tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_custom_ui.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_daemon_config.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_daemon_push.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_daemon_scheduler.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_daemon_session_isolation.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_daemon_unified_sessions.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_discord_progress.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_error_display.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_file_references.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_file_tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_history_integration.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_history_performance.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_history_tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_http_tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_interaction_backends.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_interactive_context.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_interactive_tool.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_jsonl_ui.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_list_agents_tool.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_mcp_client.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_mcp_server.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_multi_agent.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_multistep_agents.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_orchestrator_heartbeat.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_plugins.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_renderer.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_rendering_scenarios.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_repl_commands.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_repl_completer.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_repl_handler.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_retry_system.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_run_if.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_schedule_model_override.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_scheduler_history_injection.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_schema.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_security_phase1.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_send_message.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_skill_discovery.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_skill_tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_stdin.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_subagent_subprocess.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_tool_directives.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_tool_registry.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_workspace_auto_continue.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_workspace_cwd.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tests/test_workspace_discovery.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/agent_inheritance.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/agent_preparation.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/agent_runner/metrics.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/agent_utils.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/attachments/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/attachments/auto_context.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/attachments/base.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/attachments/file.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/attachments/inline.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/attachments/storage.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/attachments/url.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/attachments/youtube.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/builtin_agents/.gitkeep +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/builtin_agents/code_searcher.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/builtin_agents/file_searcher.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/builtin_agents/onboard.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/builtin_skills/.gitkeep +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/builtin_skills/codebase_exploration.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/builtin_skills/python_math.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/builtin_skills/response_patterns.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/builtin_skills/scheduling.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/builtin_skills/skill_authoring.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/builtin_skills/tsugite_agent_basics.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/builtin_skills/tsugite_jinja_reference.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/builtin_skills/tsugite_skill_basics.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cache.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/agents.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/attachments.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/cache.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/daemon.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/helpers.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/mcp.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/plugins.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/render.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/serve.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/cli/workspace.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/console.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/constants.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/core/claude_code.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/core/content_blocks.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/core/memory.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/core/proxy.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/core/sandbox.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/core/subprocess_executor.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/core/tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/adapters/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/adapters/scheduler_adapter.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/config.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/push.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/scheduler.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/css/responsive.css +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/css/styles.css +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/css/theme.css +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/icons/icon-192.png +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/icons/icon-512-maskable.png +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/icons/icon-512.png +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/icons/screenshot-narrow.png +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/icons/screenshot-wide.png +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/js/api.js +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/js/views/dashboard.js +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/js/views/file-editor.js +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/js/views/kvstore.js +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/js/views/schedules.js +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/js/views/webhooks.js +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/js/views/workspace.js +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/manifest.json +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/web/sw.js +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/daemon/webhook_store.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/events/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/events/base.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/events/bus.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/events/events.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/events/helpers.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/exceptions.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/history/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/history/reconstruction.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/hooks.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/interaction.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/kvstore/backend.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/kvstore/sqlite.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/mcp_client.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/mcp_config.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/mcp_server.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/options.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/renderer.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/schemas/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/shell_tool_config.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/skill_discovery.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/templates/AGENTS.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/templates/IDENTITY.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/templates/MEMORY.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/templates/USER.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/templates/personas/casual-technical.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/templates/personas/marvin.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/templates/personas/minimal.md +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tools/agents.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tools/fs.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tools/history.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tools/http.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tools/interactive.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tools/notify.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tools/sessions.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tools/shell.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tools/shell_tools.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tools/skills.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/tsugite.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/ui/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/ui/base.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/ui/helpers.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/ui/jsonl.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/ui/plain.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/ui/repl_completer.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/ui_context.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/workspace/__init__.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/workspace/context.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/workspace/models.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.0}/tsugite/workspace/session.py +0 -0
- {tsugite_cli-0.9.4 → tsugite_cli-0.10.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.
|
|
3
|
+
Version: 0.10.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,15 +239,14 @@ 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
|
|
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
|
|
251
250
|
Requires-Dist: pathspec>=0.11.0
|
|
252
251
|
Requires-Dist: portalocker>=2.8.0
|
|
253
252
|
Requires-Dist: prompt-toolkit>=3.0.43
|
|
@@ -255,6 +254,7 @@ Requires-Dist: pydantic>=2.12.3
|
|
|
255
254
|
Requires-Dist: pyyaml>=6.0
|
|
256
255
|
Requires-Dist: questionary>=2.1.1
|
|
257
256
|
Requires-Dist: rich>=13.0
|
|
257
|
+
Requires-Dist: tiktoken>=0.7.0
|
|
258
258
|
Requires-Dist: typer>=0.12
|
|
259
259
|
Requires-Dist: tzlocal>=5.3.1
|
|
260
260
|
Requires-Dist: youtube-transcript-api>=0.6.0
|
|
@@ -269,162 +269,149 @@ Description-Content-Type: text/markdown
|
|
|
269
269
|
|
|
270
270
|
# tsugite
|
|
271
271
|
|
|
272
|
-
Tsugite (
|
|
272
|
+
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
273
|
|
|
274
|
-
|
|
274
|
+
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
275
|
|
|
276
|
-
|
|
276
|
+
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
277
|
|
|
278
|
-
|
|
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).
|
|
278
|
+
## What an agent looks like
|
|
290
279
|
|
|
291
|
-
|
|
280
|
+
A simple "hello world" agent looks like:
|
|
292
281
|
|
|
293
|
-
```
|
|
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'
|
|
282
|
+
```markdown
|
|
299
283
|
---
|
|
300
|
-
name:
|
|
301
|
-
model:
|
|
284
|
+
name: morning-brief
|
|
285
|
+
model: anthropic:claude-sonnet-4-20250514
|
|
286
|
+
tools: [web_search, fetch_text, write_file, final_answer]
|
|
302
287
|
---
|
|
303
288
|
|
|
304
|
-
|
|
289
|
+
You are a morning briefing assistant.
|
|
305
290
|
|
|
306
|
-
|
|
307
|
-
|
|
291
|
+
Current date: {{ now() }}
|
|
292
|
+
User location: {{ env("LOCATION", "unknown") }}
|
|
308
293
|
|
|
309
|
-
|
|
294
|
+
Check the weather, scan top news, and write a short briefing.
|
|
295
|
+
Use final_answer() to return the result.
|
|
310
296
|
```
|
|
311
297
|
|
|
312
|
-
|
|
298
|
+
YAML frontmatter for config, markdown body for instructions, Jinja for dynamic context. Run it with:
|
|
313
299
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
- **Copy-paste friendly output** - `--plain` flag or auto-detection for pipe/redirect
|
|
300
|
+
```bash
|
|
301
|
+
tsu run +morning-brief "what's happening today"
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Key ideas
|
|
320
305
|
|
|
321
|
-
|
|
306
|
+
- **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.
|
|
307
|
+
- **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.
|
|
308
|
+
- **Any LLM.** Plugin interface to add support for additional LLM providers. Built-in we have openai-compatible apis, ollama, anthropic, and claude code.
|
|
309
|
+
- **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.
|
|
310
|
+
- **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.
|
|
311
|
+
|
|
312
|
+
## Install
|
|
322
313
|
|
|
323
314
|
```bash
|
|
324
|
-
|
|
325
|
-
|
|
315
|
+
uv tool install tsugite-cli # recommended
|
|
316
|
+
pipx install tsugite-cli # alternative
|
|
317
|
+
pip install tsugite-cli # or plain pip
|
|
318
|
+
```
|
|
326
319
|
|
|
327
|
-
|
|
328
|
-
tsugite run +assistant "task" | grep result
|
|
320
|
+
The package is `tsugite-cli`, the command is `tsugite` (or `tsu` for short).
|
|
329
321
|
|
|
330
|
-
|
|
331
|
-
tsugite run +assistant "task" --headless
|
|
322
|
+
## Quick start
|
|
332
323
|
|
|
333
|
-
|
|
334
|
-
|
|
324
|
+
```bash
|
|
325
|
+
# Initialize a workspace
|
|
326
|
+
tsu init my-workspace
|
|
327
|
+
cd my-workspace
|
|
328
|
+
|
|
329
|
+
# Run the built-in default agent
|
|
330
|
+
tsu run +default "summarize the files in this directory"
|
|
335
331
|
|
|
336
|
-
#
|
|
337
|
-
|
|
338
|
-
tsugite chat --continue CONV_ID
|
|
332
|
+
# Run an agent file directly
|
|
333
|
+
tsu run my-agent.md "do the thing"
|
|
339
334
|
|
|
340
|
-
#
|
|
341
|
-
|
|
342
|
-
tsugite history show CONV_ID
|
|
335
|
+
# Start the web UI
|
|
336
|
+
tsu serve
|
|
343
337
|
```
|
|
344
338
|
|
|
345
|
-
##
|
|
339
|
+
## Features
|
|
346
340
|
|
|
347
|
-
|
|
341
|
+
- **Multi-step workflows** with `<!-- tsu:step -->` to chain steps and pass data between them
|
|
342
|
+
- **Scheduling** built-in cron for recurring agent tasks (daily summaries, monitoring, etc.)
|
|
343
|
+
- **Web UI** for conversations, with Discord as an alternative interface
|
|
344
|
+
- **Sub-agents** that can spawn other agents for specific subtasks
|
|
345
|
+
- **Skills** reusable knowledge files agents can load on demand, mostly compatible with [agentskills.io](https://agentskills.io/)
|
|
346
|
+
- **Hooks** that fire shell commands on lifecycle events (post-tool, pre-message, pre/post-compact)
|
|
347
|
+
- **Sandbox** (linux only) via bubblewrap with filesystem and network isolation
|
|
348
|
+
- **KV store** for persistent agent state
|
|
349
|
+
- **MCP** integration for connecting to MCP servers
|
|
348
350
|
|
|
349
|
-
|
|
350
|
-
# Sandbox with specific domains allowed
|
|
351
|
-
tsu run +default "task" --sandbox --allow-domain "github.com" --allow-domain "*.openai.com"
|
|
351
|
+
## Agents in more detail
|
|
352
352
|
|
|
353
|
-
|
|
354
|
-
|
|
353
|
+
Agents support YAML frontmatter for configuration:
|
|
354
|
+
|
|
355
|
+
```yaml
|
|
356
|
+
---
|
|
357
|
+
name: code-reviewer
|
|
358
|
+
model: anthropic:claude-sonnet-4-20250514
|
|
359
|
+
max_turns: 15
|
|
360
|
+
tools: [read_file, list_files, web_search, final_answer]
|
|
361
|
+
auto_load_skills: [coding-standards]
|
|
362
|
+
---
|
|
355
363
|
```
|
|
356
364
|
|
|
357
|
-
|
|
365
|
+
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
366
|
|
|
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
|
-
```
|
|
367
|
+
Multi-step agents use `<!--tsu -->` comments as directives:
|
|
366
368
|
|
|
367
|
-
|
|
369
|
+
```markdown
|
|
370
|
+
<!-- tsu:step name="research" model="openai:gpt-4o" -->
|
|
371
|
+
Research the topic and save findings to a variable.
|
|
368
372
|
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
373
|
+
<!-- tsu:step name="write" -->
|
|
374
|
+
Using the research from the previous step, write a summary.
|
|
375
|
+
The variable `research` is available as a Python variable.
|
|
376
|
+
```
|
|
372
377
|
|
|
373
|
-
|
|
378
|
+
For a complete example, check the built-in [default agent](tsugite/builtin_agents/default.md).
|
|
374
379
|
|
|
375
|
-
|
|
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
|
|
380
|
+
## Sandbox
|
|
379
381
|
|
|
380
|
-
|
|
382
|
+
On Linux only (for now), agent code runs inside a [bubblewrap](https://github.com/containers/bubblewrap) sandbox when you pass `--sandbox`:
|
|
381
383
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
| `*.github.com:8080` | port 8080 on subdomains |
|
|
387
|
-
| `*:*` | all domains, all ports |
|
|
384
|
+
```bash
|
|
385
|
+
tsu run +default "task" --sandbox --allow-domain "github.com"
|
|
386
|
+
tsu run +default "task" --sandbox --no-network
|
|
387
|
+
```
|
|
388
388
|
|
|
389
|
-
|
|
389
|
+
Filesystem access is limited to the workspace. Network goes through a filtering proxy that only allows domains you specify.
|
|
390
390
|
|
|
391
|
-
|
|
391
|
+
## Config and Data Directories
|
|
392
392
|
|
|
393
|
-
|
|
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
|
-
```
|
|
393
|
+
All paths follow [XDG Base Directory](https://specifications.freedesktop.org/basedir-spec/latest/) conventions and can be overridden with the standard environment variables.
|
|
413
394
|
|
|
414
|
-
|
|
395
|
+
| Path | Default | Contents |
|
|
396
|
+
|----------------------------------------|--------------------------------------|----------------------------------------------|
|
|
397
|
+
| `$XDG_CONFIG_HOME/tsugite/` | `~/.config/tsugite/` | `config.json`, `mcp.json`, `daemon.yaml` |
|
|
398
|
+
| `$XDG_DATA_HOME/tsugite/history/` | `~/.local/share/tsugite/history/` | Session history (JSONL per session) |
|
|
399
|
+
| `$XDG_DATA_HOME/tsugite/daemon/` | `~/.local/share/tsugite/daemon/` | Daemon state |
|
|
400
|
+
| `$XDG_DATA_HOME/tsugite/secrets/` | `~/.local/share/tsugite/secrets/` | Encrypted secrets (`secrets.db`) |
|
|
401
|
+
| `$XDG_DATA_HOME/tsugite/kvstore/` | `~/.local/share/tsugite/kvstore/` | Key-value store (`kv.db`) |
|
|
402
|
+
| `$XDG_DATA_HOME/tsugite/usage/` | `~/.local/share/tsugite/usage/` | Usage (cost and token) tracking (`usage.db`) |
|
|
403
|
+
| `$XDG_DATA_HOME/tsugite/workspaces/` | `~/.local/share/tsugite/workspaces/` | Workspace directories |
|
|
404
|
+
| `$XDG_CACHE_HOME/tsugite/attachments/` | `~/.cache/tsugite/attachments/` | Attachment cache |
|
|
415
405
|
|
|
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
406
|
|
|
421
407
|
## Development
|
|
422
408
|
|
|
423
409
|
```bash
|
|
424
|
-
# Clone and install for development
|
|
425
410
|
git clone https://github.com/justyns/tsugite.git
|
|
426
411
|
cd tsugite
|
|
427
412
|
uv sync --dev
|
|
428
413
|
```
|
|
429
414
|
|
|
430
|
-
|
|
415
|
+
## Status
|
|
416
|
+
|
|
417
|
+
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.
|