agent-cloud-kit 1.0.0-rc.6 → 1.0.0-rc.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/manual.js
CHANGED
|
@@ -76,7 +76,7 @@ export function renderEnvironmentSection(config, packageVersion) {
|
|
|
76
76
|
"",
|
|
77
77
|
"Elige el entorno con `/remote-env` y edítalo en claude.ai/code:",
|
|
78
78
|
"",
|
|
79
|
-
`- **
|
|
79
|
+
`- **Acceso a la red:** Limitado (Custom) con "Permitir administradores de paquetes" encendido ("Also include default list of common package managers"). Dominios extra: ${hosts.length ? code(hosts) : "ninguno"}.`,
|
|
80
80
|
`- **Variables:** ${config.requiredEnv.length ? `${code(config.requiredEnv)} (solo los nombres; los valores los pones tú)` : "ninguna"}.`,
|
|
81
81
|
"- **Claude GitHub App:** instalado en el repo, o la sesión no puede pushear.",
|
|
82
82
|
"- **Setup script:**",
|
|
@@ -89,6 +89,12 @@ export function renderEnvironmentSection(config, packageVersion) {
|
|
|
89
89
|
lines.push("", "> ⚠️ Quien use el entorno puede leer las variables, y no llegan al setup script (solo a la sesión).");
|
|
90
90
|
return lines.join("\n");
|
|
91
91
|
}
|
|
92
|
+
/** What to do when the tests change, one line. */
|
|
93
|
+
const TESTS_CHANGE_SECTION = [
|
|
94
|
+
"## Si cambian los tests",
|
|
95
|
+
"",
|
|
96
|
+
`Si agregas tests (p. ej. de Electron) o cambias cómo se corren, corre \`npx ${PACKAGE} prepare\`: la skill \`cloud-ready\` los adapta a la nube sin cambiar lo que comprueban y actualiza este documento.`,
|
|
97
|
+
].join("\n");
|
|
92
98
|
/** The "how to verify" section, one line. */
|
|
93
99
|
const VERIFY_SECTION = [
|
|
94
100
|
"## Verificar",
|
|
@@ -143,6 +149,7 @@ export function renderManual(input) {
|
|
|
143
149
|
renderEnvironmentSection(input.config, input.packageVersion),
|
|
144
150
|
VERIFY_SECTION,
|
|
145
151
|
`## Qué corre en la nube\n\n${notes?.trim() ? notes.trim() : "Nada anotado."}`,
|
|
152
|
+
TESTS_CHANGE_SECTION,
|
|
146
153
|
END,
|
|
147
154
|
];
|
|
148
155
|
return parts.join("\n\n");
|
package/package.json
CHANGED
|
@@ -65,6 +65,9 @@ No le pidas al usuario una lista de variables secretas ni de dominios: anota en
|
|
|
65
65
|
o una rama por `CLAUDE_CODE_REMOTE` en un script existente.
|
|
66
66
|
3. Si nada de eso alcanza, déjalo fuera de la nube y explica por qué.
|
|
67
67
|
|
|
68
|
+
Una app gráfica (Electron, Expo, React Native) no se descarta entera por no tener pantalla:
|
|
69
|
+
mira "Electron" y "Expo y React Native" en `reference/compat.md` y propone lo que sí corre.
|
|
70
|
+
|
|
68
71
|
Muestra cada propuesta con el cambio exacto (archivo y contenido).
|
|
69
72
|
6. **Pregunta y aplica solo lo aprobado.** Un cambio fuera de la config (scripts, compose,
|
|
70
73
|
configuración de tests) necesita un sí explícito del usuario. Nunca cambies lo que un test
|
|
@@ -75,7 +78,7 @@ No le pidas al usuario una lista de variables secretas ni de dominios: anota en
|
|
|
75
78
|
antes) o ❌ (no corre), sin párrafos. Por ejemplo:
|
|
76
79
|
|
|
77
80
|
```markdown
|
|
78
|
-
- ✅ `npm test` (~1 min)
|
|
81
|
+
- ✅ `npm test` (~1 min), el mismo comando que en local y en la CI
|
|
79
82
|
- ⏳ Antes de `npm run test:db`: `docker compose up -d db` (~3 min, en segundo plano)
|
|
80
83
|
- ❌ `npm run test:e2e:prod`: pega a una API externa que el entorno no permite
|
|
81
84
|
```
|
|
@@ -88,9 +91,22 @@ No le pidas al usuario una lista de variables secretas ni de dominios: anota en
|
|
|
88
91
|
claude.ai" de `docs/agent-cloud.md` (setup script, dominios, variables). Dile que ese
|
|
89
92
|
documento se irá actualizando: si la skill, en local o en la nube, detecta que hace falta un
|
|
90
93
|
dominio o una variable nueva, lo agrega ahí y se lo dice.
|
|
91
|
-
10. **
|
|
94
|
+
10. **Resume lo que hiciste**, corto y siempre con estas líneas:
|
|
95
|
+
|
|
96
|
+
```
|
|
97
|
+
Tests en la nube: <comando>, el mismo que en local y en la CI (o qué variante y por qué)
|
|
98
|
+
Adaptaciones: <qué cambió en la preparación (apt, dominios, setup), o "ninguna">
|
|
99
|
+
Tests y scripts: <"no se tocaron", o cada archivo cambiado con tu aprobación>
|
|
100
|
+
Fuera de la nube: <qué no corre y por qué, o "nada">
|
|
101
|
+
Archivos: <los que creaste o cambiaste>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Y termina con: "Si agregas tests (p. ej. de Electron) o cambias cómo se corren, vuelve a
|
|
105
|
+
correr `npx agent-cloud-kit prepare`: adapto lo nuevo a la nube y actualizo
|
|
106
|
+
`docs/agent-cloud.md`."
|
|
107
|
+
11. **No hagas commit:** `agent-cloud-kit prepare` lo hace al salir. Si te invocaron fuera de
|
|
92
108
|
`prepare`, pregunta al usuario.
|
|
93
|
-
|
|
109
|
+
12. **Termina diciéndole al usuario que salga:** dile al usuario, con estas palabras o parecidas,
|
|
94
110
|
"configure terminó: sal de claude con `/exit` y `prepare` sigue". Si te
|
|
95
111
|
invocaron fuera de `prepare`, omite este paso.
|
|
96
112
|
|
|
@@ -176,7 +192,7 @@ inicio de la sesión la marca como faltante, o el error nombra una variable vac
|
|
|
176
192
|
2. Corre `agent-cloud-kit manual`: `docs/agent-cloud.md` queda con lo nuevo.
|
|
177
193
|
3. **Díselo al usuario en la sesión, en ese momento**, sin esperar al final: qué falta, por qué
|
|
178
194
|
(el comando y el error) y qué hacer, con estas palabras o parecidas: "Falta `<X>` en el entorno
|
|
179
|
-
de claude.ai. Agrégalo en <
|
|
195
|
+
de claude.ai. Agrégalo en <Acceso a la red / Variables de entorno> (está en
|
|
180
196
|
`docs/agent-cloud.md`) y vuelve a verificar: en tu terminal, en la rama `<rama>` actualizada
|
|
181
197
|
(`git pull`), corre `npx agent-cloud-kit verify`".
|
|
182
198
|
4. En `verify`, ponlo también en "Cambiar en claude.ai" del comentario del PR.
|
|
@@ -4,6 +4,27 @@ De menos a más invasivo. Prueba cada nivel antes de pasar al siguiente, y prop
|
|
|
4
4
|
cambio exacto: en `configure` se aplica solo lo aprobado; en `verify` solo se tocan los archivos
|
|
5
5
|
de la preparación y el resto queda propuesto en el PR.
|
|
6
6
|
|
|
7
|
+
## Principios
|
|
8
|
+
|
|
9
|
+
- **Los tests no se cambian.** En la nube corre el mismo comando que en local y en la CI, y
|
|
10
|
+
comprueba lo mismo. Si la suite entera tarda, se corre entera igual (en segundo plano).
|
|
11
|
+
- **Lo distinto va en lo que prepara o lanza**, nunca en lo que el test comprueba: el setup,
|
|
12
|
+
los servicios, las imágenes de Docker, cómo se abre la app.
|
|
13
|
+
- **Un arreglo que sirve en todas partes se hace sin condición.** Por ejemplo, que el servidor
|
|
14
|
+
de los tests escuche en `127.0.0.1` (en la nube no hay IPv6): se cambia para todos, no solo
|
|
15
|
+
para la nube.
|
|
16
|
+
- **Detecta la capacidad antes que el lugar.** Sin pantalla (`DISPLAY` vacío), `xvfb-run`; eso
|
|
17
|
+
sirve también en una CI de Linux. `CLAUDE_CODE_REMOTE=true` queda para lo que solo pasa en
|
|
18
|
+
la nube: la CA del proxy en un `docker build`, Docker apagado al empezar.
|
|
19
|
+
- **Un script solo para la nube se niega a correr fuera de ella**, con un mensaje que diga qué
|
|
20
|
+
usar en local (p. ej. `cloud:services`: "solo corre en la nube; en local, `npm run dev`").
|
|
21
|
+
- **La suite de scripts del repo se prueba igual en la nube.** Si un script se bifurca por
|
|
22
|
+
`CLAUDE_CODE_REMOTE`, sus tests empiezan con `unset CLAUDE_CODE_REMOTE` y los casos de la
|
|
23
|
+
nube lo ponen a mano; si no, en una sesión en la nube los casos "locales" corren la rama de
|
|
24
|
+
la nube.
|
|
25
|
+
- **Los tests no dependen de los scripts de desarrollo.** Si los tests levantan su propio
|
|
26
|
+
Docker, no necesitan `cloud:services`; ese script es para desarrollar en la sesión.
|
|
27
|
+
|
|
7
28
|
## 1. Adaptar la preparación
|
|
8
29
|
|
|
9
30
|
Todo va en `.claude/cloud.json`; no toca código ni tests.
|
|
@@ -13,11 +34,17 @@ Todo va en `.claude/cloud.json`; no toca código ni tests.
|
|
|
13
34
|
| Dependencias de npm, pnpm, Yarn o Bun | En `setup`, con el lockfile congelado: `npm ci`, `pnpm install --frozen-lockfile`, `yarn install --immutable`, `bun install --frozen-lockfile`. Node y el gestor fijados los instala el paquete. |
|
|
14
35
|
| Servicios de Docker compose (base de datos, cola) | `docker.pull: "auto"` baja las imágenes en el setup. Levántalos en el comando que corre los tests (`agent-cloud-kit docker && docker compose up -d --wait db`) o, si son rápidos, en `session` (2 min como máximo) con ese mismo comando. `agent-cloud-kit session` arranca `dockerd` en segundo plano sin esperar a que responda; `agent-cloud-kit docker` lo arranca si hace falta y espera hasta 60 s a que `docker info` responda (sale con error si no). Para comprobarlo a mano: `docker info`. |
|
|
15
36
|
| Testcontainers | Necesita Docker respondiendo: corre `agent-cloud-kit docker` antes de los tests (`agent-cloud-kit session` lo arranca pero no espera) y que la imagen esté en el setup: lístala en `docker.pull` si no está en un compose. Si construye imágenes, el CA del proxy entra con `CLOUD_PROXY_CA` como secreto. |
|
|
16
|
-
|
|
|
17
|
-
| `
|
|
37
|
+
| `docker build` dentro de los tests o del e2e | El build no confía en la CA del proxy (`SELF_SIGNED_CERT_IN_CHAIN` al instalar dependencias en la imagen). Ver "Docker build en la nube", abajo. Es un cambio de script y de `Dockerfile`: necesita aprobación. |
|
|
38
|
+
| Playwright | En `setup`, después de instalar las dependencias: `npx playwright install --with-deps chromium` desde la carpeta que declara `@playwright/test` (así usa la versión instalada; el rango de `package.json` no es la versión exacta). Chromium baja de `cdn.playwright.dev`; los otros navegadores pueden usar `playwright.download.prss.microsoft.com`: los dos en `domains`. Baja a `/opt/pw-browsers` (`PLAYWRIGHT_BROWSERS_PATH` ya apunta ahí). La imagen trae los de Playwright 1.63: con otra versión, o se agregan los dominios y se instala, o se usa el Chrome de la imagen (`launchOptions: { executablePath: process.env.CHROME_PATH }`, que no necesita red; es un cambio de config: con aprobación). `--with-deps` usa apt: después de los pasos de apt, nunca a la vez. Corre contra el servidor local de la sesión. |
|
|
39
|
+
| `localhost` en URLs de tests o servicios | No hay IPv6. El servidor escucha en `127.0.0.1`. La URL del navegador puede quedar en `localhost` (Chromium prueba `::1` y luego `127.0.0.1`; así pasó un e2e en la nube), y debe quedar así si el framework reescribe el host: Next (`NextURL`) cambia `127.0.0.1` por `localhost` en las redirecciones, el origen cambia y se pierden las cookies. Un buscador de puertos libres pide el `0` en `127.0.0.1` y prueba el mismo en `::1`; trata como "sin IPv6" un error sin `code` (Bun), `EADDRNOTAVAIL` o `EAFNOSUPPORT` (Node). |
|
|
18
40
|
| Variables secretas (API keys de prueba) | Nombres en `requiredEnv`; el usuario pone los valores en el entorno de claude.ai. Recuerda que las lee cualquiera que use el entorno. |
|
|
19
41
|
| Hosts externos que el setup o los tests necesitan | En `domains`; el manual los lista para la red del entorno. |
|
|
20
|
-
|
|
|
42
|
+
| Electron | Ver "Electron", abajo: corre con `xvfb-run -a … --no-sandbox`; la imagen ya trae Xvfb. |
|
|
43
|
+
| Expo o React Native | Ver "Expo y React Native", abajo: casi todo menos el simulador corre. |
|
|
44
|
+
| Instalar herramientas en el setup | Los releases públicos de GitHub se bajan; lo que da 403 es la API, `archive/` y `codeload` de otros repos. Node: de `nodejs.org`. Bun, pnpm, Yarn: de npm (lo hace el paquete). Un CLI cuyo paquete npm baja de releases: el repo apt del proveedor (`aptRepos`). Dentro de una imagen, no `curl … \| sh` de GitHub: copia el binario de la imagen oficial fijada por digest (`COPY --from=oven/bun:<v>@sha256:<d> /usr/local/bin/bun /usr/local/bin/bun`; `bunx` es un symlink y no viene, y para musl va la etiqueta `-alpine`). |
|
|
45
|
+
| Instalación pesada (dependencias en frío, navegadores) | En `setup`, no en `session` (cada paso de `session` se corta a los 2 min, con SIGKILL al grupo: no corren los `trap`). Lo independiente va en paralelo en un script del repo llamado desde `setup` (`cmd1 & cmd2 &`, `wait` de cada uno, sale con 1 si alguno falló). Si `session` reinstala, con `timeout` (manda SIGTERM, a diferencia del corte del paquete) y una marca (`touch node_modules/.instalado`) que solo se escribe si terminó bien. |
|
|
46
|
+
| Hook SessionStart propio del repo | Nunca hace fallar el inicio (`set -uo pipefail` sin `-e`, cada paso `\|\| aviso`, `exit 0` al final), avisa por stdout (stderr no llega a Claude), revisa lo que dejaron los pasos de `session` (la marca de instalación) y exporta variables en `$CLAUDE_ENV_FILE` solo si el comando que las generó terminó bien (p. ej. un `direnv export` fallido imprime `unset …` y borraría variables). Su `timeout` por defecto ya es 600 s. |
|
|
47
|
+
| Corridas largas (más de 2 min) | En segundo plano con la salida a un log. En la nube, un comando en segundo plano tiene 30 min por defecto (hasta 2 h con `timeout`); `BASH_DEFAULT_TIMEOUT_MS` y `BASH_MAX_TIMEOUT_MS` en las variables del entorno lo cambian. Anota en `notes` cuánto tardan. Ver "Corridas largas", abajo, si pasan de ~25 min. |
|
|
21
48
|
|
|
22
49
|
## 2. Bifurcar una variante para la nube
|
|
23
50
|
|
|
@@ -37,7 +64,132 @@ Déjalo fuera y anótalo en `notes` con el porqué:
|
|
|
37
64
|
- APIs externas que el entorno no permite o que no deben recibir tráfico de pruebas.
|
|
38
65
|
- Secretos que el entorno no tiene (o que no deben estar en un entorno compartido).
|
|
39
66
|
- Lo que necesita abrir puertos hacia fuera o una vista previa (no existen).
|
|
40
|
-
-
|
|
67
|
+
- iOS (simulador o build local): necesita macOS. El emulador de Android: la VM no tiene `/dev/kvm`.
|
|
68
|
+
- Sitios HTTPS externos abiertos con Playwright (bug abierto, ver `knowledge.md`).
|
|
69
|
+
|
|
70
|
+
Antes de dejar fuera una app gráfica (Electron, Expo, un navegador), mira las secciones de abajo:
|
|
71
|
+
casi siempre hay algo que sí corre, y eso va en `notes` con ✅.
|
|
72
|
+
|
|
73
|
+
## Docker build en la nube
|
|
74
|
+
|
|
75
|
+
La CA del proxy entra al build como secreto, solo en la nube; el mismo `Dockerfile` sigue
|
|
76
|
+
funcionando en local y en la CI.
|
|
77
|
+
|
|
78
|
+
1. **Dónde está la CA:** el primero que exista de `CLOUD_PROXY_CA` (lo exporta
|
|
79
|
+
`agent-cloud-kit session`), `SSL_CERT_FILE`, `NODE_EXTRA_CA_CERTS` y
|
|
80
|
+
`/root/.ccr/ca-bundle.crt` (a donde apunta `SSL_CERT_FILE`). Por si una sesión reanudada
|
|
81
|
+
no tiene `CLOUD_PROXY_CA`, se busca en ese orden.
|
|
82
|
+
2. **El script que construye**, solo con `CLAUDE_CODE_REMOTE=true`:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
secret=(); [ -n "$ca" ] && secret=(--secret "id=proxy_ca,src=$ca")
|
|
86
|
+
docker buildx build ${secret[@]+"${secret[@]}"} --load -t "$ref" .
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
3. **El `Dockerfile`**, en cada `RUN` que baja algo (no solo el primero):
|
|
90
|
+
|
|
91
|
+
```dockerfile
|
|
92
|
+
RUN --mount=type=secret,id=proxy_ca,required=false \
|
|
93
|
+
if [ -f /run/secrets/proxy_ca ]; then export SSL_CERT_FILE=/run/secrets/proxy_ca NODE_EXTRA_CA_CERTS=/run/secrets/proxy_ca; fi \
|
|
94
|
+
&& npm ci
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Sin el secreto (local, CI) el build sigue igual: `required=false` es el valor por defecto y
|
|
98
|
+
se deja explícito por claridad. Las dos variables hacen falta: Node y npm leen
|
|
99
|
+
`NODE_EXTRA_CA_CERTS` (no `SSL_CERT_FILE`); Bun lee `SSL_CERT_FILE`.
|
|
100
|
+
4. **Red:** una imagen basada en Debian funcionó con `deb.debian.org` y `security.debian.org`
|
|
101
|
+
en `domains` (la lista por defecto no trae los mirrors de Debian).
|
|
102
|
+
|
|
103
|
+
## Corridas largas
|
|
104
|
+
|
|
105
|
+
Una suite de ~35 min corre entera en la nube (~4 vCPU). Cómo seguirla sin que se corte (la
|
|
106
|
+
técnica está diseñada, pero todavía no se probó entera en la nube):
|
|
107
|
+
|
|
108
|
+
- **Lanzarla suelta:** un proceso aparte, en su propio grupo, con la salida a un log, que
|
|
109
|
+
vuelve enseguida (p. ej. `setsid nohup <comando> > log 2>&1 &`, o un lanzador de Node con
|
|
110
|
+
`detached: true` y `unref()`). Un candado por nombre evita dos corridas a la vez. Si eso la
|
|
111
|
+
saca del límite de 30 min de los comandos en segundo plano de Claude no está comprobado.
|
|
112
|
+
- **Seguirla:** con la herramienta Monitor sobre un comando que imprime una línea de avance
|
|
113
|
+
por minuto y termina antes de los 30 min (el límite de Monitor); si sigue corriendo, se
|
|
114
|
+
relanza. Decide por la última línea del log, no por el código de salida del `watch`.
|
|
115
|
+
- **Pararla:** SIGTERM al grupo (`kill -TERM -- -<pgid>`), con `trap … INT TERM` en el runner
|
|
116
|
+
para que bajen Docker. Un proceso lanzado con `&` desde una shell no interactiva (la de
|
|
117
|
+
Claude) ignora SIGINT y su `trap INT` no corre; SIGINT solo sirve si lo lanzó un lanzador de
|
|
118
|
+
Node. Nunca `kill -9`. Como una corrida cortada deja contenedores, cada runner hace
|
|
119
|
+
`docker compose down -v --remove-orphans` antes del `up`.
|
|
120
|
+
- **No cargar la máquina:** los tests de integración y e2e usan tiempos reales; mientras
|
|
121
|
+
corren, nada pesado en paralelo (ni otros agentes).
|
|
122
|
+
|
|
123
|
+
## Electron
|
|
124
|
+
|
|
125
|
+
Probado en la nube el 2026-11-03 con Electron 45 (`knowledge.md`, "Apps de escritorio y
|
|
126
|
+
móviles"). La imagen ya trae Xvfb y las librerías de Chromium: no hace falta `apt`.
|
|
127
|
+
|
|
128
|
+
1. **El binario:** se baja de releases de GitHub sin nada especial. Desde Electron 42 se baja
|
|
129
|
+
al primer uso: en `setup`, después de instalar las dependencias,
|
|
130
|
+
`node node_modules/electron/install.js`, para que la sesión ya lo tenga. Si el repo tiene su
|
|
131
|
+
propio paso (p. ej. un script que corre `install-electron`), sirve ese. Solo si GitHub
|
|
132
|
+
fallara: `ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/`, con `npmmirror.com` y
|
|
133
|
+
`cdn.npmmirror.com` en `domains`.
|
|
134
|
+
2. **Correrlo:** `xvfb-run -a <comando de Electron> --no-sandbox`. Sin `--no-sandbox` se cae
|
|
135
|
+
(la sesión es root); sin Xvfb, `Missing X server or $DISPLAY`. Los errores de `dbus` y el
|
|
136
|
+
aviso de `--use-openssl-ca` del log son ruido.
|
|
137
|
+
3. **Ver que arranca:** una captura con Playwright (`page.screenshot`) o `import -window root`
|
|
138
|
+
dentro del mismo `xvfb-run` (fuera no hay `DISPLAY`):
|
|
139
|
+
`xvfb-run -a sh -c '<app> --no-sandbox & sleep 5; import -window root captura.png'`.
|
|
140
|
+
`webContents.capturePage()` no sirve (`UnknownVizError`).
|
|
141
|
+
4. **Tests e2e:** Playwright con
|
|
142
|
+
`_electron.launch({ args: ["<main>", "--no-sandbox"] })` bajo `xvfb-run -a` (no necesita
|
|
143
|
+
navegadores de Playwright). Si el repo no los tiene, no los crees: propónlos.
|
|
144
|
+
|
|
145
|
+
`--no-sandbox` y `xvfb-run` van en el comando que lanza Electron en la nube. Si eso cambia un
|
|
146
|
+
script del repo, que sea según la capacidad (sin `DISPLAY`, `xvfb-run`; como root,
|
|
147
|
+
`--no-sandbox`) y con aprobación.
|
|
148
|
+
|
|
149
|
+
## Expo y React Native
|
|
150
|
+
|
|
151
|
+
| Qué | En la nube |
|
|
152
|
+
| --- | --- |
|
|
153
|
+
| Tests de componentes (`jest-expo`, Testing Library) | Corren tal cual, sin red extra. |
|
|
154
|
+
| `npx expo export --platform android` (o `ios`, o `web`), `npx expo prebuild --no-install` | Corren sin simulador ni red extra (~30 s cada export): comprueban que Metro compila el bundle y que la config genera los proyectos nativos. `EXPO_OFFLINE=1` en el export evita llamadas a Expo. `prebuild` escribe `android/` e `ios/` y cambia `app.json` y `package.json`: no lo dejes en el árbol si el repo no lo versiona. |
|
|
155
|
+
| `npx expo-doctor` | Necesita `exp.host`, `api.expo.dev` y `reactnative.directory` en `domains`; con ellos pasa. Sin ellos sale con 1, aun con `EXPO_OFFLINE=1` o `EXPO_DOCTOR_WARN_ON_NETWORK_ERRORS=1`. |
|
|
156
|
+
| Expo web (`react-native-web`) | `npx expo export --platform web` y Playwright contra el resultado servido en `127.0.0.1` (o `npx expo start --web`, que sirve en `:8081`). Con el Chrome de la imagen no necesita red. En web, `GlassView` es un `View` común; `SymbolView` con nombre para web dibuja el ícono (la fuente viene en el bundle) y con solo un nombre de SF Symbols, su `fallback`. Las APIs `@expo/ui/swift-ui` y Compose no tienen web. |
|
|
157
|
+
| Build de Android | Corre, pero es pesado (~19 min y 2,7 GB de SDK la primera vez): ver "Build de Android", abajo. Si el repo no lo corre en sus tests, no lo agregues. |
|
|
158
|
+
| Emulador de Android | Fuera: la VM no tiene `/dev/kvm`. |
|
|
159
|
+
| iOS (simulador, `expo run:ios`, build) | Fuera: necesita macOS. Alternativa: build remoto en EAS con `EXPO_TOKEN` en `requiredEnv` y `expo.dev` y `api.expo.dev` en `domains`. |
|
|
160
|
+
|
|
161
|
+
## Build de Android
|
|
162
|
+
|
|
163
|
+
Verificado con Expo SDK 58 (`expo prebuild` y `./gradlew assembleDebug`). Cada paso hace falta:
|
|
164
|
+
sin él, el build falla en 1–3 min.
|
|
165
|
+
|
|
166
|
+
1. **Red:** `dl.google.com` en `domains` (SDK y `maven.google.com`, que redirige ahí).
|
|
167
|
+
2. **SDK, en el setup:** las command-line tools de
|
|
168
|
+
`https://dl.google.com/android/repository/commandlinetools-linux-<n>_latest.zip` (el número,
|
|
169
|
+
de `repository2-3.xml`) en `$ANDROID_HOME/cmdline-tools/latest`, y los archivos de licencia
|
|
170
|
+
en `$ANDROID_HOME/licenses` (`android-sdk-license` con sus hashes). El resto (NDK, CMake,
|
|
171
|
+
build-tools, plataforma) lo baja Gradle solo. `ANDROID_HOME` va en `$CLAUDE_ENV_FILE`.
|
|
172
|
+
3. **Java:** el JDK que pida el toolchain (Java 17 con React Native) por `apt`
|
|
173
|
+
(`openjdk-17-jdk-headless`); Gradle no puede bajarlo (`api.foojay.io` bloqueado).
|
|
174
|
+
4. **Maven Central:** responde 429 de forma intermitente (IP compartida). Un init script de
|
|
175
|
+
Gradle pone antes el mirror de Google, sin tocar el repo:
|
|
176
|
+
|
|
177
|
+
```groovy
|
|
178
|
+
// ~/.gradle/init.d/maven-mirror.gradle
|
|
179
|
+
def mirror = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
|
180
|
+
beforeSettings { settings ->
|
|
181
|
+
settings.pluginManagement.repositories { maven { url = uri(mirror) }; google(); gradlePluginPortal() }
|
|
182
|
+
}
|
|
183
|
+
allprojects {
|
|
184
|
+
buildscript.repositories { maven { url = uri(mirror) }; google() }
|
|
185
|
+
repositories { maven { url = uri(mirror) }; google() }
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
5. **El build:** en segundo plano con log (~19 min la primera vez, con 4 CPUs).
|
|
190
|
+
|
|
191
|
+
Todo esto es preparación (setup y `~/.gradle`), no cambia el repo. El emulador sigue fuera (sin
|
|
192
|
+
`/dev/kvm`): el build comprueba que compila, no que la app funcione.
|
|
41
193
|
|
|
42
194
|
## Ejemplo: vitest, Postgres en compose y Playwright
|
|
43
195
|
|
|
@@ -1,56 +1,119 @@
|
|
|
1
1
|
# Lo que se sabe de la nube de Claude Code
|
|
2
2
|
|
|
3
|
-
Cada hecho lleva su estado: `verificado` (alguien lo vio,
|
|
4
|
-
en una sesión ves algo que no está aquí o que lo contradice, va
|
|
5
|
-
`docs/agent-cloud.md`, marcado "proponer al paquete" (ver `SKILL.md`).
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
Cada hecho lleva su estado: `verificado` (alguien lo vio, o lo dice la documentación oficial, con
|
|
4
|
+
la fuente) o `por verificar`. Si en una sesión ves algo que no está aquí o que lo contradice, va
|
|
5
|
+
a "Hallazgos" de `docs/agent-cloud.md`, marcado "proponer al paquete" (ver `SKILL.md`).
|
|
6
|
+
|
|
7
|
+
Fuentes: "README" es el README del paquete `agent-cloud-kit`; "documentación" es la de Claude
|
|
8
|
+
Code en code.claude.com (revisada el 2026-11-03); "prueba en la nube, 2026-11-02" son sesiones de
|
|
9
|
+
prueba del paquete (las del 2026-11-03 probaron Electron y Expo, con la red Limitado más la lista de gestores de paquetes); "sesión en la nube, 2026-10" son sesiones de prueba de otro repo preparado
|
|
10
|
+
para la nube.
|
|
8
11
|
|
|
9
12
|
## Máquina y setup
|
|
10
13
|
|
|
11
14
|
| Hecho | Estado | Fuente |
|
|
12
15
|
| --- | --- | --- |
|
|
13
|
-
| El setup script
|
|
14
|
-
|
|
|
15
|
-
|
|
|
16
|
-
|
|
|
17
|
-
|
|
|
18
|
-
|
|
|
19
|
-
|
|
|
20
|
-
|
|
|
21
|
-
|
|
|
22
|
-
|
|
|
23
|
-
| `
|
|
16
|
+
| La VM es Ubuntu 24.04 x86_64 con ~4 vCPU, 16 GB de RAM y 30 GB de disco. El setup script corre como root (`apt install` funciona) desde `/home/user`, antes de que empiece Claude; el repo queda en `/home/user/<repo>`. | verificado | Documentación ("Configure cloud environments"); prueba en la nube, 2026-11-02 |
|
|
17
|
+
| La documentación dice que un setup script que sale con código distinto de 0 impide arrancar la sesión. Pero en una sesión, un setup con una ruta relativa salió con 127 y la sesión arrancó igual, sin aviso. El campo no debe llevar rutas del repo: `npx -y agent-cloud-kit@<versión> setup` lee la config de cada repo en `/home/user`. | verificado (lo visto); contradice la documentación | Documentación ("Setup scripts"); sesión en la nube, 2026-10 |
|
|
18
|
+
| Un setup de más de ~5 min no deja máquina guardada: cada sesión arranca de cero (y puede quedarse en el paso del setup). Cada paso de `setup` del paquete tiene 180 s. | verificado | Documentación ("Environment caching"); README ("What it solves") |
|
|
19
|
+
| La máquina guardada es una copia del disco: lo que el setup escribe (también bajo `/opt`) queda; los procesos que dejó corriendo, no. Se rehace cada ~7 días o al editar el setup script o la red; cambiar `.claude/cloud.json` no la rehace (para forzarla, edita el setup script, p. ej. un comentario con la fecha). | verificado | Documentación ("Environment caching"); README ("Machine fingerprint") |
|
|
20
|
+
| Una sesión cuya VM se restaura (tras una pausa) no vuelve a correr el setup; los cambios del entorno se prueban con una sesión nueva. | verificado | Documentación; README ("What it does not do") |
|
|
21
|
+
| Las variables del panel del entorno llegan a la sesión, pero no al setup script (corre antes de que se definan). Las puede leer cualquiera que use ese entorno. | verificado | Documentación ("Setup scripts", "Set environment variables") |
|
|
22
|
+
| El `node_modules` que instala el setup sigue ahí en la sesión: el `bun install` o `npm ci` en frío va en el setup, no en `session`. | verificado | Sesión en la nube, 2026-10 |
|
|
23
|
+
| `NODE_OPTIONS` lleva `--use-openssl-ca` (Node usa la CA del sistema, con la del proxy). Electron lo avisa en el log ("The NODE_OPTION --use-openssl-ca is not supported in Electron") y sigue; no es un error. | verificado | prueba en la nube, 2026-11-03 (Electron) |
|
|
24
|
+
| No hay `/dev/kvm`: el emulador de Android no corre acelerado. | verificado | prueba en la nube, 2026-11-03 (Electron) |
|
|
25
|
+
| Node: la documentación lista `/opt/node20`, `/opt/node21` y `/opt/node22`, con 22 en el `PATH`. En la prueba también estaban `/opt/node24` y navegadores de Playwright en `/opt/pw-browsers` (`PLAYWRIGHT_BROWSERS_PATH` apunta ahí). Sin el setup del paquete, `node -v` da 22 aunque el repo fije otra versión en `.tool-versions`. | verificado | Documentación ("Installed tools"); prueba en la nube, 2026-11-02 y 2026-11-03 (Expo) |
|
|
26
|
+
| Los navegadores de `/opt/pw-browsers` son los de `playwright@1.63.0`, instalado global con `serve`, `http-server`, `typescript`, `eslint`, `prettier`, `pnpm` y `yarn`. Un repo con otra versión de `@playwright/test` (p. ej. 1.64) pide su propio navegador y falla con `Executable doesn't exist` hasta instalarlo (necesita `cdn.playwright.dev` en `domains`) o hasta apuntar `launchOptions.executablePath` al Chrome de la imagen (`CHROME_PATH`), que funcionó. | verificado | prueba en la nube, 2026-11-03 (Expo) |
|
|
27
|
+
| La imagen trae Chrome for Testing (`/usr/bin/google-chrome`, `CHROME_PATH`), OpenJDK 21 con Maven y Gradle, PostgreSQL 16 y Redis 7 (sin arrancar). No trae Android SDK ni emulador. | verificado | Documentación ("Installed tools") |
|
|
28
|
+
| La imagen también trae, aunque la documentación no lo lista, Xvfb, `xauth`, ImageMagick (`import`) y las librerías de Chromium con los nombres de Ubuntu 24.04 (`libnss3`, `libgtk-3-0t64`, `libgbm1`, `libasound2t64`, `libxss1`, `libatk-bridge2.0-0t64`): para Electron no hace falta `apt`. | verificado | prueba en la nube, 2026-11-03 (Electron) |
|
|
29
|
+
| No hay pantalla (`DISPLAY` vacío): una app gráfica sin Xvfb sale con `Missing X server or $DISPLAY`. Con `xvfb-run -a …` (ya instalado) arranca; la pantalla virtual mide 1280×1024. | verificado | prueba en la nube, 2026-11-03 (Electron) |
|
|
30
|
+
| `dockerd` viene apagado y el clon es parcial (sin historial completo ni `origin/<rama por defecto>`); `agent-cloud-kit session` prende Docker y completa el clon. Docker funciona dentro de la sesión. | verificado | README ("What it solves"); prueba en la nube, 2026-11-02 |
|
|
31
|
+
| Dos `apt` a la vez chocan en el lock de dpkg (también `playwright install --with-deps`, que usa apt). | verificado | README ("What it solves"); sesión en la nube, 2026-10 |
|
|
32
|
+
| La documentación advierte que Bun tiene problemas con el proxy. Con Bun 1.4.2, `bun install --frozen-lockfile` funcionó en el setup y en el hook. | verificado | Documentación ("Installed tools"); sesión en la nube, 2026-10 |
|
|
33
|
+
| Desde Bun 1.4.0 las credenciales del proxy se codifican bien (`oven-sh/bun#31782`, arreglo en `fetch`; que `bun install` use el mismo cliente es una inferencia): el problema sería de versiones anteriores. | por verificar | Changelog de Bun; no comprobado con versiones anteriores |
|
|
34
|
+
| `bun install` puede colgarse en repos grandes (`anthropics/claude-code#14926`, con Bun 1.3.5; cerrado por inactividad, sin arreglo): ponle `timeout`. | por verificar | Issue; no visto |
|
|
35
|
+
| Tiempos medidos: setup ~77 s en el log del runner (Node, Bun, apt en serie, imágenes de Docker, Playwright); con un `bun install` en frío, ~1,5 min. Un hook SessionStart que instala, completa el clon y trae `origin/<rama por defecto>`, ~18 s. | verificado | Sesión en la nube, 2026-10 |
|
|
36
|
+
| `SSL_CERT_FILE` apunta a la CA del proxy, `/root/.ccr/ca-bundle.crt`. | verificado | Sesión en la nube, 2026-10 |
|
|
37
|
+
| Si faltan `SSL_CERT_FILE` y `NODE_EXTRA_CA_CERTS`, la CA sigue en `/root/.ccr/ca-bundle.crt`. | por verificar | Respaldo usado en el script de un repo; no visto |
|
|
38
|
+
| Una sesión reanudada puede no tener lo que un hook anterior exportó en `$CLAUDE_ENV_FILE` (p. ej. `CLOUD_PROXY_CA`): los scripts deben volver a buscarlo. El hook SessionStart también corre al reanudar, así que puede no pasar. | por verificar | Supuesto en el script de un repo; no visto |
|
|
39
|
+
| La lista de red por defecto trae los mirrors de Ubuntu, no los de Debian. Un `docker build` basado en Debian funcionó con `deb.debian.org` y `security.debian.org` en `domains`; no se probó sin ellos. | verificado (la lista); por verificar (que hagan falta) | Documentación ("Default allowed domains"); sesión en la nube, 2026-10 |
|
|
40
|
+
| `CLAUDE_CODE_SYNC_SKILLS=1` baja las skills habilitadas en la cuenta de claude.ai antes de la primera consulta. `CLAUDE_CODE_SYNC_PLUGINS=1` también está definida; qué hace no está documentado. | verificado (SKILLS); por verificar (PLUGINS) | Documentación ("Environment variables"); prueba en la nube, 2026-11-02 |
|
|
24
41
|
|
|
25
42
|
## Red
|
|
26
43
|
|
|
27
44
|
| Hecho | Estado | Fuente |
|
|
28
45
|
| --- | --- | --- |
|
|
29
|
-
| La red *Custom* sin la casilla "Also include default list of common package managers" bloquea npm (DNS o `CONNECT 403`). | verificado |
|
|
30
|
-
| El proxy
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
46
|
+
| La red *Custom* sin la casilla "Also include default list of common package managers" bloquea npm (DNS o `CONNECT 403`). En la app en español, Custom es **Limitado** y la casilla es **Permitir administradores de paquetes** (Trusted no aparece: las opciones son Ninguno, Limitado y Completo). | verificado | Documentación ("Allow specific domains"); sesión en la nube, 2026-10 |
|
|
47
|
+
| El tráfico a GitHub pasa por un proxy propio, no por la lista de red. La API REST solo sirve los repos de la sesión (otro repo da 403, `GitHub access to …`); GraphQL, nunca. Las descargas `github.com/<o>/<r>/archive/` y `codeload.github.com` de otro repo dan el mismo 403, aunque sea público. | verificado | Documentación ("GitHub proxy"); prueba en la nube, 2026-11-02 (GraphQL y REST) |
|
|
48
|
+
| Los releases públicos de GitHub sí se bajan: `github.com/<o>/<r>/releases/download/…` redirige a `release-assets.githubusercontent.com` (en la lista por defecto) y responde 200. Probado con Electron 45.2.1 y con el wrapper de Gradle (`services.gradle.org` redirige a releases de GitHub). Lo que da 403 es la API, `archive/` y `codeload` de repos que no son de la sesión. | verificado | prueba en la nube, 2026-11-03 (Electron) |
|
|
49
|
+
| Los archivos de repos públicos pasan por `raw.githubusercontent.com` (en la lista por defecto). jsDelivr (`cdn.jsdelivr.net`, `data.jsdelivr.com`, agregándolos) sirvió de mirror para bajar archivos de GitHub. | verificado | Documentación ("GitHub proxy"); sesión en la nube, 2026-10 |
|
|
50
|
+
| Un host propio (también detrás de Cloudflare) responde desde la nube en cuanto se agrega a `domains`. `npmmirror.com` y `cdn.npmmirror.com`, agregados, respondieron 200. | verificado | Sesión en la nube, 2026-10; prueba en la nube, 2026-11-03 (Electron) |
|
|
51
|
+
| `dl.google.com` (Android SDK) no está en la lista por defecto: sin agregarlo, no responde. `maven.google.com` sí responde, pero sus artefactos redirigen a `dl.google.com` (403): el repo `google()` de Gradle también necesita `dl.google.com`. | verificado | prueba en la nube, 2026-11-03 (Electron y Expo) |
|
|
52
|
+
| Maven Central (`repo.maven.apache.org`, `repo1.maven.org`) responde 429 ("Your ip has exceeded rate limits") de forma intermitente, también a artefactos que existen: la IP de salida es compartida. Gradle trata el 429 como error y no pasa al repo siguiente, y `plugins.gradle.org` redirige a Maven Central muchos artefactos, así que ponerlo primero no alcanza. El mirror de Google, `maven-central.storage-download.googleapis.com/maven2/`, responde sin agregarlo a `domains`; consultado antes que Maven Central (init script de Gradle), el build no hizo ningún pedido a Maven Central y no hubo 429. | verificado | prueba en la nube, 2026-11-03 (Expo, 4 sesiones) |
|
|
53
|
+
| Gradle no puede bajar JDKs (toolchains): `api.foojay.io` no está en la lista (`Unable to tunnel through proxy … 403`). Un JDK que falte se instala con `apt` (`openjdk-17-jdk-headless`, 16 s). | verificado | prueba en la nube, 2026-11-03 (Expo) |
|
|
54
|
+
| `cdn.playwright.dev` y `playwright.download.prss.microsoft.com` no están en la lista por defecto: `npx playwright install` falla con 403 (`request blocked: no rule or allowlist entry allows host`). | verificado | prueba en la nube, 2026-11-03 (Expo) |
|
|
55
|
+
| Expo: `exp.host`, `api.expo.dev`, `expo.dev` y `reactnative.directory` no están en la lista por defecto. | verificado | prueba en la nube, 2026-11-03 (Expo) |
|
|
56
|
+
| Los "network secrets" del entorno los pone el proxy en el pedido (por defecto, una cabecera `Authorization: Bearer`; hay otros tipos, p. ej. usuario y contraseña), nunca en el cuerpo: una credencial que va en el cuerpo (p. ej. el login de un CLI de secretos) tiene que ser una variable de entorno. No se aplican a los pedidos del setup script ni a los registros públicos (npm, PyPI…). | verificado | Documentación ("Add network secrets") |
|
|
57
|
+
| Un cambio de variables llega a una sesión abierta cuando su VM se restaura o se rehace; para usarlo ya, sesión nueva. | verificado | Documentación ("Set environment variables") |
|
|
58
|
+
| El proxy reemplaza el TLS: `HTTPS_PROXY`, `NO_PROXY`, `SSL_CERT_FILE` y `NODE_EXTRA_CA_CERTS` vienen definidas. `docker build` no confía en su CA (`SELF_SIGNED_CERT_IN_CHAIN` al instalar dependencias en la imagen): pásala como secreto con `CLOUD_PROXY_CA` (lo exporta `agent-cloud-kit session`). | verificado | Prueba en la nube, 2026-11-02; sesión en la nube, 2026-10; README ("The proxy CA") |
|
|
59
|
+
| No hay IPv6: `listen` en `::1` falla. Bun 1.4.2 tira un error sin `code`; Node 24 da `EAFNOSUPPORT`. Un buscador de puertos libres que probaba `::1` falló en los tests de scripts. | verificado | README ("What it solves"); sesión en la nube, 2026-10 |
|
|
60
|
+
| Un e2e con el servidor en `127.0.0.1` y la URL del navegador en `localhost` pasó en la nube (Chromium prueba `::1` y luego `127.0.0.1`). | verificado | Sesión en la nube, 2026-10 |
|
|
61
|
+
| No hay puertos abiertos ni vista previa: la app no se ve en un navegador externo. Playwright sí corre dentro de la sesión, contra `localhost`. | verificado | README ("What it does not do"); sesión en la nube, 2026-10 |
|
|
62
|
+
| Playwright (Chromium) puede no llegar a sitios HTTPS externos a través del proxy; contra `localhost` funciona. | verificado | Bug abierto `anthropics/claude-code#11791` |
|
|
36
63
|
|
|
37
64
|
## GitHub
|
|
38
65
|
|
|
39
66
|
| Hecho | Estado | Fuente |
|
|
40
67
|
| --- | --- | --- |
|
|
41
|
-
| `gh` 2.89 está instalado. `gh auth status` dice que
|
|
42
|
-
| `gh pr …` y `gh issue …` fallan con 403 porque usan GraphQL
|
|
43
|
-
| `gh pr ready` no funciona (GraphQL). Para draft/ready y auto-merge habría rutas REST: `POST /repos/{o}/{r}/pulls/{n}/ccr/ready_for_review`, `…/ccr/convert_to_draft`, `PUT\|DELETE …/ccr/auto_merge`, `GET …/ccr/review_threads`. | por verificar | Mensaje del 403 de GraphQL en la nube (2026-11)
|
|
44
|
-
|
|
|
45
|
-
|
|
|
68
|
+
| `gh` 2.89 está instalado. `GH_TOKEN` y `GITHUB_TOKEN` valen `proxy-injected` y `gh auth status` dice que el token es inválido, pero `gh api` REST funciona: el proxy pone la credencial. | verificado | Documentación ("Work with GitHub issues and pull requests"); prueba en la nube, 2026-11-02 |
|
|
69
|
+
| `gh pr …` y `gh issue …` fallan con 403 porque usan GraphQL. El 403 empieza con `GitHub GraphQL is not available from Claude Code sessions`, nombra la alternativa `gh api repos/{owner}/{repo}/...` y vale para todo pedido a GraphQL (también `gh api graphql`, con cualquier token). | verificado | Documentación ("GitHub proxy"); prueba en la nube, 2026-11-02 |
|
|
70
|
+
| `gh pr ready` no funciona (GraphQL). Para draft/ready y auto-merge habría rutas REST: `POST /repos/{o}/{r}/pulls/{n}/ccr/ready_for_review`, `…/ccr/convert_to_draft`, `PUT\|DELETE …/ccr/auto_merge`, `GET …/ccr/review_threads`. Nadie las probó todavía. | por verificar | Mensaje del 403 de GraphQL en la nube (2026-11) |
|
|
71
|
+
| Comentar por REST (`gh api repos/{o}/{r}/issues/{n}/comments`) y `git push origin HEAD:<otra rama>` funcionan y salen con la cuenta del usuario. | verificado | Sesión en la nube, 2026-10; prueba en la nube, 2026-11-02 |
|
|
72
|
+
| Crear un PR (`POST repos/{o}/{r}/pulls` con `-F draft=true`), editarlo (`PATCH pulls/{n}`) y asignar (`POST issues/{n}/assignees`) por REST. | por verificar | Diseñado en un repo; no probado en la nube |
|
|
73
|
+
| `gh api user` (y `@me`) puede fallar porque no es una ruta de un repo: avisa y sigue. `gh extension install <owner/repo>` fallaría (otro repo); una herramienta así va como paquete npm. | por verificar | Documentación ("GitHub proxy"); `gh api search/issues` dio 403 por no ser una ruta del repo (sesión en la nube, 2026-10) |
|
|
74
|
+
| El `origin` del clon es el proxy local de git (`http://local_proxy@127.0.0.1:<puerto>/git/<owner>/<repo>`): lo que espera una URL de github.com se rompe; tomar las dos últimas partes de la ruta funciona. | por verificar | Formato usado en los tests de un repo |
|
|
75
|
+
| El clon trae solo algunas ramas (la de la sesión y la base), sin `origin/<rama por defecto>`: `git fetch origin <rama>` no crea `origin/<rama>`. Pasa el refspec: `git fetch -q origin <rama>:refs/remotes/origin/<rama>` (o `'+refs/heads/*:refs/remotes/origin/*'` para todas). | verificado | Sesión en la nube, 2026-10 |
|
|
76
|
+
| El clon es superficial: lo que mira el historial (p. ej. un escáner de secretos en los tests) ve todo como agregado en el commit del borde hasta un `git fetch --unshallow` (lo hace `agent-cloud-kit session`). | verificado | Sesión en la nube, 2026-10 |
|
|
77
|
+
| La sesión trabaja en su propia rama `claude/<slug>`, parte del commit de la rama local desde la que se lanzó (`CLAUDE_CODE_BASE_REF`) y puede empujar a otra rama: `git push origin HEAD:<rama>`. | verificado | Prueba en la nube, 2026-11-02 |
|
|
78
|
+
| Sin el Claude GitHub App instalado en el repo, `claude --cloud` sube una copia local del repo. Esa sesión solo puede empujar si la conexión de GitHub del usuario tiene permiso (p. ej. con `/web-setup`). | verificado | Documentación ("Send local repositories without GitHub") |
|
|
46
79
|
|
|
47
80
|
## Claude Code
|
|
48
81
|
|
|
49
82
|
| Hecho | Estado | Fuente |
|
|
50
83
|
| --- | --- | --- |
|
|
51
|
-
| Claude Code no descubre `.agents/skills/`, ni en local ni en la nube
|
|
52
|
-
| Los plugins de la máquina local
|
|
53
|
-
| `claude --
|
|
54
|
-
|
|
|
55
|
-
|
|
|
56
|
-
|
|
|
84
|
+
| Claude Code no descubre `.agents/skills/`, ni en local ni en la nube: solo `.claude/skills/`. Un symlink `.claude/skills/<nombre> -> ../../.agents/skills/<nombre>` funciona (lo crea `agent-cloud-kit init`). | verificado | Documentación ("Skills"); prueba en la nube, 2026-11-02 |
|
|
85
|
+
| Los plugins de la máquina local (y los que activa `.claude/settings.json`) no se cargan en la nube. | verificado | Documentación ("Install plugins"); README ("What it does not do") |
|
|
86
|
+
| Un plugin instalado en el setup (un marketplace local y `claude plugin install <p>@<mkt> --scope user`) tiene sus skills y comandos en la sesión. Copiar las skills al repo es más simple y no depende de la red. | verificado | Sesión en la nube, 2026-10 |
|
|
87
|
+
| En la nube corren los hooks de la configuración administrada por la organización y los del repo; los del repo no corren en sesiones con varios repos ni en los hilos de un proyecto. Si corren los hooks de un plugin instalado en el setup no se sabe (en una sesión no apareció la salida del SessionStart de uno). | verificado (la documentación); por verificar (plugins) | Documentación ("Cloud environments"); sesión en la nube, 2026-10 |
|
|
88
|
+
| El hook SessionStart corre al empezar y al reanudar (el setup, solo en sesiones nuevas). Lo que imprime en stdout entra al contexto de Claude; el stderr de un hook que sale con 0 no llega. Su `timeout` por defecto es 600 s; un hook de 165 s terminó bien. | verificado | Documentación ("Hooks"); sesión en la nube, 2026-10 |
|
|
89
|
+
| Lo que el hook SessionStart escribe en `$CLAUDE_ENV_FILE` queda para los comandos de Bash de Claude. Esos comandos corren en shells no interactivos: los hooks de shell (p. ej. direnv) no se disparan, así que lo que deban ver se exporta ahí. | verificado | Documentación ("Hooks"); sesión en la nube, 2026-10 |
|
|
90
|
+
| En la nube, los hooks del `.claude/settings.json` del repo corren sin pedir confianza: abrir una sesión en la rama de otro ejecuta su código. En local, una sesión interactiva los retiene hasta aceptar el diálogo de confianza. Para revisar PRs ajenos en local: `claude --settings '{"disableAllHooks": true}'`. | verificado | Documentación ("Hooks"); sesión en la nube, 2026-10 |
|
|
91
|
+
| Una skill del repo con el nombre de una integrada (p. ej. `code-review`) choca con ella. La documentación dice que la del proyecto reemplaza a la integrada (`/review` sigue siendo la integrada); en una sesión pareció ganar la integrada. Mejor no repetir nombres de skills integradas. | por verificar | Documentación ("Skills"); sesión en la nube, 2026-10 |
|
|
92
|
+
| `CLAUDE_CODE_REMOTE=true` solo en las sesiones en la nube. `CLAUDE_CODE_REMOTE_SESSION_ID` vale `cse_<id>`; el enlace es `https://claude.ai/code/session_<id>` (mismo sufijo). `claude --teleport session_<id>` (o `cse_<id>`) la retoma desde otra máquina. | verificado | Documentación ("Environment variables", "Link output back to the session"); prueba en la nube, 2026-11-02 |
|
|
93
|
+
| `claude --cloud` usa el entorno elegido con `/remote-env`, que queda en `remote.defaultEnvironmentId` de la configuración del usuario. `--environment` solo acepta entornos self-hosted (`ccpool_…`, desde Claude Code 2.1.224), que son beta pública en planes Team y Enterprise. | verificado | Documentación ("Cloud environments", "Self-hosted environments"); `claude --help` |
|
|
94
|
+
| `claude --cloud <prompt>` exige una terminal interactiva (con la salida a un pipe se niega; corre en primer plano); toma el texto como primer mensaje, imprime la URL de la sesión y el comando `claude --teleport`, y vuelve. | verificado | Prueba en la nube, 2026-11-02 |
|
|
95
|
+
| `claude --cloud` clona del remoto de GitHub la rama actual, no el checkout local: empuja antes. Si la rama no está en GitHub, avisa `Branch <name> is not on GitHub` y parte de otro commit. No tiene opción de rama. | verificado | Documentación ("Start a cloud session from your terminal"); prueba en la nube, 2026-11-02 |
|
|
96
|
+
| Un `/skill args` como primer mensaje de `claude --cloud`. | por verificar | No probado |
|
|
97
|
+
| El teleport trae la conversación y la rama a la terminal (pide el árbol limpio y la misma cuenta), pero lo que se hace en local no vuelve a la sesión en la nube. Desde la terminal no se sigue la sesión en vivo: solo se le manda un mensaje con `claude -p "<mensaje>" --cloud <id>`. | verificado | Documentación ("Move tasks between terminal and cloud") |
|
|
98
|
+
| Una suite de ~35 min (34 min) corre entera en la nube con ~4 vCPU. | verificado | Sesión en la nube, 2026-10 |
|
|
99
|
+
| Un comando de Bash en primer plano espera 2 min por defecto (10 como máximo); al llegar al límite no se corta: pasa a segundo plano (salvo que empiece con `sleep`) y puede seguir 30 min más. En la nube, un comando en segundo plano tiene 30 min por defecto, hasta 2 h con `timeout`; `BASH_DEFAULT_TIMEOUT_MS` y `BASH_MAX_TIMEOUT_MS` en las variables del entorno los cambian. | verificado | Documentación ("Time limits", "Tools reference") |
|
|
100
|
+
| La herramienta Monitor tiene un plazo de 5 min por defecto y 30 min como máximo: una corrida más larga se sigue en tramos. | verificado | Documentación ("Tools reference") |
|
|
101
|
+
| Tras unos minutos sin actividad la VM se pausa (los archivos quedan) y luego puede ser reclamada: al reabrir, los procesos en segundo plano no vuelven. Si un proceso en segundo plano cuenta como actividad no está documentado. | verificado (la pausa); por verificar (la actividad) | Documentación ("Environment expired") |
|
|
102
|
+
|
|
103
|
+
## Apps de escritorio y móviles
|
|
104
|
+
|
|
105
|
+
"No hay pantalla" no significa "no corre": casi siempre se puede probar algo. Cómo, en
|
|
106
|
+
`compat.md` ("Electron" y "Expo y React Native"). Electron y Expo (SDK 58) se probaron en la
|
|
107
|
+
nube el 2026-11-03; el build de Android, solo hasta donde lo frena la red.
|
|
108
|
+
|
|
109
|
+
| Hecho | Estado | Fuente |
|
|
110
|
+
| --- | --- | --- |
|
|
111
|
+
| Electron 45 corre en la nube con `xvfb-run -a npx electron <main> --no-sandbox`. Sin `--no-sandbox` (la sesión es root) se cae: `Running as root without --no-sandbox is not supported` (SIGTRAP). Los errores de `dbus` del log (`Failed to connect to the bus`) no impiden nada. | verificado | prueba en la nube, 2026-11-03 (Electron) |
|
|
112
|
+
| El binario de Electron se baja directo de releases de GitHub en ~8 s, sin mirror ni variables. `ELECTRON_MIRROR=https://npmmirror.com/mirrors/electron/` (con `npmmirror.com` y `cdn.npmmirror.com` en `domains`) también funciona, pero no hace falta; `ELECTRON_GET_USE_PROXY=1` tampoco hizo falta. Desde Electron 42 no hay postinstall: se baja al primer uso, o en el setup con `node node_modules/electron/install.js` (`npx install-electron --no`). | verificado | prueba en la nube, 2026-11-03 (Electron); código de `electron` 45 |
|
|
113
|
+
| Playwright `_electron.launch({ args: ["<main>", "--no-sandbox"] })` bajo `xvfb-run -a` abre la ventana y saca capturas (`page.screenshot`): el test pasó en 1,8 s. `import -window root` dentro del mismo `xvfb-run` captura la pantalla entera. `webContents.capturePage()` falla con `UnknownVizError`: usa Playwright o `import`. | verificado | prueba en la nube, 2026-11-03 (Electron) |
|
|
114
|
+
| Expo SDK 58 sin red extra: `npm ci` (48 s), `jest-expo` con Testing Library (10 s), `expo export` para web, Android e iOS (~30 s cada uno; Android e iOS con `EXPO_OFFLINE=1`) y `expo prebuild --no-install` para Android e iOS (~5 s) pasan. `prebuild` escribe `android/` e `ios/` y además cambia `app.json` y `package.json`. `expo start --web` sirve la página en `127.0.0.1:8081`. | verificado | prueba en la nube, 2026-11-03 (Expo) |
|
|
115
|
+
| `expo-doctor` sin los dominios de Expo sale con 1 (falla el chequeo del esquema, que va a `exp.host`, y el de React Native Directory). `EXPO_OFFLINE=1` no cambia nada, y `EXPO_DOCTOR_WARN_ON_NETWORK_ERRORS=1` tampoco lo hace pasar. Con `exp.host`, `api.expo.dev` y `reactnative.directory` en `domains` pasa (20/20, ~5 s). | verificado | prueba en la nube, 2026-11-03 (Expo) |
|
|
116
|
+
| Expo web con Playwright y el Chrome de la imagen, contra el export servido en `127.0.0.1`: pasa, con capturas. En web, `GlassView` (`expo-glass-effect`) es un `View` común y su contenido se ve. `SymbolView` (`expo-symbols`) con un nombre por plataforma (`{ ios, android, web }`) dibuja el ícono con la fuente Material Symbols, que viene en el bundle (sin red); con solo un nombre de SF Symbols dibuja el `fallback`. Las APIs `@expo/ui/swift-ui` y Jetpack Compose no tienen versión web (no probado). | verificado (glass, symbols); por verificar (`@expo/ui`) | prueba en la nube, 2026-11-03 (Expo); documentación de Expo |
|
|
117
|
+
| iOS (simulador o build) nunca corre en la nube: necesita macOS y Xcode. Se puede lanzar un build remoto en EAS con `EXPO_TOKEN` en `requiredEnv` (el proyecto ya vinculado, `extra.eas.projectId`) y `expo.dev` y `api.expo.dev` en `domains`. | verificado (iOS); por verificar (EAS) | Requisito de Xcode; documentación de EAS |
|
|
118
|
+
| El emulador de Android necesita `/dev/kvm`, y la VM no lo tiene: queda fuera. | verificado | prueba en la nube, 2026-11-03 (Electron) |
|
|
119
|
+
| El build de Android (`./gradlew assembleDebug` tras `expo prebuild`, Expo SDK 58) corre en la nube: APK debug de 252 MB en 18 min 49 s (4 CPUs). Hace falta: `dl.google.com` en `domains`; las command-line tools del SDK (~16 s) y los archivos de licencia en `$ANDROID_HOME/licenses` (el `sdkmanager` nuevo dice que `--licenses` ya no hace falta, pero Gradle falla con `LicenceNotAcceptedException`); Java 17 por `apt` (el plugin de React Native lo pide como toolchain); y el mirror de Maven Central. Con eso, Gradle bajó solo el NDK, CMake, build-tools y la plataforma: el SDK quedó en 2,7 GB. Sin cada uno de esos pasos, falla en 1–3 min. | verificado | prueba en la nube, 2026-11-03 (Expo, 6 sesiones) |
|