Repository navigation
[Bug]: OpenCode CLI OSC title leak pollutes agent inventory — Agent not found → UnknownError #7754
Description
Activity
📦 Want this fix today — without waiting for #7755 to merge?
Two ways, both live now:
Option A — zero tooling: ImBIOS/t3code@main already contains this fix (landed via ImBIOS#2). Clone/vendor from there:
gh repo clone ImBIOS/t3code && cd t3code && bun testOption B — forkhub intent-patch (recommended if you maintain your own fork and want to keep receiving upstream releases)
This fix is published as an intent-patch: instead of pinning a frozen diff, you import the spec (INTENT.md + acceptance criteria + verify.sh), and an AI coding agent re-derives it against whatever upstream SHA your checkout is at — then again on every future upstream release, until #7755 merges (after which fh cleanup --apply drops the patch and you return to official releases).
# 1) Install the CLI (canary channel)
pnpm add -g "github:ImBIOS/forkhub#canary&path:packages/cli"
# 2) From inside YOUR t3code checkout
# (remotes: upstream = pingdotgg/t3code, origin = <you>/t3code)
fh init --target github.com/pingdotgg/t3code
# 3) Import this patch intent (author attribution preserved)
fh import https://github.com/ImBIOS/.forkhub/blob/main/repos/github.com/pingdotgg/t3code/patches/fix-t3code-strip-osc-ansi-escapes-from-opencode-cl-y7shx01y/INTENT.md
# 4) Re-derive against your checkout
fh re-derive fix-t3code-strip-osc-ansi-escapes-from-opencode-cl-y7shx01y
# → prints a context-bundle path (README.md inside is authoritative)
# 5) Have your AI agent implement the bundle (OpenCode: run the `/forkhub`
# skill with no args), writing REALIZATION/realization.diff, then:
fh apply <bundle-path> # verify gate runs `bun test`
# 6) Ongoing maintenance
fh watch # daemon: auto drift-detect → regenerate → apply → tag
fh update # advance to latest tagged build
fh pr-status # tracks THIS issue/PR state via ghPatch contents (browse): INTENT.md (root cause, non-negotiables, implementation notes) · ACCEPTANCE.md · reference.diff (+139/−14, hint only) · verify.sh. Discoverable via fh search --author ImBIOS or fh search --target github.com/pingdotgg/t3code.
If you hit the same bug on a different T3 version, the intent survives: re-derivation adapts the fix to your tree rather than replaying a stale diff.
Related report #7716 covers the same problem and adds useful evidence.
The exact broken build-agent value contains the OSC title fragment ready build. Issue 7754 documents the same stdout escape leak, failed agent selection, and persisted polluted value, with a more complete reproduction. This is not the separate plan-mode filter or custom-agent enumeration issue.
I'm linking the report here before I close it as a duplicate during an automated pass. The source report and its attachments will remain available at #7716.
Bug
OpenCode <=1.18 writes OSC title sequence
ESC ]0;<cwd>: ready BELto stdout for every non-help command even when stdout is a pipe. T3 captures that viaChildProcessSpawner+collectStreamAsStringand the parsers stored a polluted agent id:Followed by generic wrapper:
Evidence
~/.t3/userdata/logs/provider/events.*.logshows twosession.errorper turn: first is the polluted agent, second is the generic UnknownError.projection_threads.model_selection_jsonpolluted for 3 threads:{"instanceId":"opencode","model":"opencode-go/mimo-v2.5","options":[{"id":"agent","value":"\u001b]0;imbios: ready\u0007build"}]}opencode agent list 2>&1 | cat -v→^[]0;tmp: ready^Gbuild (primary)even withenv -i PATH=... opencode agent listandTERM=dumb— opencode binary itself leaks, not shell/ghostty.opencode models --verbose 2>&1 | cat -v→^[]0;tmp: ready^Gopencode/big-pickle— caused model inventory to drop to 0 without the fix (SLUG_RE didn't match). Skills JSON degraded to[].Root cause
apps/server/src/provider/opencodeRuntime.ts:208,270parseModelsCliOutput/parseAgentListCliOutputassumed clean stdout. No strip of OSCESC ]...BEL/ CSIESC[...m.Fix
See PR from fork (ImBIOS#2 merged to ImBIOS:main, will open upstream PR). Summary:
packages/shared/src/stripTerminalEscapes.ts: sharedstripTerminalEscapes/sanitizeTerminalValueopencodeRuntime.ts: strip beforeparseModels/Agent/Skills, defensive at entryOpenCodeProvider.ts: sanitize inventory agent names/variants +--versionparsingOpenCodeAdapter.ts+OpenCodeTextGeneration.ts: sanitize storedagent/variantbeforesession.promptAsyncpackages/shared/src/model.ts: sanitize persisted option values and model slugs on read (repairs polluted threads without DB migration)Upstream
Should be fixed in
sst/opencodeas well: CLI should write OSC title to/dev/tty/stderronly when isTTY, not stdout pipe. T3 fix is defensive regardless.Repro steps
opencode agent list | cat -vshows OSC prefixloadInventoryFromClistores polluted agentExpected
Clean agent inventory, no OSC leak.