Yosegi — construyendo pantallas a partir de los componentes del anfitrión
Versión: 2026-08-13. Un arnés de agente puede cargar una copia desactualizada de una habilidad sin indicarlo. Si esta fecha es más antigua que la del archivo
skills/yosegi/SKILL.mden el repositorio, estás leyendo una copia obsoleta: vuelve a instalarla antes de continuar.
Yosegi convierte los componentes de un proyecto anfitrión en hechos con los que puedes construir una pantalla, y emite la
pantalla como una Story (CSF) para su revisión antes de implementar nada. No tiene ni un entorno de renderizado ni una GUI
propia; tú verificas el aspecto en el Storybook del anfitrión. En un anfitrión sin Storybook, el entregable se convierte en un
archivo de componente React plano (--target component) — la rama del paso 1 a continuación indica cómo cambia el procedimiento.
Este documento es el procedimiento, y tú eres quien lo lleva a cabo. La CLI (y las herramientas MCP equivalentes) son los instrumentos a los que recurre.
Cuándo usarlo
- Componer una propuesta de pantalla o maqueta de UI a partir de un sistema de diseño existente, en una forma revisable.
- Obtener un primer borrador de una nueva pantalla visible en Storybook antes de implementarla.
- Consultar qué componentes tiene un anfitrión y qué props realmente aceptan, antes de escribir cualquier UI.
- Transcribir una Story de maqueta aprobada a una página real. Realiza los pasos 1 y 2, luego salta al paso 5.
No para: cambios de componentes puntuales.
Dónde está el valor
El trabajo del registro es específico: es la fuente de verdad para las props de un componente — los nombres reales de las
props, las opciones reales de enum, cuáles son obligatorias, cuáles son slots versus children, la firma de llamada de una
prop de función. Los componentes de un anfitrión no son la biblioteca de la que se bifurcaron. Sus enums de variantes se han
renombrado, sus escalas de tamaño difieren entre hermanos, una prop de icono toma una referencia de componente en lugar de un
elemento, una prop ReactNode es un slot con nombre en lugar de children, y tres componentes diferentes comparten un nombre de
exportación. Nada de eso se puede deducir de la familiaridad con React o con la biblioteca upstream, y cada uno de esos es un
defecto que enviarás si escribes la prop que esperas en lugar de la prop que dice el registro que existe. Para eso sirven las
llamadas inspect de los pasos 1 y 2, y saltarlas es cómo una maqueta con apariencia plausible envía un defecto.
El registro no te da el esqueleto de la pantalla, el modismo de composición o el diseño — la llamada a un hook de biblioteca
de cuadrícula que impulsa un DataGrid, un meta específico del anfitrión como { stickyHeader: true }, qué wrapper espera un
componente a su alrededor. Eso proviene de las Stories propias del anfitrión y, en un anfitrión con un generador de
páginas/rutas, de sus plantillas de Ejemplo (paso 2). Cuanto más rica sea la cobertura de plantillas y Stories del anfitrión,
menor será la participación del registro en lo que realmente necesitabas para construir la pantalla — y eso no es una carencia.
El registro y los ejemplos propios del anfitrión responden preguntas diferentes, y ambos son fundamentales para la pregunta
que responden.
Referencias
Ábrelas cuando el paso siguiente te envíe a ellas, no de forma preventiva. En la ruta 3a (escribir la Story directamente),
eso puede ser nunca: registry status y la salida de component inspect más el cuerpo de este archivo suelen ser lo
suficientemente autodescriptivos para construir toda la pantalla. Sin embargo, una vez que necesites una, trabaja a partir de
ella y no solo de la memoria de este archivo — su detalle no se repite aquí.
| Archivo | Léelo |
|---|---|
references/registry.md | Cuando la salida de inspect tenga algo que no puedas interpretar — una línea shape: / signature: de una prop opaca, una prop no documentada, un especificador de importación que parezca incorrecto |
references/cli.md | Cuando un comando o flag no esté cubierto arriba, la CLI no se ejecute, o necesites los equivalentes MCP |
references/screen-json.md | Solo si tomas la ruta Screen JSON (3b). El formato, y lo que no puede expresar |
references/errors.md | En el momento en que cualquier comando imprima un error o una advertencia. Cada código y su solución |
references/implementation.md | Para la plantilla meta en el paso 3, y antes del paso 5 |
Paso 1. Construir el registro
Yosegi necesita un tsconfig.json legible del anfitrión (las props provienen de los tipos TypeScript, y eso solo es
suficiente). Storybook es donde va la Story y donde confirmas cómo se renderiza, pero no es un requisito.
Si no puedes detectar Storybook — sin directorio de configuración
.storybook/(o equivalente), sin scriptstorybooken elpackage.jsondel anfitrión, sinindex.jsonpara apuntar--index— el entregable es un archivo de componente React plano en lugar de una Story (screen generate --target component,references/cli.md). No elijas la ubicación de salida ni el método de revisión tú mismo: antes de construir nada, pregúntale al usuario (a) dónde debería ir el archivo del componente y (b) cómo quiere confirmar el resultado (renderizándolo en una ruta provisional de la aplicación anfitriona, por ejemplo). Yosegi no prescribe la superficie de revisión, y adivinar cualquiera de las dos respuestas viola la misma regla que adivinar una prop. Con esas respuestas, el procedimiento a continuación sigue siendo el mismo, con tres diferencias:registry buildse ejecuta sin--index/--storybook-url(pierdes la curación, nada más); en la ruta 3a escribes el archivo del componente en la ubicación que nombró el usuario, y en la 3b pasas--target component --out <esa ubicación>.tsx; y las comprobaciones de Storybook del paso 4 se reemplazan por la verificación de tipos del anfitrión más el método de confirmación que nombró el usuario.
- ¿Puedes ejecutar la CLI?
npx yosegi(opnpm yosegi,yarn yosegi,bunx yosegi) sin argumentos imprime todos los comandos, una vez que@yosegi/yosegiya sea una dependencia del anfitrión — instálalo primero si no lo es (references/cli.md). Node.js 20 o más reciente, anfitrión React + TypeScript. Si el comando falla, consulta "Si la CLI no se ejecuta" enreferences/cli.md; el movimiento más útil es leer<data-dir>/registry.json'sbuiltWithCliPathsi ya existe un registro de una sesión anterior. - Fija un
--data-dirahora y pásalo a cada comando. Usa.yosegibajo la raíz del paquete del anfitrión, que también es el valor predeterminado; los ejemplos a continuación aún lo escriben, porque el valor predeterminado sigue tu directorio de trabajo actual y un comando ejecutado desde otro lugar no encontrará lo que construiste. - ¿Ya hay un registro y está actualizado? Ejecuta
yosegi registry status --data-dir .yosegiprimero — recalcula la versión del registro a partir de sus propias entradas registradas e informasource: currentosource: stalecon el comando de reconstrucción exacto, en lugar de que tú verifiques el encabezado decomponent list. "Registro no encontrado" significa que es la primera ejecución. Su mitad de índice de Storybook es de mejor esfuerzo y puede informar que el índice es inalcanzable mientras el veredicto de la fuente aún se mantiene — lee esa mitad como "no se pudo verificar", no como "obsoleto" o "actualizado", y no dejes que un servidor de desarrollo inalcanzable te impida confiar en un veredicto de fuentecurrent. Reconstruye cada vez questatusinforme obsoleto, cada vez que se imprimaREGISTRY_VERSION_MISMATCH, o cada vez questatusinformesource: unknownporque el registro es anterior a las entradas registradas (built: not recorded) — no hay nada que recalcular a partir de ahí, por lo que la antigüedad es la única señal que tienes. Reconstruye también cada vez que un comando advierta que el registro fue construido por una versión diferente de Yosegi a la que estás ejecutando: un Yosegi más antiguo no puede emitir campos que este sí puede (las firmas de llamada de una prop de función, por ejemplo), y ninguna otra señal muestra esa brecha — la cadena de versión, al ser un hash de contenido, permanece idéntica, por lo que un registro reconstruido a partir de un anfitrión sin cambios mantiene la misma. El registro es una instantánea, y una obsoleta es peor que ninguna.
yosegi registry build \
--source "app/components/**/*.tsx" \
--tsconfig <host>/tsconfig.json \
--index http://localhost:6006/index.json \
--storybook-url http://localhost:6006 \
--report tmp/registry-report.json \
--data-dir .yosegi
6006 arriba es el valor predeterminado de Storybook, utilizado solo porque esta es la primera compilación y nada te ha dicho
otra cosa aún — no es necesariamente el puerto del anfitrión. Verifica el script de Storybook en el package.json del
anfitrión (o pregunta) por el puerto en el que realmente se ejecuta antes de ejecutar esto. Cada reconstrucción después de
esta primera tiene una mejor fuente que adivinar: el encabezado de component list imprime una línea rebuild: que lleva el
--storybook-url exacto con el que se construyó el registro por última vez (references/cli.md).
Las flags y valores predeterminados están en references/cli.md. --index es la única parte con un requisito previo: una
URL de servidor de desarrollo significa que el Storybook del anfitrión ya debe estar en ejecución. Sin él, pierdes las
categorías derivadas de Stories y las marcas recommended, nada más.
Lee las estadísticas que imprime:
files: 0→ el glob no coincidió con nada. El comando aún tiene éxito y escribe un registro que contiene solo los tres primitivos sintéticos, así que no leas "Wrote 3 components" como éxito.componentCandidates: 0confilespositivo, owithNodeSlots: 0con unanyShapedPropsalto → la compilación se degradó aunque tuvo éxito. El primero significa que el glob no cubrió ningún componente React; el segundo significa que@types/reactno se resolvió, por lo que cada propReactNodese aplanó ajsony no se detectaron slots. Una líneaWarning:nombra la solución en ambos casos: resuélvela y reconstruye antes de continuar.propsUnreadablealto en relación conextractedComponents→ el tsconfig probablemente sea incorrecto. Resuélvelo ahora (references/cli.md,registry metadata); un componente en ese estado rechazará props perfectamente reales más adelante.
Paso 2. Consulta cada componente que planees usar
Si una plantilla de Ejemplo de un generador de páginas/rutas es la coincidencia más cercana a la pantalla que estás construyendo, léela primero, o junto con los comandos a continuación — decide el esqueleto y el modismo de composición, y luego el registro confirma las props exactas que la plantilla deja abiertas.
yosegi component list --category app/components/ui --data-dir .yosegi
yosegi component list --query card --data-dir .yosegi
yosegi component inspect "app/components/ui/button#Button" --data-dir .yosegi
El registro puede llegar a varios cientos de entradas, así que reduce con --category / --query, orienta con el resumen,
luego inspect cada componente que vayas a escribir. inspect es autoritativo y tu conocimiento del framework no lo es.
Lee references/registry.md para saber cómo interpretar lo que te da — las opciones de enum, las líneas shape: y
signature: bajo una prop opaca, el especificador de importación que el anfitrión realmente escribe, y qué significa una
prop no documentada.
Prefiere los componentes marcados como recommended; tienen una Story propia.
Luego recopila las convenciones del anfitrión. La Story aterriza en el repositorio del anfitrión y se revisa como código del anfitrión; saltarse esto produce una UI que funciona y aún así es devuelta.
- Encuentra el contrato de datos, si ya existe uno — una definición de OpenAPI/JSON Schema, un esquema GraphQL, tipos
TypeScript escritos a mano para la respuesta de la API, cualquier forma que use la capa de datos del anfitrión. Léelo
antes de inventar datos simulados. Decide más que las props de los componentes: qué campos son obligatorios versus anulables
y qué significa nulo para un campo dado (un límite nulo puede significar "ilimitado", no "desconocido"), qué campos son
mutuamente excluyentes y — igual de útil — qué no está ahí (ningún campo de ordenación o búsqueda en el contrato significa
que la pantalla tampoco debería inventar uno). Esto es lo que convierte el mock de una propuesta de apariencia en algo que
refleja la forma real de los datos. Dónde vive varía según el anfitrión (
openapi/schemas/, un archivo.graphql, untypes.tsgenerado); encuentra el que exista para este dominio y síguelo en lugar de una suposición plausible. - Busca en el directorio de rutas/páginas del anfitrión (
app/routes/, o donde sea que sirva páginas) una pantalla existente en el mismo dominio. En un producto maduro a menudo existe una, y encontrarla puede redefinir la tarea por completo — por ejemplo, una ruta existentebookings.calendar._indexpodría convertir "hacer una pantalla de reservas" en "proponer una lista transversal contra el flujo de reservas existente". Esto determina si el mock que te pidieron es incluso lo correcto para construir, así que hazlo antes del punto de control a continuación y deja que dé forma a las preguntas que hagas allí. - Ejecuta
git statusy mira el directorio de salida antes de construir nada. Un intento anterior, sin confirmar, de la misma pantalla ya puede estar en el árbol de trabajo — común después de un reinicio de contexto y una solicitud reemitida. Concilia con él en lugar de crear un duplicado a su lado. Para rehacer un archivo que ya existe — un generador del anfitrión se niega cuando la ruta de destino existe, o un intento anterior necesita ser reemplazado — muévelo a un lado (renómbralo) en lugar de eliminarlo; la eliminación puede no estar disponible para ti, y un cambio de nombre despeja la ruta de todos modos. - Verifica si el anfitrión tiene un generador para nuevas páginas o pantallas — un generador plop/hygen, un script estilo
bun add-route, a menudo documentado en elAGENTS.mddel anfitrión o en un script depackage.json. En un anfitrión con uno, escribir un nuevo archivo de pantalla desde cero es incorrecto: el generador clona la plantilla sancionada y aplica las convenciones de archivo y nomenclatura, así que ejecútalo en lugar de crear el archivo tú mismo. Esto también resuelve la elección del paso 3 entre una Story de árbol en línea y un módulo de página más una Story wrapper delgada — un anfitrión con un generador como este casi siempre quiere lo último. - Lee
AGENTS.md/CLAUDE.mden cada nivel desde la raíz del repositorio hasta el directorio de salida, y sigue cualquier documento al que apunten. - Lee una o dos Stories existentes cerca de la ubicación de salida. Los ejemplos compuestos que combinan varios componentes
son los que vale la pena imitar para el esqueleto de la página, el espaciado y la selección de componentes. Para el
modismo de composición — cómo se ensambla realmente un componente, no solo qué props toma: la llamada al hook de biblioteca
de cuadrícula que impulsa un DataGrid, un
metaespecífico del anfitrión como{ stickyHeader: true }, el wrapper que un componente espera a su alrededor — una Story existente es la fuente de verdad, y el registro no lo es.
...