Composer redesign: goal, harness, and controls

Fourteen designs for the new message composer, plus three designs for the combined Harness & Model picker, a full goal lifecycle, and the OpenCode story. Phones are 390px wide and a fixed height, so every pixel the composer takes is honest. Everything is clickable where it says so: effort cycles, menus open.

What must fit

Goal, always visibleWhen a /goal is active you can see what it is, how it's going, and why it isn't done yet. You can edit or clear it in one tap.
Live statusFrom B3: working time, the current step, and a jump back to live. Stop is always one tap away.
Harness & Model buttonOne button showing the harness logo and model name. It opens harness, model, effort, context window, and agent. The standalone agent and context-window selectors go away.
Effort, quickChanging effort takes one tap, without opening the picker.
Approvals, quickOne tap away, amber when elevated. It opens a menu rather than cycling, so you can't land on Full access by accident.
AttachFiles, photos, and camera, plus @ files and / commands. Setting a goal also lives here.

What a goal actually is

Researched against the Claude Code docs (code.claude.com/docs/en/goal) and the installed SDK 0.3.280.

HarnessNative goal?What a UI can read
ClaudeYes. /goal <condition>, /goal for status, /goal clearactive_goal message: condition, iterations (turns checked), set_at, tokens_at_start, last_reason. null when cleared. After each turn a small model decides not yet, met, or impossible. Catch: the type is not in the public query() union, so we need to verify at runtime that we receive it.
OpenCodeNo. Request #27167 is open. Only community plugins exist.Nothing native. See OpenCode for options, including conduit running the goal loop itself.
Codex (precedent)Yes, plus pause / resumeNot a conduit harness. It's the reason pause shows up in one design.

So the goal UI has these fields to show: condition, elapsed, checks, tokens, last reason, and the outcome: achieved, impossible, or cleared. The goal colour is violet throughout, so it never reads as working (amber), ask (pink), or elevated (amber).

Best

These build on B3 and keep today's layout recognisable. Each one puts the goal in a different place relative to the composer.

A1 · Dock+

best

B3's live header, with the goal as a second line inside it. Both status lines share one hairline-divided header, so the composer reads as a single object. The footer holds attach, the Harness & Model button, a one-tap effort meter, approvals, and send. Tap the goal line to open its receipt.

Working 38m 12s· Running pnpm acceptance:visual↓ live
All 38 acceptance scenarios pass6 checks
Reply to steer the agent…
Opus 5 Ask
Goalpursuing
All 38 acceptance scenarios pass on two consecutive runs of pnpm acceptance:visual.
Last check · 2m ago · not yet35 of 38 pass. phone-transcript-scrolling still fails at the jump-to-live step.
38m elapsed6 checks1.24M tokens
EditClear goal
Working 38m 14s· Running pnpm acceptance:visual↓ live
All 38 acceptance scenarios pass6 checks
Reply to steer the agent…
Opus 5 Edits
Desktop · steering while workingsend + stop
Working 38m 12s· Running pnpm acceptance:visual↓ live
All 38 acceptance scenarios pass on two consecutive runs of pnpm acceptance:visual6 checks · 38m · last: 35 of 38 pass
Skip the mutation run, the visual gate is enough here
Opus 51M Ask
Goal lives
Header line 2, violet target, with a check count on the right.
Height cost
+22px while a goal is active. Nothing extra when none is set.
Effort
The meter chip cycles on tap: Low → Medium → High → Max. Try it.
Stop / send
Empty and working shows stop. Typing adds send (steer) next to it.
Strength
Closest to B3, which you liked. The why-not-yet reason is one tap away.
Risk
The header grows to 3 lines if subagent or drift banners also stack there.

A2 · Folder tabs

best

Goal and live status sit in two tabs on the composer's top edge: goal on the left, working on the right. They cost almost no height and read as labels on the composer rather than another bar. The Harness & Model button is split: the left half opens the picker, the right half cycles effort.

