Communitygithub.com

Lev-it/lev-skills

Renderizador de terminal Ink que convierte especificaciones JSON en interfaces de terminal interactivas. Útil al trabajar con @json-render/ink, crear IUs de terminal desde JSON, generar catálogos de componentes de terminal o representar especificaciones generadas por IA en la terminal.

¿Qué es lev-skills?

Este skill, denominado `@json-render/ink`, es un renderizador para terminal que transforma especificaciones JSON en árboles de componentes interactivos. Está diseñado para desarrolladores que trabajan con la biblioteca `@json-render/ink` y desean construir interfaces de terminal complejas de manera declarativa, a partir de un mapa plano de elementos JSON. Es compatible con componentes estándar como `Box`, `Text`, `Tabla`, `Gráfico de barras`, campos de entrada interactivos (`TextInput`, `Select`), y un sistema de enlace de datos bidireccional mediante `$bindState`. Además, incluye expresiones de visibilidad condicional, acciones integradas para el manejo del estado (`setState`, `pushState`, `removeState`), y soporte para renderizado progresivo a través de flujos de parches JSONL. El skill también ofrece una API servidor para generar prompts de sistema a partir del catálogo de componentes, facilitando la integración con asistentes de IA. Es útil para cualquier flujo donde se necesiten interfaces de terminal ricas y reactivas, como asistentes de IA, paneles de control en terminal, o herramientas de línea de comandos con UI completa.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Lev-it/lev-skills/tree/HEAD/.claude/skills/ink

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

@json-render/ink

Renderizador de terminal Ink que convierte especificaciones JSON en árboles de componentes de terminal interactivos con componentes estándar, enlace de datos, visibilidad, acciones y propiedades dinámicas.

Inicio Rápido

import { defineCatalog } from "@json-render/core";
import { schema } from "@json-render/ink/schema";
import {
  standardComponentDefinitions,
  standardActionDefinitions,
} from "@json-render/ink/catalog";
import { defineRegistry, Renderer, type Components } from "@json-render/ink";
import { z } from "zod";

// Crear catálogo con componentes estándar + personalizados
const catalog = defineCatalog(schema, {
  components: {
    ...standardComponentDefinitions,
    CustomWidget: {
      props: z.object({ title: z.string() }),
      slots: [],
      description: "Widget personalizado",
    },
  },
  actions: standardActionDefinitions,
});

// Registrar solo componentes personalizados (los estándar vienen integrados)
const { registry } = defineRegistry(catalog, {
  components: {
    CustomWidget: ({ props }) => <Text>{props.title}</Text>,
  } as Components<typeof catalog>,
});

// Renderizar
function App({ spec }) {
  return (
    <JSONUIProvider initialState={{}}>
      <Renderer spec={spec} registry={registry} />
    </JSONUIProvider>
  );
}

Estructura de la Especificación (Mapa Plano de Elementos)

El esquema Ink utiliza un mapa plano de elementos con una clave raíz:

{
  "root": "main",
  "elements": {
    "main": {
      "type": "Box",
      "props": { "flexDirection": "column", "padding": 1 },
      "children": ["heading", "content"]
    },
    "heading": {
      "type": "Heading",
      "props": { "text": "Dashboard", "level": "h1" },
      "children": []
    },
    "content": {
      "type": "Text",
      "props": { "text": "¡Hola desde la terminal!" },
      "children": []
    }
  }
}

Componentes Estándar

Diseño

  • Box - Contenedor de diseño Flexbox (como un <div> de terminal). Útil para agrupar, espaciar, bordes y alineación. El flexDirection por defecto es row.
  • Text - Salida de texto con estilo opcional (color, negrita, cursiva, etc.)
  • Newline - Inserta líneas en blanco. Debe estar dentro de un Box con flexDirection column.
  • Spacer - Espacio vacío flexible que se expande a lo largo del eje principal.

Contenido

  • Heading - Encabezado de sección (h1: negrita+subrayado, h2: negrita, h3: negrita+atenuado, h4: atenuado)
  • Divider - Separador horizontal con título centrado opcional
  • Badge - Etiqueta en línea de color (variantes: default, info, success, warning, error)
  • Spinner - Indicador de carga animado con etiqueta opcional
  • ProgressBar - Barra de progreso horizontal (0-1)
  • Sparkline - Gráfico en línea usando caracteres Unicode de bloque
  • BarChart - Gráfico de barras horizontal con etiquetas y valores
  • Table - Datos tabulares con encabezados y filas
  • List - Lista con viñetas o numerada
  • ListItem - Fila de lista estructurada con título, subtítulo, texto inicial/final
  • Card - Contenedor con borde y título opcional
  • KeyValue - Visualización de par clave-valor
  • Link - Enlace clickeable con etiqueta opcional
  • StatusLine - Mensaje de estado con ícono de color (info, success, warning, error)
  • Markdown - Renderiza texto Markdown con estilo de terminal

