1.6K App
Local Mode / CLI Reference

CLI Reference

Every maple command, argument, and flag — plus the server endpoints, environment variables, and troubleshooting for local mode.

The maple binary is one CLI with two backends: a local server (maple start) and a remote workspace (maple login). Every query command runs against whichever is resolved for that invocation. Output is JSON by default — clean enough to pipe into jq or an agent.

This page is the complete surface. For a guided walkthrough, start with Maple Local.

Global flags

These are accepted by every command (position-independent — maple --local traces and maple traces --local both work):

FlagDescription
--localForce local mode (requires a running maple start)
--remoteForce remote mode (requires maple login)
--debugPrint the compiled SQL and per-query timing to stderr (stdout stays clean JSON)
--format <json|table>Output format; default json. table renders a flat row set as an aligned table

Most query commands also share a set of filter flags. Defaults and availability vary per command (listed below), but the shapes are consistent:

FlagAliasDefaultDescription
--since <range>6hRelative time range — 30m, 1h, 6h, 24h, 7d
--start <time>Absolute start, YYYY-MM-DD HH:mm:ss UTC (use with --end)
--end <time>Absolute end, YYYY-MM-DD HH:mm:ss UTC
--service <name>-sFilter by service name
--env <name>-eFilter by deployment environment (e.g. production)
--limit <n>-n20Maximum number of results
--offset <n>0Pagination offset

Server commands

Local mode only. maple start is the long-lived process that owns the embedded chDB connection; the query commands talk to it over HTTP.

maple start

Start the local ingest + query server (embedded ClickHouse via chDB).

FlagDefaultDescription
--host <address>127.0.0.1Bind address; non-loopback exposes all unauthenticated local routes
--advertise-host <host>connection-safe bind addressHost printed for clients and the bundled UI
--port <int>4318Port for OTLP/HTTP ingest, query API, and bundled UI
--data-dir <path>~/.maple/dataEmbedded ClickHouse data directory
--chdb-config-file <path>Optional ClickHouse config file passed to embedded chDB
--offlinefalseServe the bundled same-origin UI instead of local.maple.dev
--background, -dfalseRun detached; stop with maple stop
--resetfalseWipe live chDB data while preserving checkpoints
--on-dirty-store <wipe|fail|restore-checkpoint>failRecovery policy when the store was not cleanly closed
maple start                    # foreground, UI from local.maple.dev
maple start --offline          # foreground, bundled UI, no internet needed
maple start -d --port 4400     # detached on a custom port
maple start --host 0.0.0.0 --advertise-host maple.home.arpa --offline

Detached startup forwards the selected --on-dirty-store policy unchanged to the foreground child. Before any reset, compatibility check, dirty-store decision, or data-directory creation, startup reconciles a recorded reset or checkpoint-restore transaction. Ambiguous, malformed, or conflicting transaction state fails closed and prints the preserved paths.

The default dirty-store policy is fail, so an unclean shutdown never silently deletes telemetry. Choose restore-checkpoint to recover the selected checkpoint, or explicitly choose wipe to discard only live chDB data. Checkpoint snapshots, pins, operation evidence, and quarantine state under <data-dir>/backups are preserved by both --reset and explicit wipe. Schema-incompatible stores also fail closed until an operator explicitly resets live data.

maple stop

Stop a running maple start server (reads the PID file beside the data dir).

FlagDefaultDescription
--data-dir <path>~/.maple/dataData directory of the server to stop

maple reset

Delete live chDB data so the next maple start bootstraps fresh. The checkpoint registry under <data-dir>/backups is preserved. Refuses to run while a server still owns the store.

Reset is journaled beside the data directory and removes only the chDB-owned top-level directories produced by the bundled native build (data, metadata, store, and tmp). If any other entry exists, reset preserves everything and fails with the unrecognized paths so an operator can inspect them. Startup finishes an interrupted recorded reset before it evaluates store compatibility or cleanliness.

FlagDefaultDescription
--data-dir <path>~/.maple/dataStore whose live data clears
--yes, -yfalseSkip the confirmation prompt

maple checkpoint

Create and validate a restorable checkpoint of the local chDB store. The running server must have been started with a chDB config that allows ClickHouse backups:

<clickhouse>
  <backups>
    <allowed_disk>default</allowed_disk>
    <allowed_path>backups</allowed_path>
  </backups>
</clickhouse>
maple start --chdb-config-file ./chdb-backups.xml
maple checkpoint

Checkpoint accepts --host, --port, and --data-dir. Wildcard hosts are queried through matching loopback; if the server was started with one-off host or port flags, pass the same values to maple checkpoint.

