git ls-files para coding agents: index y disco, no find
Resumen
git ls-files mezcla el index con el working tree. Default: tracked. -o son untracked; -i exige -c o -o y un --exclude*. Un agente parsea -z, nombra paths, no vuelca el árbol al LLM y no usa find. Git 2.50.1.

Qué resuelve
Esta pieza se queda en la decisión práctica: qué instalar, qué riesgo agrega y cómo aplicarlo sin romper operación.
git ls-files no es find. El man (git-ls-files(1), Git 2.50.1 / Apple Git-155; git-scm.com/docs/git-ls-files HTTP 200, last updated in 2.55.0; 2.46.2 → 2.54.0 sin cambios) mezcla la lista del index con el working tree y enseña combinaciones. Default si no pasas -c/-s/-d/-o/-u/-k/-m/--resolve-undo: tracked del index (--cached). Un path untracked no aparece. Un path que Git no rastrea no es “el árbol”.
GitHub Docs (Finding files on GitHub, HTTP 200 2026-09-04): el file finder de la UI (t / Go to file) busca en el remoto, no en tu worktree. Por default excluye .git, .hg, .sass-cache, .svn, build, dot_git, log, tmp y vendor. Eso no es ls-files. Contrato: flags explícitas, -z para parsear, cero dump del árbol al prompt.
Esta guía no sustituye status (porcelain XY) ni gitignore (qué patrón aplica). El contrato: qué forma corre un agente, qué flags están prohibidas, y por qué find no es el index.
Index y disco no son lo mismo
Sin flags, ls-files imprime paths del index. -o / --others añade untracked. -d son deletes unstaged. -m son modificaciones unstaged; el man: un delete unstaged también cuenta como modified. -s / --stage imprime modo, objeto y stage (0 en un merge limpio; 1/2/3 en conflicto). -u / --unmerged fuerza --stage y esconde el resto de tracked.
-i / --ignored no va solo. El man: exige -c o -o. Con -c, lista tracked que coinciden con un exclude. Con -o, untracked que coinciden. Las reglas estándar no se activan solas: hace falta al menos un --exclude*. --exclude-standard carga .gitignore por directorio, $GIT_DIR/info/exclude y el ignore global.
-z: NUL al final, paths sin quoting C. Sin -z, core.quotePath puede entrecomillar. Un parser que parte por espacio sobre un path con espacio se rompe.

Lo que el agente sí / no corre
| Quiero | Comando | Trampa |
|---|---|---|
| ¿Este path está en el index? | git ls-files --error-unmatch -- path | find . -name y asumir que Git lo rastrea |
| Untracked visibles | git ls-files -o --exclude-standard -z | -o sin exclude: mete node_modules |
| Ignored untracked | git ls-files -o -i --exclude-standard | -i solo (fatal: must be used with either -o or -c) |
| Conflicto | git ls-files -u | -t “porque las letras se ven mejor” |
Prohibido en autónomo:
find ./ls -Rvolcado al LLM. El man lista index + worktree según flags. Unfindcruza ignored, build y el scratch del agente.-isin-c/-o. Verificado 2026-09-04:git ls-files -i→ must be used with either -o or -c.-i -osin--exclude*. Verificado: needs some exclude pattern.-t/-v/-fpara “entender el status”. El man: para scripts, status--porcelainogit-diff-files --name-statusson casi siempre superiores. Tags:Htracked limpio,Sskip-worktree,Munmerged,Rdelete unstaged,Cchange unstaged,Kkilled,?untracked,Uresolve-undo.-vminúsculas si assume-unchanged;-fsi fsmonitor valid. Un agente no mezcla esas letras con porcelain XY.--formatcombinado con-s,-o,-k,-t,--resolve-undo,--eol. Verificado: cannot be used with… (el man local 2.50.1 también nombra--deduplicateen el fatal).--format='%(objectname) %(path)'es para cached.--debug. El man: formato puede cambiar. No es API.--recurse-submodulesautónomo. Solo--cachedy--stage. Recorre submodules activos.--sparsepara “resumir” el cone. Si el index es sparse, enseña directorios con slash (x/) sin expandir. Un agente no pide el cone entero “para listar”.--with-tree+-s/-u. El man: does not make any sense. Pretende que paths quitados del index desde un tree-ish siguen.-k/--killedcomo “limpia el disco”. Son untracked que chocan con un tracked (file vs dir) y bloquean el checkout. Borrar a ciegas no es el ticket.--pathspecglobs de shell sin comillas. El man acepta<file>…; el shell expande primero.- Encadenar
ls-files -z | xargs -0 rm -f(el ejemplo de vendor drop vive en rm). Listar no es borrar.
-c es el default. Pedirlo otra vez no cambia el set. --deduplicate aplasta duplicados de merge stages o de -d+-m solo cuando la salida es filename; con -t/-u/-s no hace nada.
Receta (60 segundos)
Solo en un worktree propio:
git status -sb
git ls-files --error-unmatch -- src/lib/foo.ts
git ls-files -o --exclude-standard -z | tr '\0' '\n' | head
Si el path no está en el index, --error-unmatch sale 1 (pathspec … did not match, Did you forget to 'git add'? ). Verificado 2026-09-04: git ls-files --error-unmatch -- no-such-file-xyz → exit 1. Sin el flag, un path ausente no imprime nada y sale 0: un typo silencioso.
Untracked a borrar: clean -n primero, no xargs rm. Untracked a stagear: add con paths nombrados. Diff del contenido: diff, no el listado.
Desde un subdirectorio los paths salen relativos al cwd. --full-name los ancla a la raíz del repo. Verificado: cd src/lib && git ls-files -- brands.ts → brands.ts; con --full-name → src/lib/brands.ts. Un parser de sesión espera la raíz.

