Ein Befehl, und mein Coding-Agent hatte ein Projekt, in dem er sich zurechtfand

Veröffentlicht am  · Aktualisiert am  · Igor Tkachenko

Ein Terminalbefehl, aus dem drei Workspaces entstehen: common, api und web

Im Juni habe ich OwlMeans Common um den Befehl create-app ergänzt. Ich wollte ein kleines Projekt, das ich einem Coding-Agenten übergeben kann, ohne ihm vorher das Framework von Grund auf zu erklären.

Common ist das TypeScript-Fundament unter den OwlMeans-Projekten. Der Befehl gibt dir einen lauffähigen Ausgangspunkt und die Anweisungen, die seine Konventionen beschreiben. Du steuerst den Agenten aber weiterhin selbst und prüfst, was er ändert.

Für diesen Rundgang habe ich das Beispiel vom Juni behalten, dazu die gepinnten Versionen aus der gepflegten Fassung der Website. Bei der Ablage der Anweisungen weiter unten ist der spätere Umzug nach .agents/ schon berücksichtigt.

Das Startprojekt

Wähle einen der Befehle:

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

Starte dann die Entwicklungsserver:

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

Öffne die Web-App, füge auf dem Session-Bildschirm testweise ein paar Einträge hinzu und entferne sie wieder. Die Demo verbindet ein Frontend über einen gemeinsamen Vertrag mit einer API. Ihre Daten liegen im Arbeitsspeicher. Ein Neustart des Prozesses genügt, und du weißt wieder, warum das wichtig ist.

Das Gerüst besteht aus drei Workspaces:

  • common enthält gemeinsame Routendeklarationen, Validierungsschemas und Typen.
  • api betreibt das Backend auf Basis von @owlmeans/server-app.
  • web liefert das Frontend auf Basis von @owlmeans/web-panel.

So sieht das minimale Gerüst aus der CLI aus. Projekte, die OwlMeans generiert, können zusätzlich eine gemeinsame Backend-Bibliothek und einen Worker enthalten. Das CLI-Beispiel richtet dir beides nicht ein, eine Datenbank ebenso wenig.

Der Vertrag der Anwendung

Ein Agent soll eine Routendeklaration finden, indem er nach ihrem Alias sucht. Und ich will dieselbe Deklaration selbst nachvollziehen können.

Common nutzt für diesen Vertrag Entrypoints. Ein Entrypoint verbindet einen Alias, einen Pfad, eine Methode und die Validierung:

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

Das Backend hängt mit elevate einen Handler an. Das Frontend hängt das Verhalten seiner Bildschirme an und ruft den Entrypoint über ctx.entrypoint(session.add).call({ params, body }) auf.

Route und Schema sind gemeinsamer Quellcode. Einen eigenen generierten API-Client gibt es in diesem Muster nicht. Änderst du die Deklaration, musst du trotzdem die Aufrufer und den Handler prüfen. Ob die Operation überhaupt erlaubt sein sollte, können gemeinsame Typen nicht entscheiden.

Bei Services ist der Weg ähnlich gut sichtbar. Eine Factory erzeugt den Service, die Anwendung registriert ihn unter einem Alias, und der Code löst ihn mit context.service('alias') auf.

Mir ist diese Art der Verdrahtung lieber, weil ich sie lesen kann. Eine Einsparquote bei Tokens gegenüber einem anderen Framework habe ich nicht gemessen, und dieses Beispiel belegt auch keine.

Eine Illustration, die implizite Verdrahtung expliziten TypeScript-Deklarationen gegenüberstellt

Persistente Daten

Die Demo-Ressource hat Methoden wie create, list und delete. Ressourcen mit einer Datenbank dahinter nutzen dieselbe Schnittstelle, sodass Handler ihre vertraute Form behalten können.

Eine Datenbankmigration wird dadurch aber nicht zur Sache eines einzigen Pakets. Du brauchst weiterhin die Verbindungskonfiguration, Indizes, Validierung und eine Entscheidung darüber, was mit vorhandenen Daten passiert. Auch die Zugriffsregeln brauchen Tests.

Für ein neues Notizen-Feature eignet sich etwa diese Anfrage an den Agenten:

Füge persistente Notizen hinzu, die in MongoDB gespeichert werden. Nutze @owlmeans/mongo und @owlmeans/mongo-resource. Deklariere Schema und Entrypoints in sources/common, registriere Ressource und Handler in sources/api und ergänze einen Bildschirm in sources/web. Halte dich an die installierten Anweisungen zu Ressourcen und zur Wiederverwendung von Code.

Die Aufrufe der Ressource können dann so aussehen:

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

Das sind Auszüge aus der Schnittstelle und noch keine vollständige Anwendung. Alias, Schema und Verbindung der Ressource müssen im Projekt registriert sein.

Starte die App nach der Änderung neu und prüfe, ob die Notiz noch da ist. Probiere auch ungültige Eingaben und eine fehlgeschlagene Verbindung aus. Gehören die Notizen verschiedenen Personen, teste, ob wirklich niemand die Notizen der anderen lesen kann.

Die Web-Schicht nutzt shadcn UI und Tailwind. Die Dokumentation von shadcn beschreibt den Ansatz so: Du bekommst den Quellcode der Komponenten und arbeitest direkt damit. In diesem Projekt kann der Agent diesen Quellcode lesen und ändern. Die Interaktion, die dabei herauskommt, musst du trotzdem selbst prüfen.

Anweisungen aus den Paketen

Die Juni-Version hat Anweisungen in getrennte Verzeichnisse für jeden Agenten kopiert. Diese parallelen Quellen haben wir später entfernt. Die maßgeblichen Anweisungen des Projekts liegen unter .agents/, mit AGENTS.md im Wurzelverzeichnis und, wo nötig, einer Brücke für Claude.

OwlMeans-Pakete verteilen ihre Anweisungen über agent-meta/. Der Installer liest diese Metadaten und schreibt Skills für die Pakete im Projekt. Ein Skill zu Ressourcen kann das Framework erklären. Wofür deine Notizen da sind, müssen deine Projektanweisungen erklären.

Nach dem Upgrade der betreffenden Pakete lautet der gepflegte Befehl für diesen Rundgang:

npx @owlmeans/agent-skills@^0.1.18

Sieh dir die Ausgabe des Installers an. Verwaltete Dateien, die du lokal bearbeitet hast, können in Konflikt geraten. Erzwingst du das Überschreiben, entscheidest du damit über deine eigenen Änderungen. Der Installer ist für Projekte gedacht, die die Pakete nutzen. Verlinkte Framework-Monorepos haben einen eigenen Wartungsablauf.

Die ursprüngliche Illustration vom Juni mit getrennten Anweisungsdateien für die einzelnen Agenten

Diese Illustration zeigt die Verzeichnisstruktur vom Juni. Nutze für den überarbeiteten Ablauf die gemeinsame .agents-Struktur, die oben beschrieben ist.

Weder AGENTS.md noch das Agent-Skills-Format garantiert, dass jedes Werkzeug jede Datei automatisch lädt. Prüfe die Integration deines Agenten, bevor du dich auf die Anweisungen verlässt.

Was für dich zu tun bleibt

create-app gibt dir das Gerüst von Common. OwlMeans baut um dieses Fundament herum eine Pipeline aus Entwicklungsrollen. Das sind zwei verschiedene Wege, mit demselben Framework anzufangen.

Der Befehl entscheidet nicht über dein Datenmodell, testet keine Berechtigungen und betreibt deinen Dienst nicht in der Produktion. Ein erfolgreicher Build sagt nur begrenzt etwas aus: In diesem Setup führst du bun run typecheck getrennt von bun run build aus.

Ich habe das Gerüst gebaut, damit ich die anfängliche Verdrahtung nicht wiederholen muss. Übrig bleibt der Teil, über den ich nachdenken muss: ob das Feature dorthin gehört und ob es funktioniert.

Erstmals veröffentlicht am 17. Juni 2026. Am 15. Oktober 2026 überarbeitet: Die Befehle nennen jetzt die gepflegten Versionen, und die Anweisungen für Agenten folgen der gemeinsamen Struktur.

OwlMeans