Docs

Project Structure

A Sixb project is a set of convention folders plus one entry file. createSixb() scans definition directories under your project root, loads every module it finds, and registers the definitions you export. Other runtime components can recognize their own folders too; for example, the agent worker reads skills/ as Agent Skills. There is no central manifest: you write the file in the matching folder, and Sixb wires it in.

Directory tree

TXT
acme-corp/
├── sixb.config.ts
├── ontology/
│   ├── customer.ts
│   └── invoice.ts
├── actions/
│   └── markPaid.ts
├── functions/
│   └── check-overdue-invoices.ts
├── datasets/
│   └── erp.ts
├── connectors/
│   └── acme-erp.ts
├── syncs/
│   └── erp.ts
├── projections/
│   └── invoice-projection.ts
├── schedules/
│   └── erp.ts
├── pipelines/
│   └── project-reporting.ts
├── rules/
│   └── business-health.ts
├── workflows/
│   └── invoice-reminder.ts
├── agents/
│   └── invoice-assistant.ts
├── skills/
│   └── acme-writing-style/
│       ├── SKILL.md
│       └── references/
│           └── examples.md
├── security/
│   ├── groups/
│   │   └── finance-admins.ts
│   ├── roles/
│   │   └── finance-access.ts
│   └── policies/
│       └── member-administration.ts
└── app/                    # custom UI — served separately, not discovered
    └── page.tsx

Every folder is optional — a missing folder is skipped, not an error. You can also pass any of these definitions in-line to createSixb() instead of (or alongside) the folders.

Discovered folders

Sixb recognizes these convention folders. Most are createSixb() definition folders: each scan recurses into subdirectories and loads .ts, .tsx, .js, .jsx, .mjs, and .cjs files. The folder selects the kind: a definition picked up depends on where it lives, not what the file is named. skills/ is different: the agent worker reads Agent Skill folders and materializes them into agent sandboxes.

FolderHoldsRelated page
ontology/Object types and value typesOntology
actions/Action definitionsActions
functions/Code that runs on an interval or cron
datasets/Dataset definitionsDatasets
connectors/Connector definitionsConnectors
syncs/Sync definitionsSyncs
projections/Object, link, and telemetry projectionsProjections
schedules/Schedule definitionsSchedules
pipelines/Pipeline definitionsPipelines
rules/Rule definitionsRules
workflows/Workflow definitionsWorkflows
agents/Agent definitionsAgents
skills/Agent Skills (<name>/SKILL.md plus references/assets/scripts) read by the agent workerAgents
security/groups/Group definitionsAuthorization
security/roles/Role definitionsAuthorization
security/policies/Membership-policy definitionsAuthorization

Discovery matches exported values, not filenames. One file can export several definitions, a definition can be split across files, and an array export is flattened — so export const all = [Customer, Invoice] registers both. A helpers.ts next to your definitions is harmless: its exports just fail the kind's type guard and are ignored.

TS
// ontology/customer.ts — both exports are discovered
import { defineObjectType, link, prop, stringEnum } from "@sixb/core/ontology"
import { Employee } from "./employee"

export const Customer = defineObjectType({
  id: "Customer",
  name: "Customer",
  properties: [
    prop("id", "string", { required: true, primary: true }),
    prop("name", "string", { required: true }),
    prop("email", "string", { required: true }),
    prop("tier", stringEnum(["bronze", "silver", "gold", "platinum"])),
  ],
  links: [link("accountManager", Employee, { cardinality: "one" })],
})

export const Invoice = defineObjectType({
  id: "Invoice",
  name: "Invoice",
  properties: [prop("id", "string", { required: true, primary: true })],
})

The entry file

sixb.config.ts is the entry. It exports a runtime as a named sixb export (preferred) or as the default export. createSixb() runs discovery and returns the runtime, so the common shape is a single export:

TS
import { LocalBlobStorage } from "@sixb/blob-local"
import { createSixb, InMemoryBroker, InMemoryQueues } from "@sixb/core"
import { LocalLakeStorage } from "@sixb/lake-local"
import { SqliteStorage } from "@sixb/sqlite"

export const sixb = createSixb({
  id: "acme-corp",
  broker: new InMemoryBroker(),
  storage: new SqliteStorage({ path: ".sixb" }),
  lakeStorage: new LocalLakeStorage({ path: ".sixb/lake" }),
  blobStorage: new LocalBlobStorage({ basePath: ".sixb" }),
  queues: new InMemoryQueues(),
})

createSixb() is async, so the export is a promise here — the CLI awaits it. It accepts three shapes, which lets you run async setup such as migrations or seeding before the runtime is returned:

Export shapeExample
A runtime promiseexport const sixb = createSixb({ ... })
A function returning a runtime (sync or async)export const sixb = () => createSixb({ ... })
A resolved runtime instanceexport const sixb = await createSixb({ ... })
TS
// async entry: seed before returning the runtime
export const sixb = bootstrap()

async function bootstrap() {
  const runtime = await createSixb({ id: "acme-corp" /* ...providers */ })
  await seedCustomers(runtime)
  return runtime
}

If the export is none of these shapes, the CLI throws:

TXT
Could not load Sixb runtime from entry. Export `sixb` (or default) as a Sixb instance or Promise<Sixb>.

See Runtime for the full createSixb() options and provider list.

app/ is not discovered

The app/ folder holds your custom UI and is not part of createSixb() discovery. @sixb/app (createCustomApp) builds and serves it separately, so nothing in app/ is treated as a backend definition. Route conventions and data access for app/ are documented under Apps.

Search docs

Search the documentation