SpyBara
Go Premium

plugins/mods/gallery.md 2026-10-01 23:59 UTC to 2026-10-02 03:00 UTC

This page contains 435 additions and 0 deletions.

2026
Fri 2 03:59

Galería de interfaz para mods

Consulta los elementos de interfaz que puede dibujar un mod de Claude Code, como texto, botones, campos, Markdown, código y diffs, con código de ejemplo y capturas de pantalla de la terminal.

Un mod dibuja su interfaz a partir de elementos: texto, cajas, botones, campos y algunos que dan formato al contenido por ti. Los ejemplos de esta página muestran el código que dibuja un elemento, y la mayoría incluyen una captura de pantalla del resultado en un panel de la terminal, para que puedas elegir un elemento según su apariencia.

Para aprender cómo funciona el dibujo, empieza con Dibujar en la interfaz. Para las props principales y qué aplicaciones dibujan cada elemento, consulta la referencia de elementos. Las declaraciones de tipos enumeran todas las props.

Prueba un ejemplo

Los ejemplos de esta página son fragmentos, no mods completos. Cada uno es el código de un elemento y de todo lo que está anidado dentro de él.

Para ver un ejemplo en tu propia terminal, crea el pequeño mod de estos pasos y pega el ejemplo en él. El mod agrega un comando /gallery que abre un panel y dibuja el ejemplo allí. Un panel es una barra lateral junto a la transcripción en una terminal ancha a pantalla completa, o una región enmarcada sobre el prompt en caso contrario.

1

Crea el mod

Crea un directorio llamado gallery con los directorios .claude-plugin y hooks dentro. Crear un mod explica los archivos.

Guarda el manifiesto como gallery/.claude-plugin/plugin.json:

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

Indica tu punto de entrada en gallery/hooks/hooks.json:

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

Guarda el código como gallery/hooks/register.js. Agrega un comando /gallery que abre un panel y dibuja Plain text en ese panel:

// 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

Ejecuta el mod

En tu shell, inicia Claude Code desde el directorio que contiene gallery:

claude --plugin-dir ./gallery

En el prompt de Claude Code, ejecuta /gallery. Se abre un panel con Plain text.

3

Cambia a otro ejemplo

Copia un ejemplo de esta página. En register.js, pégalo sobre Text({ children: ['Plain text'] }), de modo que quede después de return, y guarda el archivo. Claude Code recarga el módulo cada vez que guardas, así que ejecuta /gallery de nuevo para ver el nuevo ejemplo.

Elige un elemento

Los ejemplos están agrupados según lo que quieras mostrar en pantalla:

Mostrar texto

Tres elementos ponen palabras en pantalla: Text para tus propios estilos, Markdown para contenido que ya tiene formato y Link para una URL.

`Text`

Text dibuja una cadena con los estilos que le des. Este ejemplo muestra una línea para cada estilo:

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 panel con nueve líneas de texto, cada una nombrada según su estilo: plain, bold, italic, underline, strikethrough, dimColor en gris, inverse, color red y backgroundColor blue. Un panel con nueve líneas de texto, cada una nombrada según su estilo: plain, bold, italic, underline, strikethrough, dimColor en gris, inverse, color red y backgroundColor blue.

dimColor dibuja el texto en gris. backgroundColor rellena solo el ancho del texto.

`Markdown`

Markdown da formato al texto de la misma manera que se formatean las respuestas de Claude. Pasa el contenido en text, no en 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 panel con un encabezado en negrita, Release notes, luego una oración con una palabra en negrita y una palabra de código en color, una lista de dos elementos y una cita dibujada en cursiva con una barra a su izquierda. Un panel con un encabezado en negrita, Release notes, luego una oración con una palabra en negrita y una palabra de código en color, una lista de dos elementos y una cita dibujada en cursiva con una barra a su izquierda.

Un encabezado se dibuja en negrita sin sus marcas #. El código en línea se dibuja en color sin sus comillas invertidas. Una cita se dibuja en cursiva con una barra a su izquierda.

Link dibuja una etiqueta seguida de su URL:

Link({ href: 'https://code.claude.com/docs', label: 'Claude Code docs' })
Un panel con una línea: la etiqueta Claude Code docs y luego la URL en gris. Un panel con una línea: la etiqueta Claude Code docs y luego la URL en gris.

La terminal dibuja la URL como texto después de la etiqueta. Que un clic la abra depende de la terminal del usuario.

Mostrar código y cambios

Code dibuja texto fuente con los colores de sintaxis propios de Claude Code, o un diff.

`Code`

Indica el language, o pasa una path para que Claude Code lo infiera a partir de ella. Con startLine, las líneas se numeran a partir de ese número:

Code({
  language: 'javascript',
  startLine: 1,
  source: "const name = 'mods'\nconsole.log('hello ' + name)",
})
Un panel con dos líneas numeradas de JavaScript con colores de sintaxis. Un panel con dos líneas numeradas de JavaScript con colores de sintaxis.

Los colores provienen del tema del usuario.

`Code` como diff

Con format: 'diff', source es uno o más fragmentos 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.',
})
Un panel con un diff de cuatro líneas. La línea eliminada está sombreada en rojo y la línea agregada en verde, cada una con su número de línea. En la línea agregada, las palabras that runs code tienen un sombreado más intenso. Un panel con un diff de cuatro líneas. La línea eliminada está sombreada en rojo y la línea agregada en verde, cada una con su número de línea. En la línea agregada, las palabras that runs code tienen un sombreado más intenso.

Claude Code dibuja números de línea en lugar de la línea @@. Cuando una línea eliminada y una línea agregada se parecen, las palabras que cambiaron reciben un sombreado más intenso.

