npm Scripts
The workspace's package.json scripts as runnable tasks.
npm reads the scripts in the workspace's package.json and turns each one into a task: a name,
the package manager as its source, and the script's own command line as its detail.
import { Workbench, FileSystem } from "codelet/workbench";
import { npm } from "codelet/extensions/npm";
import { terminal } from "codelet/extensions/terminal";
import { justBash } from "codelet/extensions/terminal/just-bash";
new Workbench({
parent: document.getElementById("app")!,
fs: new FileSystem({
"/package.json": JSON.stringify({ scripts: { build: "tsc", test: "vitest run" } }),
}),
extensions: [npm(), terminal(), justBash()],
});Warning
A page cannot spawn a process, so running a script means typing its command line into a terminal
another extension contributed. npm needs
codelet/extensions/terminal plus a shell mounted alongside it —
just-bash or webcontainer. Mount npm
with no shell in the workbench and every task refuses to run: the reader sees an error message,
and executeTask rejects.
just-bash opens a shell, but it has no package manager installed in it — a script run there
fails with "command not found" rather than actually building anything. webcontainer is real
node with npm, pnpm, yarn and bun all on its PATH. If your workbench mounts both, tell
npm which one to use (see Options) — the shells are not interchangeable for this.
#Options
| Option | Type | Default | Description |
|---|---|---|---|
shell | string | — | The id of a contributes.terminal.profiles entry to run scripts in, "webcontainer.shell" among them. |
npm({ shell: "webcontainer.shell" });Without shell, the last contributed shell profile is used — the shell a host mounted last is
taken as the more deliberate choice. A named shell that isn't offered falls back the same way, so
naming webcontainer.shell is safe even before cross-origin isolation makes it available: the
task runs on whatever shell is there once it is.
#Choosing a package manager
The manager for a task's command line is worked out from the workspace, in order:
packageManager field in package.json, if the tree declares one ("pnpm@11.20.0" reads
as pnpm).pnpm-lock.yaml, yarn.lock,
bun.lock or bun.lockb, then package-lock.json, first match wins.npm, if none of the above is there.Each task's command line is <manager> install && <manager> run <script> — install runs first,
every time. A shell in a page is either a container that just booted or a tree that arrived over
a tarball, so node_modules is rarely already there, and every manager's install is close to a
no-op once it is.
#What it adds
One vscode.Task per script in package.json, plus an npm: Run Script command in the
command palette that lists them in a quick pick and runs the one you choose. Nothing is held
between fetches: package.json is read fresh each time, so a script you just added or renamed
shows up the next time you open the palette or the Tasks pane — no reload needed. A workspace
with no package.json, or one that fails to parse, simply has no npm tasks.
A script named exactly build, test or clean is tagged with the matching task group; any
other name is left ungrouped.
#Running one
Mount codelet/extensions/tasks for a pane listing every script with a
click to run it, or reach for the npm: Run Script command in the palette. Both go through the
same vscode.tasks API, so a second extension that also provides "npm"-typed tasks shows up
alongside these in either place.