Skip to content

Conversation

@wpfleger96
Copy link
Collaborator

@wpfleger96 wpfleger96 commented Nov 25, 2025

This PR adds session forking (duplication) across CLI, backend API, and desktop UI with a unified, simplified approach

Based on feedback this PR was simplified from the original implementation

I often do something like this in Claude Code by running claude --resume <id> --fork-session:

                                                                        /-> (still original): User2 ("write tests for x")
Original: User1 ("implement x for me") -> LLM1 ("ok implemented x") ---|
                                                                        \-> forked: User3 ("write docs for x")

After the change in this PR, now I can do in goose by goose --resume --session-id <id> --fork.

Unified Fork API

  • Renamed edit_message endpoint → fork and added boolean truncate and copy parameters
  • Single endpoint handles all use cases: full copy, edit-in-place, and branch-at-point
  • Removed redundant fork_session() wrapper (thin wrapper around copy_session()) from original PR implementation
  • Removed over-engineered UI code: useForkSession hook, ChatInput fork button from original PR implementation

Backend Changes

  • POST /sessions/{id}/fork with ForkRequest { truncate: bool, copy: bool, timestamp?: i64 }
  • Validation: truncate=true requires timestamp, returns structured ErrorResponse
  • Uses existing copy_session() and truncate_conversation() primitives
  • Fixed copy_session() to preserve provider_name and model_config

CLI Implementation

  • --fork flag (requires --resume) duplicates sessions
  • Calls copy_session() directly (no HTTP endpoint needed)
  • Simplified session resolution to eliminate duplication

Desktop UI

  • Added "Duplicate" button in session list using forkSession({ truncate: false, copy: true })
  • Updated existing edit message fork to use new unified API
  • Removed fork button from ChatInput and useForkSession hook

Use Case Matrix

truncate copy Result Use Case
false true Full session copy Duplicate for parallel work (my use case for this PR)
true false Edit in place Truncate current session (existing Edit in Place UI option)
true true Branch at point Copy + truncate at timestamp (exiting Fork Session UI option)

Addresses #5865

Copilot AI review requested due to automatic review settings November 25, 2025 23:49
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements session forking functionality across the full stack (CLI, backend API, and desktop UI), allowing users to create independent copies of sessions with preserved conversation history. This enables exploring different conversation paths without losing the original thread, similar to how Claude Code handles session forking.

Key changes:

  • Added POST /sessions/{id}/fork endpoint that leverages copy_session() with provider and model preservation
  • Implemented --fork CLI flag (requires --resume) supporting session ID, name, or path identifiers
  • Created fork buttons in SessionListView and ChatInput that open forked sessions in new windows via useForkSession hook

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
crates/goose/src/session/session_manager.rs Added fork_session() method and fixed copy_session() to preserve provider_name and model_config; includes test for conversation preservation
crates/goose-server/src/routes/session.rs Added fork_session API endpoint handler that returns forked session
crates/goose-server/src/openapi.rs Registered fork_session endpoint in OpenAPI schema
crates/goose-cli/src/cli.rs Added --fork flag with --resume requirement; updated get_or_create_session_id to handle fork logic for ID/name/path identifiers
crates/goose-cli/src/session/builder.rs Added fork field to SessionBuilderConfig struct and updated default/test values
crates/goose-cli/src/commands/bench.rs Set fork: false in benchmark session configuration
ui/desktop/src/hooks/useForkSession.ts Created hook that calls fork API, handles errors/loading, and opens forked session in new window
ui/desktop/src/components/sessions/SessionListView.tsx Added fork button with GitFork icon and handleForkSession callback that reloads sessions on success
ui/desktop/src/components/ChatInput.tsx Added fork button in bottom toolbar with disabled state during forking
ui/desktop/src/api/types.gen.ts Generated TypeScript types for ForkSession API including data, errors, and responses
ui/desktop/src/api/sdk.gen.ts Generated forkSession SDK function as POST to /sessions/{session_id}/fork
ui/desktop/openapi.json Added OpenAPI specification for fork endpoint with 200/404/500 responses

