Repository navigation
Description
Summary
On macOS, opencode attach has a repeatable multi-second gap after the server is already healthy and a session has already been created. The gap is visible before the first usable TUI frame, independent of the model's first reply.
Environment
- OpenCode 1.18.25 (
/opt/homebrew/bin/opencode) - macOS 26.5.1, Apple Silicon Mac Studio
opencode servebound to loopback, then a separate pty runningopencode attach <url> --session <id>- The host used an isolated OpenCode XDG home and set
OPENCODE_DISABLE_PROJECT_CONFIG=truefor its task-home; no owner process or profile was used.
Measurement
The host clicked New task, submitted a prompt, waited for GET /global/health = 200, observed the task-home session from GET /session, then spawned the exact attach command. attach connected is the attach PID's loopback TCP connection to the serve port. TUI first frame is the first visible xterm instance after the attach instance changed and the OpenCode status bar was rendered. Times below are cumulative from the New task click; t7 is reported separately from the OpenCode message ledger.
| Profile | attach spawn | attach TCP connected | TUI first frame | spawn→connected | connected→first frame | t0→t5 |
|---|---|---|---|---|---|---|
| Cold: fresh host profile + fresh OpenCode XDG home | 2.448s | 5.598s | 9.880s | 3.150s | 4.282s | 9.880s |
| Warm: same profile after app restart, OpenCode cache present | 2.336s | 5.573s | 9.257s | 3.237s | 3.684s | 9.257s |
| Hot: same app process, second new task | 2.191s | 6.435s | 10.271s | 4.244s | 3.836s | 10.271s |
The host-side preceding milestones were similarly stable: HTTP ready at 1.871–2.025s, session observed at 2.180–2.432s, and attach spawn at 2.191–2.448s. The first prompt reached the OpenCode session at 2.396–2.672s. First replies completed at 11.379–17.801s and are intentionally not included in the TUI startup claim.
Questions
Please profile the two attach-side intervals:
- attach process spawn → first TCP connection to the healthy serve;
- TCP connection → first rendered/interactive TUI frame.
In particular, can startup work such as external plugin loading, provider/model discovery, models.dev fetch, update checks, terminal capability queries, or replay be identified and deferred?
Flag probe
OpenCode 1.18.25 exposes attach --pure (run without external plugins), but no attach-specific provider/update skip flag. In an isolated serve --pure + attach --pure pty with OPENCODE_DISABLE_AUTOUPDATE=true and OPENCODE_DISABLE_MODELS_FETCH=true, the first pty output arrived 5.232s after attach spawn. This is a first-output probe, not a substitute for the full TUI table above; it shows the pure path still has a multi-second attach startup.
Related: #14965 (slow startup), #31463 (cold npm plugin resolution), #31006 (--pure plugin startup workaround), #37060 (attach TUI init hang on Windows).
Activity
shuxueshuxue commentedon Sep 9, 2026
Follow-up measurements from 2026-09-09 (OpenCode 1.18.25, macOS, isolated XDG HOME/project). These are bare controls outside Gugu. Three runs per row; median (range), seconds. TCP is the first
lsofESTABLISHED connection to the serve port. First frame is the first captured alternate-screen sequence (ESC[?1049h).--pureThe project-plugin control is repeatable across machines: OpenCode logs show config/plugin bootstrap and an unconditional dependency install before
POST /session; a warm dependency cache reduces that to about 1.1-1.4s.OPENCODE_DISABLE_PROJECT_CONFIGreturns it to about 0.1s. This explains the historical intermittent/sessiontimeout class, but it is separate from attach-side latency.The attach gap remains after
--pure, model fetch disable, update disable, and a positive network blackhole. In the blackhole runs, the server log explicitly reports repeatedFailed to fetch models.dev, while attach->TCP and TCP->frame remain unchanged. The attach sampler saw the expected loopback connection; no attach-child external socket was identified, but unrelated processes also owned external sockets, so external-socket absence is UNMEASURED rather than claimed as zero.For comparison, a same-machine direct TUI invocation (the in-process worker/server path, without external attach validation) rendered in 2.55s on the Mac mini and 4.46s on Mac1. This bounds the additional two-process/validation overhead, but is not a drop-in replacement for attach.
Source cross-check against tag
v1.18.25(cb7d8b2f5e44876ef98b661dc10590c915af3a9f):cli/cmd/attach.tsawaitsTuiConfig.get(), thenvalidateSession()(session.getwith--session), then imports/runs the TUI layer.packages/tui/src/app.tsxcreates the renderer, waits up to 1s for theme mode, then calls Solidrender(). SSE, provider/config/agent/project sync, non-blocking session/MCP/LSP/formatter/status/auth/VCS/workspace refreshes, and external TUI plugin startup happen after mount.tui.tsschedulescheckUpgrade()1s after validation, outside the render-critical await chain.The two-machine controls support profiling the attach/runtime/TUI path upstream; there is no measured Gugu-owned wait inside attach. Full raw logs and captures are available in gugu-base commit
d17c92f22ef0218c7902a7f6e2614a4f3e3303a6underevidence/2026-09-09-opencode-serve-attach-5288/.shuxueshuxue commentedon Sep 9, 2026
Additional machine controls for the attach-startup gap (2026-09-09). OpenCode is 1.18.25 on both hosts; each command was run five fresh times with isolated HOME/XDG only for the attach experiment.
/usr/bin/time -p real, seconds:opencode --versionopencode attach --helpopencode --versionopencode attach --helpThe earlier bare controls measured attach spawn -> TCP at 0.68s (0.62-0.83) on the mini and 3.32s (2.07-5.55) on Mac1. Since version/help startup is the same on both machines, the approximately 2.6s delta is not binary load, code-signing, or page-cache startup. It is in attach-specific work after argument parsing and before its first socket activity (
TuiConfig.get(),validateSession(), and dynamic TUI/Effect imports). Both probes used a tiny cwd (/private/tmp/opencode-probe-*/project).The attach-side DEBUG first-log timestamp remains unmeasured in this build:
--print-logsproduced no attach stderr/log records in this path. Source inspection at tagv1.18.25showsTuiConfig.get()resolving ancestor.opencodecandidates plus global XDGtui.json/tui.jsonc; the isolated project had no non-empty TUI file. We therefore do not claim a zero-duration config read. The machine gap is reproducible, but the exact internal sub-interval needs an upstream per-stage trace.Raw command logs are in gugu-base evidence
2026-09-09-opencode-serve-attach-5288/(follow-up v2 files).shuxueshuxue commentedon Sep 9, 2026
Follow-up measurements from two hosts (OpenCode 1.18.25, isolated XDG homes/cwd; raw evidence is in gugu-base commit
dc82f25).attach/opt/homebrew/bin/opencodedyld4::APIs::dlopen -> Loader::getLoader -> makeDiskLoader -> mapSegments -> fcntl; helper threads mostly__psynch_cvwaitopencodekevent64(1456/1657/1617 samples), shorter secondarydlopen/mapSegments(400/217/222); nostat/opendirhotspotBinary-only controls are indistinguishable (
opencode --version: 0.26-0.28s;attach --help: 0.27-0.30s), so the Mac1 gap is after argument parsing and is consistent with dynamic module/dyld segment mapping rather than binary launch or project scanning. A mini CPU control (8 and 16yesworkers, 8 CPUs) increased attach to medians 1.241s and 1.455s, but did not reproduce Mac1's 3-9s; load is a contributor, not the sole cause.The isolated XDG server log is present and shows config/instance/project loads, but this path emits no attach-side
TuiConfig/session.getline to stderr orhome/data/opencode/log; attach-first-log timing remains unmeasured rather than being claimed zero.One more same-ruler product check on Gugu (Mac1, temporary renderer probes, independent build
c1037975ff62) found, warm n=3:ESC[?1049hThe prior Gugu TCP-to-status-bar 3.7-4.3s is therefore accounted for: alt-screen arrives within the TUI interval, and only ~0.46s remains after it for Gugu visible gating/mount. No stable Gugu-owned >0.5s segment was found. Cold Electron restarts had large OpenCode/TUI tails before alt-screen (TCP->alt median 18.724s, range 2.733-33.160), reinforcing that the long segment is upstream/machine startup. I do not think this needs an upstream code change, but the dyld stack and host/load split may be useful for the issue.
thdxr commentedon Oct 11, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