@dboio/cli 0.17.0 → 0.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +111 -85
  2. package/package.json +1 -1
  3. package/plugins/claude/dbo/docs/dbo-cli-readme.md +111 -85
  4. package/src/commands/build.js +3 -3
  5. package/src/commands/clone.js +205 -71
  6. package/src/commands/deploy.js +3 -3
  7. package/src/commands/init.js +11 -11
  8. package/src/commands/install.js +3 -3
  9. package/src/commands/login.js +2 -2
  10. package/src/commands/mv.js +15 -15
  11. package/src/commands/pull.js +1 -1
  12. package/src/commands/push.js +193 -14
  13. package/src/commands/rm.js +2 -2
  14. package/src/commands/run.js +4 -4
  15. package/src/commands/status.js +1 -1
  16. package/src/commands/sync.js +2 -2
  17. package/src/lib/config.js +186 -135
  18. package/src/lib/delta.js +119 -17
  19. package/src/lib/dependencies.js +51 -24
  20. package/src/lib/deploy-config.js +4 -4
  21. package/src/lib/domain-guard.js +8 -9
  22. package/src/lib/filenames.js +12 -1
  23. package/src/lib/ignore.js +2 -3
  24. package/src/lib/insert.js +1 -1
  25. package/src/lib/metadata-schema.js +14 -20
  26. package/src/lib/metadata-templates.js +4 -4
  27. package/src/lib/migrations.js +1 -1
  28. package/src/lib/modify-key.js +1 -1
  29. package/src/lib/scaffold.js +5 -12
  30. package/src/lib/schema.js +67 -37
  31. package/src/lib/structure.js +6 -6
  32. package/src/lib/tagging.js +2 -2
  33. package/src/lib/ticketing.js +3 -7
  34. package/src/lib/toe-stepping.js +5 -5
  35. package/src/lib/transaction-key.js +1 -1
  36. package/src/migrations/004-rename-output-files.js +2 -2
  37. package/src/migrations/005-rename-output-metadata.js +2 -2
  38. package/src/migrations/006-remove-uid-companion-filenames.js +1 -1
  39. package/src/migrations/007-natural-entity-companion-filenames.js +1 -1
  40. package/src/migrations/008-metadata-uid-in-suffix.js +1 -1
  41. package/src/migrations/009-fix-media-collision-metadata-names.js +1 -1
  42. package/src/migrations/010-delete-paren-media-orphans.js +1 -1
  43. package/src/migrations/012-project-dir-restructure.js +211 -0
package/README.md CHANGED
@@ -62,7 +62,7 @@ Once installed, use `/dbo` in Claude Code:
62
62
  /dbo push assets/css/
63
63
  ```
64
64
 
65
- The plugin source lives in `plugins/claude/dbo/` at the repository root. Installed copies in `.claude/plugins/` are gitignored and managed by `dbo install`. Each plugin's installation scope (project or global) is stored per-plugin in `.dbo/config.local.json`.
65
+ The plugin source lives in `plugins/claude/dbo/` at the repository root. Installed copies in `.claude/plugins/` are gitignored and managed by `dbo install`. Each plugin's installation scope (project or global) is stored in `~/.dbo/settings.json`.
66
66
 
67
67
  ---
68
68
 
@@ -122,8 +122,19 @@ When you run `dbo init --scaffold` or `dbo clone`, the following standard direct
122
122
 
123
123
  ```
124
124
  my-project/
125
- ├── .dbo/ # Config, synchronization and session info for dbo cli commands
125
+ ├── .app/ # Config, synchronization and session info for dbo cli commands
126
+ │ ├── config.json # Domain, app metadata, placement preferences (committed)
127
+ │ ├── <shortName>.json # Server-state baseline for delta detection (committed)
128
+ │ ├── <shortName>.metadata.json # Clone of original app JSON with @references (committed)
129
+ │ ├── <shortName>.metadata_schema.json # Column templates per entity/descriptor (committed)
130
+ │ ├── directories.json # Bin directory mapping (committed)
131
+ │ ├── synchronize.json # Pending add/edit/delete staging (committed)
132
+ │ ├── credentials.json # Username, user ID (gitignored)
133
+ │ ├── cookies.txt # Session cookie (gitignored)
134
+ │ └── scripts.json # Build/push lifecycle hooks (committed)
126
135
  ├── .claude/ # Claude Code plugin config (commands, specs, plans, skills)
136
+ ├── app_dependencies/ # Read-only checkouts of dependency apps (gitignored)
137
+ │ └── _system/ # System schema dependency
127
138
  ├── lib/ # All DBO server-managed assets
128
139
  │ ├── bins/ # Assets (contents, outputs, images, HTML, CSS)
129
140
  │ │ └── app/ # Default application bin
@@ -146,8 +157,6 @@ my-project/
146
157
  ├── test/ # Project-level tests
147
158
  ├── trash/ # Staged soft-deleted files from dbo rm
148
159
  ├── docs/ # Project documentation and docs entities
149
- ├── app.json # Clone of original app JSON with @references
150
- ├── schema.json # Instance-level entity/column schema fetched from the server during `dbo init`. Refreshed explicitly with `dbo clone --schema`.
151
160
  ├── manifest.json # PWA web app manifest (auto-generated from app metadata)
152
161
  ├── .gitignore # Tells Git to ignore files in the repo sync
153
162
  ├── .dboignore # Tells dbo cli to ignore files in commands
@@ -161,51 +170,44 @@ my-project/
161
170
 
162
171
  ## Configuration
163
172
 
164
- All configuration is **directory-scoped**. Each project folder maintains its own `.dbo/` directory with its own domain and session. Switch environments by switching directories:
173
+ All configuration is **directory-scoped**. Each project folder maintains its own `.app/` directory with its own domain and session. Switch environments by switching directories:
165
174
 
166
175
  ```bash
167
- ~/projects/my-project/ → .dbo/ → my-domain.com
168
- ~/projects/my-project-prod/ → .dbo/ → prod.dbo.io
176
+ ~/projects/my-project/ → .app/ → my-domain.com
177
+ ~/projects/my-project-prod/ → .app/ → prod.dbo.io
169
178
  ```
170
179
 
171
- ### `.dbo/` directory contents
180
+ ### `.app/` directory contents
172
181
 
173
182
  | File | Purpose | Git |
174
183
  |------|---------|-----|
175
184
  | `config.json` | Domain, app metadata, placement preferences | Committable (shared) |
176
- | `config.local.json` | Per-user settings: plugin scopes, `_completedMigrations` (system-managed) | Gitignored (per-user) |
177
- | `ticketing.local.json` | Stored ticket IDs for submission error recovery | Gitignored (per-user) |
178
185
  | `credentials.json` | Username, user ID, UID, name, email (no password) | Gitignored (per-user) |
179
186
  | `cookies.txt` | Session cookie (Netscape format) | Gitignored (per-user) |
180
- | `structure.json` | Bin directory mapping (created by `dbo clone`) | Committable (shared) |
181
- | `metadata_schema.json` | Column templates per entity/descriptor (auto-generated by `dbo clone`; renamed from `metadata_templates.json`) | Committable (shared) |
187
+ | `directories.json` | Bin directory mapping (created by `dbo clone`) | Committable (shared) |
188
+ | `<shortName>.metadata_schema.json` | Column templates per entity/descriptor (auto-generated by `dbo clone`) | Committable (shared) |
182
189
  | `synchronize.json` | Pending deletions and sync state (updated by `dbo rm` and `dbo push`) | Committable (shared) |
183
- | `.app_baseline.json` | Server-state snapshot for delta detection — stores column values at last clone/push so `dbo push` can detect which columns changed locally. Read-only (chmod 444); auto-migrated from legacy root `.app.json`. | Committable (shared) |
190
+ | `<shortName>.json` | Server-state snapshot for delta detection — stores column values at last clone/push so `dbo push` can detect which columns changed locally. Read-only (chmod 444). | Committable (shared) |
191
+ | `<shortName>.metadata.json` | Clone of original app JSON with entity entries replaced by `@path/to/*.metadata.json` references | Committable (shared) |
184
192
  | `scripts.json` | Build/push lifecycle hooks (see [Script Hooks](#script-hooks)) | Committable (shared) |
185
193
  | `scripts.local.json` | Per-user hook overrides | Gitignored (per-user) |
194
+ | `ticketing.local.json` | Stored ticket IDs for submission error recovery | Gitignored (per-user) |
186
195
 
187
- `dbo init` automatically adds `.dbo/credentials.json`, `.dbo/cookies.txt`, `.dbo/config.local.json`, `.dbo/ticketing.local.json`, and `.dbo/scripts.local.json` to `.gitignore` (creates the file if it doesn't exist).
196
+ Per-user settings (plugin scopes, completed migrations) are stored globally in `~/.dbo/settings.json`.
188
197
 
189
- > **Upgrading from pre-0.9.9**: The baseline file `.app.json` in the project root has moved to `.dbo/.app_baseline.json`. Running any `dbo` command will auto-migrate the file. You can also manually remove the `.app.json` entry from your `.gitignore`.
198
+ `dbo init` automatically adds `.app/credentials.json`, `.app/cookies.txt`, `.app/ticketing.local.json`, `.app/scripts.local.json`, `.app/errors.log`, and `app_dependencies/` to `.gitignore` (creates the file if it doesn't exist).
190
199
 
191
- > **Upgrading from pre-0.11.0**: `TransactionKeyPreset` now applies only to records that carry a `UID` column (core assets). Data records without a UID are always submitted with `RowID` regardless of the preset. Migration 001 runs automatically on first command after upgrade and logs a one-time notice.
200
+ > **Upgrading to 0.18.0+**: The project directory has been restructured: `.dbo/` is renamed to `.app/`, `app.json` moves to `.app/<shortName>.metadata.json`, `schema.json` is removed (schema now sourced from `app_dependencies/_system/`), `.dbo/dependencies/` moves to `app_dependencies/`, `.app_baseline.json` becomes `<shortName>.json`, `structure.json` becomes `directories.json`, `metadata_schema.json` becomes `<shortName>.metadata_schema.json`, and `config.local.json` moves to `~/.dbo/settings.json`. Migration 012 runs automatically on first command after upgrade.
192
201
 
193
- > **Upgrading to 0.13.3+**: Entity and extension companion files no longer include `~UID` in the filename. Migration 007 automatically renames legacy `name~uid.Column.ext` files to `name.Column.ext` and updates `@references` in metadata.
202
+ > **Upgrading to 0.16.0+**: `metadata_templates.json` is renamed to `metadata_schema.json`. The `_contentColumns` field in metadata files is renamed to `_companionReferenceColumns`. Extension companion file prompts during `dbo clone` are replaced by automatic derivation from `descriptor_definition` `form-control-code` data. Migration 011 runs automatically on first use.
194
203
 
195
- > **Upgrading to 0.14.0+**: Metadata files now use `name.metadata~uid.json` instead of `name~uid.metadata.json`. The UID has moved from the base name into the `.metadata~uid` suffix. Migration 008 automatically renames all metadata files. Output child companions use index-based naming (`Sales.column.CustomSQL.sql`, `Sales.column-1.CustomSQL.sql`) instead of UID-based naming.
196
- >
197
- > | Record type | Example metadata file |
198
- > |---|---|
199
- > | Content | `colors.metadata~abc123.json` |
200
- > | Media | `logo.png.metadata~def456.json` |
201
- > | Output | `Sales.metadata~ghi789.json` |
202
- > | Extension | `MyExtension.metadata~jkl012.json` |
204
+ > **Upgrading to 0.14.0+**: Metadata files now use `name.metadata~uid.json` instead of `name~uid.metadata.json`. Migration 008 automatically renames all metadata files.
203
205
 
204
- > **Upgrading to 0.16.0+**: `.dbo/metadata_templates.json` is renamed to `.dbo/metadata_schema.json`. The `_contentColumns` field in metadata files is renamed to `_companionReferenceColumns`. Extension companion file prompts during `dbo clone` are replaced by automatic derivation from `descriptor_definition` `form-control-code` data. Migration 011 runs automatically on first use.
206
+ > **Upgrading to 0.13.3+**: Entity and extension companion files no longer include `~UID` in the filename. Migration 007 automatically renames legacy files.
205
207
 
206
208
  #### Automatic migrations
207
209
 
208
- When the CLI version is upgraded, one-time migration scripts in `tools/cli/src/migrations/` run automatically on the first command invocation in a project directory. Completed migration IDs are recorded in `.dbo/config.local.json` under `_completedMigrations` (per-user, gitignored) so each developer runs them independently and they never re-fire.
210
+ When the CLI version is upgraded, one-time migration scripts in `tools/cli/src/migrations/` run automatically on the first command invocation in a project directory. Completed migration IDs are recorded in `~/.dbo/settings.json` under `_completedMigrations` (per-user, global) so each developer runs them independently and they never re-fire.
209
211
 
210
212
  To skip migrations for a single command run:
211
213
 
@@ -250,20 +252,20 @@ Use `dbo status` to see how many pending migrations exist.
250
252
 
251
253
  ### App Dependencies
252
254
 
253
- The CLI automatically maintains local read-only checkouts of related apps under `.dbo/dependencies/<shortname>/`. By default, the `_system` app (which contains all entity, column, and extension descriptors for the connected instance) is always included.
255
+ The CLI automatically maintains local read-only checkouts of related apps under `app_dependencies/<shortname>/`. By default, the `_system` app (which contains all entity, column, and extension descriptors for the connected instance) is always included.
254
256
 
255
257
  #### How it works
256
258
 
257
- - After `dbo init` or `dbo clone`, dependency apps are cloned into `.dbo/dependencies/`.
258
- - If an `app.json` contains a `Dependencies` column, those app short-names are merged into `.dbo/config.json` and also cloned.
259
+ - After `dbo init` or `dbo clone`, dependency apps are cloned into `app_dependencies/`.
260
+ - If an app JSON contains a `Dependencies` column, those app short-names are merged into `.app/config.json` and also cloned.
259
261
  - You can add dependencies explicitly with `dbo clone --dependencies operator,launchpad`.
260
262
  - Dependencies are only re-cloned when the server's `_LastUpdated` is newer than the locally stored timestamp — so subsequent runs are fast.
261
263
  - Dependency clone output is suppressed — a single summary line shows synced/failed/up-to-date status.
262
- - `.dbo/dependencies/` is excluded from `.gitignore` and `.dboignore` automatically.
264
+ - `app_dependencies/` is excluded from `.gitignore` and `.dboignore` automatically.
263
265
 
264
266
  #### Schema merging from dependencies
265
267
 
266
- After dependency cloning, extension descriptor definitions from dependency schemas (`.dbo/dependencies/<name>/.dbo/metadata_schema.json`) are merged into the local `.dbo/metadata_schema.json`. This is useful when an app has no `descriptor_definition` extensions of its own but depends on an app (like `operator`) that does — the operator's descriptor definitions (widget, include, control, etc.) become available for local extension processing.
268
+ After dependency cloning, extension descriptor definitions from dependency schemas (`app_dependencies/<name>/.app/<name>.metadata_schema.json`) are merged into the local `.app/<shortName>.metadata_schema.json`. This is useful when an app has no `descriptor_definition` extensions of its own but depends on an app (like `operator`) that does — the operator's descriptor definitions (widget, include, control, etc.) become available for local extension processing.
267
269
 
268
270
  #### Flags
269
271
 
@@ -276,13 +278,13 @@ After dependency cloning, extension descriptor definitions from dependency schem
276
278
 
277
279
  ### Root-level project files
278
280
 
279
- #### `app.json`
281
+ #### `.app/<shortName>.metadata.json`
280
282
 
281
- Clone of the original app JSON from the server with entity entries replaced by `@path/to/*.metadata.json` references. Created by `dbo init` (empty `{}`) and populated by `dbo clone`. Committed to git.
283
+ Clone of the original app JSON from the server with entity entries replaced by `@path/to/*.metadata.json` references. Created by `dbo clone`. Committed to git. (Formerly `app.json` in the project root.)
282
284
 
283
- #### `app.json._domain`
285
+ #### `.app/<shortName>.metadata.json._domain`
284
286
 
285
- The `_domain` field in `app.json` stores the project's reference domain (set during `dbo clone`). This is committed to git and used for domain-change detection when running `dbo init --force` or `dbo clone --domain`. It provides a stable cross-user baseline — all collaborators share the same reference domain.
287
+ The `_domain` field in the app metadata file stores the project's reference domain (set during `dbo clone`). This is committed to git and used for domain-change detection when running `dbo init --force` or `dbo clone --domain`. It provides a stable cross-user baseline — all collaborators share the same reference domain.
286
288
 
287
289
  #### `manifest.json`
288
290
 
@@ -331,9 +333,9 @@ bins/
331
333
  **Default patterns:**
332
334
 
333
335
  ```gitignore
334
- .dbo/ # DBO internal
336
+ .app/ # DBO internal
337
+ app_dependencies/ # Dependency checkouts
335
338
  *.dboio.json # Export files
336
- app.json # Clone output
337
339
  .git/ # Version control
338
340
  .gitignore
339
341
  node_modules/ # Node
@@ -406,7 +408,7 @@ dbo init --scaffold --yes # scaffold dirs non-intera
406
408
  Clone an app from DBO.io to a local project structure. Creates directories, files, metadata, and populates `config.json` and `package.json`.
407
409
 
408
410
  ```bash
409
- # Clone using config (AppShortName from .dbo/config.json)
411
+ # Clone using config (AppShortName from .app/config.json)
410
412
  dbo clone
411
413
 
412
414
  # Clone from a local JSON export file
@@ -433,7 +435,7 @@ dbo clone -e extension --descriptor-types false # Clone extensions flat (no de
433
435
  | `--documentation-only` | When used with `-e extension`, clone only documentation extensions |
434
436
  | `--descriptor-types <bool>` | Sort extensions into descriptor sub-directories (default: `true`). Set to `false` to use flat `extension/` layout |
435
437
  | `--domain <host>` | Override domain. Triggers a domain-change confirmation prompt when it differs from the project reference domain |
436
- | `--schema` | Re-fetch `schema.json` from server before cloning |
438
+ | `--schema` | Re-fetch schema from server before cloning |
437
439
  | `--force` | Skip source mismatch confirmation and change detection; re-processes all files |
438
440
  | `-y, --yes` | Auto-accept all prompts (also skips source mismatch confirmation) |
439
441
  | `-v, --verbose` | Show HTTP request details |
@@ -444,29 +446,29 @@ dbo clone -e extension --descriptor-types false # Clone extensions flat (no de
444
446
 
445
447
  #### Domain change detection
446
448
 
447
- When cloning with a different domain than the project's reference domain (`app.json._domain` or `config.json.domain`), the CLI warns before proceeding. When `TransactionKeyPreset=RowID`, this escalates to a critical error because numeric IDs are not unique across domains — pushing to the wrong domain can corrupt records. In non-interactive mode (`-y`), RowUID domain changes proceed with a warning, but RowID domain changes throw a hard error.
449
+ When cloning with a different domain than the project's reference domain (`.app/<shortName>.metadata.json._domain` or `config.json.domain`), the CLI warns before proceeding. When `TransactionKeyPreset=RowID`, this escalates to a critical error because numeric IDs are not unique across domains — pushing to the wrong domain can corrupt records. In non-interactive mode (`-y`), RowUID domain changes proceed with a warning, but RowID domain changes throw a hard error.
448
450
 
449
- The project's reference domain is stored in `app.json._domain` (committed to git) during clone, giving the CLI a stable cross-user baseline.
451
+ The project's reference domain is stored in `.app/<shortName>.metadata.json._domain` (committed to git) during clone, giving the CLI a stable cross-user baseline.
450
452
 
451
453
  #### What clone does
452
454
 
453
- 1. **Fetches schema** — downloads `schema.json` from the server if missing or explicitly requested (`--schema`). Regenerates `.dbo/metadata_schema.json` from the schema
454
- 2. **Syncs dependencies** — clones dependency apps into `.dbo/dependencies/<shortname>/` (unless `--no-deps`). Merges extension descriptor definitions from dependency schemas into the local `.dbo/metadata_schema.json` (e.g., operator provides descriptor definitions for apps that lack their own)
455
+ 1. **Fetches schema** — downloads schema from the server if missing or explicitly requested (`--schema`). Regenerates `.app/<shortName>.metadata_schema.json` from the schema
456
+ 2. **Syncs dependencies** — clones dependency apps into `app_dependencies/<shortname>/` (unless `--no-deps`). Merges extension descriptor definitions from dependency schemas into the local `.app/<shortName>.metadata_schema.json` (e.g., operator provides descriptor definitions for apps that lack their own)
455
457
  3. **Loads app JSON** — from a local file, server API, or interactive prompt. A spinner shows progress while fetching from the server (responses can be slow as the JSON is assembled on demand)
456
- 4. **Updates `.dbo/config.json`** — saves `AppID`, `AppUID`, `AppName`, `AppShortName`, `AppModifyKey` (if the app is locked), and `cloneSource` (the source used for this clone)
458
+ 4. **Updates `.app/config.json`** — saves `AppID`, `AppUID`, `AppName`, `AppShortName`, `AppModifyKey` (if the app is locked), and `cloneSource` (the source used for this clone)
457
459
  5. **Updates `package.json`** — populates `name`, `productName`, `description`, `homepage`, and `deploy` script
458
460
  6. **Creates directories** — processes `children.bin` to build the directory hierarchy based on `ParentBinID` relationships
459
- 7. **Saves `.dbo/structure.json`** — maps BinIDs to directory paths for file placement
461
+ 7. **Saves `.app/directories.json`** — maps BinIDs to directory paths for file placement
460
462
  8. **Writes content files** — decodes base64 content, creates `*.metadata.json` + content files in the correct bin directory. Filename columns and companion file extraction preferences are auto-applied with sensible defaults on first clone (use `--configure` to re-prompt)
461
- 9. **Downloads media files** — fetches binary files (images, CSS, fonts) from the server using a fallback chain: `FullPath` directly (`/media/{app}/{path}`) → `/dir/` route → `/api/media/{uid}`, and saves with metadata. 404 errors create stale metadata to prevent re-prompting. Errors are logged to `.dbo/errors.log`
463
+ 9. **Downloads media files** — fetches binary files (images, CSS, fonts) from the server using a fallback chain: `FullPath` directly (`/media/{app}/{path}`) → `/dir/` route → `/api/media/{uid}`, and saves with metadata. 404 errors create stale metadata to prevent re-prompting. Errors are logged to `.app/errors.log`
462
464
  10. **Processes entity-dir records** — entities matching project directories (`extension`, `app_version`, `data_source`, `site`, `group`, `integration`, `automation`) are saved as `.metadata.json` files in their corresponding directory (e.g., `extension/`, `data_source/`)
463
465
  11. **Processes other entities** — remaining entities with a `BinID` are placed in the corresponding bin directory
464
- 12. **Saves `app.json`** — clone of the original JSON with processed entries replaced by `@path/to/*.metadata.json` references
466
+ 12. **Saves `.app/<shortName>.metadata.json`** — clone of the original JSON with processed entries replaced by `@path/to/*.metadata.json` references
465
467
  13. **Orphan cleanup** — any local `.metadata.json` files whose UID is absent from the server response are automatically moved to `trash/` along with their companion content and media files. This prevents stale records (deleted server-side) from causing false positives in `dbo push`. Skipped during `--entity-filter` clones
466
468
 
467
469
  #### Clone source tracking
468
470
 
469
- After every successful clone, the source is persisted as `cloneSource` in `.dbo/config.json`:
471
+ After every successful clone, the source is persisted as `cloneSource` in `.app/config.json`:
470
472
 
471
473
  - `"default"` — app JSON was fetched from the server using `AppShortName` (the normal flow)
472
474
  - A file path or URL — set when an explicit `<source>` argument was provided (e.g. `dbo clone /path/to/export.json`)
@@ -505,7 +507,7 @@ When multiple records would create files at the same path (e.g., a `content` rec
505
507
  [media] colors.css (UID: def456)
506
508
  ```
507
509
 
508
- The rejected record is automatically staged for deletion in `.dbo/synchronize.json`. Run `dbo push` to delete it from the server.
510
+ The rejected record is automatically staged for deletion in `.app/synchronize.json`. Run `dbo push` to delete it from the server.
509
511
 
510
512
  In non-interactive mode (`-y`), the first record is kept and others are auto-staged for deletion.
511
513
 
@@ -565,7 +567,7 @@ During clone, the CLI:
565
567
  2. **Creates sub-directories** under `extension/` for each mapped descriptor (e.g., `extension/Documentation/`, `extension/Includes/`)
566
568
  3. **Places unmapped extensions** directly in `extension/` — extensions with an unmapped or null `Descriptor` are placed in the root `extension/` directory (the legacy `_unsupported/` sub-directory is migrated automatically by Migration 011)
567
569
  4. **Prompts per descriptor** — filename column and content extraction prompts fire once per unique `Descriptor` value (not once for all extensions)
568
- 5. **Persists the mapping** in `.dbo/structure.json` under `descriptorMapping`
570
+ 5. **Persists the mapping** in `.app/directories.json` under `descriptorMapping`
569
571
 
570
572
  **Config keys** (saved per descriptor in `config.json`):
571
573
 
@@ -593,16 +595,40 @@ dbo clone -e extension --descriptor-types false # Flat layout (no descript
593
595
 
594
596
  **`dbo adopt` auto-inference**: Running `dbo adopt docs/my-doc.md` when `ExtensionDocumentationMDPlacement` is `"root"` auto-creates a companion `.metadata.json` in `lib/extension/documentation/` with the correct `@/` reference.
595
597
 
598
+ #### Entity children embedding
599
+
600
+ When a server entity record contains nested child records (e.g., `entity_column` records nested under `entity` parents), `dbo clone` embeds them inline in the parent's `.metadata~uid.json` file under a `children` key:
601
+
602
+ ```json
603
+ {
604
+ "_entity": "entity",
605
+ "UID": "abc123",
606
+ "Name": "contact",
607
+ "children": {
608
+ "entity_column": [
609
+ { "UID": "col1", "Name": "FirstName", "PhysicalOrderNumber": 1, "_LastUpdated": "2026-01-01T00:00:00" },
610
+ { "UID": "col2", "Name": "LastName", "PhysicalOrderNumber": 2, "_LastUpdated": "2026-01-02T00:00:00" }
611
+ ]
612
+ }
613
+ }
614
+ ```
615
+
616
+ Children are stored with all fields intact (including `_LastUpdated`, `_CreatedOn`, `UID`). Base64-encoded field values within child records are decoded to plain strings. This applies generically to all entity types that contain a `children` property in the server response.
617
+
618
+ **Push behaviour**: `dbo push` detects changes within the `children` arrays by comparing against the baseline. Modified child records are submitted independently as input expressions (children before parent). Removing a child from the metadata file stages a delete in `synchronize.json`. The `children` key itself is never included in the parent's input expression.
619
+
620
+ **Output hierarchy children**: Output child records (`output_value`, `output_value_filter`, `output_value_entity_column_rel`) are also embedded inline under `children`. Only the root output's `CustomSQL` is extracted as a companion `.sql` file — child `CustomSQL` values are stored inline as decoded strings.
621
+
596
622
  #### Output structure
597
623
 
598
624
  ```
599
625
  project/
600
- .dbo/
626
+ .app/
601
627
  config.json # Updated with app metadata
602
- structure.json # Bin directory mapping
628
+ directories.json # Bin directory mapping
629
+ <shortName>.metadata.json # Clone of original with @references
603
630
  .gitignore # credentials.json + cookies.txt added
604
631
  package.json # Updated with app info + deploy script
605
- app.json # Clone of original with @references
606
632
  bins/ # ← root for all bin-placed files
607
633
  app/ # ← directory from children.bin
608
634
  thomas-scratch.md
@@ -687,7 +713,7 @@ During `dbo clone`, the CLI downloads media using a **fallback chain**:
687
713
  2. **`/dir/` route** — strips the `/media/` prefix from FullPath and uses the `/dir/` route
688
714
  3. **`/api/media/{uid}`** — UID-based endpoint as last resort (when no FullPath exists)
689
715
 
690
- If all attempts fail, the error is logged to `.dbo/errors.log` (JSONL format) with the record's UID, filename, FullPath, and error details.
716
+ If all attempts fail, the error is logged to `.app/errors.log` (JSONL format) with the record's UID, filename, FullPath, and error details.
691
717
 
692
718
  #### Output hierarchy format
693
719
 
@@ -726,7 +752,7 @@ Key points:
726
752
 
727
753
  #### Metadata Schema
728
754
 
729
- During `dbo clone`, the CLI auto-generates `.dbo/metadata_schema.json` (formerly `metadata_templates.json`) — a file that records which columns each entity/descriptor uses. This file is seeded from the first cloned record of each type and can be manually edited afterwards.
755
+ During `dbo clone`, the CLI auto-generates `.app/<shortName>.metadata_schema.json` — a file that records which columns each entity/descriptor uses. This file is seeded from the first cloned record of each type and can be manually edited afterwards.
730
756
 
731
757
  **File format:**
732
758
 
@@ -793,7 +819,7 @@ Given a record with `Name="My-Widget"`, `Extension="html"`, `Ext=""` (empty):
793
819
 
794
820
  Authenticate with a DBO.io instance and store the session cookie.
795
821
 
796
- After successful authentication, the CLI automatically fetches and stores the current user's ID, UID, name, and email in `.dbo/credentials.json`. The ID and UID are used for automatic retry when server submissions require user identity (see [Automatic error recovery](#automatic-error-recovery)). The name and email are used to populate `package.json` author fields during `dbo clone`.
822
+ After successful authentication, the CLI automatically fetches and stores the current user's ID, UID, name, and email in `.app/credentials.json`. The ID and UID are used for automatic retry when server submissions require user identity (see [Automatic error recovery](#automatic-error-recovery)). The name and email are used to populate `package.json` author fields during `dbo clone`.
797
823
 
798
824
  > **Note:** User info is currently retrieved via a separate API call after login. This is a temporary workaround — the authentication endpoint should include user info in its response directly.
799
825
 
@@ -836,13 +862,13 @@ dbo status
836
862
 
837
863
  Output:
838
864
  ```
839
- Initialized: Yes (.dbo/)
865
+ Initialized: Yes (.app/)
840
866
  Domain: my-domain.com
841
867
  Username: user@example.com
842
868
  User ID: 10296
843
869
  Directory: /Users/me/projects/operator
844
870
  Session: Active (expires: 2026-03-15T10:30:00.000Z)
845
- Cookies: /Users/me/projects/operator/.dbo/cookies.txt
871
+ Cookies: /Users/me/projects/operator/.app/cookies.txt
846
872
 
847
873
  Claude Code Plugins:
848
874
  dbo: ✓ global (~/.claude/commands/dbo.md)
@@ -850,7 +876,7 @@ Output:
850
876
 
851
877
  User ID is populated by `dbo login`. If it shows "(not set)", run `dbo login` to fetch it.
852
878
 
853
- Plugin scopes (project or global) are displayed when plugins have been installed. Scopes are stored in `.dbo/config.local.json`.
879
+ Plugin scopes (project or global) are displayed when plugins have been installed. Scopes are stored in `~/.dbo/settings.json`.
854
880
 
855
881
  ---
856
882
 
@@ -1458,7 +1484,7 @@ dbo rm --keep-local bins/app/ui/
1458
1484
  ```
1459
1485
 
1460
1486
  When removing a directory, the CLI:
1461
- 1. Looks up the BinID from `.dbo/structure.json`
1487
+ 1. Looks up the BinID from `.app/directories.json`
1462
1488
  2. Recursively collects all sub-directories (processed leaves-first)
1463
1489
  3. Prompts: "Remove all files and directories", "Prompt for each file", or "Cancel"
1464
1490
  4. Stages each file's deletion, then each bin's deletion (`entity:bin`)
@@ -1476,8 +1502,8 @@ When removing a directory, the CLI:
1476
1502
  1. **Resolves metadata** — if given a content file, finds the companion `.metadata.json`
1477
1503
  2. **Reads row ID** — uses `_id` (shorthand) or derives from entity (e.g., `ContentID`, `MediaID`)
1478
1504
  3. **Prompts for confirmation** — "Do you really want to remove this file and all of its nodes?"
1479
- 4. **Stages deletion** — adds a delete entry to `.dbo/synchronize.json`
1480
- 5. **Updates app.json** — removes the `@path/to/file.metadata.json` reference from children arrays
1505
+ 4. **Stages deletion** — adds a delete entry to `.app/synchronize.json`
1506
+ 5. **Updates app metadata** — removes the `@path/to/file.metadata.json` reference from children arrays
1481
1507
  6. **Soft-deletes local files** — renames files with `__WILL_DELETE__` prefix (unless `--keep-local` or `--hard`)
1482
1508
  7. **After `dbo push`** — successfully deleted records have their `__WILL_DELETE__` files moved to `Trash/`
1483
1509
 
@@ -1485,7 +1511,7 @@ Use `--hard` to immediately delete files without the `Trash/` safety net.
1485
1511
 
1486
1512
  #### synchronize.json
1487
1513
 
1488
- Pending deletions are stored in `.dbo/synchronize.json`:
1514
+ Pending deletions are stored in `.app/synchronize.json`:
1489
1515
 
1490
1516
  ```json
1491
1517
  {
@@ -1630,7 +1656,7 @@ When the server returns a `ticket_error` (record update requires a Ticket ID), t
1630
1656
 
1631
1657
  #### Ticket suggestions
1632
1658
 
1633
- When `TicketSuggestionOutput` is configured in `.dbo/config.json` (set during `dbo init`), the CLI automatically fetches relevant ticket suggestions from the server and presents them as selectable choices:
1659
+ When `TicketSuggestionOutput` is configured in `.app/config.json` (set during `dbo init`), the CLI automatically fetches relevant ticket suggestions from the server and presents them as selectable choices:
1634
1660
 
1635
1661
  ```
1636
1662
  ? Select a Ticket ID:
@@ -1657,7 +1683,7 @@ When the server returns a `repo_mismatch` (Ticket ID belongs to a different repo
1657
1683
  Skip all
1658
1684
  ```
1659
1685
 
1660
- Ticket selections are stored in `.dbo/ticketing.local.json` for reuse across submissions. Per-record tickets are cleaned up after successful submission; the global ticket persists until explicitly cleared. The `--ticket` flag always takes precedence over stored tickets.
1686
+ Ticket selections are stored in `.app/ticketing.local.json` for reuse across submissions. Per-record tickets are cleaned up after successful submission; the global ticket persists until explicitly cleared. The `--ticket` flag always takes precedence over stored tickets.
1661
1687
 
1662
1688
  #### Ticket ID required (legacy)
1663
1689
 
@@ -1672,7 +1698,7 @@ The submission is then retried with `_OverrideTicketID`. To skip the prompt, pas
1672
1698
 
1673
1699
  #### Pre-submission ticket prompt
1674
1700
 
1675
- When a stored ticket exists in `.dbo/ticketing.local.json`, the CLI prompts before batch submissions (`push`, `input`, `add`, `content deploy`, `deploy`):
1701
+ When a stored ticket exists in `.app/ticketing.local.json`, the CLI prompts before batch submissions (`push`, `input`, `add`, `content deploy`, `deploy`):
1676
1702
 
1677
1703
  ```
1678
1704
  ? Use stored Ticket ID "TICKET-123" for this submission?
@@ -1689,7 +1715,7 @@ When a stored ticket exists in `.dbo/ticketing.local.json`, the CLI prompts befo
1689
1715
  - **No, clear** — removes the stored `ticket_id` and proceeds without a ticket
1690
1716
  - **Cancel** — aborts the submission
1691
1717
 
1692
- #### `.dbo/ticketing.local.json`
1718
+ #### `.app/ticketing.local.json`
1693
1719
 
1694
1720
  Stores ticket IDs for automatic application during submissions:
1695
1721
 
@@ -1732,7 +1758,7 @@ The ModifyKey is detected and stored during `dbo clone`. If the key wasn't store
1732
1758
  Cancel submission
1733
1759
  ```
1734
1760
 
1735
- On successful reactive entry, the key is saved to `.dbo/config.json` for future use.
1761
+ On successful reactive entry, the key is saved to `.app/config.json` for future use.
1736
1762
 
1737
1763
  To bypass the interactive prompt entirely, pass `--modify-key <key>` on any submission command:
1738
1764
 
@@ -1811,7 +1837,7 @@ Smart behavior:
1811
1837
  - If plugins differ from source, prompts to upgrade to the latest version
1812
1838
  - Compares file hashes — unchanged files are skipped
1813
1839
  - Adds project-scoped plugins to `.gitignore` (source of truth is `plugins/claude/` at repo root)
1814
- - Per-plugin scope (project or global) is stored in `.dbo/config.local.json` and remembered for future upgrades
1840
+ - Per-plugin scope (project or global) is stored in `~/.dbo/settings.json` and remembered for future upgrades
1815
1841
  - On re-install (e.g. after `npm install` or `npm link`), scope is inferred automatically from the global plugin registry (`~/.claude/plugins/installed_plugins.json`) or existing project installation — no prompt is shown
1816
1842
  - On first install with no prior preference and no existing installation, prompts for scope
1817
1843
  - `--global` / `--local` flags override stored preferences and update them
@@ -1820,7 +1846,7 @@ Smart behavior:
1820
1846
 
1821
1847
  ### `dbo deploy`
1822
1848
 
1823
- Deploy files to DBO.io using a `.dbo/deploy_config.json` manifest or direct arguments.
1849
+ Deploy files to DBO.io using a `.app/deploy_config.json` manifest or direct arguments.
1824
1850
 
1825
1851
  ```bash
1826
1852
  # Deploy a named entry from the manifest
@@ -1841,7 +1867,7 @@ dbo deploy img:logo
1841
1867
 
1842
1868
  | Flag | Description |
1843
1869
  |------|-------------|
1844
- | `<name>` | Deployment name from `.dbo/deploy_config.json` |
1870
+ | `<name>` | Deployment name from `.app/deploy_config.json` |
1845
1871
  | `--all` | Deploy all entries in the manifest |
1846
1872
  | `-C, --confirm <true\|false>` | Commit (default: `true`) |
1847
1873
  | `--ticket <id>` | Override ticket ID |
@@ -1853,9 +1879,9 @@ dbo deploy img:logo
1853
1879
 
1854
1880
  The `deploy` command includes the same automatic error recovery as `push`, `input`, and `add` — including ticket error handling, repository mismatch recovery, user identity prompts, and ModifyKey protection. When a stored ticket exists, you'll be prompted before the first submission (see [Pre-submission ticket prompt](#pre-submission-ticket-prompt)).
1855
1881
 
1856
- #### `.dbo/deploy_config.json` manifest
1882
+ #### `.app/deploy_config.json` manifest
1857
1883
 
1858
- Create a `.dbo/deploy_config.json` file to define named deployments:
1884
+ Create a `.app/deploy_config.json` file to define named deployments:
1859
1885
 
1860
1886
  ```json
1861
1887
  {
@@ -1902,10 +1928,10 @@ This replaces the curl commands typically embedded in `package.json` scripts.
1902
1928
 
1903
1929
  #### Automatic deploy config generation
1904
1930
 
1905
- When you run `dbo clone` or `dbo adopt`, each companion file (CSS, JS, HTML, SQL, etc.) is automatically registered in `.dbo/deploy_config.json` under an `<extension>:<name>` key — no manual authoring needed:
1931
+ When you run `dbo clone` or `dbo adopt`, each companion file (CSS, JS, HTML, SQL, etc.) is automatically registered in `.app/deploy_config.json` under an `<extension>:<name>` key — no manual authoring needed:
1906
1932
 
1907
1933
  ```bash
1908
- dbo clone # → .dbo/deploy_config.json auto-populated with one entry per companion file
1934
+ dbo clone # → .app/deploy_config.json auto-populated with one entry per companion file
1909
1935
  ```
1910
1936
 
1911
1937
  Keys are derived as `<extension>:<basename>` from the companion file path. If two files share the same key, a parent directory segment is appended to disambiguate (`css:colors` and `css:admin/colors`). Entries include `entity` and `column` from the record metadata.
@@ -1923,9 +1949,9 @@ Entries are updated automatically on re-clone (path changes are reflected in pla
1923
1949
 
1924
1950
  When running `dbo deploy` (or any submission command) inside npm scripts or piped commands where stdin is not a TTY, the CLI automatically skips all interactive prompts and uses stored credentials:
1925
1951
 
1926
- - **Stored ticket** — auto-applied from `.dbo/ticketing.local.json`
1927
- - **ModifyKey** — auto-applied from `.dbo/config.json` (`AppModifyKey`)
1928
- - **User identity** — auto-applied from `.dbo/credentials.json`
1952
+ - **Stored ticket** — auto-applied from `.app/ticketing.local.json`
1953
+ - **ModifyKey** — auto-applied from `.app/config.json` (`AppModifyKey`)
1954
+ - **User identity** — auto-applied from `.app/credentials.json`
1929
1955
 
1930
1956
  If a required value is missing and no interactive prompt is possible, the command fails with a clear error message explaining how to set up the missing value.
1931
1957
 
@@ -1950,14 +1976,14 @@ To set up for non-interactive use:
1950
1976
 
1951
1977
  ## Script Hooks
1952
1978
 
1953
- Script hooks let you define build and push lifecycle commands in `.dbo/scripts.json`. Hooks run automatically during `dbo push` and can also be triggered independently with `dbo build` and `dbo run`.
1979
+ Script hooks let you define build and push lifecycle commands in `.app/scripts.json`. Hooks run automatically during `dbo push` and can also be triggered independently with `dbo build` and `dbo run`.
1954
1980
 
1955
1981
  ### Configuration Files
1956
1982
 
1957
1983
  | File | Tracked | Purpose |
1958
1984
  |------|---------|---------|
1959
- | `.dbo/scripts.json` | Yes | Shared hook definitions (committed to git) |
1960
- | `.dbo/scripts.local.json` | No | Per-user overrides (gitignored) |
1985
+ | `.app/scripts.json` | Yes | Shared hook definitions (committed to git) |
1986
+ | `.app/scripts.local.json` | No | Per-user overrides (gitignored) |
1961
1987
 
1962
1988
  ### Top-level Keys
1963
1989
 
@@ -1967,7 +1993,7 @@ Script hooks let you define build and push lifecycle commands in `.dbo/scripts.j
1967
1993
  | `targets` | Per-file or per-directory hooks (highest priority) |
1968
1994
  | `entities` | Per-entity-type hooks (e.g., `content`, `extension.control`) |
1969
1995
 
1970
- ### Example `.dbo/scripts.json`
1996
+ ### Example `.app/scripts.json`
1971
1997
 
1972
1998
  ```json
1973
1999
  {
@@ -2051,7 +2077,7 @@ dbo build
2051
2077
 
2052
2078
  ### `dbo run [script-name]`
2053
2079
 
2054
- Runs a named global script from `.dbo/scripts.json` (like `npm run`). Automatically runs `pre<name>` and `post<name>` scripts if defined.
2080
+ Runs a named global script from `.app/scripts.json` (like `npm run`). Automatically runs `pre<name>` and `post<name>` scripts if defined.
2055
2081
 
2056
2082
  ```bash
2057
2083
  # List all available scripts
@@ -2358,7 +2384,7 @@ The `dbo` CLI writes cookies in Netscape format (same as curl's `--cookie-jar`).
2358
2384
 
2359
2385
  ```bash
2360
2386
  dbo login
2361
- curl -b .dbo/cookies.txt https://my-domain.com/api/content/myUID
2387
+ curl -b .app/cookies.txt https://my-domain.com/api/content/myUID
2362
2388
  ```
2363
2389
 
2364
2390
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dboio/cli",
3
- "version": "0.17.0",
3
+ "version": "0.19.0",
4
4
  "description": "CLI for the DBO.io framework",
5
5
  "type": "module",
6
6
  "bin": {