SpyBara
Go Premium

plugins/mods/gallery.md 2026-10-31 23:02 UTC to 2026-11-01 23:57 UTC

No changes for this document in this history range.

2026

Galeria de interface para mods

Veja os elementos de interface que um mod do Claude Code pode desenhar, como texto, botões, campos, Markdown, código e diffs, com código de exemplo e capturas de tela do terminal.

Um mod desenha sua interface a partir de elementos: texto, caixas, botões, campos e alguns que formatam o conteúdo para você. Os exemplos aqui mostram o código que desenha um elemento, e a maioria vem com uma captura de tela do resultado em um painel do terminal, para que você possa escolher um elemento pela aparência.

Para aprender como o desenho funciona, comece com Desenhar na interface. Para as principais props e quais aplicativos desenham cada elemento, consulte a referência de elementos. As declarações de tipo listam todas as props.

Experimentar um exemplo

Os exemplos nesta página são trechos, não mods inteiros. Cada um é o código de um elemento e de tudo o que está aninhado dentro dele.

Para ver um exemplo no seu próprio terminal, crie o pequeno mod destas etapas e cole o exemplo nele. O mod adiciona um comando /gallery que abre um painel e desenha o exemplo ali. Um painel é uma barra lateral ao lado da transcrição em um terminal largo em tela cheia, ou, caso contrário, uma região emoldurada acima do prompt.

1. Criar o mod

Crie um diretório chamado gallery com os diretórios .claude-plugin e hooks dentro dele. Criar um mod explica os arquivos.

Salve o manifesto como gallery/.claude-plugin/plugin.json:

{
  "name": "gallery",
  "version": "0.1.0",
  "description": "Opens a pane that draws one sample",
  "author": { "name": "Your Name" }
}

Indique seu ponto de entrada em gallery/hooks/hooks.json:

{
  "modules": ["./register.js"]
}

Salve o código como gallery/hooks/register.js. Ele adiciona um comando /gallery que abre um painel e desenha Plain text nesse painel:

// Stands in for your own callback in the samples that take one
const noop = () => {}
// The Select sample keeps its choice here
let picked = 'md'

// The Raster sample packs its cells with this function
const DEFAULT_COLOR = 0x01000000
function cellsOf(rows) {
  const numbers = rows.flat().flatMap(([char, color]) => [char.codePointAt(0), color, DEFAULT_COLOR])
  return new Uint8Array(Uint32Array.from(numbers).buffer).toBase64()
}

export function register(on) {
  on('session.start', async ($, e, next) => {
    await $.command.register({ name: 'gallery', description: 'Open the sample pane' })
    return next(e)
  })

  on('command.run', { command: 'gallery' }, async ($) => {
    await $.ui.open({ id: 'gallery', focus: true, closeOnEscape: true })
    return {}
  })

  on('ui.render', { component: 'Pane' }, async ($, e, next) => {
    if (e.requestId !== 'gallery') return next(e)
    const { Box, Text, Button, Input, Select, Link, Markdown, Code, Raster, Svg } = $.ui.resolve(e)
    // Replace the element after return with a sample
    return Text({ children: ['Plain text'] })
  })
}

2. Executar o mod

No seu shell, inicie o Claude Code a partir do diretório que contém gallery:

claude --plugin-dir ./gallery

No prompt do Claude Code, execute /gallery. Um painel é aberto com Plain text nele.

3. Trocar por um exemplo

Copie um exemplo desta página. Em register.js, cole-o sobre Text({ children: ['Plain text'] }), de modo que ele venha depois de return, e salve o arquivo. O Claude Code recarrega o módulo cada vez que você salva, então execute /gallery novamente para ver o novo exemplo.

Escolher um elemento

Os exemplos estão agrupados pelo que você quer colocar na tela:

Mostrar texto

Três elementos colocam palavras na tela: Text para o seu próprio estilo, Markdown para conteúdo já formatado e Link para uma URL.

Text

Text desenha uma string com os estilos que você fornece. Este exemplo mostra texto simples e oito estilos, um em cada linha:

Box({
  flexDirection: 'column',
  children: [
    Text({ children: ['Plain text'] }),
    Text({ bold: true, children: ['bold'] }),
    Text({ italic: true, children: ['italic'] }),
    Text({ underline: true, children: ['underline'] }),
    Text({ strikethrough: true, children: ['strikethrough'] }),
    Text({ dimColor: true, children: ['dimColor'] }),
    Text({ inverse: true, children: ['inverse'] }),
    Text({ color: 'red', children: ["color: 'red'"] }),
    Text({ backgroundColor: 'blue', children: ["backgroundColor: 'blue'"] }),
  ],
})

