codex-rs/package-manager/README.md
codex-package-manager is the shared installer used for versioned runtime bundles and other cached artifacts in codex-rs.
It owns the generic parts of package installation:
.zip and .tar.gzPackage-specific code stays behind the ManagedPackage trait.
The package manager is intentionally small:
ManagedPackage implementation describes how to fetch a manifest, choose an archive for a PackagePlatform, and load a validated installed package from disk.PackageManager::resolve_cached() returns a cached install for the current platform if load_installed() succeeds and the version matches.PackageManager::ensure_installed() acquires a per-install lock, downloads the archive into a staging directory, extracts it, validates the staged package, and promotes it into the cache.The default cache root is:
<codex_home>/<default_cache_root_relative>
Callers can override that root with PackageManagerConfig::with_cache_root(...).
The trait is small, but the invariants matter:
install_dir() should be unique per package version and platform. If two versions or two platforms share a directory, promotion and cleanup become unsafe.load_installed() must fully validate the installed package, not just deserialize a manifest. resolve_cached() trusts a successful load as a valid cache hit.detect_extracted_root() looks for manifest.json at the extraction root or inside a single top-level directory. Override it if your package layout differs.archive_url() should be derived from manifest data, not recomputed from unrelated caller state, so manifest selection and download stay aligned.resolve_cached() only answers "is it already present?" while ensure_installed() is the bootstrap path.PackageManagerConfig.load_installed() when debugging. The generic manager treats failed cache loads as cache misses today..zip extraction rejects entries that escape the extraction root and preserves Unix executable bits when the archive carries them..tar.gz extraction rejects symlinks, hard links, sparse files, device files, and FIFOs. Only regular files and directories are promoted.size_bytes is enforced when present in the manifest.Typical usage looks like this:
let config = PackageManagerConfig::new(codex_home, MyPackage::new(...));
let manager = PackageManager::new(config);
let package = manager.ensure_installed().await?;
In practice, most packages should expose their own small wrapper config/manager types over the generic crate so the rest of the codebase does not depend on ManagedPackage details directly.