|
| 1 | +# AGENTS.md |
| 2 | + |
| 3 | +This file provides guidance to agents when working with code in this repository. |
| 4 | + |
| 5 | +## Build and Test |
| 6 | + |
| 7 | +```bash |
| 8 | +zig build # debug build |
| 9 | +zig build -Doptimize=ReleaseSmall # optimized, <1MB |
| 10 | +zig build test # run all tests |
| 11 | +``` |
| 12 | + |
| 13 | +Zig 0.15+ required. This is Zig 0.15 which uses newer APIs (`std.Io.Writer.Allocating`, `std.Io.Reader.fixed`, `std.compress.zstd.Decompress`). Don't use `std.io.getStdOut()` — it doesn't exist in 0.15. For stdout output, use `std.posix.write(std.posix.STDOUT_FILENO, ...)`. |
| 14 | + |
| 15 | +## Architecture |
| 16 | + |
| 17 | +Onyx is a package manager with two install paths: **registry packages** (resolved via Onyx registry, fetched from the Nix binary cache) and **third-party packages** (GitHub/domain sources with `onyx.toml` manifests, installed directly). |
| 18 | + |
| 19 | +### Source files |
| 20 | + |
| 21 | +- **main.zig** — CLI entry point, all command implementations (`cmdInstall`, `cmdExec`, `cmdUninstall`, `cmdUse`, `cmdGc`, `cmdUpgrade`, `cmdInit`, `cmdImplode`) |
| 22 | +- **cli.zig** — argument parsing, `PackageRef` (name@version), `Command` union |
| 23 | +- **resolver.zig** — registry alias resolution, Nixhub API calls, index caching with TTL |
| 24 | +- **fetcher.zig** — NAR closure fetching, parallel download (thread pool), hash verification |
| 25 | +- **source.zig** — third-party package resolution (GitHub, domain), TOML manifest parsing, meta tag discovery |
| 26 | +- **store.zig** — `Database` struct: state.json load/save, version management, symlink install/remove |
| 27 | +- **nar.zig** — NAR archive format unpacker (regular files, directories, symlinks) |
| 28 | +- **ui.zig** — output functions. Data output (`print`, `ok`, `pkg`, `listPackage`) goes to stdout. Errors/warnings (`err`, `warn`, `status`, `dim`) go to stderr. |
| 29 | +- **xdg.zig** — XDG paths (`~/.local/share/onyx/`, `~/.cache/onyx/`, `~/.local/bin/`) |
| 30 | + |
| 31 | +### Two install paths |
| 32 | + |
| 33 | +**Nix path**: `resolveAlias` (registry index) → `resolve` (Nixhub API) → `fetchClosure` (cache.nixos.org, parallel NARs) → unpack to `/nix/store/` → symlink to `~/.local/bin/` |
| 34 | + |
| 35 | +**Third-party path**: `resolveGithub`/`resolveDomain` → download binary/tarball → install to `~/.local/share/onyx/packages/{name}/{version}/` → symlink to `~/.local/bin/` |
| 36 | + |
| 37 | +Both paths store state in `~/.local/share/onyx/state.json` and create symlinks in `~/.local/bin/`. |
| 38 | + |
| 39 | +### Key patterns |
| 40 | + |
| 41 | +- **Locking**: `acquireLock`/`releaseLock` via file lock on `~/.local/share/onyx/lock`. Commands that mutate state (`install`, `uninstall`, `use`, `gc`, `upgrade`) must hold the lock. `cmdInstall` wraps `cmdInstallInner` to avoid recursive lock acquisition when installing dependencies. |
| 42 | +- **Alias resolution**: `resolveAlias` checks `~/.cache/onyx/index.json`. Fast commands (`exec`, `use`, `list`) use cached index forever. Slow commands (`install`, `upgrade`) refresh if >1 day old via `resolveAliasFresh`. |
| 43 | +- **Ephemeral packages**: `exec` auto-installs packages marked `ephemeral: true` with `last_used` timestamp. These are hidden from `list` and cleaned by `gc` after 30 days. |
| 44 | +- **Symlink ownership**: `removeSymlinks` uses `readLink` to verify the symlink points to `/nix/store/` or `/onyx/packages/` before deleting — never removes files owned by other tools. |
| 45 | +- **exec fast path**: `cmdExec` checks state.json first. If the package is already installed, it skips all network calls and directly `execv`s into the binary. |
| 46 | + |
| 47 | +### Registry |
| 48 | + |
| 49 | +The registry lives on the `registry/v0` branch. `index.json` maps aliases (e.g., `nodejs` → nixpkgs attribute). Per-package `.toml` files contain cleanup metadata (paths to delete on uninstall, extracted from Homebrew). |
0 commit comments