Skip to content

uhop/dollar-shell

Repository files navigation

dollar-shell NPM version

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 its stdout as a source stream.
    • $.to — spawn a process and use its stdin as a sink stream.
    • $.io AKA $.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 its stdout as a source stream.
    • $sh.to — run a shell command and use its stdin as a sink stream.
    • $sh.io AKA $sh.through — run a shell command and use it as a transformation step in our pipeline.
  • capture — run a command and collect its stdout/stderr as strings.
  • Advanced components:
    • spawn() — spawn a process with advanced ways to configure and control it.
    • $$ — spawn a process using a template string based on spawn().
    • shell() — a helper to spawn a shell command using a template string based on spawn().
    • Various helpers for them.

Introduction

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 command

Run 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';

Installation

npm i --save dollar-shell

Documentation

Full 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.

Forcing the Node backend

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.

Node streams (dollar-shell/node)

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 Readable

Only 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.

For AI Agents

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.

License

BSD-3-Clause

Release History

  • 1.3.0 Added capture (run a command, collect stdout/stderr as strings) and the signal option (an AbortSignal kills the subprocess).
  • 1.2.1 Bugfix: DSH_FORCE_NODE and dollar-shell/node now switch only the spawn mechanism — spawned children stay native (bun run … / deno run …).
  • 1.2.0 Added dollar-shell/node with Node streams and a DSH_FORCE_NODE flag 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/, removed ts-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 asDuplex to 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.

About

Run OS and shell commands using template tag functions. Same API in Node, Deno, and Bun. Web streams, TypeScript typings, zero dependencies.

Topics

Resources

License

Contributing

Stars

3 stars

Watchers

1 watching

Forks

Sponsor this project

  •  

Contributors