You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have verified this feature I'm about to request hasn't been suggested before.
Describe the enhancement you want to request
Worktree.create() in packages/opencode/src/worktree/index.ts hardcodes three behaviors that, taken together, prevent a common workflow:
Storage location (line 339): Global.Path.data/worktree/<projectId>/<random>/ — worktrees always land under ~/.local/share/opencode/..., separate from the source repo. (Related: [FEATURE]: configurable path for worktrees #14032 — same concern, location only.)
Base ref (line 345): git worktree add --no-checkout -b ${info.branch} ${info.directory} — new branches are created off HEAD of the primary worktree, with no git fetch first. There is no way to base a worktree on, say, origin/main.
Branch naming (line 271): branch = opencode/<adjective>-<noun> — always auto-generated, always prefixed opencode/. No way to pass an explicit branch name like feat/login.
None of these can be customized via plugin today: the Hooks interface in packages/plugin/src/index.ts has no worktree.create.* hook. The only worktree-related signal a plugin can receive is the worktree.ready / worktree.failed events via the event catch-all — and by that point the worktree has been created at the wrong path, off the wrong ref, with the wrong branch name, and an Instance is already bound to the directory (line 375), making post-hoc relocation racy.
Motivation — concrete workflow
I want every new worktree to be:
created at <repoRoot>/.worktrees/<branch-as-slug>/ (consistent with .gitignore conventions; co-located with the repo for ephemeral containers, codespaces, IDE project trees)
based on a freshly-fetched origin/main, not local HEAD
on a user-supplied branch like feat/login, not opencode/cosmic-rocket
Clicking "Create new worktree" in opencode desktop should be all it takes.
Proposed design
Config schema additions (all defaults preserve current behavior):
exportconstCreateInput=z.object({name: z.string().optional(),branch: z.string().optional(),// NEW — explicit branch name; takes precedence over auto-generationbaseRef: z.string().optional(),// NEW — per-call override of config.worktree.baseRefstartCommand: z.string().optional(),})
Plugin hook (extends #15680 — they propose worktree.created/removed/reset after-the-fact events; this adds a before hook for full extensibility):
The new branch tracks origin/main at fetch time, independent of local main state. .worktrees/ is added once to .gitignore (or ~/.config/git/ignore) and the convention is global.
If the design is approved, I'll send the PR. Open to alternative shapes — e.g. a single worktree.create.before hook may be enough if maintainers prefer plugin-driven customization over new config knobs.
I never stop being amazed by how developers from different parts of the world end up thinking along the same lines.
I was considering almost exactly the same architecture: something like ~/<project-path>/.worktrees/<branch-slug>, for roughly the same reasons:
.gitignore solves the Git-related issues, and IDE excludes solve the indexing problem.
It becomes easy to switch between worktrees in the IDE, while still seeing the whole project root with all worktrees.
With hacks like subvolumes in modern filesystems such as btrfs, worktrees can be created in a fraction of a second.
But for me, simply creating a worktree from opencode is not enough. I also need to create Docker networks, start containers for each worktree, create copies of databases/caches for those worktrees, and handle other infrastructure plumbing.
So overall I do not really have this problem myself, because I already do it through my own tooling — scripts in skills. But it would definitely be more convenient if there were hooks, especially with the ability to control the target directory. I would gladly shrink my skill quite a bit and move most of that logic into hooks.
Looking forward to this being merged — it will solve a lot of the pain points I encounter when working on multiple features in parallel. It would be great to manage branches natively instead of relying on skills/plugins to orchestrate the workflow.
Feature hasn't been suggested before.
Describe the enhancement you want to request
Worktree.create()inpackages/opencode/src/worktree/index.tshardcodes three behaviors that, taken together, prevent a common workflow:Global.Path.data/worktree/<projectId>/<random>/— worktrees always land under~/.local/share/opencode/..., separate from the source repo. (Related: [FEATURE]: configurable path for worktrees #14032 — same concern, location only.)git worktree add --no-checkout -b ${info.branch} ${info.directory}— new branches are created off HEAD of the primary worktree, with nogit fetchfirst. There is no way to base a worktree on, say,origin/main.branch = opencode/<adjective>-<noun>— always auto-generated, always prefixedopencode/. No way to pass an explicit branch name likefeat/login.None of these can be customized via plugin today: the
Hooksinterface inpackages/plugin/src/index.tshas noworktree.create.*hook. The only worktree-related signal a plugin can receive is theworktree.ready/worktree.failedevents via theeventcatch-all — and by that point the worktree has been created at the wrong path, off the wrong ref, with the wrong branch name, and anInstanceis already bound to the directory (line 375), making post-hoc relocation racy.Motivation — concrete workflow
I want every new worktree to be:
<repoRoot>/.worktrees/<branch-as-slug>/(consistent with.gitignoreconventions; co-located with the repo for ephemeral containers, codespaces, IDE project trees)origin/main, not localHEADfeat/login, notopencode/cosmic-rocketClicking "Create new worktree" in opencode desktop should be all it takes.
Proposed design
Config schema additions (all defaults preserve current behavior):
{ "worktree": { "storage": "data", // "data" (default, current) | "repo" → "<repoRoot>/.worktrees/" "baseRef": "HEAD", // default "HEAD" (current). e.g. "origin/main" "fetch": false, // default false. true → `git fetch <remote>` before branching "naming": "random" // "random" (default, current) | "explicit" — require `branch` on CreateInput, error if absent } }CreateInputextension (packages/opencode/src/worktree/index.ts):Plugin hook (extends #15680 — they propose
worktree.created/removed/resetafter-the-fact events; this adds abeforehook for full extensibility):Example — what becomes possible
User clicks "Create new worktree" in opencode desktop, supplies
feat/login. Backend runs:The new branch tracks
origin/mainat fetch time, independent of localmainstate..worktrees/is added once to.gitignore(or~/.config/git/ignore) and the convention is global.Files that would change
packages/opencode/src/worktree/index.ts— creation logic,CreateInputshapepackages/opencode/src/config/...— schema (wherever worktree config lands)packages/plugin/src/index.ts—Hooksinterfacepackages/app/src/components/session/session-new-view.tsx— UI input for branch name whennaming: "explicit"Related issues
beforehook in addition to the proposedcreated/removed/resetevents)Happy to implement
If the design is approved, I'll send the PR. Open to alternative shapes — e.g. a single
worktree.create.beforehook may be enough if maintainers prefer plugin-driven customization over new config knobs.