Agent Integration
shuck exists because agents are the primary user. Humans can open a terminal and type into psql or redis-cli themselves. When a human prompts a coding agent to inspect a database, check package health, or debug a container — the agent needs shuck.
Why Agents Need shuck
Agents operate by running shell commands and reading their output. But the interactive CLI ecosystem is built for humans at keyboards:
Database REPLs
psql, mysql, redis-cli, mongosh — these all launch interactive prompts. An agent can’t type into a prompt. shuck wraps them so the agent gets clean output:
echo "SELECT version();" | shuck psql -U postgres
shuck mysql -u root -- -e "SHOW DATABASES"
shuck redis-cli -- "GET session:user:42"
Package Manager Diagnostics
brew doctor, pip check, npm doctor, rustup show — some produce TUI output with colors and spinners. Agents get garbled ANSI sequences instead of readable text:
shuck brew doctor 2>&1 > health.txt
shuck --json pip check
shuck --json npm doctor
Container Debugging
docker exec -it requires PTY allocation. Agents can’t use the -it flags. shuck provides the PTY:
shuck docker exec mycontainer cat /etc/hostname
shuck --json docker compose ps
Git Interactive Workflows
git rebase -i, git add -p, git stash --patch — powerful operations that require interactive editor input:
shuck git rebase -i HEAD~3 -- "pick\npick\nsquash"
shuck git add -p -- "y\nn\ny"
System Administration
systemctl status, journalctl, htop, top — pagers and TUI output that agents can’t navigate:
shuck systemctl status nginx
shuck journalctl -u myservice --no-pager -n 50
shuck --timeout 2 top -b -n 1
Language Version Managers
nvm ls, pyenv versions, rbenv versions — colored terminal output that needs stripping:
shuck nvm ls
shuck pyenv versions
SSH / Remote Commands
SSH requires PTY allocation for proper terminal behavior. Agents need to run commands on remote hosts:
shuck ssh user@host -- "df -h"
shuck --json ssh user@host -- "systemctl is-active myservice"
Structured Output for Decisions
--json gives agents structured data for decision chaining — check exit codes, parse stdout, branch on results:
result=$(shuck --json npm test)
exit_code=$(echo "$result" | jq .exit_code)
Agent Runtime Integration
Python
import subprocess
import json
def shuck(cmd: str, args: list[str] = [],
stdin: str | None = None,
timeout: int = 30) -> dict:
"""Run an interactive CLI non-interactively via shuck."""
run_args = ["shuck", "--json", f"--timeout={timeout}", cmd] + args
if stdin:
run_args += ["--", stdin]
result = subprocess.run(run_args, capture_output=True, text=True)
return json.loads(result.stdout)
# Agent checks database schema
result = shuck("psql", ["-U", "postgres", "mydb"], stdin="\\dt")
print(result["stdout"])
# Agent runs diagnostics
result = shuck("brew", ["doctor"])
if result["exit_code"] != 0:
print(f"Issues found: {result['stderr']}")
TypeScript / Node.js
import { execSync } from 'child_process';
interface ShuckResult {
stdout: string;
stderr: string;
exit_code: number;
duration_ms: number;
timed_out: boolean;
}
function shuck(
command: string,
args: string[] = [],
input?: string,
): ShuckResult {
const cmd = ['shuck', '--json', '--timeout=30', command, ...args];
if (input) cmd.push('--', input);
const raw = execSync(cmd.join(' '), { encoding: 'utf8' });
return JSON.parse(raw);
}
// Agent checks container status
const result = shuck('docker', ['compose', 'ps']);
console.log(result.stdout);
Bash
#!/bin/bash
shuck_run() {
local cmd="$1"
shift
local result
result=$(shuck --json "$cmd" "$@")
local exit_code
exit_code=$(echo "$result" | jq -r '.exit_code')
if [ "$exit_code" -ne 0 ]; then
echo "Error: $cmd exited with code $exit_code" >&2
echo "$result" | jq -r '.stderr' >&2
return "$exit_code"
fi
echo "$result" | jq -r '.stdout'
}
# Agent checks Redis key
value=$(shuck_run redis-cli -- "GET session:user:42")
echo "Session: $value"
Teaching Your Agent About shuck
Add shuck to your agent’s system prompt or configuration so it knows the tool exists and how to use it.
CLAUDE.md Integration
Add shuck to your project’s CLAUDE.md to make it available as a tool:
## Available Tools
### shuck — Interactive CLI Runner
Run any interactive CLI non-interactively:
\`\`\`bash
shuck --json <command> [args] [-- <stdin>]
\`\`\`
Use when:
- A tool normally opens a TUI or interactive prompt
- You need clean text output from an interactive CLI
- You want structured JSON with exit code and timing
Examples:
\`\`\`bash
shuck --json psql -U postgres mydb -- "\dt"
shuck --json redis-cli -- "GET mykey"
shuck --json brew doctor
shuck --json docker compose ps
\`\`\`
Agent System Prompts
For any agent framework, include shuck in the system prompt:
You have access to `shuck` for running interactive CLI tools non-interactively.
Use `shuck --json <command>` to get structured output with exit codes.
This works with database REPLs (psql, mysql, redis-cli), package managers
(brew doctor, pip check), docker commands, git interactive workflows, and SSH.
Error Handling
Always check the exit code:
result = shuck("my-tool", ["--flag"], stdin="input")
if result["timed_out"]:
raise TimeoutError(f"Timed out after {result['duration_ms']}ms")
elif result["exit_code"] == 127:
raise FileNotFoundError("Command not found")
elif result["exit_code"] != 0:
raise RuntimeError(f"Failed: {result['stderr']}")
output = result["stdout"]
Environment Setup for CI
In CI environments, shuck automatically uses --no-pty mode (detected via $CI). No configuration needed — agents can use shuck the same way in CI and locally.
# .github/workflows/agent.yml
- name: Run agent task
run: |
# shuck auto-detects CI=true and uses pipe fallback
shuck --json python3 -- "print('running in CI')"
MCP Server
For the most integrated agent experience, use shuck’s MCP server. See MCP Server for full setup.