Rust
1. What's in the catalogue
One published line, 1.98.0, as two images — rustc and cargo — from catalogue 2026.35.22 (2026-08-25):
| Tool | Caps | Requires | Notes |
|---|---|---|---|
rustc | rw | binutils, cc | the compiler; rustdoc ships in the same image |
cargo | net, rw | — | builds and tests; ~/.cargo/registry is host-backed |
Both are published with rw at the index level — a build tool inherently produces output. (The cargo-rust-simple example predates that decision: its transcripts show --cap rw typed by hand, when cargo carried no index-level capability. On the current catalogue the flag is not needed.) Nothing declared-not-published here — no rustup, no clippy, no rustfmt are in the catalogue.
2. The five-minute version
kapsl rustc --version
rustc 1.98.0 (88d9e12ae 2026-08-18)
kapsl cargo --version
cargo 1.98.0
Build and run a scratch project (Cargo.toml + src/main.rs):
kapsl cargo build
Compiling hello v0.1.0 (/kapsl/workdir)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.58s
kapsl cargo run
Running `target/debug/hello`
Hello from Rust!
No flags: rw from the index, and a stdlib-only project fetches nothing, so no net is exercised either. A project with crates.io dependencies needs net for the first build (or a capabilities: [net] line in the project overlay); after that, the index declares a host-backed ~/.cargo/registry cache, so already-fetched crates are reused across builds — even across different projects.
3. The environment story: a measured ABI pin
Rust is a compiled language, and compiled languages have a problem interpreted ones don't: the binary you build has to run against a C library floor. The catalogue pins that floor per image with an [image.abi] section, and the rule is that the pin is measured, never declared: the index build measures the actual GLIBC/glibc requirements of the binaries in the image and records what they need, rather than trusting a manifest to say what they need. A declared pin can lie; a measured one cannot.
What a C extension needs, concretely: a compiler and binutils reachable by name. That is why rustc's index entry declares req = binutils, cc — the gcc and binutils images are composed into its container, so build.rs scripts that shell out to cc and link libc work without the project declaring anything. A crate that builds a C dependency (the common case: anything with a build.rs) gets that floor for free.
4. Tooling
No rustfmt or clippy in the catalogue. kapsl cargo fmt works only if the rustfmt component is in the image; the published 1.98.0 line's examples don't use it, so don't write CI against it until the component ships. The one tooling affordance the catalogue does carry for cargo is per-subcommand credential handling: the published entry mounts ~/.cargo/credentials.toml and passes CARGO_REGISTRY_TOKEN for the publish/yank/logout subcommands — visible in kapsl --info cargo.
The IDE use case covers editor integration; rust-analyzer talking to a workspace is the same pattern as the other languages — the workspace is mounted, the tool runs in its own image.
5. Project patterns
cargo-rust-simple— all three levels of integration,subcommand_index: 2(the program'sservesubcommand sits afterrun --), port 8090 published only for the serve path, the rustup-shim caveat, and the built-binary limitation below with its failing transcripts.cargo-project-config— the same shape as a pure project-config exercise, with aRUST_LOGtranscript proving the overlay grant reaches the real container invocation.
The overlay from cargo-rust-simple is the clearest demonstration of subcommand_index doing real work — the trust review even prints which index each line uses:
tools:
cargo:
capabilities: [rw]
subcommand_index: 2
subcommands:
serve:
ports: ["8090"]
args: ["--addr", "0.0.0.0:8090"] SECURITY .kapslrc declares a project overlay
cargo: +rw, port(serve@arg2) 8090, args(serve@arg2) --addr 0.0.0.0:8090
INPUT Apply this project's overlay?
[ y ] yes [ n ] no [ o ] once
kapsl cargo run -- serve publishes 8090; kapsl cargo build and kapsl cargo test get no port. A test suite has no business holding a published port.
6. Known limitations
-
The built binary doesn't run standalone, yet.
kapsl ./target/debug/hellovalidates the ELF and runs it against the minimal static base — and currently fails:kapsl ./target/debug/hello ./target/debug/hello: error while loading shared libraries: libgcc_s.so.1: cannot open shared object file: No such file or directoryThe cargo image is Ubuntu/glibc and does not set
+crt-static, so default builds are dynamically linked; the static base shipslibc6andlibmbut nolibgcc. The obvious workaround — static linking — also does not work today, because the toolchain has no staticgcc_eh. The example carries both failing transcripts. -
rustupcollisions.~/.local/bin/cargois very likely already a rustup shim;kapsl --install cargoremoves and replaces it, and rustup will not know that happened. If you use rustup for anything, prefer the project-overlay level, or shim a project-scoped alias name instead ofcargoitself. -
No formatter in the catalogue.
rustfmt/clippyare not published; don't write CI againstkapsl cargo fmtuntil they are.