[FEATURE]: Auto-relink stale sessions when project_id matches but directory is outdated #27822
Description
name: "Feature Request: Auto-relink stale sessions when project_id matches current project"
about: "Suggest an idea for OpenCode"
title: "feat: auto-relink stale sessions when project_id matches but directory is outdated"
labels: ["enhancement", "core"]
问题 / Problem
当项目文件夹被重命名或移动(如 my-project → my-project-v2),所有现有会话在 UI 中消失——尽管它们仍存在于数据库中,且仍然通过 project_id 正确关联到项目。
When a project folder is renamed or moved (e.g. my-project → my-project-v2), all existing sessions become invisible in the UI — even though they still exist in the database and are still correctly linked to the project via project_id.
根本原因 / Root Cause
-
session.directory在会话创建时设置,之后从不更新。 -
project.worktree保持最新(会创建新的 project 行,使用相同的project_id和新路径)。 -
UI 通过
directory查询会话,所以当路径不存在时旧会话被过滤掉。 -
session.project_id引用project.id(派生自 git 根提交哈希),在文件夹重命名时保持稳定。 -
session.directoryis set at session creation time and never updated. -
project.worktreeis kept current (a new project row is created with the sameproject_idand the new path). -
The UI queries sessions by
directory, so old sessions are filtered out when the path no longer exists. -
session.project_idreferencesproject.id(derived from the git root commit hash), which stays stable across renames.
示例 / Example
-- 重命名前 / Before rename
session.directory = "/path/to/my-project"
project.worktree = "/path/to/my-project"
project.id = "abc123..." (git root commit hash)
-- 重命名后 / After rename
session.directory = "/path/to/my-project" ← 过时,路径已不存在 / stale, path no longer exists
project.worktree = "/path/to/my-project-v2" ← 当前路径 / current
project.id = "abc123..." ← 未改变 / unchanged会话仍然有效(相同的 project_id),但 UI 不会显示它,因为 directory 指向一个不存在的路径。
The session is still valid (same project_id), but the UI won't show it because directory points to a non-existent path.
建议方案 / Proposed Solution
加载项目会话时,如果 session.directory 在磁盘上不存在,但 session.project_id 匹配到一个具有有效 worktree 的项目,则使用 project.worktree 作为有效目录。
When loading sessions for a project, if session.directory doesn't exist on disk but session.project_id matches a project with a valid worktree, use project.worktree as the effective directory.
方案 A:查询时动态 fallback(推荐)/ Option A: On-the-fly resolution (recommended)
在会话查询中,当 session.directory 过时时回退到 project.worktree:
In the session query, fall back to project.worktree when session.directory is stale:
SELECT s.*, COALESCE(
CASE WHEN s.directory IS NOT NULL AND EXISTS (SELECT 1 FROM ... WHERE path = s.directory)
THEN s.directory
ELSE p.worktree
END,
s.directory
) AS effective_directory
FROM session s
JOIN project p ON s.project_id = p.id
WHERE p.worktree = ?方案 B:打开项目时自动更新 / Option B: Auto-update on project open
当 OpenCode 打开项目并检测到 project.worktree 已变化时,自动更新所有过时会话:
When OpenCode opens a project and detects that project.worktree has changed, automatically update all stale sessions:
UPDATE session
SET directory = p.worktree
FROM project p
WHERE session.project_id = p.id
AND session.directory != p.worktree
AND NOT EXISTS (SELECT 1 FROM ... WHERE path = session.directory);验证 / Evidence
我们构建了一个独立的恢复工具 (opencode-session-recovery),实现了方案 B。它在文件夹重命名后成功恢复了所有"丢失"的会话,通过运行:
We built a standalone recovery tool (opencode-session-recovery) that implements Option B. It successfully recovers all "lost" sessions after folder renames by running:
UPDATE session SET directory = p.worktree
FROM project p
WHERE session.project_id = p.id
AND session.directory != p.worktree;这对 git 仓库可靠有效,因为 project_id(git 根提交哈希)在重命名时保持稳定。
This works reliably for git repositories because project_id (git root commit hash) is stable across renames.
影响 / Impact
-
消除常见用户痛点:重命名文件夹当前会"丢失"所有对话历史。
-
无数据丢失风险:只更新
directory指针,不触碰对话内容。 -
适用于 git 仓库:覆盖绝大多数 OpenCode 使用场景(project_id 稳定)。
-
优雅降级:对于非 git 目录(
project_id为SHA1(path)),可保持当前行为或回退到路径启发式匹配。 -
Eliminates a common user pain point: renaming a folder currently "loses" all conversation history.
-
No data loss risk: only updates the
directorypointer, never touches conversation content. -
Works for git repos: covers the vast majority of OpenCode use cases (project_id is stable).
-
Graceful fallback: for non-git directories (where
project_idisSHA1(path)), the current behavior can remain, or fall back to path-heuristic matching.
相关问题 / Related Issues
- #16878 — Old sessions cannot be loaded
- #21156 — Session lost after folder rename
- #26505 — Session history disappears
环境 / Environment
- OpenCode 版本 / Version: 所有使用
~/.local/share/opencode/opencode.db的版本 / all versions - 操作系统 / OS: Windows / macOS / Linux
- 触发条件 / Trigger: 重命名或移动项目文件夹 / renaming or moving a project folder
Activity
github-actions commentedon May 16, 2026
This issue doesn't fully meet our contributing guidelines.
What needs to be fixed:
[FEATURE]:(current title usesfeat:)Please edit this issue to address the above within 2 hours, or it will be automatically closed.
This issue might be a duplicate of existing issues. Please check:
session.directoryafter folder rename, sessions invisible in UI despite existing in the database)If you believe this was flagged incorrectly, please let a maintainer know.
[-]feat: auto-relink stale sessions when project_id matches but directory is outdated[/-][+][FEATURE]: Auto-relink stale sessions when project_id matches but directory is outdated[/+]bbl21 commentedon May 16, 2026
Verification
Regarding Duplicates
Thank you for flagging the related issues. This issue differs in scope:
The core argument is: OpenCode already has all the data it needs (\session.project_id\ + \project.worktree) to resolve stale directories automatically. No new schema, no new UI, just a small query adjustment.
github-actions commentedon May 16, 2026
Thanks for updating the issue! The title now correctly starts with
[FEATURE]:and the content is clear and well-detailed. Theneeds:compliancelabel has been removed. We appreciate the thorough write-up and the proof-of-concept tool!WhiteGiverMa commentedon Jun 21, 2026
This would be the cleanest fix for the directory-rename problem cluster (#30697, #31869, #31888, #23248, #29703).
In my case (Windows 11 + WSL2, Desktop v1.17.9), after renaming
DreamerHeroines→dreamer-heroines:project_idremained inopencode.dbpointing to the non-existent pathproject_idwas created for the new pathproject_idhaddirectoryfields with the old absolute pathproject_idin its Electron caches but the path was goneAuto-relink on
project_idmatch +directorymismatch would have made this a non-issue. The server already knows the currentworktreefrom theprojecttable — it just needs to update sessiondirectoryfields when it detects a mismatch.Necmttn commentedon Jun 21, 2026
The
project_id-based relink sounds like the right primitive. I would add two guardrails so it stays safe:session.directoryrewriteTwo edge cases matter:
Keeping the old directory as provenance also helps later diagnostics. A session can be visible under the new project while still explaining where it was originally created.
Generated with ax.
mskadu commentedon Jun 24, 2026
The existing
/moveTUI command (session.move) is a good UX foundation to build on here. It already has the dialog, destination picker, moveSession endpoint, progress indicators, and directory-change reminder. Currently it only moves one session at a time.Enhancing
/moveto handle the project-rename case would just need:The dialog infrastructure is already there — just needs the stale-session detection and batch path.
github-actions commentedon Aug 24, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.