New:Introducing Socket Scanning for VS Code Marketplace Extensions.Learn more →
Get Started

opencode-worktree-plugin

Package Overview
Dependencies
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

opencode-worktree-plugin

Manage git worktrees across parallel OpenCode sessions — plugin + CLI

latest
Source
npmnpm
Version
2.0.0
Version published
Weekly downloads
0
-100%
Maintainers
1
Weekly downloads
 
Created
Source

owt — OpenCode Worktree Manager

Manage git worktrees across parallel OpenCode sessions. Create named worktrees, open them in new terminals, view their status, and commit — all without switching branches or losing uncommitted work.

What it does

  • Named worktrees — attach human-readable names to branches (e.g. "Fix login bug" instead of feature/WIN-123)
  • Parallel sessions — unlimited features in progress simultaneously, zero conflicts
  • Dirty status — see which worktrees have uncommitted changes at a glance
  • Quick access — owt <name> opens a worktree in a new terminal window
  • In-place git ops — owt diff, owt status, owt log, owt merge, owt commit without cd
  • Co-author strip — owt hook removes AI-injected Co-authored-by: from every commit
  • Shared node_modules — symlinked from main repo; no duplicate installs

How OWT works

OWT has three layers that work together. Each layer can be used independently.

┌─────────────────────────────────────────────────────────────┐
│                      You (human)                            │
├──────────────┬──────────────────────┬───────────────────────┤
│  OpenCode    │   OpenCode session   │   Terminal            │
│  main session│   (worktree)         │                       │
│              │                      │                       │
│ /init-worktree ──→ createworktree ──┼──→ owt <name>         │
│ /list-worktrees ─→ listworktrees    │    owt status/diff/   │
│ /open-worktree                      │    log/merge/commit   │
├──────────────┴──────────────────────┴───────────────────────┤
│              Slash Commands (command/*.md)                   │
│              Parse arguments, call plugin tools              │
├─────────────────────────────────────────────────────────────┤
│              Plugin (worktree-plugin.js)                     │
│              3 tools: createworktree / deleteworktree /      │
│              listworktrees                                   │
│              + system prompt injection                       │
│              + state management (worktree-sessions.json)     │
├─────────────────────────────────────────────────────────────┤
│              Shell Script (owt.sh)                           │
│              Terminal manager: list, open, status, diff,     │
│              log, merge, commit, hook                        │
├─────────────────────────────────────────────────────────────┤
│              git worktree (built-in git)                     │
│              The actual isolation mechanism                  │
└─────────────────────────────────────────────────────────────┘

Layer 1 — Plugin (worktree-plugin.js)

The plugin registers three tools that OpenCode's AI agent can call:

ToolWhat it does
createworktreeRuns git worktree add, symlinks node_modules, saves session state
deleteworktreeChecks for uncommitted changes, runs git worktree remove, cleans up state
listworktreesCombines git worktree list with saved display names and dirty status

System prompt injection: When OpenCode starts a session, the plugin injects context into the AI's system prompt:

  • Inside a worktree → injects cleanup rules ("tell user to run deleteworktree when done")
  • In the main repo → injects availability hint ("use createworktree for parallel tasks")

This is how the AI "knows" it's inside a worktree without being told.

State management: Display names, session IDs, and creation timestamps are stored in .opencode/worktree-sessions.json. This file is read by both the plugin and the shell script. It is not committed to git.

Layer 2 — Slash commands (command/*.md)

Markdown files that define /init-worktree, /list-worktrees, and /open-worktree. These are prompt templates that:

  • Parse user arguments (branch name, display name, base branch)
  • Call the plugin tools with the correct parameters
  • Format the output for the user

They are the user-facing interface inside OpenCode sessions. The AI reads the markdown instructions and executes them.

Layer 3 — Shell script (owt.sh)

A standalone bash script for use outside OpenCode — in any terminal. It reads the same worktree-sessions.json state file to resolve display names, and calls git directly for all operations.

Key capabilities not available through the plugin:

  • Terminal detection: Auto-detects Ghostty, iTerm, Terminal.app, WezTerm, Kitty, Alacritty, tmux — opens a new window with opencode --cwd
  • Fuzzy matching: owt fix matches "Fix login bug" by partial name or branch
  • In-place git ops: owt diff, owt log, owt status without cd-ing into the worktree
  • Co-author hook: Strips AI-injected Co-authored-by: lines from commit messages

Data flow: creating a worktree

/init-worktree feature/WIN-123 name:"Fix login bug"
                │
                ▼
    Slash command parses args
                │
                ▼
    createworktree(branch="feature/WIN-123", name="Fix login bug")
                │
                ├─ Branch exists locally?  → git worktree add <path> <branch>
                ├─ Branch exists remote?   → git fetch + git worktree add
                └─ New branch?             → git worktree add <path> -b <branch> <base>
                │
                ▼
    Symlink node_modules from main repo → worktree
                │
                ▼
    Save to .opencode/worktree-sessions.json:
    { "sessions": { "<sessionId>": { "branch": "...", "name": "...", "worktreePath": "..." } } }
                │
                ▼
    User opens: opencode --cwd ".opencode/worktrees/feature/WIN-123"
                │
                ▼
    Plugin detects worktree directory → injects WORKTREE_RULES into system prompt
                │
                ▼
    AI agent operates in isolated branch, full source checkout

Data flow: listing and opening

owt                         owt fix-login
 │                           │
 ▼                           ▼
git worktree list           Fuzzy-match "fix-login" against
 +                          display names and branch names
worktree-sessions.json       │
 │                           ▼
 ▼                          Resolve to single worktree path
Display all with             │
✓/⚠ dirty status            ▼
                            Detect terminal emulator
                             │
                             ▼
                            Open new window:
                            opencode --cwd <worktree-path>

Quick start

# Install globally (gives you owt CLI + setup tool)
npm install -g opencode-worktree-plugin

# Copy slash commands and plugin to OpenCode's config
owt-setup install

# Strip AI co-author from commits (optional)
owt hook --global

Restart OpenCode. Verify:

owt help

Troubleshooting: If owt help works but OpenCode doesn't recognize /init-worktree, restart OpenCode — plugins and commands are loaded on startup only.

Install (step by step)

If you prefer to understand each step, or only need specific parts:

Step 1 — Install the npm package (required)

npm install -g opencode-worktree-plugin

This puts two binaries on your PATH: owt (the terminal manager) and owt-setup (the config installer). Requires Node.js >= 18.

Step 2 — Copy config files into OpenCode (required)

owt-setup install

This copies the slash commands into ~/.config/opencode/command/ and the plugin into ~/.config/opencode/plugins/. Run owt-setup --version to confirm which version was installed.

Per-project loading (alternative): Instead of the global plugins directory, you can load the plugin per project by adding it to your opencode.json:

{
  "plugin": ["opencode-worktree-plugin"]
}

OpenCode will resolve the package from your project's node_modules. This is useful when different projects need different plugin versions.

Step 3 — owt is already installed

npm install -g already placed owt on your PATH. Verify:

owt help

Troubleshooting: If owt is not found after install, check that your npm global bin directory is in your PATH. Run npm bin -g to find it.

If you use OpenCode to commit, it injects Co-authored-by: Sisyphus into every commit message. To strip it globally across all repos on your machine:

owt hook --global

This installs a commit-msg git hook at ~/.config/git/hooks/commit-msg and sets git config --global core.hooksPath. One-time setup, applies everywhere.

Note: git commit --no-verify bypasses all hooks including this one. Do not use --no-verify if you want co-author stripping.

Step 5 — Restart OpenCode

Plugins and slash commands are loaded once at startup. After installing, you must restart OpenCode for changes to take effect. This is the most common reason things "don't work" after install.

Migrating from v1.x

If you previously installed the plugin by cloning the repo and copying files manually, remove the old copy before switching to the npm-based install:

rm ~/.config/opencode/plugins/worktree-plugin.js

If you also switch to opencode.json plugin loading (the "plugin": [...] key), make sure the file-based copy above is gone first. Otherwise the plugin loads twice, which causes duplicate tools and confusing behavior.

After removing the old file, follow the Quick start steps above.

Usage

List all worktrees

owt

Output:

Active worktrees:

  ⚠ Fix login bug  [dirty (uncommitted changes)]
    Branch : feature/WIN-123
    Path   : /project/.opencode/worktrees/feature/WIN-123
    Open   : opencode --cwd "/project/.opencode/worktrees/feature/WIN-123"

  ✓ pod-3 hotfix  [clean]
    Branch : release/pod-3
    Path   : /project/.opencode/worktrees/release/pod-3
    Open   : opencode --cwd "/project/.opencode/worktrees/release/pod-3"

Open a worktree in a new terminal

owt fix-login        # partial match on name or branch
owt WIN-123          # matches "feature/WIN-123"
owt pod              # matches "pod-3 hotfix"

Spawns a new terminal window running opencode --cwd <worktree-path>. Supports: Ghostty, iTerm, Terminal.app, WezTerm, Kitty, Alacritty, tmux.

View git status

owt status              # all worktrees at once
owt status fix-login    # specific worktree

View changes (diff)

owt diff fix-login               # full diff vs base branch
owt diff fix-login -- src/auth.ts  # specific file

View recent commits

owt log fix-login    # commits since branched off base

Merge into another branch

owt merge fix-login                   # merge into current branch
owt merge fix-login --into main       # merge into specific branch
owt merge fix-login --into release/qa3

Guards against dirty state — will error if uncommitted changes exist.

Commit from main session (without cd)

owt commit fix-login -m "feat: fix login redirect"

Runs git add -A + git commit inside the worktree. Useful when you want to commit without opening a new terminal.

Guideline: If you are on main and need to commit changes that belong to another worktree, always use owt commit <name> -m "..." instead of switching branches. This keeps each branch's history clean and avoids accidentally committing feature work onto main.

Examples:

owt commit implement-a -m "feat: implement A"   # commits into feature/implement-A
owt commit fix-login   -m "fix: login redirect"  # commits into feature/fix-login
owt commit pod-3       -m "chore: bump version"  # commits into release/pod-3

owt matches by partial name or branch — implement-a matches feature/implement-A.

Install co-author strip hook

owt hook --global           # all repos on this machine (recommended)
owt hook --local            # current repo only
owt hook --worktree WIN-123 # specific worktree (note: shares .git/hooks with main)

Inside OpenCode (slash commands)

CommandDescription
/init-worktree <branch> [name:"..."]Create a named worktree
/list-worktreesList all worktrees with status
/open-worktree [name-or-branch]Print opencode --cwd command

Examples:

/init-worktree feature/WIN-123 name:"Fix login bug"
/init-worktree hotfix/crash name:"Critical crash" from:main
/list-worktrees
/open-worktree fix-login

How git worktrees work — FAQ

These are the most common questions when using worktrees for the first time.

Does each worktree have the full source code?

Yes. A worktree is not a symlink or a partial copy. It is a complete checkout of the branch. Every file in the project exists inside the worktree directory.

project/                          ← full source, branch: main
project/.opencode/worktrees/
  feature/WIN-123/                ← full source, branch: feature/WIN-123
  release/pod-3/                  ← full source, branch: release/pod-3

The only thing that is symlinked is node_modules (to avoid duplicate installs).

Do 4 parallel sessions write to the same files?

No. Each session operates in its own directory. Session A edits worktrees/feature/WIN-123/src/Button.tsx. Session B edits worktrees/release/pod-3/src/Button.tsx. These are different files on disk.

Git also enforces branch locking — the same branch cannot be checked out in two worktrees simultaneously. If you try, git returns an error.

If I commit in worktree A, does the main repo see it?

Yes, immediately. All worktrees share a single .git repository. A commit in worktree A goes into the branch of worktree A. From the main session you can run:

git log feature/WIN-123 --oneline   # see the commit immediately
git diff main...feature/WIN-123      # diff without switching branches

You do not need to cd into the worktree to inspect its commits.

Do uncommitted changes get lost when I switch to another worktree?

No. Uncommitted changes stay in their worktree directory indefinitely. There is nothing to stash. To "switch" to another worktree, just cd to it or open a new terminal. The changes in the previous worktree are untouched.

This is the main advantage over git checkout — you never need to stash.

Why can't I commit feature A from the main repo directory?

The main repo directory is on a different branch (e.g. main or release/qa3). Committing there puts the commit on that branch, not on feature/implement-A.

To commit feature A, you must be in worktrees/feature/implement-A/ — or use owt commit implement-A -m "...".

Can I run npm test inside a worktree?

Yes. Each worktree has the full project structure and node_modules symlinked from the main repo. Run npm test, npm run build, or npm run start directly inside the worktree directory.

To run multiple features simultaneously on different ports:

# Each worktree gets its own port — as many as you need
PORT=3001 npm run start   # in worktrees/feature/implement-A
PORT=3002 npm run start   # in worktrees/feature/implement-B
PORT=3003 npm run start   # in worktrees/feature/implement-C
# ... and so on

How do I check out a worktree branch in the main repo?

You do not need to. From the main repo, use git -C to run git commands in any worktree without cd:

git -C .opencode/worktrees/feature/WIN-123 diff
git -C .opencode/worktrees/feature/WIN-123 log --oneline -5
git -C .opencode/worktrees/feature/WIN-123 status

Or use owt diff WIN-123, owt log WIN-123, owt status WIN-123.

End-to-end workflow

1. Create worktrees for each task

In OpenCode (main session):

/init-worktree feature/implement-A name:"Feature A"
/init-worktree feature/implement-B name:"Feature B"
/init-worktree feature/implement-C name:"Feature C"
/init-worktree feature/implement-D name:"Feature D"

2. Open each in a new session

owt feature-a    # opens terminal with opencode --cwd <path>
owt feature-b
owt feature-c
owt feature-d

Now you have 4 OpenCode sessions, each on their own branch, working in parallel.

3. Check progress from main session

owt              # see which are dirty/clean
owt status       # git status of all worktrees
owt log A        # commits in feature A

4. Review and commit

Option A — commit inside the worktree session:

# Inside the feature-A session
git add .
git commit -m "feat: implement A"

Option B — commit from main session without cd:

owt commit feature-a -m "feat: implement A"

5. Merge when done

owt merge feature-a --into release/qa3
npm test                                # verify after merge A
owt merge feature-b --into release/qa3
npm test                                # verify after merge A+B
# ... repeat for C, D

6. Cleanup

In OpenCode, call deleteworktree for each worktree, or:

git worktree remove .opencode/worktrees/feature/implement-A

Important notes

node_modules is symlinked

When a worktree is created, node_modules is symlinked from the main repo root. This means:

  • No npm install needed per worktree — saves disk and time
  • If you install a new package in a worktree session, it installs into the main node_modules and is immediately available in all other worktrees
  • If the main node_modules does not exist yet, the symlink is skipped silently; run npm install in the main repo first

git hooks are shared between worktrees

All worktrees of a repo share the same .git/hooks directory. Installing owt hook --local or owt hook --worktree affects all worktrees of that repo, not just one. This is a git design decision, not a limitation of owt.

For per-repo isolation, use --local. For machine-wide isolation, use --global.

--no-verify bypasses all hooks

Running git commit --no-verify skips the commit-msg hook entirely. Co-authored-by will not be stripped. Avoid --no-verify unless intentional.

Branch locking

Git will refuse to checkout the same branch in two worktrees at the same time:

fatal: 'feature/WIN-123' is already checked out at '/path/to/worktree'

This is intentional and protects you from editing the same branch in two places.

State file

Display names and session metadata are stored at <repo-root>/.opencode/worktree-sessions.json. This file is gitignored automatically. If display names stop showing, check that this file exists and is valid JSON.

File structure

plugins/
└── worktree-plugin.js      OpenCode plugin — createworktree / deleteworktree / listworktrees

command/
├── init-worktree.md        /init-worktree slash command
├── list-worktrees.md       /list-worktrees slash command
└── open-worktree.md        /open-worktree slash command

scripts/
└── owt.sh                  Terminal manager script (v2)

Requirements

  • OpenCode with plugin support (@opencode-ai/plugin >= 1.4.6)
  • git >= 2.5 (worktree support)
  • Node.js or Bun (for plugin runtime)
  • Python 3 (used by owt.sh for JSON parsing — pre-installed on macOS/Linux)
  • macOS or Linux

Keywords

opencode

FAQs

Package last updated on 22 Apr 2026

Related posts