Organizar elementos

`Box`

Box dispone lo que contiene en una fila o una columna, y puede dibujar un borde. Este ejemplo coloca una fila de palabras encima de una caja con borde:

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 panel con tres palabras en una fila, separadas por cuatro columnas, luego una fila en blanco y luego un borde redondeado alrededor de una línea de texto. El borde ocupa todo el ancho del panel. Un panel con tres palabras en una fila, separadas por cuatro columnas, luego una fila en blanco y luego un borde redondeado alrededor de una línea de texto. El borde ocupa todo el ancho del panel.

El borde se extiende hasta el ancho del panel.

Recibir entrada

Button, Input y Select son controles: el usuario se mueve entre ellos con Tab y usa el que tiene el foco. Foco del teclado y teclas de acceso rápido explica qué teclas les llegan.

Abrir un panel con focus: true le da el foco del teclado al panel. Las letras escritas llegan a un Input una vez que tiene el foco, así que agrega autoFocus: true a un campo que deba recibir lo que se escribe en cuanto se abre el panel.

`Button`

Un botón ejecuta onPress. Este ejemplo muestra la forma predeterminada, un botón plain con una tecla de acceso rápido y uno atenuado:

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 panel con tres botones, uno por línea: Save entre corchetes, n: Next sin corchetes y con la n en color, y Skip entre corchetes en gris. Un panel con tres botones, uno por línea: Save entre corchetes, n: Next sin corchetes y con la n en color, y Skip entre corchetes en gris.

Un botón que tiene el foco se dibuja en video inverso. Aquí el usuario ha presionado Tab dos veces:

Los mismos tres botones, con el segundo, n: Next, dibujado en video inverso. Los mismos tres botones, con el segundo, n: Next, dibujado en video inverso.

`Input`

Un Input es un campo de texto de una línea que ejecuta onSubmit cuando el usuario presiona Enter:

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

Sin el foco, el campo muestra su etiqueta y su texto de marcador de posición:

Un panel con una línea: la etiqueta Title y luego el marcador de posición Type a title and press Enter en gris. Un panel con una línea: la etiqueta Title y luego el marcador de posición Type a title and press Enter en gris.

Con el foco, la etiqueta se pone en negrita, aparece un cursor y el submitLabel se muestra después de ⏎:

El mismo campo con su etiqueta en negrita, un cursor de bloque sobre la primera letra del marcador de posición y un signo de retorno seguido de la palabra save. El mismo campo con su etiqueta en negrita, un cursor de bloque sobre la primera letra del marcador de posición y un signo de retorno seguido de la palabra save.

Al escribir, se reemplaza el marcador de posición:

El mismo campo con las letras escritas Rel, seguidas del signo de retorno y la palabra save. El mismo campo con las letras escritas Rel, seguidas del signo de retorno y la palabra save.

`Select`

Un Select permite al usuario elegir una de varias opciones y ejecuta onSelect con el value de la opción:

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

Cerrado, muestra su etiqueta y la opción actual:

Un panel con una línea: la etiqueta Format, la opción actual Markdown y una pequeña flecha hacia abajo. Un panel con una línea: la etiqueta Format, la opción actual Markdown y una pequeña flecha hacia abajo.

Abierto, enumera sus opciones y marca una:

El selector abierto, con sus tres opciones enumeradas debajo de la etiqueta. La segunda opción, HTML, está dibujada en video inverso. El selector abierto, con sus tres opciones enumeradas debajo de la etiqueta. La segunda opción, HTML, está dibujada en video inverso.

Después de que el usuario elige una opción, la lista se cierra:

El selector cerrado de nuevo, que ahora muestra HTML como la opción actual. El selector cerrado de nuevo, que ahora muestra HTML como la opción actual.

Dibujar imágenes

`Raster`

Un Raster es una cuadrícula de celdas de caracteres de colores, para un mapa de calor, un minigráfico o un tablero de juego. La terminal lo dibuja. Este ejemplo usa la función cellsOf del módulo inicial, que empaqueta las celdas en la cadena que recibe un Raster. Dibujar una cuadrícula de celdas de colores lo explica:

Raster({
  key: 'grid',
  columns: 3,
  rows: 2,
  cells: cellsOf([
    [['█', 0x2e7d32], ['█', 0xf9a825], ['█', 0xc62828]],
    [['█', 0x2e7d32], ['█', 0x2e7d32], ['█', 0xf9a825]],
  ]),
})
Un panel con una pequeña cuadrícula de bloques de colores, dos filas de tres: verde, ámbar y rojo, y luego verde, verde y ámbar. Un panel con una pequeña cuadrícula de bloques de colores, dos filas de tres: verde, ámbar y rojo, y luego verde, verde y ámbar.

Un Raster redondea cada color a una paleta más pequeña, así que 0x2e7d32 se dibuja como #337733.

`Svg`

Un Svg dibuja un documento SVG en la aplicación de escritorio:

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

En la terminal, un panel que devuelve solo un Svg se abre vacío. Para dibujar otra cosa allí, revisa e.surface y devuelve un árbol diferente.

`Image` y `Client`

Hay dos elementos más que no tienen ejemplo aquí. Image dibuja un PNG o píxeles sin procesar en la terminal. Client es una región que dibuja un segundo archivo tuyo, para animación y entrada del puntero. La referencia de elementos enumera sus props.

Descubre dónde puede dibujar un mod

Todos los ejemplos dibujan en un panel. Un mod también puede dibujar en otros lugares y llamar a Claude Code para que muestre algo por él:

Próximos pasos