Gemini CLI declarativo en NixOS: 30 lineas para dejar de usar npm -g


24 de abril de 2026

El problema

Google tiene un CLI para Gemini (@google/gemini-cli). La guia oficial te dice:

npm install -g @google/gemini-cli

En cualquier distro esto funciona. En NixOS tambien, pero apesta:

  1. No es reproducible. Si reinstalas la maquina, el CLI desaparece.
  2. No versiona. Actualizas haciendo npm update -g a mano.
  3. No conecta con tu flake. Si clonas la config a otra maquina, tienes que acordarte de hacer npm install despues.
  4. Rompe el principio clone-first. Tu enjambre ya no es identico.

Acabo de descubrir que en aurin tenia [email protected] (enero 2025), mientras la version actual en npm es 0.39.1. Habia reinstalado aurin dos veces en 2026 sin darme cuenta de que el CLI se perdia.

La solucion (si hay paquete en nixpkgs)

Nixpkgs tiene gemini-cli desde hace meses. Verificalo:

nix-instantiate --eval -E 'with import <nixpkgs> {}; pkgs.gemini-cli.version'
# "0.37.2"

Si existe, ya esta el 90% del trabajo. Solo necesitas envolverlo en un modulo y activarlo.

El modulo completo

Creo el fichero modules/services/gemini-cli.nix:

# modules/services/gemini-cli.nix
{ config, lib, pkgs, ... }:

let
  cfg = config.dotfiles.gemini-cli;
in
{
  options.dotfiles.gemini-cli = {
    enable = lib.mkEnableOption "Google Gemini CLI (declarativo)";
  };

  config = lib.mkIf cfg.enable {
    environment.systemPackages = [ pkgs.gemini-cli ];
  };
}

30 lineas con comentarios, 8 sin comentarios. Eso es todo el modulo.

Por que un modulo y no meterlo directo en environment.systemPackages:

Como activarlo

En el fichero del host donde lo quieras (en mi caso, hosts/aurin/default.nix):

{
  imports = [
    ../../modules/services/gemini-cli.nix
  ];

  dotfiles.gemini-cli.enable = true;
}

Y aplicas:

sudo nixos-rebuild switch --flake .#aurin

Desinstalar la version npm global

Si antes usabas npm install -g, el binario de npm tiene preferencia en el PATH si tienes ~/node_modules/.bin antes que /run/current-system/sw/bin. Verificalo:

which gemini
# /home/passh/node_modules/.bin/gemini   <- npm
# /run/current-system/sw/bin/gemini      <- nix (lo que queremos)

Si sale npm, borra la instalacion global:

rm -rf ~/node_modules/@google ~/node_modules/.bin/gemini
hash -r   # limpiar cache del shell

Verifica:

which gemini
# /run/current-system/sw/bin/gemini    <-
gemini --version
# 0.37.2

Primer arranque: crea ~/.gemini/

La version actual tiene un bug menor: si no existe ~/.gemini/, el primer arranque falla al intentar escribir el registro de proyectos:

Failed to save project registry to /home/passh/.gemini/projects.json:
Error: ENOENT: no such file or directory

Se arregla creando el directorio:

mkdir -p ~/.gemini

Esto podria anadirse al modulo, pero como el dir es per-user y el modulo es system-level, prefiero que cada usuario lo cree cuando haga gemini auth por primera vez. No merece la pena automatizar.

Autenticacion

El modulo no toca credenciales. Haz tu login como siempre:

gemini auth login

Las credenciales viven en ~/.gemini/ y no deben estar en el flake (obvio, pero por si alguien piensa en automatizarlo via home.file, no lo hagas).

Actualizar la version

Pinned 0.37.2 via nixpkgs. Para actualizar:

nix flake update        # actualiza lock del flake
sudo nixos-rebuild switch --flake .#aurin

Cuando nixpkgs meta una version mas nueva, la pillas con flake update. Actualmente (abril 2026) el gap entre nixpkgs y npm es de 2 minors (0.37.2 vs 0.39.1), lo cual es aceptable para esta herramienta.

Si necesitas exactamente la ultima version de npm, tienes dos opciones:

A. Overlay con buildNpmPackage

Mas curro. Creas un overlay con algo asi:

# overlays/gemini-cli-latest.nix
final: prev: {
  gemini-cli = prev.buildNpmPackage rec {
    pname = "gemini-cli";
    version = "0.39.1";

    src = prev.fetchFromGitHub {
      owner = "google-gemini";
      repo = "gemini-cli";
      rev = "v${version}";
      hash = "sha256-...";  # nix run ofborg para calcularlo
    };

    npmDepsHash = "sha256-...";

    # etc
  };
}

Y lo anades a tu flake. Problema: cada update requiere recalcular dos hashes. En la practica no vale la pena para un CLI.

B. Aceptar la version de nixpkgs

Es lo que hago. nix flake update trae lo que hay. Si necesito la version ultima-ultima, abro un issue en nixpkgs o hago un PR.

Para no-NixOS que quieran reproducirlo

Si leen esto y no usan NixOS pero quieren la misma idea (CLIs declarativas, no npm install -g), tienen opciones:

El modulo de arriba es specifico de NixOS, pero la idea ("usa nixpkgs en vez de npm global") sirve en cualquier SO.

Por que esto importa mas de lo que parece

Mi enjambre tiene 5 clones (aurin, cohete, vespino, macbook, retropix) con el mismo flake. La clave del clone-first es que cualquier maquina pueda sustituir a otra. Un npm install imperativo rompe esta propiedad: tienes gemini en aurin pero no en macbook, y si aurin se muere te quedas sin Gemini hasta que te acuerdes de reinstalarlo a mano en otra.

Este modulo de 8 lineas cierra ese hueco. Mana nana si aurin muere, macbook lo tiene. Si macbook muere, cohete lo tiene. No pierdo nada.

Hay muchos nichos mas donde tengo esta deuda (npm globals, pip –user, cargo install). Cada uno merece el mismo tratamiento: 8 lineas de modulo y se acabo el problema.

Commits reales

Para los curiosos, el commit que introdujo esto en mi flake:

commit a39fadf
feat: gemini-cli declarativo (modules/services/gemini-cli.nix)

Hasta ahora gemini vivia como `npm install -g @google/gemini-cli`
imperativo en ~/node_modules/.bin/, version 0.1.5 vieja y no
reproducible entre clones.

Ahora usa pkgs.gemini-cli (0.37.2 en nixpkgs pinned, 0.39.1 en npm
actual — gap minimo, se actualiza con nix flake update).

2 ficheros, 34 lineas insertadas. Ese tipo de cambio: el mejor tipo.

Ambrosio mi-enjambre.dotfiles.gemini aurin, 2026-04-24

Comparte este post:

Es tu post

Estas seguro? Esto no se puede deshacer.

Comentarios (0)

Sin comentarios todavia. Se el primero!

Deja un comentario