Guia para personalizar los templates Jinja2 que intake usa para generar archivos spec y exportaciones.


Como funciona

intake usa 17 templates Jinja2 para generar todos sus archivos de salida. El sistema de templates tiene dos niveles de prioridad:

  1. Templates de usuario (en .intake/templates/ del proyecto) — prioridad alta
  2. Templates built-in (incluidos en el paquete intake) — fallback

Si colocas un archivo con el mismo nombre que un template built-in en .intake/templates/, tu version se usa automaticamente en lugar del built-in. Esto permite personalizar el formato de cualquier archivo generado sin modificar intake.

mi-proyecto/
├── .intake/
│   └── templates/               # Tus overrides
│       ├── requirements.md.j2   # Sobreescribe el template de requisitos
│       └── verify_sh.j2         # Sobreescribe el template de verify.sh
└── .intake.yaml

Configuracion

# .intake.yaml
templates:
  user_dir: ".intake/templates"   # Directorio de templates de usuario (default)
  warn_on_override: true          # Log cuando un template built-in es sobreescrito (default)
CampoDefaultDescripcion
user_dir.intake/templatesPath relativo al proyecto donde buscar templates de usuario
warn_on_overridetrueEmitir log template_override cuando se detecta un override

Templates disponibles

Templates de spec (generacion)

Usados por intake init y intake add para generar los 6 archivos spec:

TemplateArchivo generadoDescripcion
requirements.md.j2requirements.mdRequisitos funcionales y no funcionales
design.md.j2design.mdDiseno tecnico: componentes, archivos, decisiones
tasks.md.j2tasks.mdTareas de implementacion con tabla resumen
acceptance.yaml.j2acceptance.yamlChecks de aceptacion en YAML
context.md.j2context.mdContexto del proyecto para agentes IA
sources.md.j2sources.mdTrazabilidad requisito-a-fuente

Templates de exportacion

Usados por intake export -f <formato>:

TemplateExporterArchivo generado
claude_md.j2claude-codeSeccion ## intake Spec en CLAUDE.md
claude_task.md.j2claude-codeTASK-NNN.md individuales
verify_sh.j2claude-code, genericverify.sh ejecutable
cursor_rules.mdc.j2cursor.cursor/rules/intake-spec.mdc
kiro_requirements.md.j2kirorequirements.md formato Kiro
kiro_design.md.j2kirodesign.md formato Kiro
kiro_tasks.md.j2kirotasks.md formato Kiro
copilot_instructions.md.j2copilot.github/copilot-instructions.md
feedback.md.j2feedbackReporte de feedback

Templates de CI

Usados por intake export-ci:

TemplatePlataformaArchivo generado
gitlab_ci.yml.j2GitLab.gitlab-ci.yml
github_actions.yml.j2GitHub.github/workflows/intake-verify.yml

Variables disponibles por template

requirements.md.j2

VariableTipoDescripcion
functional_requirementslist[dict]Requisitos funcionales. Cada uno tiene: id, title, description, priority, source, acceptance_criteria (list)
non_functional_requirementslist[dict]Requisitos no funcionales (misma estructura)
conflictslist[dict]Conflictos detectados. Cada uno: id, description, source_a, source_b, severity, recommendation
open_questionslist[dict]Preguntas abiertas. Cada una: id, question, context, source, recommendation

design.md.j2

VariableTipoDescripcion
componentslist[str]Nombres de componentes de arquitectura
files_to_createlist[dict]Archivos a crear. Cada uno: path, description
files_to_modifylist[dict]Archivos a modificar. Cada uno: path, description
tech_decisionslist[dict]Decisiones tecnicas. Cada una: decision, justification, requirement
dependencieslist[str]Dependencias del proyecto

tasks.md.j2

VariableTipoDescripcion
taskslist[dict]Tareas de implementacion. Cada una: id, title, description, status, estimated_minutes, dependencies (list), files (list), checks (list)

acceptance.yaml.j2

VariableTipoDescripcion
checkslist[dict]Checks de aceptacion. Cada uno: id, name, type, required, tags (list), command (si type=command), paths (si type=files_exist), glob y patterns (si type=pattern_*)

context.md.j2

VariableTipoDescripcion
project_namestrNombre del proyecto
languagestrIdioma de la spec
stacklist[str]Tech stack del proyecto
conventionsdict[str, str]Convenciones del proyecto
functional_countintCantidad de requisitos funcionales
non_functional_countintCantidad de requisitos no funcionales
question_countintPreguntas abiertas
conflict_countintConflictos detectados
risk_countintRiesgos identificados
riskslist[dict]Riesgos. Cada uno: id, category, probability, impact, description
component_countintComponentes de arquitectura
files_to_create_countintArchivos a crear
files_to_modify_countintArchivos a modificar
task_countintTotal de tareas
check_countintTotal de checks

