Communitygithub.com

Lev-it/lev-skills

Moteur de rendu terminal Ink pour json-render qui transforme des spécifications JSON en interfaces utilisateur terminal interactives. À utiliser avec @json-render/ink, pour créer des IU terminal à partir de JSON, générer des catalogues de composants terminal, ou afficher des spécifications générées par IA dans le terminal.

Qu'est-ce que lev-skills ?

Ce skill fournit un moteur de rendu terminal basé sur Ink, conçu pour interpréter des spécifications JSON structurées en arbres de composants interactifs dans le terminal. Il permet aux agents IA (comme Claude Code, Cursor ou Codex) de générer et d'afficher dynamiquement des interfaces utilisateur terminal complètes, incluant des formulaires, des tableaux, des graphiques, des onglets, et bien plus. La spécification utilise un format plat d'éléments avec une clé racine, où chaque élément définit son type (parmi une bibliothèque de composants standard comme Box, Text, Input, Select, Table, etc.), ses propriétés, sa visibilité conditionnelle, et ses gestionnaires d'événements. Le système prend en charge la liaison de données bidirectionnelle, les actions intégrées (setState, pushState, removeState), les listes dynamiques via `repeat`, et le rendu progressif par flux JSONL. Il est également possible d'étendre le catalogue avec des composants et actions personnalisés tout en préservant la sécurité typage grâce à Zod. Ce skill est particulièrement utile pour les agents qui doivent présenter des résultats, des formulaires de configuration, des assistants interactifs ou des tableaux de bord directement dans le terminal, sans nécessiter de navigateur web.

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

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

@json-render/ink

Moteur de rendu terminal Ink qui convertit des spécifications JSON en arbres de composants interactifs avec composants standard, liaison de données, visibilité, actions et propriétés dynamiques.

Démarrage Rapide

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";

// Créer un catalogue avec des composants standard + personnalisés
const catalog = defineCatalog(schema, {
  components: {
    ...standardComponentDefinitions,
    CustomWidget: {
      props: z.object({ title: z.string() }),
      slots: [],
      description: "Widget personnalisé",
    },
  },
  actions: standardActionDefinitions,
});

// Enregistrer uniquement les composants personnalisés (les standard sont intégrés)
const { registry } = defineRegistry(catalog, {
  components: {
    CustomWidget: ({ props }) => <Text>{props.title}</Text>,
  } as Components<typeof catalog>,
});

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

Structure de la Spécification (Plan d'Éléments Plat)

Le schéma Ink utilise un plan d'éléments plat avec une clé racine :

{
  "root": "main",
  "elements": {
    "main": {
      "type": "Box",
      "props": { "flexDirection": "column", "padding": 1 },
      "children": ["heading", "content"]
    },
    "heading": {
      "type": "Heading",
      "props": { "text": "Tableau de bord", "level": "h1" },
      "children": []
    },
    "content": {
      "type": "Text",
      "props": { "text": "Bonjour depuis le terminal !" },
      "children": []
    }
  }
}

Composants Standard

Disposition

  • Box - Conteneur de disposition Flexbox (comme un <div> terminal). Utiliser pour le regroupement, l'espacement, les bordures, l'alignement. Par défaut, flexDirection est row.
  • Text - Sortie de texte avec style optionnel (couleur, gras, italique, etc.)
  • Newline - Insère des lignes vides. Doit être à l'intérieur d'un Box avec flexDirection column.
  • Spacer - Espace vide flexible qui s'étend le long de l'axe principal.

Contenu

  • Heading - Titre de section (h1 : gras+souligné, h2 : gras, h3 : gras+atténué, h4 : atténué)
  • Divider - Séparateur horizontal avec titre centré optionnel
  • Badge - Étiquette en ligne colorée (variantes : default, info, success, warning, error)
  • Spinner - Spinner de chargement animé avec étiquette optionnelle
  • ProgressBar - Barre de progression horizontale (0-1)
  • Sparkline - Graphique en ligne utilisant des caractères Unicode de bloc
  • BarChart - Diagramme à barres horizontal avec étiquettes et valeurs
  • Table - Données tabulaires avec en-têtes et lignes
  • List - Liste à puces ou numérotée
  • ListItem - Ligne de liste structurée avec titre, sous-titre, texte de début/fin
  • Card - Conteneur avec bordure et titre optionnel
  • KeyValue - Affichage de paire clé-valeur
  • Link - URL cliquable avec étiquette optionnelle
  • StatusLine - Message de statut avec icône colorée (info, success, warning, error)
  • Markdown - Affiche du texte Markdown avec style terminal

Interactif

  • TextInput - Champ de saisie de texte (événements : submit, change)
  • Select - Menu de sélection avec navigation par touches fléchées (événements : change)
  • MultiSelect - Sélection multiple avec espace pour basculer (événements : change, submit)
  • ConfirmInput - Invite de confirmation Oui/Non (événements : confirm, deny)
  • Tabs - Navigation par onglets avec touches fléchées gauche/droite (événements : change)

Conditions de Visibilité

Utiliser visible sur les éléments pour afficher/masquer en fonction de l'état. Syntaxe : { "$state": "/chemin" }, { "$state": "/chemin", "eq": valeur }, { "$state": "/chemin", "not": true }, { "$and": [cond1, cond2] } pour ET, { "$or": [cond1, cond2] } pour OU.

Expressions de Propriétés Dynamiques

Toute valeur de propriété peut être une expression pilotée par les données résolue au moment du rendu :

  • { "$state": "/etat/cle" } - lecture depuis le modèle d'état (lecture unidirectionnelle)
  • { "$bindState": "/chemin" } - liaison bidirectionnelle : à utiliser sur la propriété de valeur naturelle des composants de formulaire
  • { "$bindItem": "champ" } - liaison bidirectionnelle à un champ d'élément de répétition
  • { "$cond": <condition>, "$then": <valeur>, "$else": <valeur> } - valeur conditionnelle
  • { "$template": "Bonjour, ${/nom} !" } - interpolation de valeurs d'état dans des chaînes

Les composants n'utilisent pas de propriété statePath pour la liaison bidirectionnelle. Utilisez { "$bindState": "/chemin" } sur la propriété de valeur naturelle à la place.

Système d'Événements

Les composants utilisent emit pour déclencher des événements nommés. Le champ on de l'élément mappe les événements aux liaisons d'actions :

CustomButton: ({ props, emit }) => (
  <Box>
    <Text>{props.label}</Text>
    {/* emit("press") déclenche l'action liée dans on.press de la spécification */}
  </Box>
),
{
  "type": "CustomButton",
  "props": { "label": "Soumettre" },
  "on": { "press": { "action": "submit" } },
  "children": []
}

Actions Intégrées

setState, pushState et removeState sont intégrées et gérées automatiquement :

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

Répétition (Listes Dynamiques)

Utilisez le champ repeat sur un élément conteneur pour afficher les éléments d'un tableau d'état :

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

À l'intérieur des enfants répétés, utilisez { "$item": "champ" } pour lire depuis l'élément courant et { "$index": true } pour l'index courant.

Streaming

Utilisez useUIStream pour rendre progressivement des spécifications à partir de flux de correctifs JSONL :

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

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

Génération de Prompts Côté Serveur

Utilisez l'export ./server pour générer des prompts système IA à partir de votre catalogue :

import { catalog } from "./catalog";

const systemPrompt = catalog.prompt({ system: "Vous êtes un assistant terminal." });

Fournisseurs

FournisseurObjectif
StateProviderPartager l'état entre les composants (chemins JSON Pointer). Accepte une propriété store optionnelle pour le mode contrôlé.
ActionProviderGérer les actions déclenchées via le système d'événements
VisibilityProviderActiver le rendu conditionnel basé sur l'état
ValidationProviderValidation des champs de formulaire
FocusProviderGérer le focus entre les composants interactifs
JSONUIProviderFournisseur combiné pour tous les contextes

Store Externe (Mode Contrôlé)

Passez un StateStore à StateProvider (ou JSONUIProvider) pour utiliser une gestion d'état externe :

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

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

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

store.set("/count", 1); // React se re-rend automatiquement

Lorsque store est fourni, initialState et onStateChange sont ignorés.

createRenderer (API de plus Haut Niveau)

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

const InkRenderer = createRenderer(catalog, {
  ...standardComponents,
  // remplacements de composants personnalisés ici
});

// InkRenderer inclut tous les fournisseurs (état, visibilité, actions, focus)
render(
  <InkRenderer spec={spec} state={{ activeTab: "aperçu" }} />
);

Exports Clés

ExportObjectif
defineRegistryCréer un registre de composants typé à partir d'un catalogue
RendererRendre une spécification à l'aide d'un registre
createRendererPlus haut niveau : crée un composant avec fournisseurs intégrés
JSONUIProviderFournisseur combiné pour tous les contextes
schemaSchéma de plan d'éléments plat Ink (inclut les actions d'état intégrées)
standardComponentDefinitionsDéfinitions du catalogue pour tous les composants standard
standardActionDefinitionsDéfinitions du catalogue pour les actions standard
standardComponentsImplémentations de composants pré-construites
useStateStoreAccéder au contexte d'état
useStateValueObtenir une seule valeur de l'état
useBoundPropLiaison bidirectionnelle pour les expressions $bindState/$bindItem
useActionsAccéder au contexte d'actions
useActionObtenir une fonction de dispatch d'action unique
useOptionalValidationVariante non bloquante de useValidation
useUIStreamStreamer des spécifications à partir d'un point de terminaison API
createStateStoreCréer un StateStore en mémoire indépendant du framework
StateStoreInterface pour brancher une gestion d'état externe
ComponentsCarte de composants typée (tenant compte du catalogue)
ActionsCarte d'actions typée (tenant compte du catalogue)
ComponentContextContexte de composant typé (tenant compte du catalogue)
flatToTreeConvertir un plan d'éléments plat en structure arborescente

Directives de Conception d'IU Terminal

  • Utiliser Box pour la disposition (flexDirection, padding, gap). Par défaut, flexDirection est row.
  • La largeur du terminal est d'environ 80 à 120 colonnes. Privilégier les dispositions verticales (flexDirection: column) pour la structure principale.
  • Utiliser borderStyle sur Box pour le regroupement visuel (single, double, round, bold).
  • Utiliser des couleurs terminal nommées : red, green, yellow, blue, magenta, cyan, white, gray.
  • Utiliser Heading pour les titres de section, Divider pour séparer les sections, Badge pour le statut, KeyValue pour les données étiquetées, Card pour les groupes encadrés.
  • Utiliser Tabs pour les IU à plusieurs vues avec conditions de visibilité sur le contenu enfant.
  • Utiliser Sparkline pour les tendances en ligne et BarChart pour comparer des valeurs.

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 associés