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

# Session Forking

> Fork the current conversation mid-session to explore two approaches from the same point

Forking splits the current conversation into a second timeline you can continue independently — try a second approach without losing the first.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    Parent[💬 Live session<br/>message 12] -->|/branch| Fork[🌿 Fork created<br/>message 12]
    Parent -->|kept resumable| Original[📁 Parent<br/>timeline A]
    Fork -->|switched onto| Continue[✨ Continue<br/>timeline B]

    classDef session fill:#8B0000,stroke:#7C90A0,color:#fff
    classDef op fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef result fill:#10B981,stroke:#7C90A0,color:#fff

    class Parent session
    class Fork op
    class Original,Continue result
```

You are mid-conversation with an agent, you want to try an alternative, and you fork instead of losing your place:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
$ praisonai code
> Refactor auth.py to use JWT
… agent proposes a refactor …

> /branch jwt-attempt
✓ Branched: sess_abc12345 → sess_def67890
Now on fork sess_def67890 (14 messages). Parent sess_abc12345 kept.

> Actually try session cookies instead
… continues on the fork; parent timeline untouched …

# Later, jump back to the JWT timeline:
$ praisonai session resume sess_abc12345
```

## Quick Start

**1. Fork here, keep talking**

Type `/branch` mid-conversation to fork at the current point and switch onto the fork:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> /branch jwt-attempt
✓ Branched: sess_abc12345 → sess_def67890
Now on fork sess_def67890 (14 messages). Parent sess_abc12345 kept.
```

The next message continues on the fork; the parent stays resumable.

**2. Fork from earlier**

Rewind before forking with `--at N` — `N` counts user turns back:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> /branch --at 3
```

Forks from 3 user turns back and switches onto that fork.

**3. Fork a saved session (no REPL)**

Fork a session from the command line, then resume the fork:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai session fork sess_abc12345
# Forked session: sess_abc12345 -> sess_def67890
# Resume the fork with: praisonai session resume sess_def67890

praisonai session resume sess_def67890
```

***

## How It Works

Forking routes through the same `HierarchicalSessionStore.fork_session` substrate whether you branch in the REPL or from the CLI.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant User
    participant REPL as praisonai code
    participant Store as HierarchicalSessionStore
    participant Fork as New session

    User->>REPL: /branch jwt-attempt
    REPL->>REPL: Check worker not busy
    REPL->>Store: fork_session(current_id, ...)
    Store->>Fork: Create with parent_id set
    Store-->>REPL: fork session object
    REPL->>REPL: Rebind session + reload history
    REPL-->>User: ✓ Branched: parent → fork
    User->>REPL: next message
    Note over REPL,Fork: Continues on fork timeline;<br/>parent stays resumable
```

| Step | What happens |
| - | - |
| Fork | The live session is copied at the current message index (or `--at N` turns back). |
| Switch | The REPL rebinds onto the fork and reloads its history. |
| Parent kept | The original timeline stays on disk, resumable by its id. |
| Lineage | The fork records `parent_id`; the parent records the fork in `children_ids`. |

***

## When to Fork

Pick the command that matches where you want to fork from.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph TB
    Q{Where do you want<br/>to fork from?}
    Q -->|Right here, now| Now["/branch [title]"]
    Q -->|A few turns back| Back["/branch --at N"]
    Q -->|A saved session<br/>from outside REPL| CLI["praisonai session fork ID"]
    Q -->|An exact past<br/>message index| Exact["praisonai session fork ID --at-message N"]

    classDef question fill:#F59E0B,stroke:#7C90A0,color:#fff
    classDef choice fill:#189AB4,stroke:#7C90A0,color:#fff

    class Q question
    class Now,Back,CLI,Exact choice
```

| Situation | Command |
| - | - |
| "Let me try this a different way from here" | `/branch` |
| "Actually, back up 3 messages and try again" | `/branch --at 3` |
| "Name this exploration" | `/branch red-team review` |
| "Fork a saved session outside the REPL" | `praisonai session fork <id>` |
| "Fork from a specific past message" | `praisonai session fork <id> --at-message 8` |

***

## Options

`/branch` (REPL) and `praisonai session fork` (CLI) share the same substrate but differ in how the fork point is expressed.

**`/branch` — REPL command**

| Option | Type | Description |
| - | - | - |
| `[title]` | `str` | Optional name for the fork (anything after the command that isn't `--at N`). |
| `--at N` / `-a N` | `int` | Fork from `N` **user turns** back. Must be `> 0` and `≤` total user turns. |

**`praisonai session fork` — CLI verb**

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai session fork <session_id> [--at-message N] [--title "..."]
```

