Shell command execution for the BeamAgent SDK.
This module provides a unified interface for running operating-system shell
commands from within any backend session handler or application code. Execution
is performed via Erlang ports using spawn_executable so it is safe,
timeout-aware, and captures both stdout and stderr.
When to use directly vs through BeamAgent
Use this module directly when your code needs to run OS-level commands — for example, in a custom tool handler, a test helper, or a build step executed as part of an agentic workflow.
Basic usage
{:ok, %{exit_code: 0, output: out}} = BeamAgent.Command.run("ls -la")
{:ok, %{exit_code: code, output: out}} = BeamAgent.Command.run("make test", %{
cwd: "/my/project",
timeout: 60_000
})Argument list form
Pass a list of binaries or strings to avoid shell quoting issues:
{:ok, result} = BeamAgent.Command.run(["git", "log", "--oneline"])Each segment is passed as part of a direct executable plus argument vector.
String and binary commands still
go through the detected shell (sh or cmd.exe) for shell semantics.
Commands always pass through a security baseline before execution. When the full command guard is initialized, the SDK uses the full stateful policy/validator/rate-limit pipeline. Otherwise, it still applies the default deny policy before opening the port.
Error handling
{:error, {:timeout, ms}}— command did not finish within the timeout{:error, {:port_exit, reason}}— the port process exited abnormally{:error, {:port_failed, reason}}— the port could not be opened
A non-zero exit code is not returned as {:error, ...} — inspect
exit_code in the result map.
Summary
Functions
Run a command through the backend's command execution facility.
Run a command through the backend's command execution facility with options.
Write data to the stdin of a running command.
Write data to the stdin of a running command with options.
Send a prompt asynchronously without blocking for the full response.
Send a prompt asynchronously with options.
Run a shell command with default options.
Run a shell command with explicit options.
Send a named command to the backend.
Destroy the current session and clean up all associated state.
Destroy a specific session by its identifier.
Perform backend-specific session initialization.
Get all messages for the current session.
Get messages for the current session with filtering options.
Execute a shell command in the session's working directory.
Execute a shell command with options.
Submit user feedback about the session or a specific response.
Append text to the TUI prompt input buffer.
Open the TUI help panel.
Respond to a turn-based request from the backend.
Types
@type command_opts() :: map()
Options accepted by run/2.
All fields are optional:
:timeout— maximum execution time in milliseconds (default: 30_000):cwd— working directory for the spawned process:env— extra environment variables as[{"KEY", "VALUE"}]string pairs:max_output— maximum bytes of output to capture (default: 1_048_576 = 1 MB)
@type command_result() :: map()
Map returned on successful command completion.
Fields:
:exit_code— OS exit code;0conventionally means success:output— captured stdout and stderr as a single binary
Functions
Run a command through the backend's command execution facility.
Convenience wrapper that calls command_run/3 with empty options.
Parameters
session-- pid of a running session.command-- binary command string or list of binary args.
Returns
{:ok, result}or{:error, reason}.
Run a command through the backend's command execution facility with options.
Executes command via the backend's native command runner (which may
apply sandboxing, permission checks, or audit logging).
Parameters
session-- pid of a running session.command-- binary command string or list of binary args.opts-- options map (:timeout,:env,:cwd).
Returns
{:ok, result}or{:error, reason}.
Write data to the stdin of a running command.
Convenience wrapper that calls command_write_stdin/4 with empty options.
Parameters
session-- pid of a running session.process_id-- binary process identifier from a previouscommand_runcall.stdin-- binary data to write to stdin.
Returns
{:ok, result}or{:error, reason}.
Write data to the stdin of a running command with options.
Parameters
session-- pid of a running session.process_id-- binary process identifier.stdin-- binary data to write.opts-- backend-specific options map.
Returns
{:ok, result}or{:error, reason}.
Send a prompt asynchronously without blocking for the full response.
Convenience wrapper that calls prompt_async/3 with empty options.
This operation requires a live session pid; persisted session ids
return {:error, :requires_live_session} from the Erlang layer.
Parameters
session-- pid of a running session.prompt-- the user prompt as a binary string.
Returns
{:ok, result_map}with a:request_idkey.{:error, reason}on failure.
Send a prompt asynchronously with options.
Submits prompt to the backend and returns immediately with a result
map containing a :request_id. Use BeamAgent.event_subscribe/1 and
BeamAgent.receive_event/2 to collect the streamed response. This
operation requires a live session pid; persisted session ids return
{:error, :requires_live_session} from the Erlang layer.
Parameters
session-- pid of a running session.prompt-- the user prompt as a binary string.opts-- query parameters map (:system_prompt,:model, etc.).
Returns
{:ok, result_map}or{:error, reason}.
@spec run(binary() | String.t() | [binary() | String.t()]) :: {:ok, command_result()} | {:error, term()}
Run a shell command with default options.
Accepts a binary command string, a plain string, or a list of binary/string segments. List-form commands execute directly as an executable plus argument vector instead of going through shell quoting.
Returns {:ok, command_result()} on completion (regardless of exit code), or
{:error, reason} if the port could not be started or timed out.
Example
{:ok, %{exit_code: 0, output: bin}} = BeamAgent.Command.run("echo hello")
@spec run(binary() | String.t() | [binary() | String.t()], command_opts()) :: {:ok, command_result()} | {:error, term()}
Run a shell command with explicit options.
Parameters:
command— binary string, plain string, or list of segmentsopts— acommand_opts()map controlling timeout, cwd, env, and max output
Example
{:ok, result} = BeamAgent.Command.run("npm test", %{
cwd: "/srv/app",
timeout: 120_000,
env: [{"NODE_ENV", "test"}]
})
%{exit_code: code, output: out} = result
Send a named command to the backend.
A general-purpose dispatch mechanism for backend-specific commands that do not have dedicated API functions.
Parameters
session-- pid of a running session.command-- binary command name.params-- map of command arguments.
Returns
{:ok, result}or{:error, reason}.
Destroy the current session and clean up all associated state.
Removes the session from the session store, runtime registry, config store,
feedback store, callback registry, and tool registry. More thorough than
BeamAgent.stop/1, which only terminates the process.
Parameters
session-- pid of a running session.
Returns
{:ok, result}or{:error, reason}.
Destroy a specific session by its identifier.
Same as session_destroy/1 but targets a specific session_id, which
may differ from the calling session's own identifier.
Parameters
session-- pid of a running session.session_id-- binary session identifier to destroy.
Returns
{:ok, result}or{:error, reason}.
Perform backend-specific session initialization.
Called after BeamAgent.start_session/1 to complete any additional setup
that requires an active transport connection.
Parameters
session-- pid of a running session.opts-- backend-specific initialization parameters map.
Returns
{:ok, result}or{:error, reason}.
Get all messages for the current session.
Returns the complete message history for the session's active conversation.
Parameters
session-- pid of a running session.
Returns
{:ok, messages}or{:error, reason}.
Get messages for the current session with filtering options.
opts may include pagination keys (:limit, :offset) or filters
(:role, :type) to narrow the returned message list.
Parameters
session-- pid of a running session.opts-- filter options map.
Returns
{:ok, messages}or{:error, reason}.
Execute a shell command in the session's working directory.
Convenience wrapper that calls shell_command/3 with empty options.
Parameters
session-- pid of a running session.command-- binary shell command string.
Returns
{:ok, result}or{:error, reason}.
Execute a shell command with options.
Runs command as a subprocess in the session's working directory.
Parameters
session-- pid of a running session.command-- binary shell command string.opts-- options map (:timeout,:env).
Returns
{:ok, result}or{:error, reason}.
Submit user feedback about the session or a specific response.
feedback may contain :rating, :comment, and :message_id.
Parameters
session-- pid of a running session.feedback-- feedback map.
Returns
{:ok, result}or{:error, reason}.
Append text to the TUI prompt input buffer.
Injects text into the terminal UI's prompt field as if the user typed it.
Only meaningful for backends with a native terminal interface.
Parameters
session-- pid of a running session.text-- binary text to append.
Returns
{:ok, result}or{:error, reason}.
Open the TUI help panel.
This operation requires a native terminal backend. The universal fallback
returns a status: :not_applicable result.
Parameters
session-- pid of a running session.
Returns
{:ok, result}or{:error, reason}.
Respond to a turn-based request from the backend.
Some backends issue permission or tool-use requests that require explicit
approval. request_id identifies the pending request; params contains
the response payload (e.g., %{approved: true}).
Parameters
session-- pid of a running session.request_id-- binary request identifier.params-- response payload map.
Returns
{:ok, result}or{:error, reason}.