CLI Plugin
Execute shell commands on the local machine with output capture, auto-backgrounding for long-running commands, and intelligent shell detection.
| Name | cli |
| Type | Tool Plugin (Registry-managed) |
| Tools Provided | cli_based_tool |
| User Commands | None |
| Auto-approved | None (requires permission) |
Features
- Shell Detection: Automatically detects pipes, redirections, and chaining
- Auto-Backgrounding: Long-running commands (>10s) become background tasks
- Output Truncation: Prevents context overflow from large outputs
- Smart Duration Estimation: Recognizes slow commands (npm, cargo, etc.)
- PATH Extension: Add custom directories to command search path
from jaato import PluginRegistry
registry = PluginRegistry()
registry.discover()
# Expose CLI plugin with defaults
registry.expose_tool('cli')
# Or with custom configuration
registry.expose_tool('cli', config={
'extra_paths': ['/usr/local/bin', '/opt/bin'],
'max_output_chars': 100000,
'auto_background_threshold': 30.0,
'background_max_workers': 8,
})
# The model calls the tool like this:
# cli_based_tool(command="ls -la /home/user")
# Shell features are supported:
# cli_based_tool(command="find . -name '*.py' | head -20")
# cli_based_tool(command="npm install && npm test")
Configuration Parameters
extra_paths
Additional directories to add to PATH when executing commands.
Useful when tools are installed in non-standard locations.
| Type | List[str] |
| Default | [] |
max_output_chars
Maximum characters to return from stdout/stderr combined. Prevents context window overflow from verbose commands.
| Type | int |
| Default | 50000 (~12k tokens) |
auto_background_threshold
Seconds before a command is automatically backgrounded. Commands exceeding this duration return a task handle instead of blocking.
| Type | float |
| Default | 10.0 |
background_max_workers
Maximum concurrent background tasks. Additional tasks queue until a slot opens.
| Type | int |
| Default | 4 |
# Development setup - more output, longer threshold
registry.expose_tool('cli', config={
'max_output_chars': 100000,
'auto_background_threshold': 60.0,
})
# CI/CD setup - additional tool paths
registry.expose_tool('cli', config={
'extra_paths': [
'/opt/node/bin',
'/usr/local/go/bin',
'~/.cargo/bin',
],
})
# Resource-constrained - limit background workers
registry.expose_tool('cli', config={
'background_max_workers': 2,
'max_output_chars': 20000,
})
Tool Reference
cli_based_tool
Execute any shell command on the local machine.
Parameters
| Name | Type | Required | Description |
|---|---|---|---|
command |
string |
Yes | Shell command to execute |
args |
string[] |
No | Arguments if passing executable separately |
Return Value
| Field | Type | Description |
|---|---|---|
stdout |
string |
Command's standard output |
stderr |
string |
Command's standard error |
returncode |
int |
Exit code (0 = success) |
truncated |
bool |
True if output was truncated |
error |
string |
Error message if execution failed |
{
"name": "cli_based_tool",
"description": "Execute any shell command...",
"parameters": {
"type": "object",
"properties": {
"command": {
"type": "string",
"description": "The shell command to execute"
},
"args": {
"type": "array",
"items": {"type": "string"},
"description": "Optional argument list"
}
},
"required": ["command"]
}
}
// Successful command
{
"stdout": "total 24\ndrwxr-xr-x 3 user...",
"stderr": "",
"returncode": 0
}
// Failed command
{
"stdout": "",
"stderr": "ls: /nonexistent: No such file...",
"returncode": 2
}
// Truncated output
{
"stdout": "... (truncated)",
"stderr": "",
"returncode": 0,
"truncated": true,
"truncation_message": "Output truncated..."
}
Auto-Backgrounding
Commands that exceed the auto_background_threshold are
automatically converted to background tasks. This prevents the model
from blocking on long operations like builds and tests.
Known Slow Commands
The CLI plugin recognizes these patterns as slow operations and estimates their duration for auto-backgrounding decisions:
| Pattern | Estimated Duration |
|---|---|
npm install, yarn install | 30s |
cargo build | 60s |
mvn install | 60s |
docker build | 60s |
pytest, npm test | 30s |
pip install | 20s |
git clone | 20s |
background plugin for task management. The model receives
a task handle and can check status or retrieve output later.
# Model invokes a slow command:
# cli_based_tool(command="npm install")
# Plugin estimates duration (~30s) > threshold (10s)
# Command runs in background, returns immediately:
{
"background_task_id": "cli_abc123",
"status": "running",
"message": "Command backgrounded due to estimated duration"
}
# Model can check status via background plugin:
# check_background_task(task_id="cli_abc123")
{
"status": "completed",
"result": {
"stdout": "added 1423 packages...",
"stderr": "",
"returncode": 0
}
}
Shell Detection
The CLI plugin automatically detects when a command requires shell interpretation and switches execution modes accordingly.
Shell Mode (shell=True)
Activated when the command contains:
- Pipes:
| - Redirections:
>,<,>> - Command chaining:
&&,||,; - Command substitution:
$(), backticks - Background execution:
&at end
Direct Mode (shell=False)
Used for simple commands without shell metacharacters. Safer and slightly faster, as the command is executed directly without shell parsing.
# Direct mode (no shell metacharacters)
cli_based_tool(command="ls -la /home/user")
cli_based_tool(command="git status")
cli_based_tool(command="python script.py --arg value")
# Shell mode (requires shell interpretation)
cli_based_tool(command="find . -name '*.py' | wc -l")
cli_based_tool(command="echo 'hello' > output.txt")
cli_based_tool(command="npm install && npm test")
cli_based_tool(command="cat file.txt || echo 'not found'")
cli_based_tool(command="export FOO=bar; echo $FOO")
Shell mode passes commands through /bin/sh.
This enables powerful features but also means:
- Shell injection is possible if commands
contain untrusted input
- The permission plugin should be used to
review commands before execution
- Consider the security implications of
allowing shell access in your use case
Error Handling
The plugin's system instructions guide the model on handling common errors:
| Error | Guidance |
|---|---|
| Non-zero returncode | Check stderr for details |
| "File exists" | Goal already achieved, continue |
| "Permission denied" | Try alternative approach or report blocker |
| "Command not found" | Check if tool installed, try alternative |
| "No such file" | Verify path exists first |
Output Truncation
When output exceeds max_output_chars, the response includes
a truncated: true flag and guidance message suggesting
the model use filters or limits.
# Instead of full output:
find /large/dir -type f
# Use filters to narrow results:
find /large/dir -type f -name "*.py" | head -50
# Limit recursion depth:
find /large/dir -maxdepth 2 -type f
# Use grep to filter:
npm list | grep -E "^[+|`]-- (react|vue)"
# Limit with head/tail:
git log --oneline | head -20