Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

opencode-relocate-cli

A standalone CLI tool for managing OpenCode session locations, no LLM required. Runs as a plain Bash script, directly manipulating the OpenCode SQLite database. No OpenCode session, no Bun runtime, and no LLM round-trips needed.

Quick Reference

CommandWhat it doesWhen to use it
opencode-relocate relocateMoves the project directory and updates all referencesYou moved or renamed a repo on disk
opencode-relocate move-sessionsReassigns selected sessions to another projectSessions were started in the wrong project
opencode-relocate split-projectCreates a new project and moves sessions into itYou split a repo or want to reorganize history
opencode-relocate relinkRe-links a project after its initial commit was recreatedYou reset/recreated the root commit and lost session history

Installation

Option 1: Symlink to PATH

ln -s "$(pwd)/opencode-relocate" /usr/local/bin/opencode-relocate

Option 2: Copy to PATH

cp opencode-relocate /usr/local/bin/opencode-relocate
chmod +x /usr/local/bin/opencode-relocate

Option 3: Run directly

./opencode-relocate <command> [args...]

Requirements

  • sqlite3 — pre-installed on macOS and most Linux distributions
  • git — required for split-project and relink (derives project IDs from root commits)
  • jq — optional; used for JSON updates when available, falls back to sed

Commands

relocate — Move a project to a new path

opencode-relocate relocate <old-path><new-path>

Moves the project directory and updates all internal OpenCode references (SQLite database and project JSON file).

# Example: rename a project directory
opencode-relocate relocate ~/Projects/my-app ~/Projects/my-app-v2

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Moves the directory with mv
  3. Updates project.worktree and session.directory in SQLite
  4. Updates the project JSON in OpenCode's storage
  5. Verifies all changes

After relocation, restart OpenCode from the new path:

cd~/Projects/my-app-v2 && opencode

move-sessions — Reassign sessions between projects

opencode-relocate move-sessions <source-path><target-path> [options]

Move sessions from one OpenCode project to another. Both projects must already exist in OpenCode (opened at least once).

The source can be a non-git directory — in that case, sessions are stored under the global project and are filtered by directory prefix so only sessions matching the source path are shown.

Three modes:

# Interactive (default) — checkbox-style session selector
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b
# List only — inspect sessions without moving
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b --list
# Scripted — provide session IDs directly
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b \
--session-ids "ses_abc123,ses_def456"

Interactive selector controls:

KeyAction
/ (or k / j)Navigate up / down
SpaceToggle current session
aToggle all sessions
EnterConfirm selection
q / EscCancel

The selector shows [x] / [ ] checkboxes, highlights the current row, scrolls automatically for long lists, and displays a live count of selected sessions.

Child/subagent sessions are moved automatically with their parent.


split-project — Create a new project from sessions

opencode-relocate split-project <source-path><target-path> [options]

Like move-sessions, but the target doesn't need to exist as an OpenCode project. If the target directory has never been opened in OpenCode, a new project entry is created automatically.

If the target directory doesn't exist, split-project will prompt you to create it (mkdir -p). If it's not a git repository (or has no commits), you'll be prompted to initialize it (git init + initial empty commit). The source can be either a git-backed project or a non-git directory (global project — sessions are filtered by directory prefix).

# Interactive (checkbox selector)
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service
# Split sessions from a non-git directory into a git-backed project
opencode-relocate split-project ~/Projects/sandbox ~/Projects/new-repo
# List only
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service --list
# Scripted
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service \
--session-ids "ses_abc123,ses_def456"

Same interactive controls as move-sessions (arrow keys, Space, Enter).

When to use split-project vs move-sessions:

ScenarioCommand
Target project already exists in OpenCodeEither works
Target directory was never opened in OpenCodesplit-project
Source is a non-git directory (global project)Either works (filtered by directory)
Target directory is not a git reposplit-project (will offer to git init)

relink — Re-link a project after its initial commit changed

opencode-relocate relink <path> [options]

OpenCode identifies a project by the hash of its first root commit (git rev-list --max-parents=0 HEAD). If you reset or recreate the initial commit — e.g. squashing history, git update-ref -d HEAD, or rebuilding the repo — that hash changes, and OpenCode treats the repo as a brand-new project. All previous sessions become orphaned.

relink migrates the existing project from the old ID to the new root-commit-derived ID: sessions, workspaces, permissions, on-disk JSON artifacts, and the .git/opencode cache file.

# Auto-detect old and new IDs and relink
opencode-relocate relink ~/Projects/my-app
# Preview changes without writing anything
opencode-relocate relink ~/Projects/my-app --dry-run
# Specify IDs explicitly
opencode-relocate relink ~/Projects/my-app \
--old-id eca18ff587da0906289bd984d8b0fd7622b69604 \
--new-id b761b3048a1c1129822fcfaaf9252db49dace055

Auto-detection:

  • New ID is derived from the repo's current root commit hash.
  • Old ID is found by looking up the project whose worktree matches <path> but whose ID differs from the new ID, falling back to the cached value in .git/opencode.

Merge behavior: If a project row for the new ID already exists (e.g. you reopened OpenCode after the reset, so it created a fresh project), the old sessions are merged into it. Otherwise a new project row is created as a copy of the old one.

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Re-points session, workspace, and permission rows to the new ID
  3. Creates or merges into the new project row, then deletes the old one
  4. Migrates storage/project/<id>.json and storage/session/<id>/ artifacts
  5. Updates the .git/opencode cache to the new ID
  6. Verifies the migration

Sessions keep their existing directory — only the project ID changes. Use --dry-run first if you want to preview the exact changes.

Safety

Automatic backups

Every command backs up opencode.db (plus WAL/SHM files) before making changes. Backups are timestamped:

~/.local/share/opencode/opencode.db.20260408_143022.bak

Interactive confirmation

All destructive operations require [y/N] confirmation before proceeding.

What's preserved

  • All session content: messages, tool calls, parts, todos
  • Session metadata: titles, timestamps, summaries
  • Parent-child session relationships (subagent sessions move with their parent)

What's NOT preserved

  • Undo/redo snapshots — stored per-project, not per-session

Recovery

Restore from backup:

cp ~/.local/share/opencode/opencode.db.20260408_143022.bak \
~/.local/share/opencode/opencode.db

Limitations

  • After relocate, the current OpenCode session breaks (restart required).
  • move-sessions requires the target to already exist as an OpenCode project.
  • Undo/redo snapshots are not moved.
  • Clones of the same repository share the same project ID (same root commit), so you cannot move sessions between clones of the same repo.
  • The global project cannot be used as a target — only as a source (sessions are filtered by directory prefix).
  • relink derives the new project ID from git rev-list --max-parents=0 HEAD and updates the .git/opencode cache; the repo must have at least one commit.

Disclaimer

This is an independent, community-built tool. It is not built by the OpenCode team and is not affiliated with OpenCode in any way. The "opencode" in the name refers only to the tool's purpose of managing OpenCode session data.

About

Bash CLI to move, relink, and reorganize OpenCode projects and sessions directly in its SQLite database.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

opencode-relocate-cli

