opencode-worktree: git worktrees that open their own terminal
Zero-friction git worktrees for OpenCode. Auto-spawns terminals, syncs files, cleans up on exit.
At a glance
- What is it?
- An OpenCode plugin that turns worktree_create and worktree_delete into lifecycle events, spawning a terminal for each isolated branch and committing changes before removal. It is a workflow layer for CLI-first AI coding, not a general-purpose worktree manager.
- Who is it for?
- Adopt it if you drive OpenCode from a terminal and want each agent branch to get its own window with file sync and hooks, and if you accept an extra plugin dependency in every project. Skip it if you work mainly in the OpenCode Desktop UI, since the README states you lose automatic terminal spawning there, or if you want per-worktree control over which changes get committed.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The friction it removes is the four steps between git worktree add and a running agent
Manual worktrees are not hard, they are just serial. The README lists the sequence plainly: create the worktree, open a terminal, navigate to it, start OpenCode. Four steps, repeated per branch, and the reverse four steps when you are done. The plugin's claim is not that it can do something git cannot. It is that the create and delete calls become events that carry the rest of the sequence with them.
The audience is narrow and the README is honest about it. The comparison table names three approaches: manual git worktree for one-off experiments and full control, the OpenCode Desktop UI for a visual workflow, and this plugin for AI-driven workflows, automation and CLI-first users. The tradeoff column for the plugin says it adds a plugin dependency to your project. That is the real cost, and it is a per-project cost, not a one-time install.
If you are the person who opens a worktree, edits for twenty minutes and closes it, this solves a problem you do not have. The plugin pays off when an agent is the one calling the tools, because the agent cannot open a terminal window or navigate a filesystem on your behalf through git alone.
Two tools, one lifecycle: what worktree_create and worktree_delete actually do
The plugin adds exactly two tools to OpenCode. worktree_create takes a branch and an optional baseBranch that defaults to HEAD. worktree_delete takes a reason string.
The create path, as documented, runs in a fixed order. It creates the git worktree at ~/.local/share/opencode/worktree/<project-id>/<branch>/. It syncs files according to .opencode/worktree.jsonc. It runs postCreate hooks, with pnpm install given as the example. Then it opens a new terminal with OpenCode already running inside.
The delete path is the part worth reading twice. It runs preDelete hooks first (the Docker example uses docker compose down), then commits all changes with a snapshot message, then removes the git worktree with --force, then cleans up session state. That ordering means the commit is unconditional and the removal is forced. There is no documented interactive prompt asking whether to keep the branch or discard it. For an agent workflow that is the point: the session ends cleanly without a human deciding anything. For a human who just spent an hour on a branch they wanted to review before committing, the same behaviour is a surprise waiting to happen.
The mermaid diagram in the README compresses this to create, terminal spawns, work in isolation, delete, auto-commit and cleanup, session ends. The diagram is accurate but it hides the force flag, which is the detail that matters most.
Worktrees live outside your repository, and the sync config is the only bridge back
Storage location is a design decision with consequences. Worktrees go to ~/.local/share/opencode/worktree/<project-id>/<branch>/, outside the repository entirely. That keeps the working tree clean and avoids the usual git worktree placement arguments, but it also means anything your build needs from the parent directory is not there by default.
The .opencode/worktree.jsonc file, auto-created on first use, is how you patch that gap. It has two top-level keys. The sync key holds copyFiles (files to copy from the main worktree), symlinkDirs (directories to symlink) and exclude (patterns to exclude). The hooks key holds postCreate and preDelete arrays.
The distinction between copyFiles and symlinkDirs is the one to get right. The README's Node.js example copies .env and .env.local and symlinks node_modules. That split is sensible: environment files are small and benefit from being independent copies, while node_modules is large and expensive to duplicate. Symlinking a directory that a build tool rewrites in place is a different matter, and the documentation does not discuss what happens when two worktrees share a symlinked directory and both write to it. If your toolchain mutates anything under a symlinked path, that is a case to think through before enabling it.
The schema is published at a registry URL referenced in the file, so editor completion depends on that endpoint being reachable. Nothing in the material describes offline behaviour.
Installation goes through OCX, and that is a second dependency before the first one
The install command is:
ocx add kdco/worktree --from https://registry.kdco.dev
OCX is not bundled. The README points to a separate repository for it, and there is an optional companion bundle, kdco/workspace, that adds background agents, planning tools and notifications on top of worktrees. So the adoption chain is OpenCode, then OCX, then this plugin, and optionally a workspace bundle. Each link is a thing that can fall behind or break independently.
There is no version pinning shown in the command. The registry URL is the source of truth, and the README does not describe how to lock a version or roll one back. For a tool that commits and force-removes worktrees on your behalf, that is worth knowing before it is on a team's machines rather than just yours. The repository lists no retrieved releases, so there is no release-notes trail to read for behaviour changes between versions.
On the plus side, the licence is MIT. That is permissive and places few obligations on how you redistribute or modify it, though as always the actual terms in the LICENSE file govern and this is not legal advice. If you fork it to change the delete behaviour, MIT lets you do that.
Terminal detection is a priority list, and tmux outranks everything
The plugin picks a terminal by working down a priority order. tmux comes first on all platforms when you are already inside a tmux session, and it creates a new tmux window rather than launching a separate terminal application. cmux comes second and is described as recommended for new agentic workflows, using its native launch flow when CMUX_WORKSPACE_ID is present or when socket control is explicitly enabled through CMUX_SOCKET_PATH together with CMUX_SOCKET_MODE=allowAll. WSL comes third and routes through Windows Terminal via wt.exe interop. Then environment variables such as TERM_PROGRAM, KITTY_WINDOW_ID and GHOSTTY_RESOURCES_DIR. Then system defaults.
One cmux detail is stated with unusual precision: each worktree launch always opens a new cmux workspace and never reuses the current one, falling back safely when cmux context is unavailable. That is a deliberate choice, and it means a cmux user accumulates workspaces at the rate the agent creates worktrees.
The platform table is broad. macOS covers Ghostty, iTerm2, Kitty, WezTerm, Alacritty, Warp and Terminal.app. Linux covers Kitty, WezTerm, Alacritty, Ghostty, Foot, GNOME Terminal, Konsole, XFCE4 Terminal and xterm. Windows gets Windows Terminal and a cmd.exe fallback. The fallback ladder means the plugin will almost always open something, but opening something is not the same as opening the terminal you configured. If your setup is not in the table, you land on a system default, and the README does not offer a documented override key for that case.
Where it is the wrong tool: desktop users, and anyone who wants a review step before commit
Two limits stand out from the material itself.
The first is stated in the FAQ. Worktrees created by the plugin work fine in OpenCode Desktop, but you lose the automatic terminal spawning. So the desktop path gets you the worktree and the config file and nothing else that makes this plugin distinct. If your daily driver is the Desktop UI, the README's own comparison table already tells you that you may not need this.
The second is the delete semantics. Committing all changes with a snapshot message and then removing the worktree with --force leaves no documented checkpoint between the two. There is no described dry-run mode, no flag to keep the branch, and no confirmation step. An AI agent calling worktree_delete with a reason string is trusted to be right about the work being finished. If your workflow depends on a human reading a diff before it lands on a branch, this plugin's cleanup path is in direct conflict with that, and the preDelete hook is the only place you could insert a check.
The plugin also assumes the branch name it is given is safe to use as a directory component under the worktree root, since the path is built from <project-id>/<branch>. Branch names with slashes are shown working in the README example (feature/dark-mode), so nesting is expected, but the material says nothing about name collisions with pre-existing directories at that path.
How it differs from plain git worktree and from OpenCode Desktop
The honest comparison is not against another plugin. It is against the two things the README names.
Plain git worktree gives you the worktree and nothing else. You choose where it lives, you open your own terminal, you run your own install step, and you decide when to remove it. Nothing happens automatically, which is both the weakness and the safety property. The plugin's difference is that create and delete become composite operations with a config file driving file sync and hooks, and the terminal spawn is part of create rather than a step after it.
OpenCode Desktop gives you worktrees through a GUI. The README positions it as the visual, integrated option and notes it is tied to the desktop app with less automation. The plugin's difference is that it is reachable from the terminal and from the agent's tool calls, which is what makes it scriptable. The two are not mutually exclusive in one direction only: plugin-created worktrees open in Desktop, but Desktop-created worktrees do not get the auto-spawn.
If neither of those differences matters to you, the plugin is an extra dependency with a config file to maintain. The README says as much in its own table, which is a point in its favour.
Maintenance surface: one config file per project, no pinned version, no release history
The recurring cost is the .opencode/worktree.jsonc file in each repository. It is auto-created empty on first use, so the initial burden is zero, but every project where you want .env copied or node_modules symlinked or pnpm install run needs its own entries. There is no described shared or global config, so a monorepo with several packages means several files or one file that has to serve all of them.
Hooks are shell commands in an array, which means they carry the usual portability questions. The Docker example runs docker compose up -d on create and docker compose down on delete. If a postCreate hook fails, the material does not say whether the worktree is left in place, rolled back, or the terminal still spawns. That is a gap worth testing on a throwaway branch before trusting it on real work.
Upgrades are the other open question. Installation goes through a registry URL with no version argument shown, and no releases were retrieved for the repository, so there is no changelog to scan before an update lands. The practical implication is that a change to the delete path, which commits and force-removes, would reach you without a version number to hold back. Pinning through whatever mechanism OCX offers is the thing to confirm at install time, not after.
Editorial conclusion
Adopt it if you drive OpenCode from a terminal and want each agent branch to get its own window with file sync and hooks, and if you accept an extra plugin dependency in every project. Skip it if you work mainly in the OpenCode Desktop UI, since the README states you lose automatic terminal spawning there, or if you want per-worktree control over which changes get committed. Before installing, verify that your terminal appears in the platform table, that the branch argument you plan to pass does not collide with your existing worktree layout, and that the default storage path under ~/.local/share/opencode/worktree is acceptable for your repository size.
Community notes