Documentation Index
Fetch the complete documentation index at: https://docs.hud.ai/llms.txt
Use this file to discover all available pages before exploring further.
Coding tools give agents shell access and file editing. Like computer tools, each provider has its own spec.
Quick Reference
Shell tools execute commands in a persistent bash session:
| Tool | Agent | Features |
|---|
BashTool | Claude | Persistent, manual restart |
ShellTool | OpenAI | Auto-restart, dynamic timeout |
GeminiShellTool | Gemini | Simple execution |
Editor tools modify files:
| Tool | Agent | Style |
|---|
EditTool | Claude | str_replace based |
ApplyPatchTool | OpenAI | Unified diff |
GeminiEditTool | Gemini | Instruction-based |
Persistent bash shell. Session survives across calls. Agent must manually restart on timeout.
from hud.tools import BashTool
bash = BashTool()
# Execute command
result = await bash(command="ls -la")
# Chain commands (session persists)
await bash(command="cd /app")
await bash(command="npm install")
# Restart if session dies
await bash(restart=True)
Uses native bash_20250124 API.
Auto-restarts on error. Supports multiple commands with per-command timeout.
from hud.tools.coding import ShellTool
shell = ShellTool()
result = await shell(
commands=["cd /app", "npm install", "npm run build"],
timeout_ms=60000,
)
for output in result.output:
print(f"stdout: {output.stdout}")
print(f"exit: {output.outcome.exit_code}")
Uses native shell API.
Simple command execution for Gemini and generic agents.
from hud.tools.coding import GeminiShellTool
shell = GeminiShellTool()
result = await shell(command="python script.py", timeout=120)
File editor using str_replace. Maintains undo history.
from hud.tools import EditTool
editor = EditTool()
Commands: view, create, str_replace, insert, undo_edit
# View file
await editor(command="view", path="/app/main.py", view_range=[1, 50])
# View directory
await editor(command="view", path="/app")
# Create file
await editor(
command="create",
path="/app/new.py",
file_text="def hello():\n print('Hello!')",
)
# Replace text (old_str must be unique in file)
await editor(
command="str_replace",
path="/app/main.py",
old_str="print('old')",
new_str="print('new')",
)
# Insert at line
await editor(
command="insert",
path="/app/main.py",
insert_line=10,
new_str="# New comment\n",
)
# Undo last edit
await editor(command="undo_edit", path="/app/main.py")
Uses native text_editor_20250728 API. Paths must be absolute.
Unified diff format for file modifications.
from hud.tools.coding import ApplyPatchTool
patcher = ApplyPatchTool()
patch = """--- a/main.py
+++ b/main.py
@@ -10,7 +10,7 @@
def greet(name):
- print(f"Hello, {name}!")
+ print(f"Welcome, {name}!")
return True
"""
result = await patcher(patch=patch)
Instruction-based editing for Gemini.
from hud.tools.coding import GeminiEditTool
editor = GeminiEditTool()
# Natural language instruction
await editor(
file_path="/app/main.py",
instruction="Add a docstring to the greet function",
)
# Direct replacement
await editor(
file_path="/app/main.py",
old_content="def greet():",
new_content="def greet(name: str):",
)
Role Exclusion
Shell tools share role="shell". Editor tools share role="editor". Only one per role can be active natively—prevents conflicts.
Typical Setup
For Claude:
from hud import Environment
from hud.tools import BashTool, EditTool
env = Environment("coding-env")
env.add_tool(BashTool())
env.add_tool(EditTool())
For OpenAI:
from hud import Environment
from hud.tools.coding import ShellTool, ApplyPatchTool
env = Environment("coding-env")
env.add_tool(ShellTool())
env.add_tool(ApplyPatchTool())
Customizing
Use hooks for simple validation:
from hud.tools import BashTool
from hud.tools.types import ToolError
bash = BashTool()
@bash.before
async def block_dangerous(command: str | None = None, **kwargs):
if command:
for blocked in ["rm -rf /", "sudo", "curl | sh"]:
if blocked in command:
raise ToolError(f"Blocked: {blocked}")
env.add_tool(bash)
Read-only editor:
from hud.tools import EditTool
from hud.tools.types import ToolError
editor = EditTool()
@editor.before
async def read_only(command: str = "", **kwargs):
if command != "view":
raise ToolError("Read-only environment")
env.add_tool(editor)
Or subclass for more complex logic:
from typing import Any
from mcp.types import ContentBlock
from hud.tools import BashTool
from hud.tools.types import ToolError
class AuditedBashTool(BashTool):
def __init__(self):
super().__init__()
self.command_history: list[str] = []
async def __call__(
self, command: str | None = None, restart: bool = False
) -> list[ContentBlock]:
if command:
self.command_history.append(command)
return await super().__call__(command, restart)