Un solo comando le dio a mi agente de programación un proyecto en el que orientarse

Publicado el  · Actualizado el  · Igor Tkachenko

Un comando de terminal que lleva a tres workspaces: common, api y web

En junio añadí a OwlMeans Common el comando create-app. Quería un proyecto pequeño que pudiera pasarle a un agente de programación sin tener que explicarle antes el framework desde cero.

Common es la base de TypeScript sobre la que se construyen los proyectos de OwlMeans. El comando te da un punto de partida que se puede ejecutar y las pautas que describen sus convenciones. Tú sigues dirigiendo al agente y revisando sus cambios.

Este recorrido conserva el ejemplo de junio y toma las versiones fijadas del texto que mantenemos al día en el sitio. La organización de las pautas que verás más abajo refleja el traslado posterior a .agents/.

El proyecto de partida

Elige uno de estos comandos:

bun create @owlmeans/app my-app
# or
npm create @owlmeans/app@latest my-app
# or
npx @owlmeans/create-app@^0.1.18 my-app

Después arranca los servidores de desarrollo:

cd my-app
bun run dev          # API on :3000, web on :3001

Abre la app web y, en la pantalla Session, prueba a añadir y quitar elementos. La demo conecta un frontend con una API mediante un contrato compartido. Los datos se guardan en memoria, y basta con reiniciar el proceso para recordar por qué eso importa.

El andamiaje tiene tres workspaces:

  • common contiene las declaraciones de rutas compartidas, los esquemas de validación y los tipos.
  • api ejecuta el backend sobre @owlmeans/server-app.
  • web aporta el frontend sobre @owlmeans/web-panel.

Ese es el andamiaje mínimo de la CLI. Los proyectos que genera OwlMeans también pueden incluir una biblioteca de backend compartida y un worker. El ejemplo de la CLI no te aprovisiona ni esas piezas ni una base de datos.

El contrato de la aplicación

Quiero que un agente encuentre la declaración de una ruta buscando su alias. Y quiero poder seguir esa misma declaración yo mismo.

Common usa puntos de entrada para ese contrato. Un punto de entrada une un alias, una ruta, un método y la validación:

entrypoint(
  route(session.add, '/:sid/items', { parent: session.base, method: RouteMethod.POST }),
  filter(params(SessionParamsSchema), body(AddItemSchema)),
)

El backend le asigna un manejador con elevate. El frontend le asocia el comportamiento de la pantalla y llama al punto de entrada con ctx.entrypoint(session.add).call({ params, body }).

La ruta y el esquema son código fuente compartido. En este patrón no hay un cliente de API generado aparte. Si cambias la declaración, todavía tienes que revisar las llamadas y el manejador. Los tipos compartidos no pueden decidir si la operación debería haberse permitido.

Los servicios siguen un camino igual de visible: una fábrica crea el servicio, la aplicación lo registra con un alias y el código lo resuelve con context.service('alias').

Prefiero ese cableado porque lo puedo leer. No he medido cuánto ahorra en tokens frente a otro framework, y este ejemplo tampoco lo demuestra.

Una ilustración que contrapone el cableado implícito a las declaraciones explícitas de TypeScript

Datos persistentes

El recurso de la demo tiene métodos como create, list y delete. Los recursos respaldados por una base de datos usan la misma interfaz, así que los manejadores pueden conservar esa forma conocida.

Eso no convierte la migración a una base de datos en algo que se resuelva con un solo paquete. Sigues necesitando la configuración de la conexión, los índices, la validación y una decisión sobre los datos que ya existen. Las reglas de acceso también necesitan pruebas.

Para una nueva funcionalidad de notas, este es un encargo útil para el agente:

Añade notas persistentes guardadas en MongoDB. Usa @owlmeans/mongo y @owlmeans/mongo-resource. Declara el esquema y los puntos de entrada en sources/common, registra el recurso y los manejadores en sources/api y añade una pantalla en sources/web. Sigue las pautas instaladas sobre recursos y sobre reutilización de código.

Las llamadas al recurso pueden quedar así:

const notes = context.resource<NotesResource>(RES_NOTES)
await notes.create({ id, text, createdAt })
const { items } = await notes.list({ criteria: { ... } })

Son fragmentos de la interfaz, no una aplicación completa. El alias del recurso, el esquema y la conexión tienen que estar registrados en el proyecto.

Después del cambio, reinicia la app y comprueba que la nota sigue ahí. Prueba también con datos no válidos y con una conexión fallida. Si las notas pertenecen a distintos usuarios, comprueba que uno no puede leer las notas de otro.

La capa web usa shadcn UI y Tailwind. La documentación de shadcn explica que su enfoque consiste en darte el código fuente de los componentes para que trabajes con él. En este proyecto, el agente puede inspeccionar y editar ese código. Revisar cómo queda la interacción sigue siendo cosa tuya.

Las pautas de los paquetes

La versión de junio copiaba las pautas en directorios separados para cada agente. Más tarde eliminamos esas fuentes paralelas. Las pautas canónicas del proyecto están en .agents/, con AGENTS.md en la raíz y un puente para Claude donde hace falta.

Los paquetes de OwlMeans distribuyen sus pautas a través de agent-meta/. El instalador lee esos metadatos y escribe las habilidades de los paquetes que hay en el proyecto. Una habilidad sobre recursos puede explicar el framework; para qué sirven tus notas lo tienen que explicar las instrucciones de tu proyecto.

Después de actualizar los paquetes correspondientes, el comando que mantenemos en este recorrido es:

npx @owlmeans/agent-skills@^0.1.18

Revisa lo que muestra el instalador. Los archivos gestionados que hayas editado en local pueden entrar en conflicto, y forzar que se sobrescriban es una decisión sobre tus propios cambios. El instalador es para los proyectos que consumen los paquetes; los monorepos enlazados del framework tienen su propio flujo de mantenimiento.

La ilustración original de junio, con archivos de pautas separados para cada agente

Esta ilustración muestra la estructura de directorios de junio. Para el flujo revisado, usa la estructura compartida de .agents que se describe más arriba.

Ni AGENTS.md ni el formato Agent Skills garantizan que todas las herramientas carguen todos los archivos automáticamente. Antes de fiarte de las instrucciones, comprueba la integración del agente.

El trabajo que te queda

create-app te da el andamiaje de Common. OwlMeans añade, alrededor de esa base, un pipeline de roles de desarrollo. Son dos formas distintas de empezar a trabajar con el mismo framework.

El comando no te resuelve el modelo de datos, no prueba los permisos ni opera el servicio de producción. Que el build pase es un resultado limitado: en esta configuración, ejecuta bun run typecheck aparte de bun run build.

Hice el andamiaje para no repetir el cableado inicial. Me deja la parte en la que sí tengo que pensar: si la funcionalidad debe estar ahí y si funciona.

Publicado originalmente el 17 de junio de 2026. Revisado el 15 de octubre de 2026 con las versiones fijadas que mantenemos para los comandos y la estructura compartida de pautas para agentes.

OwlMeans