Every completed checkpoint receives an immutable UUID and is written under:

<data-dir>/backups/
  state.json
  snapshots/<checkpoint-id>/
    backup/
    manifest.json
  operations/
  pins/
  quarantine/
  retiring/

state.json is the only authority for the selected current and previous IDs. Maple writes and syncs a strict versioned manifest only after restoring the native backup into one sacrificial chDB and validating all six raw telemetry tables. It then selects the snapshot with a synced atomic state-file replacement. A third checkpoint retires the old previous snapshot only when it is complete, compatible, unreferenced, and unpinned; uncertain state is preserved.

The earlier unreleased backups/{building,current,previous} preview layout is not inferred or deleted. If it is present without a valid new state pointer, checkpoint commands fail closed and report the paths for operator inspection. Missing, malformed, incompatible, incomplete, or symlinked checkpoint state is also rejected rather than guessed.

maple restore

Restore the local chDB store from the last promoted checkpoint. Refuses to run while a server still owns the store. The existing store is moved aside for quarantine rather than deleted.

FlagDefaultDescription
--data-dir <path>~/.maple/dataStore to restore
--checkpoint-id <uuid>selected currentRestore one immutable checkpoint ID
--yes, -yfalseSkip the confirmation prompt

Restore uses a collision-resistant working path and quarantine, and records a durable sibling transaction before changing the live directory. Reconciliation can resume the recorded quarantine, live swap, and marker-update boundaries idempotently. The displaced live store is never deleted. Unrecorded or mismatched restore-like paths fail closed without mutation.

maple restore --yes
maple restore --checkpoint-id 01234567-89ab-4cde-8fab-0123456789ab --yes

Checkpoint and restore operations share one maintenance lock. A live owner is reported as busy; uncertain ownership is preserved and blocks destructive maintenance.

Archive commands

Local mode only. Export sealed UTC-day ranges of the six raw telemetry tables from immutable checkpoints into portable Parquet, queryable independently with DuckDB. See Local telemetry archives for the full architecture, calibration, and off-happy-path reference.

maple archive create <range-date> <signal>

Seal one UTC day of one signal into a validated Parquet generation from a checkpoint. Resolves and pins the checkpoint (default: current), restores it to sacrificial scratch, exports bounded Parquet shards, validates row counts and checksums, atomically selects the generation, and releases the pin. The live store is never opened for export.

Argument / FlagDescription
<range-date>UTC day to seal, YYYY-MM-DD
<signal>logs, traces, metrics_sum, metrics_gauge, metrics_histogram, or metrics_exponential_histogram
--data-dirLive chDB data directory (default: ~/.maple/data)
--archive-dirArchive root (default: ~/.maple/archive)
--scratch-rootRestored-checkpoint scratch root (default: ~/.maple/scratch)
--checkpoint-idArchive from a specific checkpoint instead of the selected current

A late-arrival re-export creates a new generation that supersedes the old one; the previous generation is retained but excluded from active listings and query paths.

maple archive list

Report active archive generations. Superseded generations are retained on disk but never listed.

FlagDescription
--archive-dirArchive root (default: ~/.maple/archive)
--output summary|paths|jsonsummary (default), paths (machine-readable active Parquet paths for DuckDB), or json
--signal <name>Required with --output paths; the signal whose active paths to emit

maple archive rebuild <signal>

Rebuild a signal’s catalog.jsonl from the authoritative generation manifests, recovering from a truncated or missing catalog without rescanning Parquet bytes.

Services

maple services

List active services with throughput, error rate, and P95 latency. Flags: --since / --start / --end, --env.

maple diagnose <service-name>

Deep-dive a service: health, top errors, recent traces and logs.

  • <service-name> — service to diagnose
  • Flags: --since / --start / --end, --env

maple service-map

Service dependency edges (call counts, errors, latency). Flags: --since / --start / --end, --service, --env.

maple top-ops <service-name>

Top operations (span names) for a service, ranked by a metric.

  • <service-name> — service to inspect
  • --metric <count|avg_duration|p50_duration|p95_duration|p99_duration|error_rate|apdex> — ranking metric (default count)
  • Flags: --since / --start / --end, --limit

Traces

maple traces

Search traces/spans.

FlagDescription
--span-name <substr>Filter by span name (substring, case-insensitive)
--errorsOnly include traces with errors
--min-duration-ms <int>Minimum duration in milliseconds
--max-duration-ms <int>Maximum duration in milliseconds
--http-method <method>Filter by HTTP method (GET, POST, …)

Plus --since / --start / --end, --service, --limit, --offset.

maple traces --service api --min-duration-ms 500 --errors --since 1h

maple trace <trace-id>

Inspect a trace: full span tree + correlated logs.

  • <trace-id> — trace ID to inspect

maple slow-traces

Find the slowest traces with duration stats. Flags: --since / --start / --end, --service, --env, --limit.

Errors

maple errors

List error groups by fingerprint (count, affected services, last seen). Flags: --since / --start / --end, --service, --env, --limit.

maple error <fingerprint-hash>

Show detail for one error group: sample traces + timeseries.

  • <fingerprint-hash> — error fingerprint hash (from the errors command)
  • Flags: --since / --start / --end, --service, --limit

Logs

maple logs

Search logs with filtering.

FlagAliasDescription
--severity <level>Filter by severity (TRACE/DEBUG/INFO/WARN/ERROR/FATAL)
--search <text>-qSearch text (substring match)
--trace-id <id>Filter by trace ID

Plus --since / --start / --end, --service, --limit, --offset.

maple log-patterns

Cluster logs into templates to surface the noisiest patterns. Flags: --since / --start / --end, --service, --severity, --search/-q, --limit.

Attributes

maple attributes has two subcommands for discovering attribute keys and values.

maple attributes keys

Discover available attribute keys.

FlagDefaultDescription
--source <traces|metrics|services>tracesAttribute source
--scope <span|resource>spanAttribute scope (traces only)

Plus --service, --since / --start / --end, --limit.

maple attributes values <key>

List values for an attribute key.

  • <key> — attribute key to list values for
  • Flags: same as attributes keys

Metrics and raw SQL

maple metrics

List available metrics. Flags: --since / --start / --end, --service, --search/-q, --limit.

maple query "<sql>"

Run raw ClickHouse SQL against the local chDB store — an escape hatch for anything the typed commands don’t cover.

  • <sql> — raw ClickHouse SQL
maple query "SELECT ServiceName, count() FROM traces GROUP BY ServiceName ORDER BY 2 DESC"

Local only. Raw SQL against the multi-tenant cloud warehouse would let a client read other orgs’ data, so maple query returns a clear error in remote mode. Every other command works in both modes.

Analytics

maple timeseries

Time-bucketed trace metrics (count, latency quantiles, error rate, apdex emitted per bucket).

FlagDefaultDescription
--group-by <none|service|span_name|status_code|http_method>noneGroup series by dimension
--span-name <substr>Filter by span name
--errorsfalseOnly include errored spans
--bucket <seconds>60Bucket size in seconds

Plus --since / --start / --end, --service, --env.

maple breakdown

Top-N trace breakdown by dimension (service, span, status code, http method).

FlagDefaultDescription
--group-by <service|span_name|status_code|http_method>span_nameGroup results by dimension
--span-name <substr>Filter by span name
--errorsfalseOnly include errored spans

Plus --since / --start / --end, --service, --env, --limit.

maple compare

Compare service health between two time windows (regression detection). Provide either --around or all four explicit window bounds.

FlagDescription
--around <ts>Compare the 30m before vs. after this UTC time (YYYY-MM-DD HH:mm:ss)
--current-start <ts> / --current-end <ts>The “current” window
--previous-start <ts> / --previous-end <ts>The baseline window
--env <name>Filter by deployment environment

Auth and configuration

Remote credentials live in ~/.maple/config.json (mode 0600).

maple login

Save remote workspace credentials.

