xeq
Run sequences of shell commands with a single word.
Every project has a setup ritual. Ten commands, always in the same order, run 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
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. No extra setup needed.
Create a
xeq.tomlfile withxeq initand xeq creates one for you.
Installation
macOS / Linux
|
Windows (PowerShell)
iwr https://raw.githubusercontent.com/opmr0/xeq/main/install.ps1 -UseBasicParsing | iex
Via cargo
Commands
xeq init
Creates a starter xeq.toml in the current directory. Will not overwrite an existing file.
xeq run <script> [flags]
Runs a script by name. Commands execute one at a time 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 |
-p |
Run all commands at the same time |
--allow-recursion |
Let a script call itself | |
--args <values...> |
-a |
Pass arguments into the script, positional or key=value |
--global |
-g |
Use the globally saved path instead of the local xeq.toml |
--no-env |
Skip loading the .env file |
|
--summary |
-s |
Print a summary table of commands and execution times after the script finishes |
xeq list
Shows all scripts in your TOML file, their names, descriptions, and commands.
xeq validate
Checks all scripts in your TOML file for errors without running anything.
Catches:
- Nested
xeq://calls pointing to scripts that don't exist paralleloption combined withcdorxeq://- Undefined
{{@vars}}not defined in vars (warns, doesn't fail) - Circular dependencies between scripts
dirpaths that don't exist
xeq config [path]
Saves a TOML file path globally. See Global Configuration.
TOML Format
A xeq.toml file contains named scripts. Each script needs at least a run array:
[]
= "What this script does"
= "./my_app"
= ["quiet"]
= [
"command one",
"command two"
]
- Script names are case-sensitive,
Buildandbuildare different scripts descriptionis optional and only shows inxeq listdiris the path where the script will run, it can be an absolute or a relative pathoptionsare optional, see Script Options
Features
1. Script Options
Bake default behavior into a script so you don't have to pass flags every time:
[]
= ["quiet", "parallel"]
= ["cargo build", "cargo test"]
Now xeq run build always runs quietly and in parallel, no flags needed.
Available options: quiet, clear, parallel, continue_on_err, allow_recursion, summary
Toggling: CLI flags toggle script options. If a script has quiet baked in and you pass --quiet, it turns quiet off for that run.
2. Variables
Use a [vars] block to define reusable values. Reference them in commands with {{@varname}}:
[]
= "myapp:latest"
= "development"
[]
= ["docker build -t {{@image}} ."]
[]
= ["APP_ENV={{@env}} npm start"]
Local variables let a specific script override a global value:
[]
= "myapp:latest"
[]
= "myapp:build"
= ["docker build -t {{@image}} ."] # uses "myapp:build"
[]
= ["docker push {{@image}}"] # uses "myapp:latest"
Override at runtime using --args:
Resolution order, most specific wins:
--args (runtime) -> local vars (per script) -> global vars (file-level)
3. Arguments
For values that change every run, use positional placeholders {{1}}, {{2}}, etc.:
[]
= [
"npm create vite@latest {{1}} -- --template {{2}}",
"cd {{1}}",
"npm install"
]
# {{1}} = my-app
# {{2}} = react
Mix named and positional args in a single call:
4. Environment Variables
Reference system environment variables in commands using {{$VARNAME}}:
[]
= ["deploy --token {{$API_TOKEN}} --env {{$DEPLOY_ENV}}"]
xeq automatically loads a .env file from the current directory if one exists:
# .env
API_TOKEN=abc123
DEPLOY_ENV=production
Pass --no-env to skip loading the .env file.
5. Nested Scripts
A script can call other scripts using the xeq:// prefix:
[]
= ["npm install"]
[]
= ["npm run build"]
[]
= [
"xeq://install",
"xeq://build",
"npm run deploy"
]
Running xeq run deploy automatically runs install and build first, in order.
Circular dependency protection: xeq detects and exits on circular calls. Add
allow_recursiontooptionsor pass the--allow-recursionflag if you intentionally need this.
6. Parallel Execution
Run all commands in a script at the same time:
[]
= ["parallel"]
= [
"cargo test",
"cargo clippy",
"cargo fmt --check"
]
Scripts with
cdcommands orxeq://calls cannot run in parallel. Usexeq validateto catch this before running.
7. Global Configuration
xeq finds xeq.toml in your current directory automatically, no setup needed for project-level scripts.
For scripts you use across all your projects save a global file once and run it from anywhere:
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
Examples
The examples/ folder has ready-to-use TOML files for common workflows.
| File | Description | Key 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 stores your TOML file path using the system config directory
- Commands run through
sh -con Linux/macOS andcmd /Con Windows cdcommands update the working directory for all subsequent commands in that script- Variables resolve in order:
--args-> local vars -> global vars - Environment variables are loaded from
.envautomatically before any script runs - On failure, xeq exits with the same exit code as the failed command
- Script names are case-sensitive:
Buildandbuildare different scripts
Contributing
Contributions are welcome, whether it's a bug fix, a new feature, or an improvement to the docs. Open an issue.
Getting started:
Before submitting a PR:
- Run
cargo fmtto format your code - Run
cargo clippyand fix any warnings - Run
cargo testand make sure all tests pass - If you're adding a new feature, add tests for it
Project structure:
src/
main.rs # CLI parsing and command dispatch
config.rs # Path saving/loading and TOML reading
runner.rs # Script execution logic
types.rs # Shared types (Script, Scripts, Config, SavedPath)
macros.rs # log! and err! macros
validation.rs # Validation functions
examples/ # Ready-to-use TOML files
License
MIT - LICENSE