@dboio/cli 0.9.8 → 0.11.1

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 (38) hide show
  1. package/README.md +172 -70
  2. package/bin/dbo.js +2 -0
  3. package/bin/postinstall.js +9 -1
  4. package/package.json +3 -3
  5. package/plugins/claude/dbo/commands/dbo.md +3 -3
  6. package/plugins/claude/dbo/skills/cli/SKILL.md +3 -3
  7. package/src/commands/add.js +50 -0
  8. package/src/commands/clone.js +720 -552
  9. package/src/commands/content.js +7 -3
  10. package/src/commands/deploy.js +22 -7
  11. package/src/commands/diff.js +41 -3
  12. package/src/commands/init.js +42 -79
  13. package/src/commands/input.js +5 -0
  14. package/src/commands/login.js +2 -2
  15. package/src/commands/mv.js +3 -0
  16. package/src/commands/output.js +8 -10
  17. package/src/commands/pull.js +268 -87
  18. package/src/commands/push.js +814 -94
  19. package/src/commands/rm.js +4 -1
  20. package/src/commands/status.js +12 -1
  21. package/src/commands/sync.js +71 -0
  22. package/src/lib/client.js +10 -0
  23. package/src/lib/config.js +80 -8
  24. package/src/lib/delta.js +178 -25
  25. package/src/lib/diff.js +150 -20
  26. package/src/lib/folder-icon.js +120 -0
  27. package/src/lib/ignore.js +2 -3
  28. package/src/lib/input-parser.js +37 -10
  29. package/src/lib/metadata-templates.js +21 -4
  30. package/src/lib/migrations.js +75 -0
  31. package/src/lib/save-to-disk.js +1 -1
  32. package/src/lib/scaffold.js +58 -3
  33. package/src/lib/structure.js +158 -21
  34. package/src/lib/toe-stepping.js +381 -0
  35. package/src/migrations/001-transaction-key-preset-scope.js +35 -0
  36. package/src/migrations/002-move-entity-dirs-to-lib.js +190 -0
  37. package/src/migrations/003-move-deploy-config.js +50 -0
  38. package/src/migrations/004-rename-output-files.js +101 -0
package/README.md CHANGED
@@ -20,7 +20,7 @@ This installs the `dbo` command globally on your system.
20
20
  ### From the repository (local development)
21
21
 
22
22
  ```bash
23
- cd tools/dbo-cli
23
+ cd tools/cli
24
24
  npm install
25
25
  npm link
26
26
  ```
@@ -108,7 +108,7 @@ dbo login
108
108
  dbo status
109
109
 
110
110
  # 4. Query some data
111
- dbo output -e user --format json --maxrows 5
111
+ dbo output -e user --template json_indented --maxrows 5
112
112
 
113
113
  # 5. Deploy a CSS file
114
114
  dbo content deploy albain3dwkofbhnd1qtd1q assets/css/colors.css
@@ -124,28 +124,38 @@ When you run `dbo init --scaffold` or `dbo clone`, the following standard direct
124
124
  my-project/
125
125
  ├── .dbo/ # Config, synchronization and session info for dbo cli commands
126
126
  ├── .claude/ # Claude Code plugin config (commands, specs, plans, skills)
127
- ├── node_modules/ # Automatically created; contains all external libraries
127
+ ├── lib/ # All DBO server-managed assets
128
+ │ ├── bins/ # Assets (contents, outputs, images, HTML, CSS)
129
+ │ │ └── app/ # Default application bin
130
+ │ ├── automation/ # Automation entity records
131
+ │ ├── app_version/ # App version entity records
132
+ │ ├── entity/ # Entity definitions
133
+ │ ├── entity_column/ # Column definitions
134
+ │ ├── entity_column_value/ # Column value definitions
135
+ │ ├── extension/ # Extension entity records (organized by descriptor type)
136
+ │ │ ├── widget/
137
+ │ │ ├── documentation/
138
+ │ │ └── _unsupported/
139
+ │ ├── integration/ # Integration entity records
140
+ │ ├── security/ # Security policy records
141
+ │ ├── security_column/ # Column-level security records
142
+ │ ├── data_source/ # (created when data sources exist)
143
+ │ ├── group/ # (created when groups exist)
144
+ │ ├── site/ # (created when sites exist)
145
+ │ └── redirect/ # (created when redirects exist)
128
146
  ├── src/ # Your actual source code (sass, typescript, etc.)
129
- ├── tests/ # Project-level tests
130
- ├── bins/ # Assets (contents, outputs, images, HTML, CSS)
147
+ ├── test/ # Project-level tests
131
148
  ├── trash/ # Staged soft-deleted files from dbo rm
132
- ├── automation/ # Automation entity records
133
- ├── app_version/ # App version entity records
134
- ├── data_source/ # Data source entity records
135
149
  ├── docs/ # Project documentation and docs entities
