> ## Documentation Index
> Fetch the complete documentation index at: https://praison.ai/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Shell Escape

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

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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
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
```

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Shell Escape"
        In["⌨️ !cmd"] --> Gate{"🔐 Gate on?"}
        Gate -->|off| Hint["💡 Enable hint"]
        Gate -->|on| Run["🖥️ Gated executor"]
        Run --> Out["✅ Inline output"]
        Out -.->|!!cmd| Ctx["📎 Next-turn context"]
    end

    classDef input fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef gate fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef proc fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef ok fill:#10B981,stroke:#7C90A0,color:#fff
    classDef warn fill:#F59E0B,stroke:#7C90A0,color:#fff

    class In input
    class Gate gate
    class Run proc
    class Out ok
    class Hint,Ctx warn
```

## Quick Start

<Steps>
  <Step title="Enable the gate and run a command">
    Shell escape is off by default. Enable it, launch a session, and run a command inline:

    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    export PRAISONAI_ALLOW_SHELL=true
    praisonai code
    ```

    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    > !git status
    On branch main
    nothing to commit, working tree clean
    ```

    The command runs immediately and prints its output — no model turn is spent.
  </Step>

  <Step title="Attach output as context">
    Prefix with `!!` to also stash the output as context for your next message:

    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    > !!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]`.
  </Step>
</Steps>

***

## 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.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant REPL
    participant Executor as Gated executor

    User->>REPL: !git status
    REPL->>Executor: run_shell_escape("git status")
    Executor-->>REPL: output (no model call)
    REPL-->>User: inline output

    User->>REPL: !!git diff
    REPL->>Executor: run_shell_escape("git diff")
    Executor-->>REPL: output (stashed as context)
    REPL-->>User: "attached for next message"

    User->>REPL: summarise the change
    REPL->>REPL: prepend [shell output]
    Note over REPL: agent.start() fires here
```

| Prefix  | Runs command | Spends a model turn    | Attaches output |
| ------- | ------------ | ---------------------- | --------------- |
| `!cmd`  | Yes          | No                     | No              |
| `!!cmd` | Yes          | No (until next prompt) | Yes             |

***

## `!cmd` vs `!!cmd`

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

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Start["🤔 Need shell output?"] --> Q{"Should the model<br/>read it?"}
    Q -->|Just looking| One["⌨️ !cmd"]
    Q -->|Model should use it| Two["📎 !!cmd"]
    One --> R1["Prints inline, nothing attached"]
    Two --> R2["Prints inline + attached next turn"]

    classDef start fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef gate fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef ok fill:#10B981,stroke:#7C90A0,color:#fff
    classDef warn fill:#F59E0B,stroke:#7C90A0,color:#fff

    class Start start
    class Q gate
    class One ok
    class Two warn
    class R1,R2 gate
```

***

## Configuration

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

<Tabs>
  <Tab title="Environment variable">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    export PRAISONAI_ALLOW_SHELL=true
    praisonai code
    ```
  </Tab>

  <Tab title="Config file">
    ```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    # .praisonai/config.yaml
    commands:
      allow_shell: true
    ```
  </Tab>
</Tabs>

<Note>The environment variable wins if set to a truthy value; otherwise the `commands.allow_shell` config flag is consulted. When neither is set, typing `!ls` prints a one-line enable hint and never runs the command.</Note>

***

## Safety Limits

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

| Limit         | Value  |
| ------------- | ------ |
| Timeout       | 30 s   |
| Output cap    | 100 KB |
| Default state | Off    |

***

## 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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> !!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 theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> !!git diff --staged
> review this diff
```

Debug a failing test:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> !!pytest -x
> why did this fail?
```

Quick peek with no attach:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> !ls -la
```

***

## Best Practices

<AccordionGroup>
  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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/docs/cli/interactive-tui) docs.
  </Accordion>

  <Accordion title="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.
  </Accordion>
</AccordionGroup>

***

## Related

<CardGroup cols={2}>
  <Card title="Interactive TUI" icon="rectangle-terminal" href="/docs/docs/cli/interactive-tui">
    The full interactive terminal interface, including `@file` mentions.
  </Card>

  <Card title="Slash Commands" icon="terminal" href="/docs/docs/cli/slash-commands">
    Registered `/cmd` commands — a sibling input path to `!cmd`.
  </Card>

  <Card title="Custom Agents & Commands" icon="file-code" href="/docs/docs/features/custom-agents-commands">
    The sibling `` !`cmd` `` template substitution — same gate.
  </Card>
</CardGroup>
