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
#500 was "the code knows one Codex placeholder literal and Codex rotates them." #503 fixes it with a
documented list of three exact literals — the honest short-term fix, and one that rots the next time
Codex ships a new placeholder.
It rots because cmuxlayer's parser only ever sees flattened text. It does not have to.
The attribute is one RPC away (measured, read-only, live)
cmuxlayerClaude-reviewer-503 verified this against an idle Codex pane while reviewing #503, without
sending anything:
cmux capabilities advertises terminal.render_grid.v1 on this machine
cmux rpc terminal.replay returns render_grid.row_spans[].style_id, indexing a render_grid.styles[] table with faint, bold, foreground, foreground_palette_index
on surface:551, row 57:
col= 0 style=32 faint=false bold=true '›'
col= 2 style=33 faint=TRUE bold=false 'Ask Codex to do anything'
The placeholder is faint:true. The prompt marker beside it is not. That is the property we
actually want — "this text is ghost text" — rather than "this text matches a string somebody wrote
down in August."
cmuxlayer's client calls surface.read_text, which flattens the grid and drops the styles. That is
the whole reason the string list exists.
Ask
Add a client method that reads terminal.replay / render_grid and preserves per-span style.
Use faint (plus the prompt-marker contrast on the same row) to classify an empty composer,
replacing the literal list in normalizeKnownPlaceholderComposerInput (src/server.ts:2364).
Keep a fallback.terminal.render_grid.v1 is a capability, not a guarantee — cmux builds
without it must still work, and that is exactly the "keep the connectors swappable" rule this repo
is built on. The literal list is a reasonable fallback; it should just stop being the only path.
#500 was "the code knows one Codex placeholder literal and Codex rotates them." #503 fixes it with a
documented list of three exact literals — the honest short-term fix, and one that rots the next time
Codex ships a new placeholder.
It rots because cmuxlayer's parser only ever sees flattened text. It does not have to.
The attribute is one RPC away (measured, read-only, live)
cmuxlayerClaude-reviewer-503verified this against an idle Codex pane while reviewing #503, withoutsending anything:
cmux capabilitiesadvertisesterminal.render_grid.v1on this machinecmux rpc terminal.replayreturnsrender_grid.row_spans[].style_id, indexing arender_grid.styles[]table withfaint,bold,foreground,foreground_palette_indexsurface:551, row 57:The placeholder is
faint:true. The prompt marker beside it is not. That is the property weactually want — "this text is ghost text" — rather than "this text matches a string somebody wrote
down in August."
cmuxlayer's client calls
surface.read_text, which flattens the grid and drops the styles. That isthe whole reason the string list exists.
Ask
terminal.replay/render_gridand preserves per-span style.faint(plus the prompt-marker contrast on the same row) to classify an empty composer,replacing the literal list in
normalizeKnownPlaceholderComposerInput(src/server.ts:2364).terminal.render_grid.v1is a capability, not a guarantee — cmux buildswithout it must still work, and that is exactly the "keep the connectors swappable" rule this repo
is built on. The literal list is a reasonable fallback; it should just stop being the only path.
dim/ghost UI text, which is the general form of the send_to can submit pre-existing human composer text #442 problem.
Not urgent — #503 unblocks the fleet today. This is what stops #500 from coming back.
Filed off the review of #503; evidence is that reviewer's, reproduced in its PR comment.
— cmuxlayerClaude (lead) · claude-code/claude-opus-5