136
- ├── extension/ # Extension entity records
137
- ├── <DescriptorType>/ # Sub-directory per descriptor type (e.g., component/, form/)
138
- │ └── _unsupported/ # Extensions with unrecognized descriptor types
139
- ├── group/ # Group entity records
140
- ├── integration/ # Integration entity records
141
- ├── site/ # Site entity records
150
+ ├── app.json # Clone of original app JSON with @references
151
+ ├── manifest.json # PWA web app manifest (auto-generated from app metadata)
142
152
  ├── .gitignore # Tells Git to ignore files in the repo sync
143
153
  ├── .dboignore # Tells dbo cli to ignore files in commands
144
154
  ├── package.json # Metadata, scripts, and dependency list
145
155
  └── package-lock.json # Records exact versions of dependencies installed
146
156
  ```
147
157
 
148
- > **Breaking change from pre-0.9.1**: Directory names have changed from mixed-case (`Extensions/`, `App Versions/`, `bins/`) to lowercase snake_case (`extension/`, `app_version/`, `bins/`). If you have an existing project, rename your directories manually before running `dbo clone` again.
158
+ > **Breaking change in 0.11.1**: All server-managed directories (`bins/`, `extension/`, `automation/`, etc.) have moved into a `lib/` subdirectory. Existing projects are migrated **automatically** on the first `dbo` command after upgrade. Also, `tests/` has been renamed to `test/`.
149
159
 
150
160
  ---
151
161
 
@@ -163,15 +173,34 @@ All configuration is **directory-scoped**. Each project folder maintains its own
163
173
  | File | Purpose | Git |
164
174
  |------|---------|-----|
165
175
  | `config.json` | Domain, app metadata, placement preferences | Committable (shared) |
166
- | `config.local.json` | Per-user settings: plugin scopes, future user prefs | Gitignored (per-user) |
176
+ | `config.local.json` | Per-user settings: plugin scopes, `_completedMigrations` (system-managed) | Gitignored (per-user) |
167
177
  | `ticketing.local.json` | Stored ticket IDs for submission error recovery | Gitignored (per-user) |
168
178
  | `credentials.json` | Username, user ID, UID, name, email (no password) | Gitignored (per-user) |
169
179
  | `cookies.txt` | Session cookie (Netscape format) | Gitignored (per-user) |
170
180
  | `structure.json` | Bin directory mapping (created by `dbo clone`) | Committable (shared) |
171
181
  | `metadata_templates.json` | Column templates per entity/descriptor (auto-generated by `dbo clone`) | Committable (shared) |
182
+ | `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) |
172
184
 
173
185
  `dbo init` automatically adds `.dbo/credentials.json`, `.dbo/cookies.txt`, `.dbo/config.local.json`, and `.dbo/ticketing.local.json` to `.gitignore` (creates the file if it doesn't exist).
174
186
 
187
+ > **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`.
188
+
189
+ > **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.
190
+
191
+ #### Automatic migrations
192
+
193
+ 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.
194
+
195
+ To skip migrations for a single command run:
196
+
197
+ ```bash
198
+ dbo push bins/ --no-migrate
199
+ dbo clone --app myapp --no-migrate
200
+ ```
201
+
202
+ Use `dbo status` to see how many pending migrations exist.
203
+
175
204
  #### config.json reference
176
205
 
177
206
  ```json
@@ -182,8 +211,7 @@ All configuration is **directory-scoped**. Each project folder maintains its own
182
211
  "AppName": "My App",
183
212
  "AppShortName": "myapp",
184
213
  "cloneSource": "default",
185
- "ContentPlacement": "bin",
186
- "MediaPlacement": "fullpath"
214
+ "ContentPlacement": "bin"
187
215
  }
