@dboio/cli 0.11.4 → 0.15.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 (57) hide show
  1. package/README.md +183 -3
  2. package/bin/dbo.js +6 -0
  3. package/package.json +1 -1
  4. package/plugins/claude/dbo/.claude-plugin/plugin.json +1 -1
  5. package/plugins/claude/dbo/commands/dbo.md +66 -243
  6. package/plugins/claude/dbo/docs/_audit_required/API/all.md +40 -0
  7. package/plugins/claude/dbo/docs/_audit_required/API/app.md +38 -0
  8. package/plugins/claude/dbo/docs/_audit_required/API/athenticate.md +26 -0
  9. package/plugins/claude/dbo/docs/_audit_required/API/cache.md +29 -0
  10. package/plugins/claude/dbo/docs/_audit_required/API/content.md +14 -0
  11. package/plugins/claude/dbo/docs/_audit_required/API/data_source.md +28 -0
  12. package/plugins/claude/dbo/docs/_audit_required/API/email.md +18 -0
  13. package/plugins/claude/dbo/docs/_audit_required/API/input.md +25 -0
  14. package/plugins/claude/dbo/docs/_audit_required/API/instance.md +28 -0
  15. package/plugins/claude/dbo/docs/_audit_required/API/log.md +8 -0
  16. package/plugins/claude/dbo/docs/_audit_required/API/media.md +12 -0
  17. package/plugins/claude/dbo/docs/_audit_required/API/output_by_entity.md +12 -0
  18. package/plugins/claude/dbo/docs/_audit_required/API/upload.md +7 -0
  19. package/plugins/claude/dbo/docs/_audit_required/dbo-api-syntax.md +1487 -0
  20. package/plugins/claude/dbo/docs/_audit_required/dbo-problems-code.md +111 -0
  21. package/plugins/claude/dbo/docs/_audit_required/dbo-problems-performance.md +109 -0
  22. package/plugins/claude/dbo/docs/_audit_required/dbo-problems-syntax.md +97 -0
  23. package/plugins/claude/dbo/docs/_audit_required/dbo-product-market.md +119 -0
  24. package/plugins/claude/dbo/docs/_audit_required/dbo-white-paper.md +125 -0
  25. package/plugins/claude/dbo/docs/dbo-cheat-sheet.md +323 -0
  26. package/plugins/claude/dbo/docs/dbo-cli-readme.md +2279 -0
  27. package/plugins/claude/dbo/docs/dbo-core-entities.md +878 -0
  28. package/plugins/claude/dbo/docs/dbo-output-customsql.md +677 -0
  29. package/plugins/claude/dbo/docs/dbo-output-query.md +967 -0
  30. package/plugins/claude/dbo/skills/cli/SKILL.md +63 -246
  31. package/src/commands/add.js +373 -64
  32. package/src/commands/build.js +102 -0
  33. package/src/commands/clone.js +719 -212
  34. package/src/commands/deploy.js +9 -2
  35. package/src/commands/diff.js +7 -3
  36. package/src/commands/init.js +16 -2
  37. package/src/commands/input.js +3 -1
  38. package/src/commands/login.js +30 -4
  39. package/src/commands/mv.js +28 -7
  40. package/src/commands/push.js +298 -78
  41. package/src/commands/rm.js +21 -6
  42. package/src/commands/run.js +81 -0
  43. package/src/commands/tag.js +65 -0
  44. package/src/lib/config.js +67 -0
  45. package/src/lib/delta.js +7 -1
  46. package/src/lib/deploy-config.js +137 -0
  47. package/src/lib/diff.js +28 -5
  48. package/src/lib/filenames.js +198 -54
  49. package/src/lib/ignore.js +6 -0
  50. package/src/lib/input-parser.js +13 -4
  51. package/src/lib/scaffold.js +1 -1
  52. package/src/lib/scripts.js +232 -0
  53. package/src/lib/tagging.js +380 -0
  54. package/src/lib/toe-stepping.js +2 -1
  55. package/src/migrations/006-remove-uid-companion-filenames.js +181 -0
  56. package/src/migrations/007-natural-entity-companion-filenames.js +165 -0
  57. package/src/migrations/008-metadata-uid-in-suffix.js +70 -0