Interactivos

  • TextInput - Campo de entrada de texto (eventos: submit, change)
  • Select - Menú de selección con navegación por teclas de flecha (evento: change)
  • MultiSelect - Selección múltiple con espacio para alternar (eventos: change, submit)
  • ConfirmInput - Solicitud de confirmación Sí/No (eventos: confirm, deny)
  • Tabs - Navegación por pestañas con teclas de flecha izquierda/derecha (evento: change)

Condiciones de Visibilidad

Usa visible en los elementos para mostrar/ocultar según el estado. Sintaxis: { "$state": "/path" }, { "$state": "/path", "eq": valor }, { "$state": "/path", "not": true }, { "$and": [cond1, cond2] } para Y, { "$or": [cond1, cond2] } para O.

Expresiones de Propiedades Dinámicas

Cualquier valor de propiedad puede ser una expresión impulsada por datos resuelta en tiempo de renderizado:

  • { "$state": "/state/key" } - lee del modelo de estado (lectura unidireccional)
  • { "$bindState": "/path" } - enlace bidireccional: úsalo en la propiedad de valor natural de componentes de formulario
  • { "$bindItem": "campo" } - enlace bidireccional a un campo de elemento repetido
  • { "$cond": <condición>, "$then": <valor>, "$else": <valor> } - valor condicional
  • { "$template": "¡Hola, ${/name}!" } - interpola valores de estado en cadenas

Los componentes no usan una propiedad statePath para enlace bidireccional. Usa { "$bindState": "/path" } en la propiedad de valor natural en su lugar.

Sistema de Eventos

Los componentes usan emit para disparar eventos con nombre. El campo on del elemento mapea eventos a enlaces de acción:

CustomButton: ({ props, emit }) => (
  <Box>
    <Text>{props.label}</Text>
    {/* emit("press") dispara la acción vinculada en on.press de la especificación */}
  </Box>
),
{
  "type": "CustomButton",
  "props": { "label": "Enviar" },
  "on": { "press": { "action": "submit" } },
  "children": []
}

Acciones Integradas

setState, pushState y removeState están integradas y se manejan automáticamente:

{ "action": "setState", "params": { "statePath": "/activeTab", "value": "home" } }
{ "action": "pushState", "params": { "statePath": "/items", "value": { "text": "Nuevo" } } }
{ "action": "removeState", "params": { "statePath": "/items", "index": 0 } }

Repetición (Listas Dinámicas)

Usa el campo repeat en un elemento contenedor para renderizar elementos desde un arreglo de estado:

{
  "type": "Box",
  "props": { "flexDirection": "column" },
  "repeat": { "statePath": "/items", "key": "id" },
  "children": ["item-row"]
}

Dentro de los hijos repetidos, usa { "$item": "campo" } para leer del elemento actual y { "$index": true } para el índice actual.

Transmisión (Streaming)

Usa useUIStream para renderizar progresivamente especificaciones desde flujos de parches JSONL:

import { useUIStream } from "@json-render/ink";

const { spec, send, isStreaming } = useUIStream({ api: "/api/generate" });

Generación de Prompts del Lado del Servidor

Usa la exportación ./server para generar prompts de sistema AI desde tu catálogo:

import { catalog } from "./catalog";

const systemPrompt = catalog.prompt({ system: "Eres un asistente de terminal." });

Proveedores

ProveedorPropósito
StateProviderCompartir estado entre componentes (rutas JSON Pointer). Acepta la propiedad opcional store para modo controlado.
ActionProviderManejar acciones enviadas a través del sistema de eventos
VisibilityProviderHabilitar renderizado condicional basado en el estado
ValidationProviderValidación de campos de formulario
FocusProviderGestionar el foco en componentes interactivos
JSONUIProviderProveedor combinado para todos los contextos

Almacenamiento Externo (Modo Controlado)

Pasa un StateStore a StateProvider (o JSONUIProvider) para usar gestión de estado externa:

import { createStateStore, type StateStore } from "@json-render/ink";

const store = createStateStore({ count: 0 });

<StateProvider store={store}>{children}</StateProvider>

store.set("/count", 1); // React se vuelve a renderizar automáticamente

Cuando se proporciona store, se ignoran initialState y onStateChange.

createRenderer (API de Alto Nivel)

import { createRenderer } from "@json-render/ink";
import { standardComponents } from "@json-render/ink";
import { catalog } from "./catalog";