| Argument / Flag | Type | Description |
| - | - | - |
| `session_id` | `str` | Session to fork. Resolved project store first, then global. |
| `--at-message N` | `int` | Fork from this **0-based message index**. Valid range is `0..count-1`. |
| `--title "..."` | `str` | Optional title for the forked session. |

> [!NOTE]
>
> `--at N` in the REPL counts **user turns** back from the end. `--at-message N` in the CLI is a **0-based message index** into the parent's full history. They are different units — pick the one that matches the surface you're on.

***

## Lineage

Forking records parent/child links that surface everywhere sessions are shown.

The `/session` command prints lineage when set:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> /session
Session ID: sess_def67890
Messages: 14
Created: 2026-08-06 10:14:00
Updated: 2026-08-06 10:31:00
Total tokens: 12,345
Forked from: sess_abc12345
```

The parent shows its forks:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> /session
Session ID: sess_abc12345
...
Forks: sess_def67890
```

`session list` gains a **Parent** column — an 8-character parent id prefix, or `-` for a root session:

```
ID         Name          Status   Events   Tokens    Cost      Parent     Updated
abc12345   jwt-refactor  active   12       12,345    $0.0140   -          10:14
def67890   jwt-attempt   active   14       13,200    $0.0155   abc12345   10:31
```

The `--json` output includes `parent_id` per session:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai session list --json
```

```json theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
[
  {
    "id": "def67890",
    "name": "jwt-attempt",
    "parent_id": "abc12345",
    "status": "active"
  }
]
```

***

## Guardrails

Forking refuses unsafe operations rather than producing a corrupted timeline.

> [accordion] Refuses while a turn is in flight
>
> `/branch` refuses if a response is still processing — otherwise the parent's completed turn would land on the freshly-switched fork:
>
> ```
> A response is still processing. Wait for it to finish before branching (see /status).
> ```
>
> Wait for the turn to settle (check `/status`), then branch.

> [accordion] `/branch --at N` bounds
>
> `N` must be a positive integer no greater than the number of user turns:
>
> ```
> > /branch --at 0
> /branch --at expects a positive number.
>
> > /branch --at 99
> Only 5 user turns available; cannot go 99 back.
> ```

> [accordion] `session fork --at-message N` bounds
>
> `--at-message` is 0-based and validated up front against the parent's message count — no silent slice wrap:
>
> ```
> --at-message 99 is out of range (session has 14 messages, valid 0..13)
> ```

> [accordion] Not-found handling
>
> A `session fork` on an unknown id exits `1` with a remediation hint:
>
> ```
> Session not found: sess_missing
> Use 'praisonai session list' to see available sessions
> ```
>
> In the REPL, `/branch` with no active session prints `No active session to branch from.` and a store failure prints `Could not fork the current session.` — neither crashes the REPL.

***

## JSON Output

`session fork --json` returns the fork result as a single object:

```bash theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
praisonai session fork sess_abc12345 --at-message 8 --title "cookie-path" --json
```

```json theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
{
  "forked": true,
  "parent_id": "sess_abc12345",
  "session_id": "sess_def67890",
  "from_message_index": 8,
  "title": "cookie-path"
}
```

`from_message_index` and `title` are `null` when not passed.

***

## Best Practices

> [accordion] Name your branches
>
> Pass a title (`/branch jwt-attempt` or `--title "..."`) so `session list` reads like a menu of explorations instead of anonymous ids.

> [accordion] Wait for the turn to finish
>
> Branch only after the current response settles — `/branch` refuses mid-turn to keep the fork clean. Check `/status` if unsure.

> [accordion] Resume the parent later
>
> The parent timeline stays on disk. Note its id from the `✓ Branched:` line so you can `praisonai session resume <parent_id>` to jump back.

> [accordion] Fork from the right unit
>
> Use `/branch --at N` to count user turns in the REPL; use `session fork --at-message N` for an exact 0-based message index from the CLI.

***

## Related

> [card] [Session Command](https://praison.ai/docs/cli/session.md)
>
> Full `session` sub-command reference, including `fork`

> [card] [Interactive TUI](https://praison.ai/docs/cli/interactive-tui.md)
>
> REPL slash commands, including `/branch`


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.