# nixos integration inshellah provides a nixos module that automatically indexes nushell completions for all installed packages at system build time. ## enabling ```nix # in your flake.nix outputs: { nixosConfigurations.myhost = nixpkgs.lib.nixosSystem { modules = [ inshellah.nixosModules.default { programs.inshellah.enable = true; } ]; }; } ``` or if importing the module directly: ```nix # configuration.nix { pkgs, ... }: { imports = [ ./path/to/inshellah/nix/module.nix ]; programs.inshellah = { enable = true; package = pkgs.inshellah; # or your local build }; } ``` ## what happens at build time the module hooks into `environment.extraSetup`, which runs during the system profile build (the `buildEnv` that creates `/run/current-system/sw`). at that point, all system packages are merged, so `$out/bin` contains every executable and `$out/share/man` contains every manpage. inshellah runs a single command: ``` inshellah index "$out" --dir $out/share/inshellah ``` this executes a three-phase pipeline: ### phase 1: native completion detection (parallel) for each executable, inshellah scans the elf binary for the string `completion`. if found, it probes common patterns like `CMD completions nushell` to see if the program can generate its own nushell completions. native output is used verbatim — these are always higher quality than parsed completions. programs like `niri`, and any clap/cobra tool with nushell support, are handled this way. ### phase 2: manpage parsing (sequential) for commands not covered by phase 1, inshellah parses manpages from man1 (user commands) and man8 (sysadmin commands). it handles: - gnu `.TP` style (coreutils, help2man) - `.IP` style (curl, hand-written) - `.PP`+`.RS`/`.RE` style (git, docbook) - nix3 bullet+hyperlink style (`nix run`, `nix build`, etc.) - mdoc (bsd) format - deroff fallback for unusual formats synopsis sections are parsed to detect subcommands: `git-commit.1` generates `export extern "git commit"`, not `export extern "git-commit"`. ### phase 3: --help fallback (parallel) remaining executables without manpages get `--help` (or `-h`) called with a 200ms timeout. elf binaries are pre-scanned for the `-h` string to skip those that don't support help flags. shell scripts are run directly (they're fast). execution is parallelized to available cores. ### output each command gets its own file in `/share/inshellah` under the system profile. native generators produce `.nu` files; parsed results produce `.json` files. the `complete` command reads both formats. nushell built-in commands (ls, cd, cp, mv, etc.) are excluded since nushell provides its own completions. ### performance on a typical nixos system (~950 executables, ~1600 manpages): - total time: ~4-10 seconds - native gzip decompression (camlzip, no process spawning) - parallel --help with core-scaled forking - elf string scanning to skip ~15% of binaries ## module options ```nix programs.inshellah = { enable = true; # the inshellah package (set automatically by the flake module) package = pkgs.inshellah; # where to place indexed completion files under the system profile # default: "/share/inshellah" completionsPath = "/share/inshellah"; # commands to skip entirely during indexing ignoreCommands = [ "problematic-tool" ]; # commands to skip manpage parsing for (uses --help instead) helpOnlyCommands = [ "nix" ]; }; ``` ## using the completer the flake module sets a read-only `snippet` option containing the nushell config needed to wire up the completer. you can access it via `config.programs.inshellah.snippet` and paste it into your nushell config, or source it from a file generated by your nixos config. the snippet sets up the external completer pointing at the system index at `/run/current-system/sw/share/inshellah`: ```nu let inshellah_complete = {|spans| inshellah complete ...$spans --system-dir /run/current-system/sw/share/inshellah | from json } $env.config.completions.external = { enable: true max_results: 100 completer: $inshellah_complete } ``` ## home manager and other user-level package managers the nixos module only indexes packages installed at the system level (those that end up in `/run/current-system/sw`). if you use home-manager, nix-env, or another user-level package manager, those binaries and manpages live elsewhere — typically under `/etc/profiles/per-user/` or `~/.nix-profile`. to get completions for user-installed packages, run `inshellah index` against those prefixes separately: ```sh # home-manager / per-user profile inshellah index /etc/profiles/per-user/$USER # classic nix-env profile inshellah index ~/.nix-profile ``` this indexes into the default user cache (`$XDG_CACHE_HOME/inshellah`), which the completer searches automatically. you can re-run this after installing new packages, or add it to a home-manager activation script. if you want to automate this in home-manager: ```nix # home.nix home.activation.inshellah-index = lib.hm.dag.entryAfter [ "writeBoundary" ] '' ${pkgs.inshellah}/bin/inshellah index /etc/profiles/per-user/$USER 2>/dev/null || true ''; ``` the completer will then search both the system index (`--system-dir`) and the user cache, so completions from both sources are available. ## troubleshooting **completions not appearing**: ensure the completer is configured in your nushell config (see above). check that the system index exists: `ls /run/current-system/sw/share/inshellah/`. **missing completions for a specific command**: check if it's a nushell built-in (`help commands | where name == "thecommand"`). built-ins are excluded because nushell serves its own completions for them. **stale completions after update**: completions regenerate on every `nixos-rebuild`. if a command changed its flags, rebuild to pick up the changes. **build-time errors**: indexing failures are non-fatal (`|| true`). check `journalctl` for the build log if completions are missing.