npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dboio/cli

v0.19.7

Published

CLI for the DBO.io framework

Readme

dbo — Command Line Interface for DBO.io

npm version npm downloads

A terminal-based CLI for interacting with the DBO.io framework. Replaces raw curl commands with a clean, subcommand-driven interface for CRUD operations, querying, content deployment, media management, and more.

Available on npm: @dboio/cli

Installation

From npm (recommended)

npm install -g @dboio/cli

This installs the dbo command globally on your system.

From the repository (local development)

cd tools/cli
npm install
npm link

Without installing (npx)

npx @dboio/cli <command>

Shorthand: You can use dbo i as a shortcut for dbo install (similar to npm i).

Requirements

  • Node.js 18+ (uses native fetch and FormData)
  • A DBO.io instance to connect to

Claude Code Integration

The dbo CLI can be used as a /dbo slash command inside Claude Code sessions.

Install Claude Code commands

# Install the /dbo command into your project's .claude/commands/
dbo install claudecommands

# Install globally to ~/.claude/commands/ (shared across projects)
dbo install claudecommands --global

# Or install Claude Code CLI + commands together
dbo install claudecode

Once installed, use /dbo in Claude Code:

/dbo pull albain3dwkofbhnd1qtd1q
/dbo output -e user --maxrows 5
/dbo push assets/css/

The plugin source lives in plugins/claude/dbo/ at the repository root. Installed copies in .claude/plugins/ are gitignored and managed by dbo install. Each plugin's installation scope (project or global) is stored in ~/.dbo/settings.json.


Upgrading

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.

# Upgrade CLI to latest version
dbo install dbo@latest

# Install/upgrade to a specific version
dbo install [email protected]

# Upgrade from local source
dbo install /path/to/local/cli/src

# Upgrade Claude Code commands (prompts if already installed)
dbo install plugins

# Upgrade a specific Claude command
dbo install --claudecommand dbo

# Check your version
dbo --version

Quick Start

# 1. Initialize configuration for the current directory
dbo init --domain my-domain.com

# 1b. Combined with cloning an app to local project bin
dbo init --domain my-domain.com --app myapp --clone

# 2. Authenticate
dbo login

# 3. Check your session
dbo status

# 4. Query some data
dbo output -e user --template json_indented --maxrows 5

# 5. Deploy a CSS file
dbo content deploy albain3dwkofbhnd1qtd1q assets/css/colors.css

Project Directory Structure

When you run dbo init --scaffold or dbo clone, the following standard directories are created in your project root:

my-project/
├── .app/               # Config, synchronization and session info for dbo cli commands
│   ├── config.json     # Domain, app metadata, placement preferences (committed)
│   ├── <shortName>.json          # Server-state baseline for delta detection (committed)
│   ├── <shortName>.metadata.json # Clone of original app JSON with @references (committed)
│   ├── <shortName>.metadata_schema.json # Column templates per entity/descriptor (committed)
│   ├── directories.json          # Bin directory mapping (committed)
│   ├── synchronize.json          # Pending add/edit/delete staging (committed)
│   ├── credentials.json          # Username, user ID (gitignored)
│   ├── cookies.txt               # Session cookie (gitignored)
│   └── scripts.json              # Build/push lifecycle hooks (committed)
├── .claude/            # Claude Code plugin config (commands, specs, plans, skills)
├── app_dependencies/   # Read-only checkouts of dependency apps (gitignored)
│   └── _system/        # System schema dependency
├── lib/                # All DBO server-managed assets
│   ├── bins/           # Assets (contents, outputs, images, HTML, CSS)
│   │   └── app/        # Default application bin
│   ├── automation/     # Automation entity records
│   ├── app_version/    # App version entity records
│   ├── entity/         # Entity definitions
│   ├── entity_column/  # Column definitions
│   ├── entity_column_value/ # Column value definitions
│   ├── extension/      # Extension entity records (organized by descriptor type)
│   │   ├── widget/
│   │   └── documentation/
│   ├── integration/    # Integration entity records
│   ├── security/       # Security policy records
│   ├── security_column/ # Column-level security records
│   ├── data_source/    # (created when data sources exist)
│   ├── group/          # (created when groups exist)
│   ├── site/           # (created when sites exist)
│   └── redirect/       # (created when redirects exist)
├── src/                # Your actual source code (sass, typescript, etc.)
├── test/               # Project-level tests
├── trash/              # Staged soft-deleted files from dbo rm
├── docs/               # Project documentation and docs entities
├── manifest.json       # PWA web app manifest (root content file — server-tracked)
├── CLAUDE.md           # Claude Code instructions (root content file — server-tracked)
├── README.md           # Project readme (root content file — server-tracked)
├── .gitignore          # Tells Git to ignore files in the repo sync
├── .dboignore          # Tells dbo cli to ignore files in commands
├── package.json        # Metadata, scripts, and dependency list
└── package-lock.json   # Records exact versions of dependencies installed

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/.


Configuration

All configuration is directory-scoped. Each project folder maintains its own .app/ directory with its own domain and session. Switch environments by switching directories:

~/projects/my-project/    → .app/ → my-domain.com
~/projects/my-project-prod/    → .app/ → prod.dbo.io

.app/ directory contents