FlagDescription
--api-url <url>Maple API base URL (e.g. https://api.maple.dev)
--token <token>API token. If omitted, it’s read from stdin so it stays out of shell history

maple logout

Remove the stored remote token from ~/.maple/config.json.

maple whoami

Show the resolved mode (local/remote) and target.

maple use <local|remote|auto>

Pin the default backend so commands stop auto-detecting, or restore auto-detect.

  • <mode>local, remote, or auto (clear the pin)

Mode resolution, per command, in priority order:

  1. --local / --remote flags.
  2. defaultMode pinned via maple use.
  3. Auto-detect — a configured token implies remote; otherwise a quick GET /health probe of the local server implies local. If neither is available, the CLI prints an actionable error.

Server endpoints

maple start binds 127.0.0.1 by default. --host or MAPLE_LOCAL_BIND_HOST may select another address; doing so exposes every route below without application authentication. When --offline is set, the bundled SPA is also served over GET.

MethodPathPurpose
GET/healthLiveness probe (returns OK); used by mode auto-detect
POST/v1/tracesOTLP traces ingest → { "accepted": <rowCount> }
POST/v1/logsOTLP logs ingest
POST/v1/metricsOTLP metrics ingest
POST/local/queryRun SQL: { "sql": "..." } → bare JSON array of rows
OPTIONS*Restricted CORS/PNA preflight for the exact configured hosted UI origin

OTLP bodies may be protobuf (default) or JSON, optionally gzip-encoded. The /local/query handler owns the output format — it strips any trailing FORMAT <ident> and re-appends FORMAT JSONEachRow, then wraps the rows into a JSON array, so clients POST their compiled SQL verbatim.

Environment variables

Runtime (CLI + server):

VariableDefaultPurpose
MAPLE_LOCAL_BIND_HOST127.0.0.1Server bind host and default same-machine CLI target; wildcards map to loopback
MAPLE_LOCAL_ADVERTISE_HOSTconnection-safe bind hostHost printed for clients and the bundled UI
MAPLE_LOCAL_URLderived bind host + 4318Explicit base URL override for CLI query and mode detection
MAPLE_LOCAL_UI_URLhttps://local.maple.devExact separately hosted UI origin linked by maple start and allowed by CORS
MAPLE_LIBCHDB(auto)Explicit path to libchdb. Otherwise resolved beside the binary (Homebrew keeps it in the same libexec dir), then ~/.maple/bin/libchdb.{so,dylib}
MAPLE_API_URLhttps://api.maple.devRemote API base URL
MAPLE_API_TOKENRemote bearer token (overrides the stored value)
MAPLE_ORG_IDRemote org override
MAPLE_DEBUGSet to 1 to enable --debug
MAPLE_FORMATjsonjson or table — same as --format
MAPLE_NO_UPDATE_CHECKSet to 1 to disable startup update checks (the Homebrew wrapper sets this automatically)

Homebrew:

brew install Makisuo/tap/maple
brew upgrade maple
brew uninstall maple

Homebrew-managed installs block maple update; use brew upgrade maple so Homebrew owns the installed version and receipt. If Homebrew asks you to trust the third-party tap, run brew trust Makisuo/tap once and retry the install.

Manual installer (scripts/install.sh, env-only):

VariableDefaultPurpose
MAPLE_VERSIONlatestRelease tag to install
MAPLE_INSTALL_DIR~/.maple/binWhere the 2-file bundle is installed
MAPLE_BIN_DIR(auto)Where maple is symlinked onto PATH
MAPLE_SKIP_CHECKSUM0Set to 1 to skip SHA-256 verification (air-gapped mirrors only)

The on-disk config at ~/.maple/config.json stores apiUrl, token, orgId, and defaultMode. Env vars take precedence over stored values.

Troubleshooting

libchdb not found. The binary dlopens libchdb relative to its own path, then falls back to ~/.maple/bin. Homebrew keeps maple and libchdb together in its Cellar; the manual installer keeps them in ~/.maple/bin. If you move files by hand, keep libchdb.so/.dylib beside maple, or set MAPLE_LIBCHDB to its full path. (Running from source has no sibling library — set MAPLE_LIBCHDB or drop one in ~/.maple/bin.)

Homebrew installed but maple still runs the old binary. You probably have a manual-installer symlink earlier on PATH. Run command -v maple to confirm, then remove the old symlink or run curl -fsSL https://maple.dev/cli/uninstall | sh before reinstalling with Homebrew.

maple is already running (PID …). A server already owns this data dir. Stop it with maple stop, or start a second instance on another port and data dir: maple start --port 4400 --data-dir ~/.maple/data-2.

Incompatible store after an upgrade. If a new binary refuses to open an older store (the local store … is incompatible), explicitly clear live data with maple reset --yes, or start fresh in one step with maple start --reset. Both preserve the checkpoint registry; incompatible checkpoints remain preserved and fail closed until deliberately handled.

Browser asks to “access devices on your local network” (or CORS errors). The default dashboard at local.maple.dev is a public origin reaching your loopback server, which trips Chrome’s Private Network Access gate. Run maple start --offline to serve the dashboard same-origin — no prompt, no internet needed. For a wildcard LAN bind, also set --advertise-host to the hostname the browser will use; other browser hosts and cross-origins are rejected.

Authentication proxy blocks the bundled UI. The UI works with TLS and browser-managed authentication such as a session cookie or HTTP authentication. It does not inject a Bearer API key or copy an entry-page query parameter into /local/query and OTLP URLs.

No data appearing. Confirm your exporter points at the advertised host and port and the server is up (maple whoami, or curl <host>:4318/health). Widen the time range (--since 24h — the default is 6h). Local mode stores everything under org_id = "local"; a successful ingest responds { "accepted": <n> }.

No Maple backend found. No mode could be resolved: start local mode (maple start) or connect a workspace (maple login), or force one with --local / --remote.