ObjectOS
Build

Packages

The unit of organization in ObjectOS — versioned, installable, shareable.

Packages

Everything you build in ObjectOS lives in a package: a versioned, self-contained bundle of metadata. Packages are the unit the AI Builder works on, the unit the marketplace ships, and the unit ObjectOS tracks updates against.

What's in a package

com.acme.crm@1.2.0
├── manifest          id, version, namespace, dependencies
├── objects/          *.object.ts, *.state.ts, *.hook.ts
├── views/            *.view.ts, *.page.ts, *.form.ts
├── actions/          *.action.ts
├── flows/            *.flow.ts, *.approval.ts
├── agents/           *.agent.ts, *.skill.ts
├── permissions/      *.permission.ts
├── sharing/          *.sharing.ts
├── translations/     en.ts, zh-CN.ts, ...
├── apps/             *.app.ts  (navigation)
└── data/             defineDataset(...) seed

Every metadata artifact (object, action, flow, …) belongs to exactly one package. The package id is reverse-DNS (com.acme.crm, org.mycompany.helpdesk) and the namespace prefix (crm_, hd_) keeps table / object names from colliding across packages installed in the same tenant.

Creating a package

From the AI Builder

"Start a new package for our internal CRM, namespace crm."

The AI calls create_package and set_active_package. From then on, every object / field / action you describe lands in crm.

From the CLI

os init my-crm -t app
cd my-crm
# manifest lives in the `manifest:` block of ./objectstack.config.ts
pnpm dev

From Console

Console → Packages → New Package — name, id, version, namespace.

Active package

In the AI Builder, a conversation carries an active package — the default container for new metadata. The AI sets it with the set_active_package tool when you say something like "Switch to com.acme.helpdesk." From the CLI, the active package is simply the one declared in the project's objectstack.config.ts (the manifest: block).

Versioning

Packages are semver. Same rules as the runtime — see Changelog & Versioning.

Bumping a version doesn't change anything until you publish. The runtime tracks installed_version per tenant per package, and the marketplace shows an "Update available" badge when the catalog has a newer version.

Dependencies

Packages can depend on other packages:

{
  "id": "com.acme.helpdesk",
  "version": "0.3.0",
  "dependencies": {
    "com.acme.crm": "^1.0.0",
    "sys.feeds":   "*"
  }
}

The runtime resolves dependencies on install. If com.acme.crm isn't installed, the helpdesk install fails with a clear error.

System packages (sys.*) are always present — feeds, attachments, audit, identity, etc.

Publishing

os cloud login                 # once: stores a cloud token in ~/.objectstack/cloud.json
os compile                     # → dist/objectstack.json
os package publish             # → ObjectStack cloud catalog

os package publish uploads the compiled manifest to the cloud control plane configured by OS_CLOUD_URL. Authentication comes from os cloud login (interactive) or, for CI, an OS_CLOUD_API_KEY bearer token. For private / air-gapped distribution, skip publishing and hand the compiled dist/objectstack.json directly to the target install (see Installing below). See Marketplace.

Installing

Installing is an in-environment action — distinct from publishing. You publish a package once (to the catalog), then install it from inside the target environment, where the install is confirmed and authorized by your environment login. You never need to know an environment id to install.

PathHow
Console (recommended)Sign in to the environment → Marketplace → pick the package → Install. Installs into the current environment.
CLI → running runtimeos package install com.acme.crm --runtime <url> — the runtime resolves the package from its configured catalog and merges it into its own kernel
CLI air-gappedos package install ./dist/objectstack.json --runtime <url> — compiled artifact sent inline, no catalog round-trip
RESTPOST /api/v1/marketplace/install-local (body: { packageId, versionId? } or { manifest })
Air-gapped (boot-time)Mount the compiled dist/objectstack.json artifact (see Air-gapped)

Package ids in install commands are the stable manifest id (com.acme.crm) — you never need the internal pkg_… row id.

CI shortcut. Pipelines that deploy to a known environment can publish and install in one step: os package publish --env <id> --install [--seed-sample-data]. This is a convenience for automation, not the path a person uses — interactive installs happen in the environment's Marketplace.

Install merges the package's metadata into the live kernel, registers its objects with ObjectQL, and seeds initial data on first install — no restart needed. Cached installs are re-registered on the next boot, so they survive process restarts.

Uninstalling

Uninstalling removes the package's cached manifest so it is no longer re-registered on the next boot. Because object registration is additive, a kernel restart is required to fully unload an already-running package's objects. Data is kept by default, so you can re-install and resume.

Cross-package conventions

To prevent collisions when many packages coexist:

ArtifactConvention
Object namesAlways prefixed: crm_account, hd_ticket
Action namesPrefixed: crm_assign_owner, hd_close_ticket
Flow namesPrefixed: hd_overdue_alert
Translation keysScoped under the namespace: crm.account.label
Seed externalId<prefix>:<key>, e.g. crm:demo-account-1
System namesReserved: sys_* (never use in custom packages)

The CLI and the AI Builder both enforce this on creation.

System packages

The runtime ships a small set of always-present packages that provide polymorphic services:

PackageProvides
sys.identitysys_user, sys_organization, sys_member, sessions, API keys
sys.feedssys_comment, sys_activity, sys_attachment
sys.auditsys_audit_log
sys.filessys_file
sys.aiai_conversations, ai_pending_actions
sys.settingssys_setting

You enable them via enable: { feeds: true, trackHistory: true, … } on your objects — see Data Model.

Where to go next

On this page