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
Transcript links open only every other click: re-clicks inside the double-click window are silently dropped #56062
Clicking a link in the session transcript works about every other attempt. A click that lands on the link does nothing, and clicking again immediately after also fails. Waiting a moment and clicking again works.
Steps to reproduce
Run opencode in a terminal with mouse reporting (e.g. VS Code integrated terminal; mouse capture is on by default).
Get a response containing a link.
Click the link — it opens.
Click the same link again within ~0.5 s — nothing happens. Another immediate click — still nothing.
Wait a moment and click again — it opens.
Cause
clickedLink() in packages/tui/src/ui/link.tsx requires a fresh "cell" selection to treat a release as a click. OpenTUI's nextClickBehavior() (packages/core/src/renderer.ts, CLICK_REPEAT_INTERVAL_MS = 500) classifies a re-click on the same renderable within 500 ms and ±1 cell as a "word" selection, and further rapid clicks as "line" (the counter sticks at 3 while clicking). The gate rejects both, so the link silently does not open — and rapid re-clicks keep the classification pinned at "line", so impatient clicking makes it less likely to work, not more.
Separately, a pointer that crosses a cell boundary between press and release clears selection.isStart, so the release is treated as a drag even when it settles back on the link cell.
Environment
opencode v2.0.21 (checked, also present on dev)
VS Code integrated terminal on Linux, but any terminal with mouse reporting should behave the same
Thanks for the detailed report. I can confirm this. In the reproduction, the simulated model replies with a link and the script clicks it four times: once, twice more about 250 ms apart, then once after a 1.5 s pause. Only the first and the last click open the link. The two quick re-clicks do nothing, and a multi-click selection seems to be copied instead (a "Copied to clipboard" toast appears). The recording below shows this, and the script below reproduces it.
One note on the version: v2.0.21 can't open transcript links by clicking at all. That feature first shipped in v2.0.26 (#53903). I reproduced it on v2.0.31 and on the latest dev (83c5abb), where it still happens. clickedLink() in packages/tui/src/ui/link.tsx is unchanged on dev. I only tested repeated clicks in place, not the press–move–release case you also describe.
// Reproduction for anomalyco/opencode#56062: transcript links only open on every other click.// A fake `xdg-open`/`$BROWSER` (see run instructions) appends every opened URL to /tmp/opencode/opened.log.//// mkdir -p /workspace/repro/bin /tmp/opencode// printf '#!/bin/sh\necho "$*" >> /tmp/opencode/opened.log\n' > /workspace/repro/bin/xdg-open// chmod +x /workspace/repro/bin/xdg-open// PATH=/workspace/repro/bin:$PATH BROWSER=/workspace/repro/bin/xdg-open opencode-drive run drive.tsimport{Effect}from"effect"import*asfsfrom"node:fs"import{Llm,OpenCodeDriver}from"opencode-drive"constLOG="/tmp/opencode/opened.log"constURL_TEXT="https://example.com/docs"constopened=()=>(fs.existsSync(LOG) ? fs.readFileSync(LOG,"utf8").split("\n").filter(Boolean).length : 0)exportdefaultOpenCodeDriver.use({
...(process.env.OC_DEV ? {opencode: {dev: process.env.OC_DEV}} : {}),tui: {recording: true,pointerOverlay: true},},({ ui, llm })=>Effect.gen(function*(){yield*Effect.sync(()=>fs.rmSync(LOG,{force: true}))yield*llm.queue(Llm.text(`See ${URL_TEXT} for details.`))yield*ui.submit("give me a link")yield*ui.waitFor("for details.")yield*Effect.sleep(1000)constframe=yield*ui.capture()letpos: {x: number;y: number}|undefinedframe.lines.forEach((line,y)=>{consttext=line.spans.map((s)=>s.text).join("")constx=text.indexOf(URL_TEXT)if(x>=0&&!text.includes("give me"))pos={x: x+5, y }})if(!pos)returnyield*Effect.die("link not found on screen")const{ x, y }=posconstclick=(label: string)=>Effect.gen(function*(){constbefore=opened()yield*ui.mouse({action: "move", x, y })yield*ui.mouse({action: "down", x, y,button: "left"})yield*ui.mouse({action: "up", x, y,button: "left"})yield*Effect.sleep(150)constresult=opened()>before ? "OPENED" : "nothing"yield*Effect.log(`${label}: ${result}`)returnresult})constresults: string[]=[]results.push(yield*click("click 1 (fresh)"))yield*Effect.sleep(100)results.push(yield*click("click 2 (~250ms later)"))yield*Effect.sleep(100)results.push(yield*click("click 3 (~250ms later)"))yield*Effect.sleep(1500)results.push(yield*click("click 4 (after 1.5s pause)"))yield*ui.screenshot("after-clicks")yield*Effect.log(`RESULTS: ${results.join(", ")}`)yield*Effect.log(`opened.log:\n${fs.existsSync(LOG) ? fs.readFileSync(LOG,"utf8") : "(empty)"}`)}),)
Run it with opencode-drive: opencode-drive run ./drive.ts. It drives opencode from your PATH; set OC_DEV to the path of an OpenCode checkout to run that from source instead.
Activity
opencode-agent commentedon Oct 16, 2026
Thanks for the detailed report. I can confirm this. In the reproduction, the simulated model replies with a link and the script clicks it four times: once, twice more about 250 ms apart, then once after a 1.5 s pause. Only the first and the last click open the link. The two quick re-clicks do nothing, and a multi-click selection seems to be copied instead (a "Copied to clipboard" toast appears). The recording below shows this, and the script below reproduces it.
One note on the version: v2.0.21 can't open transcript links by clicking at all. That feature first shipped in v2.0.26 (#53903). I reproduced it on v2.0.31 and on the latest
dev(83c5abb), where it still happens.clickedLink()inpackages/tui/src/ui/link.tsxis unchanged ondev. I only tested repeated clicks in place, not the press–move–release case you also describe.Related: #56061 is an open PR for this issue.
recording.mp4
Reproduction script (drive.ts)
Run it with opencode-drive:
opencode-drive run ./drive.ts. It drivesopencodefrom yourPATH; setOC_DEVto the path of an OpenCode checkout to run that from source instead.