DEV Community

Anton Golub
Anton Golub

Posted on

zx@lite: minimalistic shell scripting with TS/JS superpowers

Ditch clunky bash syntax. Script smarter — with fewer dependencies and full TypeScript support.

⚡ What is zx@lite?

The original zx makes shell automations delightful in modern JS runtimes. The @lite version, introduced in v8.5.0, gives you optimal performance, devX without the extra API bloat:

  • ✅ Core zx functionality ($, cd, ps)
  • ✅ First-class TypeScript support
  • ⚡ ~7× smaller than full zx (~124 KB vs ~875 kB)
  • 🧱 Static build with zero dependencies.
  • 🔌 Wide compat range: Node.js 12+, Deno 1.30+, Bun 1.0+, GraalVM 17+ on Win, Mac or Linux

Ideal for:

  • Fast script prototyping
  • DevOps and CI automations
  • Docker images
  • Small CLI tooling

🧾 Setup

npm install zx@lite
Enter fullscreen mode Exit fullscreen mode

TypeScript is an option but highly recommended for safety and better IDE support.

npm install -D typescript @types/node
Enter fullscreen mode Exit fullscreen mode

Attach tsconfig.json like this:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "moduleResolution": "nodenext",
    "strict": true
  }
}
Enter fullscreen mode Exit fullscreen mode

🧪 Examples

Let’s say you want to clone several repos and list their directories. In bash, this would be a mess of &, wait, and error handling. In zx@lite, it’s much cleaner:

#!/usr/bin/env zx
import { $ } from 'zx'

// Run 3 commands in parallel
await Promise.all([
  $`git clone https://github.com/google/zx zx-clone`,
  $`git clone https://github.com/webpod/webpod webpod-clone`
])

const output = await $`ls -1`
console.log('Cloned directories:\n', output.lines())
Enter fullscreen mode Exit fullscreen mode

Combine zx@lite with runtime features. Need transport? Just bring in native fetch:

#!/usr/bin/env zx
import { $ } from 'zx'

const repo = 'google/zx'
const latest = await (await fetch(`https://api.github.com/repos/${repo}/releases/latest`)).json()
const v = latest.tag_name
const zip_file = `${repo.replace('/', '-')}-${v}.zip`

await $`curl -o ${zip_file} -L ${latest.zipball_url}`
await $`mkdir -p releases/${v}`
await $`unzip ${zip_file} -d releases/${v}`

console.log('✅ Done')
Enter fullscreen mode Exit fullscreen mode

⚠️ What’s missing in zx@lite?

Feature zx zx@lite
$
cd
ps
glob
YAML
fs-extra
minimist

Check the full API comparison for details.

📦 Upgrade path

Switching between lite and full is trivial:

# Go full speed:
npm install zx

# Back to lean mode:
npm install zx@lite
Enter fullscreen mode Exit fullscreen mode

📚 References

🧠 Final thoughts

zx@lite is everything you need — and nothing you don’t — for modern scripting with real programming ergonomics. Stop writing fragile bash. Start scripting like a developer.

💬 Got ideas, snippets, or zx@lite tips? Drop them below or feel free to share in the project repo: discussions, issues.

Top comments (4)

Collapse
 
nevodavid profile image
Nevo David

pretty cool, i never stick with bash for long anyway tbh - you think stuff like this makes people actually switch or does everyone just default back eventually?

Collapse
 
antongolub profile image
Anton Golub • Edited

I think that a zx-like API ($syntax) will gradually become an industry standard, and the choice of tool will be determined by non-functional factors. And those parts that are currently tool-specific will probably become universal plugins/mixins (we are experimenting with this idea at a very early stage).

Collapse
 
antonmedv profile image
Anton Medvedev

The zx@lite is a better replacment for execa.

Collapse
 
antongolub profile image
Anton Golub • Edited

Let me make a clarification: in certain cases. We are moving with different premises, so the implementations of the tools are noticeably different. And users now have a wide palette of choice to best suit their needs:

  • zx
  • execa
  • zx@lite
  • nano-spawn
  • zurk
  • bun