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

# Code

> Code assistant mode for programming tasks

The `code` command starts a code assistant session optimized for programming tasks.

<Note>
  As of PR #3818, `praisonai code` runs its resident TUI directly from `pip install praisonai-code` — no wrapper required. Installing the full `praisonai` wrapper enables the *richer* legacy dispatch (`PraisonAI._start_interactive_mode`), which takes over when present.
</Note>

<Note>
  `praisonai code` is **safe by default**: file writes and shell commands prompt for approval on first call. Pass `--no-safe` or `--dangerously-skip-approval` to restore the legacy ungated behaviour. Use `--plan` to make the session strictly read-only — every mutating tool is denied outright rather than gated by an approval prompt. See [Tool Approval](/docs/cli/tool-approval).
</Note>

## Usage

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code [OPTIONS] [PROMPT]
```

## Arguments

| Argument | Description                     |
| -------- | ------------------------------- |
| `PROMPT` | Code-related prompt or question |

## Options

| Option                               | Short | Description                                                                                                                                                                                                                                                                                                                                     | Default              |
| ------------------------------------ | ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------- |
| `--model`                            | `-m`  | LLM model to use                                                                                                                                                                                                                                                                                                                                | `gpt-4o-mini`        |
| `--verbose`                          | `-v`  | Verbose output                                                                                                                                                                                                                                                                                                                                  | `false`              |
| `--tools`                            | `-t`  | Comma-separated tool names (e.g. `web_search,github`) or a `tools.py` file path                                                                                                                                                                                                                                                                 |                      |
| `--workspace`                        | `-w`  | Root the code tools at this directory (sets `PRAISONAI_WORKSPACE`). Default: current directory, or the resumed session's directory when `--continue` / `--session` is used.                                                                                                                                                                     |                      |
| `--file`                             | `-f`  | Attach file(s) to context                                                                                                                                                                                                                                                                                                                       |                      |
| `--no-acp`                           |       | Disable ACP tools (file operations)                                                                                                                                                                                                                                                                                                             | `false`              |
| `--no-lsp`                           |       | Disable LSP tools (code intelligence)                                                                                                                                                                                                                                                                                                           | `false`              |
| `--safe` / `--no-safe`               |       | Safe mode: prompt before file writes and shell commands (default: **on**). `--no-safe` disables it and registers `AutoApproveBackend` on the approval registry. Re-running in safe mode within the same process clears a bypass a prior `--no-safe` installed.                                                                                  | `true`               |
| `--dangerously-skip-approval`        |       | Skip all tool approval prompts. Registers `AutoApproveBackend` on the approval registry (so the core `@require_approval` gate is also bypassed) **and** exports `PRAISON_APPROVAL_MODE=auto` / `PRAISONAI_TOOL_SAFETY=off` for the subprocess tree. Strictly opt-in; mutually exclusive with `--plan`. See [Tool Approval](/docs/cli/tool-approval). | `false`              |
| `--plan`                             |       | Read-only planning mode — the agent may explore/read/search but every mutating tool is denied. Discoverable alias for the read-only planning permission mode. Cannot be combined with `--no-safe` or `--dangerously-skip-approval` (exits 1).                                                                                                   | `false`              |
| `--session`                          | `-s`  | Session ID to resume                                                                                                                                                                                                                                                                                                                            |                      |
| `--resume`                           |       | Resume a session by id in headless `-p` mode (alias of `--session` for scripted multi-turn). `--session` still wins when both are set.                                                                                                                                                                                                          |                      |
| `--continue`                         | `-c`  | Continue last session                                                                                                                                                                                                                                                                                                                           | `false`              |
| `--print`                            | `-p`  | Headless one-shot: emit a clean machine-readable result and exit with a status-reflecting code. Requires a prompt.                                                                                                                                                                                                                              | `false`              |
| `--output`                           | `-o`  | Output format for `-p`: `json` (default) or `text`. Requires `-p`.                                                                                                                                                                                                                                                                              | `json` when `-p` set |
| `--no-context`                       |       | Disable AGENTS.md/CLAUDE.md auto-loading into system prompt                                                                                                                                                                                                                                                                                     | `false`              |
| `--pure` / `--no-plugins`            |       | Skip discovery/loading of external plugins for this run only (equivalent to `PRAISONAI_NO_PLUGINS=1`); persisted enable/disable state is unchanged.                                                                                                                                                                                             | `false`              |
| `--agent`                            | `-a`  | Named custom agent profile from `.praisonai/agents/` (tools + permission scope)                                                                                                                                                                                                                                                                 |                      |
| `--thinking`                         |       | Reasoning effort for this invocation: `off`, `minimal`, `low`, `medium`, `high`                                                                                                                                                                                                                                                                 |                      |
| `--max-steps`                        |       | Maximum tool-calling steps for this coding session. Raises **both** `ExecutionConfig.max_steps` and `ExecutionConfig.max_tool_calls_per_turn` (the two tool loops enforce different knobs). Env fallback: `PRAISONAI_CODE_MAX_STEPS`. See [Step budget for coding sessions](#step-budget-for-coding-sessions).                                  | `200`                |
| `--append-system-prompt`             |       | Append text (literal or `@file`) to the system prompt for this invocation only. Env fallback: `PRAISONAI_APPEND_SYSTEM_PROMPT`. Never persisted. See [Append System Prompt](/docs/features/append-system-prompt).                                                                                                                                    | `None`               |
| `--checkpoints` / `--no-checkpoints` |       | Auto-checkpoint the workspace before each file-mutating turn, enabling in-session `/undo` and `/revert`. **On by default** for interactive `praisonai code`; pass `--no-checkpoints` to disable it for this run.                                                                                                                                | `--checkpoints`      |
| `--revert <ref>`                     |       | One-shot: restore workspace to a prior checkpoint (`id`, short id, or `last`) and exit                                                                                                                                                                                                                                                          | —                    |

<Note>
  Safe mode (`--safe`) is **on by default** as of PR #2369. Dangerous built-in tools ask for approval in interactive sessions and are denied in non-interactive (CI) sessions. Use `--no-safe` to opt out, or `--dangerously-skip-approval` for a complete bypass — both register `AutoApproveBackend` on the approval registry so the core `@require_approval` gate is also bypassed. A safe-mode run *clears* a bypass a prior `--no-safe` call left in the same process (REPL/worker/test), removing only the backend it installed itself. See [Approval](/docs/features/approval) for full details.
</Note>

<Tip>
  Pass `--pure` (alias `--no-plugins`) to skip external-plugin discovery for a single run without touching your saved enable/disable state — see [Pure Mode](/docs/features/pure-mode).
</Tip>

## Append to the system prompt

`--append-system-prompt` adds a one-off suffix to the assembled system prompt for a single invocation. It is never persisted and disappears when the process exits.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Literal text
praisonai code --append-system-prompt "Always answer in French"

# Read the suffix from a file (@file form)
praisonai code --append-system-prompt @policy.md
```

