- Remove 'cmd' from default TOOLS list - only detected shell exposed
- Add KshTool, TcshTool, CshTool for enterprise Unix shells
- Fallback to ShellTool (smart auto-detect) if shell detection fails
- Support ksh93, pdksh, mksh as aliases for ksh
- Bump hanzo-tools-shell to 0.6.1, hanzo-mcp to 0.10.37
- Add shell_detect.py module with comprehensive shell detection:
- Detects login shell from passwd/Directory Services
- Detects invoking shell by walking parent processes
- Prefers Homebrew shell paths on macOS
- Supports override via HANZO_MCP_SHELL and HANZO_MCP_FORCE_SHELL
- Update hanzo-tools-shell to only include detected shell in TOOLS list
- HANZO_MCP_ALL_SHELLS=1 to expose all shells
- get_shell_tools() now supports shell_override parameter
- Add CLI options to hanzo-mcp:
- --shell: Specify shell by name or path
- --all-shells: Expose all shell tools
- Updated --force-shell to include fish and dash
- Bump hanzo-tools-shell to 0.6.0 (published to PyPI)
- Bump hanzo-mcp to 0.10.36
Detection order: HANZO_MCP_SHELL > HANZO_MCP_FORCE_SHELL > CLI --shell >
invoking shell > login shell > $SHELL
- Change default timeout from 45s to 30s for faster response
- Fix potential hanging in run_shell by using stream reading instead of communicate()
- Add start_new_session=True to prevent zombie processes
- Proper cleanup on error with process.kill()
- All stream reading uses chunked async reads (8KB chunks)
- Partial output preserved when backgrounding
53 tests pass in 1.1s.
- Remove ShellTool from TOOLS list (too ambiguous)
- Keep zsh, bash, fish, dash as specific shell tools
- Update get_shell_tools to include bash
- Fix test imports (ShellTool now in shell_tools.py)
- Update tests to expect cmd as primary tool
- Verify asyncio.gather + uvloop works correctly
hanzo-tools-shell: 0.5.1 → 0.5.2
- Add shellflow.py: minimal DSL for DAG execution
- Syntax: A ; B (sequential), { A & B } (parallel)
- Compiles to JSON AST, S-expressions, or command list
- Supports quoted strings, &&, ||, nested braces
- Performance optimizations:
- Precompiled regex with local variable caching
- Fast-path for simple/sequential commands (8x faster)
- LRU cache for repeated patterns
- Full type annotations for mypyc compilation
- Restore dag as separate semantic tool:
- dag: for parallel/serial/graph execution
- zsh: for shell commands with shellflow DSL
- Both support nested arrays for auto-parallel
- Add comprehensive test suite (53 tests):
- Tokenizer, parser, normalization tests
- S-expression and command conversion tests
- Performance benchmarks
- Integration tests with real shell execution
Performance: ~7M ops/sec for simple commands,
~220k ops/sec for sequential, ~100k ops/sec for mixed DAGs
Shellflow syntax:
A ; B ; C → sequential
{ A & B & C } → parallel
A ; { B & C } ; D → mixed
Usage:
zsh("mkdir dist ; { cp a dist/ & cp b dist/ } ; zip out.zip dist/")
Compiles to JSON AST then executes via DAG.
Bump to v0.4.0
- ZshTool now includes full DAG functionality (serial, parallel, graph)
- Single "zsh" command for all shell operations
- Usage: zsh("ls") or zsh(["cmd1", "cmd2"]) or zsh([...], parallel=True)
- DagTool kept in codebase for backwards compatibility
- Removed DagTool from default TOOLS list
- Bump hanzo-tools-shell to v0.3.1
- hanzo-tools now contains core infrastructure (BaseTool, ToolRegistry, etc.)
- hanzo-tools-core becomes a thin backwards-compat wrapper
- All tool packages now depend on hanzo-tools>=0.3.0
- Reduces package count and simplifies dependency tree
Add three new shell tools that bypass shell escaping issues by using
subprocess with list arguments instead of shell interpretation:
- curl: HTTP client with proper JSON body handling
- jq: JSON processor with direct filter passing
- wget: File/site downloads with mirror mode support
These tools solve the common problem of shell escaping nightmares
when working with complex JSON or special characters.
Updates:
- Added CurlTool, JqTool, WgetTool to hanzo-tools-shell
- Updated __all__ exports and TOOLS list
- Added tools to entrypoint_loader PACKAGE_TOOL_PREFIXES
Add runtime check to provide better error message if ProcessManager()
returns None. This should never happen with proper singleton pattern,
but helps diagnose issues in edge cases.