188
216
  ```
189
217
 
@@ -195,24 +223,39 @@ All configuration is **directory-scoped**. Each project folder maintains its own
195
223
  | `AppName` | string | App display name |
196
224
  | `AppShortName` | string | App short name (used for `dbo clone --app`) |
197
225
  | `AppModifyKey` | string | ModifyKey for locked/production apps (set by `dbo clone`, used for submission guards) |
198
- | `TransactionKeyPreset` | `RowUID` \| `RowID` | Row key type for auto-assembled expressions (set during `dbo init`/`dbo clone`, default `RowUID`) |
199
- | `TicketSuggestionOutput` | string | Output UID for fetching ticket suggestions during error recovery (set during `dbo init`, default `ojaie9t3o0kfvliahnuuda`) |
226
+ | `TransactionKeyPreset` | `RowUID` \| `RowID` | Row key type (auto-set to `RowUID` during init/clone) |
227
+ | `TicketSuggestionOutput` | string | Output UID for ticket suggestions (auto-set during init, default `ojaie9t3o0kfvliahnuuda`) |
200
228
  | `cloneSource` | `"default"` \| file path \| URL | Where the last `dbo clone` fetched app JSON from. `"default"` = server fetch via `AppShortName`; any other value = the explicit local file path or URL used. Set automatically after each successful clone. |
201
- | `ContentPlacement` | `bin` \| `path` \| `ask` | Where to place content files during clone |
202
- | `MediaPlacement` | `bin` \| `fullpath` \| `ask` | Where to place media files during clone |
229
+ | `ContentPlacement` | `bin` \| `path` | Where to place content files during clone (default: `bin`) |
203
230
  | `<Entity>FilenameCol` | column name | Filename column for entity-dir records (e.g., `ExtensionFilenameCol`) |
204
231
 
205
- **Placement values:**
206
- - `bin` — Place files in the BinID-mapped directory (from `structure.json`)
207
- - `path` / `fullpath` — Place files in the Path/FullPath directory from the record
208
- - `ask` — Prompt for each file that has both a BinID and a Path/FullPath
232
+ **File placement:** All content, media, and output files are placed by BinID into the `lib/bins/` directory structure. Records without a BinID go into `lib/bins/` root. Media always uses BinID — no FullPath option. Bins with `Name=null` (legacy) map directly to `lib/bins/` root.
233
+
234
+ ### Root-level project files
209
235
 
210
- These are set interactively on first clone and saved for future use. Pre-set them in `config.json` to skip the prompt entirely.
236
+ #### `app.json`
237
+
238
+ 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.
211
239
 
212
240
  #### `app.json._domain`
213
241
 
214
242
  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.
215
243
 
244
+ #### `manifest.json`
245
+
246
+ A [PWA web app manifest](https://developer.mozilla.org/en-US/docs/Web/Manifest) auto-generated during scaffolding (`dbo init` or `dbo clone`). Values are derived from `app.json` when available:
247
+
248
+ | Field | Source |
249
+ |-------|--------|
250
+ | `name` | `<AppName> \| <domain>` |
251
+ | `short_name` | `AppShortName` |
252
+ | `description` | `App.Description` |
253
+ | `start_url` / `scope` | `/app/<ShortName>/ui/` |
254
+ | `background_color` | Extracted from the `widget` extension matching the app's `ShortName` (field `String4`), defaults to `#ffffff` |
255
+ | `theme_color` | `#000000` |
256
+
257
+ The file is only created if absent — it is never overwritten by subsequent clones, so local edits (icons, screenshots, display overrides) are preserved. A companion `manifest.metadata.json` is auto-created by `dbo push` if missing, allowing the manifest to be pushed to the server as a content record.
258
+
216
259
  ### `.dboignore`
217
260
 
218
261
  A gitignore-style file in the project root that controls which files and directories are excluded from CLI operations. Created automatically by `dbo init` with sensible defaults.
@@ -248,8 +291,6 @@ bins/
248
291
  .dbo/ # DBO internal
249
292
  *.dboio.json # Export files
250
293
  app.json # Clone output
251
- .app.json # Clone baseline
252
- dbo.deploy.json # Deployment manifest
253
294
  .git/ # Version control
254
295
  .gitignore
255
296
  node_modules/ # Node
@@ -257,7 +298,10 @@ package.json
257
298
  package-lock.json
258
299
  .claude/ # AI / tooling
259
300
  .mcp.json
260
- .idea/ # Editor / IDE
301
+ .DS_Store # Editor / IDE / OS
302
+ Thumbs.db
303
+ Icon\r
304
+ .idea/
261
305
  .vscode/
262
306
  *.codekit3
263
307
  README.md # Repo scaffolding
@@ -308,7 +352,6 @@ dbo init --scaffold --yes # scaffold dirs non-intera
308
352
  | `--local` | Install Claude commands to project (`.claude/commands/`) |
309
353
  | `--scaffold` | Pre-create standard project directories (`app_version`, `automation`, `bins`, `data_source`, `docs`, `extension`, `group`, `integration`, `site`, `src`, `tests`, `trash`) |
310
354
  | `--dboignore` | Create `.dboignore` with default patterns (use with `--force` to overwrite existing) |
311
- | `--media-placement <placement>` | Set media placement when cloning: `fullpath` or `binpath` (default: `bin`) |
312
355
  | `-y, --yes` | Skip all interactive prompts (legacy migration, Claude Code setup) |
313
356
  | `--non-interactive` | Alias for `--yes` |
314
357
 
@@ -345,7 +388,6 @@ dbo clone -e extension --descriptor-types false # Clone extensions flat (no de
345
388
  | `-e, --entity <type>` | Only clone a specific entity type (e.g. `output`, `content`, `media`, `extension`) |
346
389
  | `--documentation-only` | When used with `-e extension`, clone only documentation extensions |
347
390
  | `--descriptor-types <bool>` | Sort extensions into descriptor sub-directories (default: `true`). Set to `false` to use flat `extension/` layout |
348
- | `--media-placement <placement>` | Set media placement: `fullpath` or `binpath` (default: `bin`). Skips interactive media placement prompt |
349
391
  | `--domain <host>` | Override domain. Triggers a domain-change confirmation prompt when it differs from the project reference domain |
350
392
  | `--force` | Skip source mismatch confirmation and change detection; re-processes all files |
351
393
  | `-y, --yes` | Auto-accept all prompts (also skips source mismatch confirmation) |
@@ -365,7 +407,7 @@ The project's reference domain is stored in `app.json._domain` (committed to git
365
407
  4. **Creates directories** — processes `children.bin` to build the directory hierarchy based on `ParentBinID` relationships
