xeq 2.0.0

Run sequences of commands from a TOML file with a single word
xeq-2.0.0 is not a library.

xeq

Crates.io Downloads License Build Rust

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.

xeq run setup


Table of Contents


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. No extra setup needed.

Create a xeq.toml file with xeq init and xeq creates one for you.


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

cargo install xeq


Commands

xeq init

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

xeq init


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.

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 -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 list

xeq list --global


xeq validate

Checks all scripts in your TOML file for errors without running anything.

xeq validate

xeq validate --global

Catches:

  • Nested xeq:// calls pointing to scripts that don't exist
  • parallel option combined with cd or xeq://
  • Undefined {{@vars}} not defined in vars (warns, doesn't fail)
  • Circular dependencies between scripts
  • dir paths that don't exist

xeq config [path]

Saves a TOML file path globally. See Global Configuration.

xeq config ~/my-scripts/xeq.toml   # save the path

xeq config                          # open the saved file in your default editor


TOML Format

A xeq.toml file contains named scripts. Each script needs at least a run array:

[my-script]

description = "What this script does"

dir = "./my_app"

options = ["quiet"]

run = [

    "command one",

    "command two"

]

  • Script names are case-sensitive, Build and build are different scripts
  • description is optional and only shows in xeq list
  • dir is the path where the script will run, it can be an absolute or a relative path
  • options are optional, see Script Options

Features

1. Script Options

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

[build]

options = ["quiet", "parallel"]

run = ["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.

xeq run build          # quiet ON  (from TOML)

xeq run build --quiet  # quiet OFF (toggled by CLI flag)


2. Variables

Use a [vars] block to define reusable values. Reference them in commands with {{@varname}}:

[vars]

image = "myapp:latest"

env = "development"



[build]

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



[start]

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

Local variables let a specific script override a global value:

[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 using --args:

xeq run build --args image=myapp:hotfix

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.:

[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 in a single call:

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


4. Environment Variables

Reference system environment variables in commands using {{$VARNAME}}:

[deploy]

run = ["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
xeq run deploy   # API_TOKEN and DEPLOY_ENV loaded automatically

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


5. Nested Scripts

A script can call other scripts 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 automatically runs install and build first, in order.

Circular dependency protection: xeq detects and exits on circular calls. Add allow_recursion to options or pass the --allow-recursion flag if you intentionally need this.


6. Parallel Execution

Run all commands in a script at the same time:

[check]

options = ["parallel"]

run = [

    "cargo test",

    "cargo clippy",

    "cargo fmt --check"

]

xeq run check      # all three run at the same time

xeq run check -p   # same using CLI flag

Scripts with cd commands or xeq:// calls cannot run in parallel. Use xeq validate to 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:

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

xeq run git-cleanup --global        # run from any directory

xeq list --global                   # see all global scripts

8. Run Summary

Pass --summary to see every command and how long it took:

xeq run build --summary

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 -c on Linux/macOS and cmd /C on Windows
  • cd commands 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 .env automatically before any script runs
  • On failure, xeq exits with the same exit code as the failed command
  • Script names are case-sensitive: Build and build are 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:

git clone https://github.com/opmr0/xeq

cd xeq

cargo build

cargo test

Before submitting a PR:

  • Run cargo fmt to format your code
  • Run cargo clippy and fix any warnings
  • Run cargo test and 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