dollar-shell 1.1.7 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md ADDED
@@ -0,0 +1,68 @@
1
+ # Agent Instructions for dollar-shell
2
+
3
+ This file provides guidance for AI coding agents working with or on the `dollar-shell` package.
4
+
5
+ ## What This Package Does
6
+
7
+ `dollar-shell` runs OS and shell commands from JavaScript/TypeScript using template tag functions. It works on Node, Deno, and Bun with the same API. All streams are web streams.
8
+
9
+ ## Quick Reference
10
+
11
+ ```js
12
+ import $, {$$, $sh, shell, sh, spawn} from 'dollar-shell';
13
+
14
+ // Run a command, get exit info
15
+ const result = await $`echo hello`;
16
+ // result: {code: 0, signal: null, killed: false}
17
+
18
+ // Run a command, get full Subprocess
19
+ const sp = $$`sleep 5`;
20
+ sp.kill();
21
+ await sp.exited;
22
+
23
+ // Shell command (supports pipes, aliases)
24
+ await $sh`ls -l . | grep LICENSE | wc`;
25
+
26
+ // Stream pipelines
27
+ $.from`ls -l .`
28
+ .pipeThrough($.io`grep LIC`)
29
+ .pipeTo($.to({stdout: 'inherit'})`wc`);
30
+
31
+ // Custom options (returns new tag function with updated defaults)
32
+ const $verbose = $({stdout: 'inherit', stderr: 'inherit'});
33
+ await $verbose`ls -l .`;
34
+ ```
35
+
36
+ ## Architecture
37
+
38
+ - `src/index.js` — Main entry point, wires everything together
39
+ - `src/index.d.ts` — TypeScript declarations for the full public API
40
+ - `src/bq-spawn.js` — Template tag factory for spawn-based functions (`$`, `$$`)
41
+ - `src/bq-shell.js` — Template tag factory for shell-based functions (`$sh`, `shell`)
42
+ - `src/utils.js` — Shared utilities (`raw`, `isWindows`, `winCmdEscape`, etc.)
43
+ - `src/spawn/node.js`, `src/spawn/deno.js`, `src/spawn/bun.js` — Runtime-specific Subprocess implementations
44
+ - `src/shell/unix.js`, `src/shell/windows.js` — Platform-specific shell escaping and command building
45
+
46
+ ## Key Patterns
47
+
48
+ - **Tag function + options pattern**: All tag functions (`$`, `$$`, `$sh`, `shell`) can be called with an options object to produce a new tag function with updated defaults. The new function retains all properties (`.from`, `.to`, `.io`, `.through`).
49
+ - **raw()**: Wraps a value to bypass escaping (shell) or argument splitting (spawn).
50
+ - **Platform detection**: `isWindows` boolean is exported. Runtime detection (Node/Deno/Bun) happens at import via dynamic imports.
51
+
52
+ ## When Using This Package
53
+
54
+ - Import `$` as the default export for simple command execution.
55
+ - Use `$sh` when you need shell features (pipes, aliases, globbing).
56
+ - Use `$$` or `shell` when you need the full `Subprocess` object (kill, streams, exit code).
57
+ - Use `.from`, `.to`, `.io`/`.through` for stream pipelines with web streams.
58
+ - Always `await` the result of `$` and `$sh` (they return promises).
59
+ - `$$` and `shell` return `Subprocess` synchronously — use `await sp.exited` to wait.
60
+
61
+ ## When Modifying This Package
62
+
63
+ - Run `npm test` to execute tests (uses tape-six).
64
+ - Run `npm run ts-check` to verify TypeScript declarations (`tsc --noEmit`).
65
+ - Keep `src/index.d.ts` in sync with any API changes in `src/index.js`.
66
+ - The wiki (in the `wiki/` submodule) documents the public API — update it alongside code changes.
67
+ - Tests are in `tests/` (automated) and `tests/manual/` (manual verification).
68
+ - TypeScript usage examples are in `ts-check/` — they are compiled but not executed during `npm run ts-check`.
package/README.md CHANGED
@@ -194,16 +194,28 @@ the spawn options with the following properties:
194
194
  - `shellArgs` — an array of strings that are passed to the shell as arguments.