Um painel com nove linhas de texto, cada uma nomeada pelo seu estilo: simples, negrito, itálico, sublinhado, tachado, dimColor em cinza, inverso, cor vermelha e backgroundColor azul.

dimColor desenha o texto em cinza. backgroundColor preenche apenas a largura do texto.

Markdown

Markdown formata o texto da mesma forma que as respostas do Claude são formatadas. Passe o conteúdo em text, não em children:

Markdown({
  text: '## Release notes\n\nThis build has **two** fixes and one `flag`:\n\n- Faster start\n- Fewer prompts\n\n> Quoted text',
})

Um painel com um título em negrito, Release notes, depois uma frase com uma palavra em negrito e uma palavra de código colorida, uma lista de dois itens e uma citação desenhada em itálico com uma barra à esquerda.

Um título é desenhado em negrito sem suas marcas #. O código inline é desenhado em cor sem seus acentos graves. Uma citação é desenhada em itálico com uma barra à esquerda.

Link desenha um rótulo seguido de sua URL:

Link({ href: 'https://code.claude.com/docs', label: 'Claude Code docs' })

Um painel com uma linha: o rótulo Claude Code docs, depois a URL em cinza.

O terminal desenha a URL como texto após o rótulo. Se um clique a abre ou não depende do terminal do usuário.

Mostrar código e alterações

Code desenha texto-fonte com as próprias cores de sintaxe do Claude Code, ou um diff. Na extensão do VS Code, Code mostra seu source como texto simples, sem nenhuma das cores, números de linha ou sombreamento de diff destas capturas de tela.

Code

Indique a language, ou passe um path para que o Claude Code a deduza. Com startLine, as linhas são numeradas a partir desse número:

Code({
  language: 'javascript',
  startLine: 1,
  source: "const name = 'mods'\nconsole.log('hello ' + name)",
})

Um painel com duas linhas numeradas de JavaScript em cores de sintaxe.

As cores vêm do tema do usuário.

Code como diff

Com format: 'diff', source é um ou mais hunks de diff unificado:

Code({
  format: 'diff',
  source: '@@ -1,3 +1,3 @@\n # Mods\n-A mod is a plugin.\n+A mod is a plugin that runs code.\n Read on.',
})

Um painel com um diff de quatro linhas. A linha removida está sombreada em vermelho e a linha adicionada em verde, cada uma com seu número de linha. Na linha adicionada, as palavras that runs code têm uma sombra mais forte.

O Claude Code desenha números de linha no lugar da linha @@. Onde uma linha removida e uma linha adicionada são parecidas, as palavras que mudaram recebem uma sombra mais forte.

Organizar elementos

Box

Box dispõe o que está dentro dele em uma linha ou em uma coluna, e pode desenhar uma borda. Este exemplo coloca uma linha de palavras acima de uma caixa com borda:

Box({
  flexDirection: 'column',
  gap: 1,
  children: [
    Box({
      flexDirection: 'row',
      columnGap: 4,
      children: [Text({ children: ['a row'] }), Text({ children: ['of three'] }), Text({ children: ['items'] })],
    }),
    Box({
      borderStyle: 'round',
      paddingX: 1,
      children: [Text({ children: ["borderStyle: 'round'"] })],
    }),
  ],
})

Um painel com três palavras em uma linha, separadas por quatro colunas, depois uma linha em branco, depois uma borda arredondada em torno de uma linha de texto. A borda ocupa toda a largura do painel.

A borda se estende até a largura do painel.

Receber entrada

Button, Input e Select são controles: o usuário se move entre eles com Tab e usa aquele que tem o foco. Foco do teclado e teclas de atalho explica quais teclas chegam até eles.

Abra um painel com focus: true para solicitar o foco do teclado para ele. As letras digitadas chegam a um Input assim que ele tem o foco. Para escolher qual campo tem o foco quando o painel abre, consulte Definir uma tecla de atalho e o primeiro foco.

Button

Um botão executa onPress. Este exemplo mostra a forma padrão, um botão plain com uma tecla de atalho e um esmaecido:

Box({
  flexDirection: 'column',
  children: [
    Button({ key: 'save', label: 'Save', onPress: noop }),
    Button({ key: 'next', label: 'Next', hotkey: 'n', plain: true, onPress: noop }),
    Button({ key: 'skip', label: 'Skip', dimColor: true, onPress: noop }),
  ],
})

