Mapa da trilha
Conteúdo detalhado
🎨 ui.render e as superfícies
O que o hook de ui.render recebe, a tabela de elementos de cada superfície e as regras de uma árvore que valida.
O hook de ui.render recebe uma instância de componente: e.component, e.surface, e.requestId, e.props e e.viewport.
Com esses campos você decide se desenha, onde desenha e do tamanho certo.
ui.render, component, surface, requestId, viewport.
O $.ui.resolve(e) devolve a tabela de construtores da superfície, que você desestrutura nas tags JSX.
O módulo não tem elementos globais; sem resolve não há Box nem Text.
$.ui.resolve, Box, Text, JSX com h.
Cada superfície tem sua tabela: o terminal não tem Svg, mas tem Raster e Image; o mobile não tem Input nem Select.
Uma árvore com elemento que a superfície não tem não é desenhada.
superfície, Elements, diferenças, narrowing por e.surface.
O hook de render lê o estado com $.state.get e nunca escreve; quem escreve é um handler ou outro evento.
Escrever ao desenhar é negado; ler assina a instância e o redesenho vem sozinho.
render puro, $.state.get, handler, redesenho.
Uma árvore que não valida não é desenhada: o engine desenha a própria e registra o motivo no log.
Saber ler essa linha poupa horas de "por que não aparece nada".
validação, ui.render refused, debug log.
Raster desenha uma grade de células coloridas; Image mostra uma figura pelo protocolo gráfico do terminal, com alt nos outros.
Gráficos e mapas de calor sem um Box por célula.
Raster, Image, $.ui.blit, alt.
📟 Faixa, status e avisos
A faixa AbovePrompt compartilhada, status, toast e log, com o exemplo oficial band.tsx dissecado.
O componente AbovePrompt é a faixa acima da caixa de prompt; o hook desenha nela com o tamanho de bodyColumns.
É o lugar de informação contínua: contadores, avisos, estado do mod.
AbovePrompt, faixa, bodyColumns.
A faixa é uma só e compartilhada: o exemplo oficial band.tsx mostra como desenhar nela sem apagar os vizinhos.
Um mod que toma a faixa inteira apaga os vizinhos.
compartilhar, next, composição.
O $.ui.status mostra um estado curto sem abrir painel e sem começar turno.
Informação discreta não precisa de tela própria.
$.ui.status, linha de status, sem turno.
O $.ui.toast dá um aviso passageiro e o $.ui.log escreve uma linha no registro, sem chamar o modelo.
Avisos certos no lugar certo, sem poluir a conversa.
$.ui.toast, $.ui.log, aviso, registro.
Ler o exemplo oficial da faixa que vem com o Claude Code: estado tipado, resolve, árvore e botão.
É o modelo mais curto e correto de faixa que existe para copiar.
examples/band.tsx, band-state.d.ts, referência oficial.
Montar a faixa num teste para terminal e desktop, com o mesmo corpo num laço.
Prova que o mod não depende de uma superfície só.
claude plugin test, mount, terminal, desktop.
🪟 Painéis e botões
Painéis abertos por comando, dimensionados pelo bodyColumns, com botões, hotkeys, campos e modo diálogo.
O $.ui.open abre um painel, o componente Pane, que o hook de ui.render desenha.
Painel é a tela própria do mod: listas, detalhes, formulários.
$.ui.open, Pane, requestId.
O painel desenha no bodyColumns, mais estreito que a tela quando fica ao lado da conversa.
Árvore dimensionada pelo viewport quebra quando o painel está encaixado.
bodyColumns, viewport, isFullscreen.
Botões com label, variant e hotkey de uma letra ou dígito, que funcionam quando o painel tem o teclado.
Atalho de uma tecla torna o painel usável sem mouse.
Button, hotkey, variant, foco.
Os handlers ficam no plugin e disparam os eventos ui.press, ui.input e ui.select com a chave do elemento.
É assim que um clique vira ação e um texto digitado vira dado.
ui.press, ui.input, ui.select, key.
Abrir o painel com focus, closeOnEscape e holdToasts faz ele se comportar como diálogo.
Diálogo prende a atenção do usuário; deixar holdToasts num painel fixo trava os avisos.
diálogo, focus, closeOnEscape, holdToasts.
Fechar o painel por botão de dispensa ou por Esc e limpar o estado ligado a ele.
Painel que não fecha ou estado que sobra confunde a próxima abertura.
role dismiss, Esc, limpeza de estado.
⌨️ Comandos, ferramentas e configuração
Comandos de barra que respondem sem modelo, ferramentas para o modelo, opções do /config e nomes sem colisão.
Registrar um comando de barra com nome e descrição, normalmente no session.start.
Comando de mod roda na hora e não precisa de modelo.
$.command.register, session.start, /comando.
Responder o evento command.run, filtrado pelo nome do comando, com { text } e, se quiser, context.
text é a linha que aparece e o modelo também lê; context só o modelo lê.
command.run, { text }, context.
Desenhar a saída do comando como árvore na conversa hookando o componente CommandOutput.
A resposta vira tabela ou card em vez de texto cru.
CommandOutput, ui.render, matcher por props.
Declarar uma ferramenta com nome, descrição e schema, servida por um hook de tool.call; ela aparece como mcp__<plugin>__<nome>.
O modelo passa a usar uma capacidade que só o seu mod oferece.
$.tool.register, tool.call, schema, mcp__plugin__nome.
Ler os valores que o usuário ajustou no /config pelo options do register, com padrões do manifesto.
Mudar uma opção recarrega o módulo; o mod nunca lê config velha.
userConfig, options, picker, /config.
Escolher nomes de comandos, ferramentas e chaves de estado que não batam com os de outros mods.
Dois mods com o mesmo comando brigam, e o usuário não sabe qual respondeu.
colisão, prefixo, nome do plugin.