Skip to content

elizaos-plugins/plugin-shell

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

9 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

@elizaos/plugin-shell

A comprehensive shell command execution plugin for ElizaOS with PTY support, background execution, session management, and security restrictions.

Key Features:

  • πŸ”„ PTY Support - Run interactive terminal applications with full pseudo-terminal support
  • ⏱️ Background Execution - Long-running commands automatically background with session management
  • πŸ“‹ Session Management - Track, poll, and interact with running processes
  • πŸ”’ Security First - Directory restrictions, forbidden commands, and timeout protection
  • πŸ“ Command History - Per-conversation command tracking

Available in three languages:

  • 🟦 TypeScript - Primary implementation for Node.js (full feature support)
  • 🐍 Python - Native Python implementation
  • πŸ¦€ Rust - High-performance Rust implementation

🚨 TL;DR - Quick Setup

Just want your agent to execute commands? Here's the fastest path:

  1. Install the plugin:

    cd your-eliza-project
    bun add @elizaos/plugin-shell
  2. Create/update your .env:

    SHELL_ALLOWED_DIRECTORY=/path/to/safe/directory
  3. Add to your character:

    const character = {
      // ... other config
      plugins: ["@elizaos/plugin-shell"],
    };
  4. Run: bun start

⚠️ Security note: The agent can ONLY execute commands within SHELL_ALLOWED_DIRECTORY - choose wisely!

Features

Core Features

  • βœ… Cross-platform support: Works on Linux, macOS, and Windows
  • βœ… Directory restriction: Commands are restricted to a specified directory for safety
  • βœ… Command filtering: Configurable list of forbidden commands
  • βœ… Timeout protection: Automatic termination of long-running commands
  • βœ… Command history: Tracks command execution history per conversation
  • βœ… File operation tracking: Monitors file creation, modification, and deletion
  • βœ… Shell context provider: Provides command history and working directory to agent context
  • βœ… Output capture: Returns both stdout and stderr from executed commands
  • βœ… Safety first: Disabled by default, requires explicit enabling
  • βœ… Multi-language: Available in TypeScript, Python, and Rust

Advanced Features (TypeScript)

  • βœ… PTY Support: Run interactive terminal applications (vim, htop, etc.) with @lydell/node-pty
  • βœ… Background Execution: Commands automatically background after configurable yield window
  • βœ… Session Management: Track running/finished sessions, poll output, send keys
  • βœ… Process Control: List, poll, log, write, send-keys, submit, paste, kill, clear, remove
  • βœ… Output Truncation: Configurable max output with intelligent truncation
  • βœ… Platform-specific Shell: Auto-detects shell (bash, sh, PowerShell on Windows)

Project Structure

plugin-shell/
β”œβ”€β”€ typescript/          # TypeScript implementation
β”‚   β”œβ”€β”€ actions/         # EXECUTE_COMMAND, CLEAR_SHELL_HISTORY
β”‚   β”œβ”€β”€ providers/       # SHELL_HISTORY provider
β”‚   β”œβ”€β”€ services/        # ShellService
β”‚   β”œβ”€β”€ utils/           # Path validation, security checks
β”‚   β”œβ”€β”€ types/           # Type definitions
β”‚   └── __tests__/       # Unit tests
β”œβ”€β”€ python/              # Python implementation
β”‚   β”œβ”€β”€ elizaos_plugin_shell/
β”‚   β”‚   β”œβ”€β”€ service.py   # ShellService
β”‚   β”‚   β”œβ”€β”€ path_utils.py
β”‚   β”‚   └── types.py
β”‚   └── tests/           # Python tests
β”œβ”€β”€ rust/                # Rust implementation
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ lib.rs
β”‚   β”‚   β”œβ”€β”€ service.rs   # ShellService
β”‚   β”‚   β”œβ”€β”€ path_utils.rs
β”‚   β”‚   └── types.rs
β”‚   └── tests/           # Integration tests
└── package.json         # NPM package config

Installation

TypeScript (Node.js)

# Using bun (recommended)
bun add @elizaos/plugin-shell