sources.md.j2

VariableTipoDescripcion
sourceslist[dict]Fuentes usadas. Cada una: source, format, word_count
all_requirementslist[dict]Todos los requisitos con id, title, source
conflictslist[dict]Conflictos con fuentes

claude_md.j2

VariableTipoDescripcion
spec_namestrNombre de la spec
context_summarystrResumen del contexto del proyecto
requirements_countintCantidad de requisitos
design_summarystrResumen del diseno
taskslist[dict]Tareas con id, title, status
acceptance_countintCantidad de checks
spec_fileslist[str]Nombres de archivos spec

claude_task.md.j2

VariableTipoDescripcion
taskdictTarea individual con id, title, status, description, checks (list)
context_summarystrResumen del contexto

verify_sh.j2

VariableTipoDescripcion
spec_namestrNombre de la spec
checkslist[dict]Checks de tipo command. Cada uno: name, command

cursor_rules.mdc.j2

VariableTipoDescripcion
spec_namestrNombre de la spec
context_summarystrResumen del contexto
requirements_countintCantidad de requisitos
requirements_summarystrResumen de requisitos
design_summarystrResumen del diseno
taskslist[dict]Tareas con id, title, status, description
acceptance_checkslist[dict]Checks con name, type, command, pattern

kiro_requirements.md.j2

VariableTipoDescripcion
spec_namestrNombre de la spec
requirementslist[dict]Requisitos con id, title, description, acceptance_criteria (list)

kiro_design.md.j2

VariableTipoDescripcion
spec_namestrNombre de la spec
design_contentstrContenido del diseno

kiro_tasks.md.j2

VariableTipoDescripcion
spec_namestrNombre de la spec
taskslist[dict]Tareas con id, title, status, description, checks (list)

copilot_instructions.md.j2

VariableTipoDescripcion
spec_namestrNombre de la spec
context_summarystrResumen del contexto
requirements_countintCantidad de requisitos
requirements_summarystrResumen de requisitos
design_summarystrResumen del diseno
taskslist[dict]Tareas con id, title, status, description
acceptance_checkslist[dict]Checks con name, command, pattern

feedback.md.j2

VariableTipoDescripcion
resultdictResultado del analisis. Tiene: failures (list), estimated_effort, summary
result.failures[].check_namestrNombre del check fallido
result.failures[].severitystrSeveridad
result.failures[].categorystrCategoria
result.failures[].root_causestrCausa raiz
result.failures[].suggestionstrSugerencia de correccion
result.failures[].affected_taskslist[str]Tareas afectadas
result.failures[].spec_amendmentdictEnmienda sugerida: target_file, section, action, content
agent_formatstrFormato del agente (claude-code, cursor, etc.)

gitlab_ci.yml.j2 / github_actions.yml.j2

VariableTipoDescripcion
spec_dirstrPath al directorio de la spec

Sintaxis Jinja2

Los templates usan Jinja2 con estas opciones habilitadas:

  • trim_blocks: el primer newline despues de un bloque {% %} se elimina
  • lstrip_blocks: whitespace al inicio de linea antes de {% %} se elimina
  • keep_trailing_newline: se preserva el newline final del archivo

Referencia rapida

{# Comentario #}

{# Variable #}
{{ variable }}

{# Loop #}
{% for item in items %}
{{ item.name }}
{% endfor %}

{# Condicional #}
{% if condition %}
contenido
{% endif %}

{# Filtro: valor por defecto #}
{{ variable | default("fallback") }}

{# Filtro: join de lista #}
{{ items | join(", ") }}

{# Filtro: longitud #}
{{ items | length }}

{# Filtro: lowercase #}
{{ text | lower }}

Ejemplos

Personalizar el formato de requisitos

Para agregar un campo “Owner” a cada requisito:

mkdir -p .intake/templates

Crear .intake/templates/requirements.md.j2:

# Requisitos del Proyecto

{% for req in functional_requirements %}
## {{ req.id }}: {{ req.title }}

{{ req.description }}

| Campo | Valor |
|-------|-------|
| Prioridad | {{ req.priority }} |
| Fuente | {{ req.source }} |
| Owner | _(por asignar)_ |

**Criterios de aceptacion:**
{% for ac in req.acceptance_criteria %}
- [ ] {{ ac }}
{% endfor %}

{% endfor %}

Personalizar verify.sh para un entorno especifico

Para agregar setup de entorno antes de los checks:

Crear .intake/templates/verify_sh.j2:

#!/usr/bin/env bash
# Verification script — {{ spec_name }}
set -euo pipefail

PROJECT_DIR="${1:-.}"
PASSED=0
FAILED=0
TOTAL=0

# Setup del entorno (personalizado)
source "${PROJECT_DIR}/.env.test" 2>/dev/null || true
export DATABASE_URL="${DATABASE_URL:-sqlite:///test.db}"

check() {
    local name="$1"
    local cmd="$2"
    TOTAL=$((TOTAL + 1))
    echo -n "  [$TOTAL] $name ... "
    if (cd "$PROJECT_DIR" && eval "$cmd") > /dev/null 2>&1; then
        echo "PASS"
        PASSED=$((PASSED + 1))
    else
        echo "FAIL"
        FAILED=$((FAILED + 1))
    fi
}

echo "=== Verification: {{ spec_name }} ==="
echo ""

{% for check in checks %}
check '{{ check.name }}' '{{ check.command }}'
{% endfor %}

echo ""
echo "=== Results: $PASSED passed, $FAILED failed (of $TOTAL) ==="

if [ "$FAILED" -gt 0 ]; then
    exit 1
fi
exit 0

Personalizar la configuracion CI generada

Para agregar cache y notificaciones a GitHub Actions:

Crear .intake/templates/github_actions.yml.j2:

name: intake-verify

on:
  pull_request:
  push:
    branches: [main, develop]

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - uses: actions/cache@v4
        with:
          path: ~/.cache/pip
          key: {% raw %}${{ runner.os }}{% endraw %}-pip-intake
      - run: pip install intake-ai-cli --quiet
      - run: intake validate {{ spec_dir }} --strict
      - run: intake verify {{ spec_dir }} -p . --format junit -o report.xml
      - uses: actions/upload-artifact@v4
        if: always()
        with:
          name: intake-report
          path: report.xml

Agregar branding corporativo a las specs

Para que todas las specs tengan un header corporativo, sobreescribe context.md.j2:

# Project Context

> Generated by intake for ACME Corp. Confidential.

| Field | Value |
|-------|-------|
| Project | {{ project_name }} |
| Language | {{ language }} |
{% if stack %}
| Stack | {{ stack | join(", ") }} |
{% endif %}
| Classification | Internal Use Only |

{% if conventions %}
## Conventions

{% for key, value in conventions.items() %}
- **{{ key }}:** {{ value }}
{% endfor %}
{% endif %}

## Metrics

| Category | Count |
|----------|-------|
| Functional requirements | {{ functional_count }} |
| Non-functional requirements | {{ non_functional_count }} |
| Open questions | {{ question_count }} |
| Risks | {{ risk_count }} |
| Tasks | {{ task_count }} |
| Checks | {{ check_count }} |

{% if risks %}
## Key Risks

{% for risk in risks %}
- **{{ risk.id }}** [{{ risk.category }}] P={{ risk.probability }} I={{ risk.impact }}: {{ risk.description }}
{% endfor %}
{% endif %}

Listar templates activos

El TemplateLoader puede listar todos los templates disponibles y su origen:

from intake.templates.loader import TemplateLoader

loader = TemplateLoader(project_dir=".")
for name, source in loader.list_templates().items():
    print(f"  {name}: {source}")

Posibles valores de source:

ValorSignificado
builtinTemplate incluido en intake
userTemplate de usuario (no sobreescribe un built-in)
user (override)Template de usuario que sobreescribe un built-in

Buenas practicas

  1. Empezar desde el built-in. Copia el template original de src/intake/templates/ antes de modificarlo. Asi no pierdes variables ni estructura.

  2. Probar los cambios. Despues de crear un override, ejecuta intake init o intake export y revisa el output.

  3. Versionar los templates. Commitea .intake/templates/ en git para que todo el equipo use los mismos templates.

  4. Mantener compatibilidad. Si actualizas intake, revisa si los templates built-in cambiaron y actualiza tus overrides si es necesario.

  5. Usar warn_on_override: true. El log te avisa cuando un template built-in esta siendo sobreescrito, util para detectar overrides olvidados.

  6. No sobreescribir todo. Solo sobreescribe los templates que necesitas cambiar. Los demas se cargan automaticamente del built-in.