SpyBara
Go Premium

plugins/mods/gallery.md 2026-11-10 21:57 UTC to 2026-11-11 22:59 UTC

No changes for this document in this history range.

2026

Galleria dell'interfaccia per i mod

Scopri gli elementi dell'interfaccia che un mod di Claude Code può disegnare, come testo, pulsanti, campi, Markdown, codice e diff, con codice di esempio e screenshot del terminale.

Un mod disegna la sua interfaccia a partire da elementi: testo, riquadri, pulsanti, campi e alcuni elementi che formattano il contenuto al posto tuo. Gli esempi qui mostrano il codice che disegna un elemento, e la maggior parte è accompagnata da uno screenshot del risultato in un riquadro del terminale, così puoi scegliere un elemento in base al suo aspetto.

Per capire come funziona il disegno, inizia da Disegnare nell'interfaccia. Per le prop principali e per sapere quali app disegnano ciascun elemento, consulta il riferimento degli elementi. Le dichiarazioni dei tipi elencano tutte le prop.

Prova un esempio

Gli esempi in questa pagina sono frammenti, non mod completi. Ognuno è il codice di un elemento e di tutto ciò che è annidato al suo interno.

Per vedere un esempio nel tuo terminale, crea il piccolo mod seguendo questi passaggi e incollaci l'esempio. Il mod aggiunge un comando /gallery che apre un riquadro e vi disegna l'esempio. Un riquadro è una barra laterale accanto alla trascrizione in un terminale a schermo intero sufficientemente largo, oppure, negli altri casi, un'area delimitata sopra il prompt.

1. Crea il mod

Crea una directory chiamata gallery con le directory .claude-plugin e hooks al suo interno. Crea un mod spiega i file.

Salva il manifest come gallery/.claude-plugin/plugin.json:

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

Indica il tuo punto di ingresso in gallery/hooks/hooks.json:

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

Salva il codice come gallery/hooks/register.js. Aggiunge un comando /gallery che apre un riquadro e disegna Plain text in quel riquadro:

// 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. Esegui il mod

Nella tua shell, avvia Claude Code dalla directory che contiene gallery:

claude --plugin-dir ./gallery

Al prompt di Claude Code, esegui /gallery. Si apre un riquadro con Plain text al suo interno.

3. Sostituisci con un esempio

Copia un esempio da questa pagina. In register.js, incollalo al posto di Text({ children: ['Plain text'] }), in modo che segua return, e salva il file. Claude Code ricarica il modulo ogni volta che salvi, quindi esegui di nuovo /gallery per vedere il nuovo esempio.

Scegli un elemento

Gli esempi sono raggruppati in base a ciò che vuoi mostrare sullo schermo:

Mostrare testo

Tre elementi mettono parole sullo schermo: Text per uno stile personalizzato, Markdown per contenuti già formattati e Link per un URL.

Text

Text disegna una stringa con gli stili che gli assegni. Questo esempio mostra testo semplice e otto stili, uno per riga:

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'"] }),
  ],
})

Un riquadro con nove righe di testo, ciascuna chiamata con il nome del proprio stile: plain, bold, italic, underline, strikethrough, dimColor in grigio, inverse, color red e backgroundColor blue.

dimColor disegna il testo in grigio. backgroundColor riempie solo la larghezza del testo.

Markdown

Markdown formatta il testo nello stesso modo in cui vengono formattate le risposte di Claude. Passa il contenuto in text, non in 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',
})

Un riquadro con un titolo in grassetto, Release notes, seguito da una frase con una parola in grassetto e una parola di codice colorata, un elenco di due voci e una citazione in corsivo con una barra alla sua sinistra.

Un titolo viene disegnato in grassetto senza i simboli #. Il codice inline viene disegnato a colori senza i backtick. Una citazione viene disegnata in corsivo con una barra alla sua sinistra.

Link disegna un'etichetta seguita dal suo URL:

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

Un riquadro con una riga: l'etichetta Claude Code docs, seguita dall'URL in grigio.

Il terminale disegna l'URL come testo dopo l'etichetta. Il fatto che un clic lo apra dipende dal terminale dell'utente.

Mostrare codice e modifiche

Code disegna il testo sorgente con i colori di sintassi propri di Claude Code, oppure un diff. Nell'estensione VS Code, Code mostra il suo source come testo semplice, senza i colori, i numeri di riga o l'ombreggiatura del diff visibili in questi screenshot.

Code

Specifica il language, oppure passa un path da cui Claude Code possa dedurlo. Con startLine, le righe vengono numerate a partire da quel numero:

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

Un riquadro con due righe numerate di JavaScript con i colori di sintassi.

I colori provengono dal tema dell'utente.

Code come diff

Con format: 'diff', source è costituito da uno o più hunk di diff unificato:

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.',
})