UI de GitHub vs clone local
GitHub Docs (Finding files on GitHub): Go to file busca el commit que ves en github.com. No ve untracked locales ni el index sucio. Los dirs default-excluidos se pisan con .gitattributes linguist-generated=false y glob **; no con ls-files.
Viewing and understanding files (HTTP 200 2026-09-04): Raw, Blame y Copilot miran el file en GitHub. git ls-files no abre contenido. Para historia por línea, blame. Para el blob, show.
--eol imprime i/<eolinfo> w/<eolinfo> attr/<eolattr> y un tab. Valores de eolinfo: -text, none, lf, crlf, mixed o vacío (no regular / no en index / no accesible). No es un linter; no lo vuelques entero.
Verificado 2026-09-04 en esta máquina (Git 2.50.1 / Apple Git-155): git ls-files -- src/lib/brands.ts lista el path (exit 0). git ls-files -s -- src/lib/brands.ts → 100644 <sha> 0. git ls-files -z -- src/lib/brands.ts termina en NUL. git ls-files -o -i --exclude-standard lista artefacto de build (.next/…) que Git ignora y el agente sigue viendo en disco.
Checklist
- Worktree propio.
git status -sb. Nofind. -
--error-unmatchsi el path tiene que existir en el index. - Untracked:
-o --exclude-standard -z. Ignored: añade-i. - Cero
-isolo, cero-tcomo API, cero--debug, cero--formatcon-o. - Parsear
-z. Paths desde la raíz (--full-namesi el cwd no es la raíz). - Borrar untracked → clean. Stagear → add.
- File finder de GitHub no sustituye el clone.
FAQ
¿ls-files es lo mismo que status? No. Status es porcelain para humanos/scripts (XY, rama, untracked). ls-files es plumbing: elige qué conjunto (cached / others / deleted / unmerged). El man de -t manda a status para scripting.
¿Por qué no veo .env? Default = index. Un .env ignored es -o -i --exclude-standard. Git no lo rastrea; el agente sí lo lee en disco (gitignore).
¿--directory? Solo con -o. Si un dir entero es “other”, imprime dir/ y no el contenido. --no-empty-directory oculta dirs vacíos. Un agente que busca un file no usa esto para “ahorrar tokens”: nombra el path.
El curso instalar un agente cubre el loop local. Hub: comparativas y decisiones. ls-files no es status: lista conjuntos del index, no el resumen XY.
Lecturas relacionadas
Sigue explorando Coding Agents y otras piezas para builders.

git describe para coding agents: nombre legible, no un Release

git merge-base para coding agents: ancestro común, no folklore

git check-ignore para coding agents: regla ganadora, no adivinar
