These instructions are only for agents contributing changes to this repository. Do not apply them to other repositories or to general agent behavior outside this contribution workflow.
- Follow these guidelines when editing code, docs, tests, examples, CI, or release files for microsandbox.
- Prefer repository conventions over generic agent habits. When unsure, inspect nearby files and match their style.
- Do not create branches, commit, push, tag, publish, or open pull requests unless the human explicitly asks.
- Check
git status --short --branchbefore making changes. Do not overwrite or revert user work unless explicitly asked.
sdk/rustis the public Rust SDK crate.crates/clicontains themsbCLI.crates/runtimecontains VM runtime integration.crates/filesystem,crates/image,crates/network,crates/db,crates/migration,crates/metrics,crates/metrics-collector,crates/protocol, andcrates/utilsare shared internal crates.packages/agent-clientandpackages/microsandbox-typesare the shared agent-protocol client and wire-contract type packages, each with Rust and TypeScript implementations.crates/agentdis the in-guest agent. It is a workspace member; the musl guest binary that ships in releases is built separately.sdk/python,sdk/node-ts, andsdk/gocontain the language SDKs and native bindings.docs/contains the documentation site. Keep docs in sync with user-facing behavior.examples/contains runnable examples. Add new example projects only when requested or clearly required by the contribution.mcp/andskills/are submodules related to agent integrations.vendor/libkrunfwis a submodule for the kernel firmware library.
Repository layout:
.
|-- AGENTS.md
|-- Cargo.lock
|-- Cargo.toml
|-- DEVELOPMENT.md
|-- Dockerfile.agentd
|-- justfile
|-- msb-entitlements.plist
|-- assets/
|-- crates/
| |-- agentd/
| |-- cli/
| |-- db/
| |-- filesystem/
| |-- image/
| |-- metrics/
| |-- metrics-collector/
| |-- migration/
| |-- network/
| |-- protocol/
| |-- runtime/
| |-- test-init/
| |-- test-macros/
| |-- test-utils/
| `-- utils/
|-- docs/
| |-- changelog/
| |-- cli/
| |-- getting-started/
| |-- images/
| |-- networking/
| |-- observability/
| |-- recipes/
| |-- sandboxes/
| |-- sdk/
| `-- security/
|-- examples/
| |-- python/
| |-- rust/
| `-- typescript/
|-- mcp/
| |-- bin/
| |-- src/
| `-- package.json
|-- packages/
| |-- agent-client/
| `-- microsandbox-types/
|-- packaging/
| `-- docker/
|-- scripts/
| `-- smoke/
|-- sdk/
| |-- go/
| |-- node-ts/
| |-- rust/
| `-- python/
|-- skills/
| `-- microsandbox/
`-- vendor/
`-- libkrunfw/
- Before making or continuing a change that may introduce a regression or breaking change, stop and alert the human with the likely impact and affected workflows.
- Keep changes narrowly scoped to the requested behavior. Avoid drive-by refactors, unrelated formatting, or dependency churn.
- Treat sandbox isolation, host filesystem access, networking, and secret handling as security-sensitive. Validate inputs at boundaries and avoid exposing host paths, credentials, or ambient privileges.
- For public APIs, keep the Rust SDK, CLI, Python SDK, Node SDK, Go SDK, docs, and examples consistent when they describe the same capability.
- Prefer explicit errors with useful context over silent fallbacks.
- Most Rust crates use
lib/lib.rsfor library code andbin/main.rsfor binaries. Keep using those paths for new crate entries unless the surrounding crate already does something different. - When adding a new library or binary target, declare the path explicitly in
Cargo.toml:
[lib]
path = "lib/lib.rs"
[[bin]]
name = "example"
path = "bin/main.rs"- Keep crate roots and module roots thin.
lib.rsandmod.rsshould declare modules, crate attributes, and exports only. Put implementation in leaf modules such assandbox/config.rs,policy/types.rs, orcommands/run.rs. - File order should be:
- Module docs and crate/file attributes, such as
//! ...and#![warn(missing_docs)]. useimports.- Sectioned items.
- Module docs and crate/file attributes, such as
- Group imports by origin, separated by blank lines: standard library first, external crates second, then
crate::andsuper::imports. - Do not put
usestatements inside sections unless there is a narrow local reason, such as a test module import. - Use the exact section delimiter shown below. Do not invent alternate Markdown-style, shorter, or decorative section headers.
- Include only sections that contain items. Do not add empty sections just to satisfy the full order.
- Organize Rust files with these section headers, in this order when applicable:
//--------------------------------------------------------------------------------------------------
// Constants
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
// Types
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
// Methods
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
// Trait Implementations
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
// Functions
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
// Macros
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
// Tests
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
// Re-Exports
//--------------------------------------------------------------------------------------------------- Aggregator files that only expose modules and public items may use
Exportsinstead ofRe-Exportswhen matching existing files. - Use qualified section labels only to split large sections into obvious groups, for example
Types: Identifiers,Functions: Handlers, orFunctions: Helpers. - Do not create a qualified section for one or two items unless the surrounding file already uses that pattern.
- Put constants and statics under
Constants. - Put
struct,enum,trait, andtypedefinitions underTypes. - Put inherent
impl Typeblocks underMethods, directly after the related type definitions when practical. - Put
impl Trait for Typeblocks underTrait Implementations. - Put free functions under
Functions. If a free function is only used by one public function, place it later inFunctions: Helpers. - Put macros under
Macros, not near the call site. - Put unit tests under
Tests, usually as#[cfg(test)] mod tests. Keep test-only helpers in the same section. - Put public re-exports under
Re-Exports, orExportsin root files that use the existing aggregator style. - Keep items in dependency order inside a section: public surface first, private helpers later.
- Keep docs on public types, fields, methods, functions, and modules. This repo uses
#![warn(missing_docs)]in public crates, so new public items should explain what they are for. - Prefer explicit domain types over loosely typed strings, booleans, or tuples when the value crosses an API or subsystem boundary.
- During refactors, conflict resolution, bug fixes, and feature work, call out any expected behavior, API, or data-format changes and wait for direction when the risk is material.
- Use
thiserroror existing local error patterns for typed errors. Include enough context for callers to understand the failing operation. - In async code, avoid holding locks across
.await. Prefer explicit ownership, short critical sections, and existing Tokio patterns in the surrounding module. - Keep feature-gated code close to the feature it gates and use existing
#[cfg(feature = "...")]patterns. - Do not add examples under
examples/unless requested or clearly required. Prefer tests and docs for small usage coverage. - Run
cargo fmtbefore finalizing Rust changes.
- If you build
msbto run it locally on macOS, make sure the binary is codesigned withmsb-entitlements.plist; otherwise VM/runtime failures may be caused by missing entitlements instead of your code change. - Prefer
just buildorjust build-msbwhen producing a runnable local binary. The macOS recipe rebuildsmsband runs:
codesign --entitlements msb-entitlements.plist --force -s - build/msb- If you bypass
justand callcargo builddirectly, manually codesign the exactmsbbinary you are going to run before testing sandbox startup, protocol, networking, or filesystem behavior.
Use focused checks for the files you touched, then broader checks when the change crosses crate, SDK, CLI, or runtime boundaries.
Common Rust checks:
cargo fmt --all -- --check
cargo clippy --workspace -- -D warnings
cargo test --workspace
cargo build -p microsandbox-cliagentd is a workspace member, so the workspace-wide commands above cover it. The musl guest binary that ships in releases is built separately via just build-agentd.
Python SDK checks:
cd sdk/python
uv sync --group dev
uv run maturin develop --release
uv run pytest
uv run ruff check .Node SDK checks:
cd sdk/node-ts
npm ci
npm run build
npm test
npm run typecheckGo SDK checks:
cd sdk/go
go test -count=1 .
go test -tags "smoke microsandbox_ffi_path" -count=1 -timeout 2m .Integration tests may require Linux with KVM or macOS Apple Silicon support. If a needed check cannot run in the current environment, say exactly which command was skipped and why.
The full local setup and build loop is documented in DEVELOPMENT.md. Use just setup, just build, and just install when you need the full local runtime, agentd, or libkrunfw artifacts.
- Use Conventional Commits for commit titles:
feat,fix,docs,style,refactor,test,chore,perf,ci, orbuild. - Use a scope when it clarifies the affected area, for example
fix(network): ...ordocs(sdk): .... - Keep the subject imperative, lowercase after the colon, no trailing period, and at most 72 characters.
- Include a commit body for non-trivial changes. Explain what changed and why.
- Use signed commits:
git commit -S. - Before committing, inspect the actual diff, including new, modified, and deleted files. Do not write a commit message from filenames or previous commit messages alone.
- If there is nothing to commit, say so rather than creating an empty commit.
Example:
fix(network): wake smoltcp after accepted host connections
Notify the network loop after accepting a published-port connection so
pending guest traffic can make progress without waiting for another timer.
- You may make local edits while on
main, but do not commit directly tomain. Start from the latestmainwhen creating a contribution branch. - Use short, descriptive, kebab-case branch names. Avoid personal prefixes in shared documentation unless the maintainer asks for one.
- Before opening a PR, compare against the intended base branch and inspect the actual diff:
git log origin/main..HEAD --oneline
git diff origin/main..HEAD --stat
git diff origin/main..HEAD --name-status- PR titles should follow Conventional Commit style and stay under 72 characters.
- PR descriptions should be plain and accurate:
## TL;DR: one or two short sentences.## Description: a flat bullet list of core changes.## Test Plan: concrete commands or observable checks.
- Do not use emojis in PR titles or descriptions.
- If a PR description includes an API example, verify every symbol, path, flag, type, field, and signature against the diff before writing it.
- Do not bump versions, publish packages, create release tags, or modify release automation unless explicitly asked.
- All released packages share a version. When a version bump is requested, check
Cargo.toml,sdk/node-ts/package.json,mcp/package.json, and any other package metadata touched by the release process inDEVELOPMENT.md. - For release or version PRs, summarize the user-visible changes since the previous version bump and run the relevant dry-run publish checks when practical.
- Update docs when behavior, configuration, CLI flags, SDK APIs, or examples change.
- Keep examples realistic and runnable. Do not invent APIs or flags.
- Prefer editing existing examples over adding new example projects unless the new example is requested or clearly fills a missing user workflow.
- Documentation should describe current behavior, not future plans, unless the page is explicitly about roadmap work.
- Use
rgorrg --filesfor repository searches. - Read the relevant files before editing. Let existing module boundaries guide the change.
- Make the smallest coherent change that satisfies the request.
- Avoid destructive git commands such as
git reset --hardandgit checkout --unless explicitly requested. - Do not edit generated artifacts, lockfiles, or submodule pointers unless the change requires it.
- If generated files or lockfiles must change, explain why in the final summary.
- Report what changed, what validation ran, and any checks that were skipped.