rkat-rpc download. This page is for
everyone else: people who run cargo install rkat, embed the crates in their
own binary, build inside a container, or need to know where the prebuilt
binaries will and will not run. Every number below was measured against this
repository; the memory and time figures come from one cold build described in
Build Cost.
What A Build Compiles
The workspace has ~50 member crates. Its lockfile resolves ~670 package entries (~600 distinct crates) for the whole workspace with every feature, dev-dependency, and optional backend enabled. A default-featurecargo install rkat compiles ~380 crates.
Most of those are ordinary. The cost is concentrated in a few very large
first-party crates, each of which is one rustc and LLVM invocation:
These four, plus the final
rkat crate that pulls the whole surface into one
binary, dominate both wall time and peak memory. The optional consumer
profiles below therefore focus on job limits and per-package opt-level
pins rather than only the dependency count; they are not the current Windows
release recipe.
Toolchain and native requirements:
- The repository pins Rust
1.94.1inrust-toolchain.toml;make install-build-depsinstalls exactly that toolchain into a checkout. The published crates declarerust-version = "1.94.0", socargo install rkatneeds Rust 1.94 or newer. - The default feature set needs a C compiler and libc headers (bundled SQLite
and a few other C sources compile through the
cccrate) and nothing else. TLS isrustls; no OpenSSL development package is required and the release gate rejects binaries that link one. cmakeis needed only by the optionallive-webrtcfeature of themeerkatfacade andmeerkat-rpccrates (meerkat-livewebrtc, bundled Opus throughaudiopus_sys).rkathas no such feature, and no shipped binary enables it by default, so acargo installof any of them never compiles it.
Build Cost
Two cold builds, measured for this page:opt-level = 1 globally,
opt-level = 0 for meerkat-machine-schema), with the same job count so the
per-crate peaks are comparable. Peaks were sampled once per second from ps.
How to translate that to your host:
- The largest single crate is the floor, and only
opt-level = 0moves it. Even withCARGO_BUILD_JOBS=1, the build needs as much memory as its biggestrustcprocess. In both runs above that wasmeerkat-mobat ~11 GiB: going fromopt-level = 3to1halved the aggregate peak, therkatcrate, andmeerkat-machine-schema, but leftmeerkat-mobwhere it was. A third run (the samerkatbuild with the low-memory profile plusmeerkat-mobpinned toopt-level = 0) broughtmeerkat-mobdown to ~6.3 GiB, after which the largest process ismeerkat-runtimeat ~7.4 GiB. Below that, the levers are the feature set (use--no-default-featuresand omitmob,rpc-surface, and the CLIopenai-livefeature to avoid their mob dependencies in a reduced production build), swap, and prebuilt binaries. See Features for scope and limits. - Aggregate memory scales with the job count. Cargo runs up to one
rustcper core. The aggregate peaks above happened while four or five large first-party crates were compiling at once; withNjobs, budget for theNlargest crates that can be in flight together.meerkat-mob,meerkat-runtime, andmeerkat-machine-schemadid overlap in the default build, and that overlap produced its peak. - Wall time scales with cores only up to the serial tail. The hundreds of
small dependencies compile in parallel in the first few minutes, but the
large first-party crates depend on each other, and the final
rkatcrate compiled alone for roughly the last third of the wall time. A 4-core cloud VM should expect a few times the wall time above, and the tail does not shrink with more cores.cargo installalso has no warm cache to reuse, so every install is a cold build. - Disk is transient for
cargo install. The temporary target directory is deleted after the binary is installed, but it must fit while the build runs. A checkout that keeps itstarget/needs the full figure per profile.
.github/workflows/release.yml, build_binaries_windows_cross runs on
ubuntu-latest and invokes .github/actions/build-windows-cross/action.yml.
That action uses cargo-xwin with clang-cl, lld-link, and the Windows SDK to
cross-compile the four surface binaries and package their ZIP archives. It
adds an 8 GiB swap file when total swap is below 8 GiB; it does not set
CARGO_BUILD_JOBS=2 or inject the per-package optimization pins shown below.
The subsequent verify_windows_binaries job runs on windows-latest,
extracts the archives, executes each binary’s --version, and checks
rkat --help; it does not compile them natively. These workflow settings are
not new wall-time or memory measurements. Continuous integration
(.github/workflows/ci.yml) uses BuildBuddy for its broad lane and hosted
Linux for the required dense Mob topology stress; release binaries are
produced by the separate release workflow.
Rough sizing, derived from the peaks above:
Lowering Memory
Where profile settings come from
Cargo reads[profile.*] tables only from the root manifest of the build it
is running. Two consequences matter here:
- The Meerkat workspace ships no
[profile.release], so its own release builds run at Cargo’s defaults (opt-level = 3,codegen-units = 16,lto = false,debug = false) except where a lane injects pins. - Even if it did, that would not reach you.
cargo install rkatunpacks the publishedrkatcrate as the root of its own temporary workspace; the repository’s rootCargo.tomlis not part of that crate. A downstream binary that depends onmeerkat = "=0.8.32"is likewise governed by its own root manifest, never by Meerkat’s.
cargo install honors Cargo configuration
from a .cargo/config.toml in the directory you run it from (or
~/.cargo/config.toml), from CARGO_PROFILE_RELEASE_* environment variables,
and from --config on the command line. This was verified for this page with
cargo install -v: with CARGO_PROFILE_RELEASE_OPT_LEVEL=1 set, rustc
receives -C opt-level=1. Library embedders put the same tables in their own
root Cargo.toml.
Low-memory profile
meerkat-mob (~11.5 GiB at opt-level = 1, ~6.3 GiB
at 0); it trades CPU on the orchestration path for memory, so measure your
workload before shipping a binary built this way:
opt-level line and keeping these pins.
This is a consumer profile choice, not the current Windows release recipe:
--config; repeat the flag with
profile.release.package.meerkat-mob.opt-level=0 for the small-host pin.
What each lever does
CARGO_BUILD_JOBS(or-j) caps the number of concurrentrustcprocesses. Aggregate memory is the sum of the compilers running at once, so this is the first lever on any memory-limited host. Wall time rises roughly in proportion.opt-level: going from3to1removes most of LLVM’s expensive passes. Measured on the crates whose peak is in LLVM, it halved therkatcrate (~10.1 to ~4.8 GiB) and, together with theopt-level = 0pin,meerkat-machine-schema(~9.4 to ~4.8 GiB), and it cut the whole build’s wall time from ~25 min 29 s to ~19 min 6 s. It did not movemeerkat-mob; onlyopt-level = 0did (~11.5 to ~6.3 GiB). The runtime cost of1is modest for an agent host that spends its time waiting on network I/O.opt-level = 0is free formeerkat-machine-schemabecause it is a generated catalog, not hot code; onmeerkat-mobit is a real trade.codegen-units: LLVM optimizes a crate’s codegen units in parallel, bounded by your core count, so a crate split into 16 units can hold 16 LLVM contexts at once. Lowering it reduces that per-crate parallelism at the cost of a longer compile for that crate, andcodegen-units = 1also widens inlining scope, which can raise memory for the largest crates. Measure on your host before changing it; the release lane leaves it at 16.lto: leave it at the defaultfalse."thin"or"fat"LTO pulls the whole dependency graph into one optimization pass at link time and multiplies link-stage memory.- Features:
crates/meerkat-cli/Cargo.tomllists the subsystems behindrkat’s default features (mob,rpc-surface,openai-realtime,comms,schedule,workgraph,mcp,skills, storage backends, providers). A narrower--no-default-features --features ...production build can remove the mob graph only if it omitsmoband all transitive enablers, includingrpc-surface(which selectsmeerkat-rpc/mob) and the CLIopenai-livefeature (which selectsmob). Omitting just the directmobfeature while keepingrpc-surfacestill buildsmeerkat-mobandmeerkat-mob-mcp. The repository’s surface feature matrix (scripts/run-surface-feature-matrix, behindmake test-feature-matrix-surface) keeps three reducedrkatcombinations compiling:--no-default-features --features session-store,session-store,mcp, andsession-store,comms,mcp,workgraph. Other subsets are not exercised, so check that yours builds before relying on it. Reduced builds are source builds only; no reduced binaries are published (see the note under Homebrew Tap). This reduction is for the selected production package: workspace/test feature unification and dev-dependencies can bring mob back, and removing it is not a guarantee that every host below 8 GiB can compile the remaining graph.
Worker Stack Budget
Every host binary (rkat, rkat-rpc, rkat-rest, rkat-mcp) runs its Tokio
workers, blocking threads, and its own main future on one documented stack
budget: 8 MiB per thread, the constant
meerkat_runtime::host_stack::HOST_WORKER_STACK_BUDGET. The main future runs
on a budgeted thread as well, so the platform main thread (1 MiB on Windows)
never bounds a host.
The number is measured, not guessed. On the RPC router harness (session
create, turn start, session archive through the real method router) a release
build fits 1 MiB and overflows at 512 KiB; a debug build, which the e2e lanes
run, fits 4 MiB and overflows at 3 MiB because opt-level 0 gives every branch
of a function its own stack slots. 8 MiB is twice the debug figure and eight
times the release one. It is virtual address space per thread; pages are
committed only when touched. Two gates hold the figures: a debug canary in the
meerkat-rpc unit lane at 4 MiB and the nightly make stack-budget-release at
1 MiB in release.
RKAT_WORKER_STACK_BYTES=<bytes> overrides the budget for stack-overflow
diagnosis. Sweeping it distinguishes a bounded large frame (fails below one
value, passes above) from unbounded recursion (fails at every value). Values
below 65536 or that are not a byte count are refused with exit code 2 rather
than guessed at. rkat-rpc still honours its older RKAT_RPC_WORKER_STACK_BYTES
when the shared variable is unset.
Containerizing The Binaries
A Rust binary built for a*-unknown-linux-gnu target links the builder’s
glibc dynamically and records the newest glibc symbol version it used. The
runtime image must provide a glibc at least that new, or the loader refuses to
start the binary with version 'GLIBC_2.xx' not found. The reliable way to
get that right in a two-stage image is to pin one Debian release for both
stages, so the builder’s glibc is the runtime’s glibc:
ARG DEBIAN_RELEASEis declared before the firstFROMand used in bothFROMlines, so the two stages cannot drift apart when someone bumps one of them.rust:1.94-bookwormmatches the pinned toolchain family.--lockedbuilds with theCargo.lockshipped inside therkatcrate, so the container compiles the dependency set the release was tested with.- To build from a checkout instead of crates.io (unreleased commits, local
patches), replace the
RUN cargo installline withWORKDIR /src,COPY . ., andcargo build --locked -p rkat --release, and copy/src/target/release/rkat(the build stage above sets noWORKDIR, so without that line the checkout lands in/). The repository’s ownexamples/035-mdm-tux-rs/Dockerfiledoes exactly that for the example’s binaries, with the samerust:1.94-bookwormbuild stage anddebian:bookworm-slimruntime stage. - The companion surfaces are separate crates with the same shape:
cargo install meerkat-rpc(binaryrkat-rpc),meerkat-rest(rkat-rest), andmeerkat-mcp-server(rkat-mcp). rkatresolves project realm state under.rkat/in its working directory and the global realm’s config under~/.rkat/(see Configuration); mount a volume at/data, and pointHOMEat persisted storage if the global realm matters, so state outlives the container.
debian:bookworm-slim ships glibc 2.36, above
the 2.31 floor the release binaries are built against (next section):
checksums.sha256 (and, if you use
the GitHub CLI, its build provenance attestation; see below) before trusting it
in production.
Not covered by the prebuilt binaries: Alpine and other musl-based images. No
musl target is published, and the glibc binaries are not tested under
gcompat. Build from source on such a base or use a Debian-family image.
Where The Prebuilt Binaries Come From
.github/workflows/release.yml builds and publishes the release assets when a
v* tag is pushed. Each of the four binaries (rkat, rkat-rpc, rkat-rest,
rkat-mcp) is packaged per target as <binary>-<version>-<target>.tar.gz
(.zip on Windows), alongside checksums.sha256 and index.json. The
Homebrew tap and the
SDK bootstrap consume these same
assets. Targets:
x86_64-unknown-linux-gnuaarch64-unknown-linux-gnuaarch64-apple-darwinx86_64-apple-darwinx86_64-pc-windows-msvc
actions/attest-build-provenance), which binds the file’s digest to the
workflow run and commit that produced it:
Linux glibc floor
The Linux GNU binaries are built inside thebuildpack-deps:bullseye image
(Debian 11, glibc 2.31) on both release lanes: the BuildBuddy lane pins that
image as the execution container in tools/bazel/platforms/BUILD.bazel, and the
GitHub-hosted lane runs its Linux jobs under the same container:, because
building directly on the Ubuntu 24.04 runner (glibc 2.39) would silently raise
the floor. Packaging then runs
scripts/check-linux-release-binary-portability.sh on every Linux binary and
fails the release if either check trips:
- Any versioned glibc symbol reference is newer than the declared floor
(
MEERKAT_GLIBC_FLOOR=2.31). - The binary has a dynamic
NEEDEDentry onlibsslorlibcrypto. All first-party TLS isrustls, so an OpenSSL dependency means a crate regressed into a native-TLS stack.
GLIBC_2.34 that
Debian 11 could not load; the floor is enforced on the produced file, not
assumed from the build image.
What that guarantees: a published Linux binary starts on any x86_64 or aarch64
distribution whose glibc is 2.31 or newer (Debian 11 and later, Ubuntu 20.04
and later, Debian-based container images from bullseye onward) and needs no
OpenSSL runtime package. What it does not guarantee: musl-based systems (see
above), or distributions older than glibc 2.31.
Other platforms
The macOS binaries carry no notarization and the release workflow asserts no minimum macOS version (there is no deployment-target pin or gate); the GitHub-hosted lane ad-hoc codesigns them. The Windows binary is x86_64 only. The packaging step checks that every binary embeds the release version, sorkat --version on an installed binary tells you exactly which release it is.
MobKit
MobKit’s gateway binaries are built and released by the meerkat-mobkit repository’s own lane; the glibc floor and portability gate described on this page do not apply to them. Start from the MobKit quickstart for its install and build paths.See Also
- CD and distribution for the release pipeline, Homebrew tap, SDK bootstrap, and credentials.
- Build And CI for the contributor build, test, and BuildBuddy lanes.
- Quickstart for the featured install paths.
- Upgrading for per-release upgrade steps, including shutdown deadlines and termination grace periods.