A standalone CLI tool for managing OpenCode session locations, no LLM required. Runs as a plain Bash script, directly manipulating the OpenCode SQLite database. No OpenCode session, no Bun runtime, and no LLM round-trips needed.

Quick Reference

CommandWhat it doesWhen to use it
opencode-relocate relocateMoves the project directory and updates all referencesYou moved or renamed a repo on disk
opencode-relocate move-sessionsReassigns selected sessions to another projectSessions were started in the wrong project
opencode-relocate split-projectCreates a new project and moves sessions into itYou split a repo or want to reorganize history
opencode-relocate relinkRe-links a project after its initial commit was recreatedYou reset/recreated the root commit and lost session history

Installation

Option 1: Symlink to PATH

ln -s "$(pwd)/opencode-relocate" /usr/local/bin/opencode-relocate

Option 2: Copy to PATH

cp opencode-relocate /usr/local/bin/opencode-relocate
chmod +x /usr/local/bin/opencode-relocate

Option 3: Run directly

./opencode-relocate <command> [args...]

Requirements

  • sqlite3 — pre-installed on macOS and most Linux distributions
  • git — required for split-project and relink (derives project IDs from root commits)
  • jq — optional; used for JSON updates when available, falls back to sed

Commands

relocate — Move a project to a new path

opencode-relocate relocate <old-path><new-path>

Moves the project directory and updates all internal OpenCode references (SQLite database and project JSON file).

# Example: rename a project directory
opencode-relocate relocate ~/Projects/my-app ~/Projects/my-app-v2

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Moves the directory with mv
  3. Updates project.worktree and session.directory in SQLite
  4. Updates the project JSON in OpenCode's storage
  5. Verifies all changes

After relocation, restart OpenCode from the new path:

cd~/Projects/my-app-v2 && opencode

move-sessions — Reassign sessions between projects

opencode-relocate move-sessions <source-path><target-path> [options]

Move sessions from one OpenCode project to another. Both projects must already exist in OpenCode (opened at least once).

The source can be a non-git directory — in that case, sessions are stored under the global project and are filtered by directory prefix so only sessions matching the source path are shown.

Three modes:

# Interactive (default) — checkbox-style session selector
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b
# List only — inspect sessions without moving
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b --list
# Scripted — provide session IDs directly
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b \
--session-ids "ses_abc123,ses_def456"

Interactive selector controls:

KeyAction
/ (or k / j)Navigate up / down
SpaceToggle current session
aToggle all sessions
EnterConfirm selection
q / EscCancel

The selector shows [x] / [ ] checkboxes, highlights the current row, scrolls automatically for long lists, and displays a live count of selected sessions.

Child/subagent sessions are moved automatically with their parent.


split-project — Create a new project from sessions

opencode-relocate split-project <source-path><target-path> [options]

Like move-sessions, but the target doesn't need to exist as an OpenCode project. If the target directory has never been opened in OpenCode, a new project entry is created automatically.

If the target directory doesn't exist, split-project will prompt you to create it (mkdir -p). If it's not a git repository (or has no commits), you'll be prompted to initialize it (git init + initial empty commit). The source can be either a git-backed project or a non-git directory (global project — sessions are filtered by directory prefix).

# Interactive (checkbox selector)
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service
# Split sessions from a non-git directory into a git-backed project
opencode-relocate split-project ~/Projects/sandbox ~/Projects/new-repo
# List only
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service --list
# Scripted
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service \
--session-ids "ses_abc123,ses_def456"

Same interactive controls as move-sessions (arrow keys, Space, Enter).

When to use split-project vs move-sessions:

ScenarioCommand
Target project already exists in OpenCodeEither works
Target directory was never opened in OpenCodesplit-project
Source is a non-git directory (global project)Either works (filtered by directory)
Target directory is not a git reposplit-project (will offer to git init)

relink — Re-link a project after its initial commit changed

opencode-relocate relink <path> [options]

OpenCode identifies a project by the hash of its first root commit (git rev-list --max-parents=0 HEAD). If you reset or recreate the initial commit — e.g. squashing history, git update-ref -d HEAD, or rebuilding the repo — that hash changes, and OpenCode treats the repo as a brand-new project. All previous sessions become orphaned.

relink migrates the existing project from the old ID to the new root-commit-derived ID: sessions, workspaces, permissions, on-disk JSON artifacts, and the .git/opencode cache file.

# Auto-detect old and new IDs and relink
opencode-relocate relink ~/Projects/my-app
# Preview changes without writing anything
opencode-relocate relink ~/Projects/my-app --dry-run
# Specify IDs explicitly
opencode-relocate relink ~/Projects/my-app \
--old-id eca18ff587da0906289bd984d8b0fd7622b69604 \
--new-id b761b3048a1c1129822fcfaaf9252db49dace055

Auto-detection:

  • New ID is derived from the repo's current root commit hash.
  • Old ID is found by looking up the project whose worktree matches <path> but whose ID differs from the new ID, falling back to the cached value in .git/opencode.

Merge behavior: If a project row for the new ID already exists (e.g. you reopened OpenCode after the reset, so it created a fresh project), the old sessions are merged into it. Otherwise a new project row is created as a copy of the old one.

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Re-points session, workspace, and permission rows to the new ID
  3. Creates or merges into the new project row, then deletes the old one
  4. Migrates storage/project/<id>.json and storage/session/<id>/ artifacts
  5. Updates the .git/opencode cache to the new ID
  6. Verifies the migration

Sessions keep their existing directory — only the project ID changes. Use --dry-run first if you want to preview the exact changes.

Safety

Automatic backups

Every command backs up opencode.db (plus WAL/SHM files) before making changes. Backups are timestamped:

~/.local/share/opencode/opencode.db.20260408_143022.bak

Interactive confirmation

All destructive operations require [y/N] confirmation before proceeding.

What's preserved

  • All session content: messages, tool calls, parts, todos
  • Session metadata: titles, timestamps, summaries
  • Parent-child session relationships (subagent sessions move with their parent)

What's NOT preserved

  • Undo/redo snapshots — stored per-project, not per-session

Recovery

Restore from backup:

cp ~/.local/share/opencode/opencode.db.20260408_143022.bak \
~/.local/share/opencode/opencode.db

Limitations

  • After relocate, the current OpenCode session breaks (restart required).
  • move-sessions requires the target to already exist as an OpenCode project.
  • Undo/redo snapshots are not moved.
  • Clones of the same repository share the same project ID (same root commit), so you cannot move sessions between clones of the same repo.
  • The global project cannot be used as a target — only as a source (sessions are filtered by directory prefix).
  • relink derives the new project ID from git rev-list --max-parents=0 HEAD and updates the .git/opencode cache; the repo must have at least one commit.

Disclaimer

This is an independent, community-built tool. It is not built by the OpenCode team and is not affiliated with OpenCode in any way. The "opencode" in the name refers only to the tool's purpose of managing OpenCode session data.

About

Bash CLI to move, relink, and reorganize OpenCode projects and sessions directly in its SQLite database.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

opencode-relocate-cli

