Primary AI instruction file for this repo. Mirrored at .github/copilot-instructions.md — keep both in sync.
v5.0 breaking rename:
project→environmenteverywhere (CLI-e,/api/v1/environments/:id, headerX-Environment-Id,OS_ENVIRONMENT_ID, DB columnenvironment_id). No aliases. See ADR-0006. "Project" now only means the npm/monorepo sense.
pnpm install # deps
pnpm setup # first-time: install + build spec
pnpm build # turbo build (excludes docs)
pnpm test # turbo test
pnpm docs:dev # docs site| Scenario | Command | Notes |
|---|---|---|
Frontend debug (UI in ../objectui calls backend) |
PORT=3000 pnpm dev |
pnpm dev = the showcase kitchen-sink app (default; best for exercising the platform). Port must be 3000 (UI hard-wired); persistent state; leave running. For the minimal CRM app instead: PORT=3000 pnpm dev:crm. |
| Backend-only debug | pnpm dev -- --fresh -p <random> |
Random high port; ephemeral tempdir; you must kill it when done |
--fresh: ephemeral tempdir (auto-deleted on exit) + --seed-admin (POSTs sign-up, prints creds — default admin@objectos.ai / admin123, override via --admin-email/--admin-password). The seeded admin is auto-promoted to platform admin (the system seed identity usr_system is skipped), so Setup/Studio are reachable on first login.
Rules: never run two backends on port 3000; for backend tasks pick a random port and tear it down; always use a pnpm dev/dev:crm/dev:showcase script (flags after -- are forwarded), not raw pnpm --filter.
pnpm dev:crm -- --fresh -p 38421 # start; debug via curl
kill $(lsof -ti tcp:38421) # tear down — tempdir auto-deletesThis repo ships backend only. All Studio/Console UI work happens in ../objectui (separate repo, checked out next to framework/). Workflow: edit + commit + push in ../objectui, then in framework/ run pnpm objectui:refresh to pull its build into packages/console/.
Other scripts: objectui:bump (pull only), objectui:build, objectui:clean. packages/console/dist/ or .cache/objectui-*/ — regenerated.
Fast iteration on ../objectui src (no commit/refresh loop): run objectui's own console dev server — cd ../objectui && pnpm --filter @object-ui/console dev (Vite on :5180, HMR). Its /api proxy targets DEV_PROXY_TARGET || http://localhost:3000, so run the backend you're testing on :3000 (PORT=3000 pnpm dev for showcase) and browse :5180. Note :3001/_console (or whatever the backend serves) is the published console, not your ../objectui src — only :5180 reflects local UI edits. See ../objectui/AGENTS.md for the app-id / localStorage / auth gotchas.
- Zod First. All schemas start as Zod. Types via
z.infer<typeof X>. JSON Schemas generated from Zod. - No business logic in
packages/spec. Spec = schemas/types/constants only. Runtime logic goes incore,runtime, orservices/*. - Naming:
- TS config keys →
camelCase(maxLength,defaultValue) - Machine names (data values) →
snake_case(name: 'first_name') - Metadata type names → singular (
'agent','view','flow') — matchesMetadataTypeSchemainpackages/spec/src/kernel/metadata-plugin.zod.ts - REST endpoints → plural (
/api/v1/ai/agents)
- TS config keys →
- Imports: Use
@objectstack/specnamespaces or subpaths. Never relative../../packages/spec. - No workarounds. Adopt sustainable, well-architected solutions — not temporary patches.
- Object name = table name. The object
nameis the canonical id everywhere (API, ObjectQL, REST, SDK, DB table). Never setnamespace(deprecated) ortableName(always equalsname). For module prefixes, embed in the name (sys_user,ai_conversations). - One Zod source per metadata type. Each type (
view,flow,agent, …) has exactly one schema inpackages/spec/src/{domain}/. Org overlay opt-in lives only inallowOrgOverrideonDEFAULT_METADATA_TYPE_REGISTRY— no parallel whitelists. See ADR-0005. - North Star alignment. Read
content/docs/concepts/north-star.mdxbefore structural changes. If a change doesn't advance §7 Built, shrink Drift, or unlock Missing — it probably shouldn't ship. OS_env-var prefix. All ObjectStack-owned env vars MUST start withOS_. When renaming a legacy var, usereadEnvWithDeprecation('OS_NEW', 'LEGACY')from@objectstack/types(keeps legacy working one release). Third-party exceptions kept as-is:NODE_ENV,HOME,OPENAI_API_KEY,TURSO_*, OAuth*_CLIENT_ID/SECRET,RESEND_API_KEY,POSTMARK_TOKEN,AI_GATEWAY_*,SMTP_*. See #1382.
packages/
spec/ # 🏛️ Protocol schemas, types, constants (Zod source of truth)
core/ # ⚙️ ObjectKernel, DI, EventBus
types/ # 📦 Shared TS utilities
metadata/ # 📋 Metadata loading & persistence
objectql/ # 🔍 Query engine
runtime/ # 🏃 Bootstrap (Driver/App plugins)
rest/ # 🌐 Auto-generated REST layer
client/ # 📡 Framework-agnostic SDK
client-react/ # ⚛️ React hooks
cli/ # 🖥️ CLI
create-objectstack/ # 🚀 Scaffolding
vscode-objectstack/ # 🧩 VS Code extension
adapters/ # 🔌 express/fastify/hono/nestjs/nextjs/nuxt/sveltekit
plugins/ # 🧱 Official plugins & drivers
services/ # 🔧 Kernel-managed services
apps/docs/ # 📖 Fumadocs site
examples/ # 📚 Reference implementations
skills/ # 🤖 Domain skill definitions
content/docs/ # 📝 Docs content
Studio UI: ../objectui (sibling repo).
| Namespace | Path | Responsibility |
|---|---|---|
Data |
data/ |
Object, Field, FieldType, Query, Filter, Sort |
UI |
ui/ |
App, View (grid/kanban/calendar/gantt), Dashboard, Report, Action |
System |
system/ |
Manifest, Datasource, API endpoints, Translation (i18n) |
Automation |
automation/ |
Flow, Workflow, Trigger registry |
AI |
ai/ |
Agent, Tool, Skill, RAG, Model registry |
API |
api/ |
REST/GraphQL contract, Endpoint, Realtime |
Identity |
identity/ |
User, Organization, Profile |
Security |
security/ |
Permission, Role, Policy |
Kernel |
kernel/ |
Plugin lifecycle (PluginContext) |
Cloud |
cloud/ |
Multi-tenant, deployment, environment |
QA |
qa/ |
Test, validation |
Contracts |
contracts/ |
Cross-package interfaces |
Integration |
integration/ |
External integrations |
Studio |
studio/ |
Studio UI metadata |
Shared |
shared/ |
Error maps, normalization utilities |
Root also exports: defineStack, composeStacks, defineView, defineApp, defineFlow, defineAgent, defineTool, defineSkill.
| Kernel | Use For |
|---|---|
ObjectKernel |
Default production runtime. Full DI / EventBus / Plugin lifecycle. |
LiteKernel |
Tests (vitest), serverless, edge (Workers). |
EnhancedObjectKernel is deprecated — do not use.
| Path | Type | Rule |
|---|---|---|
content/docs/references/ |
AUTO-GEN | ❌ Never hand-edit. Regenerated by packages/spec/scripts/build-docs.ts. |
content/docs/guides/ |
hand-written | ✅ Update meta.json when adding pages. |
content/docs/concepts/ |
hand-written | ✅ |
content/docs/getting-started/ |
hand-written | ✅ |
content/docs/protocol/ |
hand-written | ✅ |
| Path | Role | Key Constraints |
|---|---|---|
**/objectstack.config.ts |
Project Architect | defineStack, driver/adapter selection |
packages/spec/src/data/** |
Data Architect | Zod-first, snake_case, TSDoc every prop |
packages/spec/src/ui/** |
UI Protocol Designer | View types, SDUI patterns |
packages/spec/src/automation/** |
Automation Architect | Flow/Workflow state machines |
packages/spec/src/ai/** |
AI Protocol Designer | Agent/Tool/Skill schemas |
packages/spec/src/system/** |
System Architect | Manifest, datasource, i18n |
packages/spec/src/kernel/** |
Kernel Engineer | Plugin lifecycle, PluginContext |
packages/spec/src/security/** |
Security Architect | RBAC, policies |
packages/core/** |
Kernel Engineer | Runtime logic OK here |
packages/runtime/** |
Runtime Engineer | Bootstrap, plugin registration |
packages/rest/** |
API Engineer | Route gen, middleware |
packages/plugins/** |
Plugin Developer | Implements spec contracts |
packages/services/** |
Service Engineer | Kernel-managed services |
packages/adapters/** |
Integration Engineer | Framework bindings, zero business logic |
packages/client*/** |
SDK Engineer | Public API, DX, type safety |
apps/docs/** |
Docs Engineer | Fumadocs + Next.js, MDX |
examples/** |
Example Author | Minimal, runnable, uses defineStack |
content/docs/** |
Technical Writer | Respect auto-gen boundaries |
../objectui/** (sibling repo) |
Studio UI Engineer | React + Shadcn + Tailwind, dark mode default |
Consult the matching SKILL.md when working in its domain: objectstack-platform, objectstack-data, objectstack-query, objectstack-api, objectstack-ui, objectstack-automation, objectstack-ai, objectstack-i18n, objectstack-formula (CEL).
Zod schema:
export const FieldSchema = z.object({
name: z.string().regex(/^[a-z_][a-z0-9_]*$/).describe('Machine name (snake_case)'),
label: z.string().describe('Display label'),
type: FieldTypeSchema,
maxLength: z.number().optional(),
defaultValue: z.any().optional(),
});
export type Field = z.infer<typeof FieldSchema>;Plugin:
export default {
async onInstall(ctx: PluginContext) { /* migrations */ },
async onEnable(ctx: PluginContext) { /* register routes/services */ },
async onDisable(ctx: PluginContext) { /* cleanup */ },
};pnpm test— verify nothing broke.- Add a changeset for feature work. When the change is a feature or functional improvement, run
pnpm changeset(or add a.changeset/*.mdentry) describing it before committing. Pure bug fixes do not require a changeset. - Update
CHANGELOG.md/ROADMAP.mdif user-facing or architectural. - Delete temporary artifacts — screenshots, traces, scratch logs,
.playwright-mcp/, throwawaytmp*.ts, ad-hoc scripts. Repo must look identical to before, minus intended changes.
Keep single edit/create payloads under ~20KB. Split larger changes into multiple sequential edits.