A /move-session slash command for opencode on Windows/PowerShell 5.
It moves the current session to another directory by updating opencode's session rows directly, so the session becomes discoverable from the new location.
中文README: README.zh-CN.md
/move-session <target>
/move-session --debug <target>
Examples:
/move-session E:\repo\subdir
/move-session ..\sibling
/move-session .\child-folder
/move-session --debug ..\other-folder
<target> can be:
- An absolute Windows path like
E:\repo\subdir - A
~/...path - A relative path like
..\siblingor.\child - The feature to specify the target directory via natural language was removed. It was taken out to simplify debugging. I don't have time to add it back.
The command updates the root session and all descendant subagent sessions.
Fields updated in session:
project_iddirectorypathtime_updated
The current behavior:
global -> global: allowedglobal -> git: allowedgit -> same git project: allowedgitA -> gitB: allowed, but downgraded toglobal
That fourth case is important: the session is not rebound to another unrelated git project by default. Instead, it is moved as a plain directory-scoped session.
When a target directory is a git repository, the script resolves its project identity using opencode's precedence:
originremote, normalized and hashed assha1("git-remote:<host/path>").git/opencodecached id- root commit hash
- fallback to
global
If the target git repository has a non-global id but is missing from opencode's project table, the script registers it automatically.
Windows path handling was the main source of bugs during development.
The final rules are:
- Stored
directorystays a normalized Windows path likeE:/test/testfolder2 - Stored
pathmust match how opencode actually filters sessions
For global sessions on Windows, that means:
directory = E:/test/testfolder2path = test/testfolder2
Not:
path = E:/test/testfolder2
For git sessions, path is relative to the git worktree root:
- repo root ->
"" - repo subdir ->
subdir/nested
By default the command is quiet and prints only one of:
moved: ...noop: already at ...ERR: ...
To enable diagnostics:
/move-session --debug <target>
That prints DEBUG: lines with values such as:
ROOT_SESSIONTARGETNEW_PIDPROJ_WORKTREEREL_PATHOLD_PROJECTDOWNGRADED_TO_GLOBAL
| File | Role |
|---|---|
plugins/session-env.js |
Injects OPENCODE_SESSION_ID, OPENCODE_PROJECT_ID, OPENCODE_WORKTREE, OPENCODE_DIRECTORY, and OPENCODE_CALL_ID into shell commands. |
commands/move-session.md |
Slash command wrapper that passes the raw user argument through to the PowerShell script. |
commands/move-session.ps1 |
Main move logic, path normalization, git detection, and direct SQLite updates. |
plugins/move-session-auto-undo.js |
Deferred cleanup on next opencode startup. |
install.ps1 |
Windows installer. |
opencode session discovery is not based only on directory.
The session list is filtered primarily by:
project_id- and then
pathordirectory, depending on the caller
So simply editing directory is not enough. The session has to be rewritten in a way that matches opencode's real lookup rules.
This repo is written around Windows PowerShell 5 behavior.
Important implementation details:
- Avoid nested quoting through
powershell -Commandby passing the target through an environment variable - Avoid native stderr causing terminating errors under
$ErrorActionPreference = 'Stop'by usingcmd /c "git ... 2>nul"where needed
(Not tested.)
iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/maxchen32/opencode-move-session-ps/main/install.ps1'))$dest = "$env:USERPROFILE\.config\opencode"
New-Item -ItemType Directory -Path "$dest\plugins", "$dest\commands" -Force | Out-Null
Copy-Item .\plugins\*.js "$dest\plugins\"
Copy-Item .\commands\*.md "$dest\commands\"
Copy-Item .\commands\*.ps1 "$dest\commands\"Then restart opencode.
- Existing opencode instances may keep old in-memory context until you switch or reopen
- This command writes directly to
opencode.db - If opencode changes session/project schema or filtering rules, this plugin may need updating
- Cross-git moves intentionally lose git project binding by degrading to
global
MIT — see LICENSE.