{
  "schemaVersion": 1,
  "updatedAt": "2026-10-15",
  "dimensions": [
    "fullHistory",
    "turnBoundary",
    "ephemeral",
    "configurationOverrides",
    "filesystemIsolation"
  ],
  "contracts": [
    {
      "harness": "claude-code",
      "variant": "current",
      "default": true,
      "support": {
        "fullHistory": "native",
        "turnBoundary": "native",
        "ephemeral": "partial",
        "configurationOverrides": "native",
        "filesystemIsolation": "native"
      },
      "evidence": [
        "claude-sessions-docs",
        "claude-agent-view-docs",
        "claude-commands-docs",
        "claude-cli-reference-docs",
        "steering-claude-code-docs-en-checkpointing",
        "sessions-claude-code-code-claude-com-docs-en-vs-code",
        "steering-claude-code-docs-en-agent-sdk-typescript",
        "delegation-claude-code-code-claude-com-docs-en-worktrees",
        "image-input-docs-0",
        "claude-hooks-docs",
        "steering-claude-code-docs-en-agent-sdk-python"
      ],
      "reference": "https://code.claude.com/docs/en/sessions#branch-a-session",
      "observedVersion": "2.1.300",
      "answers": {
        "fork": {
          "status": "supported",
          "answer": "Inside a session, `/branch [name]` copies the conversation and switches you into the copy, while `/fork [prompt]` copies it into a new background session (its own row in `claude agents`) and keeps you where you are. From the shell, add `--fork-session` to `claude --continue` or `claude --resume <id|name>` to continue in a copy with a new session ID.",
          "reference": "https://code.claude.com/docs/en/sessions#branch-a-session",
          "evidence": [
            "claude-sessions-docs",
            "claude-agent-view-docs",
            "claude-commands-docs",
            "claude-cli-reference-docs"
          ],
          "notes": [
            "`/fork` became a background copy in v2.1.212; before that (and whenever agent view is turned off) it starts a forked subagent, which is now `/subtask`.",
            "`/fork` was the old name of `/branch` before v2.1.77.",
            "A session started with flags the copy can't inherit, such as a replaced system prompt or a `--tools` allowlist, can't be copied with `/fork`."
          ]
        },
        "point": {
          "status": "partial",
          "answer": "In the terminal, `/rewind` (aliases `/checkpoint`, `/undo`) or `Esc` twice on an empty prompt opens a list of your earlier prompts, where Restore conversation rewinds the current session to that point rather than making a copy. The VS Code extension has Fork conversation from here on any message, and the Agent SDK's `forkSession(sessionId, { upToMessageId })` copies the transcript only up to a chosen message.",
          "reference": "https://code.claude.com/docs/en/checkpointing#rewind-and-summarize",
          "evidence": [
            "steering-claude-code-docs-en-checkpointing",
            "sessions-claude-code-code-claude-com-docs-en-vs-code",
            "steering-claude-code-docs-en-agent-sdk-typescript"
          ],
          "notes": [
            "`/branch` and `--fork-session` always copy the whole conversation as it stands; to branch from an earlier point in the CLI, run `/branch` first and then `/rewind` in the copy."
          ]
        },
        "carries": {
          "status": "supported",
          "answer": "Every fork copies the conversation history up to the fork point. `/branch` stays in the same process, so model, settings, \"allow for this session\" grants and running background work carry over; `/fork` copies the model, permission mode, effort and any added directories and \"don't ask again\" grants into the new background session. A `--fork-session` launch is a fresh process: session-only grants are not carried, launch flags like `--model` or `--permission-mode` apply to the copy, and it starts in the directory you launched from.",
          "reference": "https://code.claude.com/docs/en/sessions#branch-a-session",
          "evidence": [
            "claude-sessions-docs",
            "claude-agent-view-docs",
            "delegation-claude-code-code-claude-com-docs-en-worktrees"
          ],
          "notes": [
            "With `--fork-session`, a session that ended in plan mode is not put back into plan mode."
          ]
        },
        "files": {
          "status": "supported",
          "answer": "Forking copies the conversation, not your files: `/branch` and `--fork-session` keep working on the same checkout. `/fork` copies are told to make their code changes in a git worktree of their own, and you can start any session isolated with `claude --worktree <name>`. Separately, checkpoints let `/rewind` restore files that Claude's edit tools changed (Restore code, or Restore code and conversation).",
          "reference": "https://code.claude.com/docs/en/agent-view#how-file-edits-are-isolated",
          "evidence": [
            "claude-agent-view-docs",
            "steering-claude-code-docs-en-checkpointing",
            "delegation-claude-code-code-claude-com-docs-en-worktrees",
            "image-input-docs-0"
          ],
          "notes": [
            "Checkpoints don't cover changes made by Bash commands, most subagent edits, or symlinked and hard-linked files.",
            "A fork made with the SDK's `forkSession()` doesn't include the original's file checkpoints."
          ]
        },
        "lineage": {
          "status": "partial",
          "answer": "`/branch` prints both the new and the original session IDs, and the original stays in the `/resume` picker, so you switch back with `/resume <original-name>` or its ID. `/fork` copies show up as their own rows in `claude agents` and `/resume` with a `⑂` fork name, and SDK forks are titled after the original with `(fork)`. There is no tree view of parent and child sessions.",
          "reference": "https://code.claude.com/docs/en/sessions#branch-a-session",
          "evidence": [
            "claude-sessions-docs",
            "claude-hooks-docs",
            "steering-claude-code-docs-en-agent-sdk-typescript"
          ],
          "notes": ["SessionStart hooks see `source: \"fork\"` when a session starts as a fork."]
        },
        "api": {
          "status": "supported",
          "answer": "Headless: `claude -p --resume <id> --fork-session \"prompt\"`. In the Agent SDK, set `forkSession: true` (`fork_session=True` in Python) together with `resume`, or call `forkSession(sessionId, { upToMessageId, title })` / `fork_session()` to copy a transcript without running it; `resumeSessionAt` resumes at a specific message.",
          "reference": "https://code.claude.com/docs/en/agent-sdk/sessions#fork-to-explore-alternatives",
          "evidence": [
            "image-input-docs-0",
            "steering-claude-code-docs-en-agent-sdk-typescript",
            "steering-claude-code-docs-en-agent-sdk-python"
          ],
          "notes": [
            "For an unsaved fork, combine it with `--no-session-persistence` (print mode) or `persistSession: false` in the SDK."
          ]
        }
      },
      "surface": "cli"
    },
    {
      "harness": "codex",
      "variant": "cli",
      "default": true,
      "support": {
        "fullHistory": "native",
        "turnBoundary": "partial",
        "ephemeral": "native",
        "configurationOverrides": "native",
        "filesystemIsolation": "native"
      },
      "evidence": [
        "codex-developer-commands-docs",
        "codex-slash-source-0-162-1",
        "steering-codex-codex-rs-cli-src-main-rs",
        "sessions-codex-codex-rs-tui-src-app-backtrack-rs",
        "sessions-codex-codex-rs-tui-src-app-event-dispatch-rs",
        "steering-codex-codex-rs-app-server-protocol-src-protocol-v2-thread-rs",
        "mcp-codex-learn-chatgpt-com-docs-changelog",
        "sessions-codex-codex-rs-tui-src-chatwidget-worktree-picker-rs",
        "sessions-codex-codex-rs-worktree-src-lib-rs",
        "sessions-codex-codex-rs-tui-src-chatwidget-session-flow-rs",
        "instructions-codex-codex-rs-tui-src-status-card-rs",
        "sessions-codex-codex-rs-app-server-protocol-src-protocol-v2-thread-data-rs",
        "image-input-codex-codex-rs-exec-src-cli-rs",
        "sessions-codex-sdk-python-docs-api-reference-md"
      ],
      "reference": "https://learn.chatgpt.com/docs/developer-commands#fork-the-current-chat-with-fork",
      "observedVersion": "0.162.1",
      "answers": {
        "fork": {
          "status": "supported",
          "answer": "In the TUI, type `/fork` (or `/fork <name>` to name the copy) to copy the current chat into a new chat with a fresh ID; the original is left untouched. From the shell, `codex fork` opens a session picker, `codex fork --last` forks the most recent session, and `codex fork <id-or-name>` forks a specific one. `/side` (alias `/btw`) opens a throwaway side chat forked from the current one.",
          "reference": "https://learn.chatgpt.com/docs/developer-commands#fork-the-current-chat-with-fork",
          "evidence": [
            "codex-developer-commands-docs",
            "codex-slash-source-0-162-1",
            "steering-codex-codex-rs-cli-src-main-rs"
          ],
          "notes": [
            "`codex fork --help` says SESSION_ID must be a UUID, but 0.162.1 also accepts a session name, like `codex resume`."
          ]
        },
        "point": {
          "status": "partial",
          "answer": "You can't fork from an earlier turn in the CLI: `/fork`, `codex fork` and `codex exec fork` always copy the whole conversation. You can rewind the current chat instead: press Esc twice with an empty composer, pick an earlier prompt with Left/Right, and press Enter. Codex drops that prompt and everything after it from the saved history and puts the prompt back in the composer to edit.",
          "reference": "https://learn.chatgpt.com/docs/developer-commands#interactive-shortcuts",
          "evidence": [
            "codex-developer-commands-docs",
            "sessions-codex-codex-rs-tui-src-app-backtrack-rs",
            "sessions-codex-codex-rs-tui-src-app-event-dispatch-rs",
            "steering-codex-codex-rs-app-server-protocol-src-protocol-v2-thread-rs",
            "mcp-codex-learn-chatgpt-com-docs-changelog"
          ],
          "notes": [
            "The docs say Esc-Esc forks the chat from that point. Since 0.156.0 it rewinds the same chat in place, so the later turns are gone from that chat. To keep them, `/fork` first.",
            "Rewinding only works on sessions in the newer paginated history format. Older sessions can be converted with `codex migrate-rollouts --apply`.",
            "The app-server `thread/fork` request can fork at a turn (`lastTurnId`, or experimental `beforeTurnId`), but the CLI doesn't expose this."
          ]
        },
        "carries": {
          "status": "supported",
          "answer": "A fork copies the full conversation and keeps the current model, reasoning effort, permissions profile, working directory and any active goal. It doesn't keep the session name. You can rename it with `/fork <name>` or `/rename`. `codex fork` accepts the usual overrides, such as `-m`, `-s`, `-a`, `-c key=value`, `-C <dir>`, `--add-dir` and `-p`, to change these for the new chat.",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/tui/src/app/event_dispatch.rs#L554-L575",
          "evidence": [
            "sessions-codex-codex-rs-tui-src-app-event-dispatch-rs",
            "codex-developer-commands-docs",
            "steering-codex-codex-rs-app-server-protocol-src-protocol-v2-thread-rs"
          ],
          "notes": [
            "A `/side` chat inherits history only as reference. It is told not to make edits or use subagents, and it can't be renamed."
          ]
        },
        "files": {
          "status": "partial",
          "answer": "Forks don't snapshot or rewind files. By default a fork shares the same working directory. In a Git repo, `/fork` asks Where should the forked conversation run?, and you can pick Create new Git worktree. `codex fork <id> --worktree` and `codex exec fork <id> --worktree` do the same thing. Esc-Esc rewinds only the conversation and never your files.",
          "reference": "https://learn.chatgpt.com/docs/developer-commands#fork-the-current-chat-with-fork",
          "evidence": [
            "codex-developer-commands-docs",
            "sessions-codex-codex-rs-tui-src-chatwidget-worktree-picker-rs",
            "sessions-codex-codex-rs-worktree-src-lib-rs",
            "steering-codex-codex-rs-app-server-protocol-src-protocol-v2-thread-rs"
          ],
          "notes": [
            "The managed worktree is a detached checkout of the current `HEAD` commit, so uncommitted changes are not copied into it.",
            "`--worktree` needs an explicit session ID and local execution. It can't be combined with `--last`, the picker, `--ephemeral` or `resume`."
          ]
        },
        "lineage": {
          "status": "partial",
          "answer": "When a fork opens, Codex prints `Thread forked from <parent name> (<id>)`, and `/status` shows a Forked from line. To switch between the parent and the fork, use `/resume`, `codex resume <id-or-name>`, or the `codex agents` command center. There is no branch tree view.",
          "reference": "https://github.com/openai/codex/blob/092d3acd6bec3e3a14bdc7e7a2810ab628ab759d/codex-rs/tui/src/chatwidget/session_flow.rs#L280-L305",
          "evidence": [
            "sessions-codex-codex-rs-tui-src-chatwidget-session-flow-rs",
            "instructions-codex-codex-rs-tui-src-status-card-rs",
            "sessions-codex-codex-rs-app-server-protocol-src-protocol-v2-thread-data-rs"
          ]
        },
        "api": {
          "status": "supported",
          "answer": "In headless mode, `codex exec fork <id-or-name> [PROMPT]` copies a saved session. Add `--json` for JSONL events, `--ephemeral` to keep the fork unsaved (this needs a prompt), or `--worktree`. With no prompt, the fork is created without starting a turn. The app-server `thread/fork` request and the Python SDK `codex.thread_fork(thread_id, ephemeral=..., model=..., sandbox=...)` also fork. `thread/fork` adds `lastTurnId`/`beforeTurnId` to fork from an earlier turn.",
          "reference": "https://learn.chatgpt.com/docs/developer-commands#codex-exec",
          "evidence": [
            "codex-developer-commands-docs",
            "image-input-codex-codex-rs-exec-src-cli-rs",
            "steering-codex-codex-rs-app-server-protocol-src-protocol-v2-thread-rs",
            "sessions-codex-sdk-python-docs-api-reference-md"
          ]
        }
      },
      "sourceRevision": "092d3acd6bec3e3a14bdc7e7a2810ab628ab759d",
      "surface": "cli"
    },
    {
      "harness": "codex",
      "variant": "app-server-c51e7b3",
      "default": false,
      "sourceRevision": "c51e7b373647cf99208a1f391d05806ac4c3c9d7",
      "surface": "thread/fork",
      "support": {
        "fullHistory": "native",
        "turnBoundary": "native",
        "ephemeral": "native",
        "configurationOverrides": "partial",
        "filesystemIsolation": "unsupported"
      },
      "lineage": "immediate-parent",
      "historyPersistence": ["copied", "ancestor-referenced"],
      "activeTurnHandling": "append-interrupted-boundary",
      "workspaceBehavior": "inherit-source-cwd-unless-overridden",
      "boundarySelection": "at-most-one-explicit",
      "boundaries": [
        {
          "name": "latest",
          "stability": "stable",
          "inclusion": "all-persisted-history"
        },
        {
          "name": "lastTurnId",
          "stability": "stable",
          "inclusion": "through-turn-inclusive"
        },
        {
          "name": "beforeTurnId",
          "stability": "experimental",
          "inclusion": "before-turn-exclusive"
        }
      ],
      "configuration": {
        "inheritsPersistedPermissionSettings": true,
        "supportsOverrides": true,
        "stability": "mixed",
        "overrides": [
          {
            "name": "model",
            "stability": "stable"
          },
          {
            "name": "modelProvider",
            "stability": "stable"
          },
          {
            "name": "serviceTier",
            "stability": "stable"
          },
          {
            "name": "cwd",
            "stability": "stable"
          },
          {
            "name": "runtimeWorkspaceRoots",
            "stability": "experimental"
          },
          {
            "name": "approvalPolicy",
            "stability": "mixed",
            "experimentalParts": ["Granular"]
          },
          {
            "name": "approvalsReviewer",
            "stability": "stable"
          },
          {
            "name": "sandbox",
            "stability": "stable"
          },
          {
            "name": "permissions",
            "stability": "experimental"
          },
          {
            "name": "config",
            "stability": "stable"
          },
          {
            "name": "baseInstructions",
            "stability": "stable"
          },
          {
            "name": "developerInstructions",
            "stability": "stable"
          }
        ]
      },
      "constraintVocabulary": [
        "ephemeral",
        "deferGoalContinuation",
        "excludeTurns",
        "paginatedSource"
      ],
      "constraints": [
        {
          "kind": "mutually-exclusive",
          "fields": ["lastTurnId", "beforeTurnId"]
        },
        {
          "kind": "mutually-exclusive",
          "fields": ["permissions", "sandbox"]
        },
        {
          "kind": "mutually-exclusive",
          "fields": ["ephemeral", "deferGoalContinuation"]
        },
        {
          "kind": "requires",
          "when": {
            "paginatedSource": true,
            "ephemeral": true
          },
          "field": "excludeTurns",
          "value": true
        }
      ],
      "evidence": ["codex-thread-fork-source"],
      "references": {
        "protocol": "https://github.com/openai/codex/blob/c51e7b373647cf99208a1f391d05806ac4c3c9d7/codex-rs/app-server-protocol/src/protocol/v2/thread.rs#L510-L600",
        "processor": "https://github.com/openai/codex/blob/c51e7b373647cf99208a1f391d05806ac4c3c9d7/codex-rs/app-server/src/request_processors/thread_processor.rs#L4651-L5091",
        "core": "https://github.com/openai/codex/blob/c51e7b373647cf99208a1f391d05806ac4c3c9d7/codex-rs/core/src/thread_manager.rs#L1236-L1401"
      },
      "notes": [
        "A fork receives a fresh thread id and records forked_from_id for its immediate source thread.",
        "Persistent forks materialize their own rollout; paginated forks may reference inherited ancestor history.",
        "Conversation history is isolated after the fork, but filesystem state is not snapshotted or branched."
      ]
    },
    {
      "harness": "cursor-agent",
      "variant": "current",
      "default": true,
      "support": {
        "fullHistory": "native",
        "turnBoundary": "partial",
        "ephemeral": "unsupported",
        "configurationOverrides": "partial",
        "filesystemIsolation": "partial"
      },
      "evidence": [
        "cursor-cli-changelog",
        "steering-cursor-agent-help-ai-features-side-chats",
        "cursor-cli-using-docs",
        "cursor-agent-docs",
        "cursor-acp-docs",
        "cursor-cli-parameters-docs"
      ],
      "reference": "https://cursor.com/docs/cli/changelog#jun-9-2026-commands",
      "observedVersion": "2026.10.12-d47ca18",
      "answers": {
        "fork": {
          "status": "supported",
          "answer": "Type `/fork` (aliases `/branch` and `/duplicate`) in an interactive session. It copies the current chat into a new session, switches you into the copy, and prints `agent --resume <id>` so you can get back to the original. There is no `--fork` flag or `agent fork` subcommand.",
          "reference": "https://cursor.com/docs/cli/changelog#jun-9-2026-commands",
          "evidence": ["cursor-cli-changelog"],
          "notes": [
            "`/fork` is refused while the agent is still working or before the chat has any messages."
          ]
        },
        "point": {
          "status": "partial",
          "answer": "`/fork` always copies the whole chat; the CLI has no fork-from-message option. `/rewind` (aliases `/undo`, `/restore`) opens a turn timeline and moves the current chat back to an earlier message, either restoring files and conversation or the conversation only. To branch from an earlier point, run `/fork` and then `/rewind` inside the copy.",
          "reference": "https://cursor.com/docs/cli/changelog#april-2026",
          "evidence": ["cursor-cli-changelog", "steering-cursor-agent-help-ai-features-side-chats"],
          "notes": [
            "`/rewind` is on by default since v2026.06.22 and can be turned off with the `rewind` key in `cli-config.json` or in `/config`.",
            "The Cursor editor can fork from a specific message, copying the chat through that message and dropping later ones."
          ]
        },
        "carries": {
          "status": "supported",
          "answer": "The fork gets the full conversation history, including subagent and summary data. In CLI 2026.10.12 it also keeps the mode (agent, plan or ask), the last-used model, the Run Everything and approval settings, and the current plan file. It runs in the same working directory, and you can change model or mode afterwards with `/model` or Shift+Tab.",
          "reference": "https://cursor.com/docs/cli/changelog#jun-9-2026-commands",
          "evidence": ["cursor-cli-changelog"],
          "notes": ["Flags such as `--model` or `--force` can't be passed to `/fork` itself."]
        },
        "files": {
          "status": "partial",
          "answer": "Forking does not copy or isolate files: the original and the fork edit the same working tree. `/rewind` can undo file changes, offering Restore files and conversation or Restore conversation for a chosen turn. For separate files, start a session with `-w`/`--worktree [name]`, which runs it in its own git worktree under `~/.cursor/worktrees/<repo>/<name>`.",
          "reference": "https://cursor.com/docs/cli/changelog#april-2026",
          "evidence": ["cursor-cli-changelog", "cursor-cli-using-docs", "cursor-agent-docs"],
          "notes": [
            "Rewinding files in a fork also changes them for the original chat, because both share the same directory.",
            "Rewind file history is stored locally and isn't a replacement for git."
          ]
        },
        "lineage": {
          "status": "partial",
          "answer": "The fork is named after the original with ` (forked)` appended, and `/fork` prints the original chat's ID. Both chats appear as separate entries in `agent ls` / `/resume`. In CLI 2026.10.12 no parent link is stored, so there is no branch tree or switcher; you switch with `/resume` or `agent --resume <chatId>`.",
          "reference": "https://cursor.com/docs/cli/changelog#jun-9-2026-commands",
          "evidence": ["cursor-cli-changelog", "cursor-cli-using-docs"]
        },
        "api": {
          "status": "unsupported",
          "answer": "No. Headless mode (`agent -p`) can continue a chat with `--resume <chatId>`, but it has no fork option. The ACP server (`agent acp`) supports `session/new`, `session/load` and session listing, but not forking.",
          "reference": "https://cursor.com/docs/cli/acp#sessions",
          "evidence": ["cursor-acp-docs", "cursor-cli-parameters-docs"],
          "notes": [
            "`agent create-chat` makes a new empty chat and returns its ID. It does not copy an existing one."
          ]
        }
      },
      "surface": "cli"
    },
    {
      "harness": "opencode",
      "variant": "1.x",
      "default": false,
      "support": {
        "fullHistory": "native",
        "turnBoundary": "native",
        "ephemeral": "unsupported",
        "configurationOverrides": "partial",
        "filesystemIsolation": "partial"
      },
      "evidence": [
        "opencode-cli-stable-docs",
        "compaction-opencode-packages-tui-src-routes-session-index-tsx",
        "steering-opencode-packages-opencode-src-cli-cmd-run-ts",
        "sessions-opencode-packages-opencode-src-cli-cmd-tui-ts",
        "sessions-opencode-ackages-tui-src-routes-session-dialog-fork-from-timeline-tsx",
        "sessions-opencode-packages-tui-src-routes-session-dialog-message-tsx",
        "opencode-tui-docs",
        "transcripts-opencode-packages-opencode-src-session-session-ts",
        "instructions-opencode-opencode-ai-docs-config",
        "sessions-opencode-packages-opencode-src-session-revert-ts",
        "opencode-server-docs",
        "steering-opencode-pencode-src-server-routes-instance-httpapi-groups-session-ts",
        "sessions-opencode-packages-opencode-src-acp-agent-ts"
      ],
      "reference": "https://opencode.ai/docs/cli/#flags",
      "observedVersion": "1.19.0",
      "answers": {
        "fork": {
          "status": "supported",
          "answer": "Yes. In the TUI run `/fork` (or the `session_fork` keybind, unbound by default) and pick \"Full session\" or a message; from the command line use `opencode --continue --fork` or `opencode --session <id> --fork`, and the same `--fork` flag works on `opencode run` and `opencode attach`.",
          "reference": "https://opencode.ai/docs/cli/#flags",
          "evidence": [
            "opencode-cli-stable-docs",
            "compaction-opencode-packages-tui-src-routes-session-index-tsx",
            "steering-opencode-packages-opencode-src-cli-cmd-run-ts",
            "sessions-opencode-packages-opencode-src-cli-cmd-tui-ts"
          ],
          "notes": ["`/fork` is not in the TUI docs command list but is a built-in slash command."]
        },
        "point": {
          "status": "supported",
          "answer": "Yes. `/fork` lists your earlier prompts, and choosing one creates a new session with everything before that prompt and puts the prompt back in the composer; you can also open a message's action menu and choose Fork. To rewind the current session instead, use `/undo` (`<leader>u`), `/redo` (`<leader>r`), or the message menu's Revert.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/tui/src/routes/session/dialog-fork-from-timeline.tsx#L37-L72",
          "evidence": [
            "sessions-opencode-ackages-tui-src-routes-session-dialog-fork-from-timeline-tsx",
            "sessions-opencode-packages-tui-src-routes-session-dialog-message-tsx",
            "opencode-tui-docs"
          ]
        },
        "carries": {
          "status": "partial",
          "answer": "The fork copies the messages (each keeps the model and agent it used) and the session metadata and workspace, and gets the title `<original> (fork #1)`. It does not copy the session's permission overrides, share link, or lineage, and it opens in the directory the client is currently running in rather than the original session's directory.",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/session/session.ts#L691-L732",
          "evidence": ["transcripts-opencode-packages-opencode-src-session-session-ts"]
        },
        "files": {
          "status": "partial",
          "answer": "No. A fork shares your working tree and gets no worktree or file copy. Rewinding files is separate: `/undo` and Revert restore files from OpenCode's internal git snapshots (on by default, turn off with `\"snapshot\": false`).",
          "reference": "https://opencode.ai/docs/config/#snapshot",
          "evidence": [
            "instructions-opencode-opencode-ai-docs-config",
            "opencode-tui-docs",
            "sessions-opencode-packages-opencode-src-session-revert-ts"
          ]
        },
        "lineage": {
          "status": "unsupported",
          "answer": "No. A fork is saved as an ordinary top-level session with no link back to its source; only the `(fork #N)` title suffix hints at where it came from. Switch between the original and forks with `/sessions` (`<leader>l`).",
          "reference": "https://github.com/anomalyco/opencode/blob/733b2c627e5aec39cb33cc22373bdce33053ef2c/packages/opencode/src/session/session.ts#L694-L701",
          "evidence": [
            "transcripts-opencode-packages-opencode-src-session-session-ts",
            "opencode-tui-docs"
          ]
        },
        "api": {
          "status": "supported",
          "answer": "Yes. The server has `POST /session/:id/fork` with an optional `messageID` (the SDK's `session.fork`), `opencode run --continue --fork` or `opencode run --session <id> --fork` forks headlessly before sending the prompt, and `opencode acp` supports the ACP `session/fork` method.",
          "reference": "https://opencode.ai/docs/server/#sessions",
          "evidence": [
            "opencode-server-docs",
            "steering-opencode-pencode-src-server-routes-instance-httpapi-groups-session-ts",
            "sessions-opencode-packages-opencode-src-acp-agent-ts",
            "opencode-cli-stable-docs"
          ],
          "notes": [
            "Forking from a message excludes that message; omit `messageID` to copy everything."
          ]
        }
      },
      "sourceRevision": "733b2c627e5aec39cb33cc22373bdce33053ef2c",
      "surface": "cli"
    },
    {
      "harness": "opencode",
      "variant": "2.x",
      "default": true,
      "support": {
        "fullHistory": "native",
        "turnBoundary": "native",
        "ephemeral": "unsupported",
        "configurationOverrides": "partial",
        "filesystemIsolation": "partial"
      },
      "evidence": [
        "steering-opencode-packages-tui-src-routes-session-index-tsx",
        "opencode-2-0-29-source",
        "sessions-opencode-packages-tui-src-routes-session-dialog-fork-tsx",
        "sessions-opencode-opencode-ai-v2-docs-snapshots",
        "sessions-opencode-packages-tui-src-routes-session-dialog-message-tsx",
        "transcripts-opencode-packages-core-src-session-projector-ts",
        "sessions-opencode-packages-core-src-session-ts",
        "mcp-opencode-opencode-ai-v2-docs-tools",
        "steering-opencode-packages-tui-src-component-prompt-index-tsx",
        "instructions-opencode-opencode-ai-v2-docs-api",
        "sessions-opencode-packages-core-src-session-info-ts",
        "image-input-opencode-packages-cli-src-acp-service-ts"
      ],
      "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/tui/src/routes/session/index.tsx#L946-L962",
      "observedVersion": "2.0.29",
      "answers": {
        "fork": {
          "status": "supported",
          "answer": "Yes. In the TUI run `/fork` (or bind `session.fork`) and pick \"Full session\" or a prompt; from the command line use `opencode run --fork` or `opencode mini --fork` together with `--continue` or `--session <id>`.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/tui/src/routes/session/index.tsx#L946-L962",
          "evidence": [
            "steering-opencode-packages-tui-src-routes-session-index-tsx",
            "opencode-2-0-29-source"
          ],
          "notes": [
            "In 2.0.28 the full-screen `opencode` command has no `--fork` flag (1.x had one); use `/fork` after opening the session, or `opencode mini --fork`."
          ]
        },
        "point": {
          "status": "supported",
          "answer": "Yes. `/fork` lists earlier prompts, and choosing one copies the history before that prompt into a new session and pre-fills the prompt; a message's action menu also has Fork. To rewind in place, `/undo` (`<leader>u`) or a message's Revert stages a rollback that becomes final when you submit, and `/redo` (`<leader>r`) cancels it.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/tui/src/routes/session/dialog-fork.tsx#L21-L70",
          "evidence": [
            "sessions-opencode-packages-tui-src-routes-session-dialog-fork-tsx",
            "sessions-opencode-opencode-ai-v2-docs-snapshots",
            "sessions-opencode-packages-tui-src-routes-session-dialog-message-tsx"
          ]
        },
        "carries": {
          "status": "supported",
          "answer": "The fork copies finished history (assistant turns still running are skipped), the session's agent, model, permission rules, metadata, and current instruction state, and opens in the original session's directory and workspace. It gets the title `<original> (fork #1)` and starts with zero cost and token counts.",
          "reference": "https://github.com/anomalyco/opencode/blob/042d0832f5f3a73eaa039a58a7d565776f6d4290/packages/core/src/session/projector.ts#L157-L230",
          "evidence": [
            "transcripts-opencode-packages-core-src-session-projector-ts",
            "sessions-opencode-packages-core-src-session-ts"
          ]
        },
        "files": {
          "status": "partial",
          "answer": "No. The fork shares the same working directory. Files are rewound only by `/undo` and Revert, which restore paths from OpenCode's snapshot store (needs a Git repository; turn off with `\"snapshots\": false`). For isolation, ask the agent to call `worktree_create` and `session_move`, or use `/worktrees` to move the session to another workspace.",
          "reference": "https://opencode.ai/v2/docs/snapshots/#restore",
          "evidence": [
            "sessions-opencode-opencode-ai-v2-docs-snapshots",
            "mcp-opencode-opencode-ai-v2-docs-tools",
            "steering-opencode-packages-tui-src-component-prompt-index-tsx"
          ]
        },
        "lineage": {
          "status": "partial",
          "answer": "Each fork records its source session and boundary in the `fork` field (`sessionID`, `boundary`) returned by the session API, but the TUI does not show it. Forks are top-level sessions, so you switch between them with `/sessions` (`<leader>l`).",
          "reference": "https://opencode.ai/v2/docs/api/#session.get",
          "evidence": [
            "instructions-opencode-opencode-ai-v2-docs-api",
            "sessions-opencode-packages-core-src-session-info-ts",
            "transcripts-opencode-packages-core-src-session-projector-ts"
          ]
        },
        "api": {
          "status": "supported",
          "answer": "Yes. `POST /api/session/{sessionID}/fork` takes an optional `before` message ID (omit it to copy everything). `opencode run --continue --fork` and `opencode run --session <id> --fork` fork headlessly, and `opencode acp` advertises and handles ACP `session/fork`.",
          "reference": "https://opencode.ai/v2/docs/api/#session.fork",
          "evidence": [
            "instructions-opencode-opencode-ai-v2-docs-api",
            "image-input-opencode-packages-cli-src-acp-service-ts",
            "opencode-2-0-29-source"
          ],
          "notes": [
            "To change the model or agent, pass `--model` or `--agent` to the `opencode run --fork` call that sends the next prompt; the fork endpoint itself accepts no overrides."
          ]
        }
      },
      "sourceRevision": "042d0832f5f3a73eaa039a58a7d565776f6d4290",
      "surface": "cli"
    },
    {
      "harness": "pi",
      "variant": "current",
      "default": true,
      "support": {
        "fullHistory": "native",
        "turnBoundary": "native",
        "ephemeral": "partial",
        "configurationOverrides": "native",
        "filesystemIsolation": "unsupported"
      },
      "evidence": [
        "memory-pi-packages-coding-agent-docs-sessions-md",
        "instructions-pi-packages-coding-agent-docs-slash-commands-md",
        "pi-docs-1-2-0",
        "steering-pi-packages-coding-agent-docs-keybindings-md",
        "sessions-pi-packages-coding-agent-src-core-agent-session-runtime-ts",
        "steering-pi-kages-coding-agent-src-modes-interactive-interactive-mode-ts",
        "steering-pi-packages-coding-agent-docs-settings-md",
        "transcripts-pi-packages-coding-agent-src-core-session-manager-ts",
        "image-input-pi-packages-coding-agent-src-core-sdk-ts",
        "transcripts-pi-packages-coding-agent-src-main-ts",
        "instructions-pi-packages-coding-agent-docs-security-md",
        "sessions-pi-packages-coding-agent-examples-extensions-git-checkpoint-ts",
        "transcripts-pi-packages-coding-agent-docs-session-format-md",
        "transcripts-pi-g-agent-src-modes-interactive-components-session-selector-ts",
        "steering-pi-packages-coding-agent-docs-rpc-commands-md",
        "steering-pi-packages-coding-agent-docs-sdk-md"
      ],
      "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/sessions.md#L20-L30",
      "observedVersion": "1.2.0",
      "answers": {
        "fork": {
          "status": "supported",
          "answer": "Yes, three ways. `/clone` copies the current branch into a new session, `/fork` makes a new session starting just before an earlier user message you pick, and `/tree` branches inside the same session file. From the shell, `pi --fork <path|id>` copies an existing session into a new session for the current folder before interactive mode starts.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/sessions.md#L20-L30",
          "evidence": [
            "memory-pi-packages-coding-agent-docs-sessions-md",
            "instructions-pi-packages-coding-agent-docs-slash-commands-md",
            "pi-docs-1-2-0",
            "steering-pi-packages-coding-agent-docs-keybindings-md"
          ],
          "notes": [
            "`/fork` and `/tree` have keybinding actions (`app.session.fork`, `app.session.tree`) that are unbound by default. Pressing Escape twice on an empty editor opens `/tree` by default; set `doubleEscapeAction` to `\"fork\"` or `\"none\"` to change that."
          ]
        },
        "point": {
          "status": "supported",
          "answer": "Yes. `/fork` lists your earlier user messages and starts a new session just before the one you pick, putting its text back in the editor so you can edit and resend it. `/tree` lets you jump to any earlier entry in the same session; picking a user message refills the editor, and the branch you leave stays saved. When you leave a branch, Pi can ask whether to summarize it into the branch you move to.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/sessions.md#L28-L32",
          "evidence": [
            "memory-pi-packages-coding-agent-docs-sessions-md",
            "sessions-pi-packages-coding-agent-src-core-agent-session-runtime-ts",
            "steering-pi-kages-coding-agent-src-modes-interactive-interactive-mode-ts",
            "steering-pi-packages-coding-agent-docs-settings-md"
          ],
          "notes": [
            "Set `branchSummary.skipPrompt` to `true` to skip the summary question and never summarize."
          ]
        },
        "carries": {
          "status": "supported",
          "answer": "`/fork` and `/clone` copy only the active branch up to the chosen point (with its labels, compactions and any model or thinking-level changes) into a new file in the same session folder, and keep the session's working directory. Pi then reloads the session, so the model and thinking level come back from the copied history, and `--model` or `--thinking` flags you started Pi with apply again. `pi --fork` copies every entry, including other branches, and moves the copy into the current folder. Pi has no permission prompts to carry over.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/src/core/session-manager.ts#L1627-L1690",
          "evidence": [
            "transcripts-pi-packages-coding-agent-src-core-session-manager-ts",
            "image-input-pi-packages-coding-agent-src-core-sdk-ts",
            "transcripts-pi-packages-coding-agent-src-main-ts",
            "instructions-pi-packages-coding-agent-docs-security-md"
          ]
        },
        "files": {
          "status": "unsupported",
          "answer": "No. Forking, cloning and moving around `/tree` only change the conversation; files on disk stay as they are, and Pi has no checkpoints or worktrees. The repository ships an example extension, `examples/extensions/git-checkpoint.ts`, that saves a `git stash create` snapshot each turn and offers to apply it when you `/fork`.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/examples/extensions/git-checkpoint.ts#L1-L47",
          "evidence": [
            "sessions-pi-packages-coding-agent-examples-extensions-git-checkpoint-ts",
            "sessions-pi-packages-coding-agent-src-core-agent-session-runtime-ts"
          ]
        },
        "lineage": {
          "status": "supported",
          "answer": "A session made by `/fork`, `/clone` or `--fork` stores the source file path in `parentSession` on its first line. The `/resume` picker's Threaded sort (switch sorts with `Ctrl+S`) nests forks under the session they came from. Inside one session, `/tree` shows every branch, and you can label entries with `Shift+L` and filter the view.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/session-format.md#L72-L76",
          "evidence": [
            "transcripts-pi-packages-coding-agent-docs-session-format-md",
            "transcripts-pi-g-agent-src-modes-interactive-components-session-selector-ts",
            "steering-pi-packages-coding-agent-docs-keybindings-md"
          ]
        },
        "api": {
          "status": "supported",
          "answer": "Yes. In the SDK, `AgentSessionRuntime.fork(entryId, { position: \"before\" | \"at\" })` forks or clones, `SessionManager.forkFrom()` copies a whole session file, and `SessionManager.branch()` and `createBranchedSession()` work on the tree directly. RPC mode has `fork`, `clone`, `get_fork_messages` and `get_tree` commands, and `pi --fork <id> -p \"...\"` forks for a one-off headless run.",
          "reference": "https://github.com/earendil-works/pi/blob/06a466935536f8c9bcacb2d5efc0fc021be1bdff/packages/coding-agent/docs/rpc-commands.md#L610-L690",
          "evidence": [
            "steering-pi-packages-coding-agent-docs-rpc-commands-md",
            "steering-pi-packages-coding-agent-docs-sdk-md",
            "sessions-pi-packages-coding-agent-src-core-agent-session-runtime-ts",
            "transcripts-pi-packages-coding-agent-src-core-session-manager-ts",
            "pi-docs-1-2-0"
          ],
          "notes": [
            "Extensions can cancel or react to a fork through the `session_before_fork` event, and fork themselves with `ctx.fork(entryId, { position })`."
          ]
        }
      },
      "sourceRevision": "06a466935536f8c9bcacb2d5efc0fc021be1bdff",
      "surface": "cli"
    }
  ]
}
