Maple Local
Run the whole of Maple as one binary on your machine: OTLP ingest, an embedded ClickHouse, a query API, the dashboard and a CLI. No account, no containers, nothing to deploy.
Two commands. Ingest, storage and every query run on 127.0.0.1, and your telemetry stays on your machine.
brew install Makisuo/tap/maple maple start 🍁 maple · local mode● listening on http://127.0.0.1:4318OTLP/HTTP POST /v1/{traces,logs,metrics}query POST /local/querydashboard https://local.maple.devdata ~/.maple/datapid 48213 · stop with `maple stop`
- port :4318
- store embedded ClickHouse
- signals traces · logs · metrics
- deps none
Maple Local is the full product running on your machine, free, for local development. Point any OpenTelemetry exporter at localhost, open the dashboard, and explore traces, logs, metrics, errors and a service map. It is not a client for the hosted service and needs no account. Your telemetry is stored and queried on your machine. The CLI does make a few network calls of its own by default, listed in What connects to the internet.
What you get
| Surface | What it is |
|---|---|
| OTLP/HTTP ingest | POST /v1/{traces,logs,metrics} on port 4318, protobuf or JSON, gzip optional. Any OTel SDK works unchanged. |
| Dashboard | The same Maple UI, either auto-updating from local.maple.dev or bundled in the binary for offline use. |
| CLI | maple services, maple traces, maple errors and the other query commands in the CLI reference, printing JSON you can pipe into jq or an agent. |
| Raw SQL | maple query "<sql>" against the embedded store when the typed commands don’t cover it. |
Data lives in ~/.maple/data and survives restarts. See Your data for retention and restore points.
1. Install
Homebrew is the easiest path on macOS and Linux. The install script works anywhere a shell does.
brew install Makisuo/tap/maple Homebrew downloads the matching release bundle, verifies its checksum, installs maple and libchdb together, and links maple onto your PATH.
- Homebrew-managed installs block
maple updateso the package manager stays in charge. - If Homebrew asks you to trust the tap, run
brew trust Makisuo/taponce and retry the install.
curl -fsSL https://maple.dev/cli/install | sh The script is scripts/install.sh; read it first. It detects your OS/arch, downloads the matching bundle from the latest GitHub release, verifies its checksum, installs maple + libchdb into ~/.maple/bin, clears the macOS Gatekeeper quarantine, and symlinks maple onto your PATH.
- Your
~/.maple/datais kept on uninstall. - Migrating to Homebrew later? Remove the old PATH symlink so your shell resolves Homebrew's
maple.
Prefer to do it by hand? Download a release bundle (both
mapleandlibchdb) from GitHub Releases, or readscripts/install.shbefore piping it to a shell. Later,maple updateupgrades a script install in place; Homebrew installs usebrew upgrade maple.
2. Start the server
maple start # ingest + embedded ClickHouse + query API on :4318
maple start --offline # …and serve the dashboard from the binary
maple start -d # …detached; logs to ~/.maple/maple.log, stop with `maple stop`
maple start is the one long-lived process. It owns the embedded database and hosts ingest, the query API and, with --offline, the dashboard, all on a single port bound to loopback. The startup banner prints the addresses and a link to open.
The flags you are likely to touch:
| Flag | Default | Use it when |
|---|---|---|
--port <int> | 4318 | Something else already listens on 4318 |
--data-dir <path> | ~/.maple/data | You want a second, separate store |
--offline | off | You have no internet, or want the UI same-origin |
--background, -d | off | You want it out of the way; maple stop ends it |
--reset | off | A new binary refuses an old store; wipes live data, keeps checkpoints |
Everything else, including bind and advertise hosts, checkpoint cadence and recovery policy, is in the CLI reference.
3. Send telemetry
Point your app at the server. No auth header is needed locally, and most exporters default to protobuf, so this is usually all it takes:
export OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:4318"
export OTEL_SERVICE_NAME="my-service"
For custom spans, log correlation and framework auto-instrumentation, follow the guide for your language in Instrument your application. Anything you can send to hosted Maple flows into the local server unchanged.
- OTLP exporter your app / SDK
- POST /v1/* ingest · :4318
- embedded ClickHouse ~/.maple/data
- POST /local/query query API
- dashboard · CLI read your data
/local/query HTTP contract.
4. Open the dashboard
The banner links to the dashboard. There are two ways to serve it:
Default (local.maple.dev) | --offline | |
|---|---|---|
| Where the UI comes from | Hosted, always the latest build | Bundled inside the binary |
| Talks to your data over | Loopback, from a public origin | Same origin |
| Needs internet | Yes, to load the page | No |
| Browser prompt | Chrome asks once to “access devices on your local network” | None |
Both read the same local store. Pick --offline when you are on a plane, behind a strict proxy, or would rather not see the prompt.
Reaching it from another machine
Bind to all interfaces and print a hostname the other browser will actually use:
maple start --host 0.0.0.0 --advertise-host maple.home.arpa --offline
Anyone who can reach the port can then use the UI, run raw SQL through /local/query, and send OTLP data. None of these routes check credentials. The maintenance routes (checkpoint, day retirement and the local event routes) require a token that maple start writes beside the data directory with mode 0600 (<data-dir>.maintenance-token, and <data-dir>.event-consumer-token for event consumers). They are only as safe as those files. /local/retention/retire deletes a day of live data. The full route list is in the CLI reference.
Use a non-loopback bind only on a network you trust, or behind TLS with browser-managed auth such as a session cookie. The bundled UI does not attach API keys to its requests.
Query from the terminal
The same binary is the query CLI. Every command runs against the running server and prints JSON by default. Add --format table for an aligned table, or --debug to see the compiled SQL on stderr.
maple services # active services at a glance
maple traces --service api --since 1h # recent spans for one service
maple errors --since 24h # error groups by fingerprint
maple query "SELECT count() FROM traces"
Services
-
maple servicesthroughput, error rate, P95 per service -
maple diagnose <svc>health, top errors, recent traces and logs -
maple service-mapdependency edges with call and error rates -
maple top-ops <svc>operations ranked by a metric
Traces
-
maple tracessearch spans by service, duration, error -
maple trace <id>full span tree with correlated logs -
maple slow-tracesthe slowest traces with duration stats
Errors
-
maple errorserror groups by fingerprint -
maple error <hash>one group: sample traces and a timeseries
Logs
-
maple logssearch by service, severity, text, trace -
maple log-patternscluster logs into templates
Analytics
-
maple timeseriestime-bucketed latency, error rate, apdex -
maple breakdowntop-N by service, span, status, or method -
maple comparetwo windows side by side
Metrics and SQL
-
maple metricslist available metrics -
maple attributes keysdiscover attribute keys and values -
maple query "<sql>"raw SQL against the local store
Most query commands share the same filters: --since (30m, 1h, 24h, 7d) or absolute --start/--end, --service/-s, --env/-e, and --limit/-n. The CLI reference has every command, argument and flag.
Your data
- Where it lives.
~/.maple/data, or whatever--data-diryou passed. - Retention. Logs and traces are kept for 30 days, metrics for 90.
maple start --minimum-raw-telemetry-retention-days <n>raises the floor for raw logs, traces and metrics (90 to 3,650 days). Hosted retention is on Retention. - Restore points. The running server takes a checkpoint on a timer, and
maple restorerolls the store back to one. Cadence, restore and unclean-shutdown behavior are on Checkpoints and archives. - Starting over.
maple resetclears live data and keeps checkpoints.maple start --resetdoes the same in one step after an incompatible upgrade. - Keeping history.
maple archiveexports whole days as Parquet files you can open in DuckDB. See Archives.
What connects to the internet
Your telemetry and query results stay on your machine. These calls go out by default:
| Call | When | Turn it off |
|---|---|---|
The CLI’s own traces and metrics, sent to https://ingest.maple.dev with an ingest key built into the binary | Every command, and every request maple start handles | MAPLE_TELEMETRY=off |
| Release check against the GitHub releases API | At most once per 24 hours, only in an interactive terminal | MAPLE_NO_UPDATE_CHECK=1 (Homebrew installs set it) |
The dashboard page from local.maple.dev | When you open the dashboard | maple start --offline |
The CLI’s own telemetry describes the CLI, not your data. It reports the service name maple-cli, the command, its duration and errors. For each OTLP request maple start handles it records the signal, the body size and the number of items, never the payload. For each /local/query request it records only the timing and whether it succeeded. SQL text, filter values and error messages are never exported, and the CLI’s own logs are not sent at all. MAPLE_INGEST_KEY, MAPLE_ENDPOINT and MAPLE_ENVIRONMENT redirect or relabel this export; see Environment variables.
One CLI, two backends
The same maple also talks to a hosted Maple workspace. Sign in from the terminal and it opens your browser:
maple auth login # browser sign-in; `--with-token` reads a token from stdin instead
maple whoami # which backend a command would hit right now
maple use local # pin it; `maple use auto` restores detection
Per command, an explicit --local or --remote wins, then the pinned default, then auto-detect: a stored login means remote, otherwise the CLI probes the local server. Everything except maple query works against both. Raw SQL stays local because the hosted warehouse is shared between organizations. See Using the CLI with hosted Maple.
Under the hood
One compiled binary is both the CLI and the server. It talks to ClickHouse in-process through libchdb, so there is no subprocess and no second runtime to install. Short-lived CLI commands and the dashboard read the store over the same POST /local/query contract. The architecture, the UI origin model and the release bundle are described in the local mode design doc.