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.