chi is a lightweight, high-performance CLI tool for downloading and vendoring external dependencies for the Odin programming language.
It is built with minimalism and integrity in mind:
- No Central Registry: The internet (Git) is the source of truth.
- Zero Magic: No background daemons or hidden state. Everything is explicit.
- Odin-First: Configuration is written in pure Odin syntax (
chi.odin). - Reproducible: Uses BLAKE2b content hashing to verify vendored files haven't been tampered with. (p.s I'd like to switch to BLAKE3 when Odin has it in its core package).
Download from Releases:
# Linux (amd64)
curl -L https://github.com/pmbanugo/odin-chi/releases/latest/download/chi-linux-amd64 -o chi
chmod +x chi
# Linux (arm64)
curl -L https://github.com/pmbanugo/odin-chi/releases/latest/download/chi-linux-arm64 -o chi
chmod +x chi
# macOS (Apple Silicon)
curl -L https://github.com/pmbanugo/odin-chi/releases/latest/download/chi-darwin-arm64 -o chi
chmod +x chi
# macOS (Intel)
curl -L https://github.com/pmbanugo/odin-chi/releases/latest/download/chi-darwin-amd64 -o chi
chmod +x chi
# Windows (amd64)
curl -L https://github.com/pmbanugo/odin-chi/releases/latest/download/chi-windows-amd64 -o chi.exeCheck Releases for additional architectures.
git clone https://github.com/pmbanugo/odin-chi
cd odin-chi
odin build src/ -out:chiRun the test suite using Odin's built-in test runner:
odin test src/ -all-packagesRun specific tests:
# Test utility functions
odin test src/ -all-packages -define:ODIN_TEST_NAMES=main.test_url_to_dir_name,main.test_url_to_pkg_name
# Test manifest parsing
odin test src/ -all-packages -define:ODIN_TEST_NAMES=main.test_write_and_read_manifest
# Test hashing
odin test src/ -all-packages -define:ODIN_TEST_NAMES=main.test_hash_directory,main.test_verify_hashThe test suite includes:
- Unit tests for utility functions, manifest parsing, and hashing
- Uses
core:testingwith memory tracking enabled - Tests are designed to be isolated, repeatable, and automatable
In your project root, run:
chi initThis creates a chi.odin manifest file. The manifest is written in pure Odin code so it can be integrated directly into your build scripts if desired.
Add a dependency by providing its Git URL. By default, chi fetches the latest commit (HEAD):
chi add github.com/laytan/odin-httpYou can optionally pin to a specific branch, tag, or commit hash:
chi add github.com/laytan/odin-http v0.0.1
chi add github.com/laytan/odin-http 534ff16fe4ee697dDownload dependencies to the global cache (~/.cache/chi):
chi fetchPopulate the local vendor/ directory from the cache:
chi vendorNote:
chi vendorautomatically verifies the BLAKE2b hash of the downloaded content against the hash stored inchi.odin. If the content was tampered with (e.g., via a force-pushed commit), vendoring will fail.
Update an existing dependency to its latest commit:
chi update odin-httpRemove a dependency from the manifest and delete its vendor/ directory:
chi remove odin-httpView all dependencies in your manifest:
chi listAt any time, you can verify that your local vendored files match the exact hashes recorded in your chi.odin manifest:
chi checkIf you've modified files inside vendor/, you can generate .patch files to preserve your local changes across dependency updates:
chi patchPatches are saved to patches/<name>.patch as unified diffs. When you run chi vendor, existing patches are automatically re-applied after vendoring. You can also apply them manually with patch -p0 < patches/<name>.patch.
Use the --fork flag to temporarily override a dependency with a local directory for development or debugging:
chi vendor --fork=odin-http:/path/to/local/odin-httpThis copies files from the local path instead of the cache, and is not persisted in the manifest. Hash checks are skipped for forked dependencies when running chi check.
The manifest file generated and managed by chi looks like this:
package deps
Dependencies :: map[string]Dependency{
"odin-http" = {
url = "github.com/laytan/odin-http",
commit = "734920b8c4fe298dd162109e080e6fc92d1aad6a",
hash = "blake2b-f7b1842...",
},
}
Dependency :: struct {
url: string,
commit: string,
hash: string,
path: string, // Local override path
}If you are developing a dependency locally, you can temporarily override the network fetch by manually adding a path property to your chi.odin entry:
"odin-http" = {
url = "github.com/laytan/odin-http",
commit = "734920b8...",
hash = "blake2b-f7b1842...",
path = "../local/my-odin-http-fork",
},When you run chi vendor, it will copy files entirely from your local path, ignoring the remote repository and skips the integrity check for that specific dependency.