A standalone CLI tool for managing OpenCode session locations, no LLM required. Runs as a plain Bash script, directly manipulating the OpenCode SQLite database. No OpenCode session, no Bun runtime, and no LLM round-trips needed.

Quick Reference

CommandWhat it doesWhen to use it
opencode-relocate relocateMoves the project directory and updates all referencesYou moved or renamed a repo on disk
opencode-relocate move-sessionsReassigns selected sessions to another projectSessions were started in the wrong project
opencode-relocate split-projectCreates a new project and moves sessions into itYou split a repo or want to reorganize history
opencode-relocate relinkRe-links a project after its initial commit was recreatedYou reset/recreated the root commit and lost session history

Installation

Option 1: Symlink to PATH

ln -s "$(pwd)/opencode-relocate" /usr/local/bin/opencode-relocate

Option 2: Copy to PATH

cp opencode-relocate /usr/local/bin/opencode-relocate
chmod +x /usr/local/bin/opencode-relocate

Option 3: Run directly

./opencode-relocate <command> [args...]

Requirements

  • sqlite3 — pre-installed on macOS and most Linux distributions
  • git — required for split-project and relink (derives project IDs from root commits)
  • jq — optional; used for JSON updates when available, falls back to sed

Commands

relocate — Move a project to a new path

opencode-relocate relocate <old-path><new-path>

Moves the project directory and updates all internal OpenCode references (SQLite database and project JSON file).

# Example: rename a project directory
opencode-relocate relocate ~/Projects/my-app ~/Projects/my-app-v2

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Moves the directory with mv
  3. Updates project.worktree and session.directory in SQLite
  4. Updates the project JSON in OpenCode's storage
  5. Verifies all changes

After relocation, restart OpenCode from the new path:

cd~/Projects/my-app-v2 && opencode

move-sessions — Reassign sessions between projects

opencode-relocate move-sessions <source-path><target-path> [options]

Move sessions from one OpenCode project to another. Both projects must already exist in OpenCode (opened at least once).

The source can be a non-git directory — in that case, sessions are stored under the global project and are filtered by directory prefix so only sessions matching the source path are shown.

Three modes:

# Interactive (default) — checkbox-style session selector
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b
# List only — inspect sessions without moving
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b --list
# Scripted — provide session IDs directly
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b \
--session-ids "ses_abc123,ses_def456"

Interactive selector controls:

KeyAction
/ (or k / j)Navigate up / down
SpaceToggle current session
aToggle all sessions
EnterConfirm selection
q / EscCancel

The selector shows [x] / [ ] checkboxes, highlights the current row, scrolls automatically for long lists, and displays a live count of selected sessions.

Child/subagent sessions are moved automatically with their parent.


split-project — Create a new project from sessions

opencode-relocate split-project <source-path><target-path> [options]

Like move-sessions, but the target doesn't need to exist as an OpenCode project. If the target directory has never been opened in OpenCode, a new project entry is created automatically.

If the target directory doesn't exist, split-project will prompt you to create it (mkdir -p). If it's not a git repository (or has no commits), you'll be prompted to initialize it (git init + initial empty commit). The source can be either a git-backed project or a non-git directory (global project — sessions are filtered by directory prefix).

# Interactive (checkbox selector)
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service
# Split sessions from a non-git directory into a git-backed project
opencode-relocate split-project ~/Projects/sandbox ~/Projects/new-repo
# List only
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service --list
# Scripted
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service \
--session-ids "ses_abc123,ses_def456"

Same interactive controls as move-sessions (arrow keys, Space, Enter).

When to use split-project vs move-sessions:

ScenarioCommand
Target project already exists in OpenCodeEither works
Target directory was never opened in OpenCodesplit-project
Source is a non-git directory (global project)Either works (filtered by directory)
Target directory is not a git reposplit-project (will offer to git init)

relink — Re-link a project after its initial commit changed

opencode-relocate relink <path> [options]

OpenCode identifies a project by the hash of its first root commit (git rev-list --max-parents=0 HEAD). If you reset or recreate the initial commit — e.g. squashing history, git update-ref -d HEAD, or rebuilding the repo — that hash changes, and OpenCode treats the repo as a brand-new project. All previous sessions become orphaned.

relink migrates the existing project from the old ID to the new root-commit-derived ID: sessions, workspaces, permissions, on-disk JSON artifacts, and the .git/opencode cache file.

# Auto-detect old and new IDs and relink
opencode-relocate relink ~/Projects/my-app
# Preview changes without writing anything
opencode-relocate relink ~/Projects/my-app --dry-run
# Specify IDs explicitly
opencode-relocate relink ~/Projects/my-app \
--old-id eca18ff587da0906289bd984d8b0fd7622b69604 \
--new-id b761b3048a1c1129822fcfaaf9252db49dace055

Auto-detection:

  • New ID is derived from the repo's current root commit hash.
  • Old ID is found by looking up the project whose worktree matches <path> but whose ID differs from the new ID, falling back to the cached value in .git/opencode.

Merge behavior: If a project row for the new ID already exists (e.g. you reopened OpenCode after the reset, so it created a fresh project), the old sessions are merged into it. Otherwise a new project row is created as a copy of the old one.

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Re-points session, workspace, and permission rows to the new ID
  3. Creates or merges into the new project row, then deletes the old one
  4. Migrates storage/project/<id>.json and storage/session/<id>/ artifacts
  5. Updates the .git/opencode cache to the new ID
  6. Verifies the migration

Sessions keep their existing directory — only the project ID changes. Use --dry-run first if you want to preview the exact changes.

Safety

Automatic backups

Every command backs up opencode.db (plus WAL/SHM files) before making changes. Backups are timestamped:

~/.local/share/opencode/opencode.db.20260408_143022.bak

Interactive confirmation

All destructive operations require [y/N] confirmation before proceeding.

What's preserved

  • All session content: messages, tool calls, parts, todos
  • Session metadata: titles, timestamps, summaries
  • Parent-child session relationships (subagent sessions move with their parent)

What's NOT preserved

  • Undo/redo snapshots — stored per-project, not per-session

Recovery

Restore from backup:

cp ~/.local/share/opencode/opencode.db.20260408_143022.bak \
~/.local/share/opencode/opencode.db

Limitations

  • After relocate, the current OpenCode session breaks (restart required).
  • move-sessions requires the target to already exist as an OpenCode project.
  • Undo/redo snapshots are not moved.
  • Clones of the same repository share the same project ID (same root commit), so you cannot move sessions between clones of the same repo.
  • The global project cannot be used as a target — only as a source (sessions are filtered by directory prefix).
  • relink derives the new project ID from git rev-list --max-parents=0 HEAD and updates the .git/opencode cache; the repo must have at least one commit.

Disclaimer

This is an independent, community-built tool. It is not built by the OpenCode team and is not affiliated with OpenCode in any way. The "opencode" in the name refers only to the tool's purpose of managing OpenCode session data.

About

Bash CLI to move, relink, and reorganize OpenCode projects and sessions directly in its SQLite database.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

opencode-relocate-cli

