bash data types: inputs and outputs
The bash module has one request type and a small set of stream / error types.
All stream/error types below live in cosh_tools::bash::bsh — only
BashRunInput is re-exported at the bash root. Bash::run’s signature
uses them, so import from bash::bsh::… when you need to name a concrete
type (the example does).
Request type
BashRunInput — the bash_run arguments
pub struct BashRunInput {
/// The bash command to execute. Must not be an absolute path
/// and must not match dangerous security patterns.
pub command: String,
}
This is the entire per-call input. Configuration that changes execution —
cwd, env, timeout, pty — lives on the Bash
wrapper and is fixed when the harness builds its tool set. It derives
Deserialize and JsonSchema, so the same struct both parses the tool
arguments and can generate their schema (the inputSchema on
description_run mirrors it by hand).
Stream item
SpawnOutput — one item in the output stream
pub struct SpawnOutput {
pub stdout: Vec<u8>, // a stdout chunk (≤ 4096 bytes), or empty
pub stderr: Vec<u8>, // a stderr chunk (≤ 4096 bytes), or empty
pub exit_code: Option<i32>, // set exactly once: the process exited normally
pub signal: Option<i32>, // set exactly once: killed by a signal, or timeout
pub truncated: bool, // this chunk filled the whole 4096-byte buffer
}
Bash::run yields a stream of these. The three item kinds and their
invariants are described on the module page;
the essentials:
- Chunks have non-empty
stdoutorstderrand both status fieldsNone. - The status item has empty
stdout/stderrand exactly one ofexit_code/signalset.exit_codeandsignalare mutually exclusive: a normal exit setsexit_code(0 or not); a signal death setssignalto the Unix signal number; a timeout setssignalto-1. truncatedistruewhen a chunk exactly filled the 4096-byte read buffer — a per-chunk “more may be coming” hint, not an aggregate total.- Both
stdoutandstderrare raw bytes, not text: the program may emit arbitrary bytes, and PTY mode rewrites\nto\r\n. Decode withString::from_utf8_lossywhen displaying.
Error and helper types
BashError — the error from Bash::run
pub struct BashError {
pub text_err: Option<String>, // validation or human-readable reason
pub exec_err: Option<ExecError>, // present only for execution-stage failures
}
Bash::run returns Result<_, BashError> and only fails on validation:
an absolute command path, or a command matching a dangerous security pattern.
In both cases text_err holds the reason (e.g. "absolute command not allowed, use relative path" or "Pattern match found: …") and exec_err is
None.
The harness renders an error from text_err, falling back to a signal summary
from exec_err when text_err is absent.
ExecError
pub struct ExecError {
pub stderr: Option<String>,
pub signal: Option<i32>,
}
The execution-stage error payload carried by BashError::exec_err.
BashOutput
pub struct BashOutput {
pub stdout: Option<String>,
pub exit_code: Option<i32>,
pub signal: Option<i32>,
}
A legacy convenience aggregate (no stderr, no chunk granularity). Prefer
consuming the SpawnOutput
stream directly.
Stream errors are dropped by
Bash::run. The underlying executor emits stream errors (Err(io::Error)) for runtime failures — an invalid environment-variable name (ErrorKind::InvalidInput), a nonexistentcwd, a spawn failure. The wrapper’s stream only yieldsOkitems, so those surface as a silently truncated/empty stream, not as anErrfromBash::run. Only the pre-spawn validation produces a real error. This is intentional at the engine level (see the executor reference); when you need these failures, consume the engine’s rawResult-carrying stream or validate inputs yourself.
The ToolDescription on Bash
Bash::description_run is a ready-to-serve MCP tool description
({ "name", "description", "inputSchema" }) for the bash_run tool. Its
inputSchema requires exactly one property — command — matching
BashRunInput above. The prose
description covers the security validation, the streaming semantics, and the
harness truncation behavior (output over the token budget is head/tail-cut
with the middle recoverable via fs_read / find_grep).