# Claude Code: manual esencial para principiantes

> Guía completa sobre Claude Code de Anthropic: instalación de la CLI, autenticación, gestión de permisos, atajos de teclado y desarrollo paso a paso de tu primer proyecto.

Claude Code es la interfaz de línea de comandos oficial de Anthropic diseñada para interactuar con tu código fuente, realizar modificaciones, ejecutar comandos y gestionar git directamente en la terminal mediante lenguaje natural. No se trata de una ventana de chat aislada desde la cual debas copiar código a mano, sino de un agente de ingeniería autónomo integrado directamente en tu proyecto.

Este manual proporciona una base sólida para comenzar a utilizar Claude Code. El contenido se divide en tres módulos prácticos:
- **Módulo 1 — Instalación y configuración inicial:** despliegue de la CLI, autenticación vía API o navegador (OAuth), primera ejecución y gestión de archivos de configuración.
- **Módulo 2 — Sesión de trabajo e interacción:** control del contexto, atajos de teclado, comandos slash, modo no interactivo y optimización con `/compact`.
- **Módulo 3 — Seguridad y modelo de permisos:** configuración de `settings.json`, creación de listas de reglas allow/deny para comandos bash y sandboxing.

Cada módulo se complementa con un ejercicio práctico progresivo para construir, mejorar y preparar para producción un componente interactivo en Next.js y React.

---

## 1. Qué es Claude Code y requisitos del sistema

### 1.1. Qué es Claude Code y diferencias con el chat web

Claude Code actúa como un compañero de programación en tu terminal. A diferencia de un chat web pasivo, el agente dispone de herramientas operativas integradas:
- **Inspección y búsqueda:** analiza archivos, realiza búsquedas con expresiones regulares (`grep`) y navega por el árbol del proyecto (`glob`).
- **Modificación quirúrgica:** genera parches incrementales sin sobreescribir innecesariamente archivos de gran tamaño.
- **Ejecución en consola:** lanza pruebas unitarias, compiladores, linters y comandos git, monitorizando códigos de salida y errores.

### 1.2. Requisitos del sistema y preparación del entorno

Antes de proceder a la instalación, comprueba que tu entorno cumple con los siguientes requisitos:
- **Sistema Operativo:** macOS, distribuciones Linux modernas o Windows mediante WSL2.
- **Entorno de ejecución:** Node.js versión 18.0 o superior (verifica con `node -v`).
- **Control de versiones:** Git versión 2.20 o superior (verifica con `git --version`).
- **Acceso a Anthropic:** Clave de API de Anthropic Console o suscripción activa a Claude Max.

---

## 2. Instalación y autenticación

### 2.1. Instalación de la CLI mediante npm y gestores de paquetes

Claude Code se distribuye como un paquete global a través de npm:

```bash
npm install -g @anthropic-ai/claude-code
```

Verifica la disponibilidad del ejecutable en tu consola:

```bash
claude --version
```

Si la terminal responde `command not found`, la ruta de binarios globales de npm no está incluida en tu variable `$PATH`. Consulta la tabla de diagnóstico a continuación para solucionar el problema.

### 2.2. Autenticación y vinculación de la cuenta de Anthropic

Existen dos vías de autenticación:

**Opción A — Clave de API de Anthropic:**  
Define la variable de entorno correspondiente:

```bash
export ANTHROPIC_API_KEY="sk-ant-tu-clave-api"
```

Para que persista entre diferentes sesiones de terminal, añade la instrucción al archivo de configuración de tu shell:

```bash
echo 'export ANTHROPIC_API_KEY="sk-ant-tu-clave-api"' >> ~/.zshrc
source ~/.zshrc
```

**Opción B — Suscripción a Claude Max (OAuth):**  
Si dispones de un plan Claude Max ($100 o $200/mes), inicia sesión mediante el navegador:

```bash
claude login
```

El comando abrirá tu navegador predeterminado para autorizar la estación de trabajo local.

---

## 3. Primera ejecución y configuración básica

### 3.1. Primera ejecución en el proyecto y verificación del entorno

Accede al directorio de cualquier proyecto de tu equipo e inicia Claude Code:

```bash
cd ~/my-project
claude
```

Una vez iniciada la interfaz REPL, envía una primera instrucción de exploración:

```text
Summarize the structure of this project and list the main technologies used.
```

Claude inspeccionará el archivo `package.json`, los ficheros de configuración y las carpetas del repositorio para emitir un resumen estructurado.

### 3.2. Configuración base y resolución de problemas iniciales (Troubleshooting)