A standalone CLI tool for managing OpenCode session locations, no LLM required. Runs as a plain Bash script, directly manipulating the OpenCode SQLite database. No OpenCode session, no Bun runtime, and no LLM round-trips needed.

Quick Reference

CommandWhat it doesWhen to use it
opencode-relocate relocateMoves the project directory and updates all referencesYou moved or renamed a repo on disk
opencode-relocate move-sessionsReassigns selected sessions to another projectSessions were started in the wrong project
opencode-relocate split-projectCreates a new project and moves sessions into itYou split a repo or want to reorganize history
opencode-relocate relinkRe-links a project after its initial commit was recreatedYou reset/recreated the root commit and lost session history

Installation

Option 1: Symlink to PATH

ln -s "$(pwd)/opencode-relocate" /usr/local/bin/opencode-relocate

Option 2: Copy to PATH

cp opencode-relocate /usr/local/bin/opencode-relocate
chmod +x /usr/local/bin/opencode-relocate

Option 3: Run directly

./opencode-relocate <command> [args...]

Requirements

  • sqlite3 — pre-installed on macOS and most Linux distributions
  • git — required for split-project and relink (derives project IDs from root commits)
  • jq — optional; used for JSON updates when available, falls back to sed

Commands

relocate — Move a project to a new path

opencode-relocate relocate <old-path><new-path>

Moves the project directory and updates all internal OpenCode references (SQLite database and project JSON file).

# Example: rename a project directory
opencode-relocate relocate ~/Projects/my-app ~/Projects/my-app-v2

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Moves the directory with mv
  3. Updates project.worktree and session.directory in SQLite
  4. Updates the project JSON in OpenCode's storage
  5. Verifies all changes

After relocation, restart OpenCode from the new path:

cd~/Projects/my-app-v2 && opencode

move-sessions — Reassign sessions between projects

opencode-relocate move-sessions <source-path><target-path> [options]

Move sessions from one OpenCode project to another. Both projects must already exist in OpenCode (opened at least once).

The source can be a non-git directory — in that case, sessions are stored under the global project and are filtered by directory prefix so only sessions matching the source path are shown.

Three modes:

# Interactive (default) — checkbox-style session selector
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b
# List only — inspect sessions without moving
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b --list
# Scripted — provide session IDs directly
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b \
--session-ids "ses_abc123,ses_def456"

Interactive selector controls:

KeyAction
/ (or k / j)Navigate up / down
SpaceToggle current session
aToggle all sessions
EnterConfirm selection
q / EscCancel

The selector shows [x] / [ ] checkboxes, highlights the current row, scrolls automatically for long lists, and displays a live count of selected sessions.

Child/subagent sessions are moved automatically with their parent.


split-project — Create a new project from sessions

opencode-relocate split-project <source-path><target-path> [options]

Like move-sessions, but the target doesn't need to exist as an OpenCode project. If the target directory has never been opened in OpenCode, a new project entry is created automatically.

If the target directory doesn't exist, split-project will prompt you to create it (mkdir -p). If it's not a git repository (or has no commits), you'll be prompted to initialize it (git init + initial empty commit). The source can be either a git-backed project or a non-git directory (global project — sessions are filtered by directory prefix).

# Interactive (checkbox selector)
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service
# Split sessions from a non-git directory into a git-backed project
opencode-relocate split-project ~/Projects/sandbox ~/Projects/new-repo
# List only
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service --list
# Scripted
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service \
--session-ids "ses_abc123,ses_def456"

Same interactive controls as move-sessions (arrow keys, Space, Enter).

When to use split-project vs move-sessions:

ScenarioCommand
Target project already exists in OpenCodeEither works
Target directory was never opened in OpenCodesplit-project
Source is a non-git directory (global project)Either works (filtered by directory)
Target directory is not a git reposplit-project (will offer to git init)

relink — Re-link a project after its initial commit changed

opencode-relocate relink <path> [options]

OpenCode identifies a project by the hash of its first root commit (git rev-list --max-parents=0 HEAD). If you reset or recreate the initial commit — e.g. squashing history, git update-ref -d HEAD, or rebuilding the repo — that hash changes, and OpenCode treats the repo as a brand-new project. All previous sessions become orphaned.

relink migrates the existing project from the old ID to the new root-commit-derived ID: sessions, workspaces, permissions, on-disk JSON artifacts, and the .git/opencode cache file.

# Auto-detect old and new IDs and relink
opencode-relocate relink ~/Projects/my-app
# Preview changes without writing anything
opencode-relocate relink ~/Projects/my-app --dry-run
# Specify IDs explicitly
opencode-relocate relink ~/Projects/my-app \
--old-id eca18ff587da0906289bd984d8b0fd7622b69604 \
--new-id b761b3048a1c1129822fcfaaf9252db49dace055

Auto-detection:

  • New ID is derived from the repo's current root commit hash.
  • Old ID is found by looking up the project whose worktree matches <path> but whose ID differs from the new ID, falling back to the cached value in .git/opencode.

Merge behavior: If a project row for the new ID already exists (e.g. you reopened OpenCode after the reset, so it created a fresh project), the old sessions are merged into it. Otherwise a new project row is created as a copy of the old one.

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Re-points session, workspace, and permission rows to the new ID
  3. Creates or merges into the new project row, then deletes the old one
  4. Migrates storage/project/<id>.json and storage/session/<id>/ artifacts
  5. Updates the .git/opencode cache to the new ID
  6. Verifies the migration

Sessions keep their existing directory — only the project ID changes. Use --dry-run first if you want to preview the exact changes.

Safety

Automatic backups

Every command backs up opencode.db (plus WAL/SHM files) before making changes. Backups are timestamped:

~/.local/share/opencode/opencode.db.20260408_143022.bak

Interactive confirmation

All destructive operations require [y/N] confirmation before proceeding.

What's preserved

  • All session content: messages, tool calls, parts, todos
  • Session metadata: titles, timestamps, summaries
  • Parent-child session relationships (subagent sessions move with their parent)

What's NOT preserved

  • Undo/redo snapshots — stored per-project, not per-session

Recovery

Restore from backup:

cp ~/.local/share/opencode/opencode.db.20260408_143022.bak \
~/.local/share/opencode/opencode.db

Limitations

  • After relocate, the current OpenCode session breaks (restart required).
  • move-sessions requires the target to already exist as an OpenCode project.
  • Undo/redo snapshots are not moved.
  • Clones of the same repository share the same project ID (same root commit), so you cannot move sessions between clones of the same repo.
  • The global project cannot be used as a target — only as a source (sessions are filtered by directory prefix).
  • relink derives the new project ID from git rev-list --max-parents=0 HEAD and updates the .git/opencode cache; the repo must have at least one commit.

Disclaimer

This is an independent, community-built tool. It is not built by the OpenCode team and is not affiliated with OpenCode in any way. The "opencode" in the name refers only to the tool's purpose of managing OpenCode session data.

About

Bash CLI to move, relink, and reorganize OpenCode projects and sessions directly in its SQLite database.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

opencode-relocate-cli