366
408
  5. **Saves `.dbo/structure.json`** — maps BinIDs to directory paths for file placement
367
409
  6. **Writes content files** — decodes base64 content, creates `*.metadata.json` + content files in the correct bin directory. When a record's `Extension` field is empty, prompts you to choose from `css`, `js`, `html`, `xml`, `txt`, `md`, `cs`, `json`, `sql` (or skip to keep no extension). The chosen extension is saved back into the `metadata.json` `Extension` field
368
- 7. **Downloads media files** — fetches binary files (images, CSS, fonts) from the server via `/api/media/{uid}` and saves with metadata
410
+ 7. **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. Errors are logged to `.dbo/errors.log`
369
411
  8. **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/`)
370
412
  9. **Processes other entities** — remaining entities with a `BinID` are placed in the corresponding bin directory
371
413
  10. **Saves `app.json`** — clone of the original JSON with processed entries replaced by `@path/to/*.metadata.json` references
@@ -524,54 +566,107 @@ project/
524
566
  MySQL-Primary.metadata.json
525
567
  site/
526
568
  MainSite.metadata.json
527
- media/operator/app/... # FullPath placement (when MediaPlacement=fullpath)
569
+ # Media files placed by BinID into bins/ (alongside content)
528
570
  ```
529
571
 
530
- #### Understanding the `bins/` directory structure
572
+ #### Understanding the `lib/bins/` directory structure
531
573
 
532
- The `bins/` directory is the default location for all bin-placed content files during clone. It organizes files according to your app's bin hierarchy from DBO.io.
574
+ The `lib/bins/` directory is the default location for all bin-placed content files during clone. It organizes files according to your app's bin hierarchy from DBO.io.
533
575
 
534
576
  **Directory Organization:**
535
577
 
536
- - **`bins/`** — Root directory for all bin-placed files (local organizational directory only)
537
- - **`bins/app/`** — Special subdirectory for the main app bin (typically the default bin)
538
- - **`bins/custom_name/`** — Custom bin directories (e.g., `tpl/`, `ticket_test/`, etc.)
578
+ - **`lib/bins/`** — Root directory for all bin-placed files (local organizational directory only)
579
+ - **`lib/bins/app/`** — Special subdirectory for the main app bin (typically the default bin)
580
+ - **`lib/bins/custom_name/`** — Custom bin directories (e.g., `tpl/`, `ticket_test/`, etc.)
539
581
 
540
- **Important: The `bins/app/` special case**
582
+ **Important: The `lib/bins/app/` special case**
541
583
 
542
- The `app/` subdirectory under `bins/` is treated specially:
584
+ The `app/` subdirectory under `lib/bins/` is treated specially:
543
585
 
544
- 1. **It's organizational only** — The `bins/app/` prefix exists only for local file organization and is **not part of the server-side path**.
586
+ 1. **It's organizational only** — The `lib/bins/app/` prefix exists only for local file organization and is **not part of the server-side path**.
545
587
 
546
- 2. **Path normalization** — When comparing paths (during `dbo push`), the CLI automatically strips both `bins/` and `app/` from paths:
588
+ 2. **Path normalization** — When comparing paths (during `dbo push`), the CLI automatically strips both `lib/bins/` and `app/` from paths:
547
589
  ```
548
- Local file: bins/app/assets/css/operator.css
590
+ Local file: lib/bins/app/assets/css/operator.css
549
591
  Server Path: assets/css/operator.css
550
592
  → These are considered the same path ✓
551
593
  ```
552
594
 
553
- 3. **Custom bins are preserved** — Other subdirectories like `bins/tpl/` or `bins/ticket_test/` represent actual bin hierarchies and their names are meaningful:
595
+ 3. **Custom bins are preserved** — Other subdirectories like `lib/bins/tpl/` or `lib/bins/ticket_test/` represent actual bin hierarchies and their names are meaningful:
554
596
  ```
555
- Local file: bins/tpl/header.html
597
+ Local file: lib/bins/tpl/header.html
556
598
  Server Path: tpl/header.html
557
599
  → The 'tpl/' directory is preserved ✓
558
600
  ```
559
601
 
560
602
  **Why this matters:**
561
603
 
562
- - When you `dbo push` files from `bins/app/`, the CLI knows these paths should match the root-level paths in your metadata
563
- - If your metadata `Path` column contains `assets/css/colors.css`, it will correctly match files in `bins/app/assets/css/colors.css`
564
- - Custom bin directories like `bins/tpl/` serve from the `tpl/` directive and maintain their path structure
604
+ - When you `dbo push` files from `lib/bins/app/`, the CLI knows these paths should match the root-level paths in your metadata
605
+ - If your metadata `Path` column contains `assets/css/colors.css`, it will correctly match files in `lib/bins/app/assets/css/colors.css`
606
+ - Custom bin directories like `lib/bins/tpl/` serve from the `tpl/` directive and maintain their path structure
565
607
 
566
608
  **Leading slash handling:**
567
609
 
568
610
  The CLI handles leading `/` in metadata paths flexibly:
569
- - `Path: assets/css/file.css` matches `bins/app/assets/css/file.css` ✓
570
- - `Path: /assets/css/file.css` also matches `bins/app/assets/css/file.css` ✓
571
- - `Path: /assets/css/file.css` matches `bins/assets/css/file.css` ✓
611
+ - `Path: assets/css/file.css` matches `lib/bins/app/assets/css/file.css` ✓
612
+ - `Path: /assets/css/file.css` also matches `lib/bins/app/assets/css/file.css` ✓
613
+ - `Path: /assets/css/file.css` matches `lib/bins/assets/css/file.css` ✓
572
614
 
573
615
  This ensures compatibility with various path formats from the server while maintaining correct local file organization.
574
616
 
617
+ #### Media file serving (API)
618
+
619
+ The DBO.io server provides three routes for serving media files:
620
+
621
+ | Route | Example | Description |
622
+ |-------|---------|-------------|
623
+ | `/media/{app}/{path}` | `/media/todoes/App/assets/fonts/file.ttf` | Legacy FullPath — the value stored in the media record's `FullPath` column |
624
+ | `/dir/{app}/{bins}/{file}` | `/dir/todoes/App/assets/fonts/file.ttf` | Modern BinID-based route — parses `appShortName/binHierarchy/filename` |
625
+ | `/api/media/{uid}` | `/api/media/ujrOQPCdUEamNJdAjUQdYA` | UID-based endpoint — looks up media by unique identifier |
626
+
627
+ During `dbo clone`, the CLI downloads media using a **fallback chain**:
628
+
629
+ 1. **FullPath** (`/media/...`) — uses the record's `FullPath` column directly
630
+ 2. **`/dir/` route** — strips the `/media/` prefix from FullPath and uses the `/dir/` route
631
+ 3. **`/api/media/{uid}`** — UID-based endpoint as last resort (when no FullPath exists)
632
+
633
+ If all attempts fail, the error is logged to `.dbo/errors.log` (JSONL format) with the record's UID, filename, FullPath, and error details.
634
+
635
+ #### Output hierarchy format
636
+
637
+ Each root output record produces a **single compound JSON file** containing all child entities (columns, joins, filters) embedded inline:
638
+
639
+ ```
640
+ bins/app/
641
+ _output~Sales~abc123.json ← root output with inline children
642
+ _output~Sales~abc123.column~col1.CustomSQL.sql ← companion SQL file
643
+ ```
644
+
645
+ The root JSON structure:
646
+ ```json
647
+ {
648
+ "_entity": "output",
649
+ "UID": "abc123",
650
+ "Name": "Sales",
651
+ "children": {
652
+ "column": [
653
+ { "_entity": "output_value", "UID": "col1", "Title": "Amount", "children": { "column": [], "join": [], "filter": [] } }
654
+ ],
655
+ "join": [],
656
+ "filter": [
657
+ { "_entity": "output_value_filter", "UID": "f1", "ShortName": "Active", "children": { "column": [], "join": [], "filter": [] } }
658
+ ]
659
+ }
660
+ }
661
+ ```
662
+
663
+ Key points:
664
+ - All three child keys (`column`, `join`, `filter`) are always present (empty arrays when unused)
665
+ - Each child retains `_entity` set to its physical table name for push routing
666
+ - Children nest recursively following FK relationships (e.g. a column can have filters)
667
+ - `CustomSQL` content is extracted to companion `.sql` files per extraction rules
668
+ - Re-cloning moves orphaned old-format child `.json` files to `/trash`
669
+
575
670
  #### Metadata Templates
576
671
 
577
672
  During `dbo clone`, the CLI auto-generates `.dbo/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.
@@ -730,16 +825,16 @@ Query data from DBO.io outputs or entities.
730
825
  dbo output qfkyyp2vxeaggdeo7dwbig
731
826
 
732
827
  # Entity query
733
- dbo output -e user --format json
828
+ dbo output -e user --template json_indented
734
829
 
735
830
  # Single record
736
831
  dbo output -e user --row 10296
737
832
 
738
833
  # With filtering and sorting
739
- dbo output -e user --filter 'FirstName=John' --sort 'LastName:asc' --format json
834
+ dbo output -e user --filter 'FirstName=John' --sort 'LastName:asc' --template json_indented
740
835
 
741
836
  # Contains filter
742
- dbo output -e content --filter 'Name:contains=color' --format json
837
+ dbo output -e content --filter 'Name:contains=color' --template json_indented
743
838
 
744
839
  # Pagination
745
840
  dbo output -e user --page 2 --rows-per-page 25
@@ -763,18 +858,17 @@ dbo output myOutputUID --debug-sql
763
858
  | `-e, --entity <uid>` | Query by entity UID |
764
859
  | `--row <id>` | Specific row ID |
765
860
  | `--filter <expr>` | Filter expression (repeatable) |
766
- | `--format <type>` | Output format: `json`, `html`, `csv`, `xml`, `txt`, `pdf` |
861
+ | `--template <value>` | Output template: `json_raw` (default), `json_indented`, `json`, `html`, `csv`, `xml`, `txt`, `pdf`, or a content UID for custom templates |
767
862
  | `--sort <expr>` | Sort expression (repeatable), e.g., `LastName:asc` |
768
863
  | `--search <expr>` | Full-text search |
769
864
  | `--page <n>` | Page number |
770
865
  | `--rows-per-page <n>` | Rows per page |
771
866
  | `--maxrows <n>` | Maximum rows |
772
867
  | `--rows <range>` | Row range, e.g., `1-10` |
773
- | `--template <value>` | Custom template |
774
868
  | `--limit <n>` | Maximum rows to return (preferred over `--maxrows`) |
775
869
  | `--rowcount <bool>` | Include row count: `true` (default) or `false` for performance |
776
870
  | `--display <expr>` | Show/hide template tags (repeatable), e.g., `sidebar=hide` |
777
- | `--format-values` | Enable value formatting in `json_raw` output |
871
+ | `--format-values` | Enable value formatting with `--template json_raw` |
778
872
  | `--empty-response-code <code>` | HTTP status code when output returns no results |
779
873
  | `--fallback-content <expr>` | Fallback content UID for error codes, e.g., `404=contentUID` |
780
874
  | `--escape-html <bool>` | Control HTML escaping: `true` or `false` |
@@ -840,14 +934,14 @@ dbo content ykqucv0eb0ggjqgcncj6dq
840
934
  dbo content ykqucv0eb0ggjqgcncj6dq -o local/file.html
841
935
 
842
936
  # Get as plain text (disable minification)
843
- dbo content ykqucv0eb0ggjqgcncj6dq --format txt --no-minify
937
+ dbo content ykqucv0eb0ggjqgcncj6dq --template txt --no-minify
844
938
  ```
845
939
 
846
940
  | Flag | Description |
847
941
  |------|-------------|
848
942
  | `<uid>` | Content UID |
849
943
  | `-o, --output <path>` | Save to local file |
850
- | `--format <type>` | Output format |
944
+ | `--template <value>` | Output template (e.g., `json_raw`, `html`, `txt`, or a content UID) |
851
945
  | `--no-minify` | Disable minification |
852
946
  | `--json` | Output raw JSON |
853
947
 
@@ -1194,9 +1288,16 @@ The `@colors.css` reference tells push to read the content from that file. All o
1194
1288
  | `--meta-only` | Only push metadata, skip file content |
1195
1289
  | `--content-only` | Only push file content, skip metadata |
1196
1290
  | `-y, --yes` | Auto-accept all prompts |
1291
+ | `--toe-stepping <true\|false>` | Check server for conflicts before pushing (default: `true`). Set to `false` to skip the check and push unconditionally |
1197
1292
  | `--json` | Output raw JSON |
1198
1293
  | `--jq <expr>` | Filter JSON response |
1199
1294
 
1295
+ #### Server conflict detection (toe-stepping)
1296
+
1297
+ By default, `dbo push` checks the live server state before submitting changes. For each record being pushed, it fetches the current server version and compares `_LastUpdated` against the local baseline. If another user has modified a record since your last `dbo clone` or `dbo push`, you'll see a conflict warning with the name of the user who made the server-side change and a per-column diff of what changed.
1298
+
1299
+ You can then choose to overwrite the server changes or cancel and pull first. Use `--toe-stepping false` to disable the check entirely, or `--yes` to auto-accept conflicts (useful for CI/scripts).
1300
+
1200
1301
  ---
1201
1302
 
1202
1303
  ### `dbo rm`
@@ -1526,7 +1627,7 @@ If no stored user info is available, it prompts for direct input. The CLI automa
1526
1627
 
1527
1628
  ### `dbo install` (alias: `dbo i`)
1528
1629
 
1529
- Install or upgrade dbo-cli components including the CLI itself, plugins, and Claude Code integration.
1630
+ Install or upgrade dbo cli components including the CLI itself, plugins, and Claude Code integration.
1530
1631
 
1531
1632
  ```bash
1532
1633
  # Interactive — choose what to install
@@ -1584,7 +1685,7 @@ Smart behavior:
1584
1685
 
1585
1686
  ### `dbo deploy`
1586
1687
 
1587
- Deploy files to DBO.io using a `dbo.deploy.json` manifest or direct arguments.
1688
+ Deploy files to DBO.io using a `.dbo/deploy_config.json` manifest or direct arguments.
1588
1689
 
1589
1690
  ```bash
1590
1691
  # Deploy a named entry from the manifest
@@ -1605,7 +1706,7 @@ dbo deploy img:logo
1605
1706
 
1606
1707
  | Flag | Description |
1607
1708
  |------|-------------|
1608
- | `<name>` | Deployment name from `dbo.deploy.json` |
1709
+ | `<name>` | Deployment name from `.dbo/deploy_config.json` |
1609
1710
  | `--all` | Deploy all entries in the manifest |
1610
1711
  | `-C, --confirm <true\|false>` | Commit (default: `true`) |
1611
1712
  | `--ticket <id>` | Override ticket ID |
@@ -1617,9 +1718,9 @@ dbo deploy img:logo
1617
1718
 
1618
1719
  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)).
1619
1720
 
1620
- #### `dbo.deploy.json` manifest
1721
+ #### `.dbo/deploy_config.json` manifest
1621
1722
 
1622
- Create a `dbo.deploy.json` file in your project root to define named deployments:
1723
+ Create a `.dbo/deploy_config.json` file to define named deployments:
1623
1724
 
1624
1725
  ```json
1625
1726
  {
@@ -1749,7 +1850,7 @@ dbo message myUID --jq '.Successful'
1749
1850
  | `.[] \| .field` | Pipe: iterate then access |
1750
1851
  | `.["key.name"]` | Bracket notation for keys with dots |
1751
1852
 
1752
- When `--jq` is used, the API request is automatically made with `_format=json`.
1853
+ When `--jq` is used, the API request is automatically made with `_template=json_raw`.
1753
1854
 
1754
1855
  ### JSON syntax highlighting
1755
1856
 
@@ -1834,14 +1935,15 @@ _search@ColumnName=keyword # search specific column
1834
1935
  #### Template & Format
1835
1936
 
1836
1937
  ```
1837
- _template=json_raw # format name: json_raw, html, json, json_indented, csv, xml, txt, pdf
1938
+ _template=json_raw # system template name: json_raw, json_indented, json, html, csv, xml, txt, pdf
1838
1939
  _template=3iX9fHFTL064Shgol8Bktw # content UID (custom template)
1839
1940
  _format_values=true # enable value formatting in json_raw
1840
- _format=json # legacy format specifier
1841
1941
  _mime=application/json # override MIME/content type
1842
1942
  _escape_html=false # disable HTML escaping of data values
1843
1943
  ```
1844
1944
 
1945
+ > **`_format` is deprecated.** Do not use `_format` — use `_template` instead. The `_format` key is demoted and retained only for backwards compatibility in the API. Do not use `_format` in combination with `_template` — combining both in a single request causes broken responses.
1946
+
1845
1947
  #### Display Control
1846
1948
 
1847
1949
  ```
@@ -1973,12 +2075,12 @@ dbo upload image.jpg --bin 12345 --app 67890 --ownership app --path assets/image
1973
2075
 
1974
2076
  **Before:**
1975
2077
  ```bash
1976
- curl -b .cookies "https://my-domain.com/api/output/entity/user?_format=json&_filter@FirstName=John"
2078
+ curl -b .cookies "https://my-domain.com/api/output/entity/user?_template=json_indented&_filter@FirstName=John"
1977
2079
  ```
1978
2080
 
1979
2081
  **After:**
1980
2082
  ```bash
1981
- dbo output -e user --filter 'FirstName=John' --format json
2083
+ dbo output -e user --filter 'FirstName=John' --template json_indented
1982
2084
  ```
1983
2085
 
1984
2086
  ### Cookie compatibility
package/bin/dbo.js CHANGED
@@ -30,6 +30,7 @@ import { cloneCommand } from '../src/commands/clone.js';
30
30
  import { diffCommand } from '../src/commands/diff.js';
31
31
  import { rmCommand } from '../src/commands/rm.js';
32
32
  import { mvCommand } from '../src/commands/mv.js';
33
+ import { syncCommand } from '../src/commands/sync.js';
33
34
 
34
35
  // First-run welcome message
35
36
  function checkFirstRun() {
@@ -89,6 +90,7 @@ program.addCommand(cloneCommand);
89
90
  program.addCommand(diffCommand);
90
91
  program.addCommand(rmCommand);
91
92
  program.addCommand(mvCommand);
93
+ program.addCommand(syncCommand);
92
94
 
93
95
  // Show welcome message on first run
94
96
  checkFirstRun();
@@ -3,6 +3,9 @@
3
3
  // Post-install hook for `npm i @dboio/cli`
4
4
  // Interactive plugin picker when TTY is available, static message otherwise.
5
5
 
6
+ import { dirname, join } from 'path';
7
+ import { fileURLToPath } from 'url';
8
+
6
9
  const RESET = '\x1b[0m';
7
10
  const BOLD = '\x1b[1m';
8
11
  const DIM = '\x1b[2m';
@@ -14,12 +17,17 @@ function write(message) {
14
17
  console.log(message);
15
18
  }
16
19
 
20
+ // Resolve path to dbo.js entrypoint — used instead of bare `dbo` command
21
+ // because during npm postinstall the bin symlink may not be on PATH yet.
22
+ const __dirname = dirname(fileURLToPath(import.meta.url));
23
+ const DBO_BIN = join(__dirname, 'dbo.js');
24
+
17
25
  // Available plugins — add new entries here as plugins are created
18
26
  const PLUGINS = [
19
27
  {
20
28
  name: 'dbo',
21
29
  label: 'Claude Code — /dbo:cli slash command',
22
- command: 'dbo install --claudecommand dbo'
30
+ command: `node "${DBO_BIN}" install --claudecommand dbo`
23
31
  }
24
32
  ];
25
33
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dboio/cli",
3
- "version": "0.9.8",
3
+ "version": "0.11.1",
4
4
  "description": "CLI for the DBO.io framework",
5
5
  "type": "module",
6
6
  "bin": {
@@ -39,9 +39,9 @@
39
39
  "repository": {
40
40
  "type": "git",
41
41
  "url": "https://github.com/dboio/api.git",
42
- "directory": "tools/dbo-cli"
42
+ "directory": "tools/cli"
43
43
  },
44
- "homepage": "https://github.com/dboio/api/tree/master/tools/dbo-cli#readme",
44
+ "homepage": "https://github.com/dboio/api/tree/master/tools/cli#readme",
45
45
  "bugs": {
46
46
  "url": "https://github.com/dboio/api/issues"
47
47
  }
@@ -74,7 +74,7 @@ Available subcommands:
74
74
  - `rm <directory>` — Remove a directory, all files, and sub-directories recursively
75
75
  - `rm -f <path>` — Remove without confirmation prompts
76
76
  - `rm --keep-local <path>` — Stage server deletions without deleting local files/directories
77
- - `deploy [name]` — Deploy via dbo.deploy.json manifest
77
+ - `deploy [name]` — Deploy via .dbo/deploy_config.json manifest
78
78
  - `install` (alias: `i`) — Install or upgrade CLI, plugins, or Claude commands
79
79
  - `i dbo` or `i dbo@latest` — Install/upgrade the CLI from npm
80
80
  - `i dbo@0.4.1` — Install a specific CLI version
@@ -235,8 +235,8 @@ Flags: `--app <name>`, `--domain <host>`, `-y/--yes`, `-v/--verbose`
235
235
  3. Updates `package.json` with `name`, `productName`, `description`, `homepage`, and `deploy` script
236
236
  4. Creates directory structure from `children.bin` hierarchy → saves `.dbo/structure.json`
237
237
  5. Writes content files (decodes base64) with `*.metadata.json` into bin directories
238
- 6. Downloads media files from server via `/api/media/{uid}` with `*.metadata.json`
239
- 7. Processes entity-dir records (`extension`, `app_version`, `data_source`, `site`, `group`, `integration`, `automation`) into project directories (`Extensions/`, `Data Sources/`, etc.) as `.metadata.json` files with optional companion content files
238
+ 6. Downloads media files from server using fallback chain: FullPath (`/media/{app}/{path}`) → `/dir/` route → `/api/media/{uid}`, with `*.metadata.json`. Errors logged to `.dbo/errors.log`
239
+ 7. Processes entity-dir records (`extension`, `app_version`, `data_source`, `site`, `group`, `integration`, `automation`) into `lib/` project directories as `.metadata.json` files with optional companion content files
240
240
  8. Processes remaining entities with BinID into corresponding bin directories
241
241
  9. Saves `app.json` to project root with `@path/to/*.metadata.json` references
242
242
 
@@ -80,7 +80,7 @@ Available subcommands:
80
80
  - `rm <directory>` — Remove a directory, all files, and sub-directories recursively
81
81
  - `rm -f <path>` — Remove without confirmation prompts
82
82
  - `rm --keep-local <path>` — Stage server deletions without deleting local files/directories
83
- - `deploy [name]` — Deploy via dbo.deploy.json manifest
83
+ - `deploy [name]` — Deploy via .dbo/deploy_config.json manifest
84
84
  - `install` (alias: `i`) — Install or upgrade CLI, plugins, or Claude commands
85
85
  - `i dbo` or `i dbo@latest` — Install/upgrade the CLI from npm
86
86
  - `i dbo@0.4.1` — Install a specific CLI version
@@ -241,8 +241,8 @@ Flags: `--app <name>`, `--domain <host>`, `-y/--yes`, `-v/--verbose`
241
241
  3. Updates `package.json` with `name`, `productName`, `description`, `homepage`, and `deploy` script
242
242
  4. Creates directory structure from `children.bin` hierarchy → saves `.dbo/structure.json`
243
243
  5. Writes content files (decodes base64) with `*.metadata.json` into bin directories
244
- 6. Downloads media files from server via `/api/media/{uid}` with `*.metadata.json`
245
- 7. Processes entity-dir records (`extension`, `app_version`, `data_source`, `site`, `group`, `integration`, `automation`) into project directories (`Extensions/`, `Data Sources/`, etc.) as `.metadata.json` files with optional companion content files
244
+ 6. Downloads media files from server using fallback chain: FullPath (`/media/{app}/{path}`) → `/dir/` route → `/api/media/{uid}`, with `*.metadata.json`. Errors logged to `.dbo/errors.log`
245
+ 7. Processes entity-dir records (`extension`, `app_version`, `data_source`, `site`, `group`, `integration`, `automation`) into `lib/` project directories as `.metadata.json` files with optional companion content files
246
246
  8. Processes remaining entities with BinID into corresponding bin directories
247
247
  9. Saves `app.json` to project root with `@path/to/*.metadata.json` references
248
248