cargo: command not found, aunque rustup está instalado
Síntoma: rustup funciona, rustup show lista una toolchain instalada y activa, pero cargo, rustc y rustfmt fallan todos con “command not found”.
Causa
En macOS con Homebrew, rustup es una fórmula keg-only. Homebrew solo enlaza el propio binario rustup dentro de /opt/homebrew/bin. No enlaza los shims proxy que rustup normalmente incluye junto a él, cargo, rustc, rustfmt, cargo-clippy, etcétera. Esos viven en el keg:
/opt/homebrew/opt/rustup/bin/
Homebrew nunca añade ese directorio al PATH. Así que rustup se resuelve, pero ninguno de los comandos que normalmente delegaría a la toolchain activa lo hace.
Puedes confirmarlo con:
$ which rustup
/opt/homebrew/bin/rustup
$ which cargo
cargo not found
$ brew info rustup
==> Caveats
To use rustup, ensure you have "$(brew --prefix rustup)/bin" in your $PATH
La toolchain en sí está bien, ~/.rustup/toolchains/<target>/bin/ tiene binarios cargo y rustc reales. Los shims del keg son lo que normalmente se sitúa delante de ellos y elige la toolchain activa; sin ellos en el PATH, nada de esa maquinaria es accesible.
Solución
Añade /opt/homebrew/opt/rustup/bin al PATH. opt/rustup es un symlink estable que Homebrew mantiene apuntando a la versión actual del Cellar, así que sobrevive a las actualizaciones.
Para un perfil de shell simple:
export PATH="/opt/homebrew/opt/rustup/bin:$PATH"
Para una configuración de fish gestionada con chezmoi, esto encaja en el mismo patrón que cualquier otro fragmento de PATH por toolchain (un go.fish.tmpl, dotnet.fish.tmpl, etc.):
if test -d /opt/homebrew/opt/rustup/bin
path_insert /opt/homebrew/opt/rustup/bin
end
Una peculiaridad al probar la solución
Si ya tienes una shell interactiva abierta, aplicar la solución con source en una shell anidada puede parecer que no hace nada, aunque funciona perfectamente en una terminal nueva. En esta configuración, la config de fish cachea si la inserción del PATH ya se ejecutó, mediante una variable de entorno PATHS que se establece al final de config.fish. Esa variable se exporta, así que se filtra a cada proceso hijo, incluida una invocación anidada fish -c usada para probar la solución. La lógica de inserción ve PATHS ya establecida y se salta a sí misma.
Esto no es un fallo de la solución. Es un efecto secundario de probar un cambio en el arranque de la shell desde dentro de una shell que ya ejecutó el arranque una vez. Verificarlo requiere limpiar esa variable para la invocación de prueba:
env -u PATHS fish -c 'cargo --version'
Una ventana de terminal genuinamente nueva no tiene este problema, ya que nunca heredó el PATHS=true obsoleto.
Conclusión
Si una herramienta CLI instalada con Homebrew “funciona” pero los comandos que se supone que debe exponer no lo hacen, comprueba primero si la fórmula es keg-only. brew info <formula> imprime la advertencia exacta sobre el PATH, sin adivinar.