xeq 2.4.1

xeq is a cross-platform CLI tool that runs sequences of commands from a single TOML file, making repetitive tasks fast and consistent.
xeq-2.4.1 is not a library.

xeq

Crates.io Downloads License Build Rust

xeq runs sequences of commands from a single TOML file, making repetitive tasks fast and consistent.

Every project has a setup ritual. Ten commands, always in the same order, every time. Write them once in a xeq.toml, commit it, and anyone on any OS runs the exact same steps with one command.


Table of Contents


Demo

demo

Installation

macOS / Linux

curl -sSf https://raw.githubusercontent.com/opmr0/xeq/main/install.sh | sh

Windows (Powershell)

iwr https://raw.githubusercontent.com/opmr0/xeq/main/install.ps1 -UseBasicParsing | iex

Via cargo (Rust package manager)

cargo install xeq


Quick Start

1. Create a xeq.toml in your project root:

[setup]

run = [

    "npm install",

    "npm run build"

]



[dev]

run = ["npm run dev"]

2. Run any script by name:

xeq run setup

xeq run dev

xeq finds xeq.toml in the current directory automatically. Use xeq init to generate a starter file.


Comparison

Feature xeq Makefile npm scripts just
File type TOML Makefile package.json Justfile
Cross-platform Yes Mostly Linux/macOS Yes Yes
Validation command Yes (xeq validate) No No No
Variables Yes Yes Limited Yes
Args support Yes Limited Limited Yes
Nested scripts Yes (xeq:) Yes No Yes
Parallel execution Yes Yes (-j) No No
.env support Yes (auto) No No Yes (opt-in)
Init templates Yes (30+) No No No

Commands

xeq run <script> [flags]

Runs a script by name. Commands execute in order. If any command fails, xeq stops unless you pass --continue-on-err.

If no script name is given, xeq runs the default script defined in your config:

default = "dev"



[dev]

run = ["npm run dev"]

xeq run        # runs "dev"

xeq run setup

xeq run build --continue-on-err

xeq run dev --quiet

xeq run test --parallel

xeq run create --args my-app

xeq run deploy --args env=prod

Flag Short Description
--continue-on-err -C Keep going even if a command fails
--quiet -q Hide xeq's own log messages
--clear -c Clear the terminal before each command
--parallel [threads] -p Run all commands in parallel (default: logical CPU count)
--args <values...> -a Pass arguments into the script, positional or key=value
--global -g Use the globally saved xeq.toml instead of the local one
--dry-run -d Preview commands without executing them
--no-events -e Disable events for this run
--allow-empty-args -A Skip errors for missing variables or arguments
--no-env Skip loading the .env file
--allow-recursion Let a script call itself

Exit codes: xeq exits 0 on success and non-zero if any command fails. Use this in CI pipelines or shell scripts to halt on failure.


xeq init [template]

Creates a starter xeq.toml in the current directory. Will not overwrite an existing file.

xeq init

xeq init rust

xeq init docker

Available templates: android, ansible, astro, aws, bun, deno, django, docker, dotnet, elixir, expo, fastapi, flutter, git, go, hugo, java-gradle, java-maven, kubernetes, laravel, monorepo, nestjs, nextjs, node, python, rails, react, rust, svelte, tauri


xeq validate

Checks all scripts for errors without running anything.

Check Flag
Circular dependencies static
Missing xeq: targets static
default script existence static
continue_on_err + events conflict static
parallel_threads <= 1 static
parallel + cd/xeq: conflict static
dir existence static
Undefined {{@var}} static
dir cd permission --runtime
Unset {{$VAR}} env vars --runtime
Command existence --runtime

Add --runtime to also validate environment variables and system commands:

xeq validate

xeq validate --runtime

xeq validate --global


xeq list

Shows all scripts in your xeq.toml, names, descriptions, and commands.

xeq list

xeq list --global


xeq config [path]

Saves a xeq.toml path globally so you can run it from anywhere.

xeq config ~/my-scripts/xeq.toml   # save once

xeq config                          # open saved file in your editor


xeq toml

Prints the full TOML format reference.


Aliases

Command Alias
xeq run xeq r
xeq config xeq c
xeq init xeq i
xeq validate xeq v

TOML Format

Each script needs at minimum a run array:

[my-script]

description = "What this script does"

dir = "./my_app"

parallel_threads = 4

options = ["quiet"]

run = [

    "command one",

    "command two"

]

  • run - required, commands to execute in order
  • description - optional, shown in xeq list
  • dir - optional, working directory (absolute or relative to where xeq is invoked, not where xeq.toml lives)
  • parallel_threads - optional, enables parallel execution with a set thread count
  • options - optional, baked-in flags. see Script Options

Script names are case-sensitive. Build and build are different scripts.


Features

1. Script Options

Bake default behavior into a script so you don't have to pass flags every time:

[build]

options = ["quiet", "continue_on_err"]

run = ["cargo build", "cargo test"]

Available options: quiet, clear, continue_on_err, allow_recursion, allow_empty_vars

CLI flags toggle script options. If quiet is baked in and you pass --quiet, it turns quiet off for that run.

xeq run build          # quiet ON  (from TOML)

xeq run build --quiet  # quiet OFF (toggled)


2. Variables

Define reusable values in a [vars] block and reference them with {{@varname}}:

[vars]

image = "myapp:latest"

env = "development"



[build]

run = ["docker build -t {{@image}} ."]



[start]

run = ["APP_ENV={{@env}} npm start"]

Local variables override global ones for a specific script:

[vars]

image = "myapp:latest"



[build]

vars.image = "myapp:build"

run = ["docker build -t {{@image}} ."]   # uses "myapp:build"



[push]

run = ["docker push {{@image}}"]          # uses "myapp:latest"

Override at runtime with --args:

xeq run build --args image=myapp:hotfix

Fallback values use | to provide a default if a variable isn't set:

[build]

run = ["docker build -t {{@image | myapp:latest}} ."]

Resolution order: --args -> local vars -> global vars -> fallback

If a variable isn't defined and no fallback is set, xeq exits with an error. Pass --allow-empty-vars or add allow_empty_vars to options to skip this.


3. Arguments

Use positional placeholders {{1}}, {{2}} for values that change every run:

[create]

run = [

    "npm create vite@latest {{1}} -- --template {{2}}",

    "cd {{1}}",

    "npm install"

]

xeq run create --args my-app react

# {{1}} = my-app

# {{2}} = react

Mix named and positional args:

xeq run deploy --args env=production my-app

Missing arguments cause an error. Use --allow-empty-vars to skip this.


4. Environment Variables

Reference environment variables with {{$VARNAME}}:

[deploy]

run = ["deploy --token {{$API_TOKEN}} --env {{$DEPLOY_ENV}}"]

xeq loads a .env file from the directory where xeq is invoked automatically:

# .env

API_TOKEN=abc123
DEPLOY_ENV=production

Pass --no-env to skip loading .env.

Missing env vars cause an error. Use --allow-empty-vars to skip this.


5. Nested Scripts

Call other scripts from within a script using the xeq: prefix:

[install]

run = ["npm install"]



[build]

run = ["npm run build"]



[deploy]

run = [

    "xeq:install",

    "xeq:build",

    "npm run deploy"

]

Running xeq run deploy runs install and build first, in order.

xeq detects circular dependencies and exits. Add allow_recursion to options if you intentionally need a script to call itself.


6. Parallel Execution

Run all commands in a script at the same time:

[check]

parallel_threads = 4

run = [

    "cargo test",

    "cargo clippy",

    "cargo fmt --check"

]

Use -p to toggle parallel mode from the CLI, or -p <threads> to override the thread count:

xeq run check         # uses parallel_threads from TOML

xeq run check -p      # uses logical CPU count

xeq run check -p 8    # uses 8 threads

Scripts with cd commands or xeq: calls cannot run in parallel. xeq validate catches this. If parallel_threads is 1 or less, xeq falls back to sequential execution.


7. Global Configuration

Save a xeq.toml globally to run scripts from any directory:

xeq config ~/my-scripts/xeq.toml   # save once

xeq run git-cleanup --global        # run from anywhere

xeq list --global                   # list global scripts


8. Events

Run additional commands when a script succeeds or fails:

[build]

run = ["cargo test", "cargo build"]

on_success = ["echo build passed"]

on_error = ["echo build failed"]

Events cannot be combined with continue_on_err.


9. Custom Shells

Set a shell at the file level to run all commands with:

shell = "zsh"



[build]

run = ["cargo build", "cargo test"]

Available shells: sh, bash, zsh, fish, cmd, powershell

Defaults to sh on Linux/macOS and cmd on Windows.


CI Usage

xeq works well in CI pipelines. Use xeq validate --runtime as a pre-flight check to catch missing commands or unset env vars before anything runs.

GitHub Actions example:

- name: Validate config
  run: xeq validate --runtime

- name: Build
  run: xeq run build

- name: Test
  run: xeq run test

xeq exits non-zero on any failure, so your pipeline halts automatically without extra configuration.


Examples

The examples/ folder has ready-to-use TOML files for common workflows.

File Description Features Used
react-tailwind.toml Scaffold and run a React + Tailwind project variables, cd operators
nextjs.toml Next.js project setup and pipeline nested scripts, variables
rust-project.toml Rust checks, build and publish parallel, nested scripts
docker.toml Docker image and container management variables, nested scripts
git-workflow.toml Common git operations variables, arguments
nested-scripts.toml CI pipeline from reusable pieces nested scripts
env-vars.toml Deploy and notify using env vars {{$VAR}}, nested scripts
python-project.toml Virtualenv, checks and PyPI publish parallel, nested scripts, variables
database.toml Migrations, seed, dump and restore env vars, arguments, nested scripts
monorepo.toml Multi-package frontend workspace parallel, variables, nested scripts
aws-deploy.toml ECR push and ECS deploy pipeline env vars, nested scripts
go-project.toml Go build, test and cross-compile parallel, nested scripts, variables
arguments.toml Positional and named arg patterns arguments, variables
script-options.toml Flag toggle mechanic demonstrations options, parallel, quiet, continue_on_err

How It Works

  • xeq reads xeq.toml from the current directory, or a globally saved path with --global
  • Commands run through sh -c on Linux/macOS and cmd /C on Windows by default
  • cd commands update the working directory for all subsequent commands in that script
  • dir is resolved relative to where xeq is invoked, not where xeq.toml lives
  • Variables resolve in order: --args -> local vars -> global vars -> fallback
  • .env is loaded from the invocation directory automatically before any script runs
  • Script names are case-sensitive

Contributing

See CONTRIBUTING.md.


License

MIT - LICENSE