New features
-
coop agent update— refresh in-guest Claude Code and Codex (#403) —
Agents are installed "latest at build time" duringcoop setupand are not
part of the image-staleness hash, so a plaincoop setupnever refreshes
them; they go stale in long-running VMs and in new VMs built from an old
image.coop agent update [NAME] [--claude] [--codex] [--check] [-y]updates
the agent binaries inside a running instance without rebuilding the golden
image. No agent flag updates both;--checkreports installed vs. latest and
changes nothing. Codex (root-owned/usr/local/bin/codex, no background
updater) is reinstalled from the current release via coop's own installer
over SSH; Claude Code (~/.local/bin, already self-updating) runs
claude updatesynchronously. Versions are parsed to semver so "update
available" is a comparison, not a string diff; an unparseable version
degrades toUnknownrather than erroring. -
Codex plugins and marketplaces (#407) — New
[codex] marketplaces/
[codex] pluginsconfig fields (with~expansion and local-path
validation), mirroring the existing Claude Code mechanism. On Lima the set is
baked into the golden image and staleness-checked; on Firecracker it installs
on first boot. coop preserves the guest's own[marketplaces.*]/[plugins.*]
tables across the per-boot~/.codex/config.tomlrewrite — so plugins
installed in-guest and manual/pluginstoggles survive stop/start — while
dropping any that came from the host config. Local marketplace directories
are copied into a per-tool guest subdir so same-basename marketplaces from
the two agents don't collide. Behavior change: marketplaces/plugins set
directly in the host~/.codex/config.toml(rather than in coop's[codex])
are now stripped from the guest; declarative[codex]is the source of
truth.
Fixes
-
Guest-memory floor enforced by construction (#404) —
coop up --mem 16,
coop setup --mem 16, aconfig.tomlwithmem_size_mib = 16, and a
cloned repo whosedevcontainer.jsonsetshostRequirements.memorybelow
the 128 MiB minimum are now all rejected up front, instead of booting an
unbootable VM that never comes up on SSH. The floor lives in a new
VmMemorytype whose constructor every entry point routes through (CLI,
config.toml,coop resize, the devcontainer translator), so no lifecycle
path can hold a sub-floor value. The staleValidatedwitness — which
vouched for a config that lifecycle commands mutated afterward, and which
the actual VM boot (create_and_start) never even consumed — is removed;
the environmental (path-existence) checks it stood in for now run at the
backend boot choke point on the freshest filesystem state, so a new
lifecycle path cannot skip them. The start-time mount set gains a
ValidatedMountsconstructor that enforces guest-path uniqueness on every
path, closing a gap wherecoop quickstartskipped the check. -
Firecracker CI artifact listing fetched over HTTPS (#401) — the S3
ListObjectsV2request that discovers kernel/rootfs versions during
setup used plain HTTP: the bucket name contains dots, which breaks TLS
certificate matching for the virtual-hosted URL. It now uses the same
path-style HTTPS endpoint as the downloads themselves, so a network
attacker can no longer steer version selection.
Documentation
- Docs describe the public repository (#401) — removed the
transitional "whiletrailofbits/coopis private" wording from the
README anddocs/commands.md.coop updateandinstall.shwork
anonymously and usegh/GITHUB_TOKENopportunistically when present.
Internal
repositorymetadata added to Cargo.toml (#401).