38 scenarios pass· 638mpnpm acceptance…
Reply to steer the agent…
Opus 5 Ask
Goal met · 52m · 9 checksIdle · 2m ago
Ask anything. / for commands, @ for files
Opus 5 Ask
Desktop · working with goaltabs widen to full text
All 38 acceptance scenarios pass on two consecutive runs· 6 checks · not yet: 35 of 38Working 38m 12s· pnpm acceptance:visual ↓
Reply to steer the agent…
Opus 51M · build Ask
Goal lives
The left tab. It turns green with a receipt when the goal is met and red when it's impossible.
Height cost
+22px, whether or not a goal is set, because the status tab is always there.
Effort
The right half of the split button. The picker still has the full list.
Strength
It looks distinctive, and the outcome stays visible after the run ends.
Risk
At 390px the goal text truncates hard. Tabs also need care in light mode.

A3 · Status island

best

The status leaves the composer and floats above it as a black pill, like the iPhone's Dynamic Island. It shows the timer and the goal's check count. Tap it and it grows into a live card with the step, goal, reason, stop, and clear. The composer shrinks to a one-line capsule with icon-only effort, approvals, and harness.

38:126 checks
Steer… O5
Working38:14
Running pnpm acceptance:visual · 41 tools · 3 edits
Goal6 checks · 1.24M tok

All 38 acceptance scenarios pass on two consecutive runs.

Not yet · 35 of 38 pass. phone-transcript-scrolling fails at jump-to-live.
↓ Jump to liveClear goal■ Stop
Steer… O5
Goal lives
In the island: a check count at rest, the full card on tap.
Height cost
0px. The island floats over the transcript's bottom fade.
Effort / approvals
Icon-only: the meter bars and the shield, amber when elevated. Desktop shows labels.
Strength
The most room for the transcript on a phone, and it feels premium and native.
Risk
The island covers the last line of the transcript. Icon-only approvals are less legible for new users.

A4 · Meta line

best

A calm, pro-tool look. The composer is only the text field, attach, and send. Status and goal read like plain text above it, and every setting reads like plain text below it: opus-5 · high · ask · 42%. Each word is its own tap target, which suits a monospace UI and sits closest to a terminal prompt.

Working 38m 12s· Running pnpm acceptance:visual↓ live
All 38 acceptance scenarios pass35/38 · 6 checks
Reply to steer the agent…
opus-5· · ask· 42% goal
Working 38m 15s· Running pnpm acceptance:visual↓ live
All 38 acceptance scenarios pass35/38 · 6 checks
Reply to steer the agent…
opus-5· high· ask· 42% goal
Desktop · elevated approvals, context highamber words, not boxes
All 38 acceptance scenarios pass on two consecutive runs of pnpm acceptance:visualnot yet: 35 of 38 · 6 checks · 38m · 1.24M tok
Also run the Linux baselines before you call it done
claude/opus-5· high· 1M· build· full access· 81% ctx ⏎ send · ⇧⏎ newline
Goal lives
Plain text above the composer. A violet "goal" token below it opens the receipt. With no goal, the token reads "+ goal".
Height cost
+18px per live line and +26px for the meta line.
Effort
Tap the "high" word to cycle it. Try it.
Strength
The densest and most honest layout: every setting is visible as text, with nothing hidden in icons.
Risk
Tap targets are words, and some are under 44px tall. The rows need padding to be thumb-safe.

Middle

These go further from today's layout. Each one tests a single idea: a scrollable chip tray, a goal border, a pinned goal card, a keyboard toolbar, or moving the goal to the top bar.

B1 · Chip tray

middle

Every control is a labelled pill in one row you can swipe sideways, with send pinned at the end. The goal is the first pill when one is active. Nothing is icon-only and nothing needs a second tap to read. Attach opens a sheet of big tiles, and "Set goal" is one of them.

38m 12s· Running pnpm acceptance:visual↓
Reply to steer the agent…
35/38 · 6 Opus 5 Ask Attach

Add to message

Attach
Photos
Camera
Files
Mention file
Command
Set goal
Goal lives
The first pill: 35/38 · 6. Tap it for the receipt. It isn't there when no goal is set.
Height cost
+20px status line. The tray replaces today's footer.
Strength
You can scan every label and it's easy to extend. Chips can be long-pressed to reorder or pin.
Risk
Chips past the fold (Attach here) are easy to miss, and horizontal scroll conflicts with the swipe-back gesture.

B2 · Goal border

middle

An active goal gives the composer itself a violet edge and a small label on its border. You can tell a goal is running from across the room, at zero height cost. The footer is icon-dense: the effort bars sit inside the Harness & Model button and are their own tap target. Approvals is a shield with a tiny caption.

goal · 6 checks · 38m
Reply to steer the agent…
Opus 5 ask
goal impossible · 44m
The checker says this can't be metTwo consecutive runs need the Linux baselines, and this machine can't render them.
Edit goalDismiss
Ask anything…
Opus 5 edits
Goal lives
The composer's border and its label. Violet while pursuing, red when impossible, green for a moment when met.
Height cost
+9px for the label.
Strength
Strongest ambient signal. The goal is part of the composer rather than a line beside it.
Risk
The edge fights the focus ring. Icon-only approvals rely on a 7.5px caption.

B3 · Pinned goal card

middle

The goal gets its own small card pinned above the composer, holding the condition, a pass-rate bar, and the checker's reason. Treat it as the mission and the composer as the conversation. When the keyboard opens, the card shrinks to a one-line pill so typing space wins.

Goal · check 6⌄
All 38 acceptance scenarios pass, twice in a row
not yet · 35 of 3838m · 1.24M tok
Working 38m 12s· pnpm acceptance:visual↓ live
Reply to steer the agent…
Opus 5 Ask
All 38 scenarios pass35/38
Leave the mutation run for later, just the visual gate
Opus 5 High Ask
Goal lives
Its own card above the composer. It becomes a pill while typing and a green receipt when met.
Height cost
+84px open, +30px as a pill. That's the most of any design here.
Pass-rate bar
Only when the reason contains a count (35 of 38). Otherwise it's one segment per check.
Strength
The clearest mental model: the goal is a separate thing from the chat.
Risk
Parsing a count out of free-text reasons is guesswork, so the bar may lie. It also takes vertical space.

B4 · Keyboard accessory

middle

The composer changes shape with focus. At rest it's one capsule. The harness logo sits inside an orbit ring that spins while the goal is being pursued. When you tap to type, every control moves to a toolbar docked on the keyboard, the way iOS Notes and Things do it. Controls are there when your thumbs are down and gone when you're reading.

38m · pnpm acceptance:visual◎ 35/38
Reply to steer Opus 5…
Use the Linux runner for the baselines
Opus 5 Ask 6
Goal lives
At rest, the spinning orbit plus a small count. Focused, a goal chip on the keyboard toolbar.
Height cost
The smallest here at rest (≈64px total). Focused, it costs the toolbar height.
Strength
Reading gets the whole screen, and every control is within thumb reach while typing.
Risk
You can't check or change approvals without focusing the field. iOS's visual-viewport quirks need care. Desktop needs its own layout.

B5 · Top-bar goal

middle

The goal belongs to the session, so it lives under the session title. The Harness & Model button moves to the top-right as a pill, because a harness is chosen per session and rarely per message. The composer keeps only per-message things: attach, effort, approvals, send. Pull down on the title for the goal receipt.

‹
Green acceptance suiteAll 38 scenarios pass · 35/38 · check 6
Opus 5
Working 38m 12s· pnpm acceptance:visual↓ live
Reply to steer the agent…
Ask
‹
Green acceptance suiteAll 38 scenarios pass · 35/38 · check 6
Opus 5

All 38 acceptance scenarios pass on two consecutive runs of pnpm acceptance:visual.

Check 6, 2m ago: not yet. phone-transcript-scrolling fails at jump-to-live. · 38m · 1.24M tokens
EditClearHistory ›
Working 38m 14s· pnpm acceptance:visual↓ live
Reply to steer the agent…
High Ask
Goal lives
The subtitle under the session title. It pulls down into a receipt.
Height cost
+16px in the top bar. The composer gets shorter.
Strength
Clean separation: session-level settings on top, per-message ones at the bottom.
Risk
Your eyes live at the bottom, so the top goes unnoticed. Conduit's session bar already has a view switcher competing for that row.

Wild

Riskier ideas: a shell-prompt breadcrumb, a radial long-press fan, a swipeable control deck, the goal filling the empty composer, and a timeline of the goal's checks.

C1 · Prompt line

wild

The settings become a powerline-style shell prompt: opus-5 ❯ high ❯ ask ❯ ◎ 35/38. Tap a segment and the prompt line turns into that setting's options. Pick one and it snaps back. Conduit is monospace and terminal-flavoured, so this leans into that.

38m 12s· pnpm acceptance:visual↓ live
opus-5highask35/38 · 6
❯steer the agent…
@ files · / commands
38m 14s· pnpm acceptance:visual↓ live
effort ❯lowmediumhighmaxesc
❯steer the agent…
tap to cycle
Goal lives
The last prompt segment. Tap it for the receipt, shown inline in the same way.
Height cost
+24px for the prompt line, and the footer shrinks.
Strength
One visual grammar for every setting, and very on-brand.
Risk
The harness choice has too many options to fit inline, so it needs the sheet anyway. The chevron segments crowd at 390px.

C2 · Long-press fan

wild

The composer is a pill with one big harness button. Tap it for the full Harness & Model sheet. Press and hold it for a radial fan: effort on the inner ring, approvals on the outer ring. Slide to one and let go, the way you'd pick an emoji reaction. A violet pip on the logo means a goal is active.

38m · pnpm acceptance:visual◎ goal · check 6
Steer Opus 5 · high · ask
L M H X Plan Ask Edits Auto Full Never
Slide and releaseInner ring: effort.
Outer ring: approvals.

Tap the logo instead for harness, model, context, and agent.
Steer Opus 5 · high · ask
Goal lives
A pip on the logo plus the status line. Tapping the status opens the receipt.
Height cost
The smallest composer here (≈54px).
Strength
Changing effort and approvals together is one gesture, and it's delightful once learned.
Risk
You'd never discover it without teaching. Long-press conflicts with text selection. There's no hover equivalent on desktop.

C3 · Control deck

wild

The composer's bottom half is a pager: Model · Effort · Access · Goal. Swipe sideways between them. Every page is one full-width control with thumb-sized segments, so nothing is a 24px chip. The tab labels double as a readout of the current settings.

38m 12s· pnpm acceptance:visual↓ live
Reply to steer the agent…
✳ Opus 5EffortAsk◎ Goal
LowMediumHighMax
38m 14s· pnpm acceptance:visual↓ live
Reply to steer the agent…
✳ Opus 5HighAsk◎ Goalcheck 6

All 38 acceptance scenarios pass, twice in a row

Not yet · 35 of 38. phone-transcript-scrolling fails at jump-to-live.
EditHistoryClear
Goal lives
Its own page, and the tab label glows violet while it's active.
Height cost
+76px. You could collapse the deck to just its tab row (+28px) with a flick.
Strength
The best thumb ergonomics here: big targets, and one gesture reaches everything.
Risk
It's heavy for the common case of just typing. Swiping inside the composer fights iOS's back gesture.

C4 · Goal as canvas

wild

When a goal is active and you haven't started typing, the empty composer shows the goal instead of placeholder text, with the checker's latest reason under it. The moment you type, it gets out of the way. This costs no extra space, because an empty composer is wasted space anyway. The right-hand phone shows setting a goal: typing /goal turns the composer violet and explains what will happen.

Working 38m 12s· pnpm acceptance:visual↓ live
Goalcheck 6 · 1.24M tok
All 38 acceptance scenarios pass, twice in a row
Not yet: 35 of 38. phone-transcript-scrolling fails at jump-to-live.
Type to steer · tap goal to edit
Opus 5 Ask
Set a goalOpus keeps working until this is true. After every turn a checker reads the transcript and decides not yet, met, or impossible.
⏎ set and start · /goal clear stops it
/goal every acceptance scenario passes on two consecutive runs, including Linux baselines
Opus 5 High Ask
Goal lives
In the empty composer. Once you type, it drops to a one-line header like A1's.
Height cost
Grows the empty composer by about 50px. Nothing extra while typing.
Set flow
Works in any design: /goal gets a violet send button and a what-happens-next card.
Risk
It hides the "reply here" cue. A new user may not realise they can type over the goal.

C5 · Check timeline

wild

The goal shown as what it really is: a series of checks. Each dot is one turn the checker judged. The pulsing violet one is the check that's coming. Tap any dot to read that check's reason. It shows momentum at a glance, so you can see whether the reasons are converging or going in circles.

123456738 scenarios pass
#6 · not yet · 35 of 38 pass. phone-transcript-scrolling fails at jump-to-live.
Working 38m 12s· pnpm acceptance:visual↓ live
Reply to steer the agent…
Opus 5 Ask
12678met · 52m
Achieved after 9 checks and 1.9M tokens. “38 of 38 pass on runs 11 and 12.”
Ask anything. / for commands, @ for files
Opus 5 High Ask
Goal lives
A timeline above the composer, collapsing to its first/last dots past 8 checks.
Height cost
+60px with the reason bubble, +26px without.
Needs
Each check's reason kept, not just last_reason. Conduit would store every active_goal event, which suits the event store.
Risk
The most data-hungry design, and it's noisy for goals that finish in 1–2 checks.

Shared

These pieces work with any design above: the Harness & Model picker, every state a goal can be in, and OpenCode support.

Harness & Model picker

shared

One button, showing the harness logo and model name, holds everything we're removing from the input row: harness (including custom instances), model, effort, context window, and agent. Effort stays in here as well as in the quick chip. Three layouts:

Claude · Opus 5applies to this session

Harness
Claudepersonal
Claudework
OpenCodelocal
Model
Opus 5most capable✓
Sonnet 5faster
Opus 4.7previous
Effort
LowMedHighMax
Context window
200K1M
AgentDefault
DoneHarness & Model
HarnessClaude · personal
ModelOpus 5
EffortHigh
Context1M · 42% used
AgentDefault
Changes apply from your next message.
P3 · Desktop two-pane popoverkeyboard: ⌘M, type to filter
Harness
Claudepersonal
Claudework
OpenCodelocal
Opus 51M · ✓
Sonnet 51M
Opus 4.71M
Sonnet 4.6200K
Effort
LowMedHighMax
Context window
200K1M
Agent
Default⌄
↑↓ move←→ column⏎ applyOpus 5 · high · 1M · default
Ask anything. / for commands, @ for files
Opus 5 High Ask
P1
Everything is one tap away, with no back button. Recommended for phone. It fits in about 480px.
P2
Scales best if the model list grows long (OpenCode lists every provider's models). The cost is two taps per change.
P3
The desktop version of P1, usable entirely from the keyboard. On OpenCode, the middle column groups models by provider.
Button label
Logo plus model name only. Show context size (1M) as small grey text on desktop, and drop it on phone.

Goal lifecycle

shared

Every state a Claude goal can be in, drawn in A1's header style, though any design can use the same set. Violet means active, green means met, red means impossible, and amber means paused. The goal line never grows beyond one line plus an optional reason line, so the composer's height stays predictable.

Noneentry: + menu · /goal
Ask anything…Opus 5
Startingset, first turn running
All 38 acceptance scenarios pass, twicestarting…
Reply to steer…
Pursuingworking between checks
All 38 acceptance scenarios pass, twicecheck 6 · 38m
Reply to steer…
Checkingturn ended, checker reading
All 38 acceptance scenarios pass, twicechecking…
Reply to steer…
Not yetreason shown for 1 turn
All 38 acceptance scenarios pass, twicenot yet · 6
35 of 38 pass. phone-transcript-scrolling fails at jump-to-live.
Reply to steer…
PausedAPI error, will retry
All 38 acceptance scenarios pass, twicepaused
Rate limited. Retrying in 42s. Retry nowClear goal
Ask anything…
Achievedstays until dismissed or next send
All 38 acceptance scenarios pass, twicemet · 52m · 9 checks
“38 of 38 pass on runs 11 and 12.” DetailsDismiss
Ask anything…
Impossiblechecker gave up
Linux baselines match on this Macimpossible
Linux baselines need the Docker renderer, which isn't installed. Edit goalDismiss
Ask anything…
Clearedby /goal clear or Clear
Goal cleared after 6 checksUndo
Source
Claude sends active_goal with the goal or null. Conduit derives checking (turn ended, no update yet) and achieved/impossible (goal went null right after a reason) from the order of events.
Undo
Re-sends /goal <same condition>. The check count restarts; say so in the toast.
Paused
Claude has no pause command, only an automatic pause when an error happens. If the user asks, we could add a manual pause that clears the goal and remembers the condition (Codex has this).
Risk
active_goal isn't in the public SDK message type. Before building, confirm it actually reaches query() consumers in 0.3.280.

OpenCode support

shared

OpenCode has no goal feature (there's an open request, anomalyco/opencode#27167, and a few community plugins). The composer is identical apart from the cyan logo. The question is what happens in the goal slot.

Ask anything. / for commands, @ for files
gpt-6-sol High Ask
Working 12m 40s· bash pnpm test:unit↓ live
pnpm test:unit is greenconduitcheck 2
Reply to steer the agent…
gpt-6-sol High Ask
(a) Not supported
Show "Set goal" greyed out with "Claude only", and treat /goal as an unknown command. Ships with v1 at no cost.
(b) Conduit-run goal
Conduit stores the condition. When the session goes idle, a cheap model call judges the transcript and returns not yet, met, or impossible. On "not yet", conduit sends "Continue toward the goal: …" as the next message. The small conduit tag shows who is checking. This works for any harness, and could later replace Claude's built-in goal if we wanted identical behaviour everywhere.
(c) Community plugin
Detect a goal plugin and read its state. That ties us to someone else's format, which could change without warning. Not recommended.
Recommendation
(a) for v1, (b) as a follow-up. (b) is a real feature: it needs a loop owner, a token budget, a stop condition, and a way to survive a daemon restart. It should get its own spec, not ride along with the redesign.

Recommendation

pick

A1 Dock+ as the base, plus four pieces taken from other designs. It keeps the B3 status line you liked, adds just one line (22px) and only while a goal is active, and every control is still a single tap on phone and desktop.

Base: A1
B3's status line, the goal on line 2, and tapping the goal opens the goal details (Edit / Clear). Footer: + · logo + model · effort meter (tap to cycle) · approvals shield · send/stop.
+ B1's attach sheet
The + button opens photo, camera, file, and Set goal, so goals can be found without knowing /goal.
+ C4's set-goal flow
Typing /goal turns the send button violet and shows a one-card explainer.
+ C5's check history
Put the check timeline inside the goal details, not as a permanent rail. You get the full history without paying for the height.
+ A4's approvals menu
Each mode gets a one-line description, and elevated modes stay amber.
Picker
P1 sheet on phone, P3 popover on desktop, both built from the same parts.
Removed
AgentSelector and ContextWindowSelector leave the input row and move into the picker. The context meter stays in ContextBar.
Runner-up
B2 goal border, if you'd rather the goal be ambient (a violet frame) than a line of text. Its downside: a border can't show the reason text.

Compose your own

builder

Every design breaks down into the same parts. Pick one option per part (some parts allow several), and the panel flags anything that clashes. When you're happy, copy the request and paste it to me, and I'll render the final version in every state you leave ticked. The bold codes link back to the design they came from. It starts on my recommended mix.

Your request