# agentOS `.aospkg` package container schema.
#
# Container layout: 16-byte header (magic 0x89 'A' 'O' 'S', u16 LE format
# version, u16 reserved, u32 LE manifest len, u32 LE index len) followed by
# chunk1 PackageManifest, chunk2 MountIndex, and chunk3 — the uncompressed
# mount tar served byte-for-byte by `TarFileSystem`.
#
# Chunk payloads are encoded as [u16 little-endian schema version] ++ BARE(root).
# PACKAGE_MANIFEST_VERSION is currently 1. Never edit a published v1.bare in
# place; copy to vN.bare and add converters. Enum members are append-only
# because their order is the on-wire ordinal.
#
# Tooling: two packers encode this schema and must stay behaviorally identical —
# Rust `crates/vfs/src/package_format/pack.rs` (bench/test fixtures, canonical)
# and TS `packages/agentos-toolchain/src/aospkg.ts` (what `agentos-toolchain
# build`/`pack` emit as `dist/package.aospkg`). The TS codecs are generated from
# this file via `pnpm --dir packages/build-tools build:package-format`; the Rust
# types are generated by `crates/vfs/build.rs` (vbare-compiler). The
# `cross_validates_toolchain_built_aospkg` test in
# `crates/vfs/tests/package_format.rs` catches codec drift.
#
# The chunk1 manifest is the ONLY runtime manifest. `agentos-package.json` is a
# toolchain-input file: packers parse it to build chunk1 and strip it from the
# mount tar, so packed packages never ship it and nothing materializes JSON
# back into the guest.
# File type of a mount tar entry, as served by `TarFileSystem` stat/readdir.
type TarEntryKind enum {
FILE
DIRECTORY
SYMLINK
}
# One entry of the chunk3 mount tar. The index lets the VFS project the tar
# without parsing tar headers at VM startup: file contents are served as
# byte ranges directly out of chunk3.
type TarEntry struct {
# Absolute path within the package mount root, e.g. `/bin/jq`.
path: str
kind: TarEntryKind
# Byte offset of the file's content within chunk3 (the mount tar). 0 for
# directories and symlinks, which carry no content.
offset: u64
# Content length in bytes. 0 for directories and symlinks.
size: u64
# POSIX mode bits (file-type bits + permissions) reported by guest stat.
mode: u32
# Ownership reported by guest stat. Deterministic packs emit 0.
uid: u32
gid: u32
# Modification time (Unix seconds) reported by guest stat. Deterministic
# packs emit 0.
mtime: i64
# Symlink target; present only when kind is SYMLINK.
linkTarget: optional<str>
}
# Agent metadata for packages that ship an ACP agent adapter. Present only on
# agent packages; absence means the package is not launchable as an agent.
type AgentBlock struct {
# Name of a command in `PackageManifest.commands` that speaks ACP on
# stdio. The sidecar launches this to run the agent.
acpEntrypoint: str
# True when the package ships a prebuilt SDK snapshot bundle for fast agent
# cold starts; see `PackageManifest.snapshotBundlePath`.
snapshot: bool
# Environment variables applied to the agent process at launch.
env: map<str><str>
# Extra argv appended when launching the ACP entrypoint.
launchArgs: list<str>
}
# One command projected into the shared `$PATH` dir. All packages link their
# commands into a single `/opt/agentos/bin`, each as its own virtual symlink
# leaf, so the sidecar can enumerate and remap commands from chunk1 alone —
# no tar scan or JSON parse at VM startup.
type CommandTarget struct {
# The name the guest types: the link name under `/opt/agentos/bin`.
command: str
# Path of the executable it resolves to, relative to the package mount root
# at `/opt/agentos/pkgs/<name>/<version>/`, e.g. `bin/jq` or
# `dist/claude-cli.mjs`. Not necessarily under `bin/`: npm-style
# `package.json` `bin` maps may point anywhere in the package.
entry: str
}
# One man page shipped by the package, derived at pack time from mount paths
# of the form `/share/man/<section>/<page>`. The projection serves manpage
# aliases from this list without scanning the mount index at startup.
type ManPage struct {
# Man section directory name, e.g. `man1`.
section: str
# Page file name within the section, e.g. `jq.1`.
page: str
}
# One directory the package projects to a fixed location in the guest
# filesystem, for software that expects its runtime files at a well-known
# absolute path (e.g. vim's `$VIMRUNTIME` tree).
type ProvidesFile struct {
# Source directory relative to the package mount root, e.g. `share/vim/vim92`.
# Must be a directory; non-directory sources are skipped with a warning.
source: str
# Absolute guest path where the source is mounted read-only, e.g.
# `/usr/local/share/vim/vim92`.
target: str
}
# Guest environment and filesystem projections the package provides.
type ProvidesBlock struct {
# Guest-wide environment defaults applied at VM creation. First package
# wins: a key already set (by the VM config or an earlier package) is not
# overridden.
env: map<str><str>
# Package directories mounted at fixed guest paths; see `ProvidesFile`.
files: list<ProvidesFile>
}
# Chunk1: the runtime package manifest. Read alone (without chunk2/chunk3) on
# the VM cold-start path to project `/opt/agentos` — keep it small and free of
# anything that would require reading the mount payload.
type PackageManifest struct {
# Runtime package name, e.g. `jq` or `claude-code`. Names the projection dir
# `/opt/agentos/pkgs/<name>/` and, for agent packages, the agent id.
name: str
# Package version, e.g. `0.3.0-rc.2`. Names the version dir under the
# package projection dir.
version: str
# Agent metadata; present only for packages launchable as ACP agents.
agent: optional<AgentBlock>
# Env/file projections; present only when the package provides them.
provides: optional<ProvidesBlock>
# Commands linked under `/opt/agentos/bin`. Derived at pack time from the
# `package.json` `bin` map when present, else from `/bin/*` in the mount.
commands: list<CommandTarget>
# Man pages shipped under `/share/man/` in the mount.
manPages: list<ManPage>
# Mount-root-relative path to the prebuilt SDK snapshot bundle
# (`/dist/sdk-snapshot.js`), set iff `agent.snapshot` is true and the file
# exists in the mount. Null otherwise.
snapshotBundlePath: optional<str>
}
# Chunk2: index of the chunk3 mount tar, entries sorted by path.
type MountIndex struct {
tarEntries: list<TarEntry>
}