{"id":51851211,"url":"https://github.com/lu-zero/portage-cli","last_synced_at":"2026-07-23T19:30:35.908Z","repository":{"id":358414160,"uuid":"1240546016","full_name":"lu-zero/portage-cli","owner":"lu-zero","description":"Command line tools for Gentoo","archived":false,"fork":false,"pushed_at":"2026-07-15T16:56:29.000Z","size":3990,"stargazers_count":4,"open_issues_count":4,"forks_count":1,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-07-15T18:26:17.596Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lu-zero.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE-MIT","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null},"funding":{"liberapay":"lu_zero","github":"lu-zero"}},"created_at":"2026-05-16T09:07:13.000Z","updated_at":"2026-07-15T16:57:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/lu-zero/portage-cli","commit_stats":null,"previous_names":["lu-zero/gentoo-cli","lu-zero/portage-cli"],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/lu-zero/portage-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lu-zero%2Fportage-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lu-zero%2Fportage-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lu-zero%2Fportage-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lu-zero%2Fportage-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lu-zero","download_url":"https://codeload.github.com/lu-zero/portage-cli/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lu-zero%2Fportage-cli/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35814999,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-07-20T02:08:10.276Z","status":"online","status_checked_at":"2026-07-23T02:00:06.683Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-07-23T19:30:35.411Z","updated_at":"2026-07-23T19:30:35.892Z","avatar_url":"https://github.com/lu-zero.png","language":"Rust","funding_links":["https://liberapay.com/lu_zero","https://github.com/sponsors/lu-zero"],"categories":[],"sub_categories":[],"readme":"# portage-cli\n\n[![LICENSE](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE-MIT)\n[![Build Status](https://github.com/lu-zero/portage-cli/workflows/CI/badge.svg)](https://github.com/lu-zero/portage-cli/actions?query=workflow:CI)\n[![dependency status](https://deps.rs/repo/github/lu-zero/portage-cli/status.svg)](https://deps.rs/repo/github/lu-zero/portage-cli)\n\nA Rust reimplementation of the Gentoo Portage command-line tools, built on a\nfamily of purpose-built crates for parsing atoms, metadata, repositories, and\nthe installed package database.\n\n\u003e **Note**: For a more mature Rust-based alternative, see\n\u003e [Pkgcraft](https://pkgcraft.github.io/).\n\n\u003e **Warning**: This codebase is currently mainly slop-coded and has not yet been\n\u003e thoroughly audited, some crates are already polished up to a degree and perform\n\u003e correctly. Use at your own risk.\n\n\u003e **Pre-release git checkout**: This is development source from `git` before the\n\u003e first release of `portage-cli` / the `em` binary on crates.io. The Applet status\n\u003e table below (and the per-crate \"Published\" vs \"Local only\" table) documents the\n\u003e current implementation state. See the warning above.\n\n## The `em` binary\n\n`em` is a unified front-end for the Portage tool suite. It dispatches to\nsubcommands corresponding to the traditional tools.\n\n### Applet status\n\n| Applet | Maps to | Status |\n|--------|---------|--------|\n| `atom` | — | Working |\n| `query` | `equery` | Partial — see below |\n| `use` | `euse` | Partial — see below |\n| `maint` | `emaint` | Partial — see below |\n| `regen` | `emerge --regen` | Working |\n| `search` | `emerge --search` | Working |\n| *(default)* | `emerge` | Working — resolve → build loop; `-uD` in-slot upgrades; `--prefix` / multi-root |\n| `ebuild` | `ebuild` | Working — fetch, unpack, phases, merge, VDB registration |\n| `depclean` | `emerge --depclean` | Working — reverse-dep orphan clean (`-c`); world-aware |\n| `quickpkg` | `quickpkg` | Working — GPKG from installed files / VDB `CONTENTS`; skips `CONFIG_PROTECT` by default |\n| `mirror` | `emirrordist` | Stub |\n| `clean` | `eclean` | Stub |\n| `revdep` | `revdep-rebuild` | Stub |\n| `news` | `eselect news` | Stub |\n| `glsa` | `glsa-check` | Stub |\n| `log` | `genlop` | Stub |\n| `grep` | `egreplite` | Stub |\n| `select` | `eselect` | Partial — `profile`, `repository`, `compiler`, `binutils`, `linker`, `clang`, … |\n| `crossdev` | `crossdev` | Working — cross sysroot + staged toolchain bootstrap (`--target`) |\n| `toolchain` | — | Working — native self-hosting toolchain bootstrap into `--root` |\n| `dispatch` | `dispatch-conf` | Stub |\n| `etc` | `etc-update` | Stub |\n| `env` | `env-update` | Working — `profile.env` + `ld.so.conf` from `etc/env.d` |\n\n---\n\n### `em query` (equery)\n\n| Subcommand | Alias | Status |\n|---|---|---|\n| `belongs` | `b` | Working — file → owning package via VDB CONTENTS |\n| `check` | `k` | Working — MD5 checksum + mtime verification |\n| `depends` | `d` | Working — reverse-dep search in metadata cache |\n| `depgraph` | `g` | Working — full dep tree via PubGrub solver, portage-compatible output |\n| `files` | `f` | Working — all files installed by a package |\n| `has` | `a` | Working — VDB field search across installed packages |\n| `hasuse` | `h` | Working — packages with a given USE flag in IUSE |\n| `keywords` | `y` | Working — keyword status across architectures |\n| `list` | `l` | Working — available packages; `-I` for installed only |\n| `meta` | `m` | Working — maintainers, homepage, longdesc, installed info |\n| `size` | `s` | Working — installed size + build timestamp |\n| `uses` | `u` | Working — IUSE flags with descriptions + installed status |\n| `which` | `w` | Working — path to best matching ebuild |\n\n**`em query depgraph` / default resolve feature summary:**\n\n- **VDB awareness** — installed packages use `InstalledPolicy::Favor` (keep satisfying versions); already-installed exact CPVs are filtered from the merge list; installed-and-kept packages expand runtime deps only\n- **`-uD` / `--update --deep`** — transitive **in-slot upgrades** (`prefer_update`); host-satisfied build tools still enter the graph so they can upgrade (emerge deep-update). `-u` alone does not mass-upgrade deps; `-D` alone still bumps `:*` slots (`prefer_newest_slot`). See `todo/deep-in-slot-upgrades.md`\n- **`-N` / `--newuse` and `-U` / `--changed-use`** — same-CPV rebuild when planned USE/IUSE differs from the VDB (`todo/newuse.md`); with `-uD`, prefer newest when USE drift forces a rebuild\n- **Profile USE flags** — `make.defaults` / `make.conf` through brush with portage-style incremental USE stacking (see `docs/architecture.md`)\n- **USE_EXPAND** — `PYTHON_TARGETS`, `CPU_FLAGS_*`, `ABI_X86`, etc. expanded and grouped in output\n- **OR-group branch selection** — prefer branches whose USE deps are already satisfied (avoids gratuitous rebuilds)\n- **Post-solve USE-dep rebuilds** — violated USE deps on installed packages force rebuild / `upgrade_to` fixpoint (not full `--newuse`)\n- **Action tags** — `N` new, `NS` new slot, `U` upgrade (`[old_ver]`), `D` downgrade, `R` reinstall\n- **Preserve-libs** — NEEDED.ELF.2–driven orphan library keep/reclaim (parallel install-image ELF scan)\n- **Cycle handling** — soft edges broken after SCC / Kahn order rather than silently dropping packages\n\n**Performance** (AmpereOne aarch64, warm cache, hyperfine 2026-07-18; exit 1 ignored when the plan needs config changes):\n\n| Target / mode | `emerge` | `em` |\n|---------------|---------:|-----:|\n| `www-client/firefox` `-p` | ~3.65 s | **~1.4 s** |\n| `www-client/firefox` `-uDp` | ~6.3 s | **~1.45 s** (plan size ≈ emerge) |\n| `app-office/libreoffice` `-p` | ~4.0 s | **~1.75 s** |\n\nOlder micro-tables (sub-second depgraph on lighter hosts) live in\n[`benchmarks/BENCHMARKS.md`](./benchmarks/BENCHMARKS.md). Metadata cache regen\nand install-image ELF scan benches are also there (`benchmarks/bench-elfscan.sh`).\n\n**Gaps vs `emerge`:**\n- Shallow `-p` package-set can still differ slightly from emerge on some hosts (emerge may list extra BDEPEND upgrades without `-u`); `-uDp` / `-uNDp` are near-parity on firefox-class targets\n- Wrapper packages for old-slot BDEPEND (`autoconf-wrapper`, `gcc-config`, …) not fully modelled\n- Flag ordering / `(-flag)` USE_EXPAND_IMPLICIT display polish\n- Upgrade display shows full USE rather than only changed flags\n\n**Gaps vs equery:**\n- `uses` descriptions come from `profiles/use.desc` + `profiles/use.local.desc`.\n  Overlay packages not yet regen'd fall back to empty description (metadata.xml\n  per-package lookup is not yet wired as a fallback).\n- No `stats` subcommand.\n\n---\n\n### `em use` (euse)\n\n| Flag | Status |\n|---|---|\n| `-a FLAG` | Working — add USE flag to `make.conf` |\n| `-r FLAG` | Working — remove USE flag from `make.conf` |\n| *(no flags)* | Working — print current USE value |\n| `--make-conf PATH` | Working — override make.conf path |\n\n**Gaps vs euse:**\n- No `-p pkg` for package-specific USE flags (`/etc/portage/package.use`).\n- `MakeConf::get()` itself still returns the raw unexpanded value (e.g.\n  `${COMMON_FLAGS}` stays literal); `em use`'s own display doesn't call the\n  newer `MakeConf::apply_to()` evaluator (used by the binpkg build-env-key\n  path — see [`docs/binhost.md`](./docs/binhost.md)) to expand it yet.\n\n---\n\n### `em maint` (emaint)\n\n| Subcommand | Status | Notes |\n|---|---|---|\n| `world` | Working | Checks `world` + `world_sets`; validates `@set` refs against known sets from `/usr/share/portage/config/sets/`, `/etc/portage/sets.conf`, and `/etc/portage/sets/`; `--fix` rewrites both files |\n| `revisions` | Working | Purges `repo_revisions` JSON (sync commit history); optional per-repo targeting |\n| `moveinst` | Partial | Detects packages needing rename from `profiles/updates/`; does not apply moves or scan installed dependency metadata |\n| `regen` | Working | Available as `em regen` |\n\n**Gaps vs emaint:**\n\n- `moveinst` — missing the second pass that walks every installed package's\n  `DEPEND`/`RDEPEND`/etc. fields for stale atom references, and the `--fix`\n  mode that writes to the VDB.\n- `world` — `@set` references are validated by name but not by content (e.g.\n  `@preserved-rebuild` is accepted as long as the name is known).\n- `all`, `binhost`, `cleanconfmem`, `cleanresume`, `logs`, `merges`,\n  `movebin`, `sync` — not implemented.\n\n---\n\n## Cross-compilation \u0026 toolchains\n\n`em` understands the multi-root model (`docs/root-model.md`): a build reads its\nconfig from one root (`--config-root`) and installs into another (`--root`),\nwith build tools resolved against the host (`BROOT`). On top of that it can\nbootstrap toolchains and assemble stages.\n\n- **`em --target \u003ctuple\u003e crossdev --init-target`** lays down a cross sysroot + overlay\n  (a `crossdev` workalike); **`--setup`** then runs the staged\n  `binutils → headers → gcc-stage1 → libc → gcc-stage2` bootstrap into\n  `/usr/\u003ctuple\u003e`. Validated end-to-end for `riscv64-unknown-linux-gnu`.\n- **`em toolchain --setup --root \u003cdir\u003e`** bootstraps a *native* self-hosting\n  toolchain (`CHOST == CBUILD`) into an empty root —\n  `baselayout → binutils → os-headers → glibc → gcc`. Unlike cross there is no\n  two-stage gcc: the host (seed) compiler builds full glibc directly and a single\n  full gcc links against it. Verified: a fully automated run produces a\n  `gcc-16.1` in the root that compiles and links a working binary against the\n  root's own libc.\n\nThe native toolchain and the cross bootstrap share one staged driver\n(`crossdev::stages`), differing only in atom naming and how the `glibc ↔ gcc`\ncycle is broken. Stage *production* (stage1 `packages.build`, stage3\n`--emptytree @system`) is the next layer — see `todo/em-stages-and-binhosts.md`.\n\n---\n\n## Binary packages \u0026 binhosts\n\n`-b`/`-B` build GLEP 78 binary packages, `-k`/`-K` reuse them locally, `-g`/`-G`\nfetch them from a configured binhost. Binpkgs are keyed by CPV + USE∩IUSE +\nCHOST + an ISA/ABI-derived build-env key, so cross-compilation host tools and\nsame-CHOST, different-`-march` board variants never get mixed up. `em maint\nbinpkg {verify,list,prune,fingerprint}` covers maintenance (no real `emaint`\nequivalent exists for this). See [`docs/binhost.md`](./docs/binhost.md) for\nthe identity model and PKGDIR/automation recipes.\n\n---\n\n## Architecture\n\nSee [`docs/architecture.md`](./docs/architecture.md) for the full crate\ndependency graph, per-crate API catalog, and design reference.\n\n### Crate family\n\n| Crate | Purpose | Status |\n|-------|---------|--------|\n| `gentoo-interner` | String interning | Published |\n| `gentoo-core` | Architecture and variant types | Published |\n| `gentoo-stages` | Stage3 tarball fetch/cache | Published |\n| `portage-atom` | PMS atom parser (`Cpn`, `Cpv`, `Dep`, `Version`) | Published |\n| `portage-metadata` | md5-cache entry parser, EAPI, phases, keywords | Published |\n| `portage-solver` | Solver-agnostic trait and shared vocabulary | Published |\n| `portage-atom-pubgrub` | PubGrub solver bridge (default in `em`) | Published |\n| `portage-atom-resolvo` | SAT dependency solver (resolvo bridge) | Published |\n| `portage-vdb` | Installed package database (`/var/db/pkg`) | Published |\n| `portage-binpkg` | GPKG binary package read/write | Published |\n| `portage-repo` | Repo layout, profiles, metadata cache, ebuild sourcing | Local only |\n| `portage-distfiles` | Distfile fetch and mirror resolution | Local only |\n| `portage-cli` | The `em` binary | Local only |\n| `portage-bench` | Benchmark harness (`benchmarks/`) | Local only |\n\nFurther reading: [`docs/architecture.md`](./docs/architecture.md),\n[`docs/build-roadmap.md`](./docs/build-roadmap.md),\n[`docs/benchmarks.md`](./docs/benchmarks.md),\n[`docs/binhost.md`](./docs/binhost.md) (binary packages, identity model, recipes),\n[`todo/PENDING.md`](./todo/PENDING.md) (stage/binhost arc),\n[`todo/deep-in-slot-upgrades.md`](./todo/deep-in-slot-upgrades.md) (`-uD`),\n[`todo/newuse.md`](./todo/newuse.md) (`-N` still open).\n\n### brush integration\n\n`portage-repo` embeds [brush](https://github.com/lu-zero/brush) (the\n`for-portage-repo` fork branch) — a Rust bash interpreter — for ebuild\nsourcing and `make.conf` parsing. Additions to the fork:\n\n- `Program.comments: Vec\u003cSourceSpan\u003e` — comment spans from the winnow parser,\n  used by `MakeConf` for byte-precise round-trip editing.\n- `ParseContext.comments` accumulator and comment-tracking whitespace parsers\n  (`spaces_tracking`, `linebreak_tracking`, `newline_list_tracking`).\n\n## Installation\n\n```bash\ncargo install --path portage-cli\n```\n\n## Local Development\n\nThe project expects sibling checkouts:\n\n```\nportage-cli/    # this workspace\nbrush/          # brush fork at for-portage-repo branch\n```\n\nThe `.cargo/config.toml` at workspace root patches the brush crates to use the\nlocal checkout.\n\n```bash\ncargo build\ncargo test --workspace --exclude portage-bench\ncargo clippy --workspace --exclude portage-bench -- -D warnings\ncargo fmt --all -- --check\ncargo msrv verify --rust-version 1.95 --path portage-cli\n```\n\n## License\n\n[MIT](LICENSE-MIT)\n\n## Contributing\n\nSee [AGENTS.md](./AGENTS.md) for project conventions (Conventional Commits,\nstyle, checks).\n\n## Author\n\nLuca Barbato \u003clu_zero@gentoo.org\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flu-zero%2Fportage-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flu-zero%2Fportage-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flu-zero%2Fportage-cli/lists"}