Build, inspect, and extract OCI bin images — static binaries packaged as OCI artifacts with
vnd.openotters.bin.* annotations.
A bin image is a regular OCI image that carries annotations describing a static binary:
manifest
annotations:
vnd.openotters.bin.name: jq
vnd.openotters.bin.path: /
vnd.openotters.bin.description: JSON processor
vnd.openotters.bin.usage: /USAGE.md
layers:
[0] jq (binary)
[1] USAGE.md (optional usage documentation)
Any OCI image can adopt these annotations. The annotation contract is defined in the Agentfile specification.
57 ready-to-use tool binaries for AI agents, published at ghcr.io/openotters/tools/{name}:latest:
Coreutils & shell (Go-source pipeline) —
base64 basename cat chmod cp date dirname echo false find grep gzip
head hostname id jina ln ls mkdir mktemp more mv ping printenv
pwd readlink realpath rm rmdir seq sh shasum sleep sort tail tee
time touch tr true uname uniq wc wget which xargs yes
Vendored upstream binaries (vendors/ pipeline) —
crane fd gh helm jq kubectl pandoc rg yaegi yq
jina fetches URL content as clean markdown; sh is a minimal POSIX shell
for agents that need to pipe or redirect between tools; yaegi is an
embedded Go interpreter (no compiler); kubectl / helm / crane give
infra-aware agents a real toolchain; gh exposes the GitHub API end-to-end;
rg / fd cover fast structured search and file discovery; pandoc does
universal document conversion (markdown ↔ html ↔ docx ↔ pdf …).
Each tool is a plain CLI — argv in, stdout out. When the openotters runtime invokes a BIN tool on behalf of an agent, it shell-splits the LLM's input string and execs the binary directly; stdout is the response, a non-zero exit code surfaces as an error. There is no JSON envelope.
Each tool image embeds a USAGE.md layer describing its expected
argv and flags.
Cross-build a tool for darwin/{arm64,amd64} + linux/{arm64,amd64} and
push it as a multi-arch bin image with task:
# A single tool
task tools:publish TOOL=wget
# Every tool under cmd/tools/
task tools:publish
# Override the registry / otters CLI
REGISTRY=registry.internal/mirror task tools:publish TOOL=jq
OTTERS="go run ../openotters/cmd/otters" task tools:publish TOOL=jqThe task wraps otters bin build + otters bin push; otters must be
on $PATH (or set OTTERS=…).
For tools that aren't usable as a Go library (yaegi, kubectl, helm,
ffmpeg, …), the vendored pipeline packages an upstream binary
release instead. Each tool is one YAML descriptor under
vendors/ — the pipeline downloads, checksum-verifies,
extracts, and repackages as a multi-arch OCI BIN image:
# A single vendored tool
task tools:vendor:publish TOOL=yaegi
# Every vendored tool
task tools:vendor:publishSee vendors/README.md for the descriptor schema.
For programmatic use, the examples/ directory has runnable Go
programs for each lifecycle stage (build, info, pull, push,
extract, validate) — see examples/README.md.
The bin-image primitives are in the importable package
github.com/openotters/bin/pkg/bin:
Build/BuildIndex— assemble multi-arch bin images.Inspect— readvnd.openotters.bin.*metadata off a manifest.Extract/FetchUsage— pull a binary or itsUSAGE.mdfrom a fetcher.
OCI transport (resolve, fetch blobs, push) lives in
agentfile/oci;
artifact-type and annotation constants live in
agentfile/spec.
See LICENSE.