6.2 KiB
using inshellah completions in nushell
inshellah indexes completions from three sources (in priority order):
- native generators — programs that can emit nushell completions directly
- manpages — groff/troff/mdoc manpage parsing
--helpoutput — parsing help text as a fallback
indexed data is stored as .json and .nu files in a directory that the
complete command reads from at tab-completion time.
quick start
index completions from a system prefix:
# index from a prefix containing bin/ and share/man/
inshellah index /usr
# index from multiple prefixes
inshellah index /usr /usr/local
# store in a custom directory
inshellah index /usr --dir ~/my-completions
parse a single manpage:
inshellah manpage /usr/share/man/man1/git.1.gz
batch-process all manpages under a directory (man1 and man8):
inshellah manpage-dir /usr/share/man
commands
inshellah index PREFIX... [--dir PATH] [--ignore FILE] [--help-only FILE]
index completions into a directory of json/nu files.
PREFIX is a directory containing bin/ and share/man/.
default dir: $XDG_CACHE_HOME/inshellah
--ignore FILE skip listed commands entirely
--help-only FILE skip manpages for listed commands, use --help instead
inshellah complete CMD [ARGS...] [--dir PATH[:PATH...]]
nushell custom completer. outputs json completion candidates.
falls back to --help resolution if command is not indexed.
--dir takes colon-separated paths. the first path is the writable
user cache; additional paths are read-only system directories.
manpages are found via sibling share/man of system dir paths.
inshellah query CMD [--dir PATH[:PATH...]]
print stored completion data for CMD.
inshellah dump [--dir PATH[:PATH...]]
list indexed commands.
inshellah manpage FILE
parse a manpage and emit nushell extern block.
inshellah manpage-dir DIR
batch-process manpages under DIR (man1 and man8 sections).
the index pipeline
the index command runs a three-phase pipeline over all executables
in each PREFIX/bin:
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
.TPstyle (coreutils, help2man) .IPstyle (curl, hand-written).PP+.RS/.REstyle (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.
subcommands are recursively resolved — if --help output lists
subcommands, inshellah runs CMD SUBCMD --help for each.
when a --help invocation produces rendered manpage output (some
commands like git stash delegate --help to man), inshellah
detects this and locates the raw manpage source to parse with the
groff parser instead. this yields richer results (subcommands,
structured flag sections) than parsing the rendered text.
output
each command gets its own file in the index directory. 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
the completer
the complete command is designed to be wired into nushell as an
external completer. it reads from the directories specified via --dir
(colon-separated), performs fuzzy matching, and outputs json completion
candidates. the first path is the writable user cache; additional paths
are read-only system directories.
if a command is not indexed, complete falls back to on-the-fly
--help resolution — it runs the command's help, caches the result
in the user directory, and returns completions immediately.
setting up the completer
# ~/.config/nushell/config.nu
$env.config.completions.external = {
enable: true
completer: {|spans|
inshellah complete ...$spans
| from json
}
}
with the nixos module, use the provided snippet option value (see
nixos.md) which points at the system index automatically.
nixos module
enable automatic completion indexing at system build time:
{
imports = [ ./path/to/inshellah/nix/module.nix ];
programs.inshellah.enable = true;
}
this runs inshellah index during the system profile build. see
nixos.md for full details.
what gets generated
the manpage and manpage-dir commands emit nushell extern blocks
with flags, parameter types, and descriptions:
export extern "rg" [
--regexp(-e): string # a pattern to search for
--file(-f): path # search for patterns from the given file
--count(-c) # only show the count of matching lines
--color: string # controls when to use color
--max-depth: int # limit the depth of directory traversal
]
subcommand manpages (e.g. git-commit.1) are detected via synopsis
parsing and generate the correct nushell name (git commit not
git-commit).
nushell built-in commands (ls, cd, mv, etc.) are excluded since nushell provides its own completions for these.