Crear Skills
Guía paso a paso para agregar nuevas capacidades a tu proyecto de Arc OS.
Antes de escribir un skill nuevo — revisa la biblioteca global
Arc OS incluye más de 40 skills genéricos en skills/ que cubren los roles comunes. Antes de crear uno nuevo, comprueba si alguno existente ya cubre tu necesidad:
| Dominio | Skills disponibles |
|---|---|
| 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 |
| Process | standup-aggregator, commit-discipline |
| Database | postgres-patterns |
Explora la lista completa: GET /api/crm/skills?category=<X> o bun -e "console.log(JSON.stringify(require('./skills/_registry.json').skills.map(s=>s.name),null,2))".
Skill = activado por triggers, no siempre activo
El skill se auto-inyecta en el prompt del worker cuando el mensaje coincide con sus triggers (en _registry.json). El campo description es lógica de trigger ("cuándo usar esto"), no un resumen. El Context Router elige los top-5 coincidentes por mensaje.
Qué es un Skill
Un skill es un conjunto de instrucciones portátil que enseña a tu bot de IA una capacidad específica. Los skills viven en el directorio skills/ y están compuestos por:
<name>.md— el archivo de instrucciones (obligatorio)<name>.evals.json— reglas de validación de calidad automáticas (opcional pero recomendado)references/— documentos de soporte, schemas, ejemplos (opcional)
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
Paso 1: Escribe skill.md
Esta es la instrucción central. Claude la lee cuando el skill se activa.
Plantilla
# 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
Pautas
- Menos de 500 palabras — los skills más largos diluyen el contexto
- Modo imperativo — "Revisa el repositorio", no "Deberías revisar"
- Ejemplos concretos — muestra pares de entrada/salida esperados
- Referencias de herramientas específicas — nombra los comandos, APIs o patrones a usar
Ejemplo: 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
Paso 2: Escribe los evals (Reglas de Calidad)
Los evals son reglas declarativas que validan automáticamente cada respuesta. Se ejecutan después de que Claude genera el output y agregan notas de advertencia si alguna regla falla.
Nomenclatura del archivo
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"
}
]
}
Tipos de Reglas Disponibles
| Tipo | Qué verifica | Usa el campo |
|---|---|---|
string_contains |
La respuesta incluye texto literal | value (string) |
string_not_contains |
La respuesta NO incluye texto | value (string) |
regex_match |
La respuesta coincide con la regex | pattern (string) |
regex_not_match |
La respuesta NO coincide con la regex | pattern (string) |
max_length |
Longitud de respuesta <= N caracteres | value (number) |
min_length |
Longitud de respuesta >= N caracteres | value (number) |
Niveles de Severidad
warning— Indica un problema de calidad. Se muestra como⚠️.info— Nota informativa. Se muestra comoℹ️.
Ejemplo
{
"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"
}
]
}
Consejos
- Empieza con 2-3 reglas. Agrega más a medida que descubras patrones a partir de correcciones.
- Seguridad primero:
string_not_containspara comandos peligrosos,regex_not_matchpara patrones de credenciales. - Convención de ID:
<skill-prefix>-<número>(ej.,oe-001,gm-002). - Prueba: Envía un mensaje que debería activar el skill y verifica que las advertencias aparezcan correctamente.
Paso 3: Registra en _registry.json
El registry le indica al Context Router sobre tu skill para que pueda recomendarlo en mensajes relevantes.
Agrega una entrada
{
"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 (2 puntos cada uno): Señales de invocación directa. El usuario quiere explícitamente este skill.
- "deploy", "review", "scaffold", "odoo", "audit"
Keywords (1 punto cada uno): Términos más amplios que sugieren relevancia sin ser comandos.
- "OWASP", "Docker", "CI/CD", "production", "module"
Pautas
- Incluye equivalentes en ucraniano en los triggers para equipos bilingües
- Mantén las descripciones en menos de 80 caracteres (se truncan en SKILLS_HINT)
- 5-8 triggers por skill (más = matching ruidoso)
- Los keywords son opcionales pero mejoran significativamente el enrutamiento
Paso 4: Library Skills (Formato Simple)
Para conocimiento de dominio que no necesita evals ni un directorio dedicado, usa skills/library/:
skills/library/
├── docker-ops.md
├── postgres-pro.md
└── react-patterns.md
Son archivos .md individuales. Sin directorio, sin evals, sin references. Ideales para skills con mucho conocimiento pero poca validación.
Lista de Verificación
-
skills/<name>/skill.md— instrucción con Purpose, Protocol, Constraints -
skills/<name>/<name>.evals.json— al menos 2 reglas de validación - Entrada en
skills/_registry.json— con triggers y keywords - El nombre coincide en todos lados — nombre del directorio = nombre del skill en evals = nombre en el registry
- Prueba: envía un mensaje de trigger → verifica SKILLS_HINT en los logs
- Prueba: activa intencionalmente un fallo de eval → verifica que aparezca la advertencia
Qué Ocurre en Tiempo de Ejecución
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
Sembrar skills en la DB global
Los skills en la DB (tabla skills_global) son el SSOT para el Context Router. El archivo en disco es la fuente de verdad del contenido; la DB es el índice rápido para matching + auto-inyección. Se sincronizan mediante scripts seeder.
Seeder genérico por categoría
# 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
Funciona para cualquier categoría presente en _registry.json. Toma la primera categoría del array como valor de la columna en la DB.
Seeders específicos
scripts/seed-startup-skills.ts— hardcodeado para category="startup" (10 skills de operaciones de startup)scripts/migrate-skills-to-db.ts— migración masiva histórica (todos los archivos, solo insert, sin update)
Cuándo ejecutarlos
- Tras crear un
.mdnuevo + su entrada en_registry.json→ ejecuta el seeder una vez - Tras actualizar el contenido de un
.mdexistente → el seeder drift-aware actualiza la DB - Bootstrap de un proyecto nuevo → los seeders corren vía
vps-sync.shStep 1.5 (planificado)
Verificación
sqlite3 data/citadel.db "SELECT name, category, owner_project FROM skills_global ORDER BY id"
owner_project = NULL → global (todos los proyectos lo ven). owner_project = 'my-project' → solo de proyecto (únicamente ese proyecto).
Skills de proyecto vs globales
| Tipo de skill | owner_project |
Caso de uso |
|---|---|---|
| Global (plantilla) | NULL | Metodología genérica (TDD, Conventional Commits, AARRR) — útil para cualquier proyecto |
| Solo de proyecto | '<project-name>' |
Documenta detalles específicos de NUESTRO codebase (p. ej. crm-api-reference vive solo en arc-v2) |
Mover un skill existente a solo-de-proyecto:
sqlite3 data/citadel.db "UPDATE skills_global SET owner_project='my-project' WHERE name='internal-api-docs'"
El filtro listForProject controla la visibilidad: otros proyectos no verán un skill solo-de-proyecto.