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

import LocalHero from "../../components/local/LocalHero.astro"
import LocalFlow from "../../components/local/LocalFlow.astro"
import LocalCommandGrid from "../../components/local/LocalCommandGrid.astro"
import InstallTabs from "../../components/local/InstallTabs.astro"

<LocalHero />

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-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](/docs/reference/cli), 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](#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.

<InstallTabs />

> Prefer to do it by hand? Download a release bundle (both `maple` and `libchdb`) from [GitHub Releases](https://github.com/MapleTechLabs/maple/releases), or read [`scripts/install.sh`](https://github.com/MapleTechLabs/maple/blob/main/scripts/install.sh) before piping it to a shell. Later, `maple update` upgrades a script install in place; Homebrew installs use `brew upgrade maple`.

## 2. Start the server

```bash
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](/docs/reference/cli#maple-start).

## 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:

```bash
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](/docs/instrumentation). Anything you can send to hosted Maple flows into the local server unchanged.

<LocalFlow />

## 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:

```bash
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](/docs/reference/cli#server-endpoints).

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.

```bash
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"
```

<LocalCommandGrid />

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](/docs/reference/cli) has every command, argument and flag.

## Your data

- **Where it lives.** `~/.maple/data`, or whatever `--data-dir` you 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](/docs/reference/retention).
- **Restore points.** The running server takes a checkpoint on a timer, and `maple restore` rolls the store back to one. Cadence, restore and unclean-shutdown behavior are on [Checkpoints and archives](/docs/local-mode/checkpoints-and-archives).
- **Starting over.** `maple reset` clears live data and keeps checkpoints. `maple start --reset` does the same in one step after an incompatible upgrade.
- **Keeping history.** `maple archive` exports whole days as Parquet files you can open in DuckDB. See [Archives](/docs/local-mode/checkpoints-and-archives#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](/docs/reference/cli#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:

```bash
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](/docs/reference/cli#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](https://github.com/MapleTechLabs/maple/blob/main/docs/local-mode.md).
