This repository has been archived on 2026-04-03. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
core/docs/PACKAGE-FORMAT.md
Jeffrey Smith 44bf63e5fe
Some checks failed
CI/CD / detect-changes (pull_request) Successful in 23s
CI/CD / test-frontend (pull_request) Has been skipped
CI/CD / test-runners (pull_request) Has been skipped
CI/CD / e2e-smoke (pull_request) Has been skipped
CI/CD / test-go-pg (pull_request) Failing after 2m59s
CI/CD / test-sqlite (pull_request) Failing after 3m22s
CI/CD / build-and-deploy (pull_request) Has been skipped
Feat v0.8.2 capability negotiation (#69)
Extensions declare environment requirements via capabilities.required and
capabilities.optional in their manifest. The kernel validates at install
time — required capabilities reject with HTTP 422 and rollback, optional
capabilities log a warning. Runtime query via settings.has_capability().
Admin endpoint GET /api/v1/admin/capabilities re-probes live.

Detected capabilities: postgres, pgvector, object_storage, s3, workspace.

18 new tests, all passing with -race.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-03 08:38:37 +00:00

4.6 KiB

Package Format

Armature packages are distributed as .pkg files -- ZIP archives with a standard internal structure.

ZIP Structure

my-package.pkg
├── manifest.json        # required -- package metadata
├── js/                  # browser-side JavaScript
│   └── index.js
├── css/                 # stylesheets
│   └── styles.css
├── script.star          # Starlark entry point
├── star/                # additional Starlark modules
├── assets/              # static assets (images, etc.)
└── migrations/          # schema migration files

Only manifest.json is required. All other directories are optional and included only if present in the source.

manifest.json Reference

{
  "id": "my-package",
  "title": "My Package",
  "type": "surface",
  "tier": "browser",
  "version": "1.0.0",
  "description": "What this package does.",
  "icon": "📦",
  "author": "your-name",
  "route": "/s/my-package",
  "auth": "authenticated",
  "permissions": [],
  "api_routes": [],
  "db_tables": {},
  "settings": {},
  "hooks": {},
  "exports": [],
  "schema_version": 1
}

Required Fields

Field Description
id Unique kebab-case identifier
title Human-readable display name
type surface, extension, full, library, workflow
tier browser, starlark, sidecar
version Semver version string

Optional Fields

Field Description
description Short description
icon Emoji for sidebar/menu display
author Package author
route URL path for surfaces (e.g., /s/my-package)
auth authenticated or public
layout Surface layout mode (e.g., single)
permissions Array of required capabilities (db.write, http, notifications, secrets, realtime.publish)
api_routes Array of {"method": "GET", "path": "/items"}
db_tables Table definitions with columns and indexes
settings User-configurable settings with type, label, description, default
hooks Event bus subscription patterns
exports Functions exported by library packages
capabilities Environment requirements: {"required": [...], "optional": [...]}
schema_version Integer for additive schema migrations

Package Lifecycle

  1. Install: Upload a .pkg file via Admin > Packages or POST /api/v1/admin/packages/install. The kernel extracts the archive, creates database tables, and registers routes.

  2. Enable: Activate the package so its routes, hooks, and UI become available. PUT /api/v1/admin/packages/:id/enable.

  3. Disable: Deactivate without removing data. PUT /api/v1/admin/packages/:id/disable.

  4. Update: Upload a new .pkg with a higher semver version. Schema changes must be additive (new columns/tables only). POST /api/v1/admin/packages/:id/update.

  5. Export: Download the installed package as a .pkg archive. GET /api/v1/admin/packages/:id/export.

  6. Delete: Remove the package and its data. DELETE /api/v1/admin/packages/:id.

Bundled vs User-Installed

Bundled packages ship inside the Docker image at /app/bundled-packages. On first boot, a curated default set is auto-installed. Behavior:

  • First boot: curated defaults are installed and enabled.
  • Subsequent boots: already-installed packages are skipped.
  • Admin uninstalls: the package stays uninstalled (never force-reinstalled).
  • Control via BUNDLED_PACKAGES env var: empty = defaults, "*" = all, or comma-separated IDs.

User-installed packages are uploaded through the Admin UI or API. They follow the same lifecycle but are not tied to the Docker image.

Building Packages

Packages are built by zipping the standard directories alongside manifest.json:

# Build all packages in the packages/ directory
cd packages && bash build.sh

# Build a single package
cd packages && bash build.sh my-package

Output goes to dist/my-package.pkg.

Manual Build

cd packages/my-package
zip -r ../../dist/my-package.pkg manifest.json js/ css/ script.star

The build script automatically includes whichever standard directories exist: js/, css/, assets/, script.star, star/, migrations/.

Custom Docker Image

To bundle custom packages into a Docker image:

  1. Place your package in packages/your-package/ with a manifest.json.
  2. Run cd packages && bash build.sh all.
  3. Build the image: docker build -t my-armature .

The Dockerfile builds all packages and copies them into the bundled packages directory.