Skip to main content

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 - --plain flag 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-network skips 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. Use capture_as to 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tsugite_cli-0.9.3.tar.gz (797.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tsugite_cli-0.9.3-py3-none-any.whl (487.1 kB view details)

Uploaded Python 3

File details

Details for the file tsugite_cli-0.9.3.tar.gz.

File metadata

  • Download URL: tsugite_cli-0.9.3.tar.gz
  • Upload date:
  • Size: 797.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for tsugite_cli-0.9.3.tar.gz
Algorithm Hash digest
SHA256 3abf48979eb951123b65da91331756c3a15b8f45bca202839e686bf9ae7eaed3
MD5 1cc7406b7f5970b9f1181d8b9a389066
BLAKE2b-256 b722e3807dd791668beaf0d8819da839a3ff863508dd63be180bea32353bd98c

See more details on using hashes here.

Provenance

The following attestation bundles were made for tsugite_cli-0.9.3.tar.gz:

Publisher: pypi-publish.yml on justyns/tsugite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file tsugite_cli-0.9.3-py3-none-any.whl.

File metadata

  • Download URL: tsugite_cli-0.9.3-py3-none-any.whl
  • Upload date:
  • Size: 487.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for tsugite_cli-0.9.3-py3-none-any.whl
Algorithm Hash digest
SHA256 e2fa102e2271d86fe4d58ccc91ca66726f750eb83992bc8365ce9deb3fc4dcfb
MD5 53720791052db054779bd8d4d01d5305
BLAKE2b-256 f124a5d1917ad1c66dddd8bea12574cda83edde6a1cac82a4daf2337e893975d

See more details on using hashes here.

Provenance

The following attestation bundles were made for tsugite_cli-0.9.3-py3-none-any.whl:

Publisher: pypi-publish.yml on justyns/tsugite

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page