Skip to content

[Bug]: OpenCode CLI OSC title leak pollutes agent inventory — Agent not found → UnknownError #7754

Description

@ImBIOS

Bug

OpenCode <=1.18 writes OSC title sequence ESC ]0;<cwd>: ready BEL to stdout for every non-help command even when stdout is a pipe. T3 captures that via ChildProcessSpawner + collectStreamAsString and the parsers stored a polluted agent id:

Agent not found: "\u001b]0;imbios: ready\u0007build". Available agents: build, explore, general, plan

Followed by generic wrapper:

UnknownError: UnknownError
    at <anonymous> (//root/chunk-09733s3k.js:1096:2069)
    at SessionPrompt.createUserMessage (//root/chunk-09733s3k.js:1096:9954)
    ...
    at SessionHttpApi.promptAsync (//root/chunk-ys5kjase.js:2:84381)

Evidence

  • ~/.t3/userdata/logs/provider/events.*.log shows two session.error per turn: first is the polluted agent, second is the generic UnknownError.
  • projection_threads.model_selection_json polluted for 3 threads:
{"instanceId":"opencode","model":"opencode-go/mimo-v2.5","options":[{"id":"agent","value":"\u001b]0;imbios: ready\u0007build"}]}
  • Repro: opencode agent list 2>&1 | cat -v → ^[]0;tmp: ready^Gbuild (primary) even with env -i PATH=... opencode agent list and TERM=dumb — opencode binary itself leaks, not shell/ghostty.
  • Also 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,270 parseModelsCliOutput/parseAgentListCliOutput assumed clean stdout. No strip of OSC ESC ]...BEL / CSI ESC[...m.

Fix

See PR from fork (ImBIOS#2 merged to ImBIOS:main, will open upstream PR). Summary:

  • packages/shared/src/stripTerminalEscapes.ts: shared stripTerminalEscapes/sanitizeTerminalValue
  • opencodeRuntime.ts: strip before parseModels/Agent/Skills, defensive at entry
  • OpenCodeProvider.ts: sanitize inventory agent names/variants + --version parsing
  • OpenCodeAdapter.ts + OpenCodeTextGeneration.ts: sanitize stored agent/variant before session.promptAsync
  • packages/shared/src/model.ts: sanitize persisted option values and model slugs on read (repairs polluted threads without DB migration)
  • Tests: regression cases for OSC/ANSI in both parsers

Upstream

Should be fixed in sst/opencode as well: CLI should write OSC title to /dev/tty/stderr only when isTTY, not stdout pipe. T3 fix is defensive regardless.

Repro steps

  1. opencode agent list | cat -v shows OSC prefix
  2. Start T3 server, no external opencode server → loadInventoryFromCli stores polluted agent
  3. New thread → send → fails with UnknownError stack

Expected

Clean agent inventory, no OSC leak.

Activity

ImBIOS commented on Aug 23, 2026

@ImBIOS
Author

📦 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 test

Option 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 gh

Patch 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.

added 2 commits that reference this issue on Aug 25, 2026
3831898
7a9f868

t3dotgg commented on Aug 27, 2026

@t3dotgg
Member

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions