
Security News
vlt 1.5.0 Adds Agent Skills Management
vlt 1.5.0 links skills from JavaScript dependencies to coding agents, with lockfile versioning and Socket data to filter out known malicious packages.
opencode-worktree-plugin
Advanced tools
Manage git worktrees across parallel OpenCode sessions — plugin + CLI
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.
feature/WIN-123)owt <name> opens a worktree in a new terminal windowowt diff, owt status, owt log, owt merge, owt commit without cdowt hook removes AI-injected Co-authored-by: from every commitnode_modules — symlinked from main repo; no duplicate installsOWT 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 │
└─────────────────────────────────────────────────────────────┘
worktree-plugin.js)The plugin registers three tools that OpenCode's AI agent can call:
| Tool | What it does |
|---|---|
createworktree | Runs git worktree add, symlinks node_modules, saves session state |
deleteworktree | Checks for uncommitted changes, runs git worktree remove, cleans up state |
listworktrees | Combines 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:
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.
command/*.md)Markdown files that define /init-worktree, /list-worktrees, and /open-worktree. These are prompt templates that:
They are the user-facing interface inside OpenCode sessions. The AI reads the markdown instructions and executes them.
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:
opencode --cwdowt fix matches "Fix login bug" by partial name or branchowt diff, owt log, owt status without cd-ing into the worktreeCo-authored-by: lines from commit messages/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
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>
# 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 helpworks but OpenCode doesn't recognize/init-worktree, restart OpenCode — plugins and commands are loaded on startup only.
If you prefer to understand each step, or only need specific parts:
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.
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.
owt is already installednpm install -g already placed owt on your PATH. Verify:
owt help
Troubleshooting: If
owtis not found after install, check that your npm global bin directory is in your PATH. Runnpm bin -gto 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-verifybypasses all hooks including this one. Do not use--no-verifyif you want co-author stripping.
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.
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.
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"
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.
owt status # all worktrees at once
owt status fix-login # specific worktree
owt diff fix-login # full diff vs base branch
owt diff fix-login -- src/auth.ts # specific file
owt log fix-login # commits since branched off base
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.
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
mainand need to commit changes that belong to another worktree, always useowt commit <name> -m "..."instead of switching branches. This keeps each branch's history clean and avoids accidentally committing feature work ontomain.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
owtmatches by partial name or branch —implement-amatchesfeature/implement-A.
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)
| Command | Description |
|---|---|
/init-worktree <branch> [name:"..."] | Create a named worktree |
/list-worktrees | List 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
These are the most common questions when using worktrees for the first time.
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).
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.
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.
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.
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 "...".
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
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.
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"
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.
owt # see which are dirty/clean
owt status # git status of all worktrees
owt log A # commits in feature A
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"
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
In OpenCode, call deleteworktree for each worktree, or:
git worktree remove .opencode/worktrees/feature/implement-A
node_modules is symlinkedWhen a worktree is created, node_modules is symlinked from the main repo root. This means:
npm install needed per worktree — saves disk and timenode_modules and is immediately available in all other worktreesnode_modules does not exist yet, the symlink is skipped silently; run npm install in the main repo firstAll 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 hooksRunning git commit --no-verify skips the commit-msg hook entirely. Co-authored-by will not be stripped. Avoid --no-verify unless intentional.
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.
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.
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)
@opencode-ai/plugin >= 1.4.6)FAQs
Manage git worktrees across parallel OpenCode sessions — plugin + CLI
The npm package opencode-worktree-plugin receives a total of 0 weekly downloads. As such, opencode-worktree-plugin popularity was classified as not popular.
We found that opencode-worktree-plugin demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
vlt 1.5.0 links skills from JavaScript dependencies to coding agents, with lockfile versioning and Socket data to filter out known malicious packages.

Security News
Rust 1.100 will add opt-in dependency cooldowns to Cargo, giving security scanners and maintainers time to catch malicious crate releases.

Security News
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.