A safe, human-in-the-loop terminal assistant capable of executing Bash and PowerShell commands. Designed for use with LangChain and LangGraph, it brings LLM reasoning, guardrails, and human oversight to real shell execution.
- β Cross-Shell Execution β Runs both Bash (Linux/macOS) and PowerShell (Windows) commands.
- π§© Policy-Governed Safety β Validates every command against an allow/deny list before execution.
- π§ LLM Integration β Uses OpenAI or Azure OpenAI chat models to interpret user intent and respond safely.
- π Human-In-The-Loop (HITL) β Requires approval before executing commands, ensuring full visibility and control.
- πͺ Persistent Shell Sessions β Maintains shell state and working directory across commands using middleware.
- π‘οΈ Sandboxed Execution β Enforces a root jail defined by
SHELL_ROOT_DIRfor added system safety. - π In-Memory State Management β Uses LangGraph's checkpointing for conversation persistence.
- βοΈ Modular Architecture β Extensible middleware system for policy enforcement and session management.
sequenceDiagram
participant User as π€ User
participant Agent as π§ LangChain Agent
participant LLM as π€ Chat Model
participant Config as βοΈ AppConfig
participant SessionMW as π Session Middleware
participant PolicyMW as π Policy Middleware
participant HITLMW as π HITL Middleware
participant Tool as β‘ Shell Tool
participant System as π» System
participant State as πΎ State Checkpointer
User->>Agent: Submit Request
Agent->>Config: Load Settings & Policy
Config-->>Agent: Return Configuration
Agent->>LLM: Generate Response
LLM-->>Agent: Tool Selection & Commands
Agent->>State: Save Current State
Agent->>SessionMW: Execute Tool Call
SessionMW->>PolicyMW: Validate Command
alt Policy Violation
PolicyMW-->>User: Policy Violation Alert
else Command Valid
PolicyMW->>HITLMW: Request Human Approval
HITLMW->>User: Show Command for Approval
User-->>HITLMW: Approve/Edit/Reject
alt Command Approved
HITLMW->>Tool: Execute Approved Command
Tool->>System: Run Shell Command
System-->>Tool: Return stdout/stderr
Tool-->>SessionMW: Command Results
SessionMW-->>Agent: Tool Response
Agent->>State: Update State with Results
Agent-->>User: Final Response with Output
else Command Rejected
HITLMW-->>Agent: Command Rejected
Agent-->>User: Execution Cancelled
end
end
git clone https://github.com/eosho/langchain_terminal_agent
cd langchain_terminal_agentUsing uv:
pip install uv
uv syncOr using pip directly:
pip install -r requirements.txtcp .env.sample .envEdit your .env file to include model credentials and shell root directory:
# LLM Provider Configuration
LLM_PROVIDER=azure_openai # or "openai"
MODEL_NAME=gpt-4o-mini
MODEL_TEMPERATURE=0.0
MODEL_MAX_TOKENS=4096
# Azure OpenAI Configuration (if using azure_openai provider)
AZURE_OPENAI_ENDPOINT=https://your-endpoint.openai.azure.com/
AZURE_OPENAI_API_KEY=your-api-key
AZURE_OPENAI_API_VERSION=2024-12-01-preview
AZURE_OPENAI_DEPLOYMENT=gpt-4o
# OpenAI Configuration (if using openai provider)
OPENAI_API_KEY=sk-your-api-key
# Terminal Agent Settings
SHELL_ROOT_DIR=./ # Repository root directory
LOG_LEVEL=INFO| Variable | Description | Default |
|---|---|---|
LLM_PROVIDER |
LLM backend: openai or azure_openai |
openai |
MODEL_NAME |
Model name or deployment ID | gpt-4o-mini |
MODEL_TEMPERATURE |
Sampling temperature for creativity | 0.0 |
MODEL_MAX_TOKENS |
Maximum number of output tokens | 4096 |
OPENAI_API_KEY |
OpenAI API key (if using openai provider) | None |
AZURE_OPENAI_ENDPOINT |
Azure OpenAI endpoint URL | None |
AZURE_OPENAI_API_KEY |
Azure OpenAI API key | None |
AZURE_OPENAI_API_VERSION |
Azure OpenAI API version | None |
AZURE_OPENAI_DEPLOYMENT |
Azure OpenAI deployment name | None |
SHELL_ROOT_DIR |
Root directory jail for shell execution | ./ |
LOG_LEVEL |
Logging verbosity (DEBUG, INFO, WARN) |
INFO |
from terminal_agent.tools.shell.bash import bash_tool
from terminal_agent.core.config import AppConfig
cfg = AppConfig.from_env()
# Direct tool invocation (bypasses HITL)
result = bash_tool(
commands=["pwd", "ls -la"],
cwd=str(cfg.shell_policy.root_dir),
)
print(result)from terminal_agent.tools.shell.powershell import powershell_tool
from terminal_agent.core.config import AppConfig
cfg = AppConfig.from_env()
# Direct tool invocation (bypasses HITL)
result = powershell_tool(
commands=["Get-Location", "Get-Date"],
cwd=str(cfg.shell_policy.root_dir),
)
print(result)from terminal_agent.builder import build_agent
import asyncio
async def main():
agent = await build_agent(shell_type="bash") # or "powershell"
config = {"configurable": {"thread_id": "1"}}
# Interactive mode with human-in-the-loop approval
result = agent.invoke(
{"messages": [{"role": "user", "content": "Show me the current directory and list its files."}]},
config=config
)
print(result)
asyncio.run(main())# Using black for code formatting
python -m black .
# Using isort for import sorting
python -m isort .# Run all tests
python -m pytest -v
# Run with coverage
python -m pytest --cov=terminal_agent tests/# Check code style
python -m flake8 src/terminal_agent
# Type checking
python -m mypy src/terminal_agent# Install in development mode
pip install -e .
# Install development dependencies
pip install -r requirements-dev.txt # if available
# Run the interactive CLI for testing
python main.py- All command executions are guarded by
ShellPolicyMiddleware. - Commands are validated against explicit allow and deny lists.
SHELL_ROOT_DIRdefines the safe sandbox β no command can escape it.- Destructive operations (
rm -rf,shutdown,format-volume, etc.) are always blocked. - Human-In-The-Loop (HITL) middleware requires user approval before any real command runs.
- Persistent shell sessions are managed safely with automatic cleanup.
- All command outputs are captured and returned safely without system exposure.
The agent uses configurable allow/deny lists for both Bash and PowerShell commands:
allowed_bash_commands = ["ls", "cat", "pwd", "echo", "mkdir"]
dangerous_bash_commands = ["rm", "mv", "shutdown", "reboot"]
allowed_powershell_commands = ["Get-ChildItem", "Set-Location", "Get-Process"]
dangerous_powershell_commands = ["Remove-Item", "Stop-Computer"]Pull requests are welcome! If you find bugs, open an issue with clear reproduction steps.
This project is licensed under the MIT License.
See LICENSE for details.