CLI
Local Data Apps
A local data app is a running dcupl SDK instance — a daemon — that lives on your machine. Ingest data into it, build it, then query, facet, and aggregate straight from your terminal. It's the fastest way to profile a CSV, prototype a model, or explore a dataset before you commit to Console.
Lifecycle
The flow is always the same: create a daemon, mutate data (which stages changes), build to apply them — or skip the build with --auto-update — then query.
create
Start a daemon (an in-memory SDK instance)
mutate
Ingest data — stages changes
build
Apply staged changes (or use --auto-update)
query
Query, facet & aggregate — then destroy
Worked example: profile a CSV
Spin up a daemon, load a CSV, and profile it end to end. The --json flag makes every command emit machine-readable output you can pipe into other tools.
start an interactive daemon that applies mutations on the fly: dcupl app create --auto-update --json — output: { "appId": "app_8f3a", "status": "running", "autoUpdate": true }
ingest the CSV, inferring the model from a 100-row sample: dcupl app data upsert --file products.csv --model Product \ --key-property id --auto-generate-sample-size 100 --json — output: { "model": "Product", "upserted": 1284, "sampled": 100, "applied": true }
see the most common categories: dcupl app fn facets --model Product --attribute category --limit 10 --json — output: [ { "value": "Accessories", "count": 514 }, { "value": "Outerwear", "count": 412 }, { "value": "Footwear", "count": 358 } ]
get price statistics: dcupl app fn aggregate --model Product --attribute price --types avg,min,max --json — output: { "avg": 84.27, "min": 4.99, "max": 489.00 }
top 5 most expensive products over $100: dcupl app query execute --model Product \ --query '{"price":{"$gt":100}}' --sort price:desc --limit 5 --json — output: [ { "key": "SKU-1190", "productName": "Alpine Shell", "price": 489.00 }, { "key": "SKU-0042", "productName": "Trail Parka", "price": 412.50 }, { "key": "SKU-0871", "productName": "Storm Boots", "price": 318.00 } ]
clean up: dcupl app destroy --json — output: { "destroyed": true, "appId": "app_8f3a" }
Numeric types from CSV. CSV columns infer as strings by default, so an aggregate over a numeric column (like avg on price) can return undefined. For reliable numeric statistics, define an explicit model with numeric property types — sample size affects inference breadth, not type correctness.
Manage the daemon
When you run a single app, the --app <id> flag is optional — the CLI targets the active one. With multiple apps, pass --app to disambiguate.
Daemon management
| Command | What it does |
|---|---|
dcupl app create [--auto-update] | Start a daemon and register an app |
dcupl app list | List running apps |
dcupl app status [--app <id>] | Show app state, including pending staged changes |
dcupl app build [--app <id>] | Run update() and apply all staged changes |
dcupl app logs [--app <id>] [--lines <n>] | Tail the daemon logs |
dcupl app destroy [--app <id>] [--keep-logs] | Shut down the daemon |
Create flags
The flags most relevant to the daemon workflow. See Commands for the full reference.
| Flag | Description |
|---|---|
--auto-update | Apply every mutation immediately, no build step needed |
--auto-generate-properties | Infer a model from data on first ingest |
--auto-generate-deep | Walk every row when inferring (instead of sampling) |
--auto-generate-sample-size <n> | Number of rows to scan when inferring a model |
--quality <bool> | Run data quality checks (default true) |
--logging-level <level> | trace, debug, info, warn, error, or fatal |
--idle-timeout <min> | Auto-shutdown after this many idle minutes (default 30) |
Ingest verbs
Use dcupl app data <verb> to feed data in. Each verb maps to an SDK mutation.
| Verb | Effect |
|---|---|
upsert | Add or update items |
update | Update existing items |
set | Replace all items for a model |
remove | Remove items by key |
reset | Drop all items for a model |
Input flags
| Flag | Description |
|---|---|
--file <path> | Read data from a file |
--url <uri> | Read data from a URL |
--content <str> | Inline content. Use "-" to read from stdin |
--format <fmt> | csv, json, or ndjson |
--model <str> | Target model |
--key-property <str> | Key property. Comma-separate for a composite key (a,b,c) |
--auto-generate-key | Generate a UUID when no key is found |
Query flags
| Flag | Description |
|---|---|
--model <str> | Model to query |
--query <str> | Filter expression (the filter flag is --query) |
--query-file <path> | Read the filter from a file instead |
--sort name:asc | Sort spec, e.g. price:desc |
--limit <n> | Maximum number of results |
--start <n> | Offset for pagination |
--projection <str> | Comma-separated list of attributes to return |
Query & analytics
Fetch one item by key or run a filtered, sorted, paginated query — then layer the SDK's analytics functions (dcupl app fn) over the same data.
The filter flag is --query, not --filter. For complex filters, keep the expression in a file and pass --query-file.
Loader integration
To query data sourced through a loader configuration, start the app with --load. This registers, processes, and builds a loader so the app is queryable from workspace files or remote sources. Remote sources need credentials — see Cloud Sync.