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.
- Advanced components:
spawn()— spawn a process with advanced ways to configure and control it.$$— spawn a process using a template string based onspawn().shell()— a helper to spawn a shell command using a template string based onspawn().- Various helpers for them.
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)
]);npm i --save dollar-shelldollar-shell/
├── src/ # Source code
│ ├── index.js # Main entry point, wires everything together
│ ├── index.d.ts # TypeScript declarations for the full public API
│ ├── bq-spawn.js # Template tag factory for spawn-based functions ($, $$)
│ ├── bq-shell.js # Template tag factory for shell-based functions ($sh, shell)
│ ├── utils.js # Shared utilities (raw, isWindows, winCmdEscape, etc.)
│ ├── spawn/ # Runtime-specific Subprocess implementations
│ └── shell/ # Platform-specific shell escaping and command building
├── tests/ # Automated tests (tape-six)
├── tests/manual/ # Manual verification scripts
├── ts-check/ # TypeScript usage examples (compiled but not executed)
└── wiki/ # GitHub wiki documentation (git submodule)
The documentation can be found in the wiki. See how it can be used in tests/.
For AI assistants: see llms.txt and llms-full.txt for LLM-optimized documentation.
Below is the documentation for the main components: spawn(), $$, $ and $sh.
Spawn a process with advanced ways to configure and control it.
The signature: spawn(command, options)
Arguments:
command— an array of strings. The first element is the command to run. The rest are its arguments.options— an optional object with options to configure the process:cwd— the optional current working directory as a string. Defaults toprocess.cwd().env— the optional environment variables as an object (key-value pairs). Defaults toprocess.env.stdin— the optional source stream. Defaults tonull.stdout— the optional destination stream. Defaults tonull.stderr— the optional destination stream. Defaults tonull.
stdin, stdout and stderr can be a string (one of 'inherit', 'ignore', 'pipe' or 'piped')
or null. The latter is equivalent to 'ignore'. 'piped' is an alias of 'pipe':
'inherit'— inherit streams from the parent process. For output steams (stdoutandstderr), it means that they will be piped to the same target, e.g., the console.'ignore'— the stream is ignored.'pipe'— the stream is available for reading or writing.
Returns a sub-process object with the following properties:
command— the command that was run as an array of strings.options— the options that were passed tospawn().exited— a promise that resolves to the exit code of the process. It is used to wait for the process to exit.finished— a boolean. It istruewhen the process has finished andfalseotherwise.killed— a boolean. It istruewhen the process has been killed andfalseotherwise.exitCode— the exit code of the process as a number. It isnullif the process hasn't exited yet.signalCode— the signal code of the process as a string. It isnullif the process hasn't exited yet.stdin— the source stream of the process ifoptions.stdinwas'pipe'. It isnullotherwise.stdout— the destination stream of the process ifoptions.stdoutwas'pipe'. It isnullotherwise.stderr— the destination stream of the process ifoptions.stderrwas'pipe'. It isnullotherwise.kill()— kills the process.killedwill betrueas soon as the process has been killed. It can be used to pipe the input and output. Seespawn()'sstdinandstdoutabove for more details.
Important: all streams are exposed as web streams.
import {spawn} from 'dollar-shell';
const sp = spawn(['sleep', '5']);
await new Promise(resolve => setTimeout(resolve, 1000));
sp.kill();
await sp.exited;
sp.finished === true;
sp.killed === true;The same as spawn(), but it returns a tag function that can be used as a template string.
The signatures:
const sp1 = $$`ls -l ${myFile}`; // runs a command the defaults
const sp2 = $$(options)`ls -l .`; // runs a command with custom spawn options
const $tag = $$(options); // returns a tag function
const sp3 = $tag`ls -l .`; // runs a command with custom spawn optionsThis function is effectively a helper for spawn(). It parses the template string
into an array of string arguments. Each inserted value is included
as a separate argument if it was surrounded by whitespaces.
The second signature is used to run a command with custom spawn options. See spawn() above for more details.
The first signature returns a sub-process object. See spawn() for more details. The second signature
returns a tag function that can be used as a template string.
This function is similar to $$ but it uses different default spawn options related to streams and
different (simpler) return values:
$— all streams are ignored. It returns a promise that resolves to an object with the following properties:code— the exit code of the process. Seespawn()'sexitCodeabove for more details.signal— the signal code of the process. Seespawn()'ssignalCodeabove for more details.killed— a boolean. It istruewhen the process has been killed andfalseotherwise. Seespawn()'skilledabove for more details.
$.from— setsstdouttopipeand returnsstdoutof the process. It can be used to process the output. Seespawn()'sstdoutabove for more details.$.to— setsstdintopipeand returnsstdinof the process. It can be used to pipe the input. Seespawn()'sstdinabove for more details.$.ioAKA$.through— setsstdinandstdouttopipeand returnsstdinandstdoutof the process as a{readable, writable}pair. It can be used to create a pipeline where an external process can be used as a transform step.
This function mirrors $ but runs the command with the shell. It takes an options object that extends
the spawn options with the following properties:
shellPath— the path to the shell.- On Unix-like systems it defaults to the value of
the
SHELLenvironment variable if specified. Otherwise it is'/bin/sh'or'/system/bin/sh'on Android. - On Windows it defaults to the value of the
ComSpecenvironment variable if specified. Otherwise it iscmd.exe.
- On Unix-like systems it defaults to the value of
the
shellArgs— an array of strings that are passed to the shell as arguments.- On Unix-like systems it defaults to
['-c']. - On Windows it defaults to
['/d', '/s', '/c']forcmd.exeor['-c']forpwsh.exeorpowershell.exe.
- On Unix-like systems it defaults to
The rest is identical to $: $sh, $sh.from, $sh.to and $sh.io/$sh.through.
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).
All files are included in the npm package.
BSD-3-Clause
- 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.