xeq
Run sequences of shell commands with a single word.
Define your commands once in a TOML file. Run them from anywhere, on any OS, without rewriting them every time.
Table of Contents
- Why xeq?
- Installation
- Quick Start
- Commands
- TOML File Format
- Features
- How It Works
- Examples
- Roadmap
- Contributing
- License
Why xeq?
Every project has a setup ritual — install dependencies, build, run tests, configure things. You either memorize the steps, paste them from a notes file, or write a shell script that only works on your machine.
xeq gives you a better option. Write your commands in a xeq.toml file, commit it to your repo, and anyone on the team can run the exact same steps with one command — on Linux, macOS, or Windows.
Installation
macOS / Linux
|
Windows (PowerShell)
iwr https://raw.githubusercontent.com/opmr0/xeq/main/install.ps1 -UseBasicParsing | iex
Via cargo
Quick Start
1. Create a xeq.toml in your project:
[]
= [
"npm install",
"npm run build"
]
[]
= ["npm run dev"]
2. Tell xeq where the file is (one time only):
3. Run any script by name:
That's it. xeq remembers the file path — you don't need to pass it every time.
Commands
xeq config [path]
Point xeq at your TOML file. This is saved globally so you only need to do it once per project (or when you move the file).
xeq run <script> [flags]
Run a script from your TOML file. Commands in the script run one at a time in order. If a command fails, xeq stops — unless you use --continue-on-err.
Available flags:
| Flag | Short | Description |
|---|---|---|
--continue-on-err |
-C |
Keep going even if a command fails |
--quiet |
-q |
Hide xeq's own log messages, only show command output |
--clear |
-c |
Clear the terminal before each command |
--parallel |
-p |
Run all commands at the same time instead of one by one |
--allow-recursion |
Let a script call itself (disabled by default to prevent infinite loops) | |
--args <values...> |
-a |
Pass arguments into the script |
xeq list
Show all scripts in your TOML file along with their commands and options.
build runs: --- options: ["quiet", "parallel"]
cargo fmt
cargo clippy
cargo build --release
TOML File Format
A xeq.toml file is a list of named scripts. Each script has a run array of shell commands:
[]
= [
"command one",
"command two",
"command three"
]
Scripts are case-sensitive. You can define as many as you want in a single file.
Features
Script Options
Scripts can have default options baked in, so you don't have to pass flags every time. Add an options array to any script:
[]
= ["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
Toggling: CLI flags toggle options. If quiet is set in TOML and you pass --quiet on the CLI, it turns quiet off for that run. This lets you override script defaults without editing the file.
Nested Scripts
Call other scripts from within a script using the xeq:// prefix:
[]
= ["npm install"]
[]
= ["npm run build"]
[]
= [
"xeq://install", # runs the install script first
"xeq://build", # then the build script
"npm run deploy" # then this command
]
Running xeq run deploy automatically runs install and build first.
Circular dependency protection: xeq tracks which scripts are currently running. If a script tries to call itself (directly or through a chain), xeq exits with an error. Pass
--allow-recursionor add it tooptionsif you intentionally want recursive behavior.
Arguments
Reference arguments in commands using {{1}}, {{2}}, etc., then pass them with --args:
[]
= [
"npm create vite@latest {{1}} -- --template react",
"cd {{1}}",
"npm install"
]
This creates a new Vite project called my-app, changes into it, and installs dependencies.
If a script uses
{{placeholders}}but no--argsare provided, xeq exits with an error instead of passing the raw placeholder to the shell.
Parallel Execution
Run all commands in a script simultaneously instead of one by one:
[]
= ["parallel"]
= [
"cargo test",
"cargo clippy",
"cargo fmt --check"
]
Note: In parallel mode,
cdcommands andxeq://calls are skipped — only plain shell commands are spawned as parallel threads.
How It Works
- xeq stores your TOML file path globally 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- On failure, xeq exits with the same exit code as the failed command
- Script names are case-sensitive:
Buildandbuildare different scripts
Examples
The examples/ folder has ready-to-use TOML files for common workflows:
| File | What it does |
|---|---|
react-tailwind.toml |
Scaffold a React + Tailwind CSS project |
nextjs.toml |
Set up a Next.js project with TypeScript |
rust-project.toml |
Format, lint, test, and release a Rust project |
docker-app.toml |
Start, stop, rebuild, and tail logs for Docker Compose |
git-workflow.toml |
Sync, push, and stash/pop git operations |
scripts-nesting.toml |
Example of calling scripts from within 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, SavedPath)
macros.rs # log! and err! macros
examples/ # Ready-to-use TOML files
If you're unsure whether a change fits the project, open an issue first to discuss it before writing code.
License
MIT — LICENSE