Omit the flag and set the environment variable instead — handy for CI:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
export PRAISONAI_APPEND_SYSTEM_PROMPT="Reply in strict JSON, no prose."
praisonai code
```

See [Append System Prompt](/docs/features/append-system-prompt) for the full behaviour.

## Piped Input

`praisonai code` reads piped stdin when the prompt is provided in the shell pipeline.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
cat data.json | praisonai code "Write a parser for this shape"
```

Prompt argument is merged **first**, piped body second (joined with `\n`). See [Piped Input](/docs/features/cli-piped-stdin).

## Step budget for coding sessions

`praisonai code` runs with a **coding-sized** step budget by default: **200 steps**, applied to both tool-execution loops.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Flag["--max-steps N"] --> Env["PRAISONAI_CODE_MAX_STEPS"]
    Env --> Def["DEFAULT_CODE_MAX_STEPS = 200"]
    Def --> Budget["ExecutionConfig(max_steps=N,<br/>max_tool_calls_per_turn=N)"]

    classDef flag fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef env fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef def fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef cfg fill:#10B981,stroke:#7C90A0,color:#fff

    class Flag flag
    class Env env
    class Def def
    class Budget cfg
```

The core `Agent` defaults (`max_steps=20`, `max_tool_calls_per_turn=10`) are tuned for a general-purpose Q\&A agent with two or three tools, and are left untouched — no library user's behaviour changes. But 10 tool calls is "list files, read two files, one grep": it cannot reach a test run. The coding CLI raises the ceiling for its own sessions only.

### Override

<Steps>
  <Step title="Explicit flag">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    praisonai code --max-steps 300 "Refactor the auth module across all files"
    ```
  </Step>

  <Step title="Environment fallback (CI / sandbox)">
    ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
    export PRAISONAI_CODE_MAX_STEPS=300
    praisonai code "Refactor the auth module across all files"
    ```
  </Step>
</Steps>

**Precedence:** `--max-steps` flag > `PRAISONAI_CODE_MAX_STEPS` env > `DEFAULT_CODE_MAX_STEPS` (200). An unparseable or non-positive value falls through to the next source.

The flag raises *both* budget knobs to the same value, because:

| Model routing                                  | Bounded by                                                                             |
| ---------------------------------------------- | -------------------------------------------------------------------------------------- |
| OpenAI-native (`gpt-4o-mini`, the default)     | `ExecutionConfig.max_steps`                                                            |
| LiteLLM (`gemini/*`, `anthropic/*`, ollama, …) | `ExecutionConfig.max_steps` **and** `ExecutionConfig.max_tool_calls_per_turn` per turn |

Raising only one leaves the other as the real (and invisible) ceiling.

<AccordionGroup>
  <Accordion title="Why 200?">
    A coding agent's unit of work is *read → edit → run tests → read the failure* (≈4 calls per fix attempt), before any orientation. 200 steps is \~50 edit/verify cycles, chosen to cover the *tail* rather than the median: trajectories cluster at 20–40 steps, but hard tasks — the ones benchmarks measure — run past 100, and a budget at the median silently truncates those. Runaway loops stay bounded by the orthogonal guards (per-tool loop guard, `ExecutionConfig.max_execution_time`, `max_budget`, model context window).
  </Accordion>

  <Accordion title="What about max_tool_calls_per_turn?">
    The LiteLLM tool loop counts every tool call in a turn against `max_tool_calls_per_turn`, while the OpenAI-native loop is bounded by `max_steps`. `--max-steps` sets both to the same value so a Gemini/Anthropic-routed session isn't capped at 10 calls while an OpenAI-routed one runs to your budget.
  </Accordion>

  <Accordion title="Does this change the SDK defaults?">
    No. The coding budget applies only to `praisonai code`. The Python `Agent` defaults (`max_steps=20`, `max_tool_calls_per_turn=10`) are unchanged.
  </Accordion>
</AccordionGroup>

See [Step Budget](/docs/features/max-steps#praisonai-code-defaults) for the general `ExecutionConfig.max_steps` contract and how to detect truncation with `agent.last_stop_reason`.

## Headless truncation contract (`code -p`)

A budget-exhausted headless run exits **`2`** with `status: "truncated"` — distinct from a hard failure (`1`) and a clean completion (`0`).

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Req[📝 code -p task] --> Loop[🔧 LLM tool loop]
    Loop --> Ex[⚠️ Budget exhausted]
    Ex --> Wrap[📝 Wrap-up summary]
    Wrap --> Out[⛔ exit 2<br/>status: truncated]

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

    class Req input
    class Loop proc
    class Ex,Wrap warn
    class Out out
```

This matches [`praisonai run` → truncation](/docs/cli/run#exit-codes) and closes a hazard where a wrap-up summary (a perfectly non-empty string) was classified as `status: "ok"`, exit `0`, silently reporting truncation as success to CI and benchmark adapters.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code -p --output json --max-steps 6 \
  "Run pytest and fix every failing test until 0 failures"

# → exit 2
# → {"result": "Tool call limit reached (…). Task may be too complex …",
#    "session_id": null, "usage": {…}, "status": "truncated"}
```

Under `--output text`, a stderr warning follows the printed result:

```
Warning: run hit the step/tool-call budget; the output above is a summary of partial progress, not a completed task. Re-run with a higher --max-steps.
```

JSON / stream-JSON consumers do **not** see this stderr line — the `status: "truncated"` field is the machine signal.

The shared truncation check (`run._run_was_truncated`) resolves through `agent.last_stop_reason == "max_steps"`, so `code -p` and `praisonai run` agree on the `0` / `1` / `2` exit-code contract.

## First-run credential gate

`praisonai code` routes first-run onboarding through the shared credential gate, so a keyless newcomer is offered the `setup` wizard (interactive) or exits with a hint (headless) instead of dead-ending on a raw provider error.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    A[🚀 praisonai code] --> B{Configured?}
    B -->|Yes| C[✅ Run normally]
    B -->|No| LOCAL{Local endpoint<br/>reachable? no --model}
    LOCAL -->|Yes| LN[🖥️ Adopt local model<br/>stderr notice → continue]
    LN --> C
    LOCAL -->|No| HL{Headless?<br/>-p / piped stdin}
    HL -->|Yes| EXIT[⛔ exit 1<br/>Run: praisonai setup]
    HL -->|No| WIZ[🧙 Offer setup wizard]

    classDef start fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef check fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef success fill:#10B981,stroke:#7C90A0,color:#fff
    classDef local fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef wizard fill:#6366F1,stroke:#7C90A0,color:#fff

    class A start
    class B,LOCAL,HL check
    class C,LN success
    class WIZ wizard
    class EXIT start
```

| Situation                                                                   | Outcome                                                                                                                      |
| --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Configured (any provider key or stored credential)                          | Runs normally with your chosen model.                                                                                        |
| Keyless, local Ollama / OpenAI-compatible endpoint reachable (no `--model`) | Adopts the local model; one-line stderr notice; continues.                                                                   |
| Keyless, headless (`-p` / `--print` or piped stdin)                         | Exits `1` with `Error: No API key configured. Run: praisonai setup`.                                                         |
| Keyless, interactive TTY                                                    | Prompts `Would you like to run the setup wizard now?`. `Y` → wizard runs, re-checks, continues. `n` → exits `0` with a hint. |

<Note>
  `--agent <profile>` passes the profile's `llm` value through the gate, so onboarding validates the profile's model — not a silently-adopted local one.
</Note>

See [First-run Onboarding](/docs/features/first-run-onboarding) for the full flow and [Setup](/docs/cli/setup) for the wizard.

## Headless / scripting mode

`-p/--print` runs one task and prints a clean, machine-readable result — no `Chat mode:` banners, no profiling block — then exits with a code that reflects success or failure. This is the scripting parity `code` shares with `run --output json` and `chat --json`.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code -p "Write a Python function to sort a list" --output json
```

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Prompt[📝 code -p task] --> Agent[🤖 Minimal code agent]
    Agent --> Env[📦 JSON / text on stdout]
    Env --> Exit{status}
    Exit -->|ok| Zero[✅ exit 0]
    Exit -->|failed / error| One[⛔ exit non-zero]

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

    class Prompt input
    class Agent proc
    class Env,Exit out
    class Zero ok
    class One bad
```

### JSON envelope

`--output json` (the default under `-p`) prints a single-line JSON object on stdout:

```json theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
{"result": "def sort_list(items): return sorted(items)", "session_id": null, "usage": {"in": 128, "out": 42, "cost": 0.0}, "status": "ok"}
```

| Field        | Meaning                                                                                                                                      |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `result`     | The agent's answer as a string, or `null` when nothing was produced.                                                                         |
| `session_id` | The resolved session id when `--resume`/`--session`/`--continue` was used, else `null`.                                                      |
| `usage.in`   | Input tokens for this run.                                                                                                                   |
| `usage.out`  | Output tokens for this run.                                                                                                                  |
| `usage.cost` | Estimated cost from the token collector + pricing table.                                                                                     |
| `status`     | `ok` on success, `truncated` when the step/tool budget was exhausted (exit `2`), `failed` on an empty result, `error` when the agent raised. |
| `error`      | Present only when `status` is `error` — the exception message.                                                                               |

### Text mode

`--output text` prints just the result on stdout — nothing else — so it pipes cleanly:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code -p "What is 2+2?" --output text
# 4
```

Errors go to stderr; status is carried by the exit code.

### Exit-code contract

The exit code lets CI, benchmarks, and shell scripts branch on success without parsing stdout.

| `status`    | When                                                           | Exit code |
| ----------- | -------------------------------------------------------------- | --------- |
| `ok`        | Non-empty result                                               | `0`       |
| `truncated` | Step/tool budget exhausted (`last_stop_reason == "max_steps"`) | `2`       |
| `failed`    | Empty / `None` result                                          | `1`       |
| `error`     | The agent raised an exception                                  | `1`       |

See [Headless truncation contract (`code -p`)](#headless-truncation-contract-code-p) for the `truncated` case.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
if praisonai code -p "Generate the release notes" --output text > notes.md; then
  echo "wrote notes.md"
else
  echo "generation failed" >&2
fi
```

### Scripted multi-turn with `--resume`

`--resume <id>` composes with `-p` so a script can carry a session across calls. The id flows back out in the envelope's `session_id`:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code --resume my-feature -p "Draft the auth refactor" --output json
praisonai code --resume my-feature -p "Now add tests"          --output json
```

### Fail-closed options

Headless mode runs a minimal code agent, so options that need the full interactive wiring are **rejected up front** (exit 1) rather than silently dropped:

| Rejected under `-p`            | Why                                                                                                                |
| ------------------------------ | ------------------------------------------------------------------------------------------------------------------ |
| `--no-acp`                     | Toggles the resident split-pane TUI's runtime ACP tool server, which the one-shot headless agent does not spin up. |
| `--no-lsp`                     | Toggles the resident split-pane TUI's runtime LSP tool server, which the one-shot headless agent does not spin up. |
| `--profile` / `--profile-deep` | Prints a human report and always exits 0 — it would break the machine-readable contract.                           |

Two more guards keep the contract explicit: `--output` without `-p` errors, and `-p` without a prompt errors.

<Note>
  On a keyless install, `code -p` fails fast at the [first-run credential gate](#first-run-credential-gate) with `Error: No API key configured. Run: praisonai setup` (exit `1`) — before the Agent path is touched.
</Note>

**Honored under `-p`:** `--model`, `--thinking`, `--verbose`, `--workspace`, `--resume` / `--session` / `--continue`, **`--tools`**, **`--agent`**, and **`--plan`** (as of PraisonAI [PR #4026](https://github.com/MervinPraison/PraisonAI/pull/4026)). `--tools` and the profile's named tools are **merged onto** the default headless coding toolset (de-duped by identity), so custom tools *add to* the defaults rather than replacing them. `--plan` and a profile's declarative `permissions` are enforced via a **non-interactive** approval backend, so honouring the scope is a tightening (deny/ask fails closed) — never an interactive prompt that would stall a scripted run.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    subgraph "praisonai code -p — headless"
        P[📝 prompt] --> H{flag?}
        H -->|--tools name / .py| T[🔧 ToolResolver → merge with defaults]
        H -->|--agent name| A[👤 profile: instructions + tools + permissions]
        H -->|--plan| Pl[🔒 read-only backend]
        H -->|--no-acp / --no-lsp| X[⛔ exit 1]
        T --> Run[🤖 headless agent]
        A --> Run
        Pl --> Run
        Run --> Env[📦 JSON / text envelope]
    end

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

    class P input
    class H,Run proc
    class T,A,Pl cfg
    class Env ok
    class X bad
```

<Note>
  The envelope reuses the same token collector and cost tracker as `run --output json`, so `usage.in/out/cost` reflect real figures without any extra flags.
</Note>

## Sessions

`praisonai code` shares the canonical session store at `~/.praisonai/sessions/` (Windows: `%USERPROFILE%\.praisonai\sessions\`). Every conversation you start here is the same session object the rest of the CLI reads and writes.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Unified session store"
        Code[💻 praisonai code<br/>REPL / TUI] --> Store[(📂 ~/.praisonai/sessions/)]
        Run[▶️ praisonai run<br/>--continue / --session] --> Store
        Session[📋 praisonai session<br/>list / show / export] --> Store
        Dashboard[📊 praisonai dashboard] --> Store
    end

    classDef surface fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef store fill:#189AB4,stroke:#7C90A0,color:#fff

    class Code,Run,Session,Dashboard surface
    class Store store
```

Sessions created inside `praisonai code` are visible to:

* `praisonai session list` (and `list --all`)
* `praisonai session show <id>` / `delete <id>` / `export <id>` / `share <id>` / `unshare <id>`
* `praisonai run --continue` / `--session <id>` — same id, same conversation
* the `praisonai dashboard`

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Start a session in code, then continue it from run
praisonai code --session my-feature "Draft the auth refactor"
praisonai run --session my-feature "Now add tests"

# List and export the same session
praisonai session list
praisonai session export my-feature
```

<Note>
  Prior to `praisonai-code` ≥ 1.x (post-fix [#3645](https://github.com/MervinPraison/PraisonAI/issues/3645)), code sessions were written to `~/.praison/sessions/` and were **not** visible to `session list` or the dashboard. Upgrading unifies the store; pre-fix sessions stay in the legacy path. To bring them across, move them manually:

  ```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
  mv ~/.praison/sessions/*.json ~/.praisonai/sessions/
  ```
</Note>

See [Session Management](/docs/cli/session) for the full command set and [Storage Paths](/docs/concepts/storage-paths) for where files live.

## Examples

### Start code assistant

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

### Ask a coding question

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code "Write a Python function to sort a list"
```

### Specify language context

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code --language python "Explain decorators"
```

### Disable safe mode (opt out of approval prompts)

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code --no-safe "Refactor main.py"
```

### Full bypass (no approval prompts, applies to subprocess tree)

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code --dangerously-skip-approval "Clean up old logs"
```

### Headless one-shot for scripts

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Machine-readable JSON envelope on stdout, status-reflecting exit code
praisonai code -p "Write a Python function to sort a list" --output json
```

See [Headless / scripting mode](#headless-scripting-mode) for the envelope shape and exit-code contract.

### Headless one-shot with a custom tool

`--tools` is now first-class under `-p`. The resolved tools are merged onto the default headless coding toolset (ACP + edit + search + LSP), so custom tools **add to** the defaults rather than replacing them.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Add the `github` tool to a scripted coding run
praisonai code -p "Open a PR that fixes the failing lint" --tools github --output json
```

`--tools` accepts either comma-separated names resolved through `ToolResolver` (identical to `run --tools`) or a `./tools.py` file path. If a user `tools.py` fails at import time, the failure is reported through the same machine-readable JSON envelope (`status: "error"`, non-zero exit) — never as a raw traceback.

### Headless one-shot under a named agent profile

`--agent <name>` loads a profile from `.praisonai/agents/` and applies its **instructions**, **role**, **goal**, **llm**, and **named tools** to the headless run. Its declarative **`permissions`** are enforced via a non-interactive approval backend, so a pinned least-privilege profile runs safely in CI.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Least-privilege review profile — instructions + permission scope from .praisonai/agents/reviewer.md
praisonai code -p --agent reviewer "Audit src/security/ for auth bugs" --output json
```

An explicit `--model` still wins over the profile's `llm`. See [Custom Agents & Commands](/docs/features/custom-agents-commands) for profile definitions.

### Headless read-only planning (`--plan`)

`--plan` under `-p` runs a **read-only** headless session: reads, searches, and LSP queries are allowed, but every mutating tool (write, edit, shell) is denied by a non-interactive `PermissionMode.PLAN` backend. Ideal for CI review jobs that must produce a plan without touching the tree.

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Plan-only headless run — writes/edits/shell are denied
praisonai code -p --plan "Draft a migration plan for the auth module" --output json
```

`--plan` overrides any profile permission scope with the read-only planning mode. See [Permission Modes](/docs/features/permission-modes) and [Approval](/docs/features/approval).

### Read-only planning session

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# REPL session that can read/search but never writes or shells
praisonai code --plan "Draft a migration plan for the auth module"
```

`--plan` is the read-only planning permission mode (`PermissionMode.PLAN`). See [Permission Modes](/docs/features/permission-modes) and [Permissions](/docs/cli/permissions).

### Reasoning effort (per invocation)

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code --thinking high "Refactor src/utils.py for readability"
```

### Custom agent profile

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Profile defined in .praisonai/agents/plan.md
praisonai code --agent plan "Review the auth module and propose a refactor"

# Profile + reasoning effort combined
praisonai code --agent reviewer --thinking high "Audit src/security/"
```

See [Custom Agents & Commands](/docs/features/custom-agents-commands) for profile definitions and [Thinking](/docs/cli/thinking) for budget levels.

### Append a one-off instruction (per invocation)

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code --append-system-prompt "Always answer in French"
```

The text is appended to the end of the system prompt for this run only — never written to any agent file. See [Append System Prompt](/docs/features/append-system-prompt).

## Project context

By default, `praisonai code` walks up from the current directory to your git root and prepends any `AGENTS.md` / `CLAUDE.md` / `agents.md` / `.agents/AGENTS.md` it finds to the agent's system prompt, layered on top of `~/.praisonai/AGENTS.md`. Pass `--no-context` (or set `PRAISON_NO_CONTEXT=true`) to disable. See [Context Files](/docs/features/context-files) for details.

## Workspace directory

`praisonai code` runs its file, edit, search, and shell tools inside one workspace directory. Everything the agent reads and writes is contained there.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Start([praisonai code launched]) --> Q1{--workspace passed?}
    Q1 -- Yes --> W1[Use flag value]
    Q1 -- No --> Q2{PRAISONAI_WORKSPACE set?}
    Q2 -- Yes --> W2[Use env value]
    Q2 -- No --> Q3{PRAISON_WORKSPACE set?<br/><i>legacy</i>}
    Q3 -- Yes --> W3[Use legacy env value]
    Q3 -- No --> Q4{--continue or --session?}
    Q4 -- Yes --> W4[Use the session's<br/>original directory]
    Q4 -- No --> W5[Use current directory]

    classDef start fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef decision fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef result fill:#10B981,stroke:#7C90A0,color:#fff

    class Start start
    class Q1,Q2,Q3,Q4 decision
    class W1,W2,W3,W4,W5 result
```

### Pick a workspace explicitly

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code --workspace ./src "Refactor the auth module"
```

Everything the agent reads or writes stays inside `./src`.

### Pick a workspace with an environment variable

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
export PRAISONAI_WORKSPACE=/path/to/project
praisonai code "Add tests for user.py"
```

`PRAISONAI_WORKSPACE` is the canonical name. The older `PRAISON_WORKSPACE` still works for backwards compatibility, but `PRAISONAI_WORKSPACE` wins when both are set.

### Resume back into the same directory

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code --continue           # resumes the last session in its original directory
praisonai code --session abc123     # resumes that specific session in its original directory
```

Launch `praisonai code --continue` from any shell — the tools re-root into the directory the session was created in, so the conversation stays consistent.

If the recorded directory no longer exists you'll see a warning and the tools fall back to the current directory:

```
⚠ Session workspace no longer exists: /old/path — using current directory instead.
```

An explicit `--workspace` always wins over the resumed directory.

## Windows Automation

For Windows automation scenarios, use the `--no-acp` flag and set UTF-8 encoding. The `-w` flag is now honored end-to-end, so the agent's tools operate inside the directory you pass:

```powershell theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Windows PowerShell
$env:PRAISON_APPROVAL_MODE = "auto"
$env:PYTHONIOENCODING       = "utf-8"

praisonai code -w . --no-acp "Fix the failing tests"
```

See the [Windows Automation section](/docs/cli/realworld-examples#windows-automation) in Real-world Examples for complete setup instructions.

## Auto checkpointing & in-session undo

Workspace checkpointing is **on by default** for interactive `praisonai code` sessions, so `/undo` and `/revert` work out of the box. Disable per-run with `--no-checkpoints`, or project-wide with `checkpoints.auto: false` (or `PRAISONAI_CHECKPOINTS=off`).

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code "Refactor auth module"
```

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Start[🚀 Session start] --> CP0[📸 Baseline checkpoint]
    CP0 --> T1[📝 Turn 1 edits]
    T1 --> CP1[📸 Checkpoint 1]
    CP1 --> T2[📝 Turn 2 edits]
    T2 --> Revert[⏪ /revert]
    Revert --> CP1

    classDef checkpoint fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef turn fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef action fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef ok fill:#10B981,stroke:#7C90A0,color:#fff

    class CP0,CP1 checkpoint
    class T1,T2 turn
    class Start action
    class Revert ok
```

### How `/undo` differs by mode

| Mode                                                                                                  | What `/undo` does                                                                                                   |
| ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------- |
| Checkpointing **on** (default for interactive `praisonai code`)                                       | Removes the last turn from history **and** restores workspace files to the pre-turn checkpoint (diff preview first) |
| Checkpointing **off** (`--no-checkpoints`, `checkpoints.auto: false`, or `PRAISONAI_CHECKPOINTS=off`) | Removes the last assistant+user message from history only                                                           |

### Interactive slash commands

Type these inside a `praisonai code` REPL (checkpointing is on by default; disable with `--no-checkpoints`):

| Command        | What it does                                                        |
| -------------- | ------------------------------------------------------------------- |
| `/undo`        | Undo the last turn: remove from history and restore workspace files |
| `/revert`      | Same as `/revert 1` — roll back 1 turn                              |
| `/revert last` | Explicit alias for the last 1 turn                                  |
| `/revert 2`    | Roll the workspace back 2 turns                                     |

Both commands show a diff preview before restoring and refuse to run while a turn is still in progress.

### One-shot revert from CLI

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai code --revert last
```

Shows the diff preview and restores the workspace, then exits.

### Project config

Enable checkpointing for all `praisonai code` sessions in a project:

```yaml theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# agents.yaml
checkpoints:
  auto: true
  storage_dir: ./.praisonai/checkpoints   # optional — shared with praisonai run
```

**Precedence (highest last):** `default` → `checkpoints.auto` (config) → `PRAISONAI_CHECKPOINTS` (env). Interactive `praisonai code` passes `default=True`, so checkpointing is on unless you disable it.

See [Checkpoints](/docs/features/checkpoints) for the full checkpoint feature reference.

## See Also

* [Chat](/docs/cli/chat) - General chat mode (`--json` headless output)
* [Piped Input](/docs/features/cli-piped-stdin) - Compose `code -p` in Unix pipelines and CI
* [LSP Code Intelligence](/docs/cli/lsp-code-intelligence) - Language server integration
* [Approval](/docs/features/approval) - Tool approval and safety defaults
* [Checkpoints](/docs/features/checkpoints) - Workspace checkpointing and undo
* [Step Budget](/docs/features/max-steps#praisonai-code-defaults) - The `max_steps` contract and the coding-sized default