Um painel com três botões, um por linha: Save entre colchetes, n: Next sem colchetes e com o n em cor, e Skip entre colchetes em cinza.

Um botão que tem o foco é desenhado em vídeo inverso. Aqui o usuário pressionou Tab duas vezes:

Os mesmos três botões, com o segundo, n: Next, desenhado em vídeo inverso.

Input

Um Input é um campo de texto que, por padrão, contém uma linha e executa onSubmit quando o usuário pressiona Enter:

Input({
  key: 'title',
  label: 'Title',
  placeholder: 'Type a title and press Enter',
  value: '',
  submitLabel: 'save',
  onSubmit: noop,
})

Sem o foco, o campo mostra seu rótulo e seu placeholder:

Um painel com uma linha: o rótulo Title, depois o placeholder Type a title and press Enter em cinza.

Com o foco, o rótulo fica em negrito, um cursor aparece e o submitLabel é exibido após ⏎:

O mesmo campo com seu rótulo em negrito, um cursor de bloco na primeira letra do placeholder e um sinal de retorno seguido da palavra save.

Digitar substitui o placeholder:

O mesmo campo contendo as letras digitadas Rel, seguidas do sinal de retorno e da palavra save.

Defina rows como 2 ou mais para um campo que contém várias linhas, como uma nota ou uma mensagem de commit:

Input({
  key: 'note',
  label: 'Note',
  placeholder: 'Write a note',
  rows: 4,
  onSubmit: noop,
})

O terminal e o aplicativo Desktop desenham as linhas. Na extensão do VS Code, o campo contém uma linha. rows requer o Claude Code v2.1.301 ou posterior. Em versões anteriores, o campo contém uma linha.

O campo ocupa a quantidade de linhas que você definir, mesmo quando está vazio, até a altura do painel ou da faixa em que é desenhado. Enquanto o campo tem o foco, textos mais longos rolam dentro dele.

  • No terminal, Enter ainda envia. Lá, o usuário inicia uma nova linha digitando uma barra invertida e depois pressionando Enter, ou pressionando Shift+Enter onde o emulador de terminal oferece suporte. São as mesmas teclas do prompt.
  • No terminal, Para cima e Para baixo movem entre as linhas do campo. A partir da primeira e da última linha, elas movem para o controle anterior ou seguinte.
  • onSubmit e onInput recebem o texto inteiro com suas linhas unidas por \n.

Select

Um Select permite que o usuário escolha uma entre várias opções e executa onSelect com o value da opção:

Select({
  key: 'format',
  label: 'Format',
  value: picked,
  options: [
    { value: 'md', label: 'Markdown' },
    { value: 'html', label: 'HTML' },
    { value: 'txt', label: 'Plain text' },
  ],
  onSelect: (value) => {
    picked = value
  },
})

Fechado, ele mostra seu rótulo e a opção atual:

Um painel com uma linha: o rótulo Format, a opção atual Markdown e uma pequena seta para baixo.

Aberto, ele lista suas opções e marca uma:

O seletor aberto, com suas três opções listadas abaixo do rótulo. A segunda opção, HTML, é desenhada em vídeo inverso.

Depois que o usuário escolhe uma opção, a lista se fecha:

O seletor fechado novamente, agora mostrando HTML como a opção atual.

Desenhar imagens

Raster

Um Raster é uma grade de células de caracteres coloridas, para um mapa de calor, um sparkline ou um tabuleiro de jogo. O terminal o desenha. Este exemplo usa a função cellsOf do módulo inicial, que empacota as células na string que um Raster recebe. Desenhar uma grade de células coloridas explica isso:

Raster({
  key: 'grid',
  columns: 3,
  rows: 2,
  cells: cellsOf([
    [['█', 0x2e7d32], ['█', 0xf9a825], ['█', 0xc62828]],
    [['█', 0x2e7d32], ['█', 0x2e7d32], ['█', 0xf9a825]],
  ]),
})

Um painel com uma pequena grade de blocos coloridos, duas linhas de três: verde, âmbar e vermelho, depois verde, verde e âmbar.

Um Raster arredonda cada cor para uma paleta menor, então 0x2e7d32 é desenhado como #337733.

Svg

Um Svg desenha um documento SVG no aplicativo Desktop e na extensão do VS Code:

Svg({
  alt: 'Three bars of rising height',
  width: 120,
  height: 60,
  source:
    '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 60"><rect x="10" y="40" width="20" height="20" fill="#2e7d32"/><rect x="50" y="25" width="20" height="35" fill="#f9a825"/><rect x="90" y="5" width="20" height="55" fill="#c62828"/></svg>',
})