| File | Purpose | Git | |------|---------|-----| | config.json | Domain, app metadata, placement preferences | Committable (shared) | | credentials.json | Username, user ID, UID, name, email (no password) | Gitignored (per-user) | | cookies.txt | Session cookie (Netscape format) | Gitignored (per-user) | | directories.json | Bin directory mapping (created by dbo clone) | Committable (shared) | | <shortName>.metadata_schema.json | Column templates per entity/descriptor (auto-generated by dbo clone) | Committable (shared) | | synchronize.json | Pending deletions and sync state (updated by dbo rm and dbo push) | Committable (shared) | | <shortName>.json | Server-state snapshot for delta detection — stores column values at last clone/push so dbo push can detect which columns changed locally. Read-only (chmod 444). | Committable (shared) | | <shortName>.metadata.json | Clone of original app JSON with entity entries replaced by @path/to/*.metadata.json references | Committable (shared) | | scripts.json | Build/push lifecycle hooks (see Script Hooks) | Committable (shared) | | scripts.local.json | Per-user hook overrides | Gitignored (per-user) | | ticketing.local.json | Stored ticket IDs for submission error recovery | Gitignored (per-user) |

Per-user settings (plugin scopes, completed migrations) are stored globally in ~/.dbo/settings.json.

dbo init automatically adds .app/credentials.json, .app/cookies.txt, .app/ticketing.local.json, .app/scripts.local.json, .app/errors.log, and app_dependencies/ to .gitignore (creates the file if it doesn't exist).

Upgrading to 0.18.0+: The project directory has been restructured: .dbo/ is renamed to .app/, app.json moves to .app/<shortName>.metadata.json, schema.json is removed (schema now sourced from app_dependencies/_system/), .dbo/dependencies/ moves to app_dependencies/, .app_baseline.json becomes <shortName>.json, structure.json becomes directories.json, metadata_schema.json becomes <shortName>.metadata_schema.json, and config.local.json moves to ~/.dbo/settings.json. Migration 012 runs automatically on first command after upgrade.

Upgrading to 0.16.0+: metadata_templates.json is renamed to metadata_schema.json. The _contentColumns field in metadata files is renamed to _companionReferenceColumns. Extension companion file prompts during dbo clone are replaced by automatic derivation from descriptor_definition form-control-code data. Migration 011 runs automatically on first use.

Upgrading to 0.14.0+: Metadata files now use name.metadata~uid.json instead of name~uid.metadata.json. Migration 008 automatically renames all metadata files.

Upgrading to 0.13.3+: Entity and extension companion files no longer include ~UID in the filename. Migration 007 automatically renames legacy files.

Automatic migrations

When the CLI version is upgraded, one-time migration scripts in tools/cli/src/migrations/ run automatically on the first command invocation in a project directory. Completed migration IDs are recorded in ~/.dbo/settings.json under _completedMigrations (per-user, global) so each developer runs them independently and they never re-fire.

To skip migrations for a single command run:

dbo push bins/ --no-migrate
dbo clone --app myapp --no-migrate

Use dbo status to see how many pending migrations exist.

config.json reference

{
  "domain": "my-domain.com",
  "AppID": 10198,
  "AppUID": "abc123",
  "AppName": "My App",
  "AppShortName": "myapp",
  "cloneSource": "default",
  "ContentPlacement": "bin"
}

| Key | Values | Description | |-----|--------|-------------| | domain | hostname | DBO.io instance to connect to | | AppID | number | App ID (set by dbo clone, used by dbo adopt/dbo input) | | AppUID | string | App UID | | AppName | string | App display name | | AppShortName | string | App short name (used for dbo clone --app) | | AppModifyKey | string | ModifyKey for locked/production apps (set by dbo clone, used for submission guards) | | TransactionKeyPreset | RowUID | RowID | Row key type (auto-set to RowUID during init/clone) | | TicketSuggestionOutput | string | Output UID for ticket suggestions (auto-set during init, default ojaie9t3o0kfvliahnuuda) | | 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. | | ContentPlacement | bin | path | Where to place content files during clone (default: bin) | | UserMedia | true | false | Whether to download user media (/media/<app>/user/...) during clone. Set on first clone via prompt (or false in non-interactive mode). | | <Entity>FilenameCol | column name | Filename column for entity-dir records (e.g., ExtensionFilenameCol) | | dependencies | string[] | Array of app short-names to auto-clone as read-only local checkouts. Default: ["_system"] | | dependencyLastUpdated | object | Map of dependency short-name to last-cloned _LastUpdated ISO string |

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.

App Dependencies

The CLI automatically maintains local read-only checkouts of related apps under app_dependencies/<shortname>/. By default, the _system app (which contains all entity, column, and extension descriptors for the connected instance) is always included.

How it works

  • After dbo init or dbo clone, dependency apps are cloned into app_dependencies/.
  • If an app JSON contains a Dependencies column, those app short-names are merged into .app/config.json and also cloned.
  • You can add dependencies explicitly with dbo clone --dependencies operator,launchpad.
  • Dependencies are only re-cloned when the server's _LastUpdated is newer than the locally stored timestamp — so subsequent runs are fast.
  • Dependency clone output is suppressed — a single summary line shows synced/failed/up-to-date status.
  • app_dependencies/ is excluded from .gitignore and .dboignore automatically.

Schema merging from dependencies

After dependency cloning, extension descriptor definitions from dependency schemas (app_dependencies/<name>/.app/<name>.metadata_schema.json) are merged into the local .app/<shortName>.metadata_schema.json. This is useful when an app has no descriptor_definition extensions of its own but depends on an app (like operator) that does — the operator's descriptor definitions (widget, include, control, etc.) become available for local extension processing.

Flags

| Flag | Commands | Effect | |------|----------|--------| | --no-deps | dbo init, dbo clone | Skip dependency syncing | | --dependencies <list> | dbo clone | Add and sync specific dependencies (comma-separated short-names) | | --force | dbo clone | Re-clone all dependencies regardless of staleness | | --schema | dbo clone | Re-clone all dependencies regardless of staleness |

Root-level project files

.app/<shortName>.metadata.json

Clone of the original app JSON from the server with entity entries replaced by @path/to/*.metadata.json references. Created by dbo clone. Committed to git. (Formerly app.json in the project root.)

.app/<shortName>.metadata.json._domain

The _domain field in the app metadata file stores the project's reference domain (set during dbo clone). This is committed to git and used for domain-change detection when running dbo init --force or dbo clone --domain. It provides a stable cross-user baseline — all collaborators share the same reference domain.

Root content files (manifest.json, CLAUDE.md, README.md)

Certain files live at the project root (not inside lib/) but are still tracked and synced to the server as content entities. Their metadata companions live in lib/bins/app/ with a root-relative @/ reference (Content: "@/manifest.json").

| File | Server entity | Public | Description | |------|--------------|--------|-------------| | manifest.json | content | Yes | PWA web app manifest | | CLAUDE.md | content | No | Claude Code project instructions | | README.md | content | Yes | Project readme |

dbo clone writes all three to the project root. If the server has no record for a file, a stub is generated automatically (manifest.json from app metadata, CLAUDE.md and README.md from app name/description).

dbo push auto-creates the companion metadata in lib/bins/app/ for any listed root file that exists locally but has no tracked metadata yet — no manual dbo adopt needed before the first push.

dbo adopt <filename> called from the project root also works for any root content file: it bypasses the .dboignore check and entity inference, and writes the metadata directly to lib/bins/app/.

manifest.json generated fields (when produced as a stub):

| Field | Source | |-------|--------| | name | AppName | | short_name | AppShortName | | description | App.Description | | start_url / scope | /app/<ShortName>/ui/ | | background_color | Extracted from the widget extension matching ShortName (field String4), defaults to #ffffff | | theme_color | #000000 |

rootContentFiles config

The list of root content files is stored in .app/config.json under rootContentFiles:

{
  "rootContentFiles": ["CLAUDE.md", "README.md", "manifest.json"]
}
  • Absent: defaults are written on the first dbo push["CLAUDE.md", "README.md", "manifest.json"]
  • [], false, or null: feature disabled — no root content files are auto-managed
  • Custom list: any filename can be added; metadata is derived from the file extension

.dboignore

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.

Used by:

  • dbo init — scaffold empty-check (determines if directory is "effectively empty")
  • dbo adopt ./ — directory scanning (which files/dirs to skip); also checked in single-file mode (dbo adopt file.html)
  • dbo push — metadata file discovery: skips matching .metadata.json / _output~*.json files AND any record whose companion content file (@reference) matches an ignore pattern

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.

Pattern examples:

# Ignore all SQL companion files (output records with CustomSQL)
**/*.CustomSQL.sql

