OpenTelemetry observability platform
$ npx -y skills add mapletechlabs/maple --agent claude-code
Repo: mapletechlabs/maple
What's inside
Send telemetry to maple.dev. Create an ingest key in Settings, then configure any OpenTelemetry SDK or collector:
export OTEL_EXPORTER_OTLP_ENDPOINT="https://ingest.maple.dev"
export OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer YOUR_INGEST_KEY"
Or try it on your machine. One binary with OTLP ingest on :4318, an embedded ClickHouse and the dashboard:
brew install Makisuo/tap/maple
maple start
No Homebrew? curl -fsSL https://maple.dev/cli/install | sh. See docs/local-mode.md for details.
Connect your coding agent to the MCP server:
claude mcp add --transport http maple https://api.maple.dev/mcp
| Path | What lives there |
|---|---|
apps/web | Dashboard (TanStack Start, React 19, Vite) |
apps/api | Effect HTTP API, auth and OAuth |
apps/ai | MCP server, chat agent and investigations |
apps/ingest | OTLP ingest gateway: key auth, org enrichment, forwarding |
apps/alerting | Alert evaluation worker |
apps/cli, apps/local-ui | The maple CLI and the local-mode dashboard |
apps/landing | maple.dev and the docs |
apps/ios | Native SwiftUI app |
packages/* | Shared Maple code: domain, query-engine, backend, db, ui, SDKs |
lib/* | Standalone libraries with no Maple knowledge |
>=1.3bun install
Run the whole stack — the Cloudflare Workers under alchemy's local runtime,
the rest as child processes of the same alchemy dev — behind
https://<app>.localhost:
bun dev
Or just some of it (api, alerting, electric-sync, web, landing,
ingest, local-ui, scraper):
bun dev api web
A single non-Worker app can also run on its raw port, outside the stack:
bun --filter=@maple/web dev
bun run typecheck
bun run build
bun run test
Run the local multi-service stack (API + web + ingest + otel collector):
docker compose -f docker-compose.yml up --build
Services:
http://localhost:3472http://localhost:3471http://localhost:34744317 (gRPC), 4318 (HTTP), 13133 (health/extensions)Deployments run on Alchemy v2 (Effect-based): the root alchemy.run.ts exports a
single Alchemy.Stack("maple", …) whose program yields one module per app:
apps/api/src/worker.ts — the api Worker: Hyperdrive (PlanetScale Postgres) MAPLE_DB,
KV, queues, the two Workflows and the ChatSession Durable Object, all yielded from its initapps/alerting/src/worker.ts — cron-driven alerting Worker (cross-script workflow ref)apps/electric-sync/src/worker.ts — ElectricSQL shape-proxy Workerapps/web/src/worker.ts / apps/landing/src/worker.ts / apps/local-ui/src/worker.ts
— static builds via Command.Build + asset-serving WorkersStage grammar is prd / pr-<number> / dev names, resolved via
@maple/infra/cloudflare (parseMapleStage, resolveMapleDomains, resolveWorkerName,
resolveHyperdriveRefId, resolveMapleProfile). prd binds the
dashboard-managed Hyperdrive by config ID (resolveHyperdriveRefId) — origin credentials
never touch a deploy. MAPLE_PG_URL is only needed for dev stages, whose Hyperdrive alchemy
manages itself. PR previews bind no database at all (their profile's database is "none"):
DB-backed routes 500, everything else in the preview works.
Run locally:
PR_NUMBER=123 bun run alchemy:deploy:pr
The first v2 deploy against a stage with live v1-created resources needs --adopt
(the pr script passes it already); v1 state is incompatible and simply abandoned —
never run a v1 alchemy destroy against a live stage.
Tear down:
PR_NUMBER=123 bun run alchemy:destroy:pr
CI workflows:
workflow_dispatch): .github/workflows/deploy-prd.yml.github/workflows/deploy-pr-preview.yml (pull_request opened/synchronize/reopened/closed)Secrets source model (CI):
Infisical/secrets-action using OIDC
(credential-less — GitHub's OIDC token authenticates a machine identity, no long-lived
token stored). CI needs:
INFISICAL_PROJECT_SLUG (the project slug — a
variable, not a secret: GitHub masks secret values everywhere, and a
slug like maple would then blank out the PR-preview deployment URL
app-pr-<n>.maple.dev)INFISICAL_MACHINE_IDENTITY_ID (the machine identity ID)prod, dev — mapped from the old Doppler
prd/pr configs) must define:
CLOUDFLARE_API_TOKENCLOUDFLARE_DEFAULT_ACCOUNT_ID (bridged to alchemy v2's CLOUDFLARE_ACCOUNT_ID in the root alchemy.run.ts; ALCHEMY_PASSWORD/ALCHEMY_STATE_TOKEN were v1-only and are no longer read)TINYBIRD_HOSTTINYBIRD_TOKENEMAIL_FROM (sender address on an onboarded Cloudflare Email Service domain; delivery uses the EMAIL worker binding, no API key)MAPLE_INGEST_KEY_ENCRYPTION_KEYMAPLE_INGEST_KEY_LOOKUP_HMAC_KEYMAPLE_AUTH_MODEMAPLE_ROOT_PASSWORD (required in self_hosted mode)CLERK_SECRET_KEYCLERK_PUBLISHABLE_KEYCLERK_JWT_KEYSetup note: the machine identity must have a GitHub OIDC auth method configured in Infisical (scoped to this repo, ideally to the production/pr-preview GitHub environments) and read access to the project. The workflows select secrets via project-slug (INFISICAL_PROJECT_SLUG) and per-stage env-slug (prod/dev).
Runtime API URL behavior:
VITE_API_BASE_URL from the Cloudflare api worker domain (api.maple.dev in prd, worker.dev URL for pr-*).bun --filter=@maple/web dev can still use root .env VITE_API_BASE_URL for local API routing..env.exampleapps/api/.env.example.env values are local-only and should stay untracked.The web app expects VITE_API_BASE_URL to point to the API (defaults to http://localhost:3472).
For ingest + key auth, set these at minimum in your root .env when running the ingest gateway:
MAPLE_INGEST_KEY_LOOKUP_HMAC_KEYMAPLE_INGEST_KEY_ENCRYPTION_KEY (required when ingest reads encrypted credentials from Postgres)INGEST_PORTINGEST_FORWARD_OTLP_ENDPOINTMAPLE_INTERNAL_ORG_ID (the org the gateway's own telemetry is filed under; no default)INGEST_FORWARD_TIMEOUT_MSINGEST_MAX_REQUEST_BODY_BYTESINGEST_REQUIRE_TLSINGEST_REPLAY_MAX_SESSION_BYTES (optional; ceiling on the decompressed rrweb
payload one replay session may record, default 1 GiB, 0 disables)Maple persists application state in PostgreSQL:
bun db:up.apps/api/.data/pglite; set
MAPLE_DB_URL=memory:// for an ephemeral database.Migration commands:
bun db:up
bun db:migrate:local
bun run --cwd packages/db db:generate
bun run --cwd packages/db db:studio
CI migrates deployed PlanetScale branches over their direct port before Alchemy deploys the
Workers. See docs/persistence.md for the full workflow.
public + private).MAPLE_INGEST_KEY_ENCRYPTION_KEY (base64-encoded 32-byte key).MAPLE_INGEST_KEY_LOOKUP_HMAC_KEY.Maple supports exactly two auth modes via MAPLE_AUTH_MODE:
clerk
MAPLE_AUTH_MODE=clerkCLERK_SECRET_KEYCLERK_JWT_KEY for networkless verificationCLERK_PUBLISHABLE_KEY for the web appVITE_CLERK_SIGN_IN_URL and VITE_CLERK_SIGN_UP_URLself_hosted
MAPLE_AUTH_MODE=self_hostedMAPLE_ROOT_PASSWORD (required)MAPLE_DEFAULT_ORG_ID (defaults to default)Showing a partial view of a very large repo.
FAQ
maple is a Claude Code plugin with 37 hand-picked skills for monitoring work, indexed on Flowy. Install it with the command on its page. It includes maple-agent-tracing-agno, maple-agent-tracing-claude-agent-sdk, maple-agent-tracing-cloudflare-agents. Its skills do not fire on their own yet. Request auto-invocation to have Flowy route them as you prompt. Free and open source.
Is this plugin yours?
Claim it with GitHubSubmit a pluginPromote it