Skip to content

feat(cli): add fork-session resume flag#4159

Open
qqqys wants to merge 2 commits into
QwenLM:mainfrom
qqqys:feat/fork-session-cli
Open

feat(cli): add fork-session resume flag#4159
qqqys wants to merge 2 commits into
QwenLM:mainfrom
qqqys:feat/fork-session-cli

Conversation

@qqqys
Copy link
Copy Markdown
Collaborator

@qqqys qqqys commented May 14, 2026

Summary

  • add a --fork-session CLI flag for resuming into a new session
  • wire --resume ... --fork-session and --continue --fork-session through SessionService.forkSession(...)
  • add parser/config tests for validation, picker-style --resume --fork-session, and forked resume loading

Closes #4158

Test plan

  • npm test -- --run src/config/config.test.ts
  • npm run lint -- src/config/config.ts src/config/config.test.ts

Notes

  • npm run typecheck currently fails on unrelated existing project-wide type errors (for example missing core exports and channel package types). This change does not add forkSession/config-test-related type errors.

@github-actions
Copy link
Copy Markdown
Contributor

📋 Review Summary

This PR adds a --fork-session CLI flag that allows users to resume a session while creating a new forked session ID, preserving the original session unchanged. The implementation is clean and well-tested, with proper validation and error handling throughout.

🔍 General Feedback

  • Good use of existing patterns (mirrors --continue/--resume architecture)
  • Test coverage is comprehensive for the new functionality
  • The validation logic correctly prevents invalid flag combinations
  • Error messages are clear and actionable

🎯 Specific Feedback

🟡 High

  • File: packages/cli/src/config/config.ts:1533-1536 - The error handling for --continue --fork-session when no session exists has a logic issue. The else if (argv.forkSession) only triggers when !sessionData in the argv.continue branch, but this means if --continue is used without an existing session AND --fork-session is set, it will error. However, this is actually correct behavior (can't fork nothing), but the error message "No saved session found to fork." could be clearer by mentioning that --continue requires an existing session. Consider: "Cannot use --fork-session with --continue: no saved session found to fork."

🟢 Medium

  • File: packages/cli/src/config/config.ts:164 - The JSDoc comment says "Fork the resumed session into a new session before continuing" but this is slightly misleading since it works with both --resume AND --continue. Consider: "Create a new forked session from the resumed session. Must be used with --resume or --continue."

  • File: packages/cli/src/config/config.ts:916-917 - The validation error message uses --fork-session but the actual flag in yargs is defined as 'fork-session' (kebab-case). While yargs handles both, being consistent in error messages helps users. The current message is correct, but consider adding the short form if one exists (none defined currently).

  • File: packages/cli/src/config/config.test.ts:933 - The test assertion expect(config.getSessionId()).not.toBe(sourceSessionId) is good but could be stronger. Consider also asserting that it equals the expected forked ID: expect(config.getSessionId()).toBe('forked-session-id') to verify the fork actually changed the session ID as expected.

🔵 Low

  • File: packages/cli/src/config/config.ts:809-814 - Consider adding an alias property for --fork-session if there's a natural short form (e.g., -f), though this should be checked against existing aliases to avoid conflicts.

  • File: packages/cli/src/config/config.test.ts:438-443 - The test for "picker form" (--resume --fork-session) expects argv.resume to be '' (empty string). This is correct per the existing --resume behavior, but consider adding a comment explaining why empty string is expected (the picker form) to help future maintainers.

  • File: packages/cli/src/config/config.ts:1552-1561 - The fork logic creates a new SessionService instance inside the if (argv.continue || argv.resume) block at line 1528, then uses it again here. This is fine, but consider extracting the fork logic into a helper function for clarity and testability:

    async function forkCurrentSession(
      sourceSessionId: string,
      sessionService: SessionService
    ): Promise<string> {
      const forkedSessionId = randomUUID();
      await sessionService.forkSession(sourceSessionId, forkedSessionId);
      const sessionData = await sessionService.loadSession(forkedSessionId);
      if (!sessionData) {
        writeStderrLine(`Failed to load forked session ${forkedSessionId}.`);
        process.exit(1);
      }
      return forkedSessionId;
    }

✅ Highlights

  • File: packages/cli/src/config/config.ts:916-917 - Excellent validation preventing --fork-session from being used standalone without --resume or --continue

  • File: packages/cli/src/config/config.test.ts:913-941 - Well-structured test that verifies the complete fork flow including mock setup, execution, and assertions on both the service call and resulting session ID

  • File: packages/cli/src/config/config.test.ts:446-460 - Good coverage of the error case where --fork-session is used without required flags, including verification of the error message

  • Clean integration with existing session resumption logic without disrupting the current flow

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/feature-request New feature or enhancement request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a user-facing way to fork from an existing session

2 participants