# 🚀 Runx
### Universal Project Launcher with Portable Runtimes
Run projects with reproducible, isolated runtimes — no global installations, no shell integration.
[](https://github.com/aryankahar31/runx/actions/workflows/ci.yml)
[](https://github.com/aryankahar31/runx/releases)
[](LICENSE)
[](https://www.rust-lang.org/)
[](https://github.com/aryankahar31/runx)
**🌐 [runx-cli.vercel.app](https://runx-cli.vercel.app/)**
```text
$ runx dev
No runx.toml found — detected from project files:
node 20.11.0 (from .nvmrc)
Installing node 20.11.0
Downloading https://nodejs.org/dist/v20.11.0/node-v20.11.0-linux-x64.tar.xz
✓ Checksum verified
Running `npm run dev`
```
Second run — everything is already cached:
```text
$ runx dev
No runx.toml found — detected from project files:
node 20.11.0 (from .nvmrc)
Using cached node 20.11.0 at /home/user/.runx/runtimes/node/20.11.0
Running `npm run dev`
```
---
## Contents
- [Why Runx?](#why-runx)
- [What Runx is not](#what-runx-is-not)
- [Quick Start](#quick-start)
- [Features](#features)
- [Supported Runtimes](#supported-runtimes)
- [Zero-Config Detection](#zero-config-detection)
- [Runtime Resolution](#runtime-resolution)
- [Lockfiles](#lockfiles)
- [Security](#security)
- [Comparison](#comparison)
- [Benchmarks](#benchmarks)
- [Architecture](#architecture)
- [CLI Reference](#cli-reference)
- [Roadmap](#roadmap)
- [Documentation](#documentation)
---
## Why Runx?
Modern projects pin runtime versions per project; your machine has one global `PATH`. Runx closes that gap:
- **No global runtime installations** — runtimes live in a local cache (`~/.runx`), not in your system
- **Project-driven detection** — reads `.nvmrc`, `package.json` `engines`, `pyproject.toml`, `go.mod`, Bun/Deno version files that your project *already* declares
- **Isolated execution** — each command runs with exactly the declared runtime versions on its child `PATH`
- **Multi-runtime projects** — Node + Python + Go in one project? All resolved and placed on one `PATH`
- **Reproducible environments** — exact pins resolve offline; ranges resolve to the newest matching release; `runx.lock` freezes both
- **Editor-independent** — works the same from any terminal, any editor, any CI runner
## What Runx is not
Runx is not an IDE, build system, or language-specific package manager. It provisions and isolates the runtimes your project's commands run with — nothing more.
- VS Code / any editor → terminal or task runner → `runx dev` → node/python/go/bun/deno → your app
- Android Studio → Gradle / Android SDK → (optionally) runx providing the underlying JVM/Node runtime
If your workflow needs full IDE tooling, build orchestration, or platform-specific SDKs, those tools still own that job. Runx's job is narrower: resolve, verify, cache, isolate, and run the exact runtime version a project declares.
## Quick Start
Install (macOS / Linux):
```bash
curl -fsSL https://raw.githubusercontent.com/aryankahar31/runx/main/install.sh | sh
```
> Behind a network that blocks Fastly (`raw.githubusercontent.com`)? Use the jsDelivr mirror:
> `curl -fsSL https://cdn.jsdelivr.net/gh/aryankahar31/runx@main/install.sh | sh`
Windows PowerShell:
```powershell
iwr https://raw.githubusercontent.com/aryankahar31/runx/main/install.ps1 | iex
```
Both scripts verify the downloaded binary against its published SHA-256 checksum before installing — see [Security](#security).
Initialize a project:
```bash
runx init
```
This creates a starter `runx.toml`:
```toml
[runtimes]
node = "20.11.0"
python = "3.11.7"
[run]
dev = "npm run dev"
build = "npm run build"
test = "npm test"
```
Run:
```bash
runx dev
```
Or skip `runx.toml` entirely — if your project already has a `.nvmrc`, `pyproject.toml`, or similar, just run `runx dev` ([detection rules](#zero-config-detection)).
## Features
### Runtime management
- Node.js, Python, Bun, Go, Deno
- Automatic downloads with retry, exponential backoff and **resume**
- Semver/range resolution to the newest matching release
- Shared runtime cache across all projects
### Reproducibility & security
- [`runx.lock`](docs/lockfile.md) pins resolved versions for CI and teams
- A recorded platform artifact's digest **becomes the install's integrity constraint**: locked installs verify against `runx.lock` itself, so upstream mutations of a published release fail instead of flowing through
- `--locked` fails on anything the lockfile doesn't pin
- SHA-256 verification of every download, plus Sigstore/cosign signatures since v0.4.2
- Atomic installs — an interrupted download can never corrupt the cache
### Developer experience
- Zero-config auto-detection (every `package.json` script becomes a run command), or explicit `runx.toml`
- No shell integration required, ever — nothing happens until you type `runx`
- Cross-platform: Linux, macOS, Windows
- Scripting modes: `--json`, `--quiet`, `--offline`
- `runx doctor` (plus `doctor --verify`, an integrity sweep over cached executables), cache management (`list`/`size`/`clean`/`prune`), `self update`, shell completions
## Supported Runtimes
| Runtime | Status |
|----------|--------|
| Node.js | ✅ |
| Python | ✅ |
| Bun | ✅ |
| Go | ✅ |
| Deno | ✅ |
| Java | 🚧 Planned |
| .NET | 🚧 Planned |
## Zero-Config Detection
Runx automatically detects runtimes from files your project already uses — `.nvmrc`, `.python-version`, `pyproject.toml`, `Pipfile`, `package.json` `engines`, `go.mod`, and Bun/Deno version files. Multiple runtimes are detected together and share one isolated environment, and every script in `package.json` becomes a run command (`runx dev`, `runx test`, `runx build`, …) without any configuration.
Detection never writes to disk and never merges with an existing `runx.toml`; explicit configuration always wins.
**[View full detection rules →](docs/zero-config.md)**
## Runtime Resolution
Ranges (`>=20`, `^20`, `~20.11`) resolve against each vendor's own release index to the newest matching release; exact pins (`20.11.0`) never touch the network and never change. Resolution results are cached for at most 6 hours — there is no third-party registry in the path.
**[View resolution internals & registry freshness →](docs/runtime-resolution.md)**
## Lockfiles
```bash
runx lock
```
Installs the declared runtimes and writes `runx.lock`, pinning the exact resolved version (with per-platform checksums) so every machine and CI runner gets identical runtimes. Enforce it with `runx run --locked`.
**[View lockfile format & CI usage →](docs/lockfile.md)**
## Security
Every install is verified before it touches your disk:
- SHA-256 checksum verification of every download, before extraction
- Locked installs verify against `runx.lock` itself: a recorded platform artifact's digest is the integrity constraint, not the vendor's live checksum document
- Sigstore/cosign keyless signature verification on release archives (opt-in strict mode via `RUNX_REQUIRE_SIGNATURE=1`)
- Atomic installs into staging directories — a failed or interrupted install leaves nothing behind
- Every install records a digest of the runtime's entry-point binary; `runx doctor --verify` detects replaced or corrupted cached executables
- Strict validation of every version string at a single chokepoint (path-traversal safe by construction)
- Installers fail closed when no checksum tool is available
**[Read the full security model →](docs/security.md)**
## Comparison
What runx combines in one editor-independent workflow:
| Capability | Runx |
| :--- | :---: |
| Project launcher | ✅ |
| Multiple runtimes per project | ✅ |
| Zero-config detection from existing files | ✅ |
| Isolated child `PATH` | ✅ |
| No shell integration required | ✅ |
| Lockfile with per-platform checksums | ✅ |
Traditional version managers (nvm, Volta, pyenv, asdf, mise) each cover parts of this list differently — several require shell hooks or shims, and none read `package.json` `engines` / `pyproject.toml` directly today. Runx does not claim to reinvent runtime management; its focus is combining provisioning, detection, isolation, verification, and execution into one workflow.
**[View the detailed per-tool comparison →](docs/comparison.md)**
## Benchmarks
Headline numbers on warm cache (macOS, Apple silicon, zsh — full method in [docs/benchmarks.md](docs/benchmarks.md)):
| Measurement | Mean |
| :-- | --: |
| Complete `runx ` run, warm cache | 5.9 ms |
| Runx overhead before your command starts | ~0.2 ms, **once per invocation** |
| Shell-hook alternative (`mise activate`) | +15.2 ms **per prompt render** |
Because runx adds no shell hook, prompts without `runx` pay nothing at all.
**[View full benchmark methodology →](docs/benchmarks.md)**
## Architecture
```text
runx
│
▼
Parse runx.toml / detect project files
│
▼
Resolve runtime versions
│
▼
Check local cache ─── hit ──┐
│ miss │
▼ │
Download + verify │
(atoms: staging → rename) │
└──────────────────────────┘
│
▼
Build isolated PATH
│
▼
Execute project command
```
Runtimes are cached under `~/.runx/runtimes///` and reused across all projects.
**[View isolation guarantees & implementation notes →](docs/architecture.md)**
## CLI Reference
```bash
runx dev # run a key from [run] (any non-builtin word works)
runx build # same — detected projects expose every package.json script
runx test --locked # enforce the lockfile
runx init # create a starter runx.toml
runx lock # write runx.lock
runx doctor # diagnose cache, PATH and detection issues
runx doctor --verify # also hash each runtime against its install-time digest
runx cache list # also: size, clean, prune (--older-than N)
runx self update # verified atomic binary swap
runx completions zsh # bash, zsh, fish, powershell
runx --json doctor # machine-readable output (also: cache list/size)
runx --quiet dev # suppress banners and progress bars
runx --offline dev # refuse any network access; cached/pinned only
```
Global flags work before any subcommand (`runx --json `).
Pass arguments through with `--`: `runx dev -- --port 3000`. Without `--`, extra arguments are rejected rather than silently dropped.
### Environment variables
| Variable | Effect |
|----------|--------|
| `RUNX_HOME` | Cache location (default `~/.runx`). Useful for CI caching and isolation. |
| `HTTP_PROXY` / `HTTPS_PROXY` / `ALL_PROXY` | Proxy for all outbound requests. Precedence follows curl; TLS and checksum verification are unchanged by proxying. |
| `NO_PROXY` | Comma-separated hosts that bypass the proxy (`*` disables it entirely). Loopback always bypasses. |
| `RUNX_RESOLUTION` | `latest` (default) or `minimum` — see [strict mode](docs/runtime-resolution.md#strict-mode). |
| `GITHUB_TOKEN` | Optional. Raises GitHub API rate limits for Bun/Deno/Python lookups (60 → 5000 req/hour). Sent only to `api.github.com`. |
| `RUNX_REQUIRE_SIGNATURE` | `1` makes a missing cosign signature an error instead of a warning. |
There is no telemetry, and runx makes no network requests beyond fetching runtime release metadata, archives, and their checksums.
## Roadmap
**Current** (v0.5)
- Node.js, Python, Bun, Go, Deno
- `runx.lock` + `--locked`, Sigstore/cosign signing
- Cache management, `doctor`, `self update`, completions
- Multi-runtime detection and isolated multi-runtime `PATH`
**Next**
- Java, .NET
- Monorepo / workspace support
- Pre/post run hooks
**Future**
- Plugin system and runtime registry
- VS Code extension
- Homebrew, Scoop, Winget, Chocolatey
- Stable API
## Documentation
- [Website](https://runx-cli.vercel.app/) — overview, quick start, benchmarks
- [Zero-Config Detection](docs/zero-config.md) — every detected file, priority order, inference rules
- [Runtime Resolution](docs/runtime-resolution.md) — range semantics, strict mode, registry freshness
- [Lockfiles](docs/lockfile.md) — format, platform artifacts, CI enforcement
- [Security](docs/security.md) — verification model, manual release verification
- [Architecture](docs/architecture.md) — isolation guarantees, atomic installs
- [Benchmarks](docs/benchmarks.md) — shell-overhead methodology, freshness checks
- [Comparison](docs/comparison.md) — per-tool matrix vs nvm/Volta/pyenv/asdf/mise
---
## Contributing
Contributions are welcome. Please ensure:
- Runtime installers remain portable
- Downloads are deterministic
- Existing tests continue to pass; new features include tests
- Documentation is updated
```bash
git clone https://github.com/aryankahar31/runx.git && cd runx
cargo test # full suite
cargo build --release # produce target/release/runx
```
## License
MIT — see the [LICENSE](LICENSE) file.
⭐ **If Runx helped you, consider giving the repository a star!**