# Plan: Instalar Claude Code system-wide (username-agnostic, última versión) en el Dockerfile

## Context

El [Dockerfile](Dockerfile) instala Claude Code vía el repo apt oficial (`claude-code`,
líneas 147‑155) desde el commit `7096b11`. Eso provocó dos problemas:

1. **Versión vieja**: el canal apt `stable` va por detrás del canal `latest`. En este
   contenedor hay `2.1.197`, mientras que `latest` ya está en `2.1.207`.
2. **MCPs no cargan**: verificado que es *estructural*, no de versión. El usuario declaró sus
   MCPs (gitea, docmost, github-personal, penpot, atlassian) bajo la clave `mcpServers` dentro
   de `~/.claude/settings.json`, pero **Claude Code no lee `mcpServers` desde `settings.json`**.
   `claude mcp list` lo confirmó: solo aparecen los conectores de claude.ai, ninguno de los del
   usuario. Los MCPs de usuario viven en `~/.claude.json` (archivo hermano de `.claude/`, no
   dentro), en `.mcp.json` de proyecto, o en `/etc/claude-code/managed-mcp.json` (enterprise).

Intentos previos y por qué fallaron:
- `curl … install.sh | bash` (commit original): deja el binario en `~/.local/bin` del usuario que
  instala (root) → inalcanzable para otros HOME_USER.
- `HOME=/usr/local/claude … install.sh` (`be1a141`): el binario resuelve su home por el registro
  del SO, ignoró el override y volvió a caer en `/root`.
- apt `claude-code` (`7096b11`): quedó en `/usr/bin` (bien para multi-usuario) pero atado al canal
  `stable` desactualizado.

**Objetivo**: que `claude` esté disponible por defecto para **cualquier nombre de usuario** del
SO, siempre en la **última versión**, con **auto-update en runtime** funcionando, y sin depender
de trucos de `$HOME`/`.bashrc`.

## Alcance (confirmado con el usuario)

- **Este repo (Dockerfile)**: SOLO arreglar la instalación de Claude Code.
- **MCPs**: NO se toca la imagen. Se documenta la guía para que el usuario los reubique vía sus
  volúmenes (sección "Guía MCPs" abajo).

## Enfoque recomendado

Descargar el binario nativo standalone directamente del canal oficial `latest` (el mismo artefacto
que `install.sh` usa internamente), verificar su checksum, y colocarlo en `/usr/local/bin/claude`
(modo 0755, root). Esa ruta ya está en el PATH por defecto de todo usuario (igual que `gh`,
`kubectl`, `docker`), así que es completamente independiente del nombre de usuario y no necesita
exports en `.bashrc`.

El auto-update en runtime sigue funcionando **por usuario**: el updater nativo descarga nuevas
versiones en el propio `~/.local/share/claude/versions/` de cada usuario, independiente del binario
root de `/usr/local/bin`. La línea existente `export PATH="$HOME/.local/bin:$PATH"` (línea 176)
hace que esa copia actualizada por usuario tome precedencia. El binario base de la imagen se
refresca además en cada build de CI.

## Cambios en [Dockerfile](Dockerfile)

### 1. Reemplazar el bloque apt (líneas 147‑155) por descarga directa del binario `latest`

`python3` ya está disponible en esta etapa (viene de `python3-pip`), así que se usa para parsear el
`manifest.json` de forma robusta. El base es Debian/glibc → variante `linux-<arch>` (no musl).

```dockerfile
# Installing Claude Code (system-wide, latest native build, accessible by any user)
# Pull the standalone native binary straight from the official 'latest' release
# channel (the same artifact install.sh uses internally) and drop it on the
# system PATH at /usr/local/bin -- already on every user's PATH, like gh/kubectl.
# Avoids install.sh's per-user ~/.local/bin layout (unreachable for other users)
# and the apt 'stable' channel lag that shipped an outdated build. Runtime
# auto-update still works per user: the native updater writes new versions into
# each user's own ~/.local/share/claude/versions.
RUN set -eux; \
    case "$(dpkg --print-architecture)" in \
      amd64) CC_ARCH=x64 ;; \
      arm64) CC_ARCH=arm64 ;; \
      *) echo "unsupported architecture: $(dpkg --print-architecture)" >&2; exit 1 ;; \
    esac; \
    CC_BASE="https://downloads.claude.ai/claude-code-releases"; \
    CC_VERSION="$(curl -fsSL "${CC_BASE}/latest")"; \
    CC_CHECKSUM="$(curl -fsSL "${CC_BASE}/${CC_VERSION}/manifest.json" \
      | python3 -c "import sys,json;print(json.load(sys.stdin)['platforms']['linux-${CC_ARCH}']['checksum'])")"; \
    curl -fsSL "${CC_BASE}/${CC_VERSION}/linux-${CC_ARCH}/claude" -o /tmp/claude; \
    echo "${CC_CHECKSUM}  /tmp/claude" | sha256sum -c -; \
    sudo install -m 0755 -o root -g root /tmp/claude /usr/local/bin/claude; \
    rm -f /tmp/claude; \
    claude --version
```

### 2. Eliminar la línea de auto-update específica de apt (líneas 177‑178)

```dockerfile
# Let Claude Code auto-upgrade its apt package in the background when a new version ships
RUN echo 'export CLAUDE_CODE_PACKAGE_MANAGER_AUTO_UPDATE=1' | sudo tee -a /usr/bin/.bashrc
```

Ya no aplica (no es instalación apt). El auto-update nativo funciona por defecto sin esa env var.
Se **conserva** la línea 176 (`export PATH="$HOME/.local/bin:$PATH"`) porque es de propósito
general y ayuda a que el claude auto-actualizado por usuario tome precedencia.

### 3. Bump de versión en [README.md](README.md)

`1.4.1` → `1.4.2` (mismo patrón que los commits previos).

## Guía MCPs (fuera de la imagen — lo aplica el usuario en sus volúmenes)

Causa raíz: `mcpServers` en `~/.claude/settings.json` es ignorado. El resto de `settings.json`
(`permissions`, `hooks`, `model`, `enabledPlugins`, `env`, `theme`, etc.) **sí es válido y se
queda ahí**.

Pasos:
1. Mover el bloque `mcpServers` de `~/.claude/settings.json` al archivo `~/.claude.json`
   (en el HOME, hermano del directorio `.claude/`), como clave top-level:
   ```json
   { "mcpServers": { "gitea": { "type": "http", "url": "…", "headers": { … } }, "docmost": { … } } }
   ```
2. Persistir `~/.claude.json` en el volumen por usuario, montado **read-write** (Claude reescribe
   ese archivo con historial de proyectos; no debe ser read-only). El volumen actual que monta
   `~/.claude/` no lo cubre porque `~/.claude.json` está fuera de ese directorio.
3. Borrar el bloque `mcpServers` obsoleto de `settings.json` para evitar confusión.

## Verificación

1. **Build**: `docker build -t vscode-server:test .` (o vía el workflow de Gitea). Confirmar que el
   nuevo `RUN` imprime `claude --version` = `2.1.207` (o superior) sin error de checksum.
2. **Multi-arch**: el `case` cubre amd64/arm64; el build de CI es `linux/amd64,linux/arm64`.
3. **Username-agnostic**: correr el contenedor y, como el usuario por defecto y como otro usuario
   distinto, verificar `which claude` → `/usr/local/bin/claude` y que `claude --version` responde.
4. **Auto-update runtime**: tras un rato de uso, confirmar que aparece `~/.local/share/claude/versions/`
   en el home del usuario (update nativo por usuario) sin permisos root.
5. **MCPs** (tras aplicar la guía en el volumen): `claude mcp list` debe listar gitea/docmost/
   github-personal/penpot/atlassian como `Connected`.
