Commit Diff


commit - 49f04ef1f1ef7c6313dd7a678e18ac2b89027a74
commit + 3a286fd37210cfe48087f2df40914f2f76e689cd
blob - 7838a3aa48ff740fff06cdc1eef7bef1ce24be5d
blob + e0d1a4e5c11bb083e076ac63819a8d31b0b1a725
--- NOTES.md
+++ NOTES.md
@@ -852,6 +852,87 @@ antes de que `nixos-rebuild build/switch` lo pueda ver
 recordar este patrón para la próxima vez que se agregue un archivo nuevo,
 en vez de sorprenderse de nuevo con el mismo error.
 
+## Reproductor de música: Feishin → Psysonic, y completado de terminal (2026-07-13)
+
+### Feishin → Psysonic
+
+A pedido del usuario, reemplazado `feishin` (paquete de nixpkgs) por
+[Psysonic](https://github.com/Psychotoxical/psysonic) en
+`environment.systemPackages` (`modules/desktop.nix`) — cliente de música
+self-hosted (Navidrome) igual que Feishin, pero Tauri (React+Rust) en vez de
+Electron. Verificado contra el repo real (no de memoria): tiene su propio
+`flake.nix` (no está en nixpkgs), expone `packages.<system>.default`.
+Agregado como input de flake (`flake.nix`, mismo patrón que `zen-browser`:
+`inputs.nixpkgs.follows = "nixpkgs"`), y referenciado en `desktop.nix` como
+`inputs.psysonic.packages.${pkgs.stdenv.hostPlatform.system}.default`.
+Verificado con `nix eval` que `psysonic` aparece en `environment.
+systemPackages` en lugar de `feishin`, y que `config.assertions` sigue en
+`[]`. `~/.config/feishin` (config vieja) borrado a pedido del usuario.
+**Pendiente manual:** correr `sudo nixos-rebuild switch --flake /nixdots#ale`
+para aplicar (no lo corrí yo, ver política de acciones de sistema).
+
+### fzf-tab + zsh-autosuggestions
+
+A pedido del usuario ("sugerencias de completado" en la terminal): agregado
+menú interactivo con fuzzy-search en Tab (`zsh-fzf-tab`) y autosugerencias
+tipo fish desde el historial (`zsh-autosuggestions`), en `home/ale/home.nix`.
+
+- **Riesgo real evitado, no un bug ya cometido:** iba a usar la opción nativa
+  `programs.zsh.autosuggestion.enable`, pero leyendo el código fuente real de
+  home-manager (`modules/programs/zsh/default.nix`, rev
+  `7566825d4652a1b885bd4ce65bd9e8def432fec9`) confirmé que esa opción fija su
+  propio `lib.mkOrder 700` para el `source` de zsh-autosuggestions — que
+  carga ANTES del `compinit` de oh-my-zsh (`mkOrder 800`,
+  `modules/programs/zsh/plugins/oh-my-zsh.nix`) y ANTES de donde cargaría
+  `fzf-tab` vía el mecanismo genérico `programs.zsh.plugins` (`mkOrder 900`,
+  `modules/programs/zsh/plugins/default.nix`). Confirmé contra el README real
+  de `Aloxaf/fzf-tab` (no de memoria) que el orden exigido es exactamente el
+  opuesto: *"fzf-tab needs to be loaded after compinit, but before plugins
+  which will wrap widgets, such as zsh-autosuggestions"*. Con la opción
+  nativa, el orden real habría sido autosuggestions(700) → compinit(800) →
+  fzf-tab(900) — al revés dos veces.
+- **Solución:** `fzf-tab` vía `programs.zsh.plugins` (carga a 900, después
+  del compinit de oh-my-zsh a 800 — correcto solo). `zsh-autosuggestions`
+  sourceado a mano dentro de `initContent` envuelto en `lib.mkOrder 950`
+  (en vez de la opción nativa), para que quede después de fzf-tab. Verificado
+  con `nix eval` el `.zshrc` generado completo: el orden real es
+  `compinit(800) → fzf-tab(900) → autosuggestions(950) → resto(1000, p10k/
+  yubico/pfetch, sin envolver, como ya estaba)` — exactamente el exigido.
+- Agregado `pkgs.fzf` a `home.packages` (binario que `fzf-tab` invoca para
+  el menú; no era necesario antes porque nada lo requería).
+- Requirió agregar `lib` a la firma de `home.nix` (`{ config, pkgs, inputs,
+  ... }` no lo traía) para poder usar `lib.mkMerge`/`lib.mkOrder` en
+  `initContent`.
+- Paquetes `zsh-fzf-tab` y `zsh-autosuggestions` confirmados como atributos
+  reales de nixpkgs (`nix build` real, no solo `nix eval` del outPath) antes
+  de usarlos, y sus rutas de archivo `.plugin.zsh` confirmadas listando el
+  store path ya construido, no asumidas por convención de nombre.
+
+## zsh-syntax-highlighting (2026-07-13)
+
+A pedido del usuario ("colores en la terminal, comandos que existen de un
+color y los que no de otro" -- exactamente lo que hace `zsh-syntax-
+highlighting`, la herramienta estándar para esto). A diferencia de
+`autosuggestion.enable` (ver sección anterior), la opción nativa
+`programs.zsh.syntaxHighlighting.enable` **sí** sourcea en el orden correcto
+por defecto: confirmado en `modules/programs/zsh/default.nix` que usa
+`lib.mkOrder 1200`, que cae después de `fzf-tab` (900) sin necesitar ningún
+`mkOrder` manual -- satisface igual el requisito del README de fzf-tab
+("before plugins which will wrap widgets"). Verificado con `nix eval` el
+`.zshrc` generado: orden real `compinit(31) → fzf-tab(35) →
+autosuggestions(61) → zsh-syntax-highlighting(103)`. `config.assertions`
+sigue en `[]`.
+
+## Reproductor de música: Feishin → Psysonic, caché binario y completado de terminal -- resumen de cambios previos
+
+Ver secciones de arriba para el detalle completo: reemplazo de Feishin por
+Psysonic (input de flake propio + `psysonic.cachix.org` agregado en
+`hosts/ale/configuration.nix` tras el primer switch sin caché, que tardó
+~23 min compilando npm+Rust/Tauri desde cero), y fzf-tab + zsh-
+autosuggestions (con el bug de orden evitado, ver arriba). Todo aplicado con
+éxito en la máquina real (`nixos-rebuild switch` confirmado por el usuario:
+`Done.`, sin errores).
+
 ## Referencias usadas
 
 - https://docs.noctalia.dev/v5/getting-started/nixos/
@@ -893,3 +974,13 @@ en vez de sorprenderse de nuevo con el mismo error.
   `gtk.enable` no toca `gtk.css` salvo `extraCss`), `modules/programs/zsh/
   plugins/oh-my-zsh.nix`, y `share/oh-my-zsh/oh-my-zsh.sh` real instalado
   (confirma que no hay fallback a "robbyrussell" sin `ZSH_THEME` seteado).
+- https://github.com/Psychotoxical/psysonic (repo real, incluido su
+  `flake.nix`, verificado antes de agregarlo como input).
+- https://github.com/Aloxaf/fzf-tab (README real — orden exigido de carga
+  relativo a `compinit`/`zsh-autosuggestions`).
+- `modules/programs/zsh/default.nix` y `modules/programs/zsh/plugins/
+  default.nix` real de home-manager (rev
+  `7566825d4652a1b885bd4ce65bd9e8def432fec9`) — `mkOrder` reales de
+  `autosuggestion.enable` (700), compinit de oh-my-zsh (800) y
+  `programs.zsh.plugins` genérico (900), que motivaron sourcear
+  zsh-autosuggestions a mano en vez de con la opción nativa.
blob - 82c6e02e50b5f86c0e137856f18a721d4d89dc24
blob + a0136acc1f3d9d06a7e8da7b16b0ca609ac1ca2b
--- flake.lock
+++ flake.lock
@@ -117,6 +117,26 @@
         "type": "github"
       }
     },
+    "psysonic": {
+      "inputs": {
+        "nixpkgs": [
+          "nixpkgs"
+        ]
+      },
+      "locked": {
+        "lastModified": 1783979082,
+        "narHash": "sha256-dPcHzu5IZiaCsyMuAeqhaZ2rDHCcj196rrlwVlH4TJI=",
+        "owner": "Psychotoxical",
+        "repo": "psysonic",
+        "rev": "fd19419ac28b64ca6079e41f1c0769a4dd27632f",
+        "type": "github"
+      },
+      "original": {
+        "owner": "Psychotoxical",
+        "repo": "psysonic",
+        "type": "github"
+      }
+    },
     "root": {
       "inputs": {
         "gruvbox-wallpapers": "gruvbox-wallpapers",
@@ -124,6 +144,7 @@
         "nixpkgs": "nixpkgs",
         "noctalia": "noctalia",
         "noctalia-greeter": "noctalia-greeter",
+        "psysonic": "psysonic",
         "zen-browser": "zen-browser"
       }
     },
blob - 02f916f69a5a475c5dd7077845f0d1cdae0ce464
blob + 37fe91427e7ae3863d87e748116893d47a62e1cd
--- flake.nix
+++ flake.nix
@@ -24,6 +24,11 @@
       inputs.nixpkgs.follows = "nixpkgs";
     };
 
+    psysonic = {
+      url = "github:Psychotoxical/psysonic";
+      inputs.nixpkgs.follows = "nixpkgs";
+    };
+
     # Wallpapers estilo Gruvbox (paquete Nix real, no archivos sueltos —
     # ver home/ale/home.nix para cómo se instala vía home.file).
     gruvbox-wallpapers = {
@@ -40,6 +45,7 @@
     , noctalia-greeter
     , zen-browser
     , gruvbox-wallpapers
+    , psysonic
     , ...
     }@inputs:
     let
blob - 4ce50ae5bb0c2a35f31df18034a4d60518fa6c56
blob + 4ff95acd276b85f8fffb2fd747a2fcebe1acdd86
--- home/ale/home.nix
+++ home/ale/home.nix
@@ -1,4 +1,4 @@
-{ config, pkgs, inputs, ... }:
+{ config, pkgs, lib, inputs, ... }:
 
 {
   imports = [
@@ -121,7 +121,42 @@
       enable = true;
       plugins = [ "git" "sudo" ];
     };
-    initContent = ''
+    # fzf-tab -- menú interactivo con fuzzy-search en el Tab (en vez de la
+    # lista plana de zsh). Va acá (programs.zsh.plugins, no oh-my-zsh.plugins
+    # porque no es un plugin bundled de oh-my-zsh) para que se sourcee vía el
+    # mecanismo genérico de home-manager, que carga a mkOrder 900 -- DESPUÉS
+    # del compinit que corre oh-my-zsh (mkOrder 800, ver "source $ZSH/oh-my-
+    # zsh.sh" en modules/programs/zsh/plugins/oh-my-zsh.nix). Confirmado
+    # contra el README real de fzf-tab: exige cargarse "after compinit, but
+    # before plugins which will wrap widgets" (zsh-autosuggestions, fast-
+    # syntax-highlighting) -- ver el bloque de autosuggestions más abajo.
+    plugins = [
+      {
+        name = "fzf-tab";
+        src = pkgs.zsh-fzf-tab;
+        file = "share/fzf-tab/fzf-tab.plugin.zsh";
+      }
+    ];
+    # zsh-syntax-highlighting -- colorea el comando mientras lo escribís:
+    # verde si el comando/alias/función existe, rojo si no. Opción nativa de
+    # home-manager (a diferencia de autosuggestion.enable, esta SÍ sourcea en
+    # mkOrder 1200 por defecto -- confirmado en modules/programs/zsh/
+    # default.nix -- que ya cae después de fzf-tab (900), como exige su
+    # README, sin necesitar ningún mkOrder manual).
+    syntaxHighlighting.enable = true;
+    initContent = lib.mkMerge [
+      # zsh-autosuggestions -- sourceado a mano (NO con la opción nativa
+      # programs.zsh.autosuggestion.enable) porque esa opción fija su propio
+      # mkOrder en 700, es decir ANTES del compinit de oh-my-zsh (800) y
+      # ANTES de fzf-tab (900) -- el orden opuesto al que exige el README de
+      # fzf-tab (compinit -> fzf-tab -> autosuggestions). mkOrder 950 acá
+      # deja la secuencia real: compinit (800) -> fzf-tab (900) ->
+      # autosuggestions (950) -> resto del initContent (1000, sin envolver
+      # -- ver comentario de p10k debajo).
+      (lib.mkOrder 950 ''
+        source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.plugin.zsh
+      '')
+      ''
       # Powerlevel10k -- bloques de color sólidos + wizard interactivo de
       # configuración (fuentes/símbolos/una o dos líneas/conectado o no) la
       # primera vez que abras una terminal, porque a propósito NO se pre-crea
@@ -158,7 +193,8 @@
       # sale una advertencia de "console output during initialization" (el
       # wizard eligió modo Verbose), es solo informativa, no rompe nada.
       pfetch
-    '';
+      ''
+    ];
   };
 
   home.file.".p10k.zsh".source = ./p10k.zsh;
@@ -197,5 +233,6 @@
     gitstatus # da el binario gitstatusd que necesita Powerlevel10k (ver programs.zsh)
     meslo-lgs-nf # Nerd Font que recomienda p10k para sus glifos/iconos
     pfetch # info del sistema al abrir terminal (ver programs.zsh.initContent)
+    fzf # binario que fzf-tab invoca para el menú interactivo del Tab (ver programs.zsh.plugins)
   ];
 }
blob - 9f4cddfad2a149f03692c899e905a410b11a1e41
blob + ac79586c8a16139bbdcb738100c88e45b7f88e21
--- hosts/ale/configuration.nix
+++ hosts/ale/configuration.nix
@@ -43,9 +43,20 @@
   # Binary cache oficial de Noctalia -- sin esto, cada rebuild compila
   # Noctalia desde fuente en vez de bajar el binario prearmado
   # (docs.noctalia.dev/v5/getting-started/nixos).
-  nix.settings.extra-substituters = [ "https://noctalia.cachix.org" ];
+  #
+  # Binary cache oficial de Psysonic (nixos-install.md del repo real, no
+  # nixpkgs) -- sin esto, cada rebuild compila el frontend (npm) y el
+  # binario Tauri (Rust) desde cero en vez de bajarlos ya armados. La build
+  # que disparó este agregado (primer switch tras el cambio Feishin →
+  # Psysonic) ya venía compilando en local antes de que esto se agregara --
+  # no la acelera retroactivamente, pero sí los rebuilds futuros.
+  nix.settings.extra-substituters = [
+    "https://noctalia.cachix.org"
+    "https://psysonic.cachix.org"
+  ];
   nix.settings.extra-trusted-public-keys = [
     "noctalia.cachix.org-1:pCOR47nnMEo5thcxNDtzWpOxNFQsBRglJzxWPp3dkU4="
+    "psysonic.cachix.org-1:M9cQyQ7tgvUWOQ5Pyt8ozlMoPLtOZir6MfRuTH9/VYA="
   ];
 
   environment.systemPackages = with pkgs; [
blob - 984982f2a26d09d74c7411903766af1301dbc476
blob + 4aa6c8a617e15eebead780bc38a4d92a4d54396b
--- modules/desktop.nix
+++ modules/desktop.nix
@@ -126,9 +126,10 @@
                                     # (confirmado con un cat real) pero nada los usaba: ni
                                     # Kleopatra ni pinentry-qt (el diálogo de PIN de la
                                     # YubiKey) los mostraban.
-    feishin  # cliente de música self-hosted (Navidrome/Jellyfin/Subsonic) --
-             # ya empaquetado en nixpkgs. Hace falta apuntarlo a un servidor
-             # la primera vez que se abre.
+    inputs.psysonic.packages.${pkgs.stdenv.hostPlatform.system}.default
+      # cliente de música self-hosted (Navidrome), reemplaza a feishin --
+      # empaquetado vía su propio flake.nix (no está en nixpkgs). Hace
+      # falta apuntarlo a un servidor la primera vez que se abre.
   ];
 
   # Necesario para que QT_QPA_PLATFORMTHEME=kde (de abajo) resuelva al plugin