# Using npm
npm install @elizaos/plugin-shell

# Using pnpm
pnpm add @elizaos/plugin-shell

Python

pip install elizaos-plugin-shell

Rust

Add to your Cargo.toml:

[dependencies]
elizaos-plugin-shell = "1.2.0"

Configuration

Set the following environment variables:

# Set the allowed directory (commands can only run here)
SHELL_ALLOWED_DIRECTORY=/home/user/safe-workspace

# OPTIONAL: Set custom timeout in milliseconds (default: 30000)
SHELL_TIMEOUT=60000

# OPTIONAL: Add additional forbidden commands (comma-separated)
SHELL_FORBIDDEN_COMMANDS=rm,mv,cp,chmod,chown,shutdown,reboot

# OPTIONAL: Maximum output characters to capture (default: 200000)
SHELL_MAX_OUTPUT_CHARS=200000

# OPTIONAL: Milliseconds before backgrounding (default: 10000)
SHELL_BACKGROUND_MS=10000

# OPTIONAL: Allow background execution (default: true)
SHELL_ALLOW_BACKGROUND=true

# OPTIONAL: Session record TTL in milliseconds (default: 1800000 = 30min)
SHELL_JOB_TTL_MS=1800000

Usage Examples

TypeScript

import { shellPlugin, ShellService } from "@elizaos/plugin-shell";

// Use as a plugin
const character = {
  plugins: [shellPlugin],
};

// Or use the service directly
const service = new ShellService(runtime);
const result = await service.executeCommand("ls -la", "conversation-123");

// Advanced: Use exec with PTY and background support
const execResult = await service.exec("npm install", {
  pty: true,         // Run with pseudo-terminal
  background: false, // Or yieldMs: 5000 to auto-background after 5s
  timeout: 300,      // 5 minute timeout
  workdir: "/project",
});

if (execResult.status === "running") {
  console.log(`Background session: ${execResult.sessionId}`);
  
  // Poll for updates
  const pollResult = await service.processAction({
    action: "poll",
    sessionId: execResult.sessionId,
  });
  console.log(pollResult.message);
}

// Get the service from an Eliza agent runtime
const shellService = runtime.getService<ShellService>("shell");

Python

from elizaos_plugin_shell import ShellService, ShellConfig

config = ShellConfig.from_env()
service = ShellService(config)

result = await service.execute_command("ls -la", "conversation-123")
if result.success:
    print(f"Output: {result.stdout}")

Rust

use elizaos_plugin_shell::{ShellConfig, ShellService};

let config = ShellConfig::from_env()?;
let mut service = ShellService::new(config);

let result = service.execute_command("ls -la", Some("conversation-123")).await?;
if result.success {
    println!("Output: {}", result.stdout);
}

πŸ“‹ Available Actions

EXECUTE_COMMAND

Executes ANY shell command within the allowed directory, including file operations.

Examples:

  • run ls -la - List files with details
  • execute npm test - Run tests
  • create a file called hello.txt - Creates a new file
  • check git status - Show git repository status

MANAGE_PROCESS

Manage running and finished shell sessions. Supports the following operations:

Action Description
list List all running and finished sessions
poll Get new output from a running session
log Get session output with offset/limit
write Write data to session stdin
send-keys Send terminal key sequences (arrows, ctrl, etc)
submit Send carriage return (Enter)
paste Paste text with bracketed paste mode
kill Kill a running session
clear Clear a finished session record
remove Kill (if running) and remove session

Examples:

  • list all running processes
  • check session calm-harbor
  • kill the process swift-reef
  • send enter to session brisk-cove

CLEAR_SHELL_HISTORY

Clears the command history for the current conversation.

Examples:

  • clear my shell history
  • reset the terminal history

🧠 Shell History Provider

The plugin includes a SHELL_HISTORY provider that makes the following information available to the agent:

  • Recent Commands: Last 10 executed commands with their outputs
  • Current Working Directory: The current directory within the allowed path
  • Allowed Directory: The configured safe directory boundary
  • File Operations: Recent file creation, modification, and deletion operations

πŸ”’ Security Considerations