Un riquadro con un diff di quattro righe. La riga rimossa è ombreggiata in rosso e quella aggiunta in verde, ciascuna con il proprio numero di riga. Nella riga aggiunta, le parole that runs code hanno un'ombreggiatura più intensa.

Claude Code disegna i numeri di riga al posto della riga @@. Quando una riga rimossa e una riga aggiunta sono simili, le parole modificate ricevono un'ombreggiatura più intensa.

Disporre gli elementi

Box

Box dispone ciò che contiene in una riga o in una colonna e può disegnare un bordo. Questo esempio posiziona una riga di parole sopra un riquadro con bordo:

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'"] })],
    }),
  ],
})

Un pannello con tre parole in una riga, distanziate di quattro colonne, poi una riga vuota, poi un bordo arrotondato attorno a una riga di testo. Il bordo si estende per l'intera larghezza del pannello.

Il bordo si estende fino alla larghezza del pannello.

Ricevere input

Button, Input e Select sono controlli: l'utente si sposta tra di essi con Tab e usa quello che ha il focus. Focus della tastiera e tasti di scelta rapida spiega quali tasti li raggiungono.

Apri un pannello con focus: true per richiedere il focus della tastiera. Le lettere digitate raggiungono un Input una volta che questo ha il focus. Per scegliere quale campo ha il focus all'apertura del pannello, consulta Impostare un tasto di scelta rapida e il primo focus.

Button

Un pulsante esegue onPress. Questo esempio mostra la forma predefinita, un pulsante plain con un tasto di scelta rapida e uno attenuato:

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 }),
  ],
})

Un pannello con tre pulsanti, uno per riga: Save tra parentesi quadre, n: Next senza parentesi e con la n colorata, e Skip tra parentesi quadre in grigio.

Un pulsante che ha il focus viene disegnato in video inverso. Qui l'utente ha premuto Tab due volte:

Gli stessi tre pulsanti, con il secondo, n: Next, disegnato in video inverso.

Input

Un Input è un campo di testo che per impostazione predefinita contiene una riga ed esegue onSubmit quando l'utente preme Enter:

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

Senza il focus, il campo mostra la sua etichetta e il suo placeholder:

Un pannello con una riga: l'etichetta Title, poi il placeholder Type a title and press Enter in grigio.

Con il focus, l'etichetta diventa in grassetto, compare un cursore e il submitLabel viene mostrato dopo ⏎:

Lo stesso campo con l'etichetta in grassetto, un cursore a blocco sulla prima lettera del placeholder e un simbolo di invio seguito dalla parola save.

Digitando, il placeholder viene sostituito:

Lo stesso campo contenente le lettere digitate Rel, seguite dal simbolo di invio e dalla parola save.

Imposta rows a 2 o più per un campo che contiene più righe, come una nota o un messaggio di commit:

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

Il terminale e l'app Desktop disegnano le righe. Nell'estensione VS Code, il campo contiene una sola riga. rows richiede Claude Code v2.1.301 o versioni successive. Nelle versioni precedenti il campo contiene una sola riga.

Il campo occupa il numero di righe che imposti, anche quando è vuoto, fino all'altezza del pannello o della fascia in cui è disegnato. Mentre il campo ha il focus, il testo più lungo scorre al suo interno.

  • Nel terminale, Enter continua a inviare. Lì, l'utente inizia una nuova riga digitando una barra rovesciata e poi premendo Enter, oppure premendo Shift+Enter dove l'emulatore di terminale lo supporta. Sono gli stessi tasti del prompt.
  • Nel terminale, Su e Giù si spostano tra le righe del campo. Dalla prima e dall'ultima riga si spostano al controllo precedente o successivo.
  • onSubmit e onInput ricevono l'intero testo con le righe unite da \n.

Select

Un Select permette all'utente di scegliere una tra diverse opzioni ed esegue onSelect con il value dell'opzione:

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
  },
})

Chiuso, mostra la sua etichetta e l'opzione corrente:

Un pannello con una riga: l'etichetta Format, l'opzione corrente Markdown e una piccola freccia verso il basso.

Aperto, elenca le sue opzioni e ne evidenzia una:

Il selettore aperto, con le sue tre opzioni elencate sotto l'etichetta. La seconda opzione, HTML, è disegnata in video inverso.

Dopo che l'utente ha scelto un'opzione, l'elenco si chiude:

Il selettore di nuovo chiuso, che ora mostra HTML come opzione corrente.

Disegnare immagini

Raster

Un Raster è una griglia di celle di caratteri colorate, per una mappa di calore, una sparkline o una plancia di gioco. Lo disegna il terminale. Questo esempio usa la funzione cellsOf del modulo iniziale, che comprime le celle nella stringa accettata da un Raster. Disegnare una griglia di celle colorate la spiega:

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

