Shell Escape

Run a shell command inline in praisonai code without spending a model turn

Next

Type !cmd in an interactive session to run a shell command without spending a model turn. !!cmd also attaches the output as context for your next message.

python
from praisonaiagents import Agent

# The shell escape lives in the `praisonai code` interactive REPL/TUI,
# not on the Agent class. Nothing to configure on the agent itself —
# just launch a session and enable the gate:
agent = Agent(
    name="Coder",
    instructions="You are a coding assistant.",
)

# Then from your terminal:
#   $ export PRAISONAI_ALLOW_SHELL=true
#   $ praisonai code
#   > !git status                # run inline, no model turn
#   > !!git diff                 # attach output as context for the next prompt
#   > summarise the change       # this turn sees the diff
Diagram

Shell Escape

off

on

!!cmd

⌨️ !cmd

🔐 Gate on?

💡 Enable hint

🖥️ Gated executor

✅ Inline output

📎 Next-turn context

Quick Start

  1. Enable the gate and run a command

    Shell escape is off by default. Enable it, launch a session, and run a command inline:

    bash
    export PRAISONAI_ALLOW_SHELL=true
    praisonai code
    bash
    > !git status
    On branch main
    nothing to commit, working tree clean

    The command runs immediately and prints its output — no model turn is spent.

  2. Attach output as context

    Prefix with !! to also stash the output as context for your next message:

    bash
    > !!git diff
    [diff prints here]
    Output attached as context for the next message.
    
    > summarise the change

    The follow-up turn sees the diff, prefixed as [shell output].


How It Works

The !cmd path never calls the model — agent.start() only fires on your next real prompt, prefixed with [shell output] if a !!cmd is pending.

Diagram
Gated executorREPLUserGated executorREPLUseragent.start() fires here!git statusrun_shell_escape(“git status”)output (no model call)inline output!!git diffrun_shell_escape(“git diff”)output (stashed as context)“attached for next message”summarise the changeprepend [shell output]
PrefixRuns commandSpends a model turnAttaches output
!cmdYesNoNo
!!cmdYesNo (until next prompt)Yes

!cmd vs !!cmd

Pick ! for a quick peek and !! when you want the model to read the output.

Diagram

Just looking

Model should use it

🤔 Need shell output?

Should the model
read it?

⌨️ !cmd

📎 !!cmd

Prints inline, nothing attached

Prints inline + attached next turn


Configuration

Shell escape reuses the same gate that powers ` !cmd ` template substitution — there is no second flag to remember.

Environment variable

bash
export PRAISONAI_ALLOW_SHELL=true
praisonai code

Config file

yaml
# .praisonai/config.yaml
commands:
  allow_shell: true

Safety Limits

Shell escape carries the same safety posture as ` !cmd ` template substitution.

LimitValue
Timeout30 s
Output cap100 KB
Default stateOff

Failure Behaviour

A non-zero exit, timeout, or output cap never raises into the REPL loop — the diagnostic is rendered inline instead. For !!cmd, the error text is still attached as context so the model can help debug it.

bash
> !!pytest -x
[test failures print here]
Output attached as context for the next message.

> why did this fail?

The failing output is attached, so the follow-up turn can reason about it.


Pending-Context Lifecycle

!!cmd output is retained until the next model call succeeds. If that call raises, the context stays so you can retry without re-running the command.


Common Patterns

Review a staged diff with the model:

bash
> !!git diff --staged
> review this diff

Debug a failing test:

bash
> !!pytest -x
> why did this fail?

Quick peek with no attach:

bash
> !ls -la

Best Practices

Keep the gate off for unattended surfaces

Bots and webhooks that never need a shell should leave PRAISONAI_ALLOW_SHELL unset. Default-off keeps unattended surfaces shell-free.

Prefer !!cmd for context you actually want the model to read

Attaching everything bloats prompts. Use ! for a quick look and reserve !! for output the model needs.

Combine with @file mentions

Pair shell escape with @file mentions to give the model both live output and file content in one turn. See the @file mentions docs.

Beware the 100 KB cap for verbose commands

Output is capped at 100 KB. Pipe noisy commands through head, tail, or grep first to keep the useful lines.


Related