A standalone CLI tool for managing OpenCode session locations, no LLM required. Runs as a plain Bash script, directly manipulating the OpenCode SQLite database. No OpenCode session, no Bun runtime, and no LLM round-trips needed.

Quick Reference

CommandWhat it doesWhen to use it
opencode-relocate relocateMoves the project directory and updates all referencesYou moved or renamed a repo on disk
opencode-relocate move-sessionsReassigns selected sessions to another projectSessions were started in the wrong project
opencode-relocate split-projectCreates a new project and moves sessions into itYou split a repo or want to reorganize history
opencode-relocate relinkRe-links a project after its initial commit was recreatedYou reset/recreated the root commit and lost session history

Installation

Option 1: Symlink to PATH

ln -s "$(pwd)/opencode-relocate" /usr/local/bin/opencode-relocate

Option 2: Copy to PATH

cp opencode-relocate /usr/local/bin/opencode-relocate
chmod +x /usr/local/bin/opencode-relocate

Option 3: Run directly

./opencode-relocate <command> [args...]

Requirements

  • sqlite3 — pre-installed on macOS and most Linux distributions
  • git — required for split-project and relink (derives project IDs from root commits)
  • jq — optional; used for JSON updates when available, falls back to sed

Commands

relocate — Move a project to a new path

opencode-relocate relocate <old-path><new-path>

Moves the project directory and updates all internal OpenCode references (SQLite database and project JSON file).

# Example: rename a project directory
opencode-relocate relocate ~/Projects/my-app ~/Projects/my-app-v2

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Moves the directory with mv
  3. Updates project.worktree and session.directory in SQLite
  4. Updates the project JSON in OpenCode's storage
  5. Verifies all changes

After relocation, restart OpenCode from the new path:

cd~/Projects/my-app-v2 && opencode

move-sessions — Reassign sessions between projects

opencode-relocate move-sessions <source-path><target-path> [options]

Move sessions from one OpenCode project to another. Both projects must already exist in OpenCode (opened at least once).

The source can be a non-git directory — in that case, sessions are stored under the global project and are filtered by directory prefix so only sessions matching the source path are shown.

Three modes:

# Interactive (default) — checkbox-style session selector
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b
# List only — inspect sessions without moving
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b --list
# Scripted — provide session IDs directly
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b \
--session-ids "ses_abc123,ses_def456"

Interactive selector controls:

KeyAction
/ (or k / j)Navigate up / down
SpaceToggle current session
aToggle all sessions
EnterConfirm selection
q / EscCancel

The selector shows [x] / [ ] checkboxes, highlights the current row, scrolls automatically for long lists, and displays a live count of selected sessions.

Child/subagent sessions are moved automatically with their parent.


split-project — Create a new project from sessions

opencode-relocate split-project <source-path><target-path> [options]

Like move-sessions, but the target doesn't need to exist as an OpenCode project. If the target directory has never been opened in OpenCode, a new project entry is created automatically.

If the target directory doesn't exist, split-project will prompt you to create it (mkdir -p). If it's not a git repository (or has no commits), you'll be prompted to initialize it (git init + initial empty commit). The source can be either a git-backed project or a non-git directory (global project — sessions are filtered by directory prefix).

# Interactive (checkbox selector)
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service
# Split sessions from a non-git directory into a git-backed project
opencode-relocate split-project ~/Projects/sandbox ~/Projects/new-repo
# List only
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service --list
# Scripted
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service \
--session-ids "ses_abc123,ses_def456"

Same interactive controls as move-sessions (arrow keys, Space, Enter).

When to use split-project vs move-sessions:

ScenarioCommand
Target project already exists in OpenCodeEither works
Target directory was never opened in OpenCodesplit-project
Source is a non-git directory (global project)Either works (filtered by directory)
Target directory is not a git reposplit-project (will offer to git init)

relink — Re-link a project after its initial commit changed

opencode-relocate relink <path> [options]

OpenCode identifies a project by the hash of its first root commit (git rev-list --max-parents=0 HEAD). If you reset or recreate the initial commit — e.g. squashing history, git update-ref -d HEAD, or rebuilding the repo — that hash changes, and OpenCode treats the repo as a brand-new project. All previous sessions become orphaned.

relink migrates the existing project from the old ID to the new root-commit-derived ID: sessions, workspaces, permissions, on-disk JSON artifacts, and the .git/opencode cache file.

# Auto-detect old and new IDs and relink
opencode-relocate relink ~/Projects/my-app
# Preview changes without writing anything
opencode-relocate relink ~/Projects/my-app --dry-run
# Specify IDs explicitly
opencode-relocate relink ~/Projects/my-app \
--old-id eca18ff587da0906289bd984d8b0fd7622b69604 \
--new-id b761b3048a1c1129822fcfaaf9252db49dace055

Auto-detection:

  • New ID is derived from the repo's current root commit hash.
  • Old ID is found by looking up the project whose worktree matches <path> but whose ID differs from the new ID, falling back to the cached value in .git/opencode.

Merge behavior: If a project row for the new ID already exists (e.g. you reopened OpenCode after the reset, so it created a fresh project), the old sessions are merged into it. Otherwise a new project row is created as a copy of the old one.

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Re-points session, workspace, and permission rows to the new ID
  3. Creates or merges into the new project row, then deletes the old one
  4. Migrates storage/project/<id>.json and storage/session/<id>/ artifacts
  5. Updates the .git/opencode cache to the new ID
  6. Verifies the migration

Sessions keep their existing directory — only the project ID changes. Use --dry-run first if you want to preview the exact changes.

Safety

Automatic backups

Every command backs up opencode.db (plus WAL/SHM files) before making changes. Backups are timestamped:

~/.local/share/opencode/opencode.db.20260408_143022.bak

Interactive confirmation

All destructive operations require [y/N] confirmation before proceeding.

What's preserved

  • All session content: messages, tool calls, parts, todos
  • Session metadata: titles, timestamps, summaries
  • Parent-child session relationships (subagent sessions move with their parent)

What's NOT preserved

  • Undo/redo snapshots — stored per-project, not per-session

Recovery

Restore from backup:

cp ~/.local/share/opencode/opencode.db.20260408_143022.bak \
~/.local/share/opencode/opencode.db

Limitations

  • After relocate, the current OpenCode session breaks (restart required).
  • move-sessions requires the target to already exist as an OpenCode project.
  • Undo/redo snapshots are not moved.
  • Clones of the same repository share the same project ID (same root commit), so you cannot move sessions between clones of the same repo.
  • The global project cannot be used as a target — only as a source (sessions are filtered by directory prefix).
  • relink derives the new project ID from git rev-list --max-parents=0 HEAD and updates the .git/opencode cache; the repo must have at least one commit.

Disclaimer

This is an independent, community-built tool. It is not built by the OpenCode team and is not affiliated with OpenCode in any way. The "opencode" in the name refers only to the tool's purpose of managing OpenCode session data.

About

Bash CLI to move, relink, and reorganize OpenCode projects and sessions directly in its SQLite database.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

opencode-relocate-cli

A standalone CLI tool for managing OpenCode session locations, no LLM required. Runs as a plain Bash script, directly manipulating the OpenCode SQLite database. No OpenCode session, no Bun runtime, and no LLM round-trips needed.