@@ -0,0 +1,2279 @@
1
+ # dbo — Command Line Interface for DBO.io
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@dboio/cli.svg)](https://www.npmjs.com/package/@dboio/cli)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@dboio/cli.svg)](https://www.npmjs.com/package/@dboio/cli)
5
+
6
+ A terminal-based CLI for interacting with the [DBO.io](https://dbo.io) framework. Replaces raw curl commands with a clean, subcommand-driven interface for CRUD operations, querying, content deployment, media management, and more.
7
+
8
+ **Available on npm:** [@dboio/cli](https://www.npmjs.com/package/@dboio/cli)
9
+
10
+ ## Installation
11
+
12
+ ### From npm (recommended)
13
+
14
+ ```bash
15
+ npm install -g @dboio/cli
16
+ ```
17
+
18
+ This installs the `dbo` command globally on your system.
19
+
20
+ ### From the repository (local development)
21
+
22
+ ```bash
23
+ cd tools/cli
24
+ npm install
25
+ npm link
26
+ ```
27
+
28
+ ### Without installing (npx)
29
+
30
+ ```bash
31
+ npx @dboio/cli <command>
32
+ ```
33
+
34
+ > **Shorthand:** You can use `dbo i` as a shortcut for `dbo install` (similar to `npm i`).
35
+
36
+ ### Requirements
37
+
38
+ - **Node.js 18+** (uses native `fetch` and `FormData`)
39
+ - A DBO.io instance to connect to
40
+
41
+ ## Claude Code Integration
42
+
43
+ The dbo CLI can be used as a `/dbo` slash command inside Claude Code sessions.
44
+
45
+ ### Install Claude Code commands
46
+
47
+ ```bash
48
+ # Install the /dbo command into your project's .claude/commands/
49
+ dbo install claudecommands
50
+
51
+ # Install globally to ~/.claude/commands/ (shared across projects)
52
+ dbo install claudecommands --global
53
+
54
+ # Or install Claude Code CLI + commands together
55
+ dbo install claudecode
56
+ ```
57
+
58
+ Once installed, use `/dbo` in Claude Code:
59
+ ```
60
+ /dbo pull albain3dwkofbhnd1qtd1q
61
+ /dbo output -e user --maxrows 5
62
+ /dbo push assets/css/
63
+ ```
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`.
66
+
67
+ ---
68
+
69
+ ## Upgrading
70
+
71
+ The `dbo install` command handles both fresh installs and upgrades. If a component is already installed, it will prompt you to upgrade to the latest version.
72
+
73
+ ```bash
74
+ # Upgrade CLI to latest version
75
+ dbo install dbo@latest
76
+
77
+ # Install/upgrade to a specific version
78
+ dbo install dbo@0.4.1
79
+
80
+ # Upgrade from local source
81
+ dbo install /path/to/local/cli/src
82
+
83
+ # Upgrade Claude Code commands (prompts if already installed)
84
+ dbo install plugins
85
+
86
+ # Upgrade a specific Claude command
87
+ dbo install --claudecommand dbo
88
+
89
+ # Check your version
90
+ dbo --version
91
+ ```
92
+
93
+ ---
94
+
95
+ ## Quick Start
96
+
97
+ ```bash
98
+ # 1. Initialize configuration for the current directory
99
+ dbo init --domain my-domain.com
100
+
101
+ # 1b. Combined with cloning an app to local project bin
102
+ dbo init --domain my-domain.com --app myapp --clone
103
+
104
+ # 2. Authenticate
105
+ dbo login
106
+
107
+ # 3. Check your session
108
+ dbo status
109
+
110
+ # 4. Query some data
111
+ dbo output -e user --template json_indented --maxrows 5
112
+
113
+ # 5. Deploy a CSS file
114
+ dbo content deploy albain3dwkofbhnd1qtd1q assets/css/colors.css
115
+ ```
116
+
117
+ ---
118
+
119
+ ## Project Directory Structure
120
+
121
+ When you run `dbo init --scaffold` or `dbo clone`, the following standard directories are created in your project root:
122
+
123
+ ```
124
+ my-project/
125
+ ├── .dbo/ # Config, synchronization and session info for dbo cli commands
126
+ ├── .claude/ # Claude Code plugin config (commands, specs, plans, skills)
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)
146
+ ├── src/ # Your actual source code (sass, typescript, etc.)
147
+ ├── test/ # Project-level tests
148
+ ├── trash/ # Staged soft-deleted files from dbo rm
149
+ ├── docs/ # Project documentation and docs entities
150
+ ├── app.json # Clone of original app JSON with @references
151
+ ├── manifest.json # PWA web app manifest (auto-generated from app metadata)
152
+ ├── .gitignore # Tells Git to ignore files in the repo sync
153
+ ├── .dboignore # Tells dbo cli to ignore files in commands
154
+ ├── package.json # Metadata, scripts, and dependency list
155
+ └── package-lock.json # Records exact versions of dependencies installed
156
+ ```
157
+
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/`.
159
+
160
+ ---
161
+
162
+ ## Configuration
163
+
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:
165
+
166
+ ```bash
167
+ ~/projects/my-project/ → .dbo/ → my-domain.com
168
+ ~/projects/my-project-prod/ → .dbo/ → prod.dbo.io
169
+ ```
170
+
171
+ ### `.dbo/` directory contents
172
+
173
+ | File | Purpose | Git |
174
+ |------|---------|-----|
175
+ | `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
+ | `credentials.json` | Username, user ID, UID, name, email (no password) | Gitignored (per-user) |
179
+ | `cookies.txt` | Session cookie (Netscape format) | Gitignored (per-user) |
180
+ | `structure.json` | Bin directory mapping (created by `dbo clone`) | Committable (shared) |
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) |
184
+ | `scripts.json` | Build/push lifecycle hooks (see [Script Hooks](#script-hooks)) | Committable (shared) |
185
+ | `scripts.local.json` | Per-user hook overrides | Gitignored (per-user) |
186
+
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).
188
+
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`.
190
+
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.
192
+
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.
194
+
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` |
203
+
204
+ #### Automatic migrations
205
+
206
+ 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.
207
+
208
+ To skip migrations for a single command run:
209
+
210
+ ```bash
211
+ dbo push bins/ --no-migrate
212
+ dbo clone --app myapp --no-migrate
213
+ ```
214
+
215
+ Use `dbo status` to see how many pending migrations exist.
216
+
217
+ #### config.json reference
218
+
219
+ ```json
220
+ {
221
+ "domain": "my-domain.com",
222
+ "AppID": 10198,
223
+ "AppUID": "abc123",
224
+ "AppName": "My App",
225
+ "AppShortName": "myapp",
226
+ "cloneSource": "default",
227
+ "ContentPlacement": "bin"
228
+ }
229
+ ```
230
+
231
+ | Key | Values | Description |
232
+ |-----|--------|-------------|
233
+ | `domain` | hostname | DBO.io instance to connect to |
234
+ | `AppID` | number | App ID (set by `dbo clone`, used by `dbo add`/`dbo input`) |
235
+ | `AppUID` | string | App UID |
236
+ | `AppName` | string | App display name |
237
+ | `AppShortName` | string | App short name (used for `dbo clone --app`) |
238
+ | `AppModifyKey` | string | ModifyKey for locked/production apps (set by `dbo clone`, used for submission guards) |
239
+ | `TransactionKeyPreset` | `RowUID` \| `RowID` | Row key type (auto-set to `RowUID` during init/clone) |
240
+ | `TicketSuggestionOutput` | string | Output UID for ticket suggestions (auto-set during init, default `ojaie9t3o0kfvliahnuuda`) |
241
+ | `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. |
242
+ | `ContentPlacement` | `bin` \| `path` | Where to place content files during clone (default: `bin`) |
243
+ | `<Entity>FilenameCol` | column name | Filename column for entity-dir records (e.g., `ExtensionFilenameCol`) |
244
+
245
+ **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.
246
+
247
+ ### Root-level project files
248
+
249
+ #### `app.json`
250
+
251
+ 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.
252
+
253
+ #### `app.json._domain`
254
+
255
+ 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.
256
+
257
+ #### `manifest.json`
258
+
259
+ 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:
260
+
261
+ | Field | Source |
262
+ |-------|--------|
263
+ | `name` | `<AppName> \| <domain>` |
264
+ | `short_name` | `AppShortName` |
265
+ | `description` | `App.Description` |
266
+ | `start_url` / `scope` | `/app/<ShortName>/ui/` |
267
+ | `background_color` | Extracted from the `widget` extension matching the app's `ShortName` (field `String4`), defaults to `#ffffff` |
268
+ | `theme_color` | `#000000` |
269
+
270
+ 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.
271
+
272
+ ### `.dboignore`
273
+
274
+ 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.
275
+
276
+ **Used by:**
277
+ - `dbo init` — scaffold empty-check (determines if directory is "effectively empty")
278
+ - `dbo add .` — directory scanning (which files/dirs to skip); also checked in single-file mode (`dbo add file.html`)
279
+ - `dbo push` — metadata file discovery: skips matching `.metadata.json` / `_output~*.json` files AND any record whose companion content file (`@reference`) matches an ignore pattern
280
+
281
+ **Bypass:** Use `dbo input -d '...'` to submit expressions for a file that would otherwise be ignored — `dbo input` never does file discovery so `.dboignore` does not apply.
282
+
283
+ **Pattern examples:**
284
+
285
+ ```gitignore
286
+ # Ignore all SQL companion files (output records with CustomSQL)
287
+ **/*.CustomSQL.sql
288
+
289
+ # Ignore a specific record (by metadata file path)
290
+ bins/app/my-draft-page.metadata.json
291
+
292
+ # Ignore an entire directory
293
+ bins/staging/
294
+
295
+ # Ignore all content in bins/ (still push entity-dir records like extension/)
296
+ bins/
297
+ ```
298
+
299
+ **Syntax:** Same as `.gitignore` — glob patterns, `#` comments, blank lines, negation with `!`, directory-only patterns with trailing `/`.
300
+
301
+ **Default patterns:**
302
+
303
+ ```gitignore
304
+ .dbo/ # DBO internal
305
+ *.dboio.json # Export files
306
+ app.json # Clone output
307
+ .git/ # Version control
308
+ .gitignore
309
+ node_modules/ # Node
310
+ package.json
311
+ package-lock.json
312
+ .claude/ # AI / tooling
313
+ .mcp.json
314
+ .DS_Store # Editor / IDE / OS
315
+ Thumbs.db
316
+ Icon\r
317
+ .idea/
318
+ .vscode/
319
+ *.codekit3
320
+ README.md # Repo scaffolding
321
+ SETUP.md
322
+ ```
323
+
324
+ Edit `.dboignore` to add or remove patterns. Committed to git and shared across users.
325
+
326
+ ### Legacy migration
327
+
328
+ If your project uses the older `.domain`, `.username`, `.password`, `.cookies` files, `dbo init` will detect them and offer to migrate automatically.
329
+
330
+ ### Environment variables
331
+
332
+ Environment variables override file-based configuration:
333
+
334
+ - `DBO_DOMAIN` — target domain
335
+ - `DBO_USERNAME` — username
336
+ - `DBO_PASSWORD` — password
337
+
338
+ ---
339
+
340
+ ## Commands
341
+
342
+ ### `dbo init`
343
+
344
+ Initialize DBO CLI configuration for the current directory.
345
+
346
+ ```bash
347
+ dbo init # interactive prompts
348
+ dbo init --domain my-domain.com # non-interactive
349
+ dbo init --domain my-domain.com --username me@co.io # with credentials
350
+ dbo init --force # overwrite existing config
351
+ dbo init --domain my-domain.com --app myapp --clone # init + clone an app
352
+ dbo init --domain my-domain.com -y # skip all prompts
353
+ dbo init --scaffold # scaffold dirs (prompts for domain)
354
+ dbo init --scaffold --yes # scaffold dirs non-interactively
355
+ ```
356
+
357
+ | Flag | Description |
358
+ |------|-------------|
359
+ | `--domain <host>` | DBO instance domain |
360
+ | `--username <user>` | DBO username (stored for login default) |
361
+ | `--force` | Overwrite existing configuration. Triggers a domain-change confirmation prompt when the new domain differs from the project reference domain |
362
+ | `--app <shortName>` | App short name (triggers clone after init). Prompts for password and authenticates automatically before fetching app data from the server |
363
+ | `--clone` | Clone the app after initialization |
364
+ | `-g, --global` | Install Claude commands globally (`~/.claude/commands/`) |
365
+ | `--local` | Install Claude commands to project (`.claude/commands/`) |
366
+ | `--scaffold` | Pre-create standard project directories (`app_version`, `automation`, `bins`, `data_source`, `docs`, `extension`, `group`, `integration`, `site`, `src`, `tests`, `trash`) |
367
+ | `--dboignore` | Create `.dboignore` with default patterns (use with `--force` to overwrite existing) |
368
+ | `-y, --yes` | Skip all interactive prompts (legacy migration, Claude Code setup) |
369
+ | `--non-interactive` | Alias for `--yes` |
370
+
371
+ ---
372
+
373
+ ### `dbo clone`
374
+
375
+ Clone an app from DBO.io to a local project structure. Creates directories, files, metadata, and populates `config.json` and `package.json`.
376
+
377
+ ```bash
378
+ # Clone using config (AppShortName from .dbo/config.json)
379
+ dbo clone
380
+
381
+ # Clone from a local JSON export file
382
+ dbo clone /path/to/app_export.json
383
+
384
+ # Clone from server by app short name
385
+ dbo clone --app myapp
386
+
387
+ # Combined with init
388
+ dbo init --domain my-domain.com --app myapp --clone
389
+
390
+ # Extension descriptor sub-directory handling
391
+ dbo clone -e extension # Clone all extensions (sorted by descriptor type)
392
+ dbo clone -e extension --documentation-only # Clone only documentation extensions
393
+ dbo clone -e extension --documentation-only --force # Reset documentation preferences and re-clone
394
+ dbo clone -e extension --descriptor-types false # Clone extensions flat (no descriptor sorting)
395
+ ```
396
+
397
+ | Flag | Description |
398
+ |------|-------------|
399
+ | `<source>` | Local file path or URL to load app JSON from (optional positional argument) |
400
+ | `--app <name>` | App short name to fetch from server |
401
+ | `-e, --entity <type>` | Only clone a specific entity type (e.g. `output`, `content`, `media`, `extension`) |
402
+ | `--documentation-only` | When used with `-e extension`, clone only documentation extensions |
403
+ | `--descriptor-types <bool>` | Sort extensions into descriptor sub-directories (default: `true`). Set to `false` to use flat `extension/` layout |
404
+ | `--domain <host>` | Override domain. Triggers a domain-change confirmation prompt when it differs from the project reference domain |
405
+ | `--force` | Skip source mismatch confirmation and change detection; re-processes all files |
406
+ | `-y, --yes` | Auto-accept all prompts (also skips source mismatch confirmation) |
407
+ | `-v, --verbose` | Show HTTP request details |
408
+
409
+ #### Domain change detection
410
+
411
+ 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.
412
+
413
+ The project's reference domain is stored in `app.json._domain` (committed to git) during clone, giving the CLI a stable cross-user baseline.
414
+
415
+ #### What clone does
416
+
417
+ 1. **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)
418
+ 2. **Updates `.dbo/config.json`** — saves `AppID`, `AppUID`, `AppName`, `AppShortName`, `AppModifyKey` (if the app is locked), and `cloneSource` (the source used for this clone)
419
+ 3. **Updates `package.json`** — populates `name`, `productName`, `description`, `homepage`, and `deploy` script
420
+ 4. **Creates directories** — processes `children.bin` to build the directory hierarchy based on `ParentBinID` relationships
421
+ 5. **Saves `.dbo/structure.json`** — maps BinIDs to directory paths for file placement
422
+ 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
423
+ 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`
424
+ 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/`)
425
+ 9. **Processes other entities** — remaining entities with a `BinID` are placed in the corresponding bin directory
426
+ 10. **Saves `app.json`** — clone of the original JSON with processed entries replaced by `@path/to/*.metadata.json` references
427
+ 11. **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
428
+
429
+ #### Clone source tracking
430
+
431
+ After every successful clone, the source is persisted as `cloneSource` in `.dbo/config.json`:
432
+
433
+ - `"default"` — app JSON was fetched from the server using `AppShortName` (the normal flow)
434
+ - A file path or URL — set when an explicit `<source>` argument was provided (e.g. `dbo clone /path/to/export.json`)
435
+
436
+ On subsequent clones, if you provide an explicit source that **differs** from the stored `cloneSource`, the CLI warns and asks for confirmation before proceeding:
437
+
438
+ ```
439
+ ⚠ This project was previously cloned from: default
440
+ Requested source: /path/to/export.json
441
+ ? Clone from the new source anyway? This will update the stored clone source. (y/N)
442
+ ```
443
+
444
+ Use `--force` or `-y` to skip the prompt and override without being asked.
445
+
446
+ If the initial clone attempt fails (network error, file not found, empty response), the CLI prompts for a fallback source to retry with instead of aborting:
447
+
448
+ ```
449
+ ⚠ Source did not return expected results: No app found with ShortName "myapp"
450
+ ? Enter another local file path or URL to retry (or leave empty to abort):
451
+ ```
452
+
453
+ #### Change detection on re-clone
454
+
455
+ When cloning an app that was already cloned locally, the CLI detects existing files and compares modification times against the server's `_LastUpdated`. You'll be prompted to overwrite, compare differences, or skip — same as `dbo pull`. Use `-y` to auto-accept all changes.
456
+
457
+ #### Collision detection
458
+
459
+ When multiple records would create files at the same path (e.g., a `content` record and a `media` record both named `colors.css`), the CLI detects the collision before writing any files and prompts you to choose which record to keep:
460
+
461
+ ```
462
+ ⚠ Collision: 2 records want to create "bins/app/colors.css"
463
+ ? Which record should create this file?
464
+ ❯ [content] colors (UID: abc123)
465
+ [media] colors.css (UID: def456)
466
+ ```
467
+
468
+ The rejected record is automatically staged for deletion in `.dbo/synchronize.json`. Run `dbo push` to delete it from the server.
469
+
470
+ In non-interactive mode (`-y`), the first record is kept and others are auto-staged for deletion.
471
+
472
+ #### Stale media cleanup
473
+
474
+ During media downloads, files returning 404 (no longer exist on the server) are collected as "stale records". After all downloads complete, you'll be prompted to stage them for deletion:
475
+
476
+ ```
477
+ Found 3 stale media record(s) (404 - files no longer exist on server)
478
+ ? Stage these 3 stale media records for deletion? (y/N)
479
+ ```
480
+
481
+ This helps keep your app clean by removing database records for media files that have been deleted from the server.
482
+
483
+ In non-interactive mode (`-y`), stale cleanup is skipped (conservative default).
484
+
485
+ #### Path resolution
486
+
487
+ When a content record has both `Path` and `BinID`, the CLI prompts:
488
+ ```
489
+ Where do you want me to place filename.ext?
490
+ 1. Into the Path of /path/from/path/column
491
+ 2. Into the BinID of 12345 (mapped BinName → bin/directory)
492
+ ```
493
+
494
+ #### Entity directory processing
495
+
496
+ Entity types that correspond to project directories (`extension`, `app_version`, `data_source`, `site`, `group`, `integration`, `automation`) are processed into their named directories without requiring a `BinID`:
497
+
498
+ | Entity Key | Directory |
499
+ |------------|-----------|
500
+ | `extension` | `extension/<Descriptor>/` (see below) |
501
+ | `app_version` | `app_version/` |
502
+ | `data_source` | `data_source/` |
503
+ | `site` | `site/` |
504
+ | `group` | `group/` |
505
+ | `integration` | `integration/` |
506
+ | `automation` | `automation/` |
507
+
508
+ For each entity type, the CLI prompts to choose which column becomes the filename (defaults to `Name`, fallback `UID`). The choice is saved per entity type in `config.json` (e.g., `ExtensionFilenameCol`).
509
+
510
+ If any columns contain base64-encoded content, the CLI prompts to extract them as companion files. Extracted columns produce files named `<name>.<Column>.<ext>` alongside the metadata, with `@reference` entries in the metadata and a `_contentColumns` array.
511
+
512
+ **Companion file naming convention:** Only `.metadata.json` files carry the `~UID` suffix (e.g. `Add-Asst-Execute-Security~wxl6ivcwfkix3zgantszjg.metadata.json`). Companion content files use the natural base name without `~UID` (e.g. `Add-Asst-Execute-Security.String16.js`). If two records share the same name within a directory, the second gets a `-1` suffix (e.g. `Add-Asst-Execute-Security-1.String16.js` with metadata `Add-Asst-Execute-Security-1~otheruid.metadata.json`). Migration 007 automatically renames legacy `~UID` companion files to the natural convention.
513
+
514
+ Use `-y` to skip prompts (uses `Name` column, no content extraction).
515
+
516
+ #### Extension descriptor sub-directories
517
+
518
+ Extension records are organized into sub-directories under `extension/` based on their `Descriptor` column value. A special extension type called `descriptor_definition` (itself an extension with `Descriptor === "descriptor_definition"`) provides the mapping from descriptor key (`String1`) to display/directory name (`Name`).
519
+
520
+ During clone, the CLI:
521
+
522
+ 1. **Pre-scans** all extension records for `descriptor_definition` entries and builds a `String1 → Name` mapping
523
+ 2. **Creates sub-directories** under `extension/` for each mapped descriptor (e.g., `extension/Documentation/`, `extension/Includes/`)
524
+ 3. **Always creates** `extension/_unsupported/` — extensions with an unmapped or null `Descriptor` are placed here
525
+ 4. **Prompts per descriptor** — filename column and content extraction prompts fire once per unique `Descriptor` value (not once for all extensions)
526
+ 5. **Persists the mapping** in `.dbo/structure.json` under `descriptorMapping`
527
+
528
+ **Config keys** (saved per descriptor in `config.json`):
529
+
530
+ | Key | Example | Purpose |
531
+ |-----|---------|---------|
532
+ | `Extension_<descriptor>_FilenameCol` | `Extension_documentation_FilenameCol` | Filename column for that descriptor type |
533
+ | `Extension_<descriptor>_ContentExtractions` | `Extension_documentation_ContentExtractions` | Content extraction preferences per column |
534
+ | `ExtensionDocumentationMDPlacement` | `"inline"` or `"root"` | Where to place documentation MD files |
535
+
536
+ **Documentation alternate placement**: When extracting MD content from `documentation` descriptor extensions, the CLI offers a choice:
537
+
538
+ - **Root placement** (`/docs/<filename>.md`) — recommended for easy access; creates `@/docs/<filename>.md` references in metadata
539
+ - **Inline placement** (`extension/Documentation/<filename>.md`) — keeps files alongside metadata
540
+
541
+ Root-placed files use absolute-from-root `@/` references (e.g., `@/docs/my-doc.md`) so `dbo push` can locate them regardless of where the metadata lives.
542
+
543
+ **Entity filter support**:
544
+
545
+ ```bash
546
+ dbo clone -e extension --documentation-only # Clone only documentation extensions
547
+ dbo clone -e extension --documentation-only --force # Reset documentation preferences and re-clone
548
+ dbo clone -e extension # Clone all extensions (all descriptor types)
549
+ dbo clone -e extension --descriptor-types false # Flat layout (no descriptor sorting)
550
+ ```
551
+
552
+ **`dbo add` auto-inference**: Running `dbo add docs/my-doc.md` when `ExtensionDocumentationMDPlacement` is `"root"` auto-creates a companion `.metadata.json` in `extension/documentation/` with the correct `@/` reference.
553
+
554
+ #### Output structure
555
+
556
+ ```
557
+ project/
558
+ .dbo/
559
+ config.json # Updated with app metadata
560
+ structure.json # Bin directory mapping
561
+ .gitignore # credentials.json + cookies.txt added
562
+ package.json # Updated with app info + deploy script
563
+ app.json # Clone of original with @references
564
+ bins/ # ← root for all bin-placed files
565
+ app/ # ← directory from children.bin
566
+ thomas-scratch.md
567
+ thomas-scratch.metadata.json
568
+ CurrentTicketID.cs
569
+ CurrentTicketID.metadata.json
570
+ ticket_test/ # ← another bin directory
571
+ ...
572
+ extension/ # ← extension records organized by descriptor
573
+ Documentation/ # ← descriptor sub-directory (from descriptor_definition)
574
+ MyDoc.uid1.metadata.json
575
+ MyDoc.uid1.String10.md # ← extracted content column
576
+ Includes/
577
+ Header.uid2.metadata.json
578
+ _unsupported/ # ← always created (unmapped/null descriptors)
579
+ docs/ # ← root-placed documentation MD files (optional)
580
+ MyDoc.md
581
+ data_source/
582
+ MySQL-Primary.metadata.json
583
+ site/
584
+ MainSite.metadata.json
585
+ # Media files placed by BinID into bins/ (alongside content)
586
+ ```
587
+
588
+ #### Understanding the `lib/bins/` directory structure
589
+
590
+ 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.
591
+
592
+ **Directory Organization:**
593
+
594
+ - **`lib/bins/`** — Root directory for all bin-placed files (local organizational directory only)
595
+ - **`lib/bins/app/`** — Special subdirectory for the main app bin (typically the default bin)
596
+ - **`lib/bins/custom_name/`** — Custom bin directories (e.g., `tpl/`, `ticket_test/`, etc.)
597
+
598
+ **Important: The `lib/bins/app/` special case**
599
+
600
+ The `app/` subdirectory under `lib/bins/` is treated specially:
601
+
602
+ 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**.
603
+
604
+ 2. **Path normalization** — When comparing paths (during `dbo push`), the CLI automatically strips both `lib/bins/` and `app/` from paths:
605
+ ```
606
+ Local file: lib/bins/app/assets/css/operator.css
607
+ Server Path: assets/css/operator.css
608
+ → These are considered the same path ✓
609
+ ```
610
+
611
+ 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:
612
+ ```
613
+ Local file: lib/bins/tpl/header.html
614
+ Server Path: tpl/header.html
615
+ → The 'tpl/' directory is preserved ✓
616
+ ```
617
+
618
+ **Why this matters:**
619
+
620
+ - When you `dbo push` files from `lib/bins/app/`, the CLI knows these paths should match the root-level paths in your metadata
621
+ - If your metadata `Path` column contains `assets/css/colors.css`, it will correctly match files in `lib/bins/app/assets/css/colors.css`
622
+ - Custom bin directories like `lib/bins/tpl/` serve from the `tpl/` directive and maintain their path structure
623
+
624
+ **Leading slash handling:**
625
+
626
+ The CLI handles leading `/` in metadata paths flexibly:
627
+ - `Path: assets/css/file.css` matches `lib/bins/app/assets/css/file.css` ✓
628
+ - `Path: /assets/css/file.css` also matches `lib/bins/app/assets/css/file.css` ✓
629
+ - `Path: /assets/css/file.css` matches `lib/bins/assets/css/file.css` ✓
630
+
631
+ This ensures compatibility with various path formats from the server while maintaining correct local file organization.
632
+
633
+ #### Media file serving (API)
634
+
635
+ The DBO.io server provides three routes for serving media files:
636
+
637
+ | Route | Example | Description |
638
+ |-------|---------|-------------|
639
+ | `/media/{app}/{path}` | `/media/todoes/App/assets/fonts/file.ttf` | Legacy FullPath — the value stored in the media record's `FullPath` column |
640
+ | `/dir/{app}/{bins}/{file}` | `/dir/todoes/App/assets/fonts/file.ttf` | Modern BinID-based route — parses `appShortName/binHierarchy/filename` |
641
+ | `/api/media/{uid}` | `/api/media/ujrOQPCdUEamNJdAjUQdYA` | UID-based endpoint — looks up media by unique identifier |
642
+
643
+ During `dbo clone`, the CLI downloads media using a **fallback chain**:
644
+
645
+ 1. **FullPath** (`/media/...`) — uses the record's `FullPath` column directly
646
+ 2. **`/dir/` route** — strips the `/media/` prefix from FullPath and uses the `/dir/` route
647
+ 3. **`/api/media/{uid}`** — UID-based endpoint as last resort (when no FullPath exists)
648
+
649
+ If all attempts fail, the error is logged to `.dbo/errors.log` (JSONL format) with the record's UID, filename, FullPath, and error details.
650
+
651
+ #### Output hierarchy format
652
+
653
+ Each root output record produces a **single compound JSON file** containing all child entities (columns, joins, filters) embedded inline:
654
+
655
+ ```
656
+ bins/app/
657
+ _output~Sales~abc123.json ← root output with inline children
658
+ _output~Sales~abc123.column~col1.CustomSQL.sql ← companion SQL file
659
+ ```
660
+
661
+ The root JSON structure:
662
+ ```json
663
+ {
664
+ "_entity": "output",
665
+ "UID": "abc123",
666
+ "Name": "Sales",
667
+ "children": {
668
+ "column": [
669
+ { "_entity": "output_value", "UID": "col1", "Title": "Amount", "children": { "column": [], "join": [], "filter": [] } }
670
+ ],
671
+ "join": [],
672
+ "filter": [
673
+ { "_entity": "output_value_filter", "UID": "f1", "ShortName": "Active", "children": { "column": [], "join": [], "filter": [] } }
674
+ ]
675
+ }
676
+ }
677
+ ```
678
+
679
+ Key points:
680
+ - All three child keys (`column`, `join`, `filter`) are always present (empty arrays when unused)
681
+ - Each child retains `_entity` set to its physical table name for push routing
682
+ - Children nest recursively following FK relationships (e.g. a column can have filters)
683
+ - `CustomSQL` content is extracted to companion `.sql` files per extraction rules
684
+ - Re-cloning moves orphaned old-format child `.json` files to `/trash`
685
+
686
+ #### Metadata Templates
687
+
688
+ 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.
689
+
690
+ **File format:**
691
+
692
+ ```json
693
+ {
694
+ "site": ["AppID", "Name", "ShortName", "Active"],
695
+ "extension": {
696
+ "documentation": ["AppID", "Name", "Descriptor=documentation", "String10=@reference"],
697
+ "control": ["AppID", "Name", "ShortName", "Active"]
698
+ }
699
+ }
700
+ ```
701
+
702
+ **Column syntax:**
703
+
704
+ | Syntax | Meaning |
705
+ |--------|---------|
706
+ | `Name` | Plain column — populated from filename or left empty |
707
+ | `Descriptor=documentation` | Literal value — always set to `documentation` |
708
+ | `String10=@reference` | Content reference — links to the file being added |
709
+
710
+ `dbo add` uses these templates to auto-detect the entity type from a file's directory placement and generate metadata without prompting. For example, `dbo add extension/include/nav.html` resolves to entity `extension` / descriptor `include` and applies the matching template.
711
+
712
+ ---
713
+
714
+ ### `dbo login`
715
+
716
+ Authenticate with a DBO.io instance and store the session cookie.
717
+
718
+ 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`.
719
+
720
+ > **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.
721
+
722
+ ```bash
723
+ dbo login # uses stored credentials
724
+ dbo login -u user@example.com -p myPassword # explicit credentials
725
+ dbo login -e user@example.com # authenticate by email
726
+ dbo login --phone +15551234567 -p myPassword # authenticate by phone
727
+ dbo login --passkey abc123def # authenticate with passkey
728
+ ```
729
+
730
+ | Flag | Description |
731
+ |------|-------------|
732
+ | `-u, --username <value>` | Username identity |
733
+ | `-e, --email <value>` | Email identity |
734
+ | `--phone <value>` | Phone number identity |
735
+ | `-p, --password <value>` | Password credential |
736
+ | `--passkey <value>` | Passkey credential (rotating API key) |
737
+ | `--domain <host>` | Override domain for this request |
738
+
739
+ ---
740
+
741
+ ### `dbo logout`
742
+
743
+ Log out and clear the local session cookie.
744
+
745
+ ```bash
746
+ dbo logout
747
+ ```
748
+
749
+ ---
750
+
751
+ ### `dbo status`
752
+
753
+ Show current configuration, domain, and session status.
754
+
755
+ ```bash
756
+ dbo status
757
+ ```
758
+
759
+ Output:
760
+ ```
761
+ Initialized: Yes (.dbo/)
762
+ Domain: my-domain.com
763
+ Username: user@example.com
764
+ User ID: 10296
765
+ Directory: /Users/me/projects/operator
766
+ Session: Active (expires: 2026-03-15T10:30:00.000Z)
767
+ Cookies: /Users/me/projects/operator/.dbo/cookies.txt
768
+
769
+ Claude Code Plugins:
770
+ dbo: ✓ global (~/.claude/commands/dbo.md)
771
+ ```
772
+
773
+ User ID is populated by `dbo login`. If it shows "(not set)", run `dbo login` to fetch it.
774
+
775
+ Plugin scopes (project or global) are displayed when plugins have been installed. Scopes are stored in `.dbo/config.local.json`.
776
+
777
+ ---
778
+
779
+ ### `dbo input`
780
+
781
+ Submit CRUD operations (add, edit, delete records) to DBO.io. This is the core data manipulation command.
782
+
783
+ ```bash
784
+ # Add a record
785
+ dbo input -d 'RowID:add1;column:user.FirstName=John' -d 'RowID:add1;column:user.LastName=Doe'
786
+
787
+ # Edit a record by UID
788
+ dbo input -d 'RowUID:albain3dwkofbhnd1qtd1q;column:content.Content@assets/css/colors.css'
789
+
790
+ # Delete a record
791
+ dbo input -d 'RowID:del10062;entity:user=true'
792
+
793
+ # Multiple operations in one call
794
+ dbo input -d 'RowID:add1;column:user.LastName=Doe&RowUID:abc;column:content.Content@file.css'
795
+
796
+ # With file upload (multipart)
797
+ dbo input -d 'RowID:add1;column:media.BinID=12345' -f file=@path/to/image.jpg
798
+
799
+ # Validation only (no commit)
800
+ dbo input -d 'RowID:add1;column:user.FirstName=John' --confirm false
801
+
802
+ # With ticket ID override
803
+ dbo input -d 'RowID:add1;column:content.Name=test' --ticket abc123
804
+
805
+ # See the HTTP request being made
806
+ dbo input -d 'RowUID:abc;column:content.Content@file.css' -v
807
+ ```
808
+
809
+ | Flag | Description |
810
+ |------|-------------|
811
+ | `-d, --data <expr>` | DBO input expression (repeatable) |
812
+ | `-f, --file <field=@path>` | File attachment for multipart upload (repeatable) |
813
+ | `-C, --confirm <true\|false>` | Commit changes (default: `true`). Use `false` for validation only |
814
+ | `--ticket <id>` | Override ticket ID (`_OverrideTicketID`) |
815
+ | `--modify-key <key>` | Provide ModifyKey directly (skips interactive prompt) |
816
+ | `--row-key <type>` | Row key type (`RowUID` or `RowID`) — no-op for `-d` passthrough, available for consistency |
817
+ | `--login` | Auto-login user created by this submission |
818
+ | `--transactional` | Use transactional processing |
819
+ | `--json` | Output raw JSON response |
820
+ | `-v, --verbose` | Show HTTP request details |
821
+ | `--domain <host>` | Override domain |
822
+
823
+ #### Input expression syntax
824
+
825
+ ```
826
+ RowID:identifier;column:entity.ColumnName=value # direct value
827
+ RowUID:identifier;column:entity.ColumnName@filepath # value from file
828
+ RowID:delIdentifier;entity:entityName=true # delete
829
+ ```
830
+
831
+ The `@filepath` syntax reads the file contents and uses them as the column value. This is how CSS, JS, HTML, and other text content is deployed to DBO.
832
+
833
+ ---
834
+
835
+ ### `dbo output`
836
+
837
+ Query data from DBO.io outputs or entities.
838
+
839
+ ```bash
840
+ # Custom output by UID
841
+ dbo output qfkyyp2vxeaggdeo7dwbig
842
+
843
+ # Entity query
844
+ dbo output -e user --template json_indented
845
+
846
+ # Single record
847
+ dbo output -e user --row 10296
848
+
849
+ # With filtering and sorting
850
+ dbo output -e user --filter 'FirstName=John' --sort 'LastName:asc' --template json_indented
851
+
852
+ # Contains filter
853
+ dbo output -e content --filter 'Name:contains=color' --template json_indented
854
+
855
+ # Pagination
856
+ dbo output -e user --page 2 --rows-per-page 25
857
+
858
+ # Save results to local files (interactive)
859
+ dbo output -e content --filter 'AppID=10100' --save
860
+
861
+ # Save results to local files (non-interactive / scripting)
862
+ dbo output -e content --save-filename Name --save-path Path --save-content Content --save-extension Extension
863
+
864
+ # Entity metadata
865
+ dbo output -e user --meta
866
+
867
+ # Debug SQL
868
+ dbo output myOutputUID --debug-sql
869
+ ```
870
+
871
+ | Flag | Description |
872
+ |------|-------------|
873
+ | `<uid>` | Output UID (positional argument) |
874
+ | `-e, --entity <uid>` | Query by entity UID |
875
+ | `--row <id>` | Specific row ID |
876
+ | `--filter <expr>` | Filter expression (repeatable) |
877
+ | `--template <value>` | Output template: `json_raw` (default), `json_indented`, `json`, `html`, `csv`, `xml`, `txt`, `pdf`, or a content UID for custom templates |
878
+ | `--sort <expr>` | Sort expression (repeatable), e.g., `LastName:asc` |
879
+ | `--search <expr>` | Full-text search |
880
+ | `--page <n>` | Page number |
881
+ | `--rows-per-page <n>` | Rows per page |
882
+ | `--maxrows <n>` | Maximum rows |
883
+ | `--rows <range>` | Row range, e.g., `1-10` |
884
+ | `--limit <n>` | Maximum rows to return (preferred over `--maxrows`) |
885
+ | `--rowcount <bool>` | Include row count: `true` (default) or `false` for performance |
886
+ | `--display <expr>` | Show/hide template tags (repeatable), e.g., `sidebar=hide` |
887
+ | `--format-values` | Enable value formatting with `--template json_raw` |
888
+ | `--empty-response-code <code>` | HTTP status code when output returns no results |
889
+ | `--fallback-content <expr>` | Fallback content UID for error codes, e.g., `404=contentUID` |
890
+ | `--escape-html <bool>` | Control HTML escaping: `true` or `false` |
891
+ | `--mime <type>` | Override MIME/content type |
892
+ | `--strict` | Strict error mode |
893
+ | `--confirm` | Confirmation flag |
894
+ | `--include <expr>` | Include token |
895
+ | `--no-transaction` | Disable transaction wrapping |
896
+ | `--skip <phase>` | Skip execution phases (repeatable, admin-only) |
897
+ | `--profile` | Enable MiniProfiler output |
898
+ | `--debug` | Include debug info |
899
+ | `--debug-sql` | Include SQL debug info |
900
+ | `--debug-verbose` | Verbose debug output |
901
+ | `--debug-analysis` | Analysis debug output |
902
+ | `--meta` | Use meta output endpoint |
903
+ | `--meta-column <uid>` | Column metadata |
904
+ | `--save` | Interactive save-to-disk mode |
905
+ | `--save-filename <col>` | Column for filenames (non-interactive) |
906
+ | `--save-path <col>` | Column for file path (non-interactive) |
907
+ | `--save-content <col>` | Column for file content (non-interactive) |
908
+ | `--save-extension <col>` | Column or literal extension (non-interactive) |
909
+ | `--json` | Output raw JSON |
910
+ | `-v, --verbose` | Show HTTP request details |
911
+
912
+ #### Save to Disk (`--save`)
913
+
914
+ The save-to-disk feature fetches data and persists records as local files. It uses an interactive flow with arrow-key selection prompts:
915
+
916
+ 1. **Filename column** — which column value becomes the filename (default: `Name` or `UID`)
917
+ 2. **Path column** — which column contains the directory path (builds local directories)
918
+ 3. **Content column(s)** — which column(s) to save as file content (skip for metadata only)
919
+ 4. **Extension** — use an entity column or specify manually
920
+
921
+ Each record produces:
922
+ - A content file: `[filename]~[uid].[extension]` (e.g., `colors~abc123.css`)
923
+ - A metadata file: `[filename]~[uid].metadata.json` (all column values)
924
+
925
+ ### Tilde UID Convention
926
+
927
+ Every local file whose server record has a known UID embeds that UID in the filename, separated by a tilde (`~`):
928
+
929
+ - Content: `<basename>~<uid>.<ext>` / `<basename>~<uid>.metadata.json`
930
+ - Media: `<basename>~<uid>.<ext>` / `<basename>~<uid>.<ext>.metadata.json`
931
+ - Entity-dir: `<name>~<uid>.metadata.json`
932
+
933
+ Exception: if the chosen filename column value *is* the UID itself, the tilde suffix is omitted: `<uid>.<ext>`.
934
+
935
+ When pushing, the `~<uid>` portion is automatically stripped from filenames sent to the server (e.g., `logo~def456.png` is uploaded as `logo.png`).
936
+
937
+ If the path column contains a filename (e.g., `assets/js/main.js`), the CLI detects it and asks if you want to use it.
938
+
939
+ ---
940
+
941
+ ### `dbo content`
942
+
943
+ Get, deploy, or pull content from DBO.io.
944
+
945
+ ```bash
946
+ # Get content by UID
947
+ dbo content ykqucv0eb0ggjqgcncj6dq
948
+
949
+ # Save content to a local file
950
+ dbo content ykqucv0eb0ggjqgcncj6dq -o local/file.html
951
+
952
+ # Get as plain text (disable minification)
953
+ dbo content ykqucv0eb0ggjqgcncj6dq --template txt --no-minify
954
+ ```
955
+
956
+ | Flag | Description |
957
+ |------|-------------|
958
+ | `<uid>` | Content UID |
959
+ | `-o, --output <path>` | Save to local file |
960
+ | `--template <value>` | Output template (e.g., `json_raw`, `html`, `txt`, or a content UID) |
961
+ | `--no-minify` | Disable minification |
962
+ | `--json` | Output raw JSON |
963
+
964
+ #### `dbo content deploy`
965
+
966
+ Deploy a local file's contents to a DBO content record.
967
+
968
+ ```bash
969
+ dbo content deploy albain3dwkofbhnd1qtd1q assets/css/colors.css
970
+ dbo content deploy rncjivlghu65bmkbjnxynq assets/js/app.js
971
+ dbo content deploy abc123 docs/readme.md --ticket myTicket
972
+ dbo content deploy abc123 test.html --confirm false # validate only
973
+ dbo content deploy abc123 image.png --multipart # binary file upload
974
+ ```
975
+
976
+ This is a shorthand for:
977
+ ```bash
978
+ dbo input -d 'RowUID:albain3dwkofbhnd1qtd1q;column:content.Content@assets/css/colors.css'
979
+ ```
980
+
981
+ | Flag | Description |
982
+ |------|-------------|
983
+ | `<uid>` | Content UID (RowUID) |
984
+ | `<filepath>` | Local file path |
985
+ | `-C, --confirm <true\|false>` | Commit (default: `true`) |
986
+ | `--ticket <id>` | Override ticket ID |
987
+ | `--modify-key <key>` | Provide ModifyKey directly (skips interactive prompt) |
988
+ | `--multipart` | Use multipart/form-data upload (for binary files) |
989
+ | `--row-key <type>` | Override row key type for this invocation (`RowUID` or `RowID`) |
990
+
991
+ #### `dbo content pull`
992
+
993
+ Pull content records from DBO to local files. Uses the content entity's well-known columns (`Name`, `Path`, `Content`, `Extension`) automatically — no interactive prompts.
994
+
995
+ ```bash
996
+ # Pull a single content record
997
+ dbo content pull ykqucv0eb0ggjqgcncj6dq
998
+
999
+ # Pull all content for an app
1000
+ dbo content pull --filter 'AppID=10100'
1001
+
1002
+ # Pull with row limit
1003
+ dbo content pull --filter 'AppID=10100' --maxrows 50
1004
+ ```
1005
+
1006
+ Creates local files matching the content entity's `Path` and `Extension` columns:
1007
+ ```
1008
+ css/
1009
+ colors.css # content.Content value
1010
+ colors.metadata.json # all column values as JSON
1011
+ js/
1012
+ app.js
1013
+ app.metadata.json
1014
+ ```
1015
+
1016
+ #### Smart change detection
1017
+
1018
+ When pulling records that already exist locally, the CLI compares your local file modification times against the server's `_LastUpdated` timestamp. If the server has newer data, you'll be prompted:
1019
+
1020
+ 1. **Overwrite** — replace local with server version
1021
+ 2. **Compare** — show a line-by-line diff and selectively merge
1022
+ 3. **Skip** — keep local unchanged
1023
+ 4. **Overwrite all** / **Skip all** — bulk action for remaining files
1024
+
1025
+ After writing, file modification times are synced to the server's `_LastUpdated` to establish a sync point for future comparisons. Use `dbo diff` to compare without pulling.
1026
+
1027
+ ---
1028
+
1029
+ ### `dbo media`
1030
+
1031
+ Get media files from DBO.io.
1032
+
1033
+ ```bash
1034
+ # Get media by UID
1035
+ dbo media albain3dwkofbhnd1qtd1q
1036
+
1037
+ # Save to local file
1038
+ dbo media albain3dwkofbhnd1qtd1q -o logo.png
1039
+
1040
+ # Get by numeric ID
1041
+ dbo media --id 12345 -o file.jpg
1042
+
1043
+ # Get by path
1044
+ dbo media --path assets/images/logo.png -o logo.png
1045
+
1046
+ # Force download
1047
+ dbo media albain3dwkofbhnd1qtd1q --download -o file.pdf
1048
+ ```
1049
+
1050
+ | Flag | Description |
1051
+ |------|-------------|
1052
+ | `<uid>` | Media UID |
1053
+ | `--id <id>` | Media by numeric ID |
1054
+ | `--path <path>` | Media by directory path |
1055
+ | `-o, --output <path>` | Save to local file |
1056
+ | `--download` | Force download (attachment disposition) |
1057
+
1058
+ ---
1059
+
1060
+ ### `dbo upload`
1061
+
1062
+ Upload a binary file to DBO.io.
1063
+
1064
+ ```bash
1065
+ dbo upload image.jpg --bin 12345 --app 67890 --ownership app --path assets/images
1066
+ dbo upload logo.svg --bin 12345 --app 67890 --ownership app --path assets/gfx --name brand-logo
1067
+ dbo upload doc.pdf --bin 12345 --app 67890 --ownership user --path docs --confirm false
1068
+ ```
1069
+
1070
+ | Flag | Description |
1071
+ |------|-------------|
1072
+ | `<filepath>` | Local file to upload |
1073
+ | `--bin <id>` | BinID (required) |
1074
+ | `--app <id>` | AppID (required) |
1075
+ | `--ownership <type>` | Ownership: `app`, `user`, or `system` (required) |
1076
+ | `--path <dir>` | Media path (required) |
1077
+ | `--name <value>` | Override filename |
1078
+ | `-C, --confirm <true\|false>` | Commit (default: `true`) |
1079
+
1080
+ ---
1081
+
1082
+ ### `dbo message`
1083
+
1084
+ Send messages via DBO.io (email, SMS/MMS, chatbot).
1085
+
1086
+ ```bash
1087
+ # Send an email
1088
+ dbo message emailTemplateUID
1089
+
1090
+ # Send a chatbot message with thread
1091
+ dbo message chatbotTemplateUID --thread conversation123
1092
+
1093
+ # Validate without sending
1094
+ dbo message emailTemplateUID --confirm false
1095
+ ```
1096
+
1097
+ | Flag | Description |
1098
+ |------|-------------|
1099
+ | `<uid>` | Content UID for the message template |
1100
+ | `-C, --confirm <true\|false>` | Commit (default: `true`) |
1101
+ | `--thread <id>` | Thread ID for chatbot conversations |
1102
+ | `--json` | Output raw JSON |
1103
+
1104
+ ---
1105
+
1106
+ ### `dbo cache`
1107
+
1108
+ Manage the DBO.io cache.
1109
+
1110
+ ```bash
1111
+ # List all cached items
1112
+ dbo cache list
1113
+
1114
+ # List with metadata
1115
+ dbo cache list --metadata
1116
+
1117
+ # Refresh a specific cache key
1118
+ dbo cache refresh --key 'content:myContentUID'
1119
+ ```
1120
+
1121
+ #### `dbo cache list`
1122
+
1123
+ | Flag | Description |
1124
+ |------|-------------|
1125
+ | `--metadata` | Include cache provider metadata |
1126
+ | `--json` | Output raw JSON |
1127
+
1128
+ #### `dbo cache refresh`
1129
+
1130
+ | Flag | Description |
1131
+ |------|-------------|
1132
+ | `--key <value>` | Cache key to refresh (required) |
1133
+ | `--part <value>` | Cache partition |
1134
+
1135
+ ---
1136
+
1137
+ ### `dbo instance`
1138
+
1139
+ Manage DBO.io instances.
1140
+
1141
+ ```bash
1142
+ # Export the current instance
1143
+ dbo instance export
1144
+
1145
+ # Build an instance
1146
+ dbo instance build instanceUID
1147
+
1148
+ # Validate without executing
1149
+ dbo instance export --confirm false
1150
+ ```
1151
+
1152
+ #### `dbo instance export`
1153
+
1154
+ | Flag | Description |
1155
+ |------|-------------|
1156
+ | `-C, --confirm <true\|false>` | Commit (default: `true`) |
1157
+
1158
+ #### `dbo instance build <uid>`
1159
+
1160
+ | Flag | Description |
1161
+ |------|-------------|
1162
+ | `<uid>` | Instance UID |
1163
+ | `-C, --confirm <true\|false>` | Commit (default: `true`) |
1164
+
1165
+ ---
1166
+
1167
+ ### `dbo diff`
1168
+
1169
+ Compare local files against their server versions and selectively merge changes. This is a one-directional comparison: only server → local changes can be accepted. To push local changes back, use `dbo push`.
1170
+
1171
+ ```bash
1172
+ # Compare all records in the current directory
1173
+ dbo diff
1174
+
1175
+ # Compare a specific file
1176
+ dbo diff assets/css/colors.css
1177
+
1178
+ # Compare all records in a directory
1179
+ dbo diff assets/
1180
+
1181
+ # Display diffs without prompting
1182
+ dbo diff --no-interactive
1183
+
1184
+ # Accept all server changes without prompting
1185
+ dbo diff -y
1186
+ ```
1187
+
1188
+ | Flag | Description |
1189
+ |------|-------------|
1190
+ | `[path]` | File, directory, or `.` (default: current directory) |
1191
+ | `--no-interactive` | Show diffs without prompting to accept |
1192
+ | `-y, --yes` | Accept all server changes automatically |
1193
+ | `-v, --verbose` | Show HTTP request details |
1194
+ | `--domain <host>` | Override domain |
1195
+
1196
+ #### Interactive mode
1197
+
1198
+ For each file with differences, you can:
1199
+ 1. **Accept all changes** — overwrite local with server version
1200
+ 2. **Cherry-pick fields** — accept/skip individual field changes
1201
+ 3. **Skip** — keep local files unchanged
1202
+ 4. **Accept all remaining** — auto-accept for all remaining files
1203
+ 5. **Skip all remaining** — skip all remaining files
1204
+
1205
+ #### Diff output
1206
+
1207
+ Shows a unified diff format with color coding:
1208
+ - Red lines (`-`) — content only in your local file
1209
+ - Green lines (`+`) — content only on the server
1210
+ - Cyan headers — hunk markers showing line positions
1211
+
1212
+ After accepting changes, file modification times are synced to the server's `_LastUpdated` timestamp to establish a new sync point.
1213
+
1214
+ ---
1215
+
1216
+ ### `dbo push`
1217
+
1218
+ Push local files back to DBO.io using metadata from a previous pull. This is the counterpart to `dbo content pull` and `dbo output --save`.
1219
+
1220
+ Files and records matching `.dboignore` patterns are skipped — both by metadata file path (e.g. `*.metadata.json`) and by companion content file path (e.g. a record whose `@Content` points to an ignored `.sql` file). To push an ignored file directly, use `dbo input -d '...'` with an explicit expression.
1221
+
1222
+ #### Round-trip workflow
1223
+
1224
+ ```bash
1225
+ # 1. Pull content to local files
1226
+ dbo content pull --filter 'AppID=10100' --maxrows 10
1227
+
1228
+ # 2. Edit files locally
1229
+ vim css/colors.css
1230
+
1231
+ # 3. Push changes back to DBO
1232
+ dbo push css/colors.css
1233
+ ```
1234
+
1235
+ #### Single file
1236
+
1237
+ ```bash
1238
+ # Push a single file (uses companion .metadata.json)
1239
+ dbo push assets/js/main.js
1240
+
1241
+ # Validate without submitting
1242
+ dbo push assets/js/main.js --confirm false
1243
+
1244
+ # Push only the file content, not metadata columns
1245
+ dbo push assets/js/main.js --content-only
1246
+
1247
+ # Push only metadata changes, skip file content
1248
+ dbo push assets/js/main.js --meta-only
1249
+ ```
1250
+
1251
+ The push command finds `assets/js/main.metadata.json`, reads the UID and entity, and builds input expressions for all columns.
1252
+
1253
+ #### Directory (recursive)
1254
+
1255
+ ```bash
1256
+ # Push all changed records in the current directory
1257
+ dbo push
1258
+
1259
+ # Push all records in a specific directory
1260
+ dbo push assets/
1261
+
1262
+ # Push with auto-accept for all prompts
1263
+ dbo push assets/ -y
1264
+ ```
1265
+
1266
+ Recursively finds all `*.metadata.json` files, verifies `@filename` references exist, and pushes each record.
1267
+
1268
+ #### Path mismatch detection
1269
+
1270
+ If you move a file to a different directory after pulling, the push detects the mismatch:
1271
+
1272
+ ```
1273
+ ⚠ Path mismatch for "main":
1274
+ Metadata Path: css/main.css
1275
+ Current path: assets/css/main.css
1276
+ Update Path column to "assets/css/main.css"? (Y/n)
1277
+ ```
1278
+
1279
+ The `--yes` flag auto-accepts path updates.
1280
+
1281
+ #### Metadata format
1282
+
1283
+ After a pull, metadata files contain `@filename` references for content columns:
1284
+
1285
+ ```json
1286
+ {
1287
+ "_entity": "content",
1288
+ "_contentColumns": ["Content"],
1289
+ "UID": "abc123",
1290
+ "Name": "colors",
1291
+ "Content": "@colors.css",
1292
+ "Extension": "CSS",
1293
+ "Path": "css/colors.css",
1294
+ "Type": "Code"
1295
+ }
1296
+ ```
1297
+
1298
+ The `@colors.css` reference tells push to read the content from that file. All other values are pushed as literal column values.
1299
+
1300
+ | Flag | Description |
1301
+ |------|-------------|
1302
+ | `[path]` | File or directory to push (default: current directory) |
1303
+ | `-C, --confirm <true\|false>` | Commit (default: `true`) |
1304
+ | `--ticket <id>` | Override ticket ID |
1305
+ | `--modify-key <key>` | Provide ModifyKey directly (skips interactive prompt) |
1306
+ | `--row-key <type>` | Override row key type for this invocation (`RowUID` or `RowID`) |
1307
+ | `--meta-only` | Only push metadata, skip file content |
1308
+ | `--content-only` | Only push file content, skip metadata |
1309
+ | `-y, --yes` | Auto-accept all prompts |
1310
+ | `--toe-stepping <true\|false>` | Check server for conflicts before pushing (default: `true`). Set to `false` to skip the check and push unconditionally |
1311
+ | `--no-scripts` | Bypass all script hooks; run default push pipeline |
1312
+ | `--no-build` | Skip the build phase; run push phase only |
1313
+ | `--json` | Output raw JSON |
1314
+ | `--jq <expr>` | Filter JSON response |
1315
+
1316
+ #### Server conflict detection (toe-stepping)
1317
+
1318
+ 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.
1319
+
1320
+ 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).
1321
+
1322
+ ---
1323
+
1324
+ ### `dbo tag`
1325
+
1326
+ Apply macOS Finder color tags or Linux gio emblems to companion files based on their sync status relative to the server. Tags are automatically refreshed after `dbo clone` and `dbo push`.
1327
+
1328
+ | Tag | Color | Meaning |
1329
+ |-----|-------|---------|
1330
+ | `dbo:Synced` | 🟢 Green | File matches server — no local changes |
1331
+ | `dbo:Modified` | 🔵 Blue | Local edits not yet pushed |
1332
+ | `dbo:Untracked` | 🟡 Yellow | No metadata — not yet added with `dbo add` |
1333
+ | `dbo:Trashed` | 🔴 Red | File is in the `trash/` directory |
1334
+
1335
+ ```bash
1336
+ dbo tag # Refresh tags for all project files
1337
+ dbo tag --clear # Remove all dbo:* tags (preserves other Finder tags)
1338
+ dbo tag --status # Show counts per category
1339
+ dbo tag --verbose # Log each file and its status
1340
+ dbo tag path/to/dir # Tag a specific file or directory subtree
1341
+ dbo tag --enable # Enable automatic tagging after clone/push (default)
1342
+ dbo tag --disable # Disable automatic tagging
1343
+ ```
1344
+
1345
+ Tagging is silently skipped on Windows and unsupported platforms. Only macOS (Finder color tags via `xattr`) and Linux (gio emblems) are supported. The `--clear` flag only removes `dbo:*` prefixed tags, preserving any user-applied Finder tags.
1346
+
1347
+ ---
1348
+
1349
+ ### `dbo rm`
1350
+
1351
+ Remove a file or directory locally and stage server deletions for the next `dbo push`. Similar to `git rm`.
1352
+
1353
+ #### Single file
1354
+
1355
+ ```bash
1356
+ # Remove a content file (finds companion .metadata.json automatically)
1357
+ dbo rm bins/app/some-file.txt
1358
+
1359
+ # Remove by metadata file directly
1360
+ dbo rm bins/app/some-file.metadata.json
1361
+
1362
+ # Skip confirmation prompt
1363
+ dbo rm -f bins/app/some-file.txt
1364
+
1365
+ # Stage server deletion without deleting local files
1366
+ dbo rm --keep-local bins/app/some-file.txt
1367
+ ```
1368
+
1369
+ #### Directory
1370
+
1371
+ ```bash
1372
+ # Remove a directory and all its contents (prompts for approach)
1373
+ dbo rm bins/app/ui/
1374
+
1375
+ # Remove directory without prompts
1376
+ dbo rm -f bins/app/ui/
1377
+
1378
+ # Stage deletions without removing local files/directories
1379
+ dbo rm --keep-local bins/app/ui/
1380
+ ```
1381
+
1382
+ When removing a directory, the CLI:
1383
+ 1. Looks up the BinID from `.dbo/structure.json`
1384
+ 2. Recursively collects all sub-directories (processed leaves-first)
1385
+ 3. Prompts: "Remove all files and directories", "Prompt for each file", or "Cancel"
1386
+ 4. Stages each file's deletion, then each bin's deletion (`entity:bin`)
1387
+ 5. Removes the local directory (unless `--keep-local`)
1388
+
1389
+ | Flag | Description |
1390
+ |------|-------------|
1391
+ | `<path>` | File, `.metadata.json`, or directory to remove |
1392
+ | `-f, --force` | Skip all confirmation prompts |
1393
+ | `--keep-local` | Only stage server deletions, keep local files/directories |
1394
+ | `--hard` | Immediately delete local files (no `Trash/` move; legacy behavior) |
1395
+
1396
+ #### What rm does (single file)
1397
+
1398
+ 1. **Resolves metadata** — if given a content file, finds the companion `.metadata.json`
1399
+ 2. **Reads row ID** — uses `_id` (shorthand) or derives from entity (e.g., `ContentID`, `MediaID`)
1400
+ 3. **Prompts for confirmation** — "Do you really want to remove this file and all of its nodes?"
1401
+ 4. **Stages deletion** — adds a delete entry to `.dbo/synchronize.json`
1402
+ 5. **Updates app.json** — removes the `@path/to/file.metadata.json` reference from children arrays
1403
+ 6. **Soft-deletes local files** — renames files with `__WILL_DELETE__` prefix (unless `--keep-local` or `--hard`)
1404
+ 7. **After `dbo push`** — successfully deleted records have their `__WILL_DELETE__` files moved to `Trash/`
1405
+
1406
+ Use `--hard` to immediately delete files without the `Trash/` safety net.
1407
+
1408
+ #### synchronize.json
1409
+
1410
+ Pending deletions are stored in `.dbo/synchronize.json`:
1411
+
1412
+ ```json
1413
+ {
1414
+ "delete": [
1415
+ {
1416
+ "UID": "a2dxvg23rk6xsmnum7pdxa",
1417
+ "RowID": 16012,
1418
+ "entity": "content",
1419
+ "name": "nima-test-test",
1420
+ "expression": "RowID:del16012;entity:content=true"
1421
+ }
1422
+ ],
1423
+ "edit": [],
1424
+ "add": []
1425
+ }
1426
+ ```
1427
+
1428
+ The next `dbo push` processes all pending deletions before pushing file changes. Successful deletions are removed from synchronize.json; failures remain staged for retry.
1429
+
1430
+ ---
1431
+
1432
+ ### `dbo add`
1433
+
1434
+ Add a new file to DBO.io by creating a server record. Similar to `git add`, this registers a local file with the server.
1435
+
1436
+ Files matching `.dboignore` patterns are skipped — both in directory-scan mode (`dbo add .`) and single-file mode (`dbo add file.html`). Use `dbo input` to create a record for an ignored file directly.
1437
+
1438
+ #### Single file
1439
+
1440
+ ```bash
1441
+ # Add a file (interactive metadata setup if no .metadata.json exists)
1442
+ dbo add assets/css/colors.css
1443
+
1444
+ # Add with auto-accept prompts
1445
+ dbo add assets/css/colors.css -y
1446
+
1447
+ # Add with ticket ID
1448
+ dbo add assets/css/colors.css --ticket abc123
1449
+ ```
1450
+
1451
+ If the file has no companion `.metadata.json`, an interactive wizard prompts for the entity name, content column, AppID, BinID, SiteID, and Path. It then creates the metadata file and submits the insert.
1452
+
1453
+ #### Directory scan
1454
+
1455
+ ```bash
1456
+ # Scan current directory for un-added files
1457
+ dbo add .
1458
+
1459
+ # Scan a specific directory
1460
+ dbo add assets/
1461
+ ```
1462
+
1463
+ Recursively finds files that either have no `.metadata.json` companion or have metadata without `_CreatedOn` (never been on the server). Lists them and prompts for confirmation before adding.
1464
+
1465
+ When adding multiple files, the entity and column defaults from the first file are reused for subsequent files.
1466
+
1467
+ #### After adding
1468
+
1469
+ After a successful add, the server returns a UID which is written back to the metadata file. To populate all server-side columns (like `_CreatedOn`, `Extension`, etc.), run:
1470
+
1471
+ ```bash
1472
+ dbo pull -e content <uid>
1473
+ ```
1474
+
1475
+ #### Metadata generated by add
1476
+
1477
+ Minimal (no optional fields provided):
1478
+ ```json
1479
+ {
1480
+ "Name": "colors",
1481
+ "Path": "assets/css/colors.css",
1482
+ "Content": "@colors.css",
1483
+ "_entity": "content",
1484
+ "_contentColumns": ["Content"]
1485
+ }
1486
+ ```
1487
+
1488
+ With optional fields (only included if the user provides values during the wizard):
1489
+ ```json
1490
+ {
1491
+ "AppID": 10100,
1492
+ "BinID": 11045,
1493
+ "SiteID": 10061,
1494
+ "Name": "colors",
1495
+ "Path": "assets/css/colors.css",
1496
+ "Content": "@colors.css",
1497
+ "_entity": "content",
1498
+ "_contentColumns": ["Content"]
1499
+ }
1500
+ ```
1501
+
1502
+ The `@colors.css` reference tells the CLI to read the file content from `colors.css` in the same directory.
1503
+
1504
+ | Flag | Description |
1505
+ |------|-------------|
1506
+ | `<path>` | File or `.` to scan current directory |
1507
+ | `-C, --confirm <true\|false>` | Commit (default: `true`) |
1508
+ | `--ticket <id>` | Override ticket ID |
1509
+ | `--modify-key <key>` | Provide ModifyKey directly (skips interactive prompt) |
1510
+ | `--row-key <type>` | Row key type (`RowUID` or `RowID`) — `add` always uses `RowID:add1` for new records regardless |
1511
+ | `-y, --yes` | Auto-accept all prompts |
1512
+ | `--json` | Output raw JSON |
1513
+ | `--jq <expr>` | Filter JSON response |
1514
+
1515
+ #### Column filtering
1516
+
1517
+ The `add` and `push` commands never submit these server-managed columns:
1518
+ - `_CreatedOn`, `_LastUpdated` — set by the server
1519
+ - `_LastUpdatedUserID`, `_LastUpdatedTicketID` — session-provided values
1520
+ - `UID` — assigned by the server on insert
1521
+ - `_id` — internal database ID
1522
+
1523
+ ---
1524
+
1525
+ ### Automatic error recovery
1526
+
1527
+ The `input`, `push`, and `add` commands automatically detect recoverable server errors and prompt for missing values instead of failing immediately.
1528
+
1529
+ #### Ticket error recovery
1530
+
1531
+ When the server returns a `ticket_error` (record update requires a Ticket ID), the CLI prompts with interactive recovery options:
1532
+
1533
+ ```
1534
+ ⚠ This record update requires a Ticket ID.
1535
+ ? Record update requires a Ticket ID:
1536
+ ❯ Apply a Ticket ID to this record and resubmit
1537
+ Apply a Ticket ID to all updates in this transaction, and update my current Ticket ID reference
1538
+ Skip this record update
1539
+ Skip all updates that require a Ticket ID
1540
+ ```
1541
+
1542
+ #### Ticket suggestions
1543
+
1544
+ 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:
1545
+
1546
+ ```
1547
+ ? Select a Ticket ID:
1548
+ ❯ 1 (TKT-001): Fix login page [login-fix]
1549
+ 2 (TKT-002): Update dashboard [dashboard-v2]
1550
+ 3 (TKT-003): Refactor auth [auth-refactor]
1551
+ Enter a Ticket ID manually…
1552
+ ```
1553
+
1554
+ The suggestions are fetched from the configured output endpoint, filtered by the current record's UID. Users can arrow-key through the list to select a ticket, or choose "Enter a Ticket ID manually" for custom input.
1555
+
1556
+ If `TicketSuggestionOutput` is not configured or the fetch fails, the CLI falls back to a plain text input prompt.
1557
+
1558
+ When the server returns a `repo_mismatch` (Ticket ID belongs to a different repository), the CLI prompts:
1559
+
1560
+ ```
1561
+ ⚠ Ticket "TICKET-123" is for another repository.
1562
+ ? The Ticket ID of "TICKET-123" is for another Repository:
1563
+ ❯ Commit anyway
1564
+ Submit with another Ticket ID
1565
+ Skip this record
1566
+ Commit all transactions with this ID anyway
1567
+ Commit all transactions with another Ticket ID, and update my current Ticket ID reference
1568
+ Skip all
1569
+ ```
1570
+
1571
+ 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.
1572
+
1573
+ #### Ticket ID required (legacy)
1574
+
1575
+ When the server returns `ticket_lookup_required_error`, the CLI prompts:
1576
+
1577
+ ```
1578
+ ⚠ This operation requires a Ticket ID.
1579
+ ? Ticket ID Required: ___
1580
+ ```
1581
+
1582
+ The submission is then retried with `_OverrideTicketID`. To skip the prompt, pass `--ticket <id>` upfront.
1583
+
1584
+ #### Pre-submission ticket prompt
1585
+
1586
+ When a stored ticket exists in `.dbo/ticketing.local.json`, the CLI prompts before batch submissions (`push`, `input`, `add`, `content deploy`, `deploy`):
1587
+
1588
+ ```
1589
+ ? Use stored Ticket ID "TICKET-123" for this submission?
1590
+ ❯ Yes, use "TICKET-123"
1591
+ Use a different ticket for this submission only
1592
+ Use a different ticket for this and future submissions
1593
+ No, clear stored ticket
1594
+ Cancel submission
1595
+ ```
1596
+
1597
+ - **Yes** — applies the stored ticket to all records in this submission
1598
+ - **Different ticket (this submission only)** — prompts for a ticket ID, uses it for all records in this invocation without updating `ticketing.local.json`
1599
+ - **Different ticket (this and future)** — prompts for a ticket ID, updates `ticketing.local.json`, and uses it for this and all future submissions
1600
+ - **No, clear** — removes the stored `ticket_id` and proceeds without a ticket
1601
+ - **Cancel** — aborts the submission
1602
+
1603
+ #### `.dbo/ticketing.local.json`
1604
+
1605
+ Stores ticket IDs for automatic application during submissions:
1606
+
1607
+ ```json
1608
+ {
1609
+ "ticket_id": "TICKET-123",
1610
+ "records": [
1611
+ {
1612
+ "UID": "a2dxvg23rk6xsmnum7pdxa",
1613
+ "RowID": 16012,
1614
+ "entity": "content",
1615
+ "ticket_id": "TICKET-456",
1616
+ "expression": "RowID:16012;column:content._LastUpdatedTicketID=TICKET-456"
1617
+ }
1618
+ ]
1619
+ }
1620
+ ```
1621
+
1622
+ - `ticket_id` — Global ticket applied to all submissions until cleared
1623
+ - `records` — Per-record tickets (auto-cleared after successful submission)
1624
+ - `--ticket` flag always takes precedence over stored tickets
1625
+
1626
+ #### ModifyKey protection (locked/production apps)
1627
+
1628
+ When an app has a `ModifyKey` set (production/locked mode), the CLI guards all submission commands (`push`, `input`, `add`, `content deploy`, `deploy`) with an interactive prompt:
1629
+
1630
+ ```
1631
+ ⚠ This app is locked (production mode). A ModifyKey is required to submit changes.
1632
+ ? This app has a ModifyKey set. How would you like to proceed?
1633
+ ❯ Enter the ModifyKey to proceed
1634
+ Cancel submission
1635
+ ```
1636
+
1637
+ The ModifyKey is detected and stored during `dbo clone`. If the key wasn't stored locally but the server requires one, the CLI reactively prompts after the first failed submission:
1638
+
1639
+ ```
1640
+ ⚠ This app requires a ModifyKey. The key has not been set locally (try re-running `dbo clone`).
1641
+ ? A ModifyKey is required. How would you like to proceed?
1642
+ ❯ Enter the ModifyKey to retry
1643
+ Cancel submission
1644
+ ```
1645
+
1646
+ On successful reactive entry, the key is saved to `.dbo/config.json` for future use.
1647
+
1648
+ To bypass the interactive prompt entirely, pass `--modify-key <key>` on any submission command:
1649
+
1650
+ ```bash
1651
+ dbo push . --modify-key mySecretKey
1652
+ dbo input -d '...' --modify-key mySecretKey
1653
+ dbo add myfile.css --modify-key mySecretKey
1654
+ ```
1655
+
1656
+ #### User identity required
1657
+
1658
+ When the server returns an error mentioning `LoggedInUser_UID`, `LoggedInUserID`, `CurrentUserID`, or `UserID`, the CLI checks for a stored user identity from `dbo login`:
1659
+
1660
+ ```
1661
+ ⚠ This operation requires an authenticated user (LoggedInUser_UID).
1662
+ Your session may have expired, or you may not be logged in.
1663
+ You can log in with "dbo login" to avoid this prompt in the future.
1664
+ Stored session user UID: albain3dwkofbhnd1qtd1q
1665
+ ? User UID Required:
1666
+ ❯ Use session user (UID: albain3dwkofbhnd1qtd1q)
1667
+ Enter a different User UID
1668
+ ```
1669
+
1670
+ If no stored user info is available, it prompts for direct input. The CLI automatically determines whether the server needs a UID or numeric ID based on the error message pattern.
1671
+
1672
+ ---
1673
+
1674
+ ### `dbo install` (alias: `dbo i`)
1675
+
1676
+ Install or upgrade dbo cli components including the CLI itself, plugins, and Claude Code integration.
1677
+
1678
+ ```bash
1679
+ # Interactive — choose what to install
1680
+ dbo install
1681
+
1682
+ # Install/upgrade CLI from npm (latest)
1683
+ dbo i dbo
1684
+ dbo i dbo@latest
1685
+
1686
+ # Install a specific CLI version
1687
+ dbo i dbo@0.4.1
1688
+
1689
+ # Install CLI from local source directory
1690
+ dbo install /path/to/local/cli/src
1691
+
1692
+ # Install/upgrade Claude Code commands
1693
+ dbo install plugins
1694
+ dbo install claudecommands
1695
+
1696
+ # Install Claude Code commands globally (shared across projects)
1697
+ dbo install plugins --global
1698
+
1699
+ # Explicitly install to project directory
1700
+ dbo install plugins --local
1701
+
1702
+ # Install Claude Code CLI (if not present) + commands
1703
+ dbo install claudecode
1704
+
1705
+ # Install/upgrade a specific command plugin
1706
+ dbo install --claudecommand dbo
1707
+
1708
+ # Install a specific command globally
1709
+ dbo install --claudecommand dbo --global
1710
+ ```
1711
+
1712
+ | Flag | Description |
1713
+ |------|-------------|
1714
+ | `[target]` | What to install: `dbo[@version]`, `plugins`, `claudecommands`, `claudecode`, or a local path |
1715
+ | `--claudecommand <name>` | Install/upgrade a specific command by name |
1716
+ | `-g, --global` | Install commands to user home directory (`~/.claude/commands/`) |
1717
+ | `--local` | Install commands to project directory (`.claude/commands/`) |
1718
+
1719
+ Smart behavior:
1720
+ - If the CLI is already installed, prompts to upgrade (with version comparison)
1721
+ - If plugins are already installed and up to date, reports "already up to date"
1722
+ - If plugins differ from source, prompts to upgrade to the latest version
1723
+ - Compares file hashes — unchanged files are skipped
1724
+ - Adds project-scoped plugins to `.gitignore` (source of truth is `plugins/claude/` at repo root)
1725
+ - Per-plugin scope (project or global) is stored in `.dbo/config.local.json` and remembered for future upgrades
1726
+ - 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
1727
+ - On first install with no prior preference and no existing installation, prompts for scope
1728
+ - `--global` / `--local` flags override stored preferences and update them
1729
+
1730
+ ---
1731
+
1732
+ ### `dbo deploy`
1733
+
1734
+ Deploy files to DBO.io using a `.dbo/deploy_config.json` manifest or direct arguments.
1735
+
1736
+ ```bash
1737
+ # Deploy a named entry from the manifest
1738
+ dbo deploy css:colors
1739
+
1740
+ # Deploy all entries
1741
+ dbo deploy --all
1742
+
1743
+ # Deploy with ticket ID
1744
+ dbo deploy js:app --ticket abc123
1745
+
1746
+ # Validate without deploying
1747
+ dbo deploy css:colors --confirm false
1748
+
1749
+ # Deploy a multipart (binary) entry from manifest
1750
+ dbo deploy img:logo
1751
+ ```
1752
+
1753
+ | Flag | Description |
1754
+ |------|-------------|
1755
+ | `<name>` | Deployment name from `.dbo/deploy_config.json` |
1756
+ | `--all` | Deploy all entries in the manifest |
1757
+ | `-C, --confirm <true\|false>` | Commit (default: `true`) |
1758
+ | `--ticket <id>` | Override ticket ID |
1759
+ | `--modify-key <key>` | Provide ModifyKey directly (skips interactive prompt) |
1760
+ | `--row-key <type>` | Override row key type for this invocation (`RowUID` or `RowID`) |
1761
+ | `--json` | Output raw JSON |
1762
+ | `-v, --verbose` | Show HTTP request details |
1763
+ | `--domain <host>` | Override domain |
1764
+
1765
+ 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)).
1766
+
1767
+ #### `.dbo/deploy_config.json` manifest
1768
+
1769
+ Create a `.dbo/deploy_config.json` file to define named deployments:
1770
+
1771
+ ```json
1772
+ {
1773
+ "deployments": {
1774
+ "css:colors": {
1775
+ "uid": "albain3dwkofbhnd1qtd1q",
1776
+ "file": "assets/css/colors.css"
1777
+ },
1778
+ "js:app": {
1779
+ "uid": "rncjivlghu65bmkbjnxynq",
1780
+ "file": "assets/js/app.js"
1781
+ },
1782
+ "doc:colors": {
1783
+ "uid": "l2uv2gu8gu6ziyluuncv0w",
1784
+ "file": "docs/colors.md",
1785
+ "entity": "extension",
1786
+ "column": "Text"
1787
+ },
1788
+ "img:logo": {
1789
+ "uid": "x9fk2m3npqrs7tuvwyz1ab",
1790
+ "file": "assets/images/logo.png",
1791
+ "multipart": true
1792
+ },
1793
+ "upload:icons": {
1794
+ "uid": "7ddf10982a96457fa4f440",
1795
+ "file": "assets/css/launchpad-icons.css",
1796
+ "multipart": true,
1797
+ "filename": "launchpad-icons.css"
1798
+ }
1799
+ }
1800
+ }
1801
+ ```
1802
+
1803
+ | Field | Description | Default |
1804
+ |-------|-------------|---------|
1805
+ | `uid` | Target record UID (required) | — |
1806
+ | `file` | Local file path (required) | — |
1807
+ | `entity` | Target entity name | `content` (`media` when `multipart: true`) |
1808
+ | `column` | Target column name | `Content` (`File` when `multipart: true`) |
1809
+ | `multipart` | Use multipart/form-data upload (for binary files) | `false` |
1810
+ | `filename` | Set the `Filename` column on the target record | basename of `file` |
1811
+
1812
+ This replaces the curl commands typically embedded in `package.json` scripts.
1813
+
1814
+ #### Automatic deploy config generation
1815
+
1816
+ When you run `dbo clone` or `dbo add`, 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:
1817
+
1818
+ ```bash
1819
+ dbo clone # → .dbo/deploy_config.json auto-populated with one entry per companion file
1820
+ ```
1821
+
1822
+ 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.
1823
+
1824
+ Once generated, you can deploy by name or by UID:
1825
+
1826
+ ```bash
1827
+ dbo deploy css:colors # deploy by key name
1828
+ dbo deploy cdlftyk2lkg21whojzqqoa # deploy by UID (scans manifest values)
1829
+ ```
1830
+
1831
+ Entries are updated automatically on re-clone (path changes are reflected in place) and removed when you run `dbo rm`. When you `dbo mv` a file, the old entry is removed and a new entry is inserted with the correct key for the new path.
1832
+
1833
+ #### Non-interactive mode (npm scripts)
1834
+
1835
+ 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:
1836
+
1837
+ - **Stored ticket** — auto-applied from `.dbo/ticketing.local.json`
1838
+ - **ModifyKey** — auto-applied from `.dbo/config.json` (`AppModifyKey`)
1839
+ - **User identity** — auto-applied from `.dbo/credentials.json`
1840
+
1841
+ 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.
1842
+
1843
+ Example `package.json` scripts:
1844
+
1845
+ ```json
1846
+ {
1847
+ "scripts": {
1848
+ "deploy:css": "dbo deploy css:colors && dbo deploy css:layout",
1849
+ "deploy:docs": "dbo deploy doc:readme && dbo deploy doc:api",
1850
+ "deploy:all": "dbo deploy --all"
1851
+ }
1852
+ }
1853
+ ```
1854
+
1855
+ To set up for non-interactive use:
1856
+ 1. Run `dbo login` to store user credentials
1857
+ 2. Run `dbo clone` to store the ModifyKey (if applicable)
1858
+ 3. Set a ticket interactively once — it persists in `ticketing.local.json` for future npm script runs
1859
+
1860
+ ---
1861
+
1862
+ ## Script Hooks
1863
+
1864
+ 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`.
1865
+
1866
+ ### Configuration Files
1867
+
1868
+ | File | Tracked | Purpose |
1869
+ |------|---------|---------|
1870
+ | `.dbo/scripts.json` | Yes | Shared hook definitions (committed to git) |
1871
+ | `.dbo/scripts.local.json` | No | Per-user overrides (gitignored) |
1872
+
1873
+ ### Top-level Keys
1874
+
1875
+ | Key | Description |
1876
+ |-----|-------------|
1877
+ | `scripts` | Global hooks and named scripts (apply to all targets) |
1878
+ | `targets` | Per-file or per-directory hooks (highest priority) |
1879
+ | `entities` | Per-entity-type hooks (e.g., `content`, `extension.control`) |
1880
+
1881
+ ### Example `.dbo/scripts.json`
1882
+
1883
+ ```json
1884
+ {
1885
+ "scripts": {
1886
+ "prepush": "echo pushing $DBO_TARGET"
1887
+ },
1888
+ "targets": {
1889
+ "lib/bins/app/assets/js/operator.js": {
1890
+ "build": "rollup -c src/rollup_config.mjs",
1891
+ "push": false
1892
+ }
1893
+ },
1894
+ "entities": {
1895
+ "extension.control": {
1896
+ "prebuild": "npm run compile-controls"
1897
+ }
1898
+ }
1899
+ }
1900
+ ```
1901
+
1902
+ ### Lifecycle Hooks
1903
+
1904
+ | Hook | Phase | Description |
1905
+ |------|-------|-------------|
1906
+ | `prebuild` | Build | Runs before build |
1907
+ | `build` | Build | Main build step |
1908
+ | `postbuild` | Build | Runs after build |
1909
+ | `prepush` | Push | Runs before push |
1910
+ | `push` | Push | Custom push (replaces default HTTP submit) |
1911
+ | `postpush` | Push | Runs after push |
1912
+
1913
+ ### Resolution Order
1914
+
1915
+ Hooks resolve per-hook from lowest to highest priority:
1916
+
1917
+ 1. **Global** (`scripts`) — applies to all targets
1918
+ 2. **Entity** (`entities`) — applies to targets matching the entity type
1919
+ 3. **Target** (`targets`) — applies to a specific file or directory
1920
+
1921
+ A target can override `build` while the global `prepush` still applies.
1922
+
1923
+ ### Hook Value Types
1924
+
1925
+ | Value | Behavior |
1926
+ |-------|----------|
1927
+ | `"command"` | Run as shell command |
1928
+ | `["cmd1", "cmd2"]` | Run sequentially; fail-fast on first non-zero exit |
1929
+ | `false` | Skip (for `push`: skip HTTP submit) |
1930
+ | `true` / omitted | Use default behavior |
1931
+
1932
+ ### Environment Variables
1933
+
1934
+ These env vars are injected into all hook processes:
1935
+
1936
+ | Variable | Description |
1937
+ |----------|-------------|
1938
+ | `DBO_TARGET` | Relative file path being processed |
1939
+ | `DBO_ENTITY` | Entity type (e.g., `content`, `extension`) |
1940
+ | `DBO_DOMAIN` | Configured domain |
1941
+ | `DBO_APP` | App short name |
1942
+ | `DBO_APP_UID` | App UID |
1943
+
1944
+ ### Push Flags
1945
+
1946
+ | Flag | Description |
1947
+ |------|-------------|
1948
+ | `--no-scripts` | Bypass all script hooks; run default push pipeline |
1949
+ | `--no-build` | Skip build phase; run push phase only |
1950
+
1951
+ ### `dbo build [path]`
1952
+
1953
+ Runs the build lifecycle (`prebuild` → `build` → `postbuild`) without pushing.
1954
+
1955
+ ```bash
1956
+ # Build a specific target
1957
+ dbo build lib/bins/app/assets/js/operator.js
1958
+
1959
+ # Build all targets with a build hook
1960
+ dbo build
1961
+ ```
1962
+
1963
+ ### `dbo run [script-name]`
1964
+
1965
+ Runs a named global script from `.dbo/scripts.json` (like `npm run`). Automatically runs `pre<name>` and `post<name>` scripts if defined.
1966
+
1967
+ ```bash
1968
+ # List all available scripts
1969
+ dbo run
1970
+
1971
+ # Run a specific script
1972
+ dbo run prepush
1973
+ ```
1974
+
1975
+ ---
1976
+
1977
+ ## Global Flags
1978
+
1979
+ These flags are available on most commands:
1980
+
1981
+ | Flag | Description |
1982
+ |------|-------------|
1983
+ | `-C, --confirm <true\|false>` | Commit changes (default: `true`). Use `false` for validation only |
1984
+ | `--json` | Output raw JSON response with syntax highlighting |
1985
+ | `--jq <expr>` | Filter JSON response with a jq-like expression (implies `--json`) |
1986
+ | `-v, --verbose` | Show HTTP request details (method, URL, body) |
1987
+ | `--domain <host>` | Override the configured domain for this request |
1988
+ | `-h, --help` | Show help for any command |
1989
+
1990
+ ---
1991
+
1992
+ ## JSON Filtering (`--jq`)
1993
+
1994
+ The `--jq` flag provides built-in jq-like JSON filtering without requiring `jq` to be installed. It supports the most common patterns:
1995
+
1996
+ ```bash
1997
+ # Pretty-print the entire response (with syntax highlighting)
1998
+ dbo output -e user --jq '.'
1999
+
2000
+ # Extract a specific key
2001
+ dbo output -e user --jq '.Payload'
2002
+
2003
+ # Nested key access
2004
+ dbo input -d '...' --jq '.Payload.Results.Add'
2005
+
2006
+ # Pluck a field from every item in an array
2007
+ dbo output -e user --jq '.Payload.Results.Add[].UID'
2008
+
2009
+ # Array index
2010
+ dbo output -e user --jq '.Payload.Results.Add[0]'
2011
+
2012
+ # Pipe: iterate then access
2013
+ dbo output -e user --jq '.Payload.Results.Add[] | .UID'
2014
+
2015
+ # Use with any command that returns JSON
2016
+ dbo cache list --jq '.Payload'
2017
+ dbo message myUID --jq '.Successful'
2018
+ ```
2019
+
2020
+ ### Supported expressions
2021
+
2022
+ | Expression | Description |
2023
+ |-----------|-------------|
2024
+ | `.` | Identity (entire response) |
2025
+ | `.key` | Access a top-level key |
2026
+ | `.key.nested` | Nested key access |
2027
+ | `.[0]` | Array index |
2028
+ | `.[]` | Iterate array |
2029
+ | `.[].field` | Pluck field from each array item |
2030
+ | `.[] \| .field` | Pipe: iterate then access |
2031
+ | `.["key.name"]` | Bracket notation for keys with dots |
2032
+
2033
+ When `--jq` is used, the API request is automatically made with `_template=json_raw`.
2034
+
2035
+ ### JSON syntax highlighting
2036
+
2037
+ Both `--json` and `--jq` output use syntax highlighting:
2038
+ - **Keys** in cyan
2039
+ - **Strings** in green
2040
+ - **Numbers** in yellow
2041
+ - **Booleans/null** in magenta
2042
+
2043
+ ---
2044
+
2045
+ ## DBO API Parameter Reference
2046
+
2047
+ The DBO.io API uses a token architecture for dynamic parameters. All parameters are passed as URL query string key-value pairs.
2048
+
2049
+ ### Token Syntax
2050
+
2051
+ Parameters follow the token delimiter system:
2052
+
2053
+ ```
2054
+ _tokenType@reference$target!defaultValue:modifier=value
2055
+ ```
2056
+
2057
+ | Delimiter | Purpose | Example |
2058
+ |-----------|---------|---------|
2059
+ | `_` | Prefix for token type | `_filter`, `_sort`, `_limit` |
2060
+ | `@` | Reference (column, field, key) | `_filter@FirstName=John` |
2061
+ | `$` | Target (scope to a specific output/entity) | `_limit$outputUid=100` |
2062
+ | `!` | Default value (fallback) | `_filter@Status!active=value` |
2063
+ | `:` | Modifier(s) | `_filter@Name:Contains=john` |
2064
+
2065
+ ### Output Parameters
2066
+
2067
+ These parameters control the output endpoint behavior (`/api/output/{uid}` and `/api/output/entity/{entityUid}`):
2068
+
2069
+ #### Filtering
2070
+
2071
+ ```
2072
+ _filter@ColumnName=value # exact match (default)
2073
+ _filter@ColumnName:Contains=value # LIKE %value%
2074
+ _filter@ColumnName:StartsWith=value # LIKE value%
2075
+ _filter@ColumnName:EndsWith=value # LIKE %value
2076
+ _filter@ColumnName:LessThan=value # < comparison
2077
+ _filter@ColumnName:LessThanOrEqualTo=value # <= comparison
2078
+ _filter@ColumnName:GreaterThan=value # > comparison
2079
+ _filter@ColumnName:GreaterThanOrEqualTo=value # >= comparison
2080
+ _filter@ColumnName:Contains,And=value # AND logic (default is OR)
2081
+ _filter@ColumnName:Contains,Exclude=value # NOT LIKE
2082
+ _filter$outputTarget@ColumnName=value # scoped to specific output
2083
+ ```
2084
+
2085
+ #### Sorting
2086
+
2087
+ ```
2088
+ _sort=ColumnName # ascending (default)
2089
+ _sort=ColumnName:ASC # explicit ascending
2090
+ _sort=ColumnName:DESC # descending
2091
+ _sort=Column1:ASC,Column2:DESC # multiple sorts (comma-separated)
2092
+ _sort=ColumnName ASC # space-separated also works
2093
+ ```
2094
+
2095
+ Multiple `_sort` parameters can be specified; earlier sorts take precedence.
2096
+
2097
+ #### Pagination
2098
+
2099
+ ```
2100
+ _limit=30 # max 30 rows
2101
+ _limit=10-30 # rows 10 through 30 (range)
2102
+ _limit=10&_page=3 # 10 rows per page, page 3
2103
+ _rowcount=false # disable row count for performance
2104
+ ```
2105
+
2106
+ Deprecated (still accepted): `_maxrows`, `_rows`, `_rowsperpage`
2107
+
2108
+ #### Search
2109
+
2110
+ ```
2111
+ _search=keyword # full-text search across searchable columns
2112
+ _search@ColumnName=keyword # search specific column
2113
+ ```
2114
+
2115
+ #### Template & Format
2116
+
2117
+ ```
2118
+ _template=json_raw # system template name: json_raw, json_indented, json, html, csv, xml, txt, pdf
2119
+ _template=3iX9fHFTL064Shgol8Bktw # content UID (custom template)
2120
+ _format_values=true # enable value formatting in json_raw
2121
+ _mime=application/json # override MIME/content type
2122
+ _escape_html=false # disable HTML escaping of data values
2123
+ ```
2124
+
2125
+ > **`_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.
2126
+
2127
+ #### Display Control
2128
+
2129
+ ```
2130
+ _display@tagName=show # show a template content tag
2131
+ _display@tagName=hide # hide a template content tag
2132
+ _empty_response_code=404 # HTTP status when results are empty
2133
+ _fallback_content:404=contentUID # render a different content on 404
2134
+ ```
2135
+
2136
+ #### Debug & Profiling
2137
+
2138
+ ```
2139
+ _debug=true # general debug output
2140
+ _debug:sql=true # return SQL without executing
2141
+ _debug:verbose=true # verbose debug
2142
+ _debug:analysis=true # analysis debug
2143
+ _profile=true # MiniProfiler output
2144
+ ```
2145
+
2146
+ Other debug sub-keys: `http_modules`, `instance`, `rewrites`, `cache`, `executable_contents`, `security`, `controllers`, `embeds`, `includes`, `contents`, `template_render`, `tokens`, `messages`, `media`, `request_stack`, `query_execution`, `query_building`
2147
+
2148
+ #### Control Flags
2149
+
2150
+ ```
2151
+ _strict=true # strict error mode
2152
+ _confirm=true # confirmation flag for operations
2153
+ _no_transaction=true # disable transaction wrapping
2154
+ _skip=all # skip execution phases (admin-only)
2155
+ _include=value # include token
2156
+ _security=value # security filter enforcement
2157
+ ```
2158
+
2159
+ ### Data Tokens (used in templates)
2160
+
2161
+ | Token | Description |
2162
+ |-------|-------------|
2163
+ | `#{value@ColumnName}` | Column value from output row |
2164
+ | `#{id}` | Row primary key |
2165
+ | `#{uid}` | Row UID |
2166
+ | `#{CurrentUser@field}` | Current user field (e.g., `FirstName`, `Email`) |
2167
+ | `#{request@key}` | URL parameter value |
2168
+ | `#{session@variable}` | Session variable |
2169
+ | `#{site@field}` | Site field |
2170
+ | `#{date:format}` | Current date/time |
2171
+ | `#{unique:uid}` | Generate unique UID |
2172
+ | `#{count}` | Row count |
2173
+ | `#{page}` | Current page number |
2174
+
2175
+ ### Template Tags
2176
+
2177
+ System tags (used in output templates):
2178
+
2179
+ | Tag | Purpose |
2180
+ |-----|---------|
2181
+ | `<#_row>` | Row template |
2182
+ | `<#_header>` | Header template |
2183
+ | `<#_footer>` | Footer template |
2184
+ | `<#_cell>` | Cell template |
2185
+ | `<#_empty>` | Empty result template |
2186
+ | `<#_noresult>` | No result template |
2187
+ | `<#_prompt>` | Prompt template |
2188
+ | `<#_shared>` | Shared template |
2189
+ | `<#_rowdelimiter>` | Row delimiter |
2190
+ | `<#_celldelimiter>` | Cell delimiter |
2191
+ | `<#_value>` | Value template |
2192
+ | `<#_embed url="...">` | Embed nested content/output |
2193
+
2194
+ User-defined tags use `<#reference>` (no underscore prefix).
2195
+
2196
+ ---
2197
+
2198
+ ## Migration from curl
2199
+
2200
+ The `dbo` CLI is a drop-in replacement for the curl-based workflow. Here's how common operations translate:
2201
+
2202
+ ### Authentication
2203
+
2204
+ **Before:**
2205
+ ```bash
2206
+ echo "my-domain.com" > .domain
2207
+ echo "user@example.com" > .username
2208
+ echo "mypassword" > .password
2209
+ curl --cookie-jar .cookies -K authenticate.curl
2210
+ ```
2211
+
2212
+ **After:**
2213
+ ```bash
2214
+ dbo init --domain my-domain.com --username user@example.com
2215
+ dbo login
2216
+ ```
2217
+
2218
+ ### Edit a record
2219
+
2220
+ **Before:**
2221
+ ```bash
2222
+ curl -K config-data.curl -d "RowID:10065;column:user.FirstName=Jane"
2223
+ ```
2224
+
2225
+ **After:**
2226
+ ```bash
2227
+ dbo input -d 'RowID:10065;column:user.FirstName=Jane'
2228
+ ```
2229
+
2230
+ ### Deploy CSS from a local file
2231
+
2232
+ **Before:**
2233
+ ```bash
2234
+ curl -K config-data.curl --data-urlencode RowUID%3Aalbain3dwkofbhnd1qtd1q%3Bcolumn%3Acontent.Content@assets/css/colors.css
2235
+ ```
2236
+
2237
+ **After:**
2238
+ ```bash
2239
+ dbo content deploy albain3dwkofbhnd1qtd1q assets/css/colors.css
2240
+ ```
2241
+
2242
+ ### Upload a media file
2243
+
2244
+ **Before:**
2245
+ ```bash
2246
+ curl -K config-form.curl -F file=@path/to/image.jpg -F "RowID:add1;column:media.BinID=12345" -F "RowID:add1;column:media.AppID=67890" -F "RowID:add1;column:media.Ownership=app" -F "RowID:add1;column:media.Path=assets/images"
2247
+ ```
2248
+
2249
+ **After:**
2250
+ ```bash
2251
+ dbo upload image.jpg --bin 12345 --app 67890 --ownership app --path assets/images
2252
+ ```
2253
+
2254
+ ### Query data
2255
+
2256
+ **Before:**
2257
+ ```bash
2258
+ curl -b .cookies "https://my-domain.com/api/output/entity/user?_template=json_indented&_filter@FirstName=John"
2259
+ ```
2260
+
2261
+ **After:**
2262
+ ```bash
2263
+ dbo output -e user --filter 'FirstName=John' --template json_indented
2264
+ ```
2265
+
2266
+ ### Cookie compatibility
2267
+
2268
+ The `dbo` CLI writes cookies in Netscape format (same as curl's `--cookie-jar`). You can use the same cookie file with both tools during migration:
2269
+
2270
+ ```bash
2271
+ dbo login
2272
+ curl -b .dbo/cookies.txt https://my-domain.com/api/content/myUID
2273
+ ```
2274
+
2275
+ ---
2276
+
2277
+ ## License
2278
+
2279
+ Copyright manolab, LLC