Skills erstellen
Schritt-für-Schritt-Anleitung zum Hinzufügen neuer Expertise zu deinem Arc OS-Projekt.
Bevor du einen neuen Skill schreibst — prüfe die globale Bibliothek
Arc OS wird mit 40+ generischen Skills in skills/ ausgeliefert, die gängige Rollen abdecken. Prüfe vor dem Schreiben eines neuen Skills, ob ein vorhandener deinen Bedarf abdeckt:
| Domäne | Verfügbare Skills |
|---|---|
| Engineering | commit-discipline, tdd-flow, react-best-practices, postgres-patterns, mcp-builder |
| Frontend / Design | frontend-design-principles, svg-graphics, slide-deck-html, service-design, scss-modular-architecture, responsive-mobile-first |
| Startup Ops | market-analysis, gtm-strategy, financial-modeling, pitch-deck, customer-development, fundraising, founder-brand, metrics-dashboard, legal-startup |
| Marketing | seo-foundations, founder-brand |
| Prozess | standup-aggregator, commit-discipline |
| Datenbank | postgres-patterns |
Vollständige Liste durchsuchen: GET /api/crm/skills?category=<X> oder bun -e "console.log(JSON.stringify(require('./skills/_registry.json').skills.map(s=>s.name),null,2))".
Skill = trigger-matched, nicht always-on
Ein Skill wird automatisch in den Worker-Prompt injiziert, wenn die Nachricht zu seinen triggers passt (in _registry.json). Das Description-Feld ist Trigger-Logik („wann ist das zu verwenden"), keine Zusammenfassung. Der Context Router wählt die Top-5-Treffer pro Nachricht.
Was ist ein Skill
Ein Skill ist ein portabler Instruktionssatz, der deinem AI-Bot eine bestimmte Fähigkeit beibringt. Skills liegen im Verzeichnis skills/ und bestehen aus:
<name>.md— die Instruktionsdatei (erforderlich)<name>.evals.json— automatische Qualitätsvalidierungsregeln (optional, aber empfohlen)references/— unterstützende Dokumente, Schemas, Beispiele (optional)
skills/
├── _registry.json ← Central registry
├── my-new-skill/
│ ├── skill.md ← What the AI should do
│ ├── my-new-skill.evals.json ← How to validate the output
│ └── references/ ← Context documents
└── library/
└── domain-expert.md ← Simple single-file skills
Schritt 1: skill.md schreiben
Das ist die zentrale Instruktion. Claude liest diese, wenn der Skill aktiviert wird.
Vorlage
# Skill Name
## Purpose
What this skill accomplishes in one sentence.
## When to Use
- Trigger condition 1
- Trigger condition 2
## Protocol
1. First action
2. Second action
3. Third action
## Output Format
What the response should look like.
## Constraints
- What NOT to do
- Safety boundaries
Richtlinien
- Unter 500 Wörter — längere Skills verwässern den Kontext
- Imperativform — „Check the repository" statt „You should check"
- Konkrete Beispiele — zeige erwartete Input/Output-Paare
- Spezifische Tool-Referenzen — nenne die Befehle, APIs oder Muster, die verwendet werden sollen
Beispiel: Odoo Expert
# Odoo Expert
## Purpose
Odoo ERP module development: models, views, security, QWeb templates.
## When to Use
- Building or modifying Odoo modules
- Writing QWeb templates
- Configuring access rules and record rules
- Working with the ORM (create, write, search, browse)
## Protocol
1. Check if modifying an existing module or creating new
2. Follow Odoo 17 conventions (manifest, models/, views/, security/)
3. Use self.env['model.name'] for ORM operations
4. Always use _t() or t-call for translatable strings
5. Test with --test-tags after changes
## Constraints
- Never use cr.execute() for direct SQL — use ORM
- Never use sudo() unless security context explicitly requires it
- No inline JavaScript in QWeb templates
Schritt 2: Evals schreiben (Qualitätsregeln)
Evals sind deklarative Regeln, die jede Antwort automatisch validieren. Sie laufen nach der Ausgabe von Claude und fügen Warnungshinweise hinzu, wenn Regeln nicht erfüllt werden.
Dateinamenskonvention
skills/<name>/<name>.evals.json
Schema
{
"version": 1,
"skill": "my-new-skill",
"rules": [
{
"id": "ms-001",
"name": "Human-readable rule description",
"type": "rule_type",
"value": "for string/length types",
"pattern": "for regex types",
"severity": "warning"
}
]
}
Verfügbare Regeltypen
| Typ | Was geprüft wird | Verwendet Feld |
|---|---|---|
string_contains |
Antwort enthält literalen Text | value (string) |
string_not_contains |
Antwort enthält Text NICHT | value (string) |
regex_match |
Antwort stimmt mit Regex überein | pattern (string) |
regex_not_match |
Antwort stimmt mit Regex NICHT überein | pattern (string) |
max_length |
Antwortlänge <= N Zeichen | value (number) |
min_length |
Antwortlänge >= N Zeichen | value (number) |
Schweregrade
warning— Weist auf ein Qualitätsproblem hin. Wird als⚠️angezeigt.info— Hinweis. Wird alsℹ️angezeigt.
Beispiel
{
"version": 1,
"skill": "odoo-expert",
"rules": [
{
"id": "oe-001",
"name": "Must use ORM, not raw SQL",
"type": "string_not_contains",
"value": "cr.execute",
"severity": "warning"
},
{
"id": "oe-002",
"name": "Must use translation helpers",
"type": "regex_match",
"pattern": "_t\\(|t-call|t-esc",
"severity": "warning"
},
{
"id": "oe-003",
"name": "Response under 5000 chars",
"type": "max_length",
"value": 5000,
"severity": "info"
}
]
}
Tipps
- Beginne mit 2–3 Regeln. Füge weitere hinzu, sobald du Muster aus Korrekturen erkennst.
- Sicherheit zuerst:
string_not_containsfür gefährliche Befehle,regex_not_matchfür Credential-Muster. - ID-Konvention:
<skill-prefix>-<number>(z. B.oe-001,gm-002). - Testen: Sende eine Nachricht, die den Skill auslösen soll, und prüfe, ob Warnungen korrekt erscheinen.
Schritt 3: In _registry.json registrieren
Die Registry informiert den Context Router über deinen Skill, damit er für relevante Nachrichten empfohlen werden kann.
Eintrag hinzufügen
{
"name": "my-new-skill",
"description": "One sentence (shown in SKILLS_HINT, max 80 chars).",
"triggers": ["direct-command", "explicit-request", "пряма команда"],
"keywords": ["broader", "semantic", "related-term"],
"agents": ["rick"],
"category": ["complex"],
"phase": "21.5"
}
Triggers vs. Keywords
Triggers (je 2 Punkte): Direkte Aufruf-Signale. Der Nutzer möchte diesen Skill explizit.
- „deploy", „review", „scaffold", „odoo", „audit"
Keywords (je 1 Punkt): Breitere Begriffe, die Relevanz andeuten, ohne direkte Befehle zu sein.
- „OWASP", „Docker", „CI/CD", „production", „module"
Richtlinien
- Ukrainische Entsprechungen in Triggers aufnehmen für zweisprachige Teams
- Beschreibungen unter 80 Zeichen halten (werden in SKILLS_HINT abgeschnitten)
- 5–8 Triggers pro Skill (mehr = unschärfes Matching)
- Keywords sind optional, verbessern das Routing aber deutlich
Schritt 4: Library Skills (einfaches Format)
Für Domain-Expertise, die weder Evals noch ein eigenes Verzeichnis benötigt, verwende skills/library/:
skills/library/
├── docker-ops.md
├── postgres-pro.md
└── react-patterns.md
Das sind einzelne .md-Dateien. Kein Verzeichnis, keine Evals, keine Referenzen. Gut geeignet für wissensintensive Skills mit wenig Validierungsbedarf.
Checkliste
-
skills/<name>/skill.md— Instruktion mit Purpose, Protocol, Constraints -
skills/<name>/<name>.evals.json— mindestens 2 Validierungsregeln - Eintrag in
skills/_registry.json— mit Triggers und Keywords - Name überall konsistent — Verzeichnisname = Eval-Skill-Name = Registry-Name
- Testen: Trigger-Nachricht senden → SKILLS_HINT in Logs prüfen
- Testen: Eval-Fehler absichtlich auslösen → Warnung prüfen
Was zur Laufzeit passiert
1. Bot starts → loadRegistry() reads _registry.json
loadEvals() reads all .evals.json files
loadLearnings() reads learnings.md
2. Message arrives → routeContext() scores skills → SKILLS_HINT injected
formatForPrompt() adds LEARNINGS block
3. Claude responds → checkOutput() runs eval rules
formatEvalWarnings() appends footnotes
4. Fix It / thumbs-down → addLearning() writes to learnings.md
qualityTracker logs feedback
5. Nightly → findUnderperformingSkills() checks metrics
Proposals sent to CEO for approval
Skills in die globale DB seeden
Skills in der DB (Tabelle skills_global) sind die SSOT für den Context Router. Die Datei auf der Festplatte ist die Source of Truth für den Inhalt; die DB ist der schnelle Index für Matching + Auto-Injection. Synchronisiert werden sie über Seeder-Skripte.
Generischer Seeder nach Kategorie
# Reads skills/_registry.json, filters by category, upserts skills_global rows.
# Idempotent + drift-aware (skip if no change, update on content drift).
bun scripts/seed-skill-category.ts --category engineering
bun scripts/seed-skill-category.ts --category frontend
bun scripts/seed-skill-category.ts --category marketing
Funktioniert für jede in _registry.json vorhandene Kategorie. Nimmt die erste Kategorie aus dem Array als DB-Spaltenwert.
Spezifische Seeder
scripts/seed-startup-skills.ts— hartkodiert für category="startup" (10 Startup-Operations-Skills)scripts/migrate-skills-to-db.ts— historische Bulk-Migration (alle Dateien, nur Insert, kein Update)
Wann ausführen
- Nach dem Erstellen einer neuen
.md+ des_registry.json-Eintrags → Seeder einmal ausführen - Nach einer Inhaltsänderung einer bestehenden
.md→ der drift-aware Seeder aktualisiert die DB - Bootstrap eines neuen Projekts → Seeder laufen über
vps-sync.shStep 1.5 (geplant)
Verifizieren
sqlite3 data/citadel.db "SELECT name, category, owner_project FROM skills_global ORDER BY id"
owner_project = NULL → global (alle Projekte sehen ihn). owner_project = 'my-project' → project-only (nur dieses Projekt).
Project-only vs. globale Skills
| Skill-Typ | owner_project |
Use Case |
|---|---|---|
| Global (Template) | NULL | Generische Methodik (TDD, Conventional Commits, AARRR) — für jedes Projekt nützlich |
| Project-only | '<project-name>' |
Dokumente, die spezifisch für UNSERE Codebase sind (z. B. liegt crm-api-reference nur in arc-v2) |
Einen bestehenden Skill auf project-only umstellen:
sqlite3 data/citadel.db "UPDATE skills_global SET owner_project='my-project' WHERE name='internal-api-docs'"
Der listForProject-Filter gated die Sichtbarkeit: Andere Projekte sehen einen project-only Skill nicht.