[BUG] /goal long prompt has no Show less control and hides task status/messages
Preflight Checklist
- [x] I searched existing issues for
/goal,Show less, collapse behavior, and long-prompt UI behavior. - [x] This is a single bug report.
- [ ] Exact Claude Code version is included below. It is not visible in the screenshots.
What's Wrong?
When /goal is used with a large but valid prompt, around the expected 4,000-character range, the goal prompt is rendered as a large expanded block in the conversation with no visible Show less / collapse control.
In the app UI, the long goal prompt can fill most of the viewport. New messages and status updates are pushed out of sight or appear hidden behind the prompt/input area, so the user cannot reliably tell whether Claude is still running, blocked, or completed.
Observed behavior:
- Long
/goaltext remains expanded. - No
Show lessor collapse affordance is visible for the goal prompt. - The latest activity/status is not reliably visible without scrolling/guessing.
- The input box remains visible at the bottom, but the active/completion state is obscured by the large prompt content.
What Should Happen?
Long /goal prompts should be bounded in the UI, for example by:
- rendering collapsed by default after a reasonable number of lines,
- showing
Show more/Show lesscontrols like other long content blocks, and/or - using a max-height scrollable container for the goal text.
The latest agent status/messages and completion state should remain visible or easy to reach while the goal is active.
Error Messages/Logs
No error message. This is a UI visibility/state-awareness issue.
Steps to Reproduce
- Open Claude Code in the app UI / Code tab.
- Submit a
/goalprompt with a long multi-paragraph task description, still within the expected/goalinput limit, approximately 4,000 characters. - Let the task start running.
- Observe the goal prompt block in the conversation.
- The block stays expanded with no
Show lesscontrol. - Subsequent messages/status are pushed out of view or obscured.
- The user cannot reliably tell whether the task is still running, blocked, or completed without scrolling around.
Claude Model
Not sure / Multiple models
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
Unknown from screenshot. Please advise where to capture the exact app/CLI version if needed.
Platform
Claude Code app UI / Code tab
Operating System
macOS
Terminal/Shell
Other
Additional Information
This is related to long /goal prompts, but distinct from prompt-length/evaluator errors such as #58192 and #60966. In this case, the prompt is accepted and the task may be running; the problem is that the visible UI has no collapse affordance and hides the current conversation/status behind the prompt.
Refiled from the correct GitHub account after closing #61674.
5 Comments
Seeing this exact problem in the VS Code native extension, and it is not specific to
/goal— any long pasted prompt triggers it. When I paste a multi-paragraph handoff/kickoff prompt into the chat, the user-message block expands to fill the whole panel with no collapse /Show lesscontrol, pushing Claude's responses and tool activity out of view. I cannot tell whether it is running, blocked, or done without scrolling past the giant bubble.Repro (VS Code native extension, Code tab — not the terminal CLI):
Show less, or max-height scroll container on the user message.Requested fix (same as the OP): collapse long user messages by default past N lines with
Show more/Show less, or cap them in a max-height scrollable container, so the latest assistant activity stays visible. This should apply to all long user messages, not just/goal.Platform: VS Code native extension (Code tab).
Specifically for the VS Code extension
Here's a guide I had Claude generate to fix this issue for myself locally, which looks to have worked like a charm. Hope this helps anyone else struggling with this.
Patch: "Show less" collapse for long /goal & /loop slash-command prompts
What this fixes
In the Claude Code VS Code extension, regular user messages collapse with a
"Show more" / "Show less" control once they get tall. But slash-command
prompts (e.g.
/goal,/loop) rendered through a different code path thatskipped the collapsible wrapper, so a long prompt (~4,000 chars) filled the whole
chat window and pushed task status / latest messages out of view.
Reference: GitHub issue anthropics/claude-code#61675
(
[BUG] /goal long prompt has no Show less control and hides task status/messages).The fix routes the slash-command branch through the extension's existing
collapsible component so these prompts collapse just like normal messages
(default ~60px, with Show more / Show less).
Applied successfully to versions 2.1.183 and 2.1.185.
---
File to edit
This is a minified production bundle (~4.8 MB, effectively a few enormous
lines). Editing it is surgical. Two important caveats:
...-<new version>-win32-x64)with a fresh, unpatched bundle. You must re-apply this patch in the new folder.
Only the latest installed version actually runs.
relevant names were
JQe(collapsible component),Rc(its React import),wg(its CSS-module map),qi(chat CSS-module map),ey(content renderer),and locals
S/y/o/win the message renderer. In a future buildthese letters may differ. Section "If the literal strings don't match"
below explains how to re-derive them.
---
How it works (the mechanism)
JQe, internally anExpandableContent). It measuresscrollHeight; if it exceedsmaxHeightit renders the content collapsed with a truncation gradient + a hover
"Show more" button, and a "Show less" button when expanded.
createElement(JQe,{content:y,context:o,maxHeight:60}).text with no wrapper:
case"text":if(S.isSlashCommand)return createElement("div",{className:"userMessage slashCommandMessage"...},S.text);Key subtlety:
S.textis a transformed string. The normalizer (ny)runs
w8t(rawText)which extracts<command-name>+<command-args>from theraw message. So you cannot just pass the message object
ytoJQe— itsinternal renderer (
ey) would re-render the raw XML-wrapped text. The fixtherefore feeds the already-transformed string
S.textintoJQevia a newoptional prop, instead of letting
JQerender from the message object.The patch generalizes
JQewith two optional, backward-compatible props:scChildren— a pre-rendered child (string or node) to show instead of thedefault
eyrender.scClass— extra class names applied to the inner content div (to keep theslashCommandMessagemonospace styling).When both are absent,
JQebehaves exactly as before (regular messagesunaffected).
---
The three edits (exact strings — fast path for 2.1.18x)
Edit 1 — generalize
JQe's signature + re-measure when the new child changesFind:
Replace with:
(Added
,scChildren,scClassto the destructured params, and,scChildrento the effect deps.)Edit 2 — render the optional child + extra class instead of always using
eyFind:
Replace with:
(Inserted
${scClass||""}into the className, andscChildren!=null?scChildren:before theeyelement.)Edit 3 — route the slash-command branch through
JQeFind:
Replace with:
---
Verification checklist (all should be true)
Apply / test
/goalor/loopprompt; it should render collapsed withShow more / Show less.
---
If the literal strings don't match (identifiers changed in a new build)
Re-derive the names, then adapt the three edits to the new letters.
JQeequivalent). Search the bundlefor the CSS-module marker:
``
`expandableContainer:"expandableContainer_
function XXX({content:e,context:t,maxHeight:i=250})The
immediately after itXXX.useRefis the component (note its name, its React import alias used as
,<map>.contentand the CSS-map variable used as
/<map>.collapsed`)."Show more"and"Show less"literals andcreateElement(<contentRenderer>,{content:e,context:t,plainText:!0}).That
<contentRenderer>is theeyequivalent.``
`if(S.isSlashCommand)return
S(The loop variable may not be
/w/o— read the surrounding
case"text":to see the actual locals: the parsed part, the Reactkey, andcontext`.)the
,scChildren,scClassto the component's destructured props and,scChildrento its measure-effect deps;<div>, inject${scClass||""}into the className andscChildren!=null?scChildren:before the content-renderer element;component passing
scChildren:<the transformed text>andscClass:<userMessage> <slashCommandMessage>`, pluskey/context/
maxHeight:60`.S.textequivalent, i.e. thew8t(...)-processed string). Do not pass the raw message object as thechild, or you'll render the
<command-name>/<command-args>XML.node --checkthe file and reload the window.Reproducing this today on the VS Code extension (not just the referenced surface) — confirming this is still an issue and cross-surface, not CLI-specific.
Concrete example: a
/goalprompt (~700+ words, multi-paragraph task spec with numbered scope items) was submitted. After Claude started working, the ENTIRE original/goalprompt text remained rendered at full height at the top of the visible viewport, with noShow less/collapse control anywhere on it. Below it, only a sliver of the actual conversation was visible — two collapsed "Thought for Ns" rows and a single in-progress Bash tool-call label ("Debug: why X cell not flagged"). The prompt text alone consumed roughly 80% of the visible vertical space, well after the turn had moved on to executing tool calls.What made this worse than a typical long-message case: there was no way to reclaim the space at all short of scrolling past the entire original prompt every time — no click-to-collapse, no "open in separate editor tab" option, nothing. A large pasted prompt behaves like a fixed, immovable block rather than an expandable/collapsible one the way most chat UIs (and even a plain HTML
<textarea>/expander) handle long input.Suggested behavior (beyond the collapse/
Show lessalready requested above): let a long submitted prompt behave like any other resizable input — clicking it should either (a) expand it inline to a scrollable max-height box the user can shrink back down, or (b) pop it out into a separate tab/panel for review, rather than permanently occupying primary screen real estate with the live conversation squeezed into whatever's left.Related: #66578 (two-column layout / height caps so input + long messages don't cover Claude's replies) looks like the same underlying "long content has no space-reclaiming affordance" family of issue.
Found a workaround which works for me, right after sending the /goal prompt send a simple prompt like "started?" and the following messages will push the /goal prompt upward clearing the history window.
Adding controlled measurements, because I think the "~4,000 characters" framing in this thread is a red herring. Character count is not the trigger. The trigger is whether the rendered height of the pasted block fits in the viewport.
I built a throwaway skill that ignores its argument entirely and emits one fixed marker block, so the only variable was the appearance of the input. One fresh conversation per run; I recorded only whether the marker block appeared on screen.
Environment: macOS (Darwin 25.5.0), VS Code extension 2.1.226 and 2.1.227 (both reproduce), external display, logical resolution 3008 × 1692, window maximized. The interactive terminal (2.1.220 / 2.1.227) did not reproduce, even at 9,621 characters.
1. Character and byte count are not the trigger
| chars | UTF-8 bytes | result |
| ---: | ---: | --- |
| 950 | 2,840 | visible |
| 1,400 | 4,188 | visible |
| 1,550 | 4,638 | visible |
| 2,500 | 7,488 | visible |
All single-paragraph, almost no newlines. Well past 4,000 characters and still fine.
2. Line count is the trigger — at a fixed 2,500 characters
| chars | bytes | lines | result |
| ---: | ---: | ---: | --- |
| 2,500 | 7,488 | 1 | visible |
| 2,500 | 7,360 | 60 | visible |
| 2,500 | 7,340 | 70 | visible (fit on one screen) |
| 2,500 | 7,320 | 80 | invisible |
| 2,500 | 7,158 | 160 | invisible |
Identical character count, near-identical byte count (a newline is 1 byte). The only difference is line count.
3. The real variable is viewport fit
Same payload, unchanged. I only halved the window height.
| lines | window height | fits on one screen | result |
| ---: | --- | --- | --- |
| 60 | normal | yes | visible |
| 60 | ~half | no | invisible |
The result flips with no change to the input at all. So line count was only a proxy for height. The condition is the pasted block's rendered height versus the viewport.
Additional observations
end_turn. Example: 8,345-char argument, answer received 04:35:16, response generated 04:35:21 — never displayed.Why this distinction matters for a fix
If the trigger is character count, a length cap or a collapse-at-N-characters control fixes it. If the trigger is rendered height versus viewport, then the same input can be visible on one display and invisible on another, and a character-based collapse threshold will be wrong on some window sizes. A max-height scrollable container for the pasted block — as suggested in the original report — addresses the actual variable; a character threshold does not.
Full measurement record, including the derivation of a display-line threshold used as a workaround downstream:
https://github.com/kazuyakurashima/which-model/blob/main/tests/regression/vscode-render-threshold.md
Possibly related, though I have not confirmed a shared cause: #85573 and #84065 both describe text going unrendered around
AskUserQuestionturns.