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
{{ message }}
Repository navigation
Worktree actions are offered without a repository, and reach an ancestor repository #55776
Both come from the same cause: the worktree strategy is git-only and finds its
repository by searching ancestor directories.
Offered without a repository. The web session details menu offers worktree
actions for a project whose directory holds no repository. Creating one can
only fail.
Reaching an ancestor repository. A plain directory under a repository runs
worktree list/create/remove against that repository, because repository
discovery walks up. The session can end up outside the directory it runs in.
Plugins
None.
OpenCode version
2.0.29
Steps to reproduce
Open a session in a directory that is not a git repository.
Open the session details menu and pick "New worktree". POST /api/worktree
returns 400.
For the second: git init a parent of the working directory, then list or create
a worktree. The operation targets the parent repository.
Thanks for the clear report. I reproduced both parts on 2.0.29, and they still happen on the latest dev (3c61484). I used the server API, so no model was needed.
No repository: for a session in a plain directory, POST /api/worktree returns HTTP 400 (Worktree source not found: <dir>). On dev, the web session details menu still shows "New worktree" without checking whether the project uses git. I checked this in the code; I didn't open the web UI.
Parent repository: I opened a session in parent/child while it was a plain directory, then ran git init in parent. After a worktree refresh, the plain project's worktree list shows parent. Creating a worktree from it adds a real worktree to the parent repository, and git worktree list there shows it. A directory that is already inside a repository when its session starts joins that repository's project, so there this is expected.
The script below reproduces both parts. The cause looks like the one you describe: git.repo.discover walks up to the nearest .git, and nothing checks that the repository root it finds is the requested directory. Related: #55215 (the same "offered without a repository" problem in the TUI), PR #55326 (the TUI fix) and your PR #55771.
Reproduction script (repro.sh)
#!/usr/bin/env bash# Reproduces #55776 through the server API (no model needed).# Usage: bash repro.sh # server = `opencode` from PATH# OC_DEV=/path/to/checkout bash repro.sh # server = CLI run from sourceset -u
W=$(mktemp -d /tmp/opencode/oc55776.XXXX)export HOME="$W/home"; mkdir -p "$HOME"export OPENCODE_SERVER_PASSWORD=repro
PORT=${PORT:-$((4800 + RANDOM % 1000))}
URL=http://127.0.0.1:$PORTif [ -n"${OC_DEV:-}" ];then
bun --conditions=browser --preload="$OC_DEV/packages/tui/node_modules/@opentui/solid/scripts/preload.js" \
"$OC_DEV/packages/cli/src/index.ts" serve --port "$PORT">"$W/serve.log"2>&1&else
opencode serve --port "$PORT">"$W/serve.log"2>&1&fi
SERVER=$!trap'kill $SERVER 2>/dev/null' EXIT
for_in$(seq 60);do grep -q listening "$W/serve.log"&&break; sleep 1;done
cat "$W/serve.log"api() { opencode api --server "$URL""$@"2>&1| grep -v '^Warning: Server';echo; }
pid() { grep -o '"projectID":"[^"]*"'| head -1 | cut -d'"' -f4; }
echo"### 1. Plain directory, no repository: create worktree"
mkdir -p "$W/plain"
P1=$(api POST /api/session -d "{\"location\":{\"directory\":\"$W/plain\"}}"| pid);echo"project $P1"
api POST /api/worktree/refresh -d "{\"projectID\":\"$P1\"}"
api POST /api/worktree -d "{\"projectID\":\"$P1\"}"echo"### 2. Plain directory whose parent later becomes a git repository"
mkdir -p "$W/parent/child"
P2=$(api POST /api/session -d "{\"location\":{\"directory\":\"$W/parent/child\"}}"| pid)echo"plain project $P2 (canonical $W/parent/child)"
(cd "$W/parent"&& git init -q && git -c user.email=a@b -c user.name=a commit -q --allow-empty -m init)
api POST /api/worktree/refresh -d "{\"projectID\":\"$P2\"}"echo"worktree list for the plain project (expect nothing outside $W/parent/child):"
api GET "/api/worktree?projectID=$P2"echo"create worktree for the plain project from the listed checkout:"
api POST /api/worktree -d "{\"projectID\":\"$P2\",\"from\":\"$W/parent\",\"name\":\"wt1\"}"echo"git worktree list in the PARENT repository:"
(cd "$W/parent"&& git worktree list)
Activity
opencode-agent commentedon Oct 15, 2026
Thanks for the clear report. I reproduced both parts on 2.0.29, and they still happen on the latest
dev(3c61484). I used the server API, so no model was needed.POST /api/worktreereturns HTTP 400 (Worktree source not found: <dir>). Ondev, the web session details menu still shows "New worktree" without checking whether the project uses git. I checked this in the code; I didn't open the web UI.parent/childwhile it was a plain directory, then rangit initinparent. After a worktree refresh, the plain project's worktree list showsparent. Creating a worktree from it adds a real worktree to the parent repository, andgit worktree listthere shows it. A directory that is already inside a repository when its session starts joins that repository's project, so there this is expected.The script below reproduces both parts. The cause looks like the one you describe:
git.repo.discoverwalks up to the nearest.git, and nothing checks that the repository root it finds is the requested directory. Related: #55215 (the same "offered without a repository" problem in the TUI), PR #55326 (the TUI fix) and your PR #55771.Reproduction script (repro.sh)
Run it:
bash repro.sh