Skip to main content
PRAISON_SHELL picks the containment posture for every execute_command call in praisonai code: refuse shell operators, run every command inside an OS sandbox, or run operators in an uncontained shell.

Quick Start

1

Default — operators are refused

Without PRAISON_SHELL, the coding agent runs plain commands as before, but a command with a shell operator fails loudly instead of silently dropping it.
2

Contain every command

Set PRAISON_SHELL=sandboxed to run every command — with or without operators — as a real /bin/sh -c inside OS-native containment (Seatbelt on macOS, bwrap on Linux).

The Three Modes

PRAISON_SHELL selects one behaviour. It is an operator decision — the model cannot change it from a tool call. Aliases resolve to these three: 1/true/yes/sandbox/native → sandboxed; raw/host → unsafe; empty/0/false/no/none → off.

What sandboxed protects against

Containment is a property of the mode, not of the command’s syntax. rm -rf build, python x.py, pip install pkg or curl -o x.sh URL have no operator, yet all run inside the jail.

Workspace, env, and secret masking


Guarantees against model misuse

The tool-facing execute_command drops mode, writable_paths and network from its arguments. A tool call cannot pick mode="unsafe", writable_paths=["/"] or network=True — the mode and the jail are set by the operator through env vars.
run_in_background=True is refused under sandboxed. The contained runner has no process registry, so a background request would block until the timeout killed the process the caller expected back. Run such commands in the foreground.
Cancellation. A contained command stops when the agent is interrupted: the process tree is killed, output is capped, and the result reports exit_code=130 with error="Command interrupted by user". ACP in sandboxed mode. Headless praisonai code -p exposes acp_execute_command. Under sandboxed, its approved plan steps run inside the same jail with the workspace as the writable root, without a second approval prompt. Under off and unsafe, the ACP path still refuses ;, &, |, $ and backticks.

Why the default refuses

The plain executor runs shlex.split + subprocess.Popen(shell=False), so an operator becomes a literal argument.
The model is told a redirect it never performed succeeded — strictly worse than an error. Refusing names the operator and tells the agent what to do instead.

Quote-Aware Detection

Detection looks for operators outside quotes, so ordinary strings are never refused. $(...) and backticks are detected even inside double quotes because POSIX shells evaluate them there — reporting them as inert would reintroduce the false-success bug.

Approval

The real-shell path used by execute_command is wrapped in require_approval(risk_level="critical") under the tool name execute_command.
Both sandboxed and unsafe route through the same critical-risk approval as the plain executor — same tool identity, so existing allowlists and path_overlap serialisation still apply. Denying approval raises PermissionError and no file is written.
ACP plan steps under sandboxed reuse the plan-level approval and do not re-prompt per command. The approval wrap fails closed: if the approval machinery can’t be imported, the real shell does not run.

When Your Agent Hits a Refusal

An agent that hits PRAISON_SHELL=off refusal has three honest paths.
The operator can instead launch the session with PRAISON_SHELL=sandboxed to allow real operators inside a jail. Under sandboxed, a command can be refused even without an operator:

Best Practices

off never runs an uninterpreted operator and never claims false success. Reach for sandboxed only when a real shell is genuinely needed.
sandboxed gives a real /bin/sh while a kernel keeps writes inside the workspace. unsafe removes that boundary entirely — use it only when you accept an uncontained shell deliberately.
Two execute_command calls (one per && step) work in every mode and keep each step’s success signal honest.
Replace cmd > file.txt with a plain cmd call plus write_file. This works in off mode and keeps the file-creation step explicit.

OS Sandbox

Seatbelt and bwrap containment that sandboxed mode runs inside.

Safe Tools by Default

Why tools refuse rather than degrade.

Interactive Tools

The execute_command tool in the coding session.

Tool Approval

The critical-risk approval wrap on the real-shell path.