App Structure & app.yaml

How a Rome App source tree is laid out, and what the app.yaml manifest declares.

Agent-readable version: Markdown · llms.txt

A Rome App is a source tree with one manifest at the root: app.yaml. The manifest declares the app identity and lists the pieces Rome should load. Files that are not listed are just files; they are not registered as actions, agents, skills, hooks, APIs, databases, or web surfaces.

Source Tree

The default scaffold has this shape:

<app-root>/
├── app.yaml
├── README.md
├── .gitignore
├── package.json
├── pnpm-workspace.yaml
├── tsconfig.json
├── components.json
├── drizzle.config.ts
├── .rome_store/
│   └── rome_store.yaml
└── src/
    ├── actions/<name>/
    │   ├── action.yaml
    │   └── index.ts
    ├── agents/<name>.yaml
    ├── api/index.ts
    ├── assets/icon.svg
    ├── db/
    │   ├── schema.ts
    │   ├── migrations/
    │   └── repositories/
    ├── skills/
    └── web/
        ├── App.tsx
        ├── components/
        ├── lib/
        └── styles.css

Only app.yaml is required for the app model. The rest depends on which capabilities the app actually ships. The scaffold does not create a src/hooks/ directory and leaves src/skills/ empty — add src/hooks/<name>/ and src/skills/<name>/SKILL.md (plus their manifest entries) when the app needs them.

  • README.md is user-facing App Store listing copy.
  • .gitignore keeps node_modules/, dist/, and .rome/ out of git.
  • package.json, pnpm-workspace.yaml, and tsconfig.json define the app workspace and build.
  • components.json is used by the scaffolded web UI component setup.
  • drizzle.config.ts is needed only when the app uses a database.
  • .rome_store/rome_store.yaml contains store-side metadata used when publishing; it is separate from the runtime manifest.
  • src/assets/icon.svg is usually referenced by app.yaml as icon: assets/icon.svg.

Delete unused scaffold files together with their manifest entries. For example, if the app has no database, remove src/db/, drizzle.config.ts, DB scripts and dependencies, and the db: block.

Build Output

Most source apps set:

appRoot: dist

With that layout, source files live under src/, and pnpm build writes the runtime app into dist/. Rome loads declared artifacts from the effective app root, so after build these manifest paths resolve under dist/:

web:
  manifest: web/manifest.json

api:
  entry: api/index

actions:
  - actions/hello

Do not edit dist/ by hand. Source-mode install rebuilds and repacks the app.

Manifest

app.yaml is strict. Unknown fields are rejected. New apps use formatVersion: 2; version 1 remains readable only for legacy bundles. Strict does not mean minimal, though: the schema also accepts a small set of optional store-listing fields (author, long_description, screenshots, category, homepage, repository).

A typical app looks like this:

formatVersion: 2
id: invoice-tracker
name: Invoice Tracker
version: 0.1.0
description: Track invoices, payments, and follow-ups.
icon: assets/icon.svg
appRoot: dist

web:
  manifest: web/manifest.json
  displayName: Invoice Tracker
  navLabel: Invoices

api:
  entry: api/index

actions:
  - actions/create-invoice
  - actions/sync-payments

agents:
  - agents/invoice-assistant.yaml

skills:
  - skills/invoice-triage

hooks:
  - hooks/channel-message

components:
  - invoice-card

db:
  migrations: db/migrations
  tablePrefix: invoice_tracker

Identity Fields

FieldRequiredNotes
formatVersionyesUse 2 for new apps. Version 1 is read only for legacy compatibility.
idyesThe machine id: lowercase letters, numbers, hyphens, starts with a letter, max 64 chars. core and self are reserved. Used in install state, paths, URLs, artifact ids, and default table naming.
versionyesValid SemVer, such as 0.1.0.
descriptionyesShort app summary used by Rome and store surfaces.
namenoHuman display name. Use Title Case words, not the kebab-case id.
iconnoPath relative to appRoot, usually assets/icon.svg after build.
appRootnoEffective runtime root. Built apps normally use dist. Required in practice for any app built with the rome CLI — the build fails without it.

Capability Fields

Each capability block is optional. Add only what the app uses.

FieldPurpose
webReact web surface mounted by the dashboard. manifest points to the built web manifest; displayName and navLabel control host labels.
apiApp-owned HTTP API. entry defaults to api/index when omitted.
actionsAction directories, each with action.yaml and index.ts.
agentsApp-owned agent YAML files.
skillsSkill directories, each usually containing SKILL.md.
hooksRuntime hook directories.
componentsInline component ids the web bundle registers and may render in chat.
dbPer-app SQLite migrations and table prefix.
suggestedChannelBindingsOptional setup hints that suggest routing a channel to one of the app's agents.

actions, agents, skills, and hooks entries are normally plain paths:

actions:
  - actions/hello

Artifact Names and References

Agent, action, and skill definitions declare an app-local name matching ^[a-z][a-z0-9_-]{0,63}$. A definition name never contains :. Rome combines the manifest App ID and local name into the runtime identity:

<app-id>:<local-name>

References and runtime calls always use that canonical ID, including references to an artifact owned by the same app. For an app with id: invoice-tracker, an action definition might say name: create_invoice, while an Agent allowlist, Routine target, or runAction call uses invoice-tracker:create_invoice.

# src/agents/invoice-assistant.yaml
name: invoice-assistant
actions:
  - invoice-tracker:create_invoice
allowedSubagents:
  - assistant:explore

Never write a bare artifact reference or self:<local-name>. Store listing IDs such as @publisher/invoice-tracker are also not runtime artifact namespaces; the manifest App ID remains the owner.

Manifest entries can use object form for compatibility metadata:

actions:
  - path: actions/create-invoice
    publicName: create_invoice

In format version 2, publicName, when present, must match the definition's local name. aliases and legacyPath exist for legacy bundles and do not create new bare-name behavior for version 2 apps.

API Options

By default, app API requests require a session. App web UIs call the dashboard surface at /api/apps/<appId>/... through fetchAppApi. Public callbacks and third-party webhooks should use /api/app-api/<appId>/...; those public subpaths can opt out with api.noAuth:

api:
  entry: api/index
  noAuth:
    - /webhooks/stripe
    - /public/*
  • noAuth: true opens every public app-api subpath.
  • noAuth: ["/path", "/prefix/*"] opens only those public subpaths.
  • Omit it for normal dashboard-only APIs reached by fetchAppApi.

api.relayWebhook is for apps that consume the core webhook relay. Most apps do not need it.

Database Options

The db: block enables app-owned SQLite migrations:

db:
  migrations: db/migrations
  tablePrefix: invoice_tracker

tablePrefix must be a SQL-safe lowercase identifier: lowercase letters, numbers, and underscores, starting with a letter. If omitted, Rome uses the app id as the prefix; when the app id contains hyphens, set tablePrefix explicitly with underscores. Real app tables are namespaced so they do not collide with system tables or other apps.

Validation Rules

Rome validates the manifest at pack/install time.

  • Unknown manifest fields fail validation.
  • formatVersion, id, version, and description are required.
  • id must be a valid app id.
  • Format version 2 action, agent, and skill names must be valid local names.
  • Format version 2 Agent actions and allowedSubagents entries must use canonical <app-id>:<local-name> references (except the special "*" action allowlist).
  • version must be valid SemVer.
  • Paths listed in the manifest must exist in the effective app root after build.
  • api.noAuth path entries must start with /.
  • db.tablePrefix, when set, must match the table-prefix rule.

The main rule is simple: the manifest and filesystem must agree. When you add a capability, add both its files and its manifest entry. When you remove a capability, remove both.

Next

  • Use Quickstart for the scaffold and install flow.
  • Use Capabilities for action, agent, API, database, and web UI implementation details.
  • Use Design Guidelines for product, mobile, icon, and README rules.

On this page