hanzo-tools-shell¶
Unified command execution with DAG support, auto-backgrounding, and process management. The shell toolkit provides the cmd, zsh, bash, and ps tools.
Installation¶
Or as part of the full toolkit:
Overview¶
hanzo-tools-shell provides:
- cmd - Unified command execution with DAG support
- zsh / bash / shell - Shell-specific execution
- ps - Process management (list, kill, logs)
- npx / uvx - Package runner tools
- open - Platform-aware file/URL opener
Key Features¶
Auto-Backgrounding¶
Commands automatically background after 30 seconds (configurable):
# Long-running command auto-backgrounds
cmd("npm run build") # If takes >30s, continues in background
# Check status later
ps() # List all background processes
ps(logs="cmd_abc123") # View output
ps(kill="cmd_abc123") # Stop process
DAG Execution¶
Execute commands with dependency graphs:
# Sequential (default)
cmd(["mkdir dist", "cp files dist/", "zip -r out.zip dist/"])
# Parallel
cmd(["npm install", "cargo build"], parallel=True)
# Mixed DAG with dependencies
cmd([
"mkdir -p dist",
{"parallel": ["cp a.txt dist/", "cp b.txt dist/"]},
"zip -r out.zip dist/"
])
Tools Reference¶
cmd¶
The primary command execution tool:
# Simple command
cmd("ls -la")
# Sequential commands
cmd(["git status", "git diff", "git log -5"])
# Parallel execution
cmd(["npm install", "pip install -r requirements.txt"], parallel=True)
# Mixed DAG
cmd([
"mkdir -p dist",
{"parallel": ["build-frontend", "build-backend"]},
"deploy"
])
# With options
cmd(
"npm test",
timeout=120, # Command timeout in seconds
cwd="/project", # Working directory
env={"NODE_ENV": "test"}, # Environment variables
quiet=True, # Suppress stdout
strict=True # Stop on first error
)
zsh / bash / shell¶
Shell-specific wrappers around cmd:
# Use specific shell
zsh("echo $SHELL") # Uses zsh
bash("echo $SHELL") # Uses bash
shell("echo $SHELL") # Auto-detects: zsh > bash > sh
# Same options as cmd
zsh(["cmd1", "cmd2"], parallel=True, timeout=60)
ps¶
Process management for background commands:
# List all background processes
ps()
# Get specific process info
ps(id="cmd_abc123")
# View process output (last 100 lines by default)
ps(logs="cmd_abc123")
ps(logs="cmd_abc123", n=50) # Last 50 lines
# Kill process
ps(kill="cmd_abc123") # SIGTERM (default)
ps(kill="cmd_abc123", sig=9) # SIGKILL
npx / uvx¶
Package runners with auto-backgrounding:
# Run npm packages
npx("create-react-app my-app")
npx("http-server -p 8080") # Auto-backgrounds if long-running
# Run Python packages
uvx("ruff check .")
uvx("mkdocs serve") # Auto-backgrounds if long-running
open¶
Platform-aware opener for files and URLs:
# Open URLs
open("https://example.com")
# Open files with default application
open("./document.pdf")
open("/path/to/image.png")
Configuration¶
Environment Variables¶
| Variable | Default | Description |
|---|---|---|
HANZO_AUTO_BACKGROUND_TIMEOUT |
45 |
Seconds before auto-backgrounding (0 to disable) |
HANZO_DEFAULT_SHELL |
zsh |
Default shell for execution |
Timeout Configuration¶
# Disable auto-backgrounding for a command
cmd("long-running-command", timeout=0)
# Set global timeout via environment
import os
os.environ["HANZO_AUTO_BACKGROUND_TIMEOUT"] = "120" # 2 minutes
Examples¶
Build Pipeline¶
# Parallel build with sequential deploy
cmd([
{"parallel": [
"npm run build:frontend",
"npm run build:backend",
"npm run build:docs"
]},
"npm run test",
"npm run deploy"
])
Development Server¶
# Start dev server (auto-backgrounds)
cmd("npm run dev")
# Later, check status
ps()
# Output: cmd_abc123 | running | npm run dev | started 5m ago
# View logs
ps(logs="cmd_abc123")
# Stop when done
ps(kill="cmd_abc123")
Tool Invocation in DAG¶
# Mix shell commands with tool calls
cmd([
"git pull origin main",
{"tool": "search", "input": {"pattern": "TODO"}},
"npm test"
])
Parallel File Operations¶
# Process multiple files in parallel
cmd([
["process file1.txt", "process file2.txt", "process file3.txt"]
], parallel=True)
Architecture¶
ShellExecutor¶
Single async execution engine for all shell tools:
CmdTool (cmd) # Unified execution graph (DAG)
├── ZshTool (zsh) # Thin shim: shell=zsh
├── BashTool (bash) # Thin shim: shell=bash
└── ShellTool # Smart shim: zsh > bash > sh
ShellExecutor (singleton)
└── ProcessManager (singleton)
└── ps tool (process listing/kill/logs)
Process Lifecycle¶
- Command starts with
asyncio.create_subprocess_exec - Wait for completion with configured timeout
- If timeout reached: register with ProcessManager, continue in background
- User can monitor with
ps --logs <id>or stop withps --kill <id>
Error Handling¶
# Strict mode: stop on first error
cmd(["cmd1", "cmd2", "cmd3"], strict=True)
# Default: continue on errors, report all
cmd(["cmd1", "cmd2", "cmd3"]) # Returns combined output with errors
# Check exit codes in response
result = cmd("might-fail")
if "exit code" in result.lower():
# Handle error
...
Best Practices¶
- Use DAG for dependencies: Let the executor handle ordering
- Parallelize independent operations: Use
parallel=Truefor speed - Set appropriate timeouts: Avoid blocking on hung processes
- Use
psfor long tasks: Don't wait for builds, check later - Prefer
cmdover raw shell: Better error handling and logging