Módulo 7: Remote Control y CLAUDE.md para Equipos
5. Proyecto — Setup de Equipo con CLAUDE.md Estándar y Remote Control
5. Proyecto — Setup de Equipo con CLAUDE.md Estándar y Remote Control
Descripción del Proyecto
Has aprendido cada pieza por separado: remote control para supervisión remota, approval flows para operaciones sensibles, CLAUDE.md como constitución de equipo, enforcement con hooks, y la jerarquía de merge. Ahora integras todo en un setup de equipo production-ready.
En este proyecto construyes el setup operacional completo para un equipo de 3 personas que trabajan en una API de e-commerce. Diseñas el CLAUDE.md compartido, configuras remote control, defines approval flows para operaciones destructivas, creas hooks de enforcement, y documentas el proceso de onboarding para que cualquier nuevo miembro pueda adoptar el estándar en 5 minutos.
El resultado es un repositorio que cualquier developer puede clonar y empezar a trabajar con Claude Code siguiendo las mismas reglas, sin reuniones de alineación, sin documentos de 20 páginas, sin "¿cómo configuraste tu Claude?" El CLAUDE.md es la constitución, los hooks son la policía, y el remote control es el centro de monitoreo.
Este proyecto cierra el Módulo 7 y prepara directamente el Módulo 8 (Proyecto Integrador), donde este setup es la base operacional sobre la que construirás el sistema multi-agente completo.
Objetivo del Proyecto
Construir un setup de equipo completo con CLAUDE.md, remote control, approval flows, hooks de enforcement, y proceso de onboarding, verificar que todo funciona de forma integrada, y documentar el proceso para replicarlo en cualquier proyecto.
Al completar este proyecto:
- ✅ Tendrás un CLAUDE.md de equipo production-ready con convenciones, arquitectura, prohibiciones, testing, y seguridad
- ✅ Un
settings.jsoncon hooks de enforcement que validan compliance automáticamente - ✅ Scripts de approval flow para operaciones destructivas (force push, database changes, publish)
- ✅ Configuración de remote control para monitoreo y aprobación desde otros dispositivos
- ✅ CLAUDE.md en subdirectorios para reglas específicas por módulo
- ✅ Un checklist de onboarding que un nuevo miembro puede seguir en 5 minutos
- ✅ Todo versionado y listo para commitear
Duración estimada: 1-1.5 horas (CLAUDE.md: 20 min + hooks: 20 min + approval flows: 15 min + remote control: 10 min + onboarding: 10 min + verificación: 15 min).
Especificaciones Técnicas
Contexto del proyecto
El equipo trabaja en ShopFlow API — una API REST de e-commerce con:
- Stack: Python 3.12 + FastAPI + PostgreSQL + Redis
- Equipo: 3 developers (lead, backend, frontend-api)
- Repo: Monorepo con
app/,tests/,scripts/,docs/ - CI: GitHub Actions
- Deploy: Docker + AWS
Estructura final del proyecto
Al terminar, tu proyecto tendrá estos archivos:
shopflow-api/
├── CLAUDE.md ← Constitución del equipo
├── .claude/
│ ├── settings.json ← Hooks + remote control config
│ ├── agents/ ← Subagents del equipo
│ │ ├── backend-specialist.md
│ │ └── review-agent.md
│ ├── approvals/ ← Directorio de approval requests
│ └── logs/ ← Logs de enforcement y aprobaciones
│ └── approval-audit.csv
├── app/
│ ├── CLAUDE.md ← Reglas específicas del backend
│ ├── api/
│ │ └── CLAUDE.md ← Reglas específicas de endpoints
│ ├── models/
│ ├── schemas/
│ ├── services/
│ └── core/
├── tests/
│ └── CLAUDE.md ← Reglas específicas de testing
├── scripts/
│ ├── hooks/
│ │ ├── enforce-conventions.sh ← PostToolUse: validar convenciones
│ │ ├── enforce-architecture.sh ← PostToolUse: validar capas
│ │ ├── enforce-security.sh ← PostToolUse: no secrets en código
│ │ ├── approval-gate.sh ← PermissionRequest: approval flow
│ │ ├── block-destructive.sh ← PreToolUse: bloquear operaciones peligrosas
│ │ └── session-setup.sh ← SessionStart: setup automático
│ ├── verify-setup.sh ← Script de verificación de onboarding
│ └── monitor-remote.py ← Script de monitoreo remoto
├── docs/
│ └── ONBOARDING.md ← Checklist de onboarding
└── .github/
└── CONTRIBUTING.md ← Link al CLAUDE.md y proceso
Paso 1: Crear la Estructura de Directorios
mkdir -p .claude/agents
mkdir -p .claude/approvals
mkdir -p .claude/logs
mkdir -p scripts/hooks
mkdir -p app/api app/models app/schemas app/services app/core
mkdir -p tests
mkdir -p docs
mkdir -p .github
Paso 2: CLAUDE.md Principal — La Constitución del Equipo
Crea CLAUDE.md en el root del proyecto:
# CLAUDE.md — ShopFlow API
## Contexto
ShopFlow es una API REST de e-commerce. Stack: Python 3.12, FastAPI, PostgreSQL 16, Redis 7, SQLAlchemy 2.0 async. Equipo de 3 developers. Monorepo con app/, tests/, scripts/.
## Convenciones de Código
### Python
- Type hints obligatorios en TODAS las funciones (parámetros + retorno)
- Docstrings Google format en funciones públicas
- Variables descriptivas: user_repository (NO ur, NO usrRepo)
- Funciones de máximo 30 líneas
- f-strings para interpolación
- pathlib en lugar de os.path
- async/await para toda operación de I/O
### Naming
- Archivos: snake_case.py
- Clases: PascalCase
- Funciones/variables: snake_case
- Constantes: UPPER_SNAKE_CASE
- URLs de endpoints: kebab-case (/api/v1/order-items)
### Imports (orden estricto)
1. stdlib (os, sys, typing, datetime, pathlib)
2. third-party (fastapi, sqlalchemy, pydantic, redis)
3. local (app.models, app.services, app.schemas)
Separados por línea en blanco entre grupos.
## Arquitectura
### Capas (OBLIGATORIO)
- Router → Service → Repository → DB
- NUNCA Router → DB directamente
- NUNCA Repository con lógica de negocio
- NUNCA imports circulares entre capas
### Patrones
- Repository Pattern para acceso a datos
- Dependency Injection via FastAPI Depends()
- Pydantic v2 para request/response schemas
- Factory pattern para tests
## Patrones Prohibidos
- NO typing.Any sin comentario "# justified: [razón]"
- NO print() — usar structlog logger
- NO queries SQL raw — siempre SQLAlchemy ORM
- NO hardcodear URLs, ports, o credenciales
- NO datetime.now() — usar datetime.now(UTC)
- NO import desde tests/ en código de producción
- NO modificar alembic/versions/ manualmente
- NO console.log en ningún archivo
## Testing
- Framework: pytest + httpx.AsyncClient + pytest-asyncio
- Cobertura mínima: 80%
- Cada endpoint: 1 test happy path + 1 test error
- Cada service function: test unitario
- Factories con factory-boy (no datos hardcodeados)
- Tests independientes (sin dependencia de orden)
## Git
- Conventional Commits: tipo(scope): descripción
- Tipos: feat, fix, refactor, test, docs, chore, ci
- Mensajes en inglés, imperativo, sin punto final
- Máximo 72 caracteres en primera línea
- NUNCA force push a main o develop
## Seguridad
- NUNCA commitear .env, API keys, tokens, passwords
- bcrypt para password hashing
- JWT secrets mínimo 256 bits
- Rate limiting en endpoints públicos
- Pydantic validation en TODOS los endpoints
- No exponer stack traces en respuestas de error
Paso 3: CLAUDE.md de Subdirectorios
app/CLAUDE.md
## Backend Application Rules
- Todas las funciones async usan `async def`
- Excepciones custom en app/core/exceptions.py
- Configuración centralizada en app/core/config.py via pydantic-settings
- Logger configurado en app/core/logging.py — importar desde ahí
- Cada nuevo modelo requiere migración via alembic
app/api/CLAUDE.md
## API Endpoint Rules
- Cada router en su propio archivo: app/api/users.py, app/api/orders.py
- Endpoints retornan Pydantic ResponseModel (nunca dict crudo)
- Error responses via app.core.exceptions (HTTPException solo en el router)
- Documentación OpenAPI con description y response_model
- Prefijo de versión: /api/v1/
- Listar endpoints: GET, Crear: POST, Actualizar: PUT/PATCH, Eliminar: DELETE
tests/CLAUDE.md
## Testing Rules
- Nombre de archivo: test_[módulo].py
- Nombre de test: test_[qué]_[condición]_[resultado] (test_create_user_duplicate_email_returns_409)
- Fixtures compartidas en conftest.py
- Base de datos de test: usar fixture db_session con rollback automático
- No usar sleep() en tests — usar asyncio mocks
- Cada test crea sus propios datos (no depender de seed data)
Paso 4: settings.json — Hooks y Remote Control
Crea .claude/settings.json:
{
"hooks": {
"SessionStart": [
{
"hooks": [
{
"type": "command",
"command": "./scripts/hooks/session-setup.sh"
}
]
}
],
"PreToolUse": [
{
"matcher": "Bash",
"hooks": [
{
"type": "command",
"command": "./scripts/hooks/block-destructive.sh"
}
]
}
],
"PostToolUse": [
{
"matcher": "Write|Edit",
"hooks": [
{
"type": "command",
"command": "./scripts/hooks/enforce-conventions.sh"
},
{
"type": "command",
"command": "./scripts/hooks/enforce-architecture.sh"
},
{
"type": "command",
"command": "./scripts/hooks/enforce-security.sh"
}
]
}
],
"PermissionRequest": [
{
"hooks": [
{
"type": "command",
"command": "./scripts/hooks/approval-gate.sh"
}
]
}
]
},
"remote": {
"enabled": true,
"require_auth": true,
"max_connections": 3,
"allowed_operations": ["monitor", "approve", "reject"],
"log_remote_actions": true,
"auto_disconnect_idle_minutes": 30
}
}
Paso 5: Hook SessionStart — Setup Automático
Crea scripts/hooks/session-setup.sh:
#!/bin/bash
echo "=== ShopFlow API — Session Setup ==="
LOG_DIR=".claude/logs"
mkdir -p "$LOG_DIR" ".claude/approvals"
if [ -f "$LOG_DIR/enforcement.log" ]; then
mv "$LOG_DIR/enforcement.log" "$LOG_DIR/enforcement-$(date +%Y%m%d-%H%M%S).log.bak"
fi
touch "$LOG_DIR/enforcement.log"
if ! git rev-parse --git-dir > /dev/null 2>&1; then
echo "ERROR: Not a git repository"
exit 1
fi
BRANCH=$(git branch --show-current 2>/dev/null)
echo "Branch: $BRANCH"
DIRTY=$(git status --porcelain | wc -l | tr -d ' ')
if [ "$DIRTY" -gt 20 ]; then
echo "WARNING: $DIRTY uncommitted files — consider committing first"
exit 1
fi
if [ -f "requirements.txt" ]; then
if [ -d ".venv" ]; then
source .venv/bin/activate 2>/dev/null
fi
fi
TOOLS_OK=true
for tool in ruff mypy jq; do
if ! command -v $tool &> /dev/null; then
echo "WARNING: $tool not found"
TOOLS_OK=false
fi
done
if [ "$TOOLS_OK" = true ]; then
echo "Tools: ruff, mypy, jq ✓"
fi
find .claude/approvals/ -name "*.json" -mmin +60 -delete 2>/dev/null
echo "Session ID: $(date +%Y%m%d-%H%M%S)"
echo "=== SETUP COMPLETE ==="
exit 0
chmod +x scripts/hooks/session-setup.sh
Paso 6: Hook PreToolUse — Bloquear Operaciones Destructivas
Crea scripts/hooks/block-destructive.sh:
#!/bin/bash
INPUT=$(cat -)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
if [ "$TOOL_NAME" != "Bash" ] || [ -z "$COMMAND" ]; then
exit 0
fi
BLOCKED=(
"rm -rf /"
"rm -rf ~"
"rm -rf \."
"DROP DATABASE"
"DROP TABLE"
"TRUNCATE TABLE"
"mkfs"
"dd if="
":(){:|:&};:"
"chmod -R 777 /"
"npm publish"
"pip upload"
"twine upload"
)
for pattern in "${BLOCKED[@]}"; do
if echo "$COMMAND" | grep -qi "$pattern"; then
echo "BLOCKED: Destructive operation detected"
echo "Pattern: $pattern"
echo "Command: $COMMAND"
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
echo "$TIMESTAMP | BLOCKED | $pattern | $COMMAND" >> .claude/logs/enforcement.log
exit 2
fi
done
NEEDS_APPROVAL=(
"git push --force"
"git push.*-f "
"git reset --hard"
"alembic downgrade"
"docker.*production"
"kubectl.*--force"
)
for pattern in "${NEEDS_APPROVAL[@]}"; do
if echo "$COMMAND" | grep -qiE "$pattern"; then
echo "REQUIRES APPROVAL: $COMMAND"
echo "This operation needs manual approval via remote control."
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
echo "$TIMESTAMP | NEEDS_APPROVAL | $pattern | $COMMAND" >> .claude/logs/enforcement.log
exit 1
fi
done
exit 0
chmod +x scripts/hooks/block-destructive.sh
Paso 7: Hook PostToolUse — Enforce Conventions
Crea scripts/hooks/enforce-conventions.sh:
#!/bin/bash
INPUT=$(cat -)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // empty')
if [ -z "$FILE" ] || [ ! -f "$FILE" ]; then
exit 0
fi
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
VIOLATIONS=0
if [[ "$FILE" == *.py ]]; then
BASENAME=$(basename "$FILE")
if ! echo "$BASENAME" | grep -qE "^[a-z][a-z0-9_]*\.py$"; then
echo "CONVENTION VIOLATION: Python filename must be snake_case"
echo "Got: $BASENAME"
VIOLATIONS=$((VIOLATIONS + 1))
fi
if grep -n "^import\|^from" "$FILE" | grep -v "^#" > /dev/null 2>&1; then
if command -v ruff &> /dev/null; then
IMPORT_CHECK=$(ruff check "$FILE" --select I --no-fix 2>&1)
if [ $? -ne 0 ]; then
echo "CONVENTION VIOLATION: Import order incorrect in $FILE"
echo "Expected: stdlib > third-party > local"
echo "$IMPORT_CHECK" | head -3
VIOLATIONS=$((VIOLATIONS + 1))
fi
fi
fi
if grep -n "print(" "$FILE" | grep -v "^#\|# noqa\|# justified" > /dev/null 2>&1; then
PRINT_LINES=$(grep -n "print(" "$FILE" | grep -v "^#\|# noqa\|# justified" | head -3)
echo "CONVENTION VIOLATION: print() found in $FILE"
echo "Use structlog logger instead:"
echo "$PRINT_LINES"
VIOLATIONS=$((VIOLATIONS + 1))
fi
if grep -n "datetime\.now()" "$FILE" | grep -v "now(UTC)\|now(timezone.utc)" > /dev/null 2>&1; then
echo "CONVENTION VIOLATION: datetime.now() without UTC in $FILE"
echo "Use: datetime.now(UTC)"
VIOLATIONS=$((VIOLATIONS + 1))
fi
if command -v ruff &> /dev/null; then
LINT_RESULT=$(ruff check "$FILE" --no-fix 2>&1)
if [ $? -ne 0 ]; then
echo "LINT ERRORS in $FILE:"
echo "$LINT_RESULT" | head -5
VIOLATIONS=$((VIOLATIONS + 1))
fi
fi
fi
if [ $VIOLATIONS -gt 0 ]; then
echo "$TIMESTAMP | VIOLATIONS: $VIOLATIONS | $FILE" >> .claude/logs/enforcement.log
exit 1
fi
echo "$TIMESTAMP | PASS | $FILE" >> .claude/logs/enforcement.log
exit 0
chmod +x scripts/hooks/enforce-conventions.sh
Paso 8: Hook PostToolUse — Enforce Architecture
Crea scripts/hooks/enforce-architecture.sh:
#!/bin/bash
INPUT=$(cat -)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // empty')
if [ -z "$FILE" ] || [ ! -f "$FILE" ] || [[ "$FILE" != *.py ]]; then
exit 0
fi
if echo "$FILE" | grep -q "^app/api/"; then
if grep -n "from app\.models\|import.*Session\|from sqlalchemy" "$FILE" | grep -v "from app\.schemas\|from app\.services\|from app\.core" > /dev/null 2>&1; then
DIRECT_DB=$(grep -n "Session\|engine\|select(\|insert(\|update(\|delete(" "$FILE" | grep -v "^#\|# allowed" | head -3)
if [ -n "$DIRECT_DB" ]; then
echo "ARCHITECTURE VIOLATION: Router accessing DB directly"
echo "File: $FILE"
echo "Rule: Router → Service → Repository → DB"
echo "Found:"
echo "$DIRECT_DB"
exit 1
fi
fi
fi
if echo "$FILE" | grep -q "^app/repositories/"; then
if grep -n "raise HTTPException\|from fastapi" "$FILE" | grep -v "^#" > /dev/null 2>&1; then
echo "ARCHITECTURE VIOLATION: Repository contains HTTP logic"
echo "File: $FILE"
echo "Rule: Repositories handle data access only, not HTTP responses"
exit 1
fi
fi
if echo "$FILE" | grep -q "^app/" && [[ "$FILE" != *"test"* ]]; then
if grep -n "from tests\.\|import tests\." "$FILE" > /dev/null 2>&1; then
echo "ARCHITECTURE VIOLATION: Production code imports from tests/"
echo "File: $FILE"
exit 1
fi
fi
exit 0
chmod +x scripts/hooks/enforce-architecture.sh
Paso 9: Hook PostToolUse — Enforce Security
Crea scripts/hooks/enforce-security.sh:
#!/bin/bash
INPUT=$(cat -)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // empty')
if [ -z "$FILE" ] || [ ! -f "$FILE" ]; then
exit 0
fi
BASENAME=$(basename "$FILE")
if echo "$BASENAME" | grep -qE "^\.env"; then
echo "SECURITY VIOLATION: .env files must not be created or modified by agents"
echo "File: $FILE"
exit 2
fi
if [[ "$FILE" == *.py ]] || [[ "$FILE" == *.ts ]] || [[ "$FILE" == *.js ]]; then
SECRET_PATTERNS=(
"password\s*=\s*[\"'][^\"']+[\"']"
"api_key\s*=\s*[\"'][^\"']+[\"']"
"secret\s*=\s*[\"'][^\"']+[\"']"
"token\s*=\s*[\"'][A-Za-z0-9+/=_-]{20,}[\"']"
"AWS_SECRET_ACCESS_KEY\s*=\s*[\"']"
"PRIVATE_KEY\s*=\s*[\"']"
)
for pattern in "${SECRET_PATTERNS[@]}"; do
if grep -inE "$pattern" "$FILE" | grep -v "os\.environ\|os\.getenv\|config\.\|settings\.\|\.env\|# example\|# test\|_PLACEHOLDER\|changeme\|xxx" > /dev/null 2>&1; then
FOUND=$(grep -inE "$pattern" "$FILE" | grep -v "os\.environ\|os\.getenv\|config\.\|settings\.\|\.env\|# example\|# test\|_PLACEHOLDER\|changeme\|xxx" | head -2)
echo "SECURITY VIOLATION: Potential hardcoded secret in $FILE"
echo "Found:"
echo "$FOUND"
echo ""
echo "Use environment variables or app.core.config instead."
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")
echo "$TIMESTAMP | SECURITY | hardcoded_secret | $FILE" >> .claude/logs/enforcement.log
exit 1
fi
done
fi
exit 0
chmod +x scripts/hooks/enforce-security.sh
Paso 10: Hook PermissionRequest — Approval Gate
Crea scripts/hooks/approval-gate.sh:
#!/bin/bash
INPUT=$(cat -)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')
FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // empty')
AUTO_APPROVE=(
"Read"
"Grep"
"Glob"
)
for tool in "${AUTO_APPROVE[@]}"; do
if [ "$TOOL_NAME" = "$tool" ]; then
exit 0
fi
done
if [ "$TOOL_NAME" = "Write" ] || [ "$TOOL_NAME" = "Edit" ]; then
if echo "$FILE_PATH" | grep -qE "^(app/|tests/|docs/|scripts/)"; then
exit 0
fi
fi
if [ "$TOOL_NAME" = "Bash" ]; then
if echo "$COMMAND" | grep -qE "^(ls|cat|echo|pwd|which|python -m pytest|ruff|mypy|git status|git log|git diff|git branch)"; then
exit 0
fi
fi
AUDIT_LOG=".claude/logs/approval-audit.csv"
if [ ! -f "$AUDIT_LOG" ]; then
echo "timestamp,action,tool,detail" > "$AUDIT_LOG"
fi
APPROVAL_DIR=".claude/approvals"
mkdir -p "$APPROVAL_DIR"
APPROVAL_ID="approval-$(date +%s)-$$"
cat > "$APPROVAL_DIR/$APPROVAL_ID.json" << EOF
{
"id": "$APPROVAL_ID",
"timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
"tool": "$TOOL_NAME",
"command": "$COMMAND",
"file": "$FILE_PATH",
"status": "pending",
"timeout_seconds": 300
}
EOF
echo "APPROVAL REQUIRED"
echo "Operation: $TOOL_NAME"
echo "Detail: ${COMMAND:-$FILE_PATH}"
echo "ID: $APPROVAL_ID"
echo "Approve via remote control or: touch $APPROVAL_DIR/$APPROVAL_ID.approved"
TIMEOUT=300
ELAPSED=0
while [ $ELAPSED -lt $TIMEOUT ]; do
if [ -f "$APPROVAL_DIR/$APPROVAL_ID.approved" ]; then
echo "$(date -u +%Y-%m-%dT%H:%M:%SZ),APPROVED,$TOOL_NAME,${COMMAND:-$FILE_PATH}" >> "$AUDIT_LOG"
rm -f "$APPROVAL_DIR/$APPROVAL_ID.json" "$APPROVAL_DIR/$APPROVAL_ID.approved"
echo "APPROVED"
exit 0
fi
if [ -f "$APPROVAL_DIR/$APPROVAL_ID.rejected" ]; then
echo "$(date -u +%Y-%m-%dT%H:%M:%SZ),REJECTED,$TOOL_NAME,${COMMAND:-$FILE_PATH}" >> "$AUDIT_LOG"
rm -f "$APPROVAL_DIR/$APPROVAL_ID.json" "$APPROVAL_DIR/$APPROVAL_ID.rejected"
echo "REJECTED"
exit 2
fi
sleep 5
ELAPSED=$((ELAPSED + 5))
done
echo "$(date -u +%Y-%m-%dT%H:%M:%SZ),TIMEOUT,$TOOL_NAME,${COMMAND:-$FILE_PATH}" >> "$AUDIT_LOG"
rm -f "$APPROVAL_DIR/$APPROVAL_ID.json"
echo "TIMEOUT: No approval in ${TIMEOUT}s — operation rejected"
exit 2
chmod +x scripts/hooks/approval-gate.sh
Paso 11: Subagents del Equipo
Backend Specialist
Crea .claude/agents/backend-specialist.md:
---
name: backend-specialist
description: ShopFlow backend specialist. Implements services, repositories, and models.
tools: Read, Write, Edit, Grep, Glob, Bash
hooks:
PreToolUse:
- matcher: "Write|Edit"
hooks:
- type: command
command: |
#!/bin/bash
INPUT=$(cat -)
FILE=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.path // empty')
if [ -n "$FILE" ] && ! echo "$FILE" | grep -qE "^(app/|tests/|scripts/)"; then
echo "BLOCKED: backend-specialist can only edit app/, tests/, scripts/"
exit 2
fi
exit 0
---
You are the backend specialist for ShopFlow API. You implement business logic in services, data access in repositories, and database models.
Follow the project CLAUDE.md strictly. Key rules:
- Type hints on all functions
- Repository Pattern: services call repositories, never access DB directly
- Async/await for all I/O
- Use structlog, never print()
- Factory pattern for test data
Review Agent
Crea .claude/agents/review-agent.md:
---
name: review-agent
description: Code review specialist. Reads code and reports issues. Does NOT modify files.
tools: Read, Grep, Glob
---
You are the code review agent for ShopFlow API. You review code for compliance with the project CLAUDE.md.
Your process:
1. Read the files specified in the task
2. Check against CLAUDE.md rules: type hints, naming, architecture layers, forbidden patterns
3. Report violations with file, line, and specific rule violated
4. Suggest fixes but do NOT edit files
Output format:
- PASS: No violations found
- VIOLATIONS: List each with file:line — rule — description
Paso 12: Script de Monitoreo Remoto
Crea scripts/monitor-remote.py:
#!/usr/bin/env python3
"""
ShopFlow API — Remote Monitor
Monitorea sesiones de Claude Code y aprobaciones pendientes.
Uso:
python scripts/monitor-remote.py <session_id> <token>
python scripts/monitor-remote.py --local (modo local, sin remote control)
"""
import json
import sys
import time
from pathlib import Path
from datetime import datetime
APPROVALS_DIR = Path(".claude/approvals")
LOGS_DIR = Path(".claude/logs")
def check_local_approvals():
pending = []
if not APPROVALS_DIR.exists():
return pending
for f in APPROVALS_DIR.glob("*.json"):
try:
data = json.loads(f.read_text())
if data.get("status") == "pending":
pending.append(data)
except (json.JSONDecodeError, KeyError):
continue
return pending
def approve_local(approval_id):
approval_file = APPROVALS_DIR / f"{approval_id}.approved"
approval_file.touch()
print(f"Approved: {approval_id}")
def reject_local(approval_id):
approval_file = APPROVALS_DIR / f"{approval_id}.rejected"
approval_file.touch()
print(f"Rejected: {approval_id}")
def display_local_dashboard():
print(f"\033[2J\033[H")
print(f"{'='*55}")
print(f" SHOPFLOW API — LOCAL MONITOR")
print(f" {datetime.now().strftime('%H:%M:%S')}")
print(f"{'='*55}")
pending = check_local_approvals()
if pending:
print(f"\n ⚠️ PENDING APPROVALS ({len(pending)}):\n")
for p in pending:
print(f" ID: {p['id']}")
print(f" Tool: {p.get('tool', '?')}")
detail = p.get('command') or p.get('file') or 'N/A'
print(f" Info: {detail}")
print(f" Time: {p.get('timestamp', '?')}")
print()
else:
print(f"\n ✅ No pending approvals\n")
log_file = LOGS_DIR / "enforcement.log"
if log_file.exists():
lines = log_file.read_text().strip().split("\n")
recent = lines[-5:] if len(lines) > 5 else lines
print(f" Recent enforcement ({len(lines)} total):")
for line in recent:
print(f" {line}")
audit_file = LOGS_DIR / "approval-audit.csv"
if audit_file.exists():
lines = audit_file.read_text().strip().split("\n")
if len(lines) > 1:
print(f"\n Approval history ({len(lines)-1} decisions):")
for line in lines[-3:]:
print(f" {line}")
print(f"\n{'='*55}")
def interactive_mode():
print("ShopFlow API — Local Approval Monitor")
print("Commands: [a]pprove <id>, [r]eject <id>, [q]uit\n")
while True:
display_local_dashboard()
pending = check_local_approvals()
if pending:
try:
cmd = input("\nCommand (a/r/q): ").strip().lower()
except (EOFError, KeyboardInterrupt):
break
parts = cmd.split(maxsplit=1)
if not parts:
continue
if parts[0] == "q":
break
elif parts[0] == "a" and len(parts) == 2:
approve_local(parts[1])
elif parts[0] == "r" and len(parts) == 2:
reject_local(parts[1])
else:
print("Unknown command. Use: a <id>, r <id>, q")
else:
time.sleep(5)
def main():
if len(sys.argv) < 2:
print("Uso:")
print(" python scripts/monitor-remote.py --local")
print(" python scripts/monitor-remote.py <session_id> <token>")
sys.exit(1)
if sys.argv[1] == "--local":
interactive_mode()
else:
print("Remote monitoring requires Claude Code remote control.")
print("Falling back to local mode...")
interactive_mode()
if __name__ == "__main__":
main()
chmod +x scripts/monitor-remote.py
Paso 13: Script de Verificación de Onboarding
Crea scripts/verify-setup.sh:
#!/bin/bash
echo "============================================"
echo " ShopFlow API — Setup Verification"
echo "============================================"
echo ""
ERRORS=0
WARNINGS=0
check() {
local description=$1
local condition=$2
if eval "$condition"; then
echo " ✅ $description"
else
echo " ❌ $description"
ERRORS=$((ERRORS + 1))
fi
}
warn() {
local description=$1
local condition=$2
if eval "$condition"; then
echo " ✅ $description"
else
echo " ⚠️ $description"
WARNINGS=$((WARNINGS + 1))
fi
}
echo "Files:"
check "CLAUDE.md exists" "[ -f CLAUDE.md ]"
check ".claude/settings.json exists" "[ -f .claude/settings.json ]"
check "settings.json has hooks" "jq -e '.hooks' .claude/settings.json > /dev/null 2>&1"
check "app/CLAUDE.md exists" "[ -f app/CLAUDE.md ]"
check "app/api/CLAUDE.md exists" "[ -f app/api/CLAUDE.md ]"
check "tests/CLAUDE.md exists" "[ -f tests/CLAUDE.md ]"
echo ""
echo "Hook scripts:"
HOOK_DIR="scripts/hooks"
for script in session-setup.sh block-destructive.sh enforce-conventions.sh enforce-architecture.sh enforce-security.sh approval-gate.sh; do
check "$script exists and is executable" "[ -x $HOOK_DIR/$script ]"
done
echo ""
echo "Agents:"
check "backend-specialist.md exists" "[ -f .claude/agents/backend-specialist.md ]"
check "review-agent.md exists" "[ -f .claude/agents/review-agent.md ]"
echo ""
echo "Directories:"
check ".claude/approvals/ exists" "[ -d .claude/approvals ]"
check ".claude/logs/ exists" "[ -d .claude/logs ]"
echo ""
echo "Tools:"
warn "ruff installed" "command -v ruff &> /dev/null"
warn "mypy installed" "command -v mypy &> /dev/null"
warn "jq installed" "command -v jq &> /dev/null"
warn "git initialized" "git rev-parse --git-dir > /dev/null 2>&1"
echo ""
echo "============================================"
if [ $ERRORS -eq 0 ] && [ $WARNINGS -eq 0 ]; then
echo " ✅ ALL CHECKS PASSED"
elif [ $ERRORS -eq 0 ]; then
echo " ⚠️ $WARNINGS warnings (non-critical)"
else
echo " ❌ $ERRORS errors, $WARNINGS warnings"
fi
echo "============================================"
exit $ERRORS
chmod +x scripts/verify-setup.sh
Paso 14: Documentación de Onboarding
Crea docs/ONBOARDING.md:
# ShopFlow API — Developer Onboarding
## Quick Start (5 minutos)
### 1. Clone the repo
```bash
git clone <repo-url>
cd shopflow-api
2. Verify setup
./scripts/verify-setup.sh
3. Install missing tools (if any)
# macOS
brew install jq
pip install ruff mypy
# Ubuntu/Debian
sudo apt-get install jq
pip install ruff mypy
4. Start working
Open Claude Code in the project. The CLAUDE.md and hooks are loaded automatically.
What Happens Automatically
When you open Claude Code in this project:
- SessionStart hook verifies your environment (git, tools, clean workspace)
- CLAUDE.md loads the team standard (conventions, architecture, prohibitions)
- PostToolUse hooks validate every file edit against the standard
- PreToolUse hooks block destructive operations (force push, DROP TABLE)
- Approval flows pause sensitive operations until you approve them
You don't need to configure anything. It just works.
Key Files
| File | Purpose |
|---|---|
CLAUDE.md | Team standard — READ THIS FIRST |
.claude/settings.json | Hooks and remote control configuration |
app/CLAUDE.md | Backend-specific rules |
app/api/CLAUDE.md | API endpoint-specific rules |
tests/CLAUDE.md | Testing-specific rules |
scripts/hooks/ | Enforcement scripts |
.claude/agents/ | Team subagents |
Remote Control
To monitor a session from another device:
claude --remote
# Note the session ID and token
# From another device:
claude remote status --session <ID> --token <TOKEN>
To approve operations from another terminal:
python scripts/monitor-remote.py --local
Questions?
Read the CLAUDE.md first. If your question isn't answered there, ask in the #shopflow-dev channel.
Crea `.github/CONTRIBUTING.md`:
```markdown
# Contributing to ShopFlow API
## Before You Start
1. Read `CLAUDE.md` in the project root — it's the team standard
2. Run `./scripts/verify-setup.sh` to verify your environment
3. Read `docs/ONBOARDING.md` for the full onboarding guide
## Development Workflow
1. Create a feature branch: `git checkout -b feature/my-feature`
2. Make changes using Claude Code (hooks enforce the standard automatically)
3. Run tests: `python -m pytest tests/ -v`
4. Commit with conventional format: `feat(auth): add JWT refresh endpoint`
5. Create a PR with description of what, why, and how to test
## Claude Code Agents
- `backend-specialist`: For implementing services, models, repositories
- `review-agent`: For code review against CLAUDE.md standards
## Approval Flows
Some operations require manual approval:
- `git push --force` → Always blocked
- `git push` to non-feature branches → Requires approval
- Database migrations → Requires approval
- File modifications outside `app/`, `tests/`, `scripts/` → Requires approval
Use `python scripts/monitor-remote.py --local` to manage approvals.
Paso 15: Verificar Todo el Setup
Test 1: Verificación de estructura
./scripts/verify-setup.sh
Resultado esperado: todos los checks pasan (verdes). Warnings para herramientas no instaladas son aceptables.
Test 2: Test de hooks de enforcement
echo '{"tool_name":"Edit","tool_input":{"file_path":"app/services/user_service.py"}}' | \
./scripts/hooks/enforce-conventions.sh
echo "Exit code: $?"
echo '{"tool_name":"Edit","tool_input":{"file_path":"app/api/routes.py"}}' | \
./scripts/hooks/enforce-architecture.sh
echo "Exit code: $?"
Test 3: Test de bloqueo destructivo
echo '{"tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' | \
./scripts/hooks/block-destructive.sh
echo "Exit code: $?"
echo '{"tool_name":"Bash","tool_input":{"command":"ls -la"}}' | \
./scripts/hooks/block-destructive.sh
echo "Exit code: $?"
Resultado esperado:
rm -rf /→ exit 2 (bloqueado)ls -la→ exit 0 (permitido)
Test 4: Test de security enforcement
echo '{"tool_name":"Write","tool_input":{"file_path":".env.production"}}' | \
./scripts/hooks/enforce-security.sh
echo "Exit code: $?"
echo '{"tool_name":"Write","tool_input":{"file_path":"app/services/auth.py"}}' | \
./scripts/hooks/enforce-security.sh
echo "Exit code: $?"
Resultado esperado:
.env.production→ exit 2 (bloqueado)app/services/auth.py→ exit 0 (si no tiene secrets hardcodeados)
Test 5: Test del approval flow
# Terminal 1: Simular una solicitud de aprobación
echo '{"tool_name":"Bash","tool_input":{"command":"git push origin main"}}' | \
./scripts/hooks/approval-gate.sh &
# Terminal 2: Aprobar la solicitud
sleep 2
APPROVAL_ID=$(ls .claude/approvals/ | grep "approval-" | sed 's/.json//' | head -1)
touch ".claude/approvals/$APPROVAL_ID.approved"
Checklist de éxito
✅ CLAUDE.md en el root con todas las secciones del equipo
✅ CLAUDE.md en app/, app/api/, tests/ con reglas específicas
✅ settings.json con SessionStart, PreToolUse, PostToolUse, PermissionRequest hooks
✅ 6 scripts de hooks, todos ejecutables
✅ 2 subagents configurados con restricciones
✅ Script de monitoreo remoto funcional
✅ Script de verificación de setup pasa sin errores
✅ ONBOARDING.md con checklist de 5 minutos
✅ CONTRIBUTING.md con link al CLAUDE.md
✅ Bloqueo de operaciones destructivas funciona (exit 2)
✅ Approval flow crea solicitudes y espera respuesta
✅ Enforcement hooks detectan violaciones de convenciones
Errores Comunes y Soluciones
Error 1: "Permission denied" en scripts de hooks
Síntoma: Los hooks no se ejecutan y Claude Code reporta error de permisos.
Causa: Los scripts no tienen permisos de ejecución.
Solución:
chmod +x scripts/hooks/*.sh
ls -la scripts/hooks/
Error 2: "jq: command not found" en hooks
Síntoma: Los hooks que parsean JSON fallan silenciosamente. Las validaciones no funcionan.
Causa: jq no está instalado.
Solución:
# macOS
brew install jq
# Ubuntu/Debian
sudo apt-get install jq
# Verificar
jq --version
Error 3: "Enforcement hook es demasiado estricto"
Síntoma: Claude Code no puede completar ninguna tarea porque los hooks rechazan todo.
Causa: Los patrones de detección son demasiado amplios (falsos positivos).
Solución: Agrega excepciones para casos legítimos:
# En enforce-conventions.sh, permitir print() en scripts de CLI:
if echo "$FILE" | grep -q "^scripts/"; then
exit 0 # No enforcement en scripts utilitarios
fi
Error 4: "Approval timeout demasiado corto"
Síntoma: Las operaciones se rechazan por timeout antes de que puedas revisarlas.
Causa: El timeout default de 300 segundos (5 minutos) no es suficiente.
Solución: Aumenta el timeout en approval-gate.sh:
TIMEOUT=600 # 10 minutos en lugar de 5
Error 5: "CLAUDE.md del subdirectorio no se aplica"
Síntoma: Claude Code parece ignorar las reglas del subdirectorio.
Causa: El archivo CLAUDE.md está en la ubicación incorrecta o tiene un nombre diferente.
Solución: Verifica que:
- El archivo se llama exactamente
CLAUDE.md(mayúsculas) - Está en el directorio correcto:
app/api/CLAUDE.md, noapp/api/claude.md - Claude Code tiene acceso de lectura al archivo
find . -name "CLAUDE.md" -type f
Error 6: "Los hooks se ejecutan en cada herramienta y hacen todo lento"
Síntoma: Claude Code tarda 3-5 segundos en cada operación por los hooks de enforcement.
Causa: Los hooks corren ruff, mypy, y grep en cada edición.
Solución: Optimiza los hooks para ser más selectivos:
# Solo correr ruff si el archivo realmente cambió
FILE_HASH=$(md5 -q "$FILE" 2>/dev/null || md5sum "$FILE" | cut -d' ' -f1)
HASH_FILE="/tmp/hook-hash-$(echo "$FILE" | md5 -q 2>/dev/null || echo "$FILE" | md5sum | cut -c1-8)"
if [ -f "$HASH_FILE" ] && [ "$(cat "$HASH_FILE")" = "$FILE_HASH" ]; then
exit 0 # Ya se validó este contenido
fi
echo "$FILE_HASH" > "$HASH_FILE"
Error 7: "El review-agent intenta editar archivos"
Síntoma: El review-agent reporta errores porque no tiene permisos de edición.
Causa: El prompt del agente o la tarea le pide hacer cambios, pero sus tools solo incluyen Read, Grep, Glob.
Solución: Esto es intencional. El review-agent es de solo lectura. Si necesitas que aplique fixes, usa el backend-specialist con los hallazgos del review-agent como input.
Error 8: "Archivos de aprobación se acumulan en .claude/approvals/"
Síntoma: El directorio se llena de archivos .json de solicitudes antiguas.
Causa: Los archivos de aprobaciones expiradas no se limpian.
Solución: El SessionStart hook ya incluye limpieza de archivos de más de 60 minutos. Si necesitas limpieza manual:
find .claude/approvals/ -name "*.json" -mmin +60 -delete
Conexión con el Siguiente Módulo
Has construido un setup de equipo completo. El CLAUDE.md es la constitución, los hooks son los guardianes, el remote control es el centro de monitoreo, y el proceso de onboarding hace que cualquier nuevo miembro adopte el estándar automáticamente.
El Módulo 8: Proyecto Integrador usa este setup como base operacional. El CLAUDE.md define las reglas que todos los agentes del sistema multi-agente respetan. Los hooks validan cada acción de cada agente. El remote control permite aprobar operaciones críticas durante la ejecución. Los subagents que definiste trabajan dentro de las restricciones que configuraste.
Todo lo que construiste en los Módulos 1-7 se integra en el proyecto final: subagents especializados (M1) con memoria compartida (M2) trabajando en paralelo (M3) como Agent Team (M4), empaquetados en plugins (M5), automatizados con hooks y SDK (M6), operados remotamente con estándares de equipo (M7). El Módulo 8 es la prueba de que todo funciona junto.
Resumen
- Construiste un setup de equipo completo con CLAUDE.md, hooks de enforcement, approval flows, remote control, y onboarding
- El CLAUDE.md principal define convenciones, arquitectura, prohibiciones, testing, git, y seguridad para todo el equipo
- CLAUDE.md en subdirectorios (app/, app/api/, tests/) agregan reglas específicas por módulo
- 6 hooks cubren todo el ciclo: SessionStart (setup), PreToolUse (bloqueo), PostToolUse (enforcement ×3), PermissionRequest (approval)
- Los hooks de enforcement validan convenciones (naming, imports, print), arquitectura (capas, no circular), y seguridad (no secrets)
- El approval flow pausa operaciones sensibles, escribe solicitudes a archivos, y espera aprobación con timeout de 5 minutos
- 2 subagents (backend-specialist, review-agent) trabajan dentro de las restricciones del equipo
- El script de monitoreo permite gestionar aprobaciones localmente o via remote control
- El script de verificación valida que todo el setup está completo en una ejecución
- ONBOARDING.md y CONTRIBUTING.md documentan el proceso para nuevos miembros
- Este setup es la base operacional del Módulo 8 (Proyecto Integrador)
Recursos del Proyecto
- Claude Code CLAUDE.md Memory — Documentación oficial de CLAUDE.md y sus niveles
- Claude Code Settings — Configuración de settings.json y hooks
- Claude Code Hooks — Documentación completa de hooks
- Claude Code Subagents — Configuración de subagents con restricciones
- Claude Code Best Practices — Buenas prácticas para equipos
- Conventional Commits — Especificación de conventional commits
Siguiente módulo: El Módulo 8 (Proyecto Integrador: Sistema Multi-Agente Completo) integra todo lo construido en los Módulos 1-7. Los subagents especializados con memoria compartida trabajan en paralelo como Agent Team, empaquetados en plugins, automatizados con hooks y SDK, operados remotamente con el CLAUDE.md como constitución. Es el cierre de la guía — un sistema multi-agente completo que funciona de principio a fin.