A small Zsh plugin that tab-completes the scripts from your package.json for npm, yarn, pnpm, and bun.
Type npm run and hit tab, and you get the list of scripts straight from the nearest package.json, each one shown next to the command it actually runs. No more opening the file to remember whether it's build, build:prod, or dev:ios.
It only reads your local package.json. It never runs a script, never phones home, and the only thing it shells out to is node, purely to parse the JSON.
- Completion for
npm run <script>, including therun-scriptalias - Completion for
yarn <script>,pnpm <script>, andbun <script>, plus the explicitrunform for each - The command behind each script shown inline, so you can see what you're about to run
- Per-file caching keyed on the file's modification time, so repeated tabs in the same project stay fast
- Optional upward search, so it finds the
package.jsonat the repo root even when you're a few directories deep
- Zsh with completion enabled (
compinit, which Oh My Zsh sets up for you) - Node, used only to parse
package.json
Clone the repo into your Oh My Zsh custom plugins directory:
git clone https://github.com/vortexture/package-scripts-autocomplete \
"${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/package-scripts-autocomplete"Then add package-scripts-autocomplete to the plugins list in your ~/.zshrc:
plugins=(git package-scripts-autocomplete)Open a new terminal, or run source ~/.zshrc, and you're done.
There's one option, set it before the plugin loads (so earlier in ~/.zshrc):
# Walk up parent directories to find the nearest package.json. On by default.
# Set to 0 if you only ever want the package.json in the current directory.
PJS_SEARCH_UPWARD=1By default the plugin also turns on an interactive, highlighted menu for npm, yarn, pnpm, and bun only, so you can arrow through the matches. It deliberately leaves completion for every other command alone.
The built-in menu is fine, but if you want a proper fuzzy finder, where you type a few letters to narrow the list down, pair this with fzf-tab. It hijacks Zsh's completion menu and renders it through fzf. The nice part is that this plugin already describes each script with the command it runs, and fzf-tab shows those descriptions right in the list, so you get build -- vite build style rows inside fzf without any extra setup.
First install fzf itself if you haven't:
brew install fzf # macOS
# or follow https://github.com/junegunn/fzf for other systemsThen add fzf-tab as an Oh My Zsh plugin, the same way you added this one:
git clone https://github.com/Aloxaf/fzf-tab \
"${ZSH_CUSTOM:-$HOME/.oh-my-zsh/custom}/plugins/fzf-tab"Order matters in your plugins list. fzf-tab needs to load after compinit and after package-scripts-autocomplete, so put it last:
plugins=(git package-scripts-autocomplete fzf-tab)That's it. Now pnpm <tab> opens fzf with the script list, you type to filter it down, and enter drops the one you want onto your command line. The command each script runs is shown next to it in the list.
If you want fzf to show more rows or sit at the top of the screen, that's controlled by your global FZF_DEFAULT_OPTS, nothing specific to this plugin.
When you tab, the plugin finds the nearest package.json, asks Node to parse it and print each script as a name<tab>command line, and caches that result against the file's modification time. The next tab in the same unchanged project skips the parse entirely. The completion functions then hand those names and commands to Zsh's _describe, which is what gives you the script name with its command alongside.
MIT