Repository navigation
Description
Feature hasn't been suggested before.
- 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 nogit fetchfirst. There is no way to base a worktree on, say,origin/main. - Branch naming (line 271):
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 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.gitignoreconventions; co-located with the repo for ephemeral containers, codespaces, IDE project trees) - based on a freshly-fetched
origin/main, not localHEAD - on a user-supplied branch like
feat/login, notopencode/cosmic-rocket
Clicking "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
}
}CreateInput extension (packages/opencode/src/worktree/index.ts):
export const CreateInput = z.object({
name: z.string().optional(),
branch: z.string().optional(), // NEW — explicit branch name; takes precedence over auto-generation
baseRef: z.string().optional(), // NEW — per-call override of config.worktree.baseRef
startCommand: 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):
"worktree.create.before"?: (
input: { name?: string; branch?: string; baseRef?: string },
output: { name: string; branch: string; baseRef: string; directory: string; fetch: boolean },
) => Promise<void>Example — what becomes possible
// ~/.config/opencode/opencode.json
{
"worktree": {
"storage": "repo",
"baseRef": "origin/main",
"fetch": true,
"naming": "explicit"
}
}User clicks "Create new worktree" in opencode desktop, supplies feat/login. Backend runs:
git fetch origin
git worktree add -b feat/login <repoRoot>/.worktrees/feat-login origin/main
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.
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
- [FEATURE]: configurable path for worktrees #14032 — configurable path for worktrees (extended here with base ref, fetch, naming, and a plugin hook)
- [FEATURE]: Expose worktree lifecycle events (created, removed, reset) to plugins #15680 — expose worktree lifecycle events to plugins (extended here with a
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.before hook may be enough if maintainers prefer plugin-driven customization over new config knobs.
Activity
trin4ik commentedon Jun 26, 2026
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: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.
devcxl commentedon Jul 18, 2026
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.
很期待这个功能被合并,能解决我在并行开发时遇到的很多问题。希望能原生管理分支,而不是每次都靠 skill 去控制分支工作流。
github-actions commentedon Sep 18, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.