Command Line Interface for building metadata-driven applications with the ObjectStack Protocol.
Built on oclif — commands are auto-discovered, and plugins can extend the CLI without modifying the main package.
pnpm add -D @objectstack/cliThe CLI is available as objectstack or the shorter alias os.
# Initialize a new project
os init my-app
# Generate metadata
os generate object task
os generate view task
os generate flow task
# Validate configuration
os validate
# Start development server
os dev
# Compile for production
os compile| Command | Description |
|---|---|
os init [name] |
Initialize a new ObjectStack project in the current directory |
os dev [package] |
Start development mode with hot reload |
os serve [config] |
Start the ObjectStack server with plugin auto-detection |
os studio [config] |
Launch Studio UI with development server |
| Command | Description |
|---|---|
os compile [config] |
Compile configuration to a JSON artifact (dist/objectstack.json) |
os validate [config] |
Validate configuration against the ObjectStack Protocol schema |
os info [config] |
Display metadata summary (objects, fields, apps, agents, etc.) |
| Command | Description |
|---|---|
os generate <type> <name> |
Generate metadata files (alias: os g) |
os create <type> [name] |
Create a new package/plugin/example from template |
Available generate types: object, view, action, flow, agent, dashboard, app
Push a locally-built package to ObjectStack Cloud and (optionally) install it
into one of your environments in a single command. Credentials and server URL
come from os cloud login (stored in ~/.objectstack/cloud.json) or the
--token / OS_CLOUD_API_KEY and --server / OS_CLOUD_URL flags.
| Command | Description |
|---|---|
os cloud login |
Authenticate to ObjectStack Cloud (browser or --email/--password); writes ~/.objectstack/cloud.json |
os cloud whoami / os cloud logout |
Inspect / clear the stored cloud session |
os environments create --org <id> --name <n> |
Provision a new environment (alias: os projects create) |
os environments list / show <id> |
List / inspect your environments |
os package publish [artifact] |
Publish dist/objectstack.json as a versioned package in your org |
Typical flow (build → publish → install into an environment, seeding sample data):
os compile # → dist/objectstack.json
os cloud login # one-time, stores the cloud session
os environments create --org "$ORG" --name "Dev" --activate
os package publish --env <env-id> --install --seed-sample-dataos package publish registers a sys_package (keyed by a reverse-domain
--manifest-id, derived from the artifact when omitted), snapshots the
artifact as a new --version, and — with --env <id> --install — installs
that version into the environment. Useful flags: --visibility private|org| marketplace, --note, and for marketplace listings --submit (request
review) or --auto-approve (platform admins only). Set OS_CLOUD_URL (or
--server) to target a non-default control plane, e.g. a staging cloud.
Runtime plugins (declared in objectstack.config.ts plugins) are loaded automatically by os serve / os dev. There is no os plugin command group in v1; runtime plugins are bundled into the build artifact. To distribute a build, publish it as a package with os package publish (see Cloud — publish & install); the legacy os projects bind <id> --artifact dist/objectstack.json path still binds an artifact directly into an environment without going through the package registry.
| Command | Description |
|---|---|
os test [files] |
Run Quality Protocol test scenarios against a running server |
os doctor |
Check development environment health |
os lint [config] |
Check configuration for style and convention issues |
os diff [before] [after] |
Compare two configurations and detect breaking changes |
| Command | Description |
|---|---|
os explain [schema] |
Display human-readable explanation of an ObjectStack schema |
| Command | Description |
|---|---|
os codemod v2-to-v3 |
Migrate ObjectStack v2 config to v3 format |
The CLI looks for objectstack.config.ts (or .js, .mjs) in the current directory:
import { defineStack } from '@objectstack/spec';
import * as objects from './src/objects';
export default defineStack({
manifest: {
id: 'com.example.my-app',
namespace: 'my_app',
version: '1.0.0',
type: 'app',
name: 'My App',
},
objects: Object.values(objects),
});dev, start, and serve all load .env files following the
Vite / Next.js convention, in this order (later files override earlier):
.env.env.${NODE_ENV}—developmentforos dev,productionforos start(override withNODE_ENV=...).env.local.env.${NODE_ENV}.local
Any variable already in the process environment wins. Typical project layout:
.env # checked in — safe defaults
.env.development # checked in — dev URLs, demo creds
.env.production # checked in — production URLs
.env.local # gitignored — secrets, personal overrides
Common variables: OS_DATABASE_URL, OS_DATABASE_DRIVER,
OS_HOME, AUTH_SECRET, PORT.
-v, --version— Show version number-h, --help— Show help
-t, --template <template>— Template:app(default),plugin,empty--no-install— Skip dependency installation
-o, --output <path>— Output path (default:dist/objectstack.json)--json— Output compile result as JSON (for CI pipelines)
--strict— Treat warnings as errors--json— Output result as JSON
-p, --port <port>— Server port. Resolution:--port›$OS_PORT›$PORT›3000. With--deva busy port auto-hops to the next free one; in production mode it's a hard error (never silently drifts).--dev— Run in development mode (load devPlugins, pretty logging)--ui— Enable Studio UI--no-server— Skip starting HTTP server plugin
-d, --dir <directory>— Override target directory
os plugins install, os plugins uninstall, os plugins update, and friends come from @oclif/plugin-plugins. They install third-party CLI extensions (oclif plugins), not runtime plugins for an ObjectStack project. See oclif's plugin docs for the full surface.
--json— Output as JSON
-v, --verbose— Show fix suggestions for warnings--scan-deprecations— Scan for deprecated patterns
The CLI uses oclif's built-in plugin system for extensibility. Third-party plugins (e.g., cloud commands, marketplace tools) can extend the CLI without modifying the main package.
- Create an oclif plugin package with its own
oclifconfig inpackage.json - Export oclif Command classes from the plugin's
src/commands/directory - Install the plugin via
os plugins install <package>or declare it in the main CLI'soclif.plugins
1. Configure the plugin's package.json:
{
"name": "@acme/plugin-marketplace",
"oclif": {
"commands": {
"strategy": "pattern",
"target": "./dist/commands",
"glob": "**/*.js"
}
}
}2. Create oclif Command classes:
// src/commands/marketplace/search.ts
import { Args, Command, Flags } from '@oclif/core';
export default class MarketplaceSearch extends Command {
static override description = 'Search marketplace applications';
static override args = {
query: Args.string({ description: 'Search query', required: true }),
};
async run() {
const { args } = await this.parse(MarketplaceSearch);
// Implementation...
}
}3. Install and use:
os plugins install @acme/plugin-marketplace
os marketplace search "crm"| Before (Commander.js) | After (oclif) |
|---|---|
Plugins declared in objectstack.config.ts |
Plugins installed via os plugins install or oclif.plugins |
Custom loadPluginCommands mechanism |
oclif's built-in plugin discovery |
contributes.commands in manifest |
oclif.commands in package.json |
Commander.js new Command(...) exports |
oclif class extends Command exports |
| Project config determines CLI commands | CLI commands available without project init |
os init # 1. Create project
os generate object customer # 2. Add a Customer object
os generate object order # 3. Add an Order object
os generate view customer # 4. Add a list view
os validate # 5. Validate everything
os dev # 6. Start dev server
os compile # 7. Build for production
os projects bind <id> --artifact dist/objectstack.json # 8. Bind to a Cloud Project
@objectstack/cli (oclif)
├── bin/run.js # Entry point (os / objectstack)
├── src/commands/ # Auto-discovered command classes
│ ├── init.ts # os init
│ ├── dev.ts # os dev
│ ├── serve.ts # os serve
│ ├── compile.ts # os compile
│ ├── validate.ts # os validate
│ ├── generate.ts # os generate (alias: g)
│ ├── projects/ # os projects <subcommand>
│ │ ├── list.ts
│ │ ├── show.ts
│ │ ├── create.ts
│ │ ├── switch.ts
│ │ └── bind.ts
│ ├── codemod/ # os codemod <subcommand>
│ │ └── v2-to-v3.ts
│ └── ...
├── src/utils/ # Shared utilities
└── package.json # oclif config under "oclif" key
objectstack serve (and os dev) auto-mount a baseline slate of
service plugins for every preset except --preset minimal:
| Capability | Plugin | Why default |
|---|---|---|
queue |
QueueServicePlugin |
Background retries (mail, audit batching) need a queue. |
job |
JobServicePlugin |
Scheduled jobs (cleanup, reports, cron). |
cache |
CacheServicePlugin |
In-memory adapter; performance baseline. |
settings |
SettingsServicePlugin |
Mail / storage / branding / feature-flag UI + persistence. |
email |
EmailServicePlugin |
Auth callbacks (verify, reset, magic-link) hard-depend. |
storage |
StorageServicePlugin |
Avatars, attachments, exports. Local fallback in dev. |
Apps no longer need to list these in requires: [...].
Opt-out: run objectstack serve --preset minimal to skip the slate
and only load core + your explicit requires.
Built-in Settings manifests: mail, storage, branding,
feature_flags are pre-registered. Both mail and storage expose a
"Test connection" action that exercises the live transport / adapter
end-to-end. Switching the storage adapter does not migrate
previously uploaded files — the plugin logs a warning on every swap.
Storage warning: when no storage: block is configured the plugin
falls back to the local driver under .objectstack/data/uploads/. In
non-dev mode a single console.warn fires at boot — switch to S3/GCS/
Azure for production by setting config.storage, OS_STORAGE_* env,
or via the Settings hub (namespace=storage).
Apache-2.0. See LICENSING.md.