# Ignore a specific record (by metadata file path)
bins/app/my-draft-page.metadata.json

# Ignore an entire directory
bins/staging/

# Ignore all content in bins/ (still push entity-dir records like extension/)
bins/

Syntax: Same as .gitignore — glob patterns, # comments, blank lines, negation with !, directory-only patterns with trailing /.

Default patterns:

.app/              # DBO internal
app_dependencies/  # Dependency checkouts
*.dboio.json       # Export files
.git/              # Version control
.gitignore
node_modules/      # Node
package.json
package-lock.json
.claude/           # AI / tooling
.mcp.json
.DS_Store          # Editor / IDE / OS
Thumbs.db
Icon\r
.idea/
.vscode/
*.codekit3
README.md          # Repo scaffolding
SETUP.md

Edit .dboignore to add or remove patterns. Committed to git and shared across users.

Legacy migration

If your project uses the older .domain, .username, .password, .cookies files, dbo init will detect them and offer to migrate automatically.

Environment variables

Environment variables override file-based configuration:

  • DBO_DOMAIN — target domain
  • DBO_USERNAME — username
  • DBO_PASSWORD — password

Commands

dbo init

Initialize DBO CLI configuration for the current directory.

dbo init                                              # interactive prompts
dbo init --domain my-domain.com                       # non-interactive
dbo init --domain my-domain.com --username [email protected]   # with credentials
dbo init --force                                      # overwrite existing config
dbo init --domain my-domain.com --app myapp --clone   # init + clone an app
dbo init --domain my-domain.com -y                    # skip all prompts
dbo init --scaffold                                   # scaffold dirs (prompts for domain)
dbo init --scaffold --yes                             # scaffold dirs non-interactively

| Flag | Description | |------|-------------| | --domain <host> | DBO instance domain | | --username <user> | DBO username (stored for login default) | | --force | Overwrite existing configuration. Triggers a domain-change confirmation prompt when the new domain differs from the project reference domain | | --app <shortName> | App short name (triggers clone after init). Prompts for password and authenticates automatically before fetching app data from the server | | --clone | Clone the app after initialization | | -g, --global | Install Claude commands globally (~/.claude/commands/) | | --local | Install Claude commands to project (.claude/commands/) | | --scaffold | Pre-create standard project directories (app_version, automation, bins, data_source, docs, extension, group, integration, site, src, tests, trash) | | --dboignore | Create .dboignore with default patterns (use with --force to overwrite existing) | | -y, --yes | Skip all interactive prompts (legacy migration, Claude Code setup) | | --non-interactive | Alias for --yes | | --no-deps | Skip dependency cloning after init |


dbo clone

Clone an app from DBO.io to a local project structure. Creates directories, files, metadata, and populates config.json and package.json.

# Clone using config (AppShortName from .app/config.json)
dbo clone

# Clone from a local JSON export file
dbo clone /path/to/app_export.json

# Clone from server by app short name
dbo clone --app myapp

# Combined with init
dbo init --domain my-domain.com --app myapp --clone

# Extension descriptor sub-directory handling
dbo clone -e extension                            # Clone all extensions (sorted by descriptor type)
dbo clone -e extension --documentation-only       # Clone only documentation extensions
dbo clone -e extension --documentation-only --force  # Reset documentation preferences and re-clone
dbo clone -e extension --descriptor-types false   # Clone extensions flat (no descriptor sorting)

| Flag | Description | |------|-------------| | <source> | Local file path or URL to load app JSON from (optional positional argument) | | --app <name> | App short name to fetch from server | | -e, --entity <type> | Only clone a specific entity type (e.g. output, content, media, extension) | | --documentation-only | When used with -e extension, clone only documentation extensions | | --descriptor-types <bool> | Sort extensions into descriptor sub-directories (default: true). Set to false to use flat extension/ layout | | --domain <host> | Override domain. Triggers a domain-change confirmation prompt when it differs from the project reference domain | | --schema | Re-fetch schema from server before cloning | | --force | Skip source mismatch confirmation and change detection; re-processes all files | | -y, --yes | Auto-accept all prompts (also skips source mismatch confirmation) | | -v, --verbose | Show HTTP request details | | --no-deps | Skip dependency cloning after clone | | --dependencies <list> | Comma-separated app short-names to add and sync as dependencies (e.g. --dependencies operator,launchpad) | | --configure | Re-prompt for filename columns, companion file extraction, and documentation placement preferences | | --media-placement <type> | Set media placement: fullpath or binpath (default: bin) |

Domain change detection

When cloning with a different domain than the project's reference domain (.app/<shortName>.metadata.json._domain or config.json.domain), the CLI warns before proceeding. When TransactionKeyPreset=RowID, this escalates to a critical error because numeric IDs are not unique across domains — pushing to the wrong domain can corrupt records. In non-interactive mode (-y), RowUID domain changes proceed with a warning, but RowID domain changes throw a hard error.

The project's reference domain is stored in .app/<shortName>.metadata.json._domain (committed to git) during clone, giving the CLI a stable cross-user baseline.

What clone does

  1. Fetches schema — downloads schema from the server if missing or explicitly requested (--schema). Regenerates .app/<shortName>.metadata_schema.json from the schema
  2. Syncs dependencies — clones dependency apps into app_dependencies/<shortname>/ (unless --no-deps). Merges extension descriptor definitions from dependency schemas into the local .app/<shortName>.metadata_schema.json (e.g., operator provides descriptor definitions for apps that lack their own)
  3. Loads app JSON — from a local file, server API, or interactive prompt. A spinner shows progress while fetching from the server (responses can be slow as the JSON is assembled on demand)
  4. Updates .app/config.json — saves AppID, AppUID, AppName, AppShortName, AppModifyKey (if the app is locked), and cloneSource (the source used for this clone)
  5. Updates package.json — populates name, productName, description, homepage, and deploy script
  6. Creates directories — processes children.bin to build the directory hierarchy based on ParentBinID relationships
  7. Saves .app/directories.json — maps BinIDs to directory paths for file placement
  8. Writes content files — decodes base64 content, creates *.metadata.json + content files in the correct bin directory. Filename columns and companion file extraction preferences are auto-applied with sensible defaults on first clone (use --configure to re-prompt)
  9. Downloads media files — classifies records into three scopes before downloading: app (/media/<app>/app/... or no FullPath — always downloaded), user (/media/<app>/user/... — opt-in, preference saved as UserMedia in config.json), and foreign (/media/<other_app>/... — silently skipped with stale metadata written). Fetches using a fallback chain: FullPath directly (/media/{app}/{path}) → /dir/ route → /api/media/{uid}. 404 errors create stale metadata to prevent re-prompting. Errors are logged to .app/errors.log
  10. Processes entity-dir records — entities matching project directories (extension, app_version, data_source, site, group, integration, automation) are saved as .metadata.json files in their corresponding directory (e.g., extension/, data_source/)
  11. Processes other entities — remaining entities with a BinID are placed in the corresponding bin directory
  12. Saves .app/<shortName>.metadata.json — clone of the original JSON with processed entries replaced by @path/to/*.metadata.json references
  13. Orphan cleanup — any local .metadata.json files whose UID is absent from the server response are automatically moved to trash/ along with their companion content and media files. This prevents stale records (deleted server-side) from causing false positives in dbo push. Skipped during --entity-filter clones

Clone source tracking

After every successful clone, the source is persisted as cloneSource in .app/config.json:

  • "default" — app JSON was fetched from the server using AppShortName (the normal flow)
  • A file path or URL — set when an explicit <source> argument was provided (e.g. dbo clone /path/to/export.json)

On subsequent clones, if you provide an explicit source that differs from the stored cloneSource, the CLI warns and asks for confirmation before proceeding:

  ⚠  This project was previously cloned from: default
     Requested source:                        /path/to/export.json
? Clone from the new source anyway? This will update the stored clone source. (y/N)

Use --force or -y to skip the prompt and override without being asked.

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:

  ⚠  Source did not return expected results: No app found with ShortName "myapp"
? Enter another local file path or URL to retry (or leave empty to abort):

Change detection on re-clone

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.

Change detection only checks companion content and media files for user edits — metadata file mtimes are not considered, since they can be bumped by CLI-internal operations (migrations, legacy companion renames).

Collision detection

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:

⚠ Collision: 2 records want to create "bins/app/colors.css"
? Which record should create this file?
❯ [content] colors (UID: abc123)
  [media] colors.css (UID: def456)

The rejected record is automatically staged for deletion in .app/synchronize.json. Run dbo push to delete it from the server.

In non-interactive mode (-y), the first record is kept and others are auto-staged for deletion.

Stale media cleanup

During media downloads, files returning 404 (no longer exist on the server) are collected as "stale records". Metadata is still written for 404 files (marked with _stale404: true) so they are not re-prompted on subsequent clones.

After all downloads complete, you'll be prompted to stage stale records for deletion:

Found 3 stale media record(s) (404 - files no longer exist on server)
? Stage these 3 stale media records for deletion? (y/N)

This helps keep your app clean by removing database records for media files that have been deleted from the server.

In non-interactive mode (-y), stale cleanup is skipped (conservative default).

Media scope filtering

During dbo clone, media records are classified by their FullPath relative to the app short name:

| Scope | Path pattern | Behavior | |-------|-------------|----------| | app | /media/<app>/app/... or no FullPath | Always downloaded | | user | /media/<app>/user/... | Downloaded only if UserMedia=true in .app/config.json | | foreign | /media/<other_app>/... | Never downloaded — stale metadata written to prevent re-prompts |

On the first clone with user media present, you'll be prompted once:

App has 14 user media file(s) (e.g. "avatar.jpg"). Download user media? (saves preference)

The answer is saved as UserMedia in .app/config.json and reused on subsequent clones. In non-interactive mode (-y), user media defaults to skipped (UserMedia=false).

Path resolution

When a content record has both Path and BinID, the CLI prompts:

Where do you want me to place filename.ext?
  1. Into the Path of /path/from/path/column
  2. Into the BinID of 12345 (mapped BinName → bin/directory)

Entity directory processing

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:

| Entity Key | Directory | |------------|-----------| | extension | extension/<Descriptor>/ (see below) | | app_version | app_version/ | | data_source | data_source/ | | site | site/ | | group | group/ | | integration | integration/ | | automation | automation/ |

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).

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 _companionReferenceColumns array (legacy name: _contentColumns, supported for backward compatibility).

Companion file naming convention: Only .metadata.json files carry the ~UID suffix (e.g. Add-Asst-Execute-Security.metadata~wxl6ivcwfkix3zgantszjg.json). Companion content files use the natural base name without ~UID (e.g. Add-Asst-Execute-Security.String5.html). When a {title} is defined in the @reference expression (see Metadata Schema), the title replaces the column name in the filename (e.g. Add-Asst-Execute-Security.Add-Form-Parameters.js instead of Add-Asst-Execute-Security.String5.js). If two records share the same name within a directory, the second gets a -1 suffix. Migration 007 automatically renames legacy ~UID companion files to the natural convention.

Use -y to skip prompts (uses Name column, no content extraction).

Extension descriptor sub-directories

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).

During clone, the CLI:

  1. Pre-scans all extension records for descriptor_definition entries and builds a String1 → Name mapping
  2. Creates sub-directories under extension/ for each mapped descriptor (e.g., extension/Documentation/, extension/Includes/)
  3. Places unmapped extensions directly in extension/ — extensions with an unmapped or null Descriptor are placed in the root extension/ directory (the legacy _unsupported/ sub-directory is migrated automatically by Migration 011)
  4. Prompts per descriptor — filename column and content extraction prompts fire once per unique Descriptor value (not once for all extensions)
  5. Persists the mapping in .app/directories.json under descriptorMapping

Config keys (saved per descriptor in config.json):

| Key | Example | Purpose | |-----|---------|---------| | Extension_<descriptor>_FilenameCol | Extension_documentation_FilenameCol | Filename column for that descriptor type | | Extension_<descriptor>_ContentExtractions | Extension_documentation_ContentExtractions | Content extraction preferences per column | | ExtensionDocumentationMDPlacement | "inline" or "root" | Where to place documentation MD files |

Documentation alternate placement: When extracting MD content from documentation descriptor extensions, the CLI offers a choice:

  • Root placement (/docs/<filename>.md) — recommended for easy access; creates @/docs/<filename>.md references in metadata
  • Inline placement (extension/Documentation/<filename>.md) — keeps files alongside metadata

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.

Entity filter support:

dbo clone -e extension --documentation-only         # Clone only documentation extensions
dbo clone -e extension --documentation-only --force  # Reset documentation preferences and re-clone
dbo clone -e extension                               # Clone all extensions (all descriptor types)
dbo clone -e extension --descriptor-types false       # Flat layout (no descriptor sorting)

dbo adopt auto-inference: Running dbo adopt docs/my-doc.md when ExtensionDocumentationMDPlacement is "root" auto-creates a companion .metadata.json in lib/extension/documentation/ with the correct @/ reference.

Entity children embedding

When a server entity record contains nested child records (e.g., entity_column records nested under entity parents), dbo clone embeds them inline in the parent's .metadata~uid.json file under a children key:

{
  "_entity": "entity",
  "UID": "abc123",
  "Name": "contact",
  "children": {
    "entity_column": [
      { "UID": "col1", "Name": "FirstName", "PhysicalOrderNumber": 1, "_LastUpdated": "2026-01-01T00:00:00" },
      { "UID": "col2", "Name": "LastName", "PhysicalOrderNumber": 2, "_LastUpdated": "2026-01-02T00:00:00" }
    ]
  }
}

Children are stored with all fields intact (including _LastUpdated, _CreatedOn, UID). Base64-encoded field values within child records are decoded to plain strings. This applies generically to all entity types that contain a children property in the server response.

Push behaviour: dbo push detects changes within the children arrays by comparing against the baseline. Modified child records are submitted independently as input expressions (children before parent). Removing a child from the metadata file stages a delete in synchronize.json. The children key itself is never included in the parent's input expression.

Output hierarchy children: Output child records (output_value, output_value_filter, output_value_entity_column_rel) are also embedded inline under children. Only the root output's CustomSQL is extracted as a companion .sql file — child CustomSQL values are stored inline as decoded strings.

Output structure

project/
  .app/
    config.json              # Updated with app metadata
    directories.json         # Bin directory mapping
    <shortName>.metadata.json # Clone of original with @references
  .gitignore                 # credentials.json + cookies.txt added
  package.json               # Updated with app info + deploy script
  bins/                      # ← root for all bin-placed files
    app/                     # ← directory from children.bin
      thomas-scratch.md
      thomas-scratch.metadata.json
      CurrentTicketID.cs
      CurrentTicketID.metadata.json
    ticket_test/             # ← another bin directory
      ...
  extension/                 # ← extension records organized by descriptor
    Documentation/           # ← descriptor sub-directory (from descriptor_definition)
      MyDoc.uid1.metadata.json
      MyDoc.uid1.String10.md     # ← extracted content column
    Includes/
      Header.uid2.metadata.json
  docs/                      # ← root-placed documentation MD files (optional)
    MyDoc.md
  data_source/
    MySQL-Primary.metadata.json
  site/
    MainSite.metadata.json
  # Media files placed by BinID into bins/ (alongside content)

Understanding the lib/bins/ directory structure

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.

Directory Organization:

  • lib/bins/ — Root directory for all bin-placed files (local organizational directory only)
    • lib/bins/app/ — Special subdirectory for the main app bin (typically the default bin)
    • lib/bins/custom_name/ — Custom bin directories (e.g., tpl/, ticket_test/, etc.)

Important: The lib/bins/app/ special case

The app/ subdirectory under lib/bins/ is treated specially:

  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.

  2. Path normalization — When comparing paths (during dbo push), the CLI automatically strips both lib/bins/ and app/ from paths:

    Local file:    lib/bins/app/assets/css/operator.css
    Server Path:   assets/css/operator.css
    → These are considered the same path ✓
  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:

    Local file:    lib/bins/tpl/header.html
    Server Path:   tpl/header.html
    → The 'tpl/' directory is preserved ✓

Why this matters:

  • When you dbo push files from lib/bins/app/, the CLI knows these paths should match the root-level paths in your metadata
  • If your metadata Path column contains assets/css/colors.css, it will correctly match files in lib/bins/app/assets/css/colors.css
  • Custom bin directories like lib/bins/tpl/ serve from the tpl/ directive and maintain their path structure

Leading slash handling:

The CLI handles leading / in metadata paths flexibly:

  • Path: assets/css/file.css matches lib/bins/app/assets/css/file.css
  • Path: /assets/css/file.css also matches lib/bins/app/assets/css/file.css
  • Path: /assets/css/file.css matches lib/bins/assets/css/file.css

This ensures compatibility with various path formats from the server while maintaining correct local file organization.

Media file serving (API)

The DBO.io server provides three routes for serving media files:

| Route | Example | Description | |-------|---------|-------------| | /media/{app}/{path} | /media/todoes/App/assets/fonts/file.ttf | Legacy FullPath — the value stored in the media record's FullPath column | | /dir/{app}/{bins}/{file} | /dir/todoes/App/assets/fonts/file.ttf | Modern BinID-based route — parses appShortName/binHierarchy/filename | | /api/media/{uid} | /api/media/ujrOQPCdUEamNJdAjUQdYA | UID-based endpoint — looks up media by unique identifier |

During dbo clone, the CLI downloads media using a fallback chain:

  1. FullPath (/media/...) — uses the record's FullPath column directly
  2. /dir/ route — strips the /media/ prefix from FullPath and uses the /dir/ route
  3. /api/media/{uid} — UID-based endpoint as last resort (when no FullPath exists)

If all attempts fail, the error is logged to .app/errors.log (JSONL format) with the record's UID, filename, FullPath, and error details.

Output hierarchy format

Each root output record produces a single compound JSON file containing all child entities (columns, joins, filters) embedded inline:

bins/app/
  _output~Sales~abc123.json          ← root output with inline children
  _output~Sales~abc123.column~col1.CustomSQL.sql  ← companion SQL file

The root JSON structure:

{
  "_entity": "output",
  "UID": "abc123",
  "Name": "Sales",
  "children": {
    "column": [
      { "_entity": "output_value", "UID": "col1", "Title": "Amount", "children": { "column": [], "join": [], "filter": [] } }
    ],
    "join": [],
    "filter": [
      { "_entity": "output_value_filter", "UID": "f1", "ShortName": "Active", "children": { "column": [], "join": [], "filter": [] } }
    ]
  }
}

Key points:

  • All three child keys (column, join, filter) are always present (empty arrays when unused)
  • Each child retains _entity set to its physical table name for push routing
  • Children nest recursively following FK relationships (e.g. a column can have filters)
  • CustomSQL content is extracted to companion .sql files per extraction rules
  • Re-cloning moves orphaned old-format child .json files to /trash

Metadata Schema

During dbo clone, the CLI auto-generates .app/<shortName>.metadata_schema.json — a file that records which columns each entity/descriptor uses. This file is seeded from the first cloned record of each type and can be manually edited afterwards.

File format:

{
  "site": ["AppID", "Name", "ShortName", "Active"],
  "extension": {
    "documentation": ["AppID", "Name", "Descriptor=documentation", "String10=@reference"],
    "control": ["AppID", "Name", "ShortName", "Active"]
  }
}

Column syntax:

| Syntax | Meaning | |--------|---------| | Name | Plain column — populated from filename or left empty | | Descriptor=documentation | Literal value — always set to documentation | | String10=@reference | Content reference — links to the file being added | | String5=@reference:@Name[js] | Content reference with filename source and extension |

dbo adopt uses these templates to auto-detect the entity type from a file's directory placement and generate metadata without prompting. For example, dbo adopt lib/extension/include/nav.html resolves to entity extension / descriptor include and applies the matching template.

@reference expression syntax

The =@reference expression controls how companion files are named during dbo clone and dbo adopt. The full grammar:

Column=@reference[:filenameSource][extPart][{title}]

Components:

| Part | Syntax | Description | |------|--------|-------------| | Filename source | :@ColumnName | Use another column's value as the base filename (e.g., :@Name) | | Filename fallback | :@Name\|\|fallback | Use fallback if the column value is empty | | Extension | [ext] | Literal extension (e.g., [js], [css], [html]) | | Extension from column | [@ColumnName] | Read extension from another column (e.g., [@Extension]) | | Extension fallback | [@Extension\|\|html] | Use html if the column value is empty | | Title | {Title Text} | Human-readable name for the companion file segment (replaces column name) |

Examples:

Given a record with Name="My-Widget", Extension="html", Ext="" (empty):

| Expression | Companion filename | Description | |---|---|---| | Content=@reference | My-Widget.Content.txt | Basic — column name as segment, default ext | | Content=@reference:@Name[@Extension] | My-Widget.html | Name and extension both from record columns | | Content=@reference:@Name\|\|untitled[@Extension] | My-Widget.html | Uses Name; would use untitled if Name were empty | | String5=@reference:@Name[js] | My-Widget.String5.js | Literal .js extension | | String5=@reference:@Name[js]{Add Form Parameters} | My-Widget.Add-Form-Parameters.js | Title replaces String5 in filename | | CustomSQL=@reference[sql] | My-Widget.CustomSQL.sql | No filename source, literal extension | | Text=@reference:@Name[@Ext\|\|js] | My-Widget.Text.js | Ext column is empty, falls back to .js | | Text=@reference:@Name[@Extension\|\|js] | My-Widget.Text.html | Extension column has value, fallback not used |

Auto-generation from descriptor_definition: During dbo clone, the CLI parses form-control-code from descriptor_definition extension records to auto-populate @reference entries per descriptor. If form-control-title is also present, the column's title is included as the {title} suffix — producing human-readable companion filenames instead of raw column names like String5.


dbo login

Authenticate with a DBO.io instance and store the session cookie.

After successful authentication, the CLI automatically fetches and stores the current user's ID, UID, name, and email in .app/credentials.json. The ID and UID are used for automatic retry when server submissions require user identity (see Automatic error recovery). The name and email are used to populate package.json author fields during dbo clone.

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.

dbo login                                         # uses stored credentials
dbo login -u [email protected] -p myPassword       # explicit credentials
dbo login -e [email protected]                     # authenticate by email
dbo login --phone +15551234567 -p myPassword      # authenticate by phone
dbo login --passkey abc123def                     # authenticate with passkey

| Flag | Description | |------|-------------| | -u, --username <value> | Username identity | | -e, --email <value> | Email identity | | --phone <value> | Phone number identity | | -p, --password <value> | Password credential | | --passkey <value> | Passkey credential (rotating API key) | | --domain <host> | Override domain for this request |


dbo logout

Log out and clear the local session cookie.

dbo logout

dbo status

Show current configuration, domain, and session status.

dbo status

Output:

  Initialized: Yes (.app/)
  Domain: my-domain.com
  Username: [email protected]
  User ID: 10296
  Directory: /Users/me/projects/operator
  Session: Active (expires: 2026-03-15T10:30:00.000Z)
  Cookies: /Users/me/projects/operator/.app/cookies.txt

  Claude Code Plugins:
  dbo: ✓ global (~/.claude/commands/dbo.md)

User ID is populated by dbo login. If it shows "(not set)", run dbo login to fetch it.

Plugin scopes (project or global) are displayed when plugins have been installed. Scopes are stored in ~/.dbo/settings.json.


dbo input

Submit raw CRUD operations (add, edit, delete records) to DBO.io. This is a low-level command that sends input expressions directly to the server without any AppID injection or metadata awareness — use dbo push for metadata-driven deployments.

# Add a record
dbo input -d 'RowID:add1;column:user.FirstName=John' -d 'RowID:add1;column:user.LastName=Doe'

# Edit a record by UID
dbo input -d 'RowUID:albain3dwkofbhnd1qtd1q;column:content.Content@assets/css/colors.css'

# Delete a record
dbo input -d 'RowID:del10062;entity:user=true'

# Multiple operations in one call
dbo input -d 'RowID:add1;column:user.LastName=Doe&RowUID:abc;column:[email protected]'

# With file upload (multipart)
dbo input -d 'RowID:add1;column:media.BinID=12345' -f file=@path/to/image.jpg

# Validation only (no commit)
dbo input -d 'RowID:add1;column:user.FirstName=John' --confirm false

# With ticket ID override
dbo input -d 'RowID:add1;column:content.Name=test' --ticket abc123

# See the HTTP request being made
dbo input -d 'RowUID:abc;column:[email protected]' -v

| Flag | Description | |------|-------------| | -d, --data <expr> | DBO input expression (repeatable) | | -f, --file <field=@path> | File attachment for multipart upload (repeatable) | | -C, --confirm <true\|false> | Commit changes (default: true). Use false for validation only | | --ticket <id> | Override ticket ID (_OverrideTicketID) | | --modify-key <key> | Provide ModifyKey directly (skips interactive prompt) | | --row-key <type> | Row key type (RowUID or RowID) — no-op for -d passthrough, available for consistency | | --login | Auto-login user created by this submission | | --transactional | Use transactional processing | | --json | Output raw JSON response | | -v, --verbose | Show HTTP request details | | --domain <host> | Override domain |

Input expression syntax

RowID:identifier;column:entity.ColumnName=value        # direct value
RowUID:identifier;column:entity.ColumnName@filepath    # value from file
RowID:delIdentifier;entity:entityName=true             # delete

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.


dbo output

Query data from DBO.io outputs or entities.

# Custom output by UID
dbo output qfkyyp2vxeaggdeo7dwbig

# Entity query
dbo output -e user --template json_indented

# Single record
dbo output -e user --row 10296

# With filtering and sorting
dbo output -e user --filter 'FirstName=John' --sort 'LastName:asc' --template json_indented

# Contains filter
dbo output -e content --filter 'Name:contains=color' --template json_indented

# Pagination
dbo output -e user --page 2 --rows-per-page 25

# Save results to local files (interactive)
dbo output -e content --filter 'AppID=10100' --save

# Save results to local files (non-interactive / scripting)
dbo output -e content --save-filename Name --save-path Path --save-content Content --save-extension Extension

# Entity metadata
dbo output -e user --meta

# Debug SQL
dbo output myOutputUID --debug-sql

| Flag | Description | |------|-------------| | <uid> | Output UID (positional argument) | | -e, --entity <uid> | Query by entity UID | | --row <id> | Specific row ID | | --filter <expr> | Filter expression (repeatable) | | --template <value> | Output template: json_raw (default), json_indented, json, html, csv, xml, txt, pdf, or a content UID for custom templates | | --sort <expr> | Sort expression (repeatable), e.g., LastName:asc | | --search <expr> | Full-text search | | --page <n> | Page number | | --rows-per-page <n> | Rows per page | | --maxrows <n> | Maximum rows | | --rows <range> | Row range, e.g., 1-10 | | --limit <n> | Maximum rows to return (preferred over --maxrows) | | --rowcount <bool> | Include row count: true (default) or false for performance | | --display <expr> | Show/hide template tags (repeatable), e.g., sidebar=hide | | --format-values | Enable value formatting with --template json_raw | | --empty-response-code <code> | HTTP status code when output returns no results | | --fallback-content <expr> | Fallback content UID for error codes, e.g., 404=contentUID | | --escape-html <bool> | Control HTML escaping: true or false | | --mime <type> | Override MIME/content type | | --strict | Strict error mode | | --confirm | Confirmation flag | | --include <expr> | Include token | | --no-transaction | Disable transaction wrapping | | --skip <phase> | Skip execution phases (repeatable, admin-only) | | --profile | Enable MiniProfiler output | | --debug | Include debug info | | --debug-sql | Include SQL debug info | | --debug-verbose | Verbose debug output | | --debug-analysis | Analysis debug output | | --meta | Use meta output endpoint | | --meta-column <uid> | Column metadata | | --save | Interactive save-to-disk mode | | --save-filename <col> | Column for filenames (non-interactive) | | --save-path <col> | Column for file path (non-interactive) | | --save-content <col> | Column for file content (non-interactive) | | --save-extension <col> | Column or literal extension (non-interactive) | | --json | Output raw JSON | | -v, --verbose | Show HTTP request details |

Save to Disk (--save)

The save-to-disk feature fetches data and persists records as local files. It uses an interactive flow with arrow-key selection prompts:

  1. Filename column — which column value becomes the filename (default: Name or UID)
  2. Path column — which column contains the directory path (builds local directories)
  3. Content column(s) — which column(s) to save as file content (skip for metadata only)
  4. Extension — use an entity column or specify manually

Each record produces:

  • A content file: [filename]~[uid].[extension] (e.g., colors~abc123.css)
  • A metadata file: [filename]~[uid].metadata.json (all column values)

Tilde UID Convention

Every local file whose server record has a known UID embeds that UID in the filename, separated by a tilde (~):

  • Content: <basename>~<uid>.<ext> / <basename>~<uid>.metadata.json
  • Media: <basename>~<uid>.<ext> / <basename>~<uid>.<ext>.metadata.json
  • Entity-dir: <name>~<uid>.metadata.json

Exception: if the chosen filename column value is the UID itself, the tilde suffix is omitted: <uid>.<ext>.

When pushing, the ~<uid> portion is automatically stripped from filenames sent to the server (e.g., logo~def456.png is uploaded as logo.png).

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.


dbo content

Get, deploy, or pull content from DBO.io.

# Get content by UID
dbo content ykqucv0eb0ggjqgcncj6dq

# Save content to a local file
dbo content ykqucv0eb0ggjqgcncj6dq -o local/file.html

# Get as plain text (disable minification)
dbo content ykqucv0eb0ggjqgcncj6dq --template txt --no-minify

| Flag | Description | |------|-------------| | <uid> | Content UID | | -o, --output <path> | Save to local file | | --template <value> | Output template (e.g., json_raw, html, txt, or a content UID) | | --no-minify | Disable minification | | --json | Output raw JSON |

dbo content deploy

Deploy a local file's contents to a DBO content record.

dbo content deploy albain3dwkofbhnd1qtd1q assets/css/colors.css
dbo content deploy rncjivlghu65bmkbjnxynq assets/js/app.js
dbo content deploy abc123 docs/readme.md --ticket myTicket
dbo content deploy abc123 test.html --confirm false    # validate only
dbo content deploy abc123 image.png --multipart        # binary file upload

This is a shorthand for:

dbo input -d 'RowUID:albain3dwkofbhnd1qtd1q;column:content.Content@assets/css/colors.css'

| Flag | Description | |------|-------------| | <uid> | Content UID (RowUID) | | <filepath> | Local file path | | -C, --confirm <true\|false> | Commit (default: true) | | --ticket <id> | Override ticket ID | | --modify-key <key> | Provide ModifyKey directly (skips interactive prompt) | | --multipart | Use multipart/form-data upload (for binary files) | | --row-key <type> | Override row key type for this invocation (RowUID or RowID) |

dbo content pull

Pull content records from DBO to local files. Uses the content entity's well-known columns (Name, Path, Content, Extension) automatically — no interactive prompts.

# Pull a single content record
dbo content pull ykqucv0eb0ggjqgcncj6dq

# Pull all content for an app
dbo content pull --filter 'AppID=10100'

# Pull with row limit
dbo content pull --filter 'AppID=10100' --maxrows 50

Creates local files matching the content entity's Path and Extension columns:

css/
  colors.css                    # content.Content value
  colors.metadata.json          # all column values as JSON
js/
  app.js
  app.metadata.json

Smart change detection

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:

  1. Overwrite — replace local with server version
  2. Compare — show a line-by-line diff and selectively merge
  3. Skip — keep local unchanged
  4. Overwrite all / Skip all — bulk action for remaining files

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.


dbo media

Get media files from DBO.io.

# Get media by UID
dbo media albain3dwkofbhnd1qtd1q

# Save to local file
dbo media albain3dwkofbhnd1qtd1q -o logo.png

# Get by numeric ID
dbo media --id 12345 -o file.jpg

# Get by path
dbo media --path assets/images/logo.png -o logo.png

# Force download
dbo media albain3dwkofbhnd1qtd1q --download -o file.pdf

| Flag | Description | |------|-------------| | <uid> | Media UID | | --id <id> | Media by numeric ID | | --path <path> | Media by directory path | | -o, --output <path> | Save to local file | | --download | Force download (attachment disposition) |


dbo upload

Upload a binary file to DBO.io.

dbo upload image.jpg --bin 12345 --app 67890 --ownership app --path assets/images
dbo upload logo.svg --bin 12345 --app 67890 --ownership app --path assets/gfx --name brand-logo
dbo upload doc.pdf --bin 12345 --app 67890 --ownership user --path docs --confirm false

| Flag | Description | |------|-------------| | <filepath> | Local file to upload | | --bin <id> | BinID (required) | | --app <id> | AppID (required) | | --ownership <type> | Ownership: app, user, or system (required) | | --path <dir> | Media path (required) | | --name <value> | Override filename | | -C, --confirm <true\|false> | Commit (default: true) |


dbo message

Send messages via DBO.io (email, SMS/MMS, chatbot).

# Send an email
dbo message emailTemplateUID

# Send a chatbot message with thread
dbo message chatbotTemplateUID --thread conversation123

# Validate without sending
dbo message emailTemplateUID --confirm false

| Flag | Description | |------|-------------| | <uid> | Content UID for the message template | | -C, --confirm <true\|false> | Commit (default: true) | | --thread <id> | Thread ID for chatbot conversations | | --json | Output raw JSON |


dbo cache

Manage the DBO.io cache.

# List all cached items
dbo cache list

# List with metadata
dbo cache list --metadata

# Refresh a specific cache key
dbo cache refresh --key 'content:myContentUID'

dbo cache list

| Flag | Description | |------|-------------| | --metadata | Include cache provider metadata | | --json | Output raw JSON |

dbo cache refresh

| Flag | Description | |------|-------------| | --key <value> | Cache key to refresh (required) | | --part <value> | Cache partition |


dbo instance

Manage DBO.io instances.

# Export the current instance
dbo instance export

# Build an instance
dbo instance build instanceUID

# Validate without executing
dbo instance export --confirm false

dbo instance export

| Flag | Description | |------|-------------| | -C, --confirm <true\|false> | Commit (default: true) |

dbo instance build <uid>

| Flag | Description | |------|-------------| | <uid> | Instance UID | | -C, --confirm <true\|false> | Commit (default: true) |


dbo diff

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.

# Compare all records in the current directory
dbo diff

# Compare a specific file
dbo diff assets/css/colors.css

# Compare all records in a directory
dbo diff assets/

# Display diffs without prompting
dbo diff --no-interactive

# Accept all server changes without prompting
dbo diff -y

| Flag | Description | |------|-------------| | [path] | File, directory, or . (default: current directory) | | --no-interactive | Show diffs without prompting to accept | | -y, --yes | Accept all server changes automatically | | -v, --verbose | Show HTTP request details | | --domain <host> | Override domain |

Interactive mode

For each file with differences, you can:

  1. Accept all changes — overwrite local with server version
  2. Cherry-pick fields — accept/skip individual field changes
  3. Skip — keep local files unchanged
  4. Accept all remaining — auto-accept for all remaining files
  5. Skip all remaining — skip all remaining files

Diff output

Shows a unified diff format with color coding:

  • Red lines (-) — content only in your local file
  • Green lines (+) — content only on the server
  • Cyan headers — hunk markers showing line positions

After accepting changes, file modification times are synced to the server's _LastUpdated timestamp to establish a new sync point.


dbo push

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.

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.

Round-trip workflow

# 1. Pull content to local files
dbo content pull --filter 'AppID=10100' --maxrows 10

# 2. Edit files locally
vim css/colors.css

# 3. Push changes back to DBO
dbo push css/colors.css

Single file

# Push a single file (uses companion .metadata.json)
dbo push assets/js/main.js

# Validate without submitting
dbo push assets/js/main.js --confirm false

# Push only the file content, not metadata columns
dbo push assets/js/main.js --content-only

# Push only metadata changes, skip file content
dbo push assets/js/main.js --meta-only

The push command finds assets/js/main.metadata.json, reads the UID and entity, and builds input expressions for all columns.

Directory (recursive)

# Push all changed records in the current directory
dbo push

# Push all records in a specific directory
dbo push assets/

# Push with auto-accept for all prompts
dbo push assets/ -y

Recursively finds all *.metadata.json files, verifies @filename references exist, and pushes each record.

Path mismatch detection

If you move a file to a different directory after pulling, the push detects the mismatch:

  ⚠ Path mismatch for "main":
    Metadata Path: css/main.css
    Current path:  assets/css/main.css
  Update Path column to "assets/css/main.css"? (Y/n)

The --yes flag auto-accepts path updates.

Metadata format

After a pull, metadata files contain @filename references for content columns:

{
  "_entity": "content",
  "_companionReferenceColumns": ["Content"],
  "UID": "abc123",
  "Name": "colors",
  "Content": "@colors.css",
  "Extension": "CSS",
  "Path": "css/colors.css",
  "Type": "Code"
}

The @colors.css reference tells push to read the content from that file. All other values are pushed as literal column values.

| Flag | Description | |------|-------------| | [path] | File or directory to push (default: current directory) | | -C, --confirm <true\|false> | Commit (default: true) | | --ticket <id> | Override ticket ID | | --modify-key <key> | Provide ModifyKey directly (skips interactive prompt) | | --row-key <type> | Override row key type for this invocation (RowUID or RowID) | | --meta-only | Only push metadata, skip file content | | --content-only | Only push file content, skip metadata | | -y, --yes | Auto-accept all prompts | | --toe-stepping <true\|false> | Check server for conflicts before pushing (default: true). Set to false to skip the check and push unconditionally | | --no-scripts | Bypass all script hooks; run default push pipeline | | --no-build | Skip the build phase; run push phase only | | --json |