Metadata-Version: 2.5
Name: mojox
Version: 0.6.0
Summary: CLI and execution layer for Mojo build tooling
Project-URL: Repository, https://github.com/Conobi/mojox
Author: Conobi
License-Expression: MIT
Requires-Python: >=3.10
Requires-Dist: mojo-compiler
Requires-Dist: mojox-core<0.7,>=0.6
Description-Content-Type: text/markdown

# mojox

CLI and execution layer for Mojo build tooling.

`mojox` reads your `pyproject.toml` manifest (via `mojox-core`), discovers targets, builds an execution plan, and runs `mojo` commands with structured output. It handles profile resolution, local settings (`.mojox/config.toml`), diagnostic formatting, and a compiled-binary cache so unchanged tests and programs are not rebuilt.

## Install

```bash
uv add mojox "mojo-compiler==1.0.0"    # in a project
uv tool install mojox                      # globally
```

## Subcommands

### `test`

Run test targets (dev profile by default). Each test file is built to a binary, then executed.

```bash
mojox test                                    # all test targets
mojox test -k "parse" tests/unit/             # filter by name + path
mojox test --output-format json               # NDJSON to stdout (CI)
mojox test --no-fail-fast                     # run all tests even after failures
mojox test --failure-output final             # show failing output after all tests
mojox test --bundle -k "parse"                # one harness binary, filter test functions
mojox test --examples                         # also compile-check examples/*/main.mojo
```

Test-specific flags:

| Flag | Default | Description |
|------|---------|-------------|
| `--output-format {human,json}` | `human` | Output format; `json` emits NDJSON to stdout |
| `--fail-fast` / `--no-fail-fast` | `--fail-fast` | Stop after first failure |
| `--success-output {immediate,final,never}` | `never` | When to show passing test output |
| `--failure-output {immediate,final,never}` | `immediate` | When to show failing test output |
| `-k` / `--filter PATTERN` | | Filter tests by name (case-insensitive substring); see `--bundle` |
| `--bundle` | off | Compile every `test_*` function into a single harness binary |
| `--examples` | off | Also compile-check `examples/*/main.mojo` |
| `--no-cache` | off | Always rebuild; cached test binaries are left untouched, precompiled packages are rebuilt in place and lose their cache entry |
| `paths` (positional) | | Filter tests by file or directory prefix |

Examples are not checked unless you pass `--examples` or a path under `examples/`. They are compiled, never executed.

With `--bundle`, test files without `test_*` functions are left out of the bundle (with a note on stderr), and `-k` matches test function names inside the harness at runtime. Without it, `-k` matches test file paths.

#### Binary cache

Build outputs live under `.mojox/cache/`: test binaries in `bin/`, their cache keys in `meta/`, example builds in `examples/`. A test is rebuilt only when its key changes. The key covers the test source, the project's library and test trees, the dependency include dirs (file size and mtime, not content), the compiler flags, the build environment and the compiler. `mojox cache clean` deletes `.mojox/cache/`.

Precompiled library packages (`.mojox/build/pkg/`) are cached too, by `test`, `build` and `check` alike: a lib is precompiled again only when its sources, the dependency include dirs, the precompile arguments, the environment or the compiler change, or when its package is missing.

Add `.mojox/` to your `.gitignore`.

### `run`

Build a single `.mojo` file, then execute the binary (dev profile by default).

```bash
mojox run src/main.mojo
mojox run --no-cache src/main.mojo            # always rebuild
```

The binary goes through the same `.mojox/cache/bin` cache as `mojox test`, so a second run of an unchanged file skips the build. Editing the file, a sibling module or a dependency triggers a rebuild. Output is captured and replayed once the program exits, not streamed. `--timeout` (or the profile's timeout) covers the build and the run.

Exit code: the program's own code; `128 + N` if it is killed by signal `N`; `1` if the build fails (compiler crash included) or the timeout is hit.

### `build`

Compile binary targets (release profile by default).

```bash
mojox build
```

### `check`

Validate the manifest, run lints, and compile library packages when a compiler is available (manifest-only otherwise). Exits 1 on a compile failure, 2 on an invalid manifest.

```bash
mojox check
```

### `metadata`

Output the build plan as JSON.

```bash
mojox metadata
```

### `cache clean`

Delete `.mojox/cache/` (cached binaries and their metadata). Safe to run when there is no cache.

```bash
mojox cache clean
```

## Common flags

These flags are available on every subcommand except `cache`:

| Flag | Description |
|------|-------------|
| `--profile PROFILE` | Build profile (`dev`, `release`, or user-defined) |
| `-j` / `--jobs N` | Maximum concurrent compilations |
| `--timeout SECONDS` | Per-target timeout |
| `--dry-run` | Show planned commands without executing |
| `-v` / `--verbose` | Expand grouped output |
| `--no-config` | Disable `.mojox/config.toml` discovery |
| `--config-file PATH` | Explicit config file path |
| `-D` / `--define KEY=VALUE` | Define a compile-time variable (repeatable) |
| `--flag VALUE` | Extra flag passed through to the compiler (repeatable; use `--flag=VALUE` for dash-prefixed flags) |

## How it works

1. Parses `pyproject.toml` via `mojox-core` (manifest model layer)
2. Reads `.mojox/config.toml` local settings, if present (TOCTOU-safe via `openat`)
3. Resolves policy: profile, defines, flags, CLI overrides
4. Discovers targets and builds a plan (pure -- returns commands as data)
5. Executes the plan: runs `mojo` commands, collects outcomes, formats output
6. For tests and `run`, builds each file to a binary (reusing a cached one when its key matches), then executes it

## Exit codes

`mojox test`:

| Code | Meaning |
|------|---------|
| `0` | Success |
| `1` | Test failure(s), including a test file that fails to build |
| `2` | Library or example compilation failure, or configuration error |
| `130` | Interrupted (Ctrl+C) |

`mojox run`:

| Code | Meaning |
|------|---------|
| any | The program's own exit code |
| `128 + N` | The program was killed by signal `N` |
| `1` | Build failure or timeout |
| `2` | Toolchain not found |

## See also

- [`mojox-core`](../mojox-core/) -- manifest parsing, target discovery, and build planning (pure model layer)
- [`mojox-build`](../mojox-build/) -- PEP 517 build backend for packaging Mojo libraries as wheels

## License

MIT
