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(...) seedEvery 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 devFrom 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 catalogos 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.
| Path | How |
|---|---|
| Console (recommended) | Sign in to the environment → Marketplace → pick the package → Install. Installs into the current environment. |
| CLI → running runtime | os 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-gapped | os package install ./dist/objectstack.json --runtime <url> — compiled artifact sent inline, no catalog round-trip |
| REST | POST /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:
| Artifact | Convention |
|---|---|
| Object names | Always prefixed: crm_account, hd_ticket |
| Action names | Prefixed: crm_assign_owner, hd_close_ticket |
| Flow names | Prefixed: hd_overdue_alert |
| Translation keys | Scoped under the namespace: crm.account.label |
Seed externalId | <prefix>:<key>, e.g. crm:demo-account-1 |
| System names | Reserved: 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:
| Package | Provides |
|---|---|
sys.identity | sys_user, sys_organization, sys_member, sessions, API keys |
sys.feeds | sys_comment, sys_activity, sys_attachment |
sys.audit | sys_audit_log |
sys.files | sys_file |
sys.ai | ai_conversations, ai_pending_actions |
sys.settings | sys_setting |
You enable them via enable: { feeds: true, trackHistory: true, … }
on your objects — see Data Model.
Where to go next
- Marketplace — distribute packages to other tenants
- Data Model — what goes inside a package
os packagecommands — full CLI reference