Un riquadro con una piccola griglia di blocchi colorati, due righe da tre: verde, ambra e rosso, poi verde, verde e ambra.

Un Raster arrotonda ogni colore a una tavolozza più ridotta, quindi 0x2e7d32 viene disegnato come #337733.

Svg

Un Svg disegna un documento SVG nell'app Desktop e nell'estensione 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>',
})

Nel terminale, un riquadro che restituisce solo un Svg si apre vuoto. Per disegnare qualcos'altro lì, controlla e.surface e restituisci un albero diverso.

Image e Client

Altri due elementi non hanno un esempio qui. Image disegna un PNG o pixel grezzi nel terminale. Client è una regione disegnata da un tuo secondo file, per animazioni e input del puntatore. Il riferimento degli elementi elenca le loro prop.

Un Image viene disegnato come immagine in questi terminali:

  • kitty 0.28 o successivo
  • Ghostty
  • iTerm2 3.5 o successivo. Il disegno in iTerm2 richiede Claude Code v2.1.305 o successivo.

In qualsiasi altro terminale, l'utente vede il testo alt dell'Image, attenuato, al posto dell'immagine. Scrivi un testo alt che si regga da solo, perché viene mostrato anche in questi casi, tra gli altri:

  • GNU screen: una sessione eseguita all'interno di screen, in qualsiasi terminale.
  • tmux: una sessione eseguita all'interno di tmux che non soddisfa un requisito per disegnare all'interno di tmux.
  • Sessioni in background: ogni sessione in background, qualunque sia il terminale da cui è collegata.
  • iTerm2 al di fuori del rendering a schermo intero: in iTerm2 l'immagine viene disegnata solo con il rendering a schermo intero, e non mentre CLAUDE_CODE_ALT_SCREEN_FULL_REPAINT è impostata su 1. Per vedere l'immagine, esegui /tui fullscreen nel prompt di Claude Code e lascia quella variabile non impostata.
  • Un percorso di file come sorgente in iTerm2 o tmux: in iTerm2 e all'interno di tmux, un Image la cui source indica un file mostra il testo alt al posto dell'immagine. Se il tuo mod ha utenti iTerm2 o tmux, passa l'immagine in base64 in source.png o source.rgba anziché come percorso in source.file.

Se gli utenti del tuo mod vedono il testo attenuato in un terminale che disegna immagini del protocollo grafico di kitty con segnaposto Unicode, possono impostare CLAUDE_CODE_FORCE_TERMINAL_IMAGES su 1. Non dovrebbero impostarla all'interno di GNU screen, all'interno di tmux precedente alla 3.3, in un popup di tmux o con l'opzione allow-passthrough di tmux disattivata. In questi casi non vedono alcuna immagine e compare un riquadro al posto del testo alt.

Disegnare un Image all'interno di tmux

Se un Image mostra il suo testo alt all'interno di tmux, verifica questi requisiti insieme agli altri casi del testo alt, come una sessione in background:

  • Claude Code v2.1.310 o successivo
  • tmux 3.3 o successivo
  • Claude Code viene eseguito in un riquadro di tmux, non in un popup di tmux
  • tmux viene eseguito all'interno di kitty 0.28 o successivo, Ghostty o iTerm2 3.5 o successivo
  • Le opzioni di tmux focus-events e allow-passthrough sono impostate su on. All'interno di kitty o Ghostty, allow-passthrough può anche essere all.
  • All'interno di iTerm2, tmux viene eseguito senza -CC, il rendering a schermo intero è attivo e CLAUDE_CODE_ALT_SCREEN_FULL_REPAINT non è impostata.
  • All'interno di iTerm2, la finestra di tmux non è più grande della finestra di iTerm2. Per verificarlo, esegui tmux display-message -p '#{window_bigger}' in quella finestra di tmux. Se stampa 1, adatta la finestra di tmux, poi riavvia Claude Code.
  • L'autore del mod passa l'immagine come byte png o rgba, non come percorso file. Se usi un mod che non hai scritto tu e gli altri requisiti sono soddisfatti, chiedi al suo autore di verificare questo.

Per ogni opzione di tmux che non è già impostata come richiesto, esegui il relativo comando nella tua shell:

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

Poi scollegati da tmux, ricollegati e riavvia Claude Code. Riavvialo di nuovo ogni volta che colleghi tmux da un terminale diverso. Per mantenere entrambe le opzioni tra i riavvii del server tmux, aggiungi entrambe le righe anche a ~/.tmux.conf.

Scopri dove un mod può disegnare

Gli esempi disegnano tutti in un pannello. Un mod può anche disegnare in altri punti e chiamare Claude Code perché mostri qualcosa al posto suo:

Passaggi successivi