Los ficheros de configuración se ubican en el directorio `~/.claude/`:
- `~/.claude/settings.json` — Reglas globales de permisos y políticas de ejecución.
- `~/.claude/CLAUDE.md` — Instrucciones de usuario aplicadas a todas las sesiones.
- `.claude/settings.json` — Ajustes específicos del proyecto (se versionan en Git).
- `CLAUDE.md` — Pautas del repositorio (criterios de calidad, linters, arquitectura).

| Incidencia inicial | Causa raíz | Solución técnica |
| :--- | :--- | :--- |
| `claude: command not found` | Directorio npm bin no está en `PATH` | Añade la ruta a tu shell: `export PATH="$(npm config get prefix)/bin:$PATH"` |
| Error `401 Unauthorized` | Clave de API inválida o expirada | Ejecuta `claude logout`, valida `ANTHROPIC_API_KEY` y reautentica con `claude login` |
| Arranque inicial lento | Indexación de repositorios extensos | La primera sesión indexa los archivos; las siguientes emplean la caché local |

---

## 4. Práctica: construcción de tu primera aplicación

### 4.1. Flujo paso a paso para la generación del prototipo

El objetivo de este primer ejercicio es crear un componente cliente de Next.js / React guiado por Claude Code:
1. Pide a Claude que genere un nuevo archivo de ruta en `app/practice/page.tsx`.
2. Indícale que cree un botón interactivo que dispare una petición asíncrona de prueba.
3. Comprueba el funcionamiento en tu navegador en `http://localhost:3000/practice`.

### 4.2. Plantilla de código inicial y comprobación en servidor local

Código base del prototipo:

```tsx
// app/practice/page.tsx
'use client';

import { useState } from 'react';

export default function PracticePage() {
  const [result, setResult] = useState('');
  const [loading, setLoading] = useState(false);

  async function runTest() {
    setLoading(true);
    try {
      const response = await fetch('/api/test');
      const data = await response.json();
      setResult(data.message || 'Petición ejecutada con éxito');
    } catch {
      setResult('Error al ejecutar la petición de prueba');
    } finally {
      setLoading(false);
    }
  }

  return (
    <div className="p-8 max-w-2xl mx-auto font-sans">
      <h1 className="text-3xl font-bold mb-6">Ejercicio práctico 1: Prototipo</h1>
      <button
        onClick={runTest}
        disabled={loading}
        className="bg-black text-white px-6 py-3 rounded-lg hover:bg-neutral-800 disabled:opacity-50 transition"
      >
        {loading ? 'Ejecutando...' : 'Iniciar prueba'}
      </button>
      {result && (
        <div className="mt-6 p-4 bg-neutral-100 rounded-lg border border-neutral-200">
          {result}
        </div>
      )}
    </div>
  );
}
```

---

## 5. Sesión de trabajo y flujo de diálogo

### 5.1. Inicio de la sesión REPL interactiva

Para el desarrollo diario, sitúate en la raíz del proyecto e inicializa el entorno interactivo:

```bash
cd ~/my-project
claude
```

Claude retiene el contexto de la conversación a lo largo de la sesión, recordando qué archivos han sido modificados y los últimos errores detectados. La comunicación se realiza en lenguaje natural.

### 5.2. El bucle de diálogo: planificación, ejecución de herramientas y validación

El flujo de trabajo del agente sigue un ciclo continuo de cinco etapas:

```mermaid
flowchart TD
    A["El desarrollador describe la tarea en lenguaje natural"] --> B["Claude examina el repositorio y elabora un plan"]
    B --> C["El agente solicita confirmación para acciones sensibles"]
    C --> D["Ejecución de herramientas y presentación del diff"]
    D --> E["El usuario valida el resultado y aporta feedback"]
```

Ejemplo de flujo:
- **Petición:** `Añade un indicador de carga en la página del panel de control.`
- **Inspección:** Claude lee `app/dashboard/page.tsx` y detecta la ausencia de feedback visual.
- **Acción:** Propone crear `loading.tsx` y envolver el componente en un límite de `Suspense`.
- **Confirmación:** Presenta el diff exacto y aguarda tu aprobación.

---

## 6. Atajos de teclado, comandos y modos de trabajo

### 6.1. Atajos principales y comandos slash para la gestión de contexto

Dominar los comandos rápidos acelera la operativa diaria:

| Atajo | Función |
| :--- | :--- |
| `Enter` | Enviar el mensaje actual al agente |
| `Escape` | Cancelar la generación en curso o la herramienta activa |
| `Ctrl+C` | Salir limpiamente de Claude Code |
| `Up` / `Down` | Desplazarse por el historial de peticiones previas |
| `Shift+Tab` | Alternar entre entrada en una sola línea y multilínea |

Comandos slash integrados para el control de la sesión:
- `/help` — Muestra el catálogo de comandos disponibles.
- `/clear` — Limpia el historial de la conversación actual.
- `/compact` — Comprime el contexto para liberar capacidad sin perder decisiones clave.
- `/model` — Cambia de modelo durante la sesión (por ejemplo, entre Sonnet y Opus).
- `/permissions` — Comprueba y gestiona los permisos concedidos a las herramientas.

### 6.2. Modo no interactivo y consejos de eficiencia operativa

Para integrar Claude Code en scripts de CI o para tareas puntuales en la terminal, utiliza el indicador `-p` (`print`):

```bash
# Consultar información sobre la arquitectura
claude -p "¿Qué base de datos utiliza este proyecto?"

# Diagnosticar registros de error canalizados
cat error.log | claude -p "Encuentra la causa de este fallo y genera una corrección"
```

> 💡 **Recomendaciones de productividad:**
> - Sé específico: en lugar de «corrige el formulario», escribe «añade debounce al botón de envío para evitar doble clic».
> - Ejecuta `/compact` con regularidad cuando el diálogo supere los 30–40 intercambios.

---

## 7. Práctica: mejora de la aplicación

### 7.1. Refactorización y optimización del código con Claude

En este segundo módulo práctico, mejoraremos el componente inicial solicitando a Claude que incorpore tipado estricto y control de errores.

Envía este prompt en la sesión:
```text
Abre app/practice/page.tsx. Añade tipado estricto de TypeScript, captura de excepciones try/catch mostrando el mensaje en un banner con fondo rojo y un spinner CSS animado durante la carga.
```

### 7.2. Expansión funcional: estilos, control de excepciones y estados de carga

Código del componente refactorizado:

```tsx
// app/practice/page.tsx - Versión mejorada
'use client';

import { useState } from 'react';

export default function PracticePage() {
  const [result, setResult] = useState<string | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);

  async function runTest() {
    setLoading(true);
    setError(null);
    try {
      const response = await fetch('/api/test');
      if (!response.ok) throw new Error(`Fallo del servidor: código ${response.status}`);
      const data = await response.json();
      setResult(data.message || 'Operación completada con éxito');
    } catch (err: unknown) {
      setError(err instanceof Error ? err.message : 'Se ha producido un error inesperado');
    } finally {
      setLoading(false);
    }
  }

  return (
    <div className="p-8 max-w-2xl mx-auto font-sans">
      <h1 className="text-3xl font-bold mb-4">Ejercicio práctico 2: Mejora</h1>
      <p className="text-neutral-600 mb-6">Comprobación de gestión de excepciones y estados dinámicos.</p>
      
      <button
        onClick={runTest}
        disabled={loading}
        className="flex items-center gap-2 bg-black text-white px-6 py-3 rounded-lg hover:bg-neutral-800 disabled:opacity-50 transition"
      >
        {loading && (
          <span className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
        )}
        {loading ? 'Procesando petición...' : 'Ejecutar acción'}
      </button>

      {error && (
        <div className="mt-6 p-4 bg-red-50 text-red-700 rounded-lg border border-red-200">
          {error}
        </div>
      )}

      {result && (
        <div className="mt-6 p-4 bg-neutral-100 text-neutral-800 rounded-lg border border-neutral-200">
          {result}
        </div>
      )}
    </div>
  );
}
```

---

## 8. Modelo de permisos y seguridad

### 8.1. Arquitectura del modelo de permisos y niveles de riesgo

El marco de seguridad de Claude Code clasifica las herramientas disponibles en dos niveles según su riesgo operativo:

| Nivel de riesgo | Herramientas comprendidas | Comportamiento del agente |
| :--- | :--- | :--- |
| **Seguras (Solo lectura)** | `Read`, `Grep`, `Glob`, listado de carpetas | Se ejecutan de manera inmediata sin confirmación |
| **Sensibles (Mutación)** | `Edit`, `Write`, `Bash`, borrado de archivos, `git push` | Requieren autorización explícita antes de ejecutarse |

### 8.2. Dinámica de aprobación y rechazo de operaciones sensibles

Al solicitar la ejecución de una acción sensible, Claude interrumpe el proceso con una consulta:

```text
Claude wants to run: npm install express
Allow? (y/n/always)
```

Opciones de interacción:
- `y` (`yes`) — Autoriza la ejecución puntual de ese comando.
- `n` (`no`) — Rechaza la acción, permitiendo solicitar un enfoque alternativo.
- `always` (o `a`) — Otorga permiso permanente para esa herramienta hasta el fin de la sesión.

---

## 9. Archivos de configuración y control de acceso

### 9.1. Archivos de configuración globales y de proyecto (settings.json)

Para guardar permisos de forma permanente, edita el archivo `~/.claude/settings.json`:

```json
{
  "permissions": {
    "allow": [
      "Read",
      "Glob",
      "Grep",
      "Edit",
      "Write",
      "Bash(npm run *)",
      "Bash(git status)"
    ],
    "deny": [
      "Bash(rm -rf *)",
      "Bash(sudo *)"
    ]
  }
}
```

### 9.2. Reglas de patrones para comandos bash y auditoría mediante /permissions

La directiva `permissions.allow` admite patrones glob:
- `Bash(npm test *)` — Permite ejecutar pruebas sin confirmación manual.
- `Bash(git commit *)` — Permite crear commits en el repositorio.
- `Bash(rm -rf *)` en `deny` — Asegura un bloqueo total contra el borrado recursivo.

En cualquier momento puedes auditar las políticas vigentes ejecutando `/permissions`.

---

## 10. Mejores prácticas de seguridad y flujo de trabajo

### 10.1. Estrategia de control de acceso: principio de mínimo privilegio

- **Expansión gradual:** Comienza trabajando con supervisión manual completa. Agrega patrones a `allow` solo tras confirmar la estabilidad del agente.
- **Prohibición de comodines globales en bash:** No configures `"Bash(*)"` en la lista permitida; esto desactiva por completo el sandbox de seguridad.
- **Bloqueos preventivos en deny:** Bloquea utilidades críticas (`sudo`, `mkfs`, `dd`) para blindar el entorno contra confirmaciones accidentales.

### 10.2. Aislamiento de variables sensibles y revisión exhaustiva de diffs

- **Protección de variables de entorno:** Claude Code hereda las variables de tu shell. Evita iniciar sesiones con credenciales activas de bases de datos de producción.
- **Revisión minuciosa de diffs:** Revisa siempre el diff generado antes de aceptar modificaciones en archivos clave.

---

## 11. Práctica: versión final de la aplicación

### 11.1. Flujo de trabajo securizado y validación para producción

En el módulo de cierre, consolidaremos un componente robusto listo para producción:
1. Establece los límites de seguridad en `.claude/settings.json`.
2. Solicita a Claude que aplique una refactorización integral con interfaces de TypeScript y validación de respuesta.
3. Verifica la compilación con `npm run build`.

### 11.2. Código final del componente y lista de control para despliegue

Implementación del componente final:

```tsx
// app/practice/page.tsx - Versión final lista para producción
'use client';

import { useState } from 'react';

interface ApiResponse {
  message: string;
  status: 'ok' | 'error';
  timestamp: string;
}

export default function PracticePage() {
  const [data, setData] = useState<ApiResponse | null>(null);
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);

  async function runTest() {
    setLoading(true);
    setError(null);
    try {
      const response = await fetch('/api/test');
      if (!response.ok) throw new Error(`Respuesta errónea del servidor: código ${response.status}`);
      const payload: ApiResponse = await response.json();
      setData(payload);
    } catch (err: unknown) {
      setError(err instanceof Error ? err.message : 'Error imprevisto en la ejecución');
    } finally {
      setLoading(false);
    }
  }

  return (
    <main className="min-h-screen bg-neutral-50 py-12 px-4 sm:px-6 lg:px-8 font-sans">
      <div className="max-w-xl mx-auto bg-white p-8 rounded-xl shadow-sm border border-neutral-200">
        <h1 className="text-2xl font-semibold text-neutral-900 mb-2">Ejercicio práctico 3: Producción</h1>
        <p className="text-sm text-neutral-500 mb-6">Componente cliente asegurado y optimizado mediante Claude Code.</p>
        
        <button
          onClick={runTest}
          disabled={loading}
          className="w-full flex justify-center items-center gap-2 bg-neutral-900 text-white py-3 px-4 rounded-lg font-medium hover:bg-neutral-800 disabled:opacity-50 transition"
        >
          {loading && (
            <span className="w-4 h-4 border-2 border-white border-t-transparent rounded-full animate-spin" />
          )}
          {loading ? 'Ejecutando verificación...' : 'Iniciar diagnóstico'}
        </button>

        {error && (
          <div className="mt-6 p-4 bg-red-50 text-red-700 text-sm rounded-lg border border-red-200">
            <strong>Error:</strong> {error}
          </div>
        )}

        {data && (
          <div className="mt-6 p-4 bg-neutral-50 text-neutral-800 text-sm rounded-lg border border-neutral-200 space-y-1">
            <div><strong>Estado:</strong> {data.status}</div>
            <div><strong>Mensaje:</strong> {data.message}</div>
            <div className="text-xs text-neutral-400"><strong>Marca temporal:</strong> {data.timestamp}</div>
          </div>
        )}
      </div>
    </main>
  );
}
```