Class: Tools::Bash

Inherits:
Base
  • Object
show all
Defined in:
lib/tools/bash.rb

Overview

Executes bash commands in a persistent ShellSession. Commands share working directory, environment variables, and shell history within a conversation. Output is truncated and timeouts are enforced by the underlying session.

Supports two modes:

  • Single command via command (string) — backward compatible

  • Batch via commands (array) with mode controlling error handling

See Also:

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Base

schema, truncation_threshold

Constructor Details

#initialize(shell_session:, session:) ⇒ Bash

Returns a new instance of Bash.

Parameters:

  • shell_session (ShellSession)

    persistent shell backing this tool

  • session (Session)

    conversation session for interrupt checking



42
43
44
45
# File 'lib/tools/bash.rb', line 42

def initialize(shell_session:, session:, **)
  @shell_session = shell_session
  @session = session
end

Class Method Details

.descriptionObject



17
# File 'lib/tools/bash.rb', line 17

def self.description = "Execute shell commands. Working directory and environment persist between calls."

.input_schemaObject



19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/tools/bash.rb', line 19

def self.input_schema
  {
    type: "object",
    properties: {
      command: {
        type: "string"
      },
      commands: {
        type: "array",
        items: {type: "string"},
        description: "Each command gets its own timeout and result."
      },
      mode: {
        type: "string",
        enum: ["sequential", "parallel"],
        description: "sequential (default) stops on first failure."
      }
    }
  }
end

.tool_nameObject



15
# File 'lib/tools/bash.rb', line 15

def self.tool_name = "bash"

Instance Method Details

#dynamic_schemaHash

Returns tool schema with the shell’s current working directory embedded in the description so the agent sees it during tool selection — eliminating redundant cd prefixes.

Returns:

  • (Hash)

    Anthropic tool schema with dynamic description



52
53
54
55
56
# File 'lib/tools/bash.rb', line 52

def dynamic_schema
  schema = self.class.schema.deep_dup
  schema[:description] = "Execute shell commands in #{@shell_session.pwd}. Working directory and environment persist between calls."
  schema
end

#execute(input) ⇒ String, Hash

Parameters:

  • input (Hash<String, Object>)

    string-keyed hash from the Anthropic API. Supports optional “timeout” key (seconds) to override the global command_timeout setting for long-running operations.

Returns:

  • (String)

    formatted output with stdout, stderr, and exit code

  • (Hash)

    with :error key on failure



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/tools/bash.rb', line 63

def execute(input)
  timeout = input["timeout"]
  has_command = input.key?("command")
  has_commands = input.key?("commands")

  if has_command && has_commands
    {error: "Provide either 'command' or 'commands', not both"}
  elsif has_commands
    execute_batch(input["commands"], mode: input.fetch("mode", "sequential"), timeout: timeout)
  elsif has_command
    execute_single(input["command"], timeout: timeout)
  else
    {error: "Either 'command' (string) or 'commands' (array of strings) is required"}
  end
end