195
195
  - On Unix-like systems it defaults to `['-c']`.
196
196
  - On Windows it defaults to `['/d', '/s', '/c']` for `cmd.exe`
197
- or `['-e']` for `pwsh.exe` or `powershell.exe`.
197
+ or `['-c']` for `pwsh.exe` or `powershell.exe`.
198
198
 
199
199
  The rest is identical to `$`: `$sh`, `$sh.from`, `$sh.to` and `$sh.io`/`$sh.through`.
200
200
 
201
+ ## For AI Agents
202
+
203
+ This package ships with files to help AI coding agents and LLMs understand and use it:
204
+
205
+ - **[AGENTS.md](./AGENTS.md)** — Quick-start instructions, architecture overview, and key patterns for AI agents working with this package.
206
+ - **[llms.txt](./llms.txt)** — Concise project overview with links to documentation, following the [llms.txt standard](https://llmstxt.org/).
207
+ - **[llms-full.txt](./llms-full.txt)** — Self-contained complete API reference (no external links needed).
208
+
209
+ These files are included in the npm package.
210
+
201
211
  ## License
202
212
 
203
213
  BSD-3-Clause
204
214
 
205
215
  ## Release History
206
216
 
217
+ - 1.1.9 _Updated dev dependencies, cleaned up docs, added info for AI agents._
218
+ - 1.1.8 _Updated dev dependencies._
207
219
  - 1.1.7 _Updated dev dependencies._
208
220
  - 1.1.6 _Updated dev dependencies._
209
221
  - 1.1.5 _Updated dev dependencies._
package/llms-full.txt ADDED
@@ -0,0 +1,313 @@
1
+ # dollar-shell
2
+
3
+ > A micro-library for running shell commands and using them in stream pipelines with ease in Node, Deno, Bun. Tiny, simple, zero-dependency package with TypeScript typings. Uses web streams.
4
+
5
+ The package provides template-tag functions to spawn OS processes (`$`, `$$`) and shell processes (`$sh`, `shell`/`sh`). Each has variants for stream pipelines: `.from` (stdout as ReadableStream), `.to` (stdin as WritableStream), `.io`/`.through` (duplex). All tag functions accept an options object to customize spawn/shell behavior and return a new tag function with updated defaults.
6
+
7
+ Install: `npm i --save dollar-shell`
8
+
9
+ ## Usage
10
+
11
+ ```js
12
+ import $, {$$, $sh, shell, sh, spawn} from 'dollar-shell';
13
+ ```
14
+
15
+ ## spawn()
16
+
17
+ Low-level function to spawn a process with full control.
18
+
19
+ Signature: `spawn(command: string[], options?: SpawnOptions): Subprocess`
20
+
21
+ ### SpawnOptions
22
+
23
+ ```ts
24
+ type SpawnStreamState = 'pipe' | 'ignore' | 'inherit' | 'piped' | null;
25
+
26
+ interface SpawnOptions {
27
+ cwd?: string; // working directory, defaults to process.cwd()
28
+ env?: {[key: string]: string | undefined}; // environment variables
29
+ stdin?: SpawnStreamState; // default: null (ignored)
30
+ stdout?: SpawnStreamState; // default: null (ignored)
31
+ stderr?: SpawnStreamState; // default: null (ignored)
32
+ }
33
+ ```
34
+
35
+ Stream states: `'pipe'`/`'piped'` makes the stream available, `'inherit'` inherits from parent, `'ignore'`/`null` ignores it.
36
+
37
+ ### Subprocess
38
+
39
+ ```ts
40
+ interface Subprocess<R = any> {
41
+ readonly command: string[];
42
+ readonly options: SpawnOptions | undefined;
43
+ readonly exited: Promise<number>; // resolves to exit code
44
+ readonly finished: boolean;
45
+ readonly killed: boolean;
46
+ readonly exitCode: number | null;
47
+ readonly signalCode: string | null;
48
+ readonly stdin: WritableStream<R> | null; // non-null when stdin is 'pipe'
49
+ readonly stdout: ReadableStream<R> | null; // non-null when stdout is 'pipe'
50
+ readonly stderr: ReadableStream<R> | null; // non-null when stderr is 'pipe'
51
+ readonly asDuplex: {readable: ReadableStream<R>, writable: WritableStream<R>};
52
+ kill(): void;
53
+ }
54
+ ```
55
+
56
+ All streams are web streams (ReadableStream/WritableStream).
57
+
58
+ Example:
59
+ ```js
60
+ import {spawn} from 'dollar-shell';
61
+
62
+ const sp = spawn(['sleep', '5']);
63
+ await new Promise(resolve => setTimeout(resolve, 1000));
64
+ sp.kill();
65
+ await sp.exited;
66
+ // sp.finished === true, sp.killed === true
67
+ ```
68
+
69
+ ## $$ (double dollar)
70
+
71
+ Template tag function wrapping `spawn()`. Parses the template string into an array of arguments (split by whitespace). Interpolated values are kept as separate arguments when surrounded by whitespace.
72
+
73
+ ```ts
74
+ type Backticks<R> = (strings: TemplateStringsArray, ...args: unknown[]) => R;
75
+
76
+ interface Dollar<R, O = SpawnOptions> extends Backticks<R> {
77
+ (options: O): Dollar<R, O>;
78
+ }
79
+
80
+ declare const $$: Dollar<Subprocess>;
81
+ ```
82
+
83
+ Signatures:
84
+ ```js
85
+ import {$$} from 'dollar-shell';
86
+
87
+ const sp = $$`ls -l ${myFile}`; // returns Subprocess
88
+ const sp2 = $$(options)`ls -l .`; // with custom options
89
+ const $tag = $$(options); // returns reusable tag function
90
+ const sp3 = $tag`ls -l .`;
91
+ ```
92
+
93
+ ## $ (dollar)
94
+
95
+ Simpler interface than `$$`. Returns a promise with exit info instead of a Subprocess.
96
+
97
+ ```ts
98
+ interface DollarResult {
99
+ code: number | null;
100
+ signal: string | null;
101
+ killed: boolean;
102
+ }
103
+
104
+ interface DollarImpl<R = any> extends Dollar<Promise<DollarResult>> {
105
+ from: Dollar<ReadableStream<R>>; // stdout as source stream
106
+ to: Dollar<WritableStream<R>>; // stdin as sink stream
107
+ through: Dollar<DuplexPair<R>>; // {readable, writable} pair
108
+ io: Dollar<DuplexPair<R>>; // alias of through
109
+ }
110
+
111
+ declare const $: DollarImpl;
112
+ export default $;
113
+ ```
114
+
115
+ `$` is the default export.
116
+
117
+ Examples:
118
+ ```js
119
+ import $ from 'dollar-shell';
120
+
121
+ // Run a command
122
+ const result = await $`echo hello`;
123
+ console.log(result.code, result.signal, result.killed);
124
+
125
+ // With custom options
126
+ const result2 = await $({stdout: 'inherit'})`ls -l .`;
127
+
128
+ // Stream pipeline
129
+ import chain from 'stream-chain';
130
+
131
+ chain([
132
+ $.from`ls -l .`,
133
+ $.io`grep LICENSE`,
134
+ $.io`wc`,
135
+ $.to({stdout: 'inherit'})`tee output.txt`
136
+ ]);
137
+
138
+ // Using $.from with web streams
139
+ $.from`ls -l .`
140
+ .pipeThrough($.io`grep LIC`)
141
+ .pipeTo($.to({stdout: 'inherit'})`wc`);
142
+ ```
143
+
144
+ When `$` is called with an options object, it returns a new `$` with updated defaults while preserving `.from`, `.to`, `.through`, `.io`:
145
+ ```js
146
+ const $custom = $({stdout: 'inherit', stderr: 'inherit'});
147
+ typeof $custom.from === 'function'; // true
148
+ typeof $custom.io === 'function'; // true
149
+ ```
150
+
151
+ ## shell / sh
152
+
153
+ Like `$$` but executes the command through a shell. Supports shell-specific features like pipes, aliases, and functions.
154
+
155
+ ```ts
156
+ interface ShellOptions extends SpawnOptions {
157
+ shellPath?: string; // path to shell executable
158
+ shellArgs?: string[]; // arguments passed to the shell
159
+ }
160
+
161
+ declare const shell: Dollar<Subprocess, ShellOptions>;
162
+ declare const sh = shell; // alias
163
+ ```
164
+
165
+ Shell defaults:
166
+ - Unix: shell = `$SHELL` or `/bin/sh` (or `/system/bin/sh` on Android), args = `['-c']`
167
+ - Windows cmd.exe: shell = `%ComSpec%` or `cmd.exe`, args = `['/d', '/s', '/c']`
168
+ - Windows PowerShell: shell = `pwsh.exe`/`powershell.exe`, args = `['-c']`
169
+
170
+ Example:
171
+ ```js
172
+ import {shell, sh} from 'dollar-shell';
173
+
174
+ const sp = sh`sleep 5`;
175
+ sp.kill();
176
+ await sp.exited;
177
+ ```
178
+
179
+ ## $sh (dollar shell)
180
+
181
+ Mirrors `$` but runs commands through a shell. Same relationship as `shell` to `$$`.
182
+
183
+ ```ts
184
+ interface ShellImpl<R = any> extends Dollar<Promise<DollarResult>, ShellOptions> {
185
+ from: Dollar<ReadableStream<R>, ShellOptions>;
186
+ to: Dollar<WritableStream<R>, ShellOptions>;
187
+ through: Dollar<DuplexPair<R>, ShellOptions>;
188
+ io: Dollar<DuplexPair<R>, ShellOptions>;
189
+ }
190
+
191
+ declare const $sh: ShellImpl;
192
+ ```
193
+
194
+ Examples:
195
+ ```js
196
+ import {$sh} from 'dollar-shell';
197
+
198
+ const result = await $sh`ls .`;
199
+ console.log(result.code, result.signal, result.killed);
200
+
201
+ // Interactive shell for aliases/functions
202
+ const $p = $sh({shellArgs: ['-ic'], stdout: 'inherit'});
203
+ await $p`nvm ls`;
204
+
205
+ // Shell pipes
206
+ await $sh({stdout: 'inherit'})`ls -l . | grep LICENSE | wc`;
207
+
208
+ // Stream pipeline
209
+ $sh.from`ls -l .`
210
+ .pipeThrough($sh.io`grep LIC`)
211
+ .pipeTo($sh.to({stdout: 'inherit'})`wc`);
212
+ ```
213
+
214
+ ## Utilities
215
+
216
+ ```js
217
+ import {
218
+ isWindows, raw, winCmdEscape,
219
+ cwd, currentExecPath, runFileArgs,
220
+ shellEscape, currentShellPath, buildShellCommand
221
+ } from 'dollar-shell';
222
+ ```
223
+
224
+ ### isWindows
225
+
226
+ `const isWindows: boolean` — `true` if the current platform is Windows.
227
+
228
+ ### raw(value)
229
+
230
+ Marks a value to bypass shell escaping or spawn argument splitting. The value is passed as-is.
231
+
232
+ ```js
233
+ import {$sh, raw} from 'dollar-shell';
234
+ await $sh({stdout: 'inherit'})`echo ${raw('"hello"')}`;
235
+ ```
236
+
237
+ For spawn (`$`/`$$`), `raw()` values are split by whitespace like template string literals.
238
+
239
+ ### winCmdEscape(value)
240
+
241
+ Escapes a value for Windows `cmd.exe` using caret (`^`) escaping. On non-Windows, returns the value as a string. Returns a `raw()`-wrapped object on Windows.
242
+
243
+ ```js
244
+ import {$sh, winCmdEscape} from 'dollar-shell';
245
+ await $sh`echo ${winCmdEscape('hello "world"')}`;
246
+ ```
247
+
248
+ ### cwd()
249
+
250
+ Returns the current working directory (platform-agnostic).
251
+
252
+ ### currentExecPath()
253
+
254
+ Returns the path of the current JS/TS runtime executable (Node, Deno, or Bun).
255
+
256
+ ### runFileArgs
257
+
258
+ Array of default arguments for the current runtime:
259
+ - Node: `[]`
260
+ - Deno: `['run']`
261
+ - Bun: `['run']`
262
+
263
+ Note: Deno may require additional permission flags (e.g., `--allow-read`).
264
+
265
+ ### shellEscape(value, options?)
266
+
267
+ Escapes a value for the current shell. Takes an optional `{shellPath?: string}` options object.
268
+ - Unix: wraps in single quotes
269
+ - Windows cmd.exe: quotes and escapes per cmd.exe rules
270
+ - Windows PowerShell: escapes control characters and non-alphanumeric characters
271
+
272
+ ### currentShellPath()
273
+
274
+ Returns the current shell path:
275
+ - Unix: `$SHELL` or `/bin/sh` (or `/system/bin/sh` on Android)
276
+ - Windows: `%ComSpec%` or `cmd.exe`
277
+
278
+ ### buildShellCommand(shell, args, command)
279
+
280
+ Builds a command array for `spawn()` from shell path, args, and command string.
281
+ - `shell`: string or undefined (defaults to `currentShellPath()`)
282
+ - `args`: string[] or undefined (defaults to shell-specific args)
283
+ - `command`: the shell command string
284
+
285
+ Returns `string[]` suitable for `spawn()`.
286
+
287
+ ## Template String Behavior
288
+
289
+ ### Spawn functions ($, $$)
290
+
291
+ Template strings are parsed into arrays of arguments by splitting on whitespace. Interpolated values:
292
+ - If surrounded by whitespace: added as a separate argument (preserving spaces within the value)
293
+ - If adjacent to text: concatenated with surrounding text
294
+ - Empty strings are skipped
295
+ - `raw()` values are split by whitespace like literal template text
296
+
297
+ ```js
298
+ $`ls -l ${'.'}`; // command: ['ls', '-l', '.']
299
+ $`${'l'}s -l a${'.'}b`; // command: ['ls', '-l', 'a.b']
300
+ $`ls ${'x y'}`; // command: ['ls', 'x y'] (preserved as one arg)
301
+ ```
302
+
303
+ ### Shell functions ($sh, shell)
304
+
305
+ Template strings are concatenated into a single command string. Interpolated values are escaped using `shellEscape()` unless wrapped with `raw()`.
306
+
307
+ ## TypeScript
308
+
309
+ Full TypeScript declarations are provided in `src/index.d.ts`. The package uses `"types": "./src/index.d.ts"` in package.json.
310
+
311
+ ## Platform Support
312
+
313
+ Works on Node.js, Deno, and Bun. The appropriate spawn implementation is selected automatically at import time. All streams use the web streams API (ReadableStream/WritableStream).
package/llms.txt ADDED
@@ -0,0 +1,28 @@
1
+ # dollar-shell
2
+
3
+ > A micro-library for running shell commands and using them in stream pipelines with ease in Node, Deno, Bun. Tiny, simple, zero-dependency package with TypeScript typings. Uses web streams.
4
+
5
+ The package provides template-tag functions to spawn OS processes (`$`, `$$`) and shell processes (`$sh`, `shell`/`sh`). Each has variants for stream pipelines: `.from` (stdout as ReadableStream), `.to` (stdin as WritableStream), `.io`/`.through` (duplex). All tag functions accept an options object to customize spawn/shell behavior and return a new tag function with updated defaults.
6
+
7
+ Key concepts:
8
+ - `$` runs a command, returns `Promise<{code, signal, killed}>`
9
+ - `$$` runs a command, returns a `Subprocess` object (full control)
10
+ - `$sh` runs a shell command, returns `Promise<{code, signal, killed}>`
11
+ - `shell`/`sh` runs a shell command, returns a `Subprocess` object
12
+ - `spawn()` is the low-level function all others build on
13
+ - Template string arguments are automatically escaped (shell) or split (spawn)
14
+ - `raw()` bypasses escaping/splitting for a value
15
+ - Works on Node, Deno, and Bun with the same API
16
+
17
+ ## Docs
18
+
19
+ - [$ (dollar)](https://github.com/uhop/dollar-shell/wiki/$): Spawn processes with simple return values, includes $.from, $.to, $.io/$.through
20
+ - [$$ (double dollar)](https://github.com/uhop/dollar-shell/wiki/$$): Spawn processes returning full Subprocess objects
21
+ - [$sh (dollar shell)](https://github.com/uhop/dollar-shell/wiki/$sh): Run shell commands with simple return values, includes $sh.from, $sh.to, $sh.io/$sh.through
22
+ - [shell / sh](https://github.com/uhop/dollar-shell/wiki/shell): Run shell commands returning full Subprocess objects
23
+ - [spawn()](https://github.com/uhop/dollar-shell/wiki/spawn): Low-level process spawning with full configuration
24
+ - [Utilities](https://github.com/uhop/dollar-shell/wiki/Utilities): Helper functions — raw(), winCmdEscape(), isWindows, cwd(), currentExecPath(), runFileArgs, shellEscape(), currentShellPath(), buildShellCommand()
25
+
26
+ ## Optional
27
+
28
+ - [TypeScript declarations](https://github.com/uhop/dollar-shell/blob/main/src/index.d.ts): Full TypeScript type definitions
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dollar-shell",
3
3
  "description": "Run shell commands and use them in streams with ease in Node, Deno, Bun. Tiny, simple, no dependency package.",
4
- "version": "1.1.7",
4
+ "version": "1.1.9",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
7
7
  "types": "./src/index.d.ts",
@@ -16,6 +16,9 @@
16
16
  "test": "tape6 --flags FO",
17
17
  "test:bun": "tape6-bun --flags FO",
18
18
  "test:deno": "tape6-deno --flags FO",
19
+ "test:seq": "tape6-seq --flags FO",
20
+ "test:seq:bun": "bun run `tape6-seq --self` --flags FO",
21
+ "test:seq:deno": "deno run -A `tape6-seq --self` --flags FO",
19
22
  "ts-check": "tsc --noEmit",
20
23
  "lint": "prettier --check .",
21
24
  "lint:fix": "prettier --write ."
@@ -23,7 +26,10 @@
23
26
  "files": [
24
27
  "/src",
25
28
  "LICENSE",
26
- "README.md"
29
+ "README.md",
30
+ "AGENTS.md",
31
+ "llms.txt",
32
+ "llms-full.txt"
27
33
  ],
28
34
  "repository": {
29
35
  "type": "git",
@@ -38,7 +44,13 @@
38
44
  "spawn",
39
45
  "$",
40
46
  "dollar",
41
- "stream"
47
+ "stream",
48
+ "process",
49
+ "exec",
50
+ "command",
51
+ "web-streams",
52
+ "deno",
53
+ "bun"
42
54
  ],
43
55
  "author": "Eugene Lazutkin <eugene.lazutkin@gmail.com> (http://www.lazutkin.com/)",
44
56
  "funding": {
@@ -47,7 +59,7 @@
47
59
  },
48
60
  "license": "BSD-3-Clause",
49
61
  "devDependencies": {
50
- "tape-six": "^1.5.1",
62
+ "tape-six": "^1.7.2",
51
63
  "typescript": "^5.9.3"
52
64
  },
53
65
  "tape6": {
package/src/index.d.ts CHANGED
@@ -123,6 +123,11 @@ export declare function currentExecPath(): string;
123
123
  */
124
124
  export declare const runFileArgs: string[];
125
125
 
126
+ /**
127
+ * Whether the current platform is Windows.
128
+ */
129
+ export declare const isWindows: boolean;
130
+
126
131
  /**
127
132
  * The function marks a value as raw. The value will be passed as-is to the shell.
128
133
  * It is used to bypass the default shell escaping rules.