Módulo 5: Skills y Hooks: automatizar tu workflow

Permission System: Control de acceso en Claude Code

Permission System: Control de acceso en Claude Code

Descripción

Claude Code es un agente que puede leer tu codebase, escribir archivos, ejecutar comandos en terminal, instalar paquetes, y hacer commits. Ese poder es lo que lo hace útil — y es exactamente lo que lo hace peligroso si no se controla. El permission system es el mecanismo que garantiza que Claude Code actúe solo dentro de los límites que tú defines.

Esta cápsula cubre el modelo de permisos de Claude Code: qué acciones requieren aprobación, cómo configurar niveles de confianza, qué hace el flag --dangerously-skip-permissions (y por qué su nombre es una advertencia), y cómo diseñar una política de permisos para proyectos reales donde la seguridad importa.

El permission system es el cierre natural de este módulo. Skills te dan control sobre qué hace Claude. Hooks te dan control sobre cómo se valida. Permissions te dan control sobre qué puede hacer Claude. Juntos, forman un sistema de gobernanza completo.


El modelo de permisos

Claude Code opera bajo un principio simple: pedir antes de actuar. Antes de ejecutar cualquier acción que modifique tu sistema, Claude te pide confirmación.

Acciones que requieren aprobación

AcciónRiesgoAprobación por defecto
Leer archivosBajo✅ Automática (no pide)
Buscar en archivos (grep/glob)Bajo✅ Automática
Escribir/editar archivosMedio⚠️ Pide confirmación
Crear archivos nuevosMedio⚠️ Pide confirmación
Ejecutar comandos en terminalAlto⚠️ Pide confirmación
Instalar paquetesAlto⚠️ Pide confirmación
Hacer requests HTTPMedio⚠️ Pide confirmación
Operaciones git (commit, push)Alto⚠️ Pide confirmación
Eliminar archivosAlto⚠️ Pide confirmación

Cómo se ve la solicitud de permiso

Cuando Claude quiere ejecutar una acción que requiere aprobación, muestra un prompt como este:

Claude wants to execute: npm test
Allow? [y/n/always]

Tus opciones:

OpciónQué hace
y (yes)Permite esta acción una vez
n (no)Bloquea esta acción
alwaysPermite esta acción siempre (para esta sesión y futuras)

El flujo de decisión

Claude quiere ejecutar una acción
  │
  ▼
¿Está en allowedTools? ──── Sí ──▶ Ejecutar sin preguntar
  │
  No
  │
  ▼
¿El usuario ya dijo "always"? ──── Sí ──▶ Ejecutar sin preguntar
  │
  No
  │
  ▼
Mostrar prompt de permiso
  │
  ├── y → Ejecutar (solo esta vez)
  ├── n → No ejecutar
  └── always → Ejecutar + recordar para siempre

Niveles de permiso (modos)

Claude Code tiene 6 permission modes, de más restrictivo a más permisivo:

  1. Default (default) — solo lecturas auto-aprobadas; pide confirmación para escrituras y comandos
  2. Accept edits (acceptEdits) — auto-aprueba escrituras a archivos; pide confirmación para comandos
  3. Plan (plan) — modo read-only para investigación y diseño antes de ejecutar
  4. Auto mode (auto) — classifier decide automáticamente (research preview, marzo 2026)
  5. Don't ask (dontAsk) — auto-aprueba un set explícito de tools que tú definiste, pregunta el resto
  6. Bypass permissions (bypassPermissions) — aprueba todo (--dangerously-skip-permissions)

Cambiar entre modos con Shift+Tab: el cycle por defecto rota entre default → acceptEdits → plan. Los modos auto y bypassPermissions se agregan al cycle si los habilitas explícitamente. dontAsk nunca aparece en el cycle (solo se activa por configuración). El modo actual se muestra en el footer.

Nivel 1: Ask every time (default)

Claude pide confirmación cada vez que quiere ejecutar una acción que modifica tu sistema.

Claude wants to write to: src/components/Button.tsx
Allow? [y/n/always]

Claude wants to execute: npm install axios
Allow? [y/n/always]

Claude wants to execute: git commit -m "Add Button"
Allow? [y/n/always]

