Contributing
Development
Rust is pinned by rust-toolchain.toml (1.97.0). The atirc client is a git
dependency pinned to a revision in Cargo.toml; builds need fetch access to
tangled.org, and the revision only moves when bumped deliberately (with
Cargo.lock updated in the same change).
cargo build --release --bins
Binaries:
asyncaiasyncai-mcp-simplesocialweb-computer-kcp-readonlysocialweb-computer-kcp-readwrite
cargo install --path . installs all four. prompts/*.md and
src/code_mode/helpers.py are embedded at build time, so prompts/ must be
present in any build context.
Checks
cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test
Pool sandbox tests need the Monty worker:
cargo +1.97.0 install monty-runtime --locked # installs `monty`
MONTY_WORKER=$(command -v monty) cargo test --test code_mode_pool
Tests mock the model, MCP servers, and the atirc bus; no live services or network are used. Never commit endpoints or tokens.
Linux amd64 build
container system start
# Drop stopped build containers from earlier runs before building.
container list --all --format json \
| jq -r '.[] | select(.status.state=="stopped") | .id' \
| while read -r id; do container delete "$id"; done
rm -rf $HOME/.tmp/asyncai-out
mkdir -p $HOME/.tmp/asyncai-out
container build --platform linux/amd64 -m 8G -c 4 \
-f Dockerfile \
-o type=local,dest=$HOME/.tmp/asyncai-out .
find $HOME/.tmp/asyncai-out -name asyncai -type f
file $HOME/.tmp/asyncai-out/*/linux_amd64/out/asyncai # ELF 64-bit, static-pie
Build context and destination must live under $HOME: the builder cannot read
/tmp (the context transfers as 2B and COPY fails). The container uses the
image's pinned 1.97.x toolchain; rust-toolchain.toml is not copied into the
build, so local builds can stay on 1.97.0 while the image builds with its own
1.97 patch release. -j 2 keeps monty's rustc within the 8G builder memory
limit (4 jobs gets OOM-killed).
Smoke-run in an Alpine container:
container run --rm --platform linux/amd64 --memory 1G \
-v $HOME/.tmp/asyncai-out/*/linux_amd64/out:/out \
alpine:latest /out/asyncai --help
Windows amd64 build (cross-compile)
Cross-compiles self-contained PE32+ x86-64 binaries with mingw-w64 inside the
build container. No Windows host, MSVC SDK, cargo-xwin or zig is needed.
container system start
# Drop stopped build containers from earlier runs before building.
container list --all --format json \
| jq -r '.[] | select(.status.state=="stopped") | .id' \
| while read -r id; do container delete "$id"; done
rm -rf $HOME/.tmp/asyncai-win-out
mkdir -p $HOME/.tmp/asyncai-win-out
# Apple Silicon: linux/arm64. Intel Macs: linux/amd64. The build container
# architecture does not change the Windows binaries.
container build --platform linux/arm64 -m 8G -c 4 \
-f Dockerfile.windows \
-o type=local,dest=$HOME/.tmp/asyncai-win-out .
find $HOME/.tmp/asyncai-win-out -name '*.exe' -type f
file $HOME/.tmp/asyncai-win-out/*/linux_arm64/out/asyncai.exe
# PE32+ executable (console) x86-64, for MS Windows
Dockerfile.windows installs the mingw-w64 toolchain plus cmake, perl and
nasm (used by aws-lc-sys), adds the Rust x86_64-pc-windows-gnu target, and
builds with a static CRT so the .exe files do not require
libgcc_s_seh-1.dll or libwinpthread-1.dll. The target is added to the
image's pinned 1.97.x toolchain; rust-toolchain.toml is not copied into the
build so rustup cannot switch to a toolchain without that target.
A PE binary cannot be run on macOS without Windows or Wine, so this target is compile-verified only. Windows runtime notes:
--monitorand the kcp runner spawnsh -c, so they need Git Bash or WSL.- The Claude Code session harness reads
HOME; on Windows setHOME(Git Bash) or pass--session-dir FORMAT=PATH, or run with--no-session.
macOS arm64 build
Native build on an Apple Silicon Mac:
cargo build --release --bins
file target/release/asyncai # Mach-O 64-bit executable arm64
All four binaries land in target/release/.
Building on a Linux host
The container commands above are Apple-container-specific. On a Linux host
use the same Dockerfiles with BuildKit (docker buildx or podman build, both
support --output type=local), or build directly with the host toolchain as
below. All three platforms can be produced from one Linux host except macOS.
Linux amd64 on a Linux host
# Debian/Ubuntu
sudo apt-get install -y build-essential cmake perl pkg-config
# Fedora/RHEL
sudo dnf install -y gcc gcc-c++ make cmake git perl pkgconf-pkg-config
cargo build --release --bins
git is required because .cargo/config.toml sets git-fetch-with-cli for
the pinned atirc dependency.
For the same static-pie binary the container build produces, add the musl target (static against musl, no glibc dependency on the target host):
sudo apt-get install -y musl-tools
rustup target add x86_64-unknown-linux-musl
cargo build --release --bins --target x86_64-unknown-linux-musl
The four binaries land in target/x86_64-unknown-linux-musl/release/.
Windows amd64 on a Linux host (cross-compile)
# Debian/Ubuntu
sudo apt-get install -y \
gcc-mingw-w64-x86-64 g++-mingw-w64-x86-64 binutils-mingw-w64-x86-64 \
nasm cmake perl pkg-config
# Fedora/RHEL
sudo dnf install -y mingw64-gcc mingw64-gcc-c++ mingw64-binutils \
nasm cmake perl pkgconf-pkg-config
rustup target add x86_64-pc-windows-gnu
export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER=x86_64-w64-mingw32-gcc
export CARGO_TARGET_X86_64_PC_WINDOWS_GNU_RUSTFLAGS="-C target-feature=+crt-static"
cargo build --release --bins --target x86_64-pc-windows-gnu
nasm is only needed for x86_64 Windows (aws-lc-sys); the static CRT flag
is what keeps the .exe files free of libgcc_s_seh-1.dll and
libwinpthread-1.dll.
macOS arm64
A macOS artifact needs a macOS host: there is no supported way to produce one
from a Linux host without an Apple SDK. Build it with cargo build --release --bins on an Apple Silicon Mac (or via an osxcross toolchain with a legally
obtained SDK, which is out of scope here). Linux (glibc or musl) and Windows
artifacts can both be built on one Linux host.
Container builds on a Linux host
docker buildx build --platform linux/amd64 -f Dockerfile \
--output type=local,dest=$PWD/out/linux .
# The build container arch does not affect the Windows artifacts.
docker buildx build --platform linux/amd64 -f Dockerfile.windows \
--output type=local,dest=$PWD/out/windows .
--output type=local requires BuildKit (default in current Docker). The
$HOME/.tmp and -m/-c builder-memory notes in the Apple sections do not
apply; Docker inherits the host's resources.
Cold container builds and cargo cache seeding
A cold container build can sit ~10 minutes at "Updating git repository":
the container VM has no IPv6 route while musl prefers AAAA for
tangled.org/crates.io. Seed the host cargo caches and build offline to skip
the hang. Keep the /work/target cache mount — when it is warm only the
asyncai crate recompiles; the cache also makes the copied registry layers
cheap.
Create the seed from the host caches (both git repositories must be present:
atirc and atproto-crates):
mkdir -p cargo-seed/git/db cargo-seed/git/checkouts cargo-seed/registry
cp -R ~/.cargo/git/db/atirc-* ~/.cargo/git/db/atproto-crates-* cargo-seed/git/db/
cp -R ~/.cargo/git/checkouts/atirc-* ~/.cargo/git/checkouts/atproto-crates-* cargo-seed/git/checkouts/
cp -R ~/.cargo/registry/index ~/.cargo/registry/cache cargo-seed/registry/
Then apply this diff to Dockerfile (and Dockerfile.windows for the same
offline behavior):
COPY src ./src
COPY prompts ./prompts
+COPY cargo-seed/git /usr/local/cargo/git
+COPY cargo-seed/registry/index /usr/local/cargo/registry/index
+COPY cargo-seed/registry/cache /usr/local/cargo/registry/cache
-RUN --mount=type=cache,target=/usr/local/cargo/registry \
- --mount=type=cache,target=/usr/local/cargo/git \
- --mount=type=cache,target=/work/target \
+RUN --mount=type=cache,target=/work/target \
TOOLCHAIN=$(echo /usr/local/rustup/toolchains/*) && \
- PATH="$TOOLCHAIN/bin:$PATH" cargo build --release --bins -j 2 && \
+ PATH="$TOOLCHAIN/bin:$PATH" CARGO_NET_OFFLINE=true \
+ cargo build --release --bins -j 2 && \
cargo-seed/ is local scratch state; leave it untracked and do not commit it.
It must stay in the build context (do not gitignore it) or the COPY steps
fail.
Disk hygiene
container build caches aggressively and never prunes itself. Each distinct
build adds an image (~0.4–0.5 GB), and the BuildKit builder container
(~/Library/Application Support/com.apple.container/containers/buildkit,
~13 GB) keeps cargo registry/target caches between builds. Apple's CLI has no
automatic garbage collection, so this grows every day a build runs.
Reclaim stopped containers (safe; the running buildkit builder is skipped):
container list --all --format json \
| jq -r '.[] | select(.status.state=="stopped") | .id' \
| while read -r id; do container delete "$id"; done
Deleting the buildkit container (container stop buildkit && container delete buildkit) drops its ~13 GB cache; the next build recreates the builder
automatically and is cold. Rust build output is the other grower:
target/ reaches multiple GB; cargo clean resets it.
Installing on a host
There is no server deploy: copy the four binaries to the machine that runs the
agent and put them on PATH together.
scp target/release/asyncai \
target/release/asyncai-mcp-simple \
target/release/socialweb-computer-kcp-readonly \
target/release/socialweb-computer-kcp-readwrite \
<host>:/tmp/
ssh <host> 'sudo install -m 0755 /tmp/asyncai /tmp/asyncai-mcp-simple \
/tmp/socialweb-computer-kcp-readonly /tmp/socialweb-computer-kcp-readwrite \
/usr/local/bin/'
Use the matching Linux, macOS or Windows build for the target host; the Linux amd64 binaries are static-pie and need no libc or CA bundle on the host.