Communitygithub.com

Lev-it/lev-skills

Renderizador de terminal para json-render que transforma especificações JSON em UIs de terminal interativas. Use ao trabalhar com @json-render/ink, construir UIs de terminal a partir de JSON, criar catálogos de componentes de terminal ou renderizar especificações geradas por IA no terminal.

O que é lev-skills?

Este skill fornece um renderizador de terminal Ink para o ecossistema @json-render/ink, permitindo que desenvolvedores convertam especificações JSON em árvores de componentes de terminal interativas. Ele suporta componentes padrão (como Box, Text, Heading, Table, Tabs, TextInput, etc.), vinculação de dados, visibilidade condicional, ações dinâmicas e expressões de propriedades dinâmicas. O skill é útil para construir UIs de terminal a partir de especificações geradas por IA, criar catálogos de componentes de terminal e renderizar especificações JSON de forma progressiva por meio de streams JSONL. Ele funciona com React Ink e fornece APIs tanto de baixo nível (Renderer, definições de catálogo) quanto de alto nível (createRenderer, useUIStream). O ecossistema inclui provedores para estado, ações, visibilidade, validação e foco, além de suporte para armazenamento de estado externo no modo controlado.

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

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

@json-render/ink

Renderizador de terminal Ink que converte especificações JSON em árvores de componentes de terminal interativas com componentes padrão, vinculação de dados, visibilidade, ações e propriedades dinâmicas.

Início 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";

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

// Registrar apenas componentes personalizados (os padrão são embutidos)
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>
  );
}

Estrutura da Especificação (Mapa de Elementos Plano)

O esquema Ink usa um mapa de elementos plano com uma chave raiz:

{
  "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": "Olá do terminal!" },
      "children": []
    }
  }
}

Componentes Padrão

Layout

  • Box - Contêiner de layout Flexbox (como um <div> no terminal). Use para agrupamento, espaçamento, bordas, alinhamento. O flexDirection padrão é row.
  • Text - Saída de texto com estilo opcional (cor, negrito, itálico, etc.)
  • Newline - Insere linhas em branco. Deve estar dentro de um Box com flexDirection column.
  • Spacer - Espaço vazio flexível que se expande ao longo do eixo principal.

Conteúdo

  • Heading - Título de seção (h1: negrito+sublinhado, h2: negrito, h3: negrito+escurecido, h4: escurecido)
  • Divider - Separador horizontal com título centralizado opcional
  • Badge - Rótulo inline colorido (variantes: default, info, success, warning, error)
  • Spinner - Spinner de carregamento animado com rótulo opcional
  • ProgressBar - Barra de progresso horizontal (0-1)
  • Sparkline - Gráfico inline usando caracteres Unicode de bloco
  • BarChart - Gráfico de barras horizontal com rótulos e valores
  • Table - Dados tabulares com cabeçalhos e linhas
  • List - Lista com marcadores ou numerada
  • ListItem - Linha de lista estruturada com título, subtítulo, texto inicial/final
  • Card - Contêiner com borda e título opcional
  • KeyValue - Exibição de par chave-valor
  • Link - URL clicável com rótulo opcional
  • StatusLine - Mensagem de status com ícone colorido (info, success, warning, error)
  • Markdown - Renderiza texto markdown com estilização de terminal

Interativos

  • TextInput - Campo de entrada de texto (eventos: submit, change)
  • Select - Menu de seleção com navegação por setas (evento: change)
  • MultiSelect - Seleção múltipla com espaço para alternar (eventos: change, submit)
  • ConfirmInput - Prompt de confirmação Sim/Não (eventos: confirm, deny)
  • Tabs - Navegação por abas com teclas de seta esquerda/direita (evento: change)

Condições de Visibilidade

Use visible em elementos para mostrar/esconder com base no estado. Sintaxe: { "$state": "/caminho" }, { "$state": "/caminho", "eq": valor }, { "$state": "/caminho", "not": true }, { "$and": [cond1, cond2] } para E, { "$or": [cond1, cond2] } para OU.

Expressões de Propriedades Dinâmicas

Qualquer valor de propriedade pode ser uma expressão orientada por dados resolvida no momento da renderização:

  • { "$state": "/state/key" } - lê do modelo de estado (leitura unidirecional)
  • { "$bindState": "/caminho" } - vinculação bidirecional: use na propriedade de valor natural de componentes de formulário
  • { "$bindItem": "campo" } - vinculação bidirecional a um campo de item repetido
  • { "$cond": <condição>, "$then": <valor>, "$else": <valor> } - valor condicional
  • { "$template": "Olá, ${/nome}!" } - interpola valores de estado em strings

Os componentes não usam uma propriedade statePath para vinculação bidirecional. Use { "$bindState": "/caminho" } na propriedade de valor natural.

Sistema de Eventos

Os componentes usam emit para disparar eventos nomeados. O campo on do elemento mapeia eventos para ligações de ações:

CustomButton: ({ props, emit }) => (
  <Box>
    <Text>{props.label}</Text>
    {/* emit("press") dispara a ação vinculada em on.press da especificação */}
  </Box>
),
{
  "type": "CustomButton",
  "props": { "label": "Enviar" },
  "on": { "press": { "action": "submit" } },
  "children": []
}

Ações Embutidas

setState, pushState e removeState são embutidas e tratadas automaticamente:

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

Repetição (Listas Dinâmicas)

Use o campo repeat em um elemento contêiner para renderizar itens de um array de estado:

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

Dentro de filhos repetidos, use { "$item": "campo" } para ler do item atual e { "$index": true } para o índice atual.

Streaming

Use useUIStream para renderizar progressivamente especificações a partir de streams de patch JSONL:

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

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

Geração de Prompt no Lado do Servidor

Use a exportação ./server para gerar prompts de sistema de IA a partir do seu catálogo:

import { catalog } from "./catalog";

const systemPrompt = catalog.prompt({ system: "Você é um assistente de terminal." });

Provedores

ProvedorPropósito
StateProviderCompartilha estado entre componentes (caminhos JSON Pointer). Aceita propriedade store opcional para modo controlado.
ActionProviderLida com ações despachadas através do sistema de eventos
VisibilityProviderHabilita renderização condicional baseada no estado
ValidationProviderValidação de campos de formulário
FocusProviderGerencia foco entre componentes interativos
JSONUIProviderProvedor combinado para todos os contextos

Armazenamento Externo (Modo Controlado)

Passe um StateStore para StateProvider (ou JSONUIProvider) para usar gerenciamento de estado externo:

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

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

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

store.set("/count", 1); // React re-renderiza automaticamente

Quando store é fornecido, initialState e onStateChange são ignorados.

createRenderer (API de Nível Superior)

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

const InkRenderer = createRenderer(catalog, {
  ...standardComponents,
  // substituições de componentes personalizados aqui
});

// InkRenderer inclui todos os provedores (estado, visibilidade, ações, foco)
render(
  <InkRenderer spec={spec} state={{ activeTab: "overview" }} />
);

Exportações Principais

ExportaçãoPropósito
defineRegistryCria um registro de componentes type-safe a partir de um catálogo
RendererRenderiza uma especificação usando um registro
createRendererNível superior: cria um componente com provedores embutidos
JSONUIProviderProvedor combinado para todos os contextos
schemaEsquema de mapa de elementos planos Ink (inclui ações de estado embutidas)
standardComponentDefinitionsDefinições de catálogo para todos os componentes padrão
standardActionDefinitionsDefinições de catálogo para ações padrão
standardComponentsImplementações de componentes pré-construídos
useStateStoreAcessa o contexto de estado
useStateValueObtém um único valor do estado
useBoundPropVinculação bidirecional para expressões $bindState/$bindItem
useActionsAcessa o contexto de ações
useActionObtém uma única função de despacho de ação
useOptionalValidationVariante que não lança exceções de useValidation
useUIStreamTransmite especificações de um endpoint de API
createStateStoreCria um StateStore em memória independente de framework
StateStoreInterface para conectar gerenciamento de estado externo
ComponentsMapa de componentes tipado (ciente do catálogo)
ActionsMapa de ações tipado (ciente do catálogo)
ComponentContextContexto de componente tipado (ciente do catálogo)
flatToTreeConverte mapa de elementos plano em estrutura de árvore

Diretrizes de Design de UI para Terminal

  • Use Box para layout (flexDirection, padding, gap). O flexDirection padrão é row.
  • Largura do terminal é de ~80-120 colunas. Prefira layouts verticais (flexDirection: column) para estrutura principal.
  • Use borderStyle em Box para agrupamento visual (single, double, round, bold).
  • Use cores de terminal nomeadas: red, green, yellow, blue, magenta, cyan, white, gray.
  • Use Heading para títulos de seção, Divider para separar seções, Badge para status, KeyValue para dados rotulados, Card para grupos com borda.
  • Use Tabs para UIs de múltiplas visões com condições de visibilidade no conteúdo filho.
  • Use Sparkline para tendências inline e 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.

Habilidades Relacionadas