* main:
  fix: adjust strange spacing in agent.rs (#5877)
  Move recipe actions to bottom bar icon and edit goosehints to settings (#5864)
  [docs] Add “Building a Social Media Agent” Blog Post (#5844)
  deps: upgrade rmcp to 0.9.1 (#5860)
  chore: suggest using text/markdown when fetching content (#5854)
  Revert "fix: do not load active extensions when no extensions in the recipe" (#5871)
  goose remote access (#5251)
  docs: add DataHub MCP server extension documentation (#5769)
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated no new comments.

Copy link
Collaborator

@DOsinga DOsinga left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have the same functionality in edit message, this duplicates this with an extra method and an extra route; either remove the old way or use it I would say.

@wpfleger96 wpfleger96 marked this pull request as draft December 4, 2025 23:08
@zanesq
Copy link
Collaborator

zanesq commented Dec 11, 2025

Just reiterating what @DOsinga said the desktop now has fork session support in chat

image

* main: (155 commits)
  remove Tool Selection Strategy preview (#6250)
  fix(cli): correct bash syntax in terminal integration functions (#6181)
  fix : opening a session to view it modifies session history order in desktop (#6156)
  test: fix recipe and audio tests to avoid side effects (#6231)
  chore: Update gemini versions in test_providers.sh (#6246)
  feat: option to stream json - jsonl really (#6228)
  feat: add mcp app renderer (#6095)
  docs: update skills extension to support .agents/skills directories (#6199)
  Add YouTube short to Chrome DevTools MCP tutorial (#6244)
  docs: Caveats for privacy information in logs documentation (#6218)
  move goose issue solver to opus (#6233)
  feat: improved UX for tool calls via execute_code (#6205)
  Blog: Code Mode Doesn't Replace MCP (#6227)
  fix: prevent keychain requests during cargo test (#6219)
  test: fix test_max_turns_limit slow execution and wrong message type (#6221)
  Skills vs MCP blog (#6220)
  Add blog post: Does Your AI Agent Need a Plan? (#6209)
  fix(ui): enable MCP UI to send a prompt message when an element is clicked (#6207)
  docs: param option for recipe deeplink/open (#6206)
  docs: edit in place or fork session (#6203)
  ...
@wpfleger96 wpfleger96 marked this pull request as ready for review December 23, 2025 20:43
Copilot AI review requested due to automatic review settings December 23, 2025 20:43
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.

@wpfleger96
Copy link
Collaborator Author

wpfleger96 commented Dec 23, 2025

@DOsinga @zanesq just simplified the PR based your feedback, what do y'all think now? I named this "fork" since that's what Claude Code calls the equivalent functionality I'm trying to implement, but I think I made it confusing since there's already a "Fork Session" in goose UI. what I want here is really "duplicate" instead of "fork"

truncate copy Result Use Case
false true Full session copy Duplicate for parallel work (my use case for this PR)
true false Edit in place Truncate current session (existing Edit in Place UI option)
true true Branch at point Copy + truncate at timestamp (exiting Fork Session UI option)

@wpfleger96 wpfleger96 force-pushed the wpfleger/fork-session branch from d5c9184 to 3fb2dc7 Compare December 23, 2025 21:03
Copilot AI review requested due to automatic review settings January 9, 2026 18:12
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 18 out of 18 changed files in this pull request and generated 1 comment.

* main: (89 commits)
  fix(google): treat signed text as regular content in streaming (#6400)
  Add frameDomains and baseUriDomains CSP support for MCP Apps (#6399)
  fix(ci): add missing dependencies to openapi-schema-check job (#6367)
  feat: http proxy support
  Add support for changing working dir and extensions in same window/session (#6057)
  Sort keys in canonical models (#6403)
  added validation and debug for invalid call tool result (#6368)
  Update MCP apps tutorial: fix _meta structure and version prereq (#6404)
  Fixed fonts (#6389)
  Update confidence levels prompt injection detection to reduce false positive rates (#6390)
  Add ML-based prompt injection detection  (#5623)
  docs: update custom extensions tutorial (#6388)
  fix ResultsFormat error when loading old sessions (#6385)
  docs: add MCP Apps tutorial and documentation updates (#6384)
  changed z-index to make sure the search highlighter does not appear on modal overlay (#6386)
  Handling special claude model response in github copilot provider (#6369)
  fix: prevent duplicate rendering when tool returns both mcp-ui and mcp-apps resources (#6378)
  fix: update MCP Apps _meta.ui.resourceUri to use nested format (SEP-1865) (#6372)
  feat(providers): add streaming support for Google Gemini provider (#6191)
  Blog: edit links in mcp apps post (#6371)
  ...
@wpfleger96 wpfleger96 force-pushed the wpfleger/fork-session branch from b4105b9 to 1b9cf6f Compare January 9, 2026 18:28
* main: (41 commits)
  Allow customizing the new line keybinding in the CLI (#5956)
  Ask for permission in the CLI (#6475)
  docs: add Ralph Loop tutorial for multi-model iterative development (#6455)
  Remove gitignore fallback from gooseignore docs (#6480)
  fix: clean up result recording for code mode (#6343)
  fix(code_execution): handle model quirks with tool calls (#6352)
  feat(ui): support prefersBorder option for MCP Apps (#6465)
  fixed line breaks (#6459)
  Use Intl.NumberFormat for token formatting in SessionsInsights (#6466)
  feat(ui): format large and small token counts for readability (#6449)
  fix: apply subrecipes when using slash commands (#6460)
  Fix: exclude platform_schedule_tool in CLI (#6442)
  Fix: Small update in how ML-based prompt injection determines final result (#6439)
  docs: remove SSE transport and rename to Streamable HTTP (#6319)
  fix: correct Cloudinary extension command and env variable (#6453)
  fix: add gap between buttons in MacDesktopInstallButtons.js (#6452)
  refactor: include hidden dotfiles folders in file picker search (#6315)
  upgraded safe npm packages (#6450)
  chore(deps): bump react-router and react-router-dom in /ui/desktop (#6408)
  chore(deps): bump lru from 0.12.5 to 0.16.3 (#6379)
  ...
Copilot AI review requested due to automatic review settings January 13, 2026 21:57
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.

@zanesq
Copy link
Collaborator

zanesq commented Jan 14, 2026

LGTM Front end changes look good also tested locally in the desktop app and everything is working. I'll defer to @DOsinga for the cli changes

Copilot AI review requested due to automatic review settings January 22, 2026 17:19
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Comments suppressed due to low confidence (1)

crates/goose-cli/src/cli.rs:742

  • The --history flag at line 741 requires resume, but when --fork is used, the user might also want to see the history. The condition at line 1131 correctly handles (resume || fork) && history, but the CLI argument at line 741 only requires resume. This means users must specify both --resume --fork --history instead of being able to use --fork --history. Consider updating the requires constraint to allow --history with either --resume or --fork.
        /// Show message history when resuming
        #[arg(
            long,
            help = "Show previous messages when resuming a session",
            requires = "resume"
        )]

@wpfleger96 wpfleger96 force-pushed the wpfleger/fork-session branch from b25ebb4 to fb5f379 Compare January 22, 2026 17:24
Copilot AI review requested due to automatic review settings January 22, 2026 17:34
@wpfleger96 wpfleger96 requested a review from a team as a code owner January 22, 2026 17:34
* main: (68 commits)
  fix(docs): use dynamic import for globby ESM module (#6636)
  chore: trigger CI
  Document tab completion (#6635)
  Install goose-mcp crate dependencies (#6632)
  feat(goose): standardize agent-session-id for session correlation (#6626)
  chore: tweak release docs (#6571)
  fix(goose): propagate session_id across providers and MCP (#6584)
  increase worker threads for ci (#6614)
  docs: todo tutorial update (#6613)
  Added goose doc map md file for goose agent to find relevant doc easily. (#6598)
  add back goose branding to home (#6617)
  fix: actually set the working dir for extensions from session (#6612)
  Multi chat (#6428)
  Lifei/fixed accumulated token count (#6587)
  Dont show MCP UI/Apps until tool is approved (#6492)
  docs: max tokens config (#6596)
  User configurable templates (#6420)
  docs: http proxy environment variables (#6594)
  feat: exclude subagent tool from code_execution filtering (#6531)
  Fix path for global agent skills (#6591)
  ...
@wpfleger96 wpfleger96 force-pushed the wpfleger/fork-session branch from a67f544 to cb9bc17 Compare January 22, 2026 17:36
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

@github-actions
Copy link
Contributor

PR Preview Action v1.6.3

🚀 View preview at
https://block.github.io/goose/pr-preview/pr-5882/

Built to branch gh-pages at 2026-01-22 17:38 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@wpfleger96 wpfleger96 merged commit 13bdff4 into main Jan 22, 2026
16 of 17 checks passed
@wpfleger96 wpfleger96 deleted the wpfleger/fork-session branch January 22, 2026 17:49
lifeizhou-ap added a commit that referenced this pull request Jan 22, 2026
* main:
  docs: ml-based prompt injection detection (#6627)
  Strip the audience for compacting (#6646)
  chore(release): release version 1.21.0 (minor) (#6634)
  add collapsable chat nav (#6649)
  fix: capitalize Rust in CONTRIBUTING.md (#6640)
  chore(deps): bump lodash from 4.17.21 to 4.17.23 in /ui/desktop (#6623)
  Vibe mcp apps (#6569)
  Add session forking capability (#5882)
  chore(deps): bump lodash from 4.17.21 to 4.17.23 in /documentation (#6624)
  fix(docs): use named import for globby v13 (#6639)
  PR Code Review (#6043)
  fix(docs): use dynamic import for globby ESM module (#6636)
  chore: trigger CI
  Document tab completion (#6635)
  Install goose-mcp crate dependencies (#6632)
  feat(goose): standardize agent-session-id for session correlation (#6626)
fbalicchia pushed a commit to fbalicchia/goose that referenced this pull request Jan 23, 2026
Co-authored-by: Zane Staggs <zane@squareup.com>
Signed-off-by: fbalicchia <fbalicchia@cuebiq.com>
tlongwell-block added a commit that referenced this pull request Jan 23, 2026
* origin/main:
  Fix GCP Vertex AI global endpoint support for Gemini 3 models (#6187)
  fix: macOS keychain infinite prompt loop    (#6620)
  chore: reduce duplicate or unused cargo deps (#6630)
  feat: codex subscription support (#6600)
  smoke test allow pass for flaky providers (#6638)
  feat: Add built-in skill for goose documentation reference (#6534)
  Native images (#6619)
  docs: ml-based prompt injection detection (#6627)
  Strip the audience for compacting (#6646)
  chore(release): release version 1.21.0 (minor) (#6634)
  add collapsable chat nav (#6649)
  fix: capitalize Rust in CONTRIBUTING.md (#6640)
  chore(deps): bump lodash from 4.17.21 to 4.17.23 in /ui/desktop (#6623)
  Vibe mcp apps (#6569)
  Add session forking capability (#5882)
  chore(deps): bump lodash from 4.17.21 to 4.17.23 in /documentation (#6624)
  fix(docs): use named import for globby v13 (#6639)
  PR Code Review (#6043)
  fix(docs): use dynamic import for globby ESM module (#6636)

# Conflicts:
#	Cargo.lock
#	crates/goose-server/src/routes/session.rs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants