[FEATURE] Cowork: draw mod UI (band, pane, spinner) like the Code tab does
Preflight Checklist
- [X] I have searched existing requests and this feature hasn't been requested yet
- [X] This is a single feature request (not multiple features)
Problem Statement
Mods are great in the CLI and the Desktop Code tab. In Cowork the hooks run, but nothing a mod draws ever shows up.
The mods docs already say cloud sessions run hooks but don't draw, so this isn't a bug report. But Cowork lives in the same desktop app that draws mods for the Code tab, and since Oct 6 Cowork on Pro/Max only runs in the cloud. So for me that's all of Cowork, which is where I spend most of my day.
What I saw in a Cowork task (Claude Code 2.1.296) with the repro below:
session.startfires and$.fs.writeworks, so the mod is loaded and running$.session.surfaces()returns[]- the
AbovePrompthook ran 0 times across 2 turns - no band, no toast, no status line
Proposed Solution
Code tab parity: AbovePrompt, Pane, Spinner, toast and status line in Cowork tasks. Raster and Image are terminal only anyway.
The mods types already describe remote surfaces drawing over the wire (ui_render), so I'm guessing some of the plumbing is there.
Alternative Solutions
- Run the mod in the Code tab or the CLI instead. Works, but it's not Cowork.
- Fall back to
$.ui.logor a command's text reply. Fine for info, useless for anything visual.
Priority
Low - Nice to have
Feature Category
Developer tools/SDK
Use Case Example
I'm building a mascot mod (a cartoon chili pepper, it's dumb, it's fun) that sits in the band above the prompt and reacts to Claude: nervous on permission prompts, facepalm when a command fails, cheering when tests pass. In Cowork it's invisible. Same deal for the boring useful stuff, like a context or rate limit band. Similar ask for the VS Code panel: #99401.
Repro plugin, hooks/register.js (passes claude plugin validate):
let renders = 0
async function save($) {
const surfaces = await $.session.surfaces()
await $.fs.write('/tmp/cowork-draw-probe.json', JSON.stringify({ surfaces, renders }))
}
export function register(on) {
on('session.start', async ($, e, next) => {
const out = await next(e)
$.ui.toast('toast works')
$.ui.status('status line works')
await save($)
return out
})
on('ui.render', { component: 'AbovePrompt' }, async ($, e, next) => {
renders += 1
await save($)
if (e.props.hasSurvey) return next(e)
const { Text } = $.ui.resolve(e)
return Text({ children: ['band works on ' + e.surface] })
})
}
- Ghostty,
claude --plugin-dir ./cowork-draw-probe(2.1.296): the band reads "band works on terminal", and the toast and status line show up. - Cowork task (2.1.296, loaded by asking Claude to write the mod into the session's mods folder and enabling hot reload): no band, no toast, no status line, and the file says
{"surfaces":[],"renders":0}.
Desktop app version: 2.31226.1