const InkRenderer = createRenderer(catalog, {
  ...standardComponents,
  // anulación de componentes personalizados aquí
});

// InkRenderer incluye todos los proveedores (estado, visibilidad, acciones, foco)
render(
  <InkRenderer spec={spec} state={{ activeTab: "overview" }} />
);

Exportaciones Clave

ExportaciónPropósito
defineRegistryCrear un registro de componentes con seguridad de tipos a partir de un catálogo
RendererRenderizar una especificación usando un registro
createRendererAlto nivel: crea un componente con proveedores integrados
JSONUIProviderProveedor combinado para todos los contextos
schemaEsquema de mapa plano de elementos Ink (incluye acciones de estado integradas)
standardComponentDefinitionsDefiniciones del catálogo para todos los componentes estándar
standardActionDefinitionsDefiniciones del catálogo para acciones estándar
standardComponentsImplementaciones de componentes preconstruidos
useStateStoreAcceder al contexto de estado
useStateValueObtener un valor único del estado
useBoundPropEnlace bidireccional para expresiones $bindState/$bindItem
useActionsAcceder al contexto de acciones
useActionObtener una función de despacho de acción única
useOptionalValidationVariante que no lanza excepción de useValidation
useUIStreamTransmitir especificaciones desde un endpoint de API
createStateStoreCrear un StateStore en memoria independiente del framework
StateStoreInterfaz para conectar gestión de estado externa
ComponentsMapa de componentes tipado (consciente del catálogo)
ActionsMapa de acciones tipado (consciente del catálogo)
ComponentContextContexto de componentes tipado (consciente del catálogo)
flatToTreeConvertir mapa plano de elementos a estructura de árbol

Directrices de Diseño de UI de Terminal

  • Usa Box para diseño (flexDirection, padding, gap). El flexDirection por defecto es row.
  • El ancho de la terminal es de ~80-120 columnas. Prefiere diseños verticales (flexDirection: column) para la estructura principal.
  • Usa borderStyle en Box para agrupación visual (simple, doble, redondeado, negrita).
  • Usa colores de terminal con nombre: rojo, verde, amarillo, azul, magenta, cian, blanco, gris.
  • Usa Heading para títulos de sección, Divider para separar secciones, Badge para estado, KeyValue para datos etiquetados, Card para grupos con borde.
  • Usa Tabs para UIs multivista con condiciones de visibilidad en el contenido hijo.
  • Usa Sparkline para tendencias en línea y BarChart para comparar valores.

Individual skills in this repo

This repo contains 11 individual skills — each has its own dedicated page.

Lev-it/lev-skills

Ask which skill or flow fits your situation. A router over the user-invoked skills in this repo.

Lev-it/lev-skills

Premium brand-kit image generation skill for creating high-end brand-guidelines boards, logo systems, identity decks, and visual-world presentations. Trained for minimalist, cinematic, editorial, dark-tech, luxury, cultural, security, gaming, developer-tool, and consumer-app brand systems. Optimized for intentional logo concepting, refined composition, sparse typography, strong symbolic meaning, premium mockups, art-directed imagery, and flexible grid layouts.

Lev-it/lev-skills

Compact the current conversation into a handoff document for another agent to pick up.

Lev-it/lev-skills

Interactive QA session where user reports bugs or issues conversationally, and the agent files GitHub issues. Explores the codebase in the background for context and domain language. Use when user wants to report bugs, do QA, file issues conversationally, or mentions "QA session".

Lev-it/lev-skills

Facilitate a structured sprint retrospective — what went well, what didn't, and prioritized action items with owners and deadlines. Use when running a retrospective, reflecting on a sprint, creating action items from team feedback, or learning how to run effective retros.

Lev-it/lev-skills

Review the changes since a fixed point (commit, branch, tag, or merge-base) along two axes — Standards (does the code follow this repo's documented coding standards?) and Spec (does the code match what the originating issue/PRD asked for?). Runs both reviews in parallel sub-agents and reports them side by side. Use when the user wants to review a branch, a PR, work-in-progress changes, or asks to "review since X".

Lev-it/lev-skills

Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.

Lev-it/lev-skills

Teach the user a new skill or concept, within this workspace.

Lev-it/lev-skills

Turn the current conversation into a PRD and publish it to the project issue tracker — no interview, just synthesis of what you've already discussed.

Lev-it/lev-skills

Move issues through a state machine of triage roles — categorise, reproduce, grill if needed, and write agent-ready briefs.

Lev-it/lev-skills

Create product backlog items in Why-What-Acceptance format — independent, valuable, testable items with strategic context. Use when writing structured backlog items, breaking features into work items, or using the WWA format.

Skills relacionados