Cuándo usarlo: Proyectos nuevos, codebases que no conoces bien, trabajo con agentes que no has verificado.

Nivel 2: Allow for session

Cuando respondes y a un permiso, Claude puede ejecutar esa acción específica en la sesión actual. En la siguiente sesión, volverá a preguntar.

Esto aplica cuando Claude te pide permiso y tú dices "sí" — no se recuerda entre sesiones.

Cuándo usarlo: La mayoría del desarrollo diario. Le dices "sí" a las acciones que esperas, y Claude deja de preguntar durante la sesión.

Nivel 3: Always allow (configurado en settings)

Configuras en settings qué herramientas Claude puede usar sin preguntar. Esto persiste entre sesiones.

{
  "allowedTools": [
    "Read",
    "Grep",
    "Glob",
    "Write",
    "Execute"
  ]
}

Cuándo usarlo: Después de establecer confianza. Proyectos personales donde sabes exactamente qué hace Claude. Workflows repetitivos donde las confirmaciones son fricción innecesaria.

Nivel 4: Auto Mode (research preview, marzo 2026)

El gran cambio de 2026: en vez de aprobar manualmente cada acción, Auto Mode pone un classifier delante de los permission prompts. Acciones seguras corren sin interrupción; acciones destructivas o sospechosas se bloquean y se te surfacean.

Es el punto medio entre:

  • Ask every time (demasiada fricción para sesiones largas)
  • --dangerously-skip-permissions (demasiado riesgo — aprueba todo)

Cómo funciona el classifier:

Claude quiere ejecutar una acción
  │
  ▼
Classifier evalúa riesgo
  │
  ├── Acción segura (edit archivo de src/, run test) → ✅ Ejecuta sin preguntar
  ├── Acción dudosa (delete, force push) → ⚠️ Te surfacea para que decidas
  └── Acción peligrosa (rm -rf /, sudo) → ❌ Bloquea

Activarlo:

# Durante una sesión: Shift+Tab para ciclar al modo auto
# Se ve en el footer: "auto mode on"

O configuralo como default en settings:

{
  "permissions": {
    "defaultMode": "auto"
  }
}

Cuándo usarlo:

  • Sesiones largas donde aprobar cada acción se vuelve ruido
  • Developers que confían en el classifier para filtrar lo peligroso
  • Como alternativa más segura a --dangerously-skip-permissions

Cuándo NO usarlo:

  • Proyectos críticos de producción donde cada acción necesita review humano
  • Primera sesión con Claude en un codebase nuevo (mejor empezar con default)
  • Cuando estás debuggeando comportamiento del agente

Requisitos para usar Auto Mode (mayo 2026):

  • Plan: Max, Team, Enterprise o API directo. No disponible en Pro plan.
  • Modelo: Sonnet 5 u Opus 5 en Team/Enterprise/API; Opus 5 en Max.
  • Provider: solo Anthropic API directo. No funciona vía Bedrock, Vertex ni Foundry.
  • Versión Claude Code: v2.1.83 o superior.
  • Admin controls: en Team/Enterprise el admin debe habilitarlo explícitamente; puede bloquearlo con permissions.disableAutoMode: "disable" en settings.

Comportamiento de fallback: si el classifier bloquea 3 acciones consecutivas o 20 totales en una sesión, Auto Mode se pausa y vuelve a prompts manuales. En modo headless (-p), bloqueos repetidos abortan la sesión completa.

Nota importante: Auto Mode sigue en research preview en mayo 2026. El classifier mejora con el tiempo pero no es infalible. Siempre revisa el output y los commits antes de pushear.


Configurar permisos en settings

Dónde se configuran

Los permisos se configuran en los mismos archivos de settings que los hooks:

ArchivoScopeEjemplo de uso
.claude/settings.jsonProyecto (compartido con equipo)Permisos del proyecto para todo el equipo
.claude/settings.local.jsonPersonal (no compartido)Tus permisos personales

Formato de allowedTools

{
  "allowedTools": [
    "Read",
    "Write",
    "Execute",
    "Grep",
    "Glob"
  ]
}

Cada entry en allowedTools es el nombre de una herramienta que Claude puede usar sin pedir permiso.

Herramientas configurables

HerramientaQué permite
ReadLeer archivos (ya permitido por defecto en la mayoría de configuraciones)
WriteEscribir y editar archivos
ExecuteEjecutar comandos en terminal
GrepBuscar contenido en archivos
GlobBuscar archivos por patrón
WebFetchHacer peticiones HTTP

Permisos granulares con patrones

Puedes ser más específico usando patrones en allowedTools:

{
  "allowedTools": [
    "Read",
    "Grep",
    "Glob",
    "Write(src/**)",
    "Execute(npm test)",
    "Execute(npm run lint)",
    "Execute(git status)",
    "Execute(git diff)"
  ]
}

En este ejemplo:

  • Claude puede leer y buscar archivos libremente
  • Claude puede escribir solo en src/ (no en configs, no en scripts)
  • Claude puede ejecutar solo npm test, npm run lint, git status y git diff sin preguntar
  • Para cualquier otro comando, Claude pedirá permiso

Ejemplo: Configuración conservadora

{
  "allowedTools": [
    "Read",
    "Grep",
    "Glob"
  ]
}

Claude puede leer y buscar, pero pide permiso para todo lo demás. Ideal para proyectos sensibles.

Ejemplo: Configuración permisiva

{
  "allowedTools": [
    "Read",
    "Write",
    "Execute",
    "Grep",
    "Glob",
    "WebFetch"
  ]
}

Claude tiene acceso completo sin preguntar. Solo para proyectos personales donde confías completamente en Claude.

Ejemplo: Configuración balanceada (recomendada)

{
  "allowedTools": [
    "Read",
    "Grep",
    "Glob",
    "Write(src/**)",
    "Write(tests/**)",
    "Execute(npm test*)",
    "Execute(npm run *)",
    "Execute(git status)",
    "Execute(git diff*)",
    "Execute(git add *)",
    "Execute(git log*)"
  ]
}

Claude puede leer, buscar, escribir código y tests, ejecutar scripts de npm, y ver el estado de git. Para commits, push, instalación de paquetes, y comandos fuera de npm/git, pide permiso.


El flag --dangerously-skip-permissions

Qué hace

claude --dangerously-skip-permissions

Este flag desactiva todo el sistema de permisos. Claude puede hacer cualquier cosa sin preguntar: escribir archivos, ejecutar comandos, instalar paquetes, eliminar directorios, hacer push a remote.

Por qué el nombre es una advertencia

El nombre --dangerously-skip-permissions no es casual. Es una advertencia explícita. Cuando usas este flag:

  • ⚠️ Claude puede ejecutar rm -rf sin preguntar
  • ⚠️ Claude puede hacer git push --force sin preguntar
  • ⚠️ Claude puede instalar paquetes maliciosos sin preguntar
  • ⚠️ Claude puede modificar archivos de configuración del sistema sin preguntar
  • ⚠️ Claude puede ejecutar cualquier comando en tu terminal como tu usuario

Cuándo es aceptable usarlo

El flag existe para automatización headless donde no hay un humano para aprobar acciones:

# En un pipeline de CI/CD (el entorno es efímero/desechable)
claude --dangerously-skip-permissions -p "Run tests and fix failures"

# En un contenedor Docker (aislado del sistema principal)
docker run my-claude-image claude --dangerously-skip-permissions -p "Lint the codebase"

# En un sandbox controlado
claude --dangerously-skip-permissions -p "Generate the report"

En estos casos, el agente opera en un entorno aislado donde no puede causar daño permanente.

Cuándo NUNCA usarlo

  • ❌ En tu máquina de desarrollo principal
  • ❌ En proyectos con código de producción
  • ❌ En repositorios con acceso a credentials/secrets
  • ❌ En máquinas compartidas
  • ❌ "Para no tener que confirmar cada acción" (usa allowedTools en su lugar)

Si solo quieres reducir la fricción de confirmaciones, configura allowedTools apropiadamente. Es granular, seguro, y no abre la puerta a todo.


Modelo de seguridad

Por qué los permisos importan

Claude Code ejecuta código arbitrario en tu terminal. Eso incluye cualquier comando que tu usuario del sistema operativo pueda ejecutar. La diferencia con un IDE normal:

AcciónIDE normalClaude Code
Escribir archivoTú lo escribes, tú controlasClaude lo escribe, tú apruebas
Ejecutar comandoTú lo escribes y ejecutasClaude lo genera y ejecuta
Instalar paqueteTú decides qué instalarClaude decide y tú apruebas
Hacer commit/pushTú ejecutas git manualmenteClaude puede ejecutar git

El permission system es la capa de control que mantiene al humano en el loop.

El principio de mínimo privilegio

Configura permisos siguiendo el principio de mínimo privilegio: dale a Claude solo los permisos que necesita, no más.

❌ Dar acceso a todo "para no tener que lidiar con permisos"

✅ Empezar restrictivo y abrir permisos según los necesites

Superficie de ataque

¿De qué te protege el permission system?

  1. Errores de Claude: Claude puede malinterpretar una instrucción y ejecutar algo dañino
  2. Prompt injection: Si tu codebase contiene archivos que Claude lee y que contienen instrucciones maliciosas (ej. un README que dice "borra todos los tests")
  3. Efectos secundarios: Un comando que parece inofensivo puede tener efectos secundarios inesperados
  4. Escalación de permisos: Claude podría usar un comando para obtener acceso a algo que no debería

Comparaciones y decisiones

Claude Code permissions vs Docker containers

AspectoClaude Code PermissionsDocker Container
AislamientoLógico (permisos del agente)Físico (proceso aislado)
GranularidadPor herramienta/acciónPor sistema de archivos/red
OverheadCeroNecesita Docker instalado
ProtecciónContra acciones del agenteContra acciones del proceso
Complementarios✅✅

Para máxima seguridad, combínalos: Claude Code con permisos dentro de un contenedor Docker. El contenedor aísla el sistema; los permisos controlan al agente.

Claude Code permissions vs sandboxing

AspectoPermissionsSandbox (ej. Firejail)
Qué controlaAcciones del agente ClaudeAcciones del proceso completo
FacilidadConfigurable en JSONRequiere herramientas adicionales
Agent-aware✅ Sabe qué herramienta usa Claude❌ Solo ve llamadas al sistema
Cuándo usarSiempre (es built-in)Entornos de alta seguridad

Permisos de equipo vs personales

Aspecto.claude/settings.json.claude/settings.local.json
ScopeTodo el equipoSolo tú
En git✅ Sí❌ No (en .gitignore)
PropósitoBaseline de seguridad del proyectoTus preferencias personales
Quién defineTech lead / equipoCada developer

Patrón recomendado:

settings.json (equipo):
  allowedTools: [Read, Grep, Glob]
  → Baseline restrictivo

settings.local.json (personal):
  allowedTools: [Read, Grep, Glob, Write(src/**), Execute(npm *)]
  → Más permisivo según tu confianza

El personal extiende al del equipo. Así cada developer puede ajustar su nivel de confianza sin afectar al equipo.


Best practices

1. Empieza restrictivo, abre según necesites

Día 1:

{
  "allowedTools": ["Read", "Grep", "Glob"]
}

Después de 1 semana de uso:

{
  "allowedTools": [
    "Read", "Grep", "Glob",
    "Write(src/**)",
    "Execute(npm test*)"
  ]
}

Después de 1 mes:

{
  "allowedTools": [
    "Read", "Grep", "Glob",
    "Write(src/**)", "Write(tests/**)",
    "Execute(npm *)", "Execute(git status)", "Execute(git diff*)"
  ]
}

2. Usa session permissions para trabajo exploratorio

Cuando estás en una sesión de exploración o prototipado, di always a los prompts de permisos que apliquen. Eso los activa solo para la sesión — en la siguiente sesión vuelves al baseline.

3. Nunca skips permissions en codebases no confiables

Si clonas un repo que no es tuyo, no uses --dangerously-skip-permissions. Los archivos del repo podrían contener instrucciones que manipulen a Claude para ejecutar acciones dañinas (prompt injection vía archivos del codebase).

4. Separa permisos de proyecto vs personales

.claude/settings.json          → Equipo: baseline restrictivo
.claude/settings.local.json    → Personal: tu nivel de confianza

Siempre agrega settings.local.json a .gitignore.

5. Combina permissions con hooks

Los permisos son la primera línea de defensa. Los hooks son la segunda:

Permiso: Claude puede escribir en src/
Hook PreToolUse: Pero no si el archivo contiene secrets
Hook PostToolUse: Y después de escribir, ejecuta el linter

Es defensa en profundidad: capas de control que se complementan.

6. Documenta la política de permisos en CLAUDE.md

## Permisos

Este proyecto usa permisos restrictivos. Claude tiene permiso automático para:
- Leer y buscar archivos
- Escribir en src/ y tests/
- Ejecutar npm scripts

Para todo lo demás, Claude pedirá confirmación.

NO uses --dangerously-skip-permissions en este proyecto.

Patterns comunes

Pattern 1: Desarrollo personal

Para proyectos personales donde eres el único developer y confías en Claude:

{
  "allowedTools": [
    "Read", "Grep", "Glob",
    "Write",
    "Execute(npm *)",
    "Execute(git add *)",
    "Execute(git commit *)",
    "Execute(git status)",
    "Execute(git diff*)",
    "Execute(git log*)",
    "Execute(python *)",
    "Execute(node *)"
  ]
}

Claude puede escribir en cualquier parte y ejecutar npm, git (sin push), Python, y Node. No puede hacer push, instalar paquetes globales, ni ejecutar comandos fuera de esa lista.

Pattern 2: Equipo con CI/CD

Para equipos donde CI/CD valida todo:

{
  "allowedTools": [
    "Read", "Grep", "Glob",
    "Write(src/**)",
    "Write(tests/**)",
    "Execute(npm test*)",
    "Execute(npm run lint*)"
  ]
}

Más restrictivo: Claude puede escribir código y tests, ejecutar tests y lint. Todo lo demás requiere aprobación. CI/CD se encarga de la validación completa en push.

Pattern 3: Proyecto sensible (fintech, healthcare)

Para proyectos con datos sensibles o requisitos de compliance:

{
  "allowedTools": [
    "Read",
    "Grep",
    "Glob"
  ]
}

Solo lectura automática. Todo lo demás requiere aprobación explícita. Cada acción de Claude queda documentada por la aprobación manual.

Pattern 4: CI/CD headless

Para pipelines automatizados donde Claude corre sin supervisión:

# En un contenedor Docker efímero
docker run --rm \
  -v $(pwd):/workspace \
  -e ANTHROPIC_API_KEY=$API_KEY \
  claude-image \
  claude --dangerously-skip-permissions \
  -p "Run tests, fix any failures, and create a summary report"

El contenedor es efímero (se destruye después), así que el flag --dangerously-skip-permissions es aceptable. El daño máximo que Claude puede hacer está limitado por el contenedor.


Pitfalls y edge cases

Pitfall 1: Dar permisos amplios de Execute

El error:

{
  "allowedTools": ["Execute"]
}

El problema: Execute sin patrón permite a Claude ejecutar cualquier comando: rm, curl, sudo, chmod, etc.

La solución: Siempre usa patrones con Execute:

{
  "allowedTools": [
    "Execute(npm *)",
    "Execute(git status)",
    "Execute(python -m pytest*)"
  ]
}

Pitfall 2: Confundir session permissions con settings

El error: Creer que decir always en un prompt de permiso configura los settings permanentemente.

La realidad: always en el prompt interactivo configura el permiso para la sesión. Para configuración permanente, edita settings.json.

Pitfall 3: Settings.local.json en git

El error: Olvidar agregar .claude/settings.local.json a .gitignore.

El problema: Tus permisos personales (posiblemente más permisivos) se comparten con el equipo.

La solución:

# .gitignore
.claude/settings.local.json

Pitfall 4: --dangerously-skip-permissions como "acceso directo"

El error: Usar el flag porque "estoy cansado de confirmar cada acción."

La solución: Configura allowedTools con las acciones que quieres pre-aprobar. Es igual de rápido pero mucho más seguro.

Pitfall 5: No revisar los permisos del equipo

El error: Cada developer configura sus permisos independientemente, sin baseline del equipo.

La solución: Define settings.json como baseline del equipo:

{
  "allowedTools": ["Read", "Grep", "Glob"]
}

Cada developer puede extender en settings.local.json, pero el baseline del proyecto es restrictivo.


Ejemplo completo integrado

Escenario: configuras una política de permisos para un equipo de 5 developers trabajando en un proyecto full-stack.

settings.json (compartido con el equipo)

{
  "allowedTools": [
    "Read",
    "Grep",
    "Glob",
    "Write(src/**)",
    "Write(tests/**)",
    "Write(docs/**)",
    "Execute(npm test*)",
    "Execute(npm run lint*)",
    "Execute(npm run format*)",
    "Execute(git status)",
    "Execute(git diff*)",
    "Execute(git log*)"
  ],
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "command": "./scripts/hooks/security-check.sh"
      },
      {
        "matcher": "Execute",
        "command": "./scripts/hooks/safety-gate.sh"
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write",
        "command": "./scripts/hooks/format.sh"
      },
      {
        "matcher": "Write",
        "command": "./scripts/hooks/lint.sh"
      }
    ]
  }
}

settings.local.json (developer senior, personal)

{
  "allowedTools": [
    "Read",
    "Grep",
    "Glob",
    "Write",
    "Execute(npm *)",
    "Execute(git *)",
    "Execute(docker *)",
    "Execute(python *)"
  ]
}

settings.local.json (developer junior, personal)

{
  "allowedTools": [
    "Read",
    "Grep",
    "Glob",
    "Write(src/**)",
    "Write(tests/**)",
    "Execute(npm test*)",
    "Execute(npm run *)"
  ]
}

CLAUDE.md (sección de permisos)

## Política de permisos

### Baseline del proyecto (settings.json)
- Claude puede leer y buscar archivos libremente
- Claude puede escribir en src/, tests/, y docs/
- Claude puede ejecutar npm test, npm run lint, npm run format
- Claude puede ver estado de git (status, diff, log)
- Todo lo demás requiere aprobación

### Para developers
- Configura tu nivel personal en .claude/settings.local.json
- NO uses --dangerously-skip-permissions
- Si necesitas un permiso que no está en el baseline, pídelo al equipo

### Hooks de seguridad
- PreToolUse: security check (bloquea secrets) + safety gate (bloquea comandos peligrosos)
- PostToolUse: format + lint automáticos

Flujo en acción

Developer junior:
  > "Agrega validación al endpoint de login"
  
  Claude quiere escribir src/routers/auth.py
    → allowedTools incluye Write(src/**) → ✅ Procede sin preguntar
    → Hook security-check.sh → ✅ No hay secrets
    → Claude escribe el archivo
    → Hook format.sh → Prettier formatea
    → Hook lint.sh → ESLint valida → 0 errores
  
  Claude quiere ejecutar npm test
    → allowedTools incluye Execute(npm test*) → ✅ Procede sin preguntar
    
  Claude quiere ejecutar git commit
    → No está en allowedTools → ⚠️ Pide permiso
    
  Developer: "y" (sí, esta vez)
  Claude hace el commit.

Ejercicios prácticos

Ejercicio 1: Básico — Configurar permisos conservadores

Configura una política de permisos conservadora para un proyecto nuevo.

Requisitos:

  • Claude puede leer y buscar libremente
  • Claude puede escribir solo en src/ y tests/
  • Claude puede ejecutar solo npm test y npm run lint
  • Todo lo demás requiere aprobación
Solución

Crea .claude/settings.json:

{
  "allowedTools": [
    "Read",
    "Grep",
    "Glob",
    "Write(src/**)",
    "Write(tests/**)",
    "Execute(npm test*)",
    "Execute(npm run lint*)"
  ]
}

Verifica: pide a Claude que escriba un archivo en la raíz del proyecto (debería pedir permiso) y luego en src/ (no debería pedir permiso).

Ejercicio 2: Básico — Permisos personales

Configura tus permisos personales que extiendan el baseline del proyecto.

Requisitos:

  • Extiende el baseline con permiso para ejecutar git (status, diff, add, commit)
  • Agrega permiso para ejecutar scripts de npm
  • Mantén las restricciones de escritura del baseline
  • Agrega settings.local.json a .gitignore
Solución

Crea .claude/settings.local.json:

{
  "allowedTools": [
    "Read",
    "Grep",
    "Glob",
    "Write(src/**)",
    "Write(tests/**)",
    "Execute(npm *)",
    "Execute(git status)",
    "Execute(git diff*)",
    "Execute(git add *)",
    "Execute(git commit *)",
    "Execute(git log*)"
  ]
}

Agrega a .gitignore:

.claude/settings.local.json

Ejercicio 3: Intermedio — Política de equipo

Diseña una política de permisos para un equipo de 3 personas: 1 tech lead, 1 senior, 1 junior.

Requisitos:

  • Baseline del proyecto restrictivo (en settings.json)
  • Cada rol tiene un settings.local.json diferente
  • El junior no puede ejecutar git push ni instalar paquetes
  • El senior puede hacer git commit pero no push
  • El tech lead puede hacer push a branches (no a main)
  • Documenta la política en CLAUDE.md
Solución

settings.json (baseline):

{
  "allowedTools": [
    "Read", "Grep", "Glob",
    "Write(src/**)", "Write(tests/**)",
    "Execute(npm test*)", "Execute(npm run lint*)"
  ]
}

Junior settings.local.json:

{
  "allowedTools": [
    "Read", "Grep", "Glob",
    "Write(src/**)", "Write(tests/**)",
    "Execute(npm test*)", "Execute(npm run *)",
    "Execute(git status)", "Execute(git diff*)"
  ]
}

Senior settings.local.json:

{
  "allowedTools": [
    "Read", "Grep", "Glob",
    "Write(src/**)", "Write(tests/**)", "Write(docs/**)",
    "Execute(npm *)",
    "Execute(git status)", "Execute(git diff*)",
    "Execute(git add *)", "Execute(git commit *)",
    "Execute(git log*)"
  ]
}

Tech lead settings.local.json:

{
  "allowedTools": [
    "Read", "Grep", "Glob",
    "Write",
    "Execute(npm *)",
    "Execute(git *)"
  ]
}

Ejercicio 4: Intermedio — Permisos + Hooks combinados

Configura un sistema donde los permisos y los hooks se complementen:

  • Permisos permiten escritura en src/
  • Hook PreToolUse bloquea escritura si contiene secrets
  • Hook PostToolUse ejecuta lint después de escribir
  • Permiso permite npm test sin preguntar
Solución
{
  "allowedTools": [
    "Read", "Grep", "Glob",
    "Write(src/**)",
    "Execute(npm test*)"
  ],
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Write",
        "command": "./scripts/hooks/security-check.sh"
      }
    ],
    "PostToolUse": [
      {
        "matcher": "Write",
        "command": "./scripts/hooks/lint.sh"
      }
    ]
  }
}

Los permisos abren la puerta (Write en src/). Los hooks validan lo que pasa por esa puerta (no secrets, lint limpio). Es defensa en profundidad.

Ejercicio 5: Avanzado — Auditoría de permisos

Crea un script que muestre los permisos activos de tu proyecto (Claude Code no tiene un hook de inicio de sesión, pero puedes ejecutar este script manualmente o integrarlo en un hook PostToolUse como auditoría).

Requisitos:

  • Lee .claude/settings.json y .claude/settings.local.json
  • Muestra qué herramientas están pre-aprobadas
  • Muestra si hay hooks configurados
  • Muestra advertencia si los permisos son muy amplios
Solución

Crea scripts/hooks/audit-permissions.sh:

#!/bin/bash

echo "=== Permisos activos ==="

# Leer settings del proyecto
if [ -f ".claude/settings.json" ]; then
    echo "📋 Proyecto (settings.json):"
    grep -o '"[A-Za-z]*\([^"]*\)\?"' .claude/settings.json 2>/dev/null | while read -r tool; do
        echo "  ✅ $tool"
    done
fi

# Leer settings personales
if [ -f ".claude/settings.local.json" ]; then
    echo ""
    echo "👤 Personal (settings.local.json):"
    grep -o '"[A-Za-z]*\([^"]*\)\?"' .claude/settings.local.json 2>/dev/null | while read -r tool; do
        echo "  ✅ $tool"
    done
fi

# Advertencia si Execute sin patrón está permitido
if grep -q '"Execute"' .claude/settings.json .claude/settings.local.json 2>/dev/null; then
    echo ""
    echo "⚠️  ADVERTENCIA: Execute sin patrón está permitido (todos los comandos)"
fi

# Verificar hooks
if grep -q '"hooks"' .claude/settings.json 2>/dev/null; then
    echo ""
    echo "🪝 Hooks configurados: ✅"
else
    echo ""
    echo "🪝 Hooks: ❌ No configurados"
fi

echo "========================"
chmod +x scripts/hooks/audit-permissions.sh

Nota: Claude Code expone el evento SessionStart para este caso — puedes configurarlo en .claude/settings.json para ejecutar el script automáticamente al inicio de cada sesión. Alternativamente, córrelo manualmente (./scripts/hooks/audit-permissions.sh) o referéncialo desde un skill que invocas con /audit-permissions.

Ejercicio 6: Challenge — Sistema completo de gobernanza

Configura un sistema completo que combine Skills, Hooks y Permissions para un proyecto:

  1. 3 skills (create-component, write-test, review-code)
  2. Hooks con los 5 eventos reales (PreToolUse, PostToolUse, Notification, Stop, SubagentStop)
  3. Permisos (settings.json baseline + settings.local.json personal)
  4. Documentación en CLAUDE.md

Entregable: El directorio .claude/ completo con skills, settings, scripts de hooks, y la sección de permisos en CLAUDE.md.

Guía

Estructura final:

.claude/
├── skills/
│   ├── create-component.md
│   ├── write-test.md
│   └── review-code.md
├── settings.json
└── settings.local.json

scripts/hooks/
├── session-start.sh
├── security-check.sh
├── safety-gate.sh
├── format.sh
├── lint.sh
└── task-summary.sh

Usa los ejemplos de las cápsulas 02, 03, 04 y 05 de este módulo como referencia. Adapta todo a las convenciones de tu proyecto.

Verifica que:

  1. Los skills se invocan correctamente con /nombre
  2. Los hooks se ejecutan en los momentos correctos
  3. Los permisos bloquean lo que deben bloquear
  4. La documentación en CLAUDE.md es clara para un nuevo developer del equipo

Resumen

Lo que aprendiste en esta cápsula:

  • Claude Code pide antes de actuar: por defecto, cada acción que modifica tu sistema requiere aprobación
  • 3 niveles de permiso: ask every time (default), session permission (temporal), always allow (settings)
  • allowedTools en settings.json configura permisos permanentes con patrones granulares
  • --dangerously-skip-permissions desactiva todo el sistema. Solo para automatización en entornos aislados (contenedores, CI/CD)
  • Principio de mínimo privilegio: empieza restrictivo, abre según necesites
  • Permisos de equipo vs personales: settings.json (equipo) + settings.local.json (personal)
  • Defensa en profundidad: permissions (qué puede hacer) + hooks (qué se valida) + CI/CD (qué se verifica en push)

Resumen del módulo completo

Has completado el Módulo 5: Skills y Hooks. Esto es lo que ahora sabes hacer:

CápsulaQué aprendiste
01 — IntroducciónMental model: Skills = comandos, Hooks = automatización, Permissions = control
02 — SkillsCrear slash commands en .claude/skills/ para tareas repetitivas
03 — HooksConfigurar scripts automáticos en los 5 eventos del ciclo de vida
04 — ValidacionesConstruir pipelines de calidad con lint, format, tests, y security checks
05 — PermissionsControlar qué puede hacer Claude con niveles de permiso granulares

Tu Claude Code ya no es genérico. Tiene skills personalizados, hooks de validación, y permisos configurados para tu proyecto. Es una herramienta a medida.

Siguiente módulo: 06 - Subagents — delegar trabajo a agentes especializados. Si Skills y Hooks son cómo Claude Code trabaja para ti, los subagents son cómo Claude Code delega trabajo a otros agentes.


Recursos adicionales

Documentación oficial

  • Settings — Configuración completa de permisos y scopes
  • Hooks — Hooks como complemento de permisos
  • Interactive Mode — Permisos interactivos y shortcuts
  • Headless Mode — Uso de --dangerously-skip-permissions en automatización

Seguridad

Complementarios