Quick Reference

CommandWhat it doesWhen to use it
opencode-relocate relocateMoves the project directory and updates all referencesYou moved or renamed a repo on disk
opencode-relocate move-sessionsReassigns selected sessions to another projectSessions were started in the wrong project
opencode-relocate split-projectCreates a new project and moves sessions into itYou split a repo or want to reorganize history
opencode-relocate relinkRe-links a project after its initial commit was recreatedYou reset/recreated the root commit and lost session history

Installation

Option 1: Symlink to PATH

ln -s "$(pwd)/opencode-relocate" /usr/local/bin/opencode-relocate

Option 2: Copy to PATH

cp opencode-relocate /usr/local/bin/opencode-relocate
chmod +x /usr/local/bin/opencode-relocate

Option 3: Run directly

./opencode-relocate <command> [args...]

Requirements

  • sqlite3 — pre-installed on macOS and most Linux distributions
  • git — required for split-project and relink (derives project IDs from root commits)
  • jq — optional; used for JSON updates when available, falls back to sed

Commands

relocate — Move a project to a new path

opencode-relocate relocate <old-path><new-path>

Moves the project directory and updates all internal OpenCode references (SQLite database and project JSON file).

# Example: rename a project directory
opencode-relocate relocate ~/Projects/my-app ~/Projects/my-app-v2

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Moves the directory with mv
  3. Updates project.worktree and session.directory in SQLite
  4. Updates the project JSON in OpenCode's storage
  5. Verifies all changes

After relocation, restart OpenCode from the new path:

cd~/Projects/my-app-v2 && opencode

move-sessions — Reassign sessions between projects

opencode-relocate move-sessions <source-path><target-path> [options]

Move sessions from one OpenCode project to another. Both projects must already exist in OpenCode (opened at least once).

The source can be a non-git directory — in that case, sessions are stored under the global project and are filtered by directory prefix so only sessions matching the source path are shown.

Three modes:

# Interactive (default) — checkbox-style session selector
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b
# List only — inspect sessions without moving
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b --list
# Scripted — provide session IDs directly
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b \
--session-ids "ses_abc123,ses_def456"

Interactive selector controls:

KeyAction
/ (or k / j)Navigate up / down
SpaceToggle current session
aToggle all sessions
EnterConfirm selection
q / EscCancel

The selector shows [x] / [ ] checkboxes, highlights the current row, scrolls automatically for long lists, and displays a live count of selected sessions.

Child/subagent sessions are moved automatically with their parent.


split-project — Create a new project from sessions

opencode-relocate split-project <source-path><target-path> [options]

Like move-sessions, but the target doesn't need to exist as an OpenCode project. If the target directory has never been opened in OpenCode, a new project entry is created automatically.

If the target directory doesn't exist, split-project will prompt you to create it (mkdir -p). If it's not a git repository (or has no commits), you'll be prompted to initialize it (git init + initial empty commit). The source can be either a git-backed project or a non-git directory (global project — sessions are filtered by directory prefix).

# Interactive (checkbox selector)
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service
# Split sessions from a non-git directory into a git-backed project
opencode-relocate split-project ~/Projects/sandbox ~/Projects/new-repo
# List only
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service --list
# Scripted
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service \
--session-ids "ses_abc123,ses_def456"

Same interactive controls as move-sessions (arrow keys, Space, Enter).

When to use split-project vs move-sessions:

ScenarioCommand
Target project already exists in OpenCodeEither works
Target directory was never opened in OpenCodesplit-project
Source is a non-git directory (global project)Either works (filtered by directory)
Target directory is not a git reposplit-project (will offer to git init)

relink — Re-link a project after its initial commit changed

opencode-relocate relink <path> [options]

OpenCode identifies a project by the hash of its first root commit (git rev-list --max-parents=0 HEAD). If you reset or recreate the initial commit — e.g. squashing history, git update-ref -d HEAD, or rebuilding the repo — that hash changes, and OpenCode treats the repo as a brand-new project. All previous sessions become orphaned.

relink migrates the existing project from the old ID to the new root-commit-derived ID: sessions, workspaces, permissions, on-disk JSON artifacts, and the .git/opencode cache file.

# Auto-detect old and new IDs and relink
opencode-relocate relink ~/Projects/my-app
# Preview changes without writing anything
opencode-relocate relink ~/Projects/my-app --dry-run
# Specify IDs explicitly
opencode-relocate relink ~/Projects/my-app \
--old-id eca18ff587da0906289bd984d8b0fd7622b69604 \
--new-id b761b3048a1c1129822fcfaaf9252db49dace055

Auto-detection:

  • New ID is derived from the repo's current root commit hash.
  • Old ID is found by looking up the project whose worktree matches <path> but whose ID differs from the new ID, falling back to the cached value in .git/opencode.

Merge behavior: If a project row for the new ID already exists (e.g. you reopened OpenCode after the reset, so it created a fresh project), the old sessions are merged into it. Otherwise a new project row is created as a copy of the old one.

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Re-points session, workspace, and permission rows to the new ID
  3. Creates or merges into the new project row, then deletes the old one
  4. Migrates storage/project/<id>.json and storage/session/<id>/ artifacts
  5. Updates the .git/opencode cache to the new ID
  6. Verifies the migration

Sessions keep their existing directory — only the project ID changes. Use --dry-run first if you want to preview the exact changes.

Safety

Automatic backups

Every command backs up opencode.db (plus WAL/SHM files) before making changes. Backups are timestamped:

~/.local/share/opencode/opencode.db.20260408_143022.bak

Interactive confirmation

All destructive operations require [y/N] confirmation before proceeding.

What's preserved

  • All session content: messages, tool calls, parts, todos
  • Session metadata: titles, timestamps, summaries
  • Parent-child session relationships (subagent sessions move with their parent)

What's NOT preserved

  • Undo/redo snapshots — stored per-project, not per-session

Recovery

Restore from backup:

cp ~/.local/share/opencode/opencode.db.20260408_143022.bak \
~/.local/share/opencode/opencode.db

Limitations

  • After relocate, the current OpenCode session breaks (restart required).
  • move-sessions requires the target to already exist as an OpenCode project.
  • Undo/redo snapshots are not moved.
  • Clones of the same repository share the same project ID (same root commit), so you cannot move sessions between clones of the same repo.
  • The global project cannot be used as a target — only as a source (sessions are filtered by directory prefix).
  • relink derives the new project ID from git rev-list --max-parents=0 HEAD and updates the .git/opencode cache; the repo must have at least one commit.

Disclaimer

This is an independent, community-built tool. It is not built by the OpenCode team and is not affiliated with OpenCode in any way. The "opencode" in the name refers only to the tool's purpose of managing OpenCode session data.

About

Bash CLI to move, relink, and reorganize OpenCode projects and sessions directly in its SQLite database.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

opencode-relocate-cli

A standalone CLI tool for managing OpenCode session locations, no LLM required. Runs as a plain Bash script, directly manipulating the OpenCode SQLite database. No OpenCode session, no Bun runtime, and no LLM round-trips needed.

