Read this in other languages:
English •
Español
The power of an orchestrator, the speed of an executor. Built in Rust.
axes is a high-performance task-workflow orchestrator that unifies complex, polyglot projects under a simple, consistent, and ultra-fast command-line interface. It acts as an abstraction layer over your existing tools—from npm and docker to other task runners—providing a universal command language for your entire ecosystem.
As projects grow, the number and variety of commands needed to operate them explode. This "command fragmentation" creates constant friction:
- Inconsistent Commands: In this part of the monorepo, do we use
npm test,pytest,cargo test, orgo test ./...? - Environment Management: Which virtual environment (
venv,nvm) needs to be activated? Which.envfile needs to be loaded? - Fragile Scripts: Relying on
bashorPowerShellscripts for business logic and argument parsing is a maintenance nightmare that is not portable across operating systems.
This constant cognitive load breaks workflow and slows down teams. Simple task runners offer shortcuts, but they don't solve the underlying orchestration problem. axes is designed to solve it from the root.
For years, developers have faced a false dilemma: use a simple, fast runner, or a powerful but slow orchestrator. axes eliminates this compromise.
Our architecture is engineered not just for speed, but for scalability. axes maintains elite performance and minimal resource usage even as project complexity grows, a domain where other tools falter. The following benchmarks, executed on Linux (WSL2), demonstrate this principle.
As the number of commands in a script increases, the architectural advantages of axes become clear.
| Benchmark Scenario | Tool | Time (Mean) | Peak Memory |
|---|---|---|---|
| Low Load | make |
~1.9 ms | ~2.4 MB |
| (100 commands) | axes |
~3.6 ms | ~4.6 MB |
task |
~21.5 ms | ~20.4 MB | |
just |
~38.4 ms | ~4.5 MB | |
| ――――――――― | ―― | ―――――― | ―――――― |
| Medium Load | axes |
~4.1 ms | ~5.5 MB |
| (1k commands) | make |
~4.5 ms | ~2.7 MB |
just |
~42.2 ms | ~6.1 MB | |
task |
~58.8 ms | ~27.5 MB | |
| ――――――――― | ―― | ―――――― | ―――――― |
| High Load | axes |
~10.5 ms | ~10.0 MB |
| (10k commands) | just |
~73.9 ms | ~23.1 MB |
make |
~172.8 ms | ~5.9 MB | |
task |
~740.2 ms | ~107.6 MB | |
| ――――――――― | ―― | ―――――― | ―――――― |
| Stress Test | axes |
~79.6 ms | ~57.6 MB |
| (100k commands) | axes(divided) |
~54.0 ms | ~56.2 MB |
just |
~359.1 ms | ~190.7 MB | |
make |
TLE (>90s) | ~37.6 MB | |
task |
TLE (>90s) | ~903.1 MB |
Note: "
axes(divided)" means that the scripts were split, 50k for itself and 50k for its first ancestor. This demonstrates that the more you divide tasks among superior parent projects, the better the speed will be.
TLE: Time Limit Exceeded. The tool failed to complete the benchmark in a reasonable time.
Benchmarks executed with hyperfine and /usr/bin/time -v on Linux (WSL2 on Windows 11, i7-1165G7, 16GB RAM).
Full methodology and results are in our BENCHMARKS.md.
The data reveals a clear architectural advantage:
- Scalability: While
makeis fastest for trivial tasks, its performance degrades exponentially with complexity.axesexhibits near-linear scaling, making it dramatically faster and the only reliable option for large-scale orchestration. - Memory Efficiency:
axesis exceptionally lightweight. In the most demanding test, it uses 3.3x less memory thanjustand a staggering 15.7x less memory thantask, which consumes nearly a gigabyte of RAM before failing.
This level of performance is the direct result of an architecture obsessed with efficiency:
- Ahead-of-Time (AOT) Compilation to a Universal AST: Your
axes.tomlfiles are compiled once into a platform-agnostic binary cache. - Just-in-Time (JIT) Optimized Execution: Subsequent runs deserialize the cache and perform an ultra-fast, in-memory specialization for your OS, eliminating parsing and decision-making overhead from the hot path.
The result is an engineering guarantee: you get scalable performance and best-in-class memory efficiency, no matter how complex your workflows become.
- ⚙️ In-depth Architecture Analysis (
TECHNICAL.md): For those interested in the engineering behind our performance.
axes is built on a foundation that simple tools ignore.
Projects do not live in isolation; they have relationships. axes allows you to organize your projects into a logical tree, where children inherit and can override their parents' configuration (scripts, variables, environment).
graph TD
A(global) --> B(my-app);
B --> C(api);
B --> D(web);
C --> E(db-migrator);
style A fill:#333,stroke:#888,stroke-width:2px,color:#fff
style B fill:#4a90e2,stroke:#333,stroke-width:2px,color:#fff
style C fill:#50e3c2,stroke:#333,stroke-width:2px,color:#fff
style D fill:#50e3c2,stroke:#333,stroke-width:2px,color:#fff
style E fill:#f5a623,stroke:#333,stroke-width:2px,color:#fff
A deploy script defined in my-app is available to api and web, but db-migrator can have its own specialized version.
Your scripts become first-class command-line applications, complete with documentation, parameters, defaults, and validation—all declared in your axes.toml.
# in .axes/toml
[scripts]
# 1. Required positional parameter.
test = "pytest --env <params::0(required)>"
# 2. Named parameter with a default value and value-only mapping.
build = "docker build . -t my-app:<params::tag(alias='-t', map='', default='latest')>"
# 3. Multiline script with a required, quoted positional parameter and an optional branch.
push = [
"git add .",
"git commit <params::0(map='-m ', required, literal)>",
"git push origin <params::branch(alias='-b', map='', default='main')>"
]# --- Script: test ---
axes test production # -> Executes: pytest --env production
axes test # -> ERROR: Positional argument at index 0 is required.
# --- Script: build ---
axes build # -> Executes: docker build . -t my-app:latest
axes build --tag v1.2.0 # -> Executes: docker build . -t my-app:v1.2.0
axes build -t v1.2.0 # -> Executes: docker build . -t my-app:v1.2.0
# --- Script: push ---
axes push "New feature" # Executes 'git push origin main' (uses default branch)
axes push "Fix bug" -b fix # Executes 'git push origin fix' (uses branch alias)
axes push # ERROR: Positional argument at index 0 (commit message) is required.Say goodbye to fragile bash scripts for parsing arguments.
axes identifies projects by an immutable UUID, not a volatile file path. Rename or move your project directories freely—axes will never lose track of your projects. This makes refactoring large monorepos trivial and safe.
Run a script in the current directory. The syntax is simple and predictable.
# Executes the 'build' script defined in the nearest axes.toml
$ axes build --release
# Executes the 'test' script in a specific sub-project.
$ axes my-app/api/testDefine constants as variables and reuse them in your scripts.
[vars]
host = "http://localhost:8080" # Defined once.
[scripts.browse]
desc = "Opens local documentation in the browser."
windows = "start <vars::host>" # Reuses the variable.
macos = "open <vars::host>"
linux = "xdg-open <vars::host>"Execute commands and use their output instantly as variables.
[scripts]
# Tags a Docker image with the current short git hash
tag_release = "docker tag my-app:latest my-app:<run('git rev-parse --short HEAD')>"Dive into a sub-project. axes sets up and tears down your environment for you.
# in my-app/api/.axes/axes.toml
[options]
at_start = "source .venv/bin/activate" # Executes upon entering the session.
at_exit = "docker-compose down" # Executes upon exiting.$ axes my-app/api start # Starts a session. `at_start` executes automatically.
(axes: my-app/api) $ axes test # You no longer need to repeat the context.
(axes: my-app/api) $ exit # `at_exit` executes upon exit.Your development environment, on demand.
Imagine a monorepo with a Python backend (Poetry) and a React frontend (npm). axes unifies the development experience.
Project Structure:
mi-monorepo/
├── web/ (React App)
│ ├── ...
│ └── .axes/axes.toml
├── api/ (Python/FastAPI App)
│ ├── ...
│ └── .axes/axes.toml
└── .axes/axes.toml (Root/Inherited Config)mi-monorepo/.axes/axes.toml (Root)
[vars]
DOCKER_REGISTRY = "registry.my-company.com"
APP_NAME = "mi-monorepo"
[scripts]
# A 'lint' script that delegates execution in parallel and silent mode.
lint = [
"@> axes web/lint",
"@> axes api/lint",
]mi-monorepo/api/.axes/axes.toml (Backend)
[scripts]
lint = "poetry run ruff check ."
run = "poetry run uvicorn app.main:app --reload"
build = "docker build . -t <vars::DOCKER_REGISTRY>/<vars::APP_NAME>-api:latest"mi-monorepo/web/.axes/axes.toml (Frontend)
[scripts]
lint = "npm run lint"
run = "npm run dev"
build = "docker build . -t <vars::DOCKER_REGISTRY>/<vars::APP_NAME>-web:latest"The axes lint command, run from the root, will now run the linters of both sub-projects simultaneously, showing only the output of the linters themselves.
axes gives you granular control over how each command is executed using simple prefixes:
-
# Message...: Comment/Print. Prints the text to the console instead of executing it. Perfect for showing status messages. -
@ <command>: Silent Mode. The command is executed, butaxeswill not print the command itself to the console. Useful for cleanup tasks or noisy scripts.@ rm -rf ./cache
-
- <command>: Ignore Errors. If the command fails (non-zero exit code),axeswill continue with the next command in the script instead of stopping.- docker stop old-container
-
> <command>: Parallel Execution. Groups this command with subsequent>commands into a batch that runs concurrently.axeswaits for the entire batch to finish before moving on.
[scripts.test-all]
run = [
"# --- Starting all tests in parallel ---",
"> axes api/test",
"> axes web/test",
"> axes integration run test", # Explicit way to run 'test' in `integration` project.
"# --- All tests completed ---"
]Modifiers can be combined in any order (e.g., @- or ->@) for powerful, precise orchestration.
The Unified Workflow:
axes lint: From the root, runs linting on both sub-projects in parallel.axes api/run: Starts only the API server.axes web/build: Builds only the frontend's Docker image, using global variables.
axes creates a cohesive language over a set of heterogeneous tools, making the development experience predictable and simple, no matter the stack's complexity.
axes is a single, dependency-free binary engineered for architectural confidence. The same high-performance experience is guaranteed on Windows, macOS, and Linux.
- Download: Go to the
axesReleases page and grab the binary for your system. - Place in PATH: Extract the executable and move it to a directory in your system's
PATH. - Verify: Open a new terminal and run
axes --version.
Our unique AOT + JIT architecture produces a platform-agnostic binary cache. This means your team can commit the .axes-cache directory to version control. If a developer on Windows compiles the configuration, their teammates on macOS and Linux will instantly benefit from "hot" executions, skipping the initial compilation cost.
axes is engineered with architectural confidence thanks to its Rust foundation and its unique caching system.
-
Engineering Guarantee: The core logic, the AST Compiler, and the execution engine are designed to be platform-agnostic. The superior speed you get from the AOT (Ahead-of-Time) Compilation is consistent across all operating systems.
-
Team Collaboration Feature:
axescreates an optimized binary cache that can be shared across different operating systems (e.g., via a network drive or a shared project folder). If one developer compiles the workflow on Windows, another developer on Linux instantly benefits from the Hot Execution Path, skipping the costly initial parsing.
We continuously test and improve the experience on all platforms. If you encounter any platform-specific issues, please Open an Issue.
The friction you feel every day is not a requirement. It is a problem with a solution. axes is that solution.
- ➡️ Quick Start Guide (
GETTING_STARTED.md): Build your first orchestrated monorepo in 15 minutes. - 📖 Mastering
axes.toml(AXES_TOML_GUIDE.md): The definitive reference for every feature and syntax. - ⌨️ Command Reference (
COMMANDS.md): A complete guide to all CLI commands (init,register,tree, etc.).
axes is more than a tool; it is an open-source project dedicated to restoring control, consistency, and performance to development. Your voice and support are crucial.
- Find a Bug or Have a Great Idea: Open an Issue. We value every piece of feedback.
- Want to Contribute Code?: Pull Requests are always welcome. Check out our Contribution Guidelines to get started.
We are obsessed with performance, robustness, and an excellent developer experience. Your financial support allows us to dedicate time and resources to maintain this level of excellence and accelerate our roadmap.
Funds are used directly for:
- Compensating core developers for their dedication to maintenance and new feature development.
- Covering CI/CD infrastructure costs, including the future addition of macOS and Linux runners.
- Prioritizing major architectural features, such as artifact caching.
Every contribution, from a symbolic thank-you to corporate sponsorship, is essential fuel for our development engine.
➡️ Support us on Open Collective
(We are in the process of applying for GitHub Sponsors. Thank you for making axes possible!)
Install axes today. Stop remembering commands. Start building.
