This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Cargo workspace of Rust crates for extending containerd (edition 2024, toolchain/MSRV pinned in rust-toolchain.toml):
shim-protos— TTRPC bindings for the shim APIs (generated from vendored.protofiles)shim— runtime v2 shim framework (Shimtrait, bootstrap/start/delete protocol, publisher, reaper, monitor)runc— wrapper around the runc CLIrunc-shim— the runc v2 shim binary, built ascontainerd-shim-runc-v2-rs(registered in containerd asio.containerd.runc.v2-rs)client— tonic gRPC bindings to containerd's APIssnapshots— remote snapshotter gRPC servicelogging— shim logger plugin helpers
protoc must be installed: build.rs in shim-protos, client and snapshots generates code from protos (scripts/install-protobuf.sh installs it in CI).
cargo build --release
cargo +nightly fmt --all # rustfmt.toml uses unstable options; stable fmt won't apply them
cargo clippy --all-targets -- -D warnings
cargo clippy --all-targets --all-features -- -D warnings
cargo test -p containerd-runc-shim <test_name> # single test
cargo test -p containerd-shim --features async
RUSTDOCFLAGS="--cfg docsrs -Dwarnings" cargo +nightly doc --no-depsPackage names differ from directory names: containerd-shim, containerd-shim-protos, containerd-client, containerd-snapshots, containerd-shim-logging, containerd-runc-shim, runc.
runc and containerd-shim each have a synchronous and an asynchronous module, selected by the async feature. They are mutually exclusive (#[cfg(not(feature = "async"))] gates the sync code), so --all-features never compiles the sync half, and because runc-shim enables async on both, a plain workspace build doesn't either. Check/clippy/test those crates on their own to cover the sync code, as CI does:
cargo clippy -p runc --all-targets -- -D warnings
cargo clippy -p containerd-shim --all-targets -- -D warnings
cargo test -p containerd-shimShared logic (e.g. runc io drivers) lives outside those two modules; changes there must compile under both feature sets.
- CI checks Linux gnu, Linux musl, and macOS. Code that is Linux-only (cgroups, mounts, eventfd, chown, etc.) must be
#[cfg(target_os = "linux")]-gated, and tests that depend on it too. - Windows only builds
containerd-shim,containerd-shim-protosandcontainerd-client. - Some tests need root (e.g.
runc-shimcgroup tests) andrunctests needXDG_RUNTIME_DIRset; CI runscargo testviasudo env HOME=... PATH=... XDG_RUNTIME_DIR=.... - containerd integration tests (containerd's Go suite run against
containerd-shim-runc-v2-rs) run only in CI (linux-integrationjob in.github/workflows/ci.yml), with a list of skipped tests there.
Other CI gates: cargo deny (deny.toml) and cargo-machete for unused dependencies — add a [package.metadata.cargo-machete] ignored entry when a dependency is used only indirectly.
Proto files are vendored under each crate's vendor/ directory. Don't edit them by hand: scripts/update-vendor.sh pulls a containerd release (version set in the script) and rsyncs the files listed in each crate's rsync.txt. Each crate's build.rs lists which protos get compiled; some modules are behind features (e.g. sandbox in shim-protos).
containerd-shimre-exports the sync or async API at the crate root depending on theasyncfeature (cfg_async!/cfg_not_async!macros inlib.rs). A shim implements theShimtrait and is started withrun::<T>(id, opts), which handles containerd's start/delete/bootstrap actions, the TTRPC server, event publishing back to containerd, and process reaping.runc-shimis async only.service.rsimplementsShim(start/delete/wait, and the exit-event loopprocess_exits);task.rsimplements the TTRPCTaskservice;container.rsholds a container's init and exec processes;processes.rsdefines the genericProcessTemplate<S>withProcessLifecycleimpls inrunc.rs(InitProcess/ExecProcess) that call into therunccrate. Console/pty handling is inconsole.rs; cgroup memory events incgroup_memory.rs.rustfmt.tomlgroups imports as std / external / crate and merges imports per crate; keep that layout when addingusestatements.