Google ZX Scripting
Use this skill when writing scripts with Google's zx library — the tool that makes shell scripting with JavaScript/TypeScript productive and safe. Read only the reference file(s) needed for the task.
Quick Start
All zx scripts use the lite entry point for portability. Scripts are standalone .mjs files — no project setup required.
#!/usr/bin/env npx zx
import { $, fs, path, glob, chalk } from 'zx/core';
const files = await glob('src/**/*.ts');
await $`eslint ${files}`;
Run directly:
chmod +x script.mjs && ./script.mjs
# or
npx zx script.mjs
Critical Rules
- Always use
zx/core— import fromzx/core(the lite bundle), never barezx. This avoids the heavy CLI wrapper and keeps scripts lean and embeddable. - Template literals auto-escape — interpolated values in
$`...`are automatically shell-quoted. Never manually quote interpolated variables:$`echo ${userInput}`is safe,$`echo "${userInput}"`double-quotes and may break. - Arrays expand correctly —
$`cmd ${arrayOfArgs}`expands each element as a separate quoted argument. Use this for flags, file lists, etc. - Non-zero exits throw — by default, a failed command throws
ProcessOutputas an error. Usenothrowoption or.nothrow()to suppress when you expect failures (e.g.,grepreturning no matches). - Use
within()for isolation —within()creates an async scope with its own$.cwd,$.env, and other settings. Essential for parallel tasks that need different working directories. - Pipe with
.pipe()— use$`cmd1`.pipe($`cmd2`)instead of shell pipes. This keeps each process managed by zx. - Prefer zx builtins over shell commands — use
glob()instead offind,fsinstead ofcat/cp/mv,fetch()instead ofcurl. These are cross-platform and return proper JS types. cd()is global —cd()changes$.cwdfor ALL subsequent commands. Usewithin()or$({cwd: '/path'})for scoped directory changes.- Scripts must be
.mjs— use.mjsextension for top-levelawaitsupport without bundler config.
Reference Map
| Need | File |
|---|---|
$, ProcessPromise, ProcessOutput, configuration, piping, streams | references/core-api.md |
| Ad-hoc scripts, CLI tools, build scripts, deployment, project scaffolding | references/scripting-patterns.md |
| File processing, data pipelines, batch ops, AI scripts, log analysis | references/processing-recipes.md |
Task Routing
- Writing a quick one-off command or shell automation ->
references/scripting-patterns.md - Building a build/deploy/CI script ->
references/scripting-patterns.md - Processing files, data, logs, or batch operations ->
references/processing-recipes.md - Need API details for
$, pipes, streams, config ->references/core-api.md - Combining multiple patterns (e.g., build + process) -> read both relevant files
Import Cheatsheet
// Core — always start here
import { $, fs, path, glob, chalk } from 'zx/core';
// Additional utilities (import individually as needed)
import { spinner, retry, question, echo, sleep, within,
stdin, tmpdir, tmpfile, which, ps, kill,
quote, YAML, argv, fetch } from 'zx/core';
Conventions for Generated Scripts
- Shebang line: Always include
#!/usr/bin/env npx zxas the first line - Error handling: Wrap top-level logic in a main function with try/catch, or use
$.nothrowselectively - Output: Use
chalkfor colored terminal output — green for success, red for errors, yellow for warnings, dim for secondary info - Progress: Use
spinner()for long-running operations in interactive contexts - Arguments: Use
argv(pre-parsedminimist) for CLI argument handling - Temp files: Use
tmpdir()andtmpfile()— they auto-clean on exit - Parallelism: Use
Promise.all()withwithin()for parallel operations that need isolation