Quick Reference

CommandWhat it doesWhen to use it
opencode-relocate relocateMoves the project directory and updates all referencesYou moved or renamed a repo on disk
opencode-relocate move-sessionsReassigns selected sessions to another projectSessions were started in the wrong project
opencode-relocate split-projectCreates a new project and moves sessions into itYou split a repo or want to reorganize history
opencode-relocate relinkRe-links a project after its initial commit was recreatedYou reset/recreated the root commit and lost session history

Installation

Option 1: Symlink to PATH

ln -s "$(pwd)/opencode-relocate" /usr/local/bin/opencode-relocate

Option 2: Copy to PATH

cp opencode-relocate /usr/local/bin/opencode-relocate
chmod +x /usr/local/bin/opencode-relocate

Option 3: Run directly

./opencode-relocate <command> [args...]

Requirements

  • sqlite3 — pre-installed on macOS and most Linux distributions
  • git — required for split-project and relink (derives project IDs from root commits)
  • jq — optional; used for JSON updates when available, falls back to sed

Commands

relocate — Move a project to a new path

opencode-relocate relocate <old-path><new-path>

Moves the project directory and updates all internal OpenCode references (SQLite database and project JSON file).

# Example: rename a project directory
opencode-relocate relocate ~/Projects/my-app ~/Projects/my-app-v2

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Moves the directory with mv
  3. Updates project.worktree and session.directory in SQLite
  4. Updates the project JSON in OpenCode's storage
  5. Verifies all changes

After relocation, restart OpenCode from the new path:

cd~/Projects/my-app-v2 && opencode

move-sessions — Reassign sessions between projects

opencode-relocate move-sessions <source-path><target-path> [options]

Move sessions from one OpenCode project to another. Both projects must already exist in OpenCode (opened at least once).

The source can be a non-git directory — in that case, sessions are stored under the global project and are filtered by directory prefix so only sessions matching the source path are shown.

Three modes:

# Interactive (default) — checkbox-style session selector
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b
# List only — inspect sessions without moving
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b --list
# Scripted — provide session IDs directly
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b \
--session-ids "ses_abc123,ses_def456"

Interactive selector controls:

KeyAction
/ (or k / j)Navigate up / down
SpaceToggle current session
aToggle all sessions
EnterConfirm selection
q / EscCancel

The selector shows [x] / [ ] checkboxes, highlights the current row, scrolls automatically for long lists, and displays a live count of selected sessions.

Child/subagent sessions are moved automatically with their parent.


split-project — Create a new project from sessions

opencode-relocate split-project <source-path><target-path> [options]

Like move-sessions, but the target doesn't need to exist as an OpenCode project. If the target directory has never been opened in OpenCode, a new project entry is created automatically.

If the target directory doesn't exist, split-project will prompt you to create it (mkdir -p). If it's not a git repository (or has no commits), you'll be prompted to initialize it (git init + initial empty commit). The source can be either a git-backed project or a non-git directory (global project — sessions are filtered by directory prefix).

# Interactive (checkbox selector)
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service
# Split sessions from a non-git directory into a git-backed project
opencode-relocate split-project ~/Projects/sandbox ~/Projects/new-repo
# List only
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service --list
# Scripted
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service \
--session-ids "ses_abc123,ses_def456"

Same interactive controls as move-sessions (arrow keys, Space, Enter).

When to use split-project vs move-sessions:

ScenarioCommand
Target project already exists in OpenCodeEither works
Target directory was never opened in OpenCodesplit-project
Source is a non-git directory (global project)Either works (filtered by directory)
Target directory is not a git reposplit-project (will offer to git init)

relink — Re-link a project after its initial commit changed

opencode-relocate relink <path> [options]

OpenCode identifies a project by the hash of its first root commit (git rev-list --max-parents=0 HEAD). If you reset or recreate the initial commit — e.g. squashing history, git update-ref -d HEAD, or rebuilding the repo — that hash changes, and OpenCode treats the repo as a brand-new project. All previous sessions become orphaned.

relink migrates the existing project from the old ID to the new root-commit-derived ID: sessions, workspaces, permissions, on-disk JSON artifacts, and the .git/opencode cache file.

# Auto-detect old and new IDs and relink
opencode-relocate relink ~/Projects/my-app
# Preview changes without writing anything
opencode-relocate relink ~/Projects/my-app --dry-run
# Specify IDs explicitly
opencode-relocate relink ~/Projects/my-app \
--old-id eca18ff587da0906289bd984d8b0fd7622b69604 \
--new-id b761b3048a1c1129822fcfaaf9252db49dace055

Auto-detection:

  • New ID is derived from the repo's current root commit hash.
  • Old ID is found by looking up the project whose worktree matches <path> but whose ID differs from the new ID, falling back to the cached value in .git/opencode.

Merge behavior: If a project row for the new ID already exists (e.g. you reopened OpenCode after the reset, so it created a fresh project), the old sessions are merged into it. Otherwise a new project row is created as a copy of the old one.

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Re-points session, workspace, and permission rows to the new ID
  3. Creates or merges into the new project row, then deletes the old one
  4. Migrates storage/project/<id>.json and storage/session/<id>/ artifacts
  5. Updates the .git/opencode cache to the new ID
  6. Verifies the migration

Sessions keep their existing directory — only the project ID changes. Use --dry-run first if you want to preview the exact changes.

Safety

Automatic backups

Every command backs up opencode.db (plus WAL/SHM files) before making changes. Backups are timestamped:

~/.local/share/opencode/opencode.db.20260408_143022.bak

Interactive confirmation

All destructive operations require [y/N] confirmation before proceeding.

What's preserved

  • All session content: messages, tool calls, parts, todos
  • Session metadata: titles, timestamps, summaries
  • Parent-child session relationships (subagent sessions move with their parent)

What's NOT preserved

  • Undo/redo snapshots — stored per-project, not per-session

Recovery

Restore from backup:

cp ~/.local/share/opencode/opencode.db.20260408_143022.bak \
~/.local/share/opencode/opencode.db

Limitations

  • After relocate, the current OpenCode session breaks (restart required).
  • move-sessions requires the target to already exist as an OpenCode project.
  • Undo/redo snapshots are not moved.
  • Clones of the same repository share the same project ID (same root commit), so you cannot move sessions between clones of the same repo.
  • The global project cannot be used as a target — only as a source (sessions are filtered by directory prefix).
  • relink derives the new project ID from git rev-list --max-parents=0 HEAD and updates the .git/opencode cache; the repo must have at least one commit.

Disclaimer

This is an independent, community-built tool. It is not built by the OpenCode team and is not affiliated with OpenCode in any way. The "opencode" in the name refers only to the tool's purpose of managing OpenCode session data.

About

Bash CLI to move, relink, and reorganize OpenCode projects and sessions directly in its SQLite database.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

opencode-relocate-cli

A standalone CLI tool for managing OpenCode session locations, no LLM required. Runs as a plain Bash script, directly manipulating the OpenCode SQLite database. No OpenCode session, no Bun runtime, and no LLM round-trips needed.