Directory Restriction

All commands execute within SHELL_ALLOWED_DIRECTORY:

  • Attempts to navigate outside are blocked
  • Absolute paths outside the boundary are rejected
  • cd .. stops at the allowed directory root

Forbidden Commands

By default, these potentially dangerous commands are blocked:

  • Destructive: rm -rf /, rmdir
  • Permission changes: chmod 777, chown, chgrp
  • System operations: shutdown, reboot, halt, poweroff
  • Process control: kill -9, killall, pkill
  • User management: sudo rm -rf, su, passwd, useradd, userdel
  • Disk operations: format, fdisk, mkfs, dd if=/dev/zero, shred

Additional Safety Features

  • No Shell Expansion: Commands execute without dangerous shell interpretation
  • Timeout Protection: Commands auto-terminate after timeout
  • Command History: All executed commands are logged for audit
  • Path Traversal Protection: Blocks ../ and similar patterns

πŸ§ͺ Development & Testing

TypeScript

cd typescript
bun run build.ts     # Build
npx vitest           # Run tests

Python

cd python
pip install -e ".[dev]"  # Install with dev dependencies
pytest                    # Run tests
mypy elizaos_plugin_shell # Type check

Rust

cd rust
cargo build --release  # Build
cargo test             # Run tests

All Languages

# From plugin root
bun run build          # Build TypeScript
bun run build:python   # Build Python
bun run build:rust     # Build Rust
bun run test           # Test TypeScript
bun run test:python    # Test Python
bun run test:rust      # Test Rust

πŸ“– API Reference

CommandResult

Field Type Description
success boolean Whether the command executed successfully
stdout string Standard output from the command
stderr string Standard error output
exitCode number | null Exit code of the command
error string | undefined Error message if command failed
executedIn string Directory where command was executed

FileOperation

Field Type Description
type FileOperationType Type of operation (create, write, read, delete, mkdir, move, copy)
target string Target file/directory path
secondaryTarget string | undefined Secondary target for move/copy

ShellConfig

Field Type Default Description
enabled boolean false Whether shell is enabled
allowedDirectory string cwd Directory to restrict commands to
timeout number 30000 Timeout in milliseconds
forbiddenCommands string[] [...] List of forbidden commands
maxOutputChars number 200000 Max output characters to capture
pendingMaxOutputChars number 200000 Max pending output per stream
defaultBackgroundMs number 10000 Default background yield window
allowBackground boolean true Allow background execution

ProcessSession

Field Type Description
id string Unique session identifier (slug)
command string The executed command
pid number | undefined Process ID
startedAt number Start timestamp
cwd string | undefined Working directory
aggregated string Accumulated output
tail string Last 2000 chars of output
exited boolean Whether process has exited
exitCode number | null Exit code (if exited)
exitSignal string | number | null Exit signal (if killed)
truncated boolean Whether output was truncated
backgrounded boolean Whether running in background

ExecResult

type ExecResult =
  | { status: "running"; sessionId: string; pid?: number; startedAt: number; cwd?: string; tail?: string }
  | { status: "completed" | "failed"; exitCode: number | null; durationMs: number; aggregated: string; cwd?: string; timedOut?: boolean; reason?: string }

ExecuteOptions

Field Type Description
workdir string Working directory
env Record<string, string> Additional environment variables
yieldMs number Yield to background after this time
background boolean Run immediately in background
timeout number Timeout in seconds
pty boolean Use pseudo-terminal
conversationId string Conversation ID for history tracking
scopeKey string Scope key for session isolation
sessionKey string Session key for notifications
notifyOnExit boolean Notify on background exit
onUpdate (session) => void Callback for output updates

🀝 Contributing

Contributions are welcome! Please ensure:

  1. All three language implementations stay in feature parity
  2. Tests pass for all languages
  3. Follow the code style of each language
  4. Update documentation as needed

πŸ“ License

MIT - See LICENSE for details.

About

A shell plugin for ElizaOS. USE AT YOUR OWN RISK. THIS GIVES AI FULL ACCESS TO THE HOST MACHINE

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors