Kommandozeile¶
Das Tool coworkee legt eine Coworkee-Anwendung aus dem Paket Coworkee.Templates an, mit den Modulen, dem Branding und den Entities Ihrer Wahl, und übernimmt die alltäglichen Befehle: starten, Migrationen, neue Module und Entities, Paket-Updates. Außerdem startet es einen MCP-Server für KI-Agenten und öffnet Coworkee Studio, einen Desktop-Assistenten.
Installation¶
coworkee doctor prüft das .NET SDK (mindestens die Version aus global.json), ob Docker läuft und ob dotnet-ef installiert ist. Die Aspire-CLI ist optional; coworkee run nutzt dotnet run.
Eine neue Anwendung¶
coworkee new installiert Coworkee.Templates in der Version des Tools, legt die Solution an, erzeugt die Module einer Spezifikation, stellt die Pakete wieder her und legt die Migration an, die die gewählten Module brauchen. Die erzeugte App verweist auf die Coworkee-Pakete genau dieser Version. Der Name muss einfach sein: ein Buchstabe, dann Buchstaben oder Ziffern (Shop, Crm2). Er wird zum Präfix aller Projekte und Namespaces.
Der Migrations-Worker legt einen Administrator admin@<name>.local und die Benutzer von --user oder der Spezifikation an. Am Ende zeigt coworkee new einen Kasten Sign in mit jedem Benutzer, seinem Passwort und seinen Rollen; dieselbe Tabelle steht in LOGIN.md der Solution. Mit Keycloak hat der Realm dieselben Benutzer mit denselben Passwörtern.
--user nimmt email[:rolle,rolle][:admin] und lässt sich wiederholen; das Passwort wird erzeugt. Die Benutzer stehen in src/<Name>.Migrations/DemoUsers.cs, das der Seed und der AppHost (für Keycloak) beide lesen. Die Passwörter sind nur für die Entwicklung: Ändern Sie sie, bevor Sie irgendwohin deployen.
Optionen¶
Jede Option ist ein Schalter von coworkee new und, unter ihrer Id, ein Schlüssel in den options einer Spezifikation. coworkee options zeigt sie mit den Gründen, sie zu wählen, coworkee options --json als Daten.
coworkee new Shop --no-samples --chat false --files --event-bus rabbitMq \
--theme Forest --primary-color "#0a7d5a" --logo ./brand/logo.svg \
--sign-in-layout Split --sign-in-media ./brand/welcome.mp4 --git
| Schalter | Id | Werte | Standard | |
|---|---|---|---|---|
-o, --output |
Ordner | ./<name> |
Zielordner | |
--spec |
Datei | Legt die App aus einer Spezifikation an, siehe unten; Schalter gewinnen gegen die Spezifikation | ||
--template-source |
Datei oder Ordner | nuget.org | Template aus einer .nupkg oder einem Ordner installieren, offline oder für einen lokalen Build |
|
--title |
title |
Text | der Name | Anzeigetitel im Browser, in der App-Leiste, auf den Anmeldeseiten und im Aspire-Dashboard |
--samples, --no-samples |
samples |
bool | true |
Module Catalog (Produkte, Marken, Dashboard) und Documents mit Seiten, Tests und Demodaten |
--tests, --no-tests |
tests |
bool | true |
API-, Migrations-, App-Host- und Seitentests |
--git |
git |
bool | false |
git init im neuen Ordner |
--auditing |
auditing |
bool | true |
Seiten für Audit-Log, Verlauf und Wiederherstellen; das Protokoll selbst wird immer geschrieben |
--notifications |
notifications |
bool | true |
Benachrichtigungen in der App mit Sammel-Mails |
--chat |
chat |
bool | true |
Direkt- und Gruppenchat |
--ai |
ai |
bool | true |
KI-Assistent, MCP-Endpunkt der App und Protokoll der Tool-Aufrufe |
--backup |
backup |
bool | true |
Datenbank-Backups aus den Admin-Seiten |
--files |
files |
bool | false |
Ordner und Dateien mit Vorschau und Rechten pro Ordner |
--features |
features |
bool | false |
Features, Editionen und die Mandantenverwaltung |
--social |
social |
bool | false |
Kommentare, Tags und Bewertungen |
--extended-attributes |
extendedAttributes |
bool | false |
Schlüssel/Wert-Attribute für beliebige Entities (das Documents-Beispiel bringt sie ohnehin mit) |
--elasticsearch |
elasticsearch |
bool | false |
Elasticsearch-Index; der App-Host ergänzt den Container |
--event-bus |
eventBus |
none, inProcess, rabbitMq |
none |
Integrationsereignisse über die Outbox; rabbitMq ergänzt den Transport und einen RabbitMQ-Container |
--client-entities |
clientEntities |
bool | false |
Browser-Kopien von OData-Sets mit [ClientEntity]; Entities der Spezifikation mit clientEntity schalten es ein |
--keycloak |
keycloak |
bool | false |
Keycloak-Container als externe Anmeldung |
--storage |
storage |
fileSystem, azureBlob |
fileSystem |
Blob-Speicher; azureBlob startet Azurite im App-Host |
--ai-provider |
aiProvider |
anthropic, openAI, azureOpenAI, ollama, openAICompatible |
anthropic |
Modellanbieter des Assistenten; ollama startet Ollama im App-Host |
--redis |
redis |
bool | true |
Redis-Container für Backplane, Anwesenheit, Cache-Invalidierung und Sitzungen über Instanzen hinweg (Redis) |
--grafana |
grafana |
bool | true |
Grafana mit Prometheus, Loki, Tempo und Collector: Telemetrie jedes Dienstes, die App-Datenbank und Dashboards (Grafana und WebDataStudio) |
--web-data-studio |
webDataStudio |
bool | true |
WebDataStudio, verbunden mit der App-Datenbank (Grafana und WebDataStudio) |
--database |
database |
postgres, sqlServer, sqlite |
postgres |
Datenbank-Engine, siehe Datenbank-Provider; sqlServer startet einen SQL-Server-Container, sqlite eine Datei ohne Container. Sicherungen brauchen postgres |
--theme |
theme |
Ocean, Coworkee, Classic, Forest, Midnight, Sunset, HighContrast |
Ocean |
Standard-Theme |
--primary-color |
primaryColor |
#rrggbb |
Markenfarbe: Die App bekommt ein eigenes Theme auf Basis von --theme, benannt wie der Titel, als Standard |
|
--secondary-color |
secondaryColor |
#rrggbb |
Zweite Markenfarbe | |
--logo |
logo |
Datei | Coworkee-Symbol | Wird in den Web-Client kopiert; App-Leiste, Browser-Tab und Anmeldeseiten |
--sign-in-layout |
signInLayout |
Card, Split, Slide |
Slide |
Layout der Anmeldeseiten |
--sign-in-media |
signInMedia |
Datei oder http(s)-Adresse | Bild oder Video neben dem Anmeldeformular; eine Datei wird nach wwwroot/media des Web-Clients kopiert |
|
--sign-in-media-side |
signInMediaSide |
Left, Right |
Left |
Seite des Mediums |
--mapping |
mapping |
manual, mapperly |
manual |
DTO-Mapping erzeugter Entities, siehe DTOs und Mapping |
--languages |
languages |
en, de, durch Kommas getrennt (in einer Spezifikation ein Array) |
alle mitgelieferten | Sprachen von Anfang an, aus denen, für die die Bibliothek Texte mitbringt; weitere fügen Administratoren auf der Seite Sprachen hinzu |
--default-language |
defaultLanguage |
en, de |
en |
Sprache der Benutzer, die keine gewählt haben; muss unter languages sein |
--color-mode |
colorMode |
system, light, dark |
system |
Standard-Farbmodus, angelegt als systemweite Einstellung Theme.Mode |
--registration |
registration |
bool | true |
Selbstregistrierung auf der Anmeldeseite, angelegt als Einstellung Account.AllowRegistration |
--github-actions |
githubActions |
bool | false |
.github/workflows/ci.yml: Build und Tests bei jedem Push und Pull Request |
--devcontainer |
devcontainer |
bool | false |
.devcontainer/devcontainer.json mit dem .NET SDK und Docker in Docker (Codespaces, VS Code) |
Ein bool-Schalter ohne Wert bedeutet true (--files), --chat false schaltet aus. Die mitgelieferte erste Migration deckt die Standardmodule ab (mit oder ohne Beispiele). Schalten Sie ein Modul mit Tabellen ein oder aus (Chat, KI, Backup, Benachrichtigungen, Dateien, Features, Social, Event-Bus, erweiterte Attribute ohne Beispiele) oder wählen eine andere Datenbank als postgres, lässt das Template die Migration weg und coworkee new legt nach dem Restore Initial mit dotnet ef an. Mit reinem dotnet new führen Sie coworkee migrations add Initial einmal selbst aus.
App-Spezifikationen¶
Eine Spezifikation beschreibt die ganze App als JSON: Name, Optionen, Branding und Feature-Module mit ihren Entities. Coworkee Studio und der MCP-Server arbeiten mit diesem Format.
coworkee spec example > shop.json # ein vollständiges Beispiel
coworkee spec schema > spec.schema.json
coworkee spec validate shop.json
coworkee new --spec shop.json
{
"name": "Shop",
"output": "shop",
"options": { "samples": false, "chat": false, "files": true, "mapping": "manual", "languages": [ "en", "de" ], "defaultLanguage": "de" },
"branding": {
"title": "Acme Shop",
"theme": "Forest",
"primaryColor": "#0a7d5a",
"logo": "brand/logo.svg",
"signInLayout": "Split",
"signInMedia": "brand/welcome.mp4"
},
"modules": [
{
"name": "Sales",
"entities": [
{
"name": "Customer",
"properties": [
{ "name": "Name", "required": true, "maxLength": 200, "display": true },
{ "name": "Email", "type": "email", "unique": true },
{ "name": "IsActive", "type": "bool", "default": "true", "facet": true }
]
},
{
"name": "Order",
"clientEntity": true,
"mapping": "mapperly",
"properties": [
{ "name": "Number", "required": true, "maxLength": 50, "unique": true },
{ "name": "Customer", "type": "reference", "reference": "Customer", "required": true, "inverse": "Orders", "facet": true },
{ "name": "Status", "type": "enum", "enum": "OrderStatus", "required": true, "default": "Open", "facet": true },
{ "name": "Total", "type": "money", "required": true },
{ "name": "OrderedOn", "type": "dateOnly", "label": "Order date" },
{ "name": "Note", "type": "text" }
]
}
]
}
],
"enums": [ { "name": "OrderStatus", "values": [ "Open", "Paid", "Shipped" ] } ]
}
optionsnimmt die Ids aus der Tabelle oben;brandingnimmttitle,theme,primaryColor,secondaryColor,logo,signInLayout,signInMediaundsignInMediaSideund gewinnt gegen dieselben Ids inoptions.- Dateien und
outputsind relativ zur Spezifikation und müssen in ihrem Ordner bleiben (keine absoluten Pfade, kein..). Ein Logo ist ein Bild (svg, png, jpg, jpeg, webp, gif, ico), das Anmeldemedium ein Bild, ein Video (mp4, webm, ogg) oder eine http(s)-Adresse: Beide liegen danach öffentlich im Web-Client. Eine als Schalter angegebene Datei (--logo C:\brand\logo.svg) darf überall liegen. Kommentare und abschließende Kommas sind erlaubt. - Der Titel landet unverändert in Code und HTML und darf daher kein
",\,<,>,@und keine Steuerzeichen enthalten. - Typen der Eigenschaften:
string,int,long,decimal,double,bool,dateTime(DateTimeOffset),guid,dateOnly,timeOnly,text(langer Text, mehrzeilig im Formular, keine Listenspalte),emailundurl(Strings mit Prüfung, 256 und 2000 Zeichen, sofernmaxLengthnichts anderes sagt),money(Decimal mitprecision18 undscale2, sofern nicht angegeben),enumundreference. Eine Eigenschaft ohnerequiredist nullable;maxLengthgilt für Strings, E-Mails und URLs,precisionundscalefür Decimal und Money. enumnennt einen Eintrag ausenums(Werte in ihrer Reihenfolge, der erste ist der Standard). Das Enum landet in den Contracts, reist in JSON und OData mit seinem Namen und erscheint mit seinen Namen in Liste, Formular und Facetten.referenceverweist auf eine andere Entity über ihren Namen (Customer) oder mit Modul (Crm.Customer): die Eigenschaft ist die Navigation,<Name>Idder Fremdschlüssel.referenceDisplayist die Texteigenschaft des Ziels, die Liste und Auswahl zeigen (Standard: seine Anzeige-Eigenschaft),onDeleteistrestrict(Standard),cascadeodersetNull(nur für optionale Referenzen),inversegibt dem Ziel eine Sammlung (nur im selben Modul). Ein Modul darf andere Module referenzieren, solange keines zurückverweist.defaultsetzt den Anfangswert von Zahlen, Bools, Enums und Texten;uniquelegt einen eindeutigen Index je Mandant und eine Prüfung im Command an;labelist die Beschriftung von Spalte und Feld;displaymarkiert den Text, der eine Zeile benennt;searchable(Standard: true für Texte) nimmt sie ins Suchfeld;facetbietet sie als Facette neben der Liste an (Bools, Enums, Referenzen, ganze Zahlen, Strings).pluralbenennt Tabelle, OData-Set, Route und Seite (Standard: ein englischer Plural des Namens).mappingübersteuert die Optionmapping.
Benutzer und Rollen¶
"roles": [ { "name": "Sales", "description": "Takes orders", "permissions": [ "Sales.Customers.View", "Sales.Orders.View", "Sales.Orders.Create", "Sales.Orders.Edit" ] } ],
"users": [
{ "email": "ada@shop.test", "displayName": "Ada Lovelace", "roles": [ "Sales" ] },
{ "email": "grace@shop.test", "roles": [ "User" ], "admin": true, "password": "Grace-2026!" }
]
roleswerden neben den eigenen Rollen der Vorlage angelegt (mit Beispielen Product Manager und Brand Manager, ohne User). Die Berechtigungen müssen zur App gehören: die der gewählten Module (Identity.Users.View,Chat.Use,Reports.View, ...), der Beispiele und<Modul>.<Plural>.View|Create|Edit|Deleteder Entities der Spezifikation; die Prüfung zählt sie auf.usersbrauchen eine E-Mail;displayNameist ohne Angabe der Teil vor@,rolesnennt Rollen der Spezifikation oder der Vorlage,admingibt alle Berechtigungen. Ohnepasswordwird eines erzeugt; ein angegebenes braucht 8 Zeichen mit Groß- und Kleinbuchstaben, einer Ziffer und einem Sonderzeichen.
coworkee spec validate und coworkee new melden jedes Problem mit seinem Pfad, zum Beispiel modules[0].entities[1].properties[0].name: 'Id' is taken by the entity itself.
Module und Entities¶
Jedes Modul einer Spezifikation, und coworkee module add, legt das Projekt src/<App>.<Modul> so an, wie Das erste Feature die Marken baut. Pro Entity:
| Wo | Was |
|---|---|
| Contracts | <Entity>Dto, AddEdit<Entity>Request, <Modul>Permissions.<Plural> (ansehen, anlegen, bearbeiten, löschen) |
| Modul | Entity (AuditedEntity, IMultiTenant, [Realtime], auf Wunsch [ClientEntity], [ProvideFacet] an Facetten), Tabelle mit Maximallängen, Genauigkeiten, Fremdschlüsseln mit Löschverhalten und eindeutigen Indizes, Rechtedefinitionen, OData-Set, Anlegen/Bearbeiten-Command mit Rechteprüfung, Prüfung referenzierter Zeilen, Eindeutigkeitsprüfung und Validator (Pflicht, Längen, E-Mails, URLs, Enums), Lösch-Command, Mapping (ToDto-Methode oder Mapperly-Mapper; eine Referenz bringt Id und Anzeigetext ihres Ziels mit), Endpunkte POST, PUT /{id} und POST /delete unter /api/v1/<plural> |
| Contracts, einmal je Enum | Enums/<Enum>.cs, mit Namen serialisiert |
| Web-Client | Seite /<modul>/<plural> mit Datentabelle (Referenzen erweitert und mit ihrem Text angezeigt, Geldbeträge formatiert), Anlegen, Bearbeiten (Auswahlfelder für Referenzen, mehrzeilig für langen Text) und Löschen, Live-Aktualisierung, API-Client und einem Navigationseintrag in der Gruppe des Moduls |
Das Modul kommt in die .slnx, das Infrastrukturprojekt verweist darauf und <App>DatabaseModule hängt davon ab; Program.cs des Web-Clients registriert die API-Clients und Navigationseinträge.
coworkee module add Sales --entity Order --property Number:string:required:50:unique --property Total:money --client-entity
coworkee entity add Sales Invoice -p Number:required:30 -p Order:ref=Order:required:onDelete=cascade -p Status:enum=InvoiceStatus:default=Open:facet \
--enum InvoiceStatus=Open,Paid --mapping Mapperly
coworkee entity add Sales Delivery -p Name:required:100 -p Carrier:ref=Logistics.Carrier
coworkee migrations add AddSales
--property liest Name[:typ][:required][:maxLänge][:flag][:schlüssel=wert] (Standard: Name:string:required:200). Flags: required, unique, display, facet, searchable. Schlüssel wie in einer Spezifikation: enum, ref (oder reference), referenceDisplay, onDelete, inverse, default, label, precision, scale, searchable. --enum Name=Wert1,Wert2 legt ein Enum in den Contracts an. Eine Referenz darf auf jede Entity der App mit OData-Set zeigen, erzeugt oder aus den Beispielen (ref=Catalog.Brand); das Modul verweist dann auf das Projekt des Ziels. entity add braucht ein von der CLI angelegtes Modul.
Coworkee Studio¶
coworkee ui startet Coworkee Studio, einen Desktop-Assistenten für Name, Titel, Logo, Farben, Module, Anmeldedesign, Theme und Entities; er legt die App mit dieser CLI an. Das Studio ist das globale Tool Coworkee.Studio (Befehl coworkee-ui): coworkee ui installiert es in der Version der CLI, wenn es fehlt, und aktualisiert es, wenn es älter ist. Weitere Argumente gehen an das Studio, siehe Coworkee Studio. Für lokale Builds: --prerelease, --add-source <ordner> und --studio-version <version>; eine ausdrücklich genannte Version, die älter als die installierte ist, wird ebenfalls installiert. --prerelease nimmt die neueste Vorabversion statt der Version der CLI und entfällt neben --studio-version.
Weitere Befehle¶
| Befehl | Was er tut |
|---|---|
coworkee run |
Startet das *.AppHost-Projekt der Solution |
coworkee migrations add <name> |
dotnet ef migrations add <name> mit dem *.Infrastructure-Projekt als Projekt und Startprojekt |
coworkee module add <name> |
Ein Feature-Modul mit seiner ersten Entity, siehe oben |
coworkee entity add <modul> <name> |
Eine weitere Entity in einem Modul, siehe oben |
coworkee options [--json] |
Die Optionen von coworkee new |
coworkee spec schema, example, validate <datei> |
App-Spezifikationen |
coworkee update [--version <version>] [--prerelease] |
Setzt <CoworkeeVersion> in Directory.Packages.props, standardmäßig auf die neueste Version auf nuget.org |
coworkee doctor |
Prüft die Werkzeuge, siehe oben |
coworkee ui |
Coworkee Studio |
coworkee mcp |
MCP-Server über stdio |
Nach coworkee update führen Sie dotnet restore aus und legen eine Migration an, falls ein Coworkee-Modul sein Modell geändert hat (coworkee migrations add CoworkeeUpdate).
Ausgabe für Werkzeuge¶
coworkee new schreibt vor jedem Schritt eine Zeile ==> <schritt> (Template installieren, Solution anlegen, Modul erzeugen, Restore, Migration anlegen, Git), vor jedem Befehl, den es ausführt, > <befehl>, und endet mit einem Code ungleich 0, wenn ein Schritt scheitert. Probleme mit der Eingabe stehen einzeln pro Zeile auf stderr.
Ohne das Tool¶
Das Template funktioniert auch mit reinem dotnet new; die Schalter heißen wie die Ids der Tabelle (--eventBus, --primaryColor, ...):
dotnet new install Coworkee.Templates
dotnet new coworkee -n Shop --samples false --keycloak true --title "My Shop" --theme Sunset
dotnet run --project Shop/src/Shop.AppHost
dotnet new coworkee --help listet sie auf. Kopieren Sie ein Logo selbst nach src/<Name>.Web.Client/wwwroot, bevor Sie --logo <dateiname> angeben.