Plugins
Extend the Nub CLI with your own subcommands — an unknown verb resolves to an executable named after it and runs, the same convention git and cargo use for their plugins.
Run nub <verb> with a verb Nub doesn't recognize and it resolves an executable named nub-<verb>, then runs it with the rest of the arguments forwarded untouched. This is the same convention behind git-foo and cargo-foo.
nub changeset publish # runs nub-changeset publish
nub release --tag beta # runs nub-release --tag betaA plugin is a package that installs a nub-<verb> bin — there is no plugin manifest and no registration step. Install it like any other dependency and the verb works.
nub add -D nub-changeset # ships a nub-changeset bin
nub changeset # now resolves and runs itResolution
The prefixed name is resolved in two places, in order:
node_modules/.bin— the project-local bin, walking up from the current directory (the same chainnub runandnubxuse).PATH— a globally-installed plugin.
Only the prefixed nub-<verb> name is ever probed — never the bare verb.
Built-in precedence
A plugin can never shadow a built-in verb. Native commands and package-manager verbs are matched before any plugin lookup, so nub run, nub install, nub add, and the rest always dispatch to Nub itself, even if a nub-run bin exists in node_modules/.bin. The fallthrough fires only for a verb Nub has no built-in for.
Script names take the same priority. A verb that names a script in the local package.json, or one of the conventional names dev, build, test, start, and lint, resolves to the nub run <verb> hint before the plugin lookup — so a nub-build or nub-test plugin is never reached through its bare verb. Name a plugin for something that isn't a script (nub-changeset, nub-release), or invoke a script-named one through nub run or by its bin directly.
Writing a plugin
A plugin is a runnable executable named nub-<verb> — a compiled JavaScript bin or a native binary, the same as any other node_modules/.bin entry or a git/cargo subcommand. There's no plugin-specific build target: author it in TypeScript and publish the compiled output, as any other bin. Installed bins are not transpiled, so the entry that runs must be JavaScript or native.
A JavaScript plugin runs under Nub's runtime augmentation, as nub run runs a script — the version-gated globals are present. A native executable runs directly. The plugin's exit code is what Nub returns.
#!/usr/bin/env node
const target = process.argv[2] ?? "staging";
console.log(`releasing ${target}`);To run a plugin with augmentation disabled, pass --node before the verb — nub --node changeset, the same position a file run uses. Anything after the verb is forwarded to the plugin untouched, so a trailing nub changeset --node reaches the plugin as an argument and does not disable augmentation. See the runtime overview for the contract.
Related
- Bin runner —
nubx, for running a tool by name without installing it as a subcommand. - Script runner —
nub run, which shares the bin-resolution chain. - Runtime — TypeScript-first execution and the augmentation a JS/TS plugin inherits.