Skip to main content

Overview

The @tinyclaw/shell package provides controlled shell command execution for Tiny Claw AI agents. It combines a permission engine with a shell executor to enforce safe command execution.

Safety Layers

  1. Permission engine — Allowlist + blocklist + approval store
  2. Shield integration — Runtime SHIELD.md threat evaluation
  3. Owner authority — Only the owner can run shell commands
  4. Executor safety — Timeout, output truncation, env filtering

Permission Model

All commands are DENIED by default unless:
  • Matched by built-in safe allowlist (read-only commands like ls, cat, git status)
  • User-configured allowed commands/patterns
  • One-time owner approval (stored for future use)
Even allowed commands are checked against a hardcoded blocklist of dangerous patterns that can never be bypassed.

Installation

bun add @tinyclaw/shell

Usage

Basic Setup

import { createShellEngine, createShellTools } from '@tinyclaw/shell';

const shell = createShellEngine({
  workingDirectory: '/path/to/project',
  defaultTimeoutMs: 30000,
});

// Create agent tools for shell interaction
const tools = createShellTools(shell);

Running Commands

// Execute a safe command (auto-allowed)
const result = await shell.run('ls -la');
console.log(result);

// Execute with custom timeout
const result2 = await shell.run('npm test', 60000); // 60 second timeout

Permission Management

// Check if a command would be allowed
const check = shell.permissions.evaluate('rm -rf node_modules');
console.log(check.decision); // 'allow' | 'deny' | 'require_approval'
console.log(check.reason);

// Approve a command (one-time)
shell.permissions.approve('npm install', false);

// Approve a command (persistent across sessions)
shell.permissions.approve('npm install', true);

// Add a custom allow pattern
shell.permissions.addAllowPattern('make *');

// List all approvals
const approvals = shell.permissions.listApprovals();

Cleanup

shell.shutdown();

API Reference

createShellEngine(config?)

Create a shell engine that combines permission checks with execution.
config
ShellEngineConfig
Configuration options.
config.workingDirectory
string
Working directory for command execution. Defaults to process.cwd().
config.defaultTimeoutMs
number
default:"30000"
Default timeout in milliseconds.
config.maxTimeoutMs
number
default:"120000"
Maximum allowed timeout in milliseconds.
config.maxOutputBytes
number
default:"10240"
Maximum output size in bytes before truncation (10 KB).
config.allowPatterns
string[]
Additional allow patterns from user config.
config.savedApprovals
ShellApproval[]
Previously persisted approvals to restore.
config.extraEnv
Record<string, string>
Additional environment variables to pass to commands.
Returns: ShellEngine

ShellEngine

run(command, timeoutMs?)

Execute a command with full permission checks.
command
string
required
The shell command to execute.
timeoutMs
number
Override timeout in milliseconds (max: 120000).
result
Promise<string>
Formatted result string suitable for the agent.

shutdown()

Shutdown and clean up resources. Clears all session (non-persistent) approvals.

createShellTools(shell)

Create agent tools for shell interaction.
shell
ShellEngine
required
The shell engine instance.
Returns: Tool[] - Array containing 3 tools:
  • run_shell — Execute a shell command
  • shell_approve — Approve a pending command
  • shell_allow — Add/remove/list allow patterns

ShellPermissionEngine

Permission evaluation and approval management.

evaluate(command)

Evaluate whether a command is allowed.
command
string
required
The command to evaluate.
result
ShellPermissionResult
Permission decision with reason and matched rule.
interface ShellPermissionResult {
  decision: 'allow' | 'deny' | 'require_approval';
  reason: string;
  matchedRule?: string; // For audit trail
}

approve(command, persistent?)

Record an owner approval for a command.
command
string
required
The exact command to approve.
persistent
boolean
default:"false"
Whether the approval persists across sessions.

revoke(command)

Revoke a previously granted approval.
command
string
required
The command to revoke.
removed
boolean
Whether an approval was removed.

listApprovals()

List all current approvals.
approvals
ShellApproval[]
Array of approval records.
interface ShellApproval {
  command: string;
  persistent: boolean;
  approvedAt: number; // Unix timestamp
}

addAllowPattern(pattern)

Add a command or glob pattern to the user allowlist.
pattern
string
required
Glob pattern like "make *" or exact command.

removeAllowPattern(pattern)

Remove a pattern from the user allowlist.
pattern
string
required
The pattern to remove.
removed
boolean
Whether the pattern was found and removed.

ShellResult

Result object from the executor.
success
boolean
Whether the command completed successfully (exit code 0).
stdout
string
Combined stdout output (truncated if necessary).
stderr
string
Combined stderr output (truncated if necessary).
exitCode
number
Process exit code.
durationMs
number
Execution duration in milliseconds.
timedOut
boolean
Whether the command was killed due to timeout.
truncated
boolean
Whether stdout was truncated.

Built-in Safe Commands

The following commands are auto-allowed without approval:
  • Filesystem reading: ls, cat, head, tail, find, tree, stat
  • Text processing: grep, awk, sed, sort, uniq, cut, diff
  • System info: echo, pwd, whoami, hostname, uname, date, env
  • Package managers: npm ls, yarn info, pip list, cargo tree
  • Git (read-only): git status, git log, git diff, git show, git branch
  • Process info: ps, top, htop, lsof

Dangerous Patterns (Always Blocked)

These patterns are always blocked regardless of allowlist:
  • Destructive operations: rm -rf /, mkfs, dd if=/dev/*
  • Privilege escalation: sudo, su, chmod 777
  • Code injection: eval, exec, source, | sh
  • Network exfiltration: nc -l, ncat, /dev/tcp/
  • System modification: shutdown, reboot, systemctl
  • Credential access: export, .env, ssh, scp

Environment Variable Filtering

Sensitive environment variables are automatically stripped before passing to child processes:
  • API keys: OPENAI_API_KEY, ANTHROPIC_API_KEY, GITHUB_TOKEN
  • Database credentials: DATABASE_URL, DB_PASSWORD, REDIS_PASSWORD
  • Generic secrets: Any var containing _KEY, _SECRET, _TOKEN, _PASSWORD

Examples

Safe Command (Auto-allowed)

const result = await shell.run('ls -la');
// Executes immediately

Unapproved Command

const result = await shell.run('npm install lodash');
// Returns: "This command requires owner approval before it can run..."

Approve and Run

shell.permissions.approve('npm install lodash', true);
const result = await shell.run('npm install lodash');
// Now executes

Dangerous Command

const result = await shell.run('sudo rm -rf /');
// Returns: "Shell command denied: Recursive delete of root filesystem"