Quick Reference

CommandWhat it doesWhen to use it
opencode-relocate relocateMoves the project directory and updates all referencesYou moved or renamed a repo on disk
opencode-relocate move-sessionsReassigns selected sessions to another projectSessions were started in the wrong project
opencode-relocate split-projectCreates a new project and moves sessions into itYou split a repo or want to reorganize history
opencode-relocate relinkRe-links a project after its initial commit was recreatedYou reset/recreated the root commit and lost session history

Installation

Option 1: Symlink to PATH

ln -s "$(pwd)/opencode-relocate" /usr/local/bin/opencode-relocate

Option 2: Copy to PATH

cp opencode-relocate /usr/local/bin/opencode-relocate
chmod +x /usr/local/bin/opencode-relocate

Option 3: Run directly

./opencode-relocate <command> [args...]

Requirements

  • sqlite3 — pre-installed on macOS and most Linux distributions
  • git — required for split-project and relink (derives project IDs from root commits)
  • jq — optional; used for JSON updates when available, falls back to sed

Commands

relocate — Move a project to a new path

opencode-relocate relocate <old-path><new-path>

Moves the project directory and updates all internal OpenCode references (SQLite database and project JSON file).

# Example: rename a project directory
opencode-relocate relocate ~/Projects/my-app ~/Projects/my-app-v2

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Moves the directory with mv
  3. Updates project.worktree and session.directory in SQLite
  4. Updates the project JSON in OpenCode's storage
  5. Verifies all changes

After relocation, restart OpenCode from the new path:

cd~/Projects/my-app-v2 && opencode

move-sessions — Reassign sessions between projects

opencode-relocate move-sessions <source-path><target-path> [options]

Move sessions from one OpenCode project to another. Both projects must already exist in OpenCode (opened at least once).

The source can be a non-git directory — in that case, sessions are stored under the global project and are filtered by directory prefix so only sessions matching the source path are shown.

Three modes:

# Interactive (default) — checkbox-style session selector
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b
# List only — inspect sessions without moving
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b --list
# Scripted — provide session IDs directly
opencode-relocate move-sessions ~/Projects/repo-a ~/Projects/repo-b \
--session-ids "ses_abc123,ses_def456"

Interactive selector controls:

KeyAction
/ (or k / j)Navigate up / down
SpaceToggle current session
aToggle all sessions
EnterConfirm selection
q / EscCancel

The selector shows [x] / [ ] checkboxes, highlights the current row, scrolls automatically for long lists, and displays a live count of selected sessions.

Child/subagent sessions are moved automatically with their parent.


split-project — Create a new project from sessions

opencode-relocate split-project <source-path><target-path> [options]

Like move-sessions, but the target doesn't need to exist as an OpenCode project. If the target directory has never been opened in OpenCode, a new project entry is created automatically.

If the target directory doesn't exist, split-project will prompt you to create it (mkdir -p). If it's not a git repository (or has no commits), you'll be prompted to initialize it (git init + initial empty commit). The source can be either a git-backed project or a non-git directory (global project — sessions are filtered by directory prefix).

# Interactive (checkbox selector)
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service
# Split sessions from a non-git directory into a git-backed project
opencode-relocate split-project ~/Projects/sandbox ~/Projects/new-repo
# List only
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service --list
# Scripted
opencode-relocate split-project ~/Projects/monorepo ~/Projects/new-service \
--session-ids "ses_abc123,ses_def456"

Same interactive controls as move-sessions (arrow keys, Space, Enter).

When to use split-project vs move-sessions:

ScenarioCommand
Target project already exists in OpenCodeEither works
Target directory was never opened in OpenCodesplit-project
Source is a non-git directory (global project)Either works (filtered by directory)
Target directory is not a git reposplit-project (will offer to git init)

relink — Re-link a project after its initial commit changed

opencode-relocate relink <path> [options]

OpenCode identifies a project by the hash of its first root commit (git rev-list --max-parents=0 HEAD). If you reset or recreate the initial commit — e.g. squashing history, git update-ref -d HEAD, or rebuilding the repo — that hash changes, and OpenCode treats the repo as a brand-new project. All previous sessions become orphaned.

relink migrates the existing project from the old ID to the new root-commit-derived ID: sessions, workspaces, permissions, on-disk JSON artifacts, and the .git/opencode cache file.

# Auto-detect old and new IDs and relink
opencode-relocate relink ~/Projects/my-app
# Preview changes without writing anything
opencode-relocate relink ~/Projects/my-app --dry-run
# Specify IDs explicitly
opencode-relocate relink ~/Projects/my-app \
--old-id eca18ff587da0906289bd984d8b0fd7622b69604 \
--new-id b761b3048a1c1129822fcfaaf9252db49dace055

Auto-detection:

  • New ID is derived from the repo's current root commit hash.
  • Old ID is found by looking up the project whose worktree matches <path> but whose ID differs from the new ID, falling back to the cached value in .git/opencode.

Merge behavior: If a project row for the new ID already exists (e.g. you reopened OpenCode after the reset, so it created a fresh project), the old sessions are merged into it. Otherwise a new project row is created as a copy of the old one.

What happens:

  1. Backs up the database (timestamped .bak file)
  2. Re-points session, workspace, and permission rows to the new ID
  3. Creates or merges into the new project row, then deletes the old one
  4. Migrates storage/project/<id>.json and storage/session/<id>/ artifacts
  5. Updates the .git/opencode cache to the new ID
  6. Verifies the migration

Sessions keep their existing directory — only the project ID changes. Use --dry-run first if you want to preview the exact changes.

Safety

Automatic backups

Every command backs up opencode.db (plus WAL/SHM files) before making changes. Backups are timestamped:

~/.local/share/opencode/opencode.db.20260408_143022.bak

Interactive confirmation

All destructive operations require [y/N] confirmation before proceeding.

What's preserved

  • All session content: messages, tool calls, parts, todos
  • Session metadata: titles, timestamps, summaries
  • Parent-child session relationships (subagent sessions move with their parent)

What's NOT preserved

  • Undo/redo snapshots — stored per-project, not per-session

Recovery

Restore from backup:

cp ~/.local/share/opencode/opencode.db.20260408_143022.bak \
~/.local/share/opencode/opencode.db

Limitations

  • After relocate, the current OpenCode session breaks (restart required).
  • move-sessions requires the target to already exist as an OpenCode project.
  • Undo/redo snapshots are not moved.
  • Clones of the same repository share the same project ID (same root commit), so you cannot move sessions between clones of the same repo.
  • The global project cannot be used as a target — only as a source (sessions are filtered by directory prefix).
  • relink derives the new project ID from git rev-list --max-parents=0 HEAD and updates the .git/opencode cache; the repo must have at least one commit.

Disclaimer

This is an independent, community-built tool. It is not built by the OpenCode team and is not affiliated with OpenCode in any way. The "opencode" in the name refers only to the tool's purpose of managing OpenCode session data.

About

Bash CLI to move, relink, and reorganize OpenCode projects and sessions directly in its SQLite database.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages