Skip to content

feat(tui): add session migration dialog#23250

Closed
sim590 wants to merge 17 commits into
anomalyco:devfrom
sim590:session-migration-menu
Closed

feat(tui): add session migration dialog#23250
sim590 wants to merge 17 commits into
anomalyco:devfrom
sim590:session-migration-menu

Conversation

@sim590

@sim590 sim590 commented Apr 18, 2026

Copy link
Copy Markdown

Issue for this PR

Closes #23249

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Adds a session migration dialog accessible via ctrl+o from the session list. This allows users to:

  1. Recover orphaned sessions — When a project directory is renamed or moved (Sessions become orphaned when project directory is renamed #23248, Session lookup fails with NotFoundError when PTY spawned from non-git directory context #8538), sessions become invisible because their directory field points to a path that no longer exists. The migration dialog shows all sessions across all projects, marks orphaned ones with a yellow ! indicator, and allows moving them to the correct project.

  2. Intentionally migrate sessions between projects — When work was started in the wrong project, users can move the session (with its full conversation history) to another project rather than starting over.

  3. Delete orphaned sessions — Since orphaned sessions don't appear in the normal /sessions list, the migration dialog is the only place where they can be found and deleted (ctrl+d with double-press confirmation).

How it works:

  • The dialog fetches all sessions via /experimental/session (bypassing the SDK's automatic directory filtering) and identifies orphans via a new GET /session/orphans endpoint.
  • Orphan detection uses two criteria: (1) the session directory no longer exists on disk, (2) a global session whose directory is inside a known project worktree.
  • Selecting a session opens a destination picker offering the current project (using the actual cwd), home directory, and all known projects.
  • Migration updates project_id and directory on the session and its children (sub-agents) via a new POST /session/:sessionID/migrate route.
  • After migration, the session list is refreshed so the migrated session appears immediately.

Files changed:

  • dialog-session-migrate.tsx — New migration dialog component
  • dialog-session-rescue.tsx — New destination picker component
  • dialog-session-list.tsx — Added ctrl+o keybind to open migration dialog
  • keybinds.ts — Added session_migrate keybind (default: ctrl+o)
  • session/session.ts — Added listOrphans() and migrate() functions
  • server/routes/instance/session.ts — Added orphans and migrate routes
  • sdk/js/src/v2/gen/ — Regenerated SDK with new endpoints

Note: This does not fix the root cause of orphaned sessions (#23248). An automatic fix in fromDirectory() to update session directories when a project worktree changes would still be valuable, but involves subtleties (e.g. multiple clones of the same repository sharing a project ID).

Possible future improvements:

  • Show a warning in the TUI when opening a migrated session, so the user can give context to the LLM about the project change.
  • Inject a system message after migration to orient the LLM toward the new project context.

How did you verify your code works?

Tested manually on Linux (Alacritty terminal):

  • Created orphaned sessions by renaming project directories (both cases from Sessions become orphaned when project directory is renamed #23248)
  • Verified orphan detection (yellow ! indicator appears and persists after filtering)
  • Migrated sessions between projects and verified they appear in /sessions immediately
  • Deleted orphaned sessions and verified full cascade removal (session, messages, parts)
  • Verified bun typecheck passes with zero errors

Screenshots / recordings

Migration dialog showing all sessions with orphaned ones marked with !:

image

Destination picker after selecting a session:

image

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

sim590 and others added 17 commits April 7, 2026 04:47
# Conflicts:
#	packages/opencode/src/cli/cmd/tui/component/dialog-session-list.tsx
#	packages/opencode/src/config/config.ts
#	packages/opencode/src/server/routes/instance/session.ts
#	packages/opencode/src/session/index.ts
Use a getter for gutter JSX to fix reactivity loss after filtering.
Add ctrl+d keybind to delete sessions with double-press confirmation.
Add orphan legend (!) indicator in the bottom bar.
# Conflicts:
#	packages/opencode/src/config/config.ts
#	packages/opencode/src/config/keybinds.ts
#	packages/opencode/src/config/provider.ts
#	packages/opencode/src/util/effect-zod.ts
#	packages/opencode/test/util/effect-zod.test.ts
@sim590

sim590 commented Apr 18, 2026

Copy link
Copy Markdown
Author

Update: Improved the orphan indicator UX:

  • The ! orphan label in the footer was misleading — it looked like a keybind, as if pressing ! would "orphanize" a session
  • Replaced it with a contextual note at the bottom: NOTE: ! means the session is orphan
  • The note is only shown when orphaned sessions are actually present in the list
  • The ! in the note is displayed in the same warning color as the gutter indicator for consistency
image

@github-actions

Copy link
Copy Markdown
Contributor

Automated PR Cleanup

Thank you for contributing to opencode.

Due to the high volume of PRs from users and AI agents, we periodically close older PRs using automated criteria so maintainers can focus review time on the most active and community-supported contributions.

This PR was closed because it matched the following cleanup criteria:

  • The PR was created more than 1 month ago
  • The PR had fewer than 2 positive reactions
  • Positive reactions are counted as thumbs-up, heart, celebration, or rocket reactions on the PR

PRs created within the last month are not affected by this cleanup.

If you believe this PR was closed incorrectly, or if you are still actively working on it, please leave a comment explaining why it should be reopened. A maintainer can review and reopen it if appropriate.

Thanks again for taking the time to contribute.

@sim590

sim590 commented May 18, 2026

Copy link
Copy Markdown
Author

This PR should be reopened. Here's why:

  1. Active development around this feature: There are currently three PRs addressing session migration (feat(tui): add session migration dialog #23250, feat(session): add methods to migrate session #24726, feat: opencode session move / session detached #24728), and contributors are actively coordinating on the design in [FEATURE]: Add session migration dialog to recover orphaned or misplaced sessions #23249. Closing this PR disrupts that coordination.

  2. Unique contribution: This is the only PR that provides a TUI dialog for session migration. feat(session): add methods to migrate session #24726 covers the backend/CLI side, and feat: opencode session move / session detached #24728 covers bulk CLI operations, but neither includes the interactive TUI experience. As noted in feat(session): add methods to migrate session #24726's own description: "This PR intentionally does not include the TUI migration dialog from feat(tui): add session migration dialog #23250 yet."

  3. The workflows were never approved: The CI checks (e2e, typecheck, unit tests) were stuck on "waiting for approval" as a first-time contributor. The PR was never actually reviewed.

  4. Still actively maintained: I'm actively rebasing and fixing compatibility issues with the latest dev branch. I'm also ready to adapt the TUI portion to work on top of feat(session): add methods to migrate session #24726's backend once the approach is agreed upon in [FEATURE]: Add session migration dialog to recover orphaned or misplaced sessions #23249.

Could a maintainer please reopen this PR?

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE]: Add session migration dialog to recover orphaned or misplaced sessions

2 participants