dollar-shell is a micro-library for running OS and shell commands from JavaScript/TypeScript using template tag functions. It works in Node, Deno, Bun with the same API. Web streams, TypeScript typings, zero dependencies.
The idea is to run OS/shell commands and/or use them in stream pipelines as sources, sinks, and transformation steps using web streams. It can be used together with stream-chain and stream-json to create efficient pipelines. It helps using shell commands in utilities written in JavaScript/TypeScript running with Node, Deno, or Bun.
Available components:
$— spawn a process using a template string.$.from— spawn a process and use itsstdoutas a source stream.$.to— spawn a process and use itsstdinas a sink stream.$.ioAKA$.through— spawn a process and use it as a transformation step in our pipeline.
$sh— run a shell command using a template string.$sh.from— run a shell command and use itsstdoutas a source stream.$sh.to— run a shell command and use itsstdinas a sink stream.$sh.ioAKA$sh.through— run a shell command and use it as a transformation step in our pipeline.
capture— run a command and collect itsstdout/stderras strings.- Advanced components:
Run a command:
import $ from 'dollar-shell';
const result = await $`echo hello`;
console.log(result.code, result.signal, result.killed);Run a shell command:
import {$sh} from 'dollar-shell';
const result = await $sh`ls .`;
console.log(result.code, result.signal, result.killed);Run a shell command (an alias or a function) and show its result:
import {$sh} from 'dollar-shell';
// custom alias that prints `stdout` and runs an interactive shell
const $p = $sh({shellArgs: ['-ic'], stdout: 'inherit'});
const result = await $p`nvm ls`;
// prints to the console the result of the commandRun a pipeline:
import $ from 'dollar-shell';
import chain from 'stream-chain';
import lines from 'stream-chain/utils/lines.js';
chain([
$.from`ls -l .`,
$.io`grep LICENSE`,
$.io`wc`,
new TextDecoderStream(),
lines(),
line => console.log(line)
]);Capture the output of a command:
import {capture} from 'dollar-shell';
const {code, stdout, stderr} = await capture`git rev-parse HEAD`;
// feed a string to stdin
const result = await capture({input: 'some text'})`cat`;
result.stdout === 'some text';npm i --save dollar-shellFull documentation is in the wiki — browse the index, or search it by name. See how it can be used in tests/.
For AI assistants: see llms.txt and llms-full.txt for LLM-optimized documentation.
Each runtime uses its own backend by default (node:child_process on Node, Bun.spawn on Bun,
Deno.Command on Deno). Set the DSH_FORCE_NODE environment variable (e.g. DSH_FORCE_NODE=1) to
make every runtime spawn through the Node backend — it swaps only the spawn mechanism, the
runtime launch stays native. Handy for sidestepping runtime-specific quirks. Details and scoping (the
whole process tree vs the current process only) are in the
Cross-runtime notes.
The default entry exposes web streams on
stdin/stdout/stderr. If you'd rather work with Node streams — to pipe straight into
fs/zlib/etc. with no adapter — import the identical API from dollar-shell/node instead:
import {spawn} from 'dollar-shell/node';
const sp = spawn(['cat', 'file.txt'], {stdout: 'pipe'});
sp.stdout.pipe(process.stdout); // sp.stdout is a Node ReadableOnly the stream types differ (stdin is a Node Writable, stdout/stderr are Node Readables,
asDuplex/.io/.through return a Node Duplex). See
Node streams for details.
This package ships with files to help AI coding agents and LLMs find, understand, and use it:
- AGENTS.md — Project conventions, architecture, commands, and coding guidelines for AI agents.
- CLAUDE.md — Claude Code specific instructions (redirects to AGENTS.md).
- CONTRIBUTING.md — Contribution guidelines for humans and AI agents.
- llms.txt — Concise project overview following the llms.txt standard.
- llms-full.txt — Self-contained complete API reference (no external links needed).
The machine-readable llms.txt and llms-full.txt ship inside the npm package, so AI tools can read them straight from node_modules. AGENTS.md and CLAUDE.md are authoring-side docs kept in the repository.
BSD-3-Clause
- 1.3.0 Added
capture(run a command, collect stdout/stderr as strings) and thesignaloption (anAbortSignalkills the subprocess). - 1.2.1 Bugfix:
DSH_FORCE_NODEanddollar-shell/nodenow switch only the spawn mechanism — spawned children stay native (bun run …/deno run …). - 1.2.0 Added
dollar-shell/nodewith Node streams and aDSH_FORCE_NODEflag to force the Node backend on any runtime. - 1.1.14 Fixed Bun stdin abort path, added js-check, Bun + Deno wired into CI.
- 1.1.13 Updated dev dependencies.
- 1.1.12 Consolidated TypeScript tests into
tests/, removedts-check/, added CJS test, improved test coverage and documentation. - 1.1.11 Updated dev dependencies.
- 1.1.10 Fixed a bug with options chaining for attached functions, fixed Bun spawn on invalid commands, Windows-compatible tests, updated dev dependencies.
- 1.1.9 Updated dev dependencies, cleaned up docs, added info for AI agents.
- 1.1.8 Updated dev dependencies.
- 1.1.7 Updated dev dependencies.
- 1.1.6 Updated dev dependencies.
- 1.1.5 Updated dev dependencies.
- 1.1.4 Updated dev dependencies.
- 1.1.3 Updated dev dependencies.
- 1.1.2 Updated dev dependencies.
- 1.1.1 Updated dev dependencies.
- 1.1.0 Added
asDuplexto the sub-process object. - 1.0.5 Updated dev dependencies.
- 1.0.4 Fixed
raw()for spawn commands. - 1.0.3 Added TSDoc comments, improved docs, fixed typos, added the missing copying of properties.
- 1.0.2 Technical release: fixed references in the package file.
- 1.0.1 Technical release: more tests, better documentation.
- 1.0.0 The initial release.
The full release notes are in the wiki: Release notes.