No terminal, um painel que retorna apenas um Svg abre vazio. Para desenhar outra coisa ali, verifique e.surface e retorne uma árvore diferente.

Image e Client

Mais dois elementos não têm exemplo aqui. Image desenha um PNG ou pixels brutos no terminal. Client é uma região que um segundo arquivo seu desenha, para animação e entrada de ponteiro. A referência de elementos lista suas props.

Uma Image é desenhada como imagem nestes terminais:

  • kitty 0.28 ou posterior
  • Ghostty
  • iTerm2 3.5 ou posterior. Desenhar no iTerm2 requer o Claude Code v2.1.305 ou posterior.

Em qualquer outro terminal, o usuário vê o texto alt da Image, esmaecido, no lugar da imagem. Escreva um texto alt que faça sentido por si só, porque ele também aparece nestes casos, entre outros:

  • GNU screen: uma sessão executada dentro do screen, em qualquer terminal.
  • tmux: uma sessão executada dentro do tmux que não atende a um requisito para desenhar dentro do tmux.
  • Sessões em segundo plano: toda sessão em segundo plano, independentemente do terminal a partir do qual ela esteja conectada.
  • iTerm2 fora da renderização em tela cheia: no iTerm2, a imagem é desenhada apenas sob a renderização em tela cheia, e não enquanto CLAUDE_CODE_ALT_SCREEN_FULL_REPAINT estiver definida como 1. Para ver a imagem, execute /tui fullscreen no prompt do Claude Code e deixe essa variável sem definir.
  • Uma origem de caminho de arquivo no iTerm2 ou no tmux: no iTerm2 e dentro do tmux, uma Image cuja source nomeia um file mostra o texto alt em vez da imagem. Se o seu mod tiver usuários do iTerm2 ou do tmux, passe a imagem como base64 em source.png ou source.rgba em vez de como caminho em source.file.

Se os usuários do seu mod virem o texto esmaecido em um terminal que desenha imagens do protocolo gráfico do kitty com placeholders Unicode, eles podem definir CLAUDE_CODE_FORCE_TERMINAL_IMAGES como 1. Eles não devem defini-la dentro do GNU screen, dentro de um tmux anterior à versão 3.3, em um popup do tmux ou com a opção allow-passthrough do tmux desativada. Nesses casos, eles não veem nenhuma imagem e veem uma caixa no lugar do texto alt.

Desenhar uma Image dentro do tmux

Se uma Image mostrar seu texto alt dentro do tmux, verifique estes requisitos junto com os outros casos de texto alt, como uma sessão em segundo plano:

  • Claude Code v2.1.310 ou posterior
  • tmux 3.3 ou posterior
  • O Claude Code é executado em um painel do tmux, não em um popup do tmux
  • O tmux é executado dentro do kitty 0.28 ou posterior, do Ghostty ou do iTerm2 3.5 ou posterior
  • As opções do tmux focus-events e allow-passthrough estão como on. Dentro do kitty ou do Ghostty, allow-passthrough também pode ser all.
  • Dentro do iTerm2, o tmux é executado sem -CC, a renderização em tela cheia está ativada e CLAUDE_CODE_ALT_SCREEN_FULL_REPAINT não está definida.
  • Dentro do iTerm2, a janela do tmux não é maior que a janela do iTerm2. Para verificar, execute tmux display-message -p '#{window_bigger}' nessa janela do tmux. Se ele imprimir 1, ajuste a janela do tmux para caber e, em seguida, reinicie o Claude Code.
  • O autor do mod passa a imagem como bytes png ou rgba, não como um caminho file. Se você usa um mod que não escreveu e os outros requisitos são atendidos, peça ao autor que verifique este.

Para cada opção do tmux que ainda não esteja definida conforme exigido, execute o comando correspondente no seu shell:

tmux set -g allow-passthrough on
tmux set -g focus-events on

Em seguida, desconecte-se do tmux, conecte-se novamente e reinicie o Claude Code. Reinicie-o novamente sempre que conectar o tmux a partir de um terminal diferente. Para manter ambas as opções entre reinicializações do servidor tmux, adicione também as duas linhas a ~/.tmux.conf.

Ver onde um mod pode desenhar

Todos os exemplos desenham em um painel. Um mod também pode desenhar em outros lugares e chamar o Claude Code para mostrar algo por ele:

Próximos passos