xeq
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
- Installation
- Quick Start
- Comparison
- Commands
- TOML Format
- Features
- Examples
- How It Works
- License
Demo

Installation
macOS / Linux
|
Windows (Powershell)
iwr https://raw.githubusercontent.com/opmr0/xeq/main/install.ps1 -UseBasicParsing | iex
Via cargo (Rust package manager)
Quick Start
1. Create a xeq.toml in your project root:
[]
= [
"npm install",
"npm run build"
]
[]
= ["npm run dev"]
2. Run any script by name:
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.
| 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 |
--summary |
-s |
Print a timing summary after the script finishes |
--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 |
xeq init [template]
Creates a starter xeq.toml in the current directory. Will not overwrite an existing file.
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.
Catches undefined variables, missing nested scripts, circular dependencies, invalid shells, parallel conflicts, and more.
xeq list
Shows all scripts in your xeq.toml - names, descriptions, and commands.
xeq config [path]
Saves a xeq.toml path globally so you can run it from anywhere.
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:
[]
= "What this script does"
= "./my_app"
= 4
= ["quiet"]
= [
"command one",
"command two"
]
run- required, commands to execute in orderdescription- optional, shown inxeq listdir- optional, working directory (absolute or relative)parallel_threads- optional, enables parallel execution with a set thread countoptions- 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:
[]
= ["quiet", "continue_on_err"]
= ["cargo build", "cargo test"]
Available options: quiet, clear, continue_on_err, allow_recursion, summary, allow_empty_vars
CLI flags toggle script options. If quiet is baked in and you pass --quiet, it turns quiet off for that run.
2. Variables
Define reusable values in a [vars] block and reference them with {{@varname}}:
[]
= "myapp:latest"
= "development"
[]
= ["docker build -t {{@image}} ."]
[]
= ["APP_ENV={{@env}} npm start"]
Local variables override global ones for a specific script:
[]
= "myapp:latest"
[]
= "myapp:build"
= ["docker build -t {{@image}} ."] # uses "myapp:build"
[]
= ["docker push {{@image}}"] # uses "myapp:latest"
Override at runtime with --args:
Fallback values - use | to provide a default if a variable isn't set:
[]
= ["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-varsor addallow_empty_varsto options to skip this.
3. Arguments
Use positional placeholders {{1}}, {{2}} for values that change every run:
[]
= [
"npm create vite@latest {{1}} -- --template {{2}}",
"cd {{1}}",
"npm install"
]
# {{1}} = my-app
# {{2}} = react
Mix named and positional args:
Missing arguments cause an error. Use
--allow-empty-varsto skip this.
4. Environment Variables
Reference environment variables with {{$VARNAME}}:
[]
= ["deploy --token {{$API_TOKEN}} --env {{$DEPLOY_ENV}}"]
xeq loads a .env file from the current directory automatically:
# .env
API_TOKEN=abc123
DEPLOY_ENV=production
Pass --no-env to skip loading .env.
Missing env vars cause an error. Use
--allow-empty-varsto skip this.
5. Nested Scripts
Call other scripts from within a script using the xeq: prefix:
[]
= ["npm install"]
[]
= ["npm run build"]
[]
= [
"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_recursionto options if you intentionally need a script to call itself.
6. Parallel Execution
Run all commands in a script at the same time:
[]
= 4
= [
"cargo test",
"cargo clippy",
"cargo fmt --check"
]
Use -p to toggle parallel mode from the CLI, or -p <threads> to override the thread count:
Scripts with
cdcommands orxeq:calls cannot run in parallel.xeq validatecatches this.
7. Global Configuration
Save a xeq.toml globally to run scripts from any directory:
8. Run Summary
Pass --summary to see every command and how long it took:
command time status
--------------------------------------------------
cargo test 1.39s succeeded
cargo clippy 0.80s succeeded
cargo fmt 0.26s succeeded
9. Events
Run additional commands when a script succeeds or fails:
[]
= ["cargo test", "cargo build"]
= ["echo build passed"]
= ["echo build failed"]
Rules:
- Events are ignored during parallel execution
- Events disable the run summary
- Events cannot be combined with
continue_on_err
10. Custom Shells
Set a shell at the file level to run all commands with:
= "zsh"
[]
= ["cargo build", "cargo test"]
Available shells: sh, bash, zsh, fish, cmd, powershell
Defaults to sh on Linux/macOS and cmd on Windows.
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.tomlfrom the current directory, or a globally saved path with--global - Commands run through
sh -con Linux/macOS andcmd /Con Windows by default cdcommands update the working directory for all subsequent commands in that script- Variables resolve in order:
--args→ local vars → global vars → fallback .envis loaded automatically before any script runs- Script names are case-sensitive
License
MIT - LICENSE