Omni.Tools.Bash.Runner (Omni Tools v0.1.0)

Copy Markdown View Source

Executes shell commands via a Port and returns captured output.

Each invocation spawns a new shell process, captures merged stdout/stderr, and returns the output alongside the exit code. No state carries over between calls.

Runner.run("echo hello", {"/bin/bash", ["-c"]}, dir: "/tmp")
#=> {:ok, %{output: "hello\n", exit_code: 0}}

Runner.run("exit 1", {"/bin/bash", ["-c"]}, dir: "/tmp")
#=> {:error, :nonzero, %{output: "", exit_code: 1}}

The runner executes arbitrary shell commands with full system access. It is not a security boundary — OS-level sandboxing (containers, restricted users) is the caller's responsibility.

Options

  • :dir (required) — working directory for the command
  • :env — extra environment variables as [{String.t(), String.t()}], merged additively with the inherited environment. Default []
  • :timeout — execution timeout in milliseconds. Default 30_000
  • :max_output — output truncation limit in bytes. Tail-biased, snapped to line boundaries. Default 50_000
  • :command_prefix — string prepended to every command. Default nil

Return values

{:ok, %{output: "hello\n", exit_code: 0}}
{:error, :nonzero, %{output: "error msg\n", exit_code: 1}}
{:error, :timeout, %{output: "partial..."}}

On success, exit_code is always 0. On a non-zero exit, the output captured up to that point is included. On timeout, partial output collected before the deadline is returned.

Summary

Types

Result of a command execution — success, non-zero exit, or timeout.

Functions

Resolves the shell to use for command execution.

Executes command in the given shell and returns captured output.

Types

result()

@type result() ::
  {:ok, %{output: String.t(), exit_code: 0}}
  | {:error, :nonzero, %{output: String.t(), exit_code: pos_integer()}}
  | {:error, :timeout, %{output: String.t()}}

Result of a command execution — success, non-zero exit, or timeout.

Functions

resolve_shell(opts)

@spec resolve_shell(keyword()) :: {String.t(), [String.t()]}

Resolves the shell to use for command execution.

Checks in order: explicit :shell option, /bin/bash, /bin/sh. Returns a {executable, args} tuple suitable for Port.open/2.

Raises ArgumentError if no usable shell is found or the option is invalid.

Runner.resolve_shell([])
#=> {"/bin/bash", ["-c"]}

Runner.resolve_shell(shell: {"/bin/zsh", ["-c"]})
#=> {"/bin/zsh", ["-c"]}

run(command, arg, opts \\ [])

@spec run(String.t(), {String.t(), [String.t()]}, keyword()) :: result()

Executes command in the given shell and returns captured output.

The shell argument is a {executable, args} tuple — the command string is appended to args when spawning the port.