Micro-agent runner for task automation using markdown definitions
Project description
tsugite
Tsugite (Japanese: 継ぎ手, the art of joinery in woodworking) is a developer-facing agentic CLI.
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).
Installation
# Recommended: Install with uv
uv tool install tsugite-cli
# Alternative: Install with pipx
pipx install tsugite-cli
# Or with pip
pip install tsugite-cli
Note: The package name is tsugite-cli, but the command is tsugite (or tsu for short).
Quick Start
# Run an agent
tsugite run examples/simple_variable_injection.md "test it"
# Create your own agent
cat > my_agent.md << 'EOF'
---
name: hello
model: openai:gpt-4o-mini
---
Task: {{ user_prompt }}
Just say hello and use final_answer() to return your greeting.
EOF
tsugite run my_agent.md "greet the user"
Features
- Multi-step workflows - Chain steps with
<!-- tsu:step -->, pass data between them - Variable injection - Step outputs automatically available as Python variables
- Multiple LLM providers - OpenAI, Anthropic, Ollama, Google, GitHub Copilot
- MCP integration - Connect to Model Context Protocol servers
- Temperature control - Set per-step model parameters
- Copy-paste friendly output -
--plainflag or auto-detection for pipe/redirect
CLI Options
# Plain output (no box-drawing characters, copy-paste friendly)
tsugite run +assistant "task" --plain
# Auto-detection: plain mode activates when piped or NO_COLOR is set
tsugite run +assistant "task" | grep result
# Headless mode for scripts (result to stdout, progress to stderr)
tsugite run +assistant "task" --headless
# Continue latest conversation (auto-detects agent)
tsugite run --continue "follow-up prompt"
# Continue specific conversation
tsugite run --continue --conversation-id CONV_ID "follow-up prompt"
tsugite chat --continue CONV_ID
# View conversation history
tsugite history list
tsugite history show CONV_ID
Sandbox
Agent code can run inside a bubblewrap sandbox with filesystem and network isolation.
# Sandbox with specific domains allowed
tsu run +default "task" --sandbox --allow-domain "github.com" --allow-domain "*.openai.com"
# Full network isolation
tsu run +default "task" --sandbox --no-network
How it works:
CLI --sandbox --allow-domain "*.github.com"
└─ SubprocessExecutor writes harness script
└─ bwrap --unshare-pid --unshare-net --die-with-parent ...
└─ TCP↔UDS bridge (HTTP_PROXY → Unix socket)
└─ ConnectProxy filters CONNECT requests by domain:port
Default mounts:
- Read-only:
/usr,/lib,/lib64,/bin,/sbin,/etc/ssl,/etc/resolv.conf, CA certs, Python venv +sys.path - Read-write: workspace directory, internal state directory
- Tmpfs:
/tmp(fresh each run)
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.
Network:
- Network is namespace-isolated; outbound HTTP/HTTPS goes through a filtering CONNECT proxy
- Direct connections to bare IP addresses are always blocked
--no-networkskips the proxy entirely — no connectivity at all
--allow-domain syntax:
| Pattern | Allows |
|---|---|
github.com |
ports 80, 443 |
github.com:22 |
port 22 only |
*.github.com:8080 |
port 8080 on subdomains |
*:* |
all domains, all ports |
Hooks
Hooks fire shell commands at lifecycle points. Configure in .tsugite/hooks.yaml:
hooks:
post_tool:
- tools: [write_file]
run: git add {{ path }}
wait: true
pre_message:
- run: uridx search "{{ message }}" --limit 5
capture_as: rag_context
- run: cat memory/preferences.md
capture_as: user_preferences
pre_compact:
- run: ./scripts/extract-facts.sh {{ turns_file }}
wait: true
post_compact:
- run: echo "Compacted {{ turns_compacted }} turns"
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).
Hook types:
post_tool— After successful tool calls. Context:tool, plus tool arguments.pre_message— Before agent execution. Context:message,user_id,agent_name. Usecapture_asto inject results into agent templates as{{ var_name }}.pre_compact/post_compact— Around session compaction. Context:conversation_id,user_id,agent_name,turns_file,turn_count.
Development
# Clone and install for development
git clone https://github.com/justyns/tsugite.git
cd tsugite
uv sync --dev
See examples/ for working agents and CLAUDE.md for AI-generated documentation.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tsugite_cli-0.9.4.tar.gz.
File metadata
- Download URL: tsugite_cli-0.9.4.tar.gz
- Upload date:
- Size: 798.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b043075f3947b357ed3b6f9cf77f6a338603f1b21761e17e9176ff4d1abfc87d
|
|
| MD5 |
6fa4e0a77b5bf55a64c9126e1b9bdfe9
|
|
| BLAKE2b-256 |
8935538be566497ae37ff4f6e29ddd2ca474b0e453fbce69ffb26fbba2cac020
|
Provenance
The following attestation bundles were made for tsugite_cli-0.9.4.tar.gz:
Publisher:
pypi-publish.yml on justyns/tsugite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tsugite_cli-0.9.4.tar.gz -
Subject digest:
b043075f3947b357ed3b6f9cf77f6a338603f1b21761e17e9176ff4d1abfc87d - Sigstore transparency entry: 1187994924
- Sigstore integration time:
-
Permalink:
justyns/tsugite@088aec5921738bb69f2e0f59bcafe45f4f68495e -
Branch / Tag:
refs/tags/v0.9.4 - Owner: https://github.com/justyns
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@088aec5921738bb69f2e0f59bcafe45f4f68495e -
Trigger Event:
push
-
Statement type:
File details
Details for the file tsugite_cli-0.9.4-py3-none-any.whl.
File metadata
- Download URL: tsugite_cli-0.9.4-py3-none-any.whl
- Upload date:
- Size: 488.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d8c22d0679a17af78f6aa6209f0b9dd7c86b6ae6fd68f4803b84e3331d5d46f8
|
|
| MD5 |
412ed90e58e8741bbc893871d2e041af
|
|
| BLAKE2b-256 |
c720528b14f968b4ea456626afa6eb7751ee5c45b154d9b310adc083638dad5b
|
Provenance
The following attestation bundles were made for tsugite_cli-0.9.4-py3-none-any.whl:
Publisher:
pypi-publish.yml on justyns/tsugite
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tsugite_cli-0.9.4-py3-none-any.whl -
Subject digest:
d8c22d0679a17af78f6aa6209f0b9dd7c86b6ae6fd68f4803b84e3331d5d46f8 - Sigstore transparency entry: 1187994926
- Sigstore integration time:
-
Permalink:
justyns/tsugite@088aec5921738bb69f2e0f59bcafe45f4f68495e -
Branch / Tag:
refs/tags/v0.9.4 - Owner: https://github.com/justyns
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@088aec5921738bb69f2e0f59bcafe45f4f68495e -
Trigger Event:
push
-
Statement type: