TL;DR Exporta
CLAUDE_CODE_DISABLE_FILE_MENTIONS=1en tu shell o en el bloqueenvde~/.claude/settings.json. Desde entonces@src/fichero.tsya no adjunta el fichero: Claude recibe la ruta con una nota y lee con sus herramientas lo que la pregunta necesita. Preguntar por una función de un fichero de 22 KB costó 16.418 tokens nuevos por defecto y 5.637 con la variable. Déjala apagada cuando quieras el fichero entero en el contexto.
Cada @ en Claude Code se resuelve antes de que el modelo vea tu mensaje: Claude Code lee el fichero del disco y lo adjunta entero al turno, con el CLAUDE.md de su árbol de propina, como mide el coste oculto del @. No gasta un turno, pero cuánto entra lo decides tú al teclear la arroba, no Claude al leer la pregunta. Desde la v2.1.299, CLAUDE_CODE_DISABLE_FILE_MENTIONS=1 cambia el adjunto por una nota de una línea con la ruta, y es Claude quien decide qué leer y cuánto.
Qué recibe Claude con la variable
La nota, tal como está en el binario de la v2.1.310, en inglés porque es lo que ve el modelo:
The user @-mentioned src/payments.ts. File contents are not attached automatically in this session: if these are files or directories in your working directory, read them with your file tools before responding.
Nada más: ni el fichero, ni el listado si era un directorio. En el .jsonl de la sesión el adjunto cambia de tipo, file con el contenido entero frente a at_mention_reference con la lista de rutas:
jq -r 'select(.type=="attachment") | .attachment
| select(.type=="file" or .type=="at_mention_reference")
| "\(.type)\t\(.filename // (.mentions|join(",")))"' \
~/.claude/projects/<tu-proyecto>/<sesion>.jsonl
Lo que cuesta cada camino
La misma pregunta, "qué devuelve handler42 en @src/payments.ts", sobre un fichero de 22 KB en un proyecto de prueba, en runs -p de Claude Code v2.1.310. Tokens nuevos son los que el turno añade al contexto (cache_creation_input_tokens), los mismos que se releen en cada turno posterior:
modelo por defecto con la variable
Sonnet 5.5 adjunto entero, 16.418 nuevos nota + grep, 5.637 nuevos
Haiku 5.5 adjunto entero, 16.415 nuevos nota + cat del fichero, 16.611 nuevos
Unos 4.700 de cada cifra son el arranque de la sesión, iguales en ambas columnas. Lo que cambia es el resto:
- Sonnet hizo un
grep -n handler42y trajo 25 líneas: cerca de mil tokens frente a los 11.700 del fichero. Y lo que queda en el historial es el fragmento, no el fichero. - Haiku leyó el fichero completo igualmente, con un
cat. El mismo coste que el adjunto, más una llamada. La variable no ahorra por sí sola: delega en el modelo la decisión que antes tomabas tú, y un modelo pequeño con una pregunta vaga lee todo.
Pedir un resumen del fichero tampoco ahorra: el modelo necesita el fichero entero y lo lee con Read, que añade números de línea (15.955 nuevos en dos llamadas frente a 18.222 del adjunto, en Haiku). El ahorro llega cuando la pregunta apunta a una parte.
El fichero grande que ya entraba así, sin avisar
Por defecto el @ adjunta el fichero solo cuando cabe en el límite de la herramienta Read, 25.000 tokens. Por encima, en la v2.1.310 no adjunta nada y no lo dice: con un fichero de 60 KB, la mención se quedó como texto en el mensaje, sin adjunto de ningún tipo, y Haiku lo leyó entero en dos llamadas a Read, 36.188 tokens nuevos, para resumirlo. Con la variable ese fichero llega con la misma nota que los pequeños, y la pregunta concreta sobre él (handler217, con Sonnet) costó 5.339 nuevos con ella y 6.677 sin ella, con un grep en ambos casos.
Cómo activarla
1. En el shell o en los ajustes de usuario
# solo esta sesión
CLAUDE_CODE_DISABLE_FILE_MENTIONS=1 claude
# todas: en ~/.zshrc o ~/.bashrc
export CLAUDE_CODE_DISABLE_FILE_MENTIONS=1
O en ~/.claude/settings.json, que se aplica lo arranques como lo arranques:
{
"env": {
"CLAUDE_CODE_DISABLE_FILE_MENTIONS": "1"
}
}
2. No en el proyecto
Claude Code ignora esta clave en .claude/settings.json y en .claude/settings.local.json, para que un repositorio clonado no decida qué lee Claude. Con --debug lo dice así:
[WARN] CLAUDE_CODE_DISABLE_FILE_MENTIONS in .claude/settings.json is ignored — project-scoped settings can't set this key. Set it in ~/.claude/settings.json or managed settings instead.
3. Apágala para una sesión cuando quieras el fichero entero
1 y true la activan; 0 o el valor vacío la desactivan, aunque la tengas exportada:
CLAUDE_CODE_DISABLE_FILE_MENTIONS=0 claude
4. Pregunta con un objetivo
Con la variable el @ solo le dice a Claude dónde mirar. "Revisa @src/auth.ts" lee el fichero entero; "por qué refreshToken en @src/auth.ts devuelve null" permite un grep. Un directorio, @src/, llega como la misma nota y Claude hace un ls: 173 tokens nuevos el listado. Las otras formas de dar contexto siguen en cinco formas de darle a Claude Code el contexto correcto.
Y un efecto que no tiene que ver con tokens: los hooks PreToolUse no se ejecutan sobre un adjunto @, porque no hay llamada a herramienta. Con la variable sí, porque Claude lee con Read o Bash. Si un hook PreToolUse decide qué puede leer Claude, la variable cierra ese hueco.
Referencia
| Caso | Qué recibe Claude | Qué cuesta |
|---|---|---|
| Por defecto, fichero bajo 25.000 tokens | El fichero entero y el CLAUDE.md de su árbol, antes del primer turno |
Todo el fichero, en este turno y releído en los siguientes |
| Por defecto, fichero por encima | Nada: la ruta queda en tu texto y Claude la lee por su cuenta, sin aviso | Lo que Claude decida leer, sin nota que le pida porciones |
Con CLAUDE_CODE_DISABLE_FILE_MENTIONS=1 |
Una nota con las rutas y la instrucción de leerlas con sus herramientas | Lo que la pregunta necesite, más una llamada |
Docs oficiales: Environment variables
Requisitos
- Claude Code v2.1.299 o posterior. Medido en la v2.1.310, en runs
-psobre un proyecto de prueba, con Sonnet 5.5 y Haiku 5.5. - La variable se lee del entorno, de los ajustes de usuario o de los gestionados; en los del proyecto se ignora.