LocalTrace
Local-first · Agent-first · MIT

Observability for coding agents.

An agent that writes code without seeing the running system is guessing. LocalTrace is a local APM: ingest what your SDKs already emit, store it in SQLite, and let the agent inspect what actually happened.

How it sits on the machine

Your SDKs in. MCP out.

Your app

Existing SDKs

  • OTLP HTTP
  • OTLP gRPC
  • Sentry
  • Datadog

This machine

LocalTrace

  • SQLite store
  • HTTP API
  • Optional UI

Primary interface

MCP

  • list_traces
  • get_trace_sql
  • get_trace_logs

Ingest on :4318 (HTTP / Sentry / Datadog / MCP / UI) and :4317 (OTLP gRPC). Nothing leaves the box.

Why agent-first

Every surface is built so a coding agent can use it, not just so a human can look at it.

The agent

MCP

Primary interface. Query traces, SQL, logs, services. Investigate a failure without opening the UI.

Your existing SDKs

Native ingest

Zero new instrumentation. Point OTLP, Sentry, or dd-trace at localhost. No LocalTrace SDK.

Agent + UI

HTTP API

Same services as MCP. Deterministic, filterable, local. Compact payloads built for agents.

You

Optional UI

A human overlay on the same data. The agent does not need it. MCP is the product.

Native connectors

You do not add a LocalTrace SDK. You do not rewrite instrumentation.

ConnectorPoint at LocalTrace
OpenTelemetry HTTPOTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4318
OpenTelemetry gRPCOTEL_EXPORTER_OTLP_ENDPOINT=http://127.0.0.1:4317
SentrySENTRY_DSN=http://local@127.0.0.1:4318/1
DatadogDD_TRACE_AGENT_URL=http://127.0.0.1:4318

Sending gRPC to :4318 returns 415 with a hint. Use :4317, or set OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf.

The product

That loop is the product.

  1. 1The agent writes a handler
  2. 2You hit the endpoint
  3. 3Telemetry lands in LocalTrace
  4. 4The agent calls list_traces / get_trace_sql
  5. 5It sees the slow query, the 500, the missing span
  6. 6It fixes the code. Repeat.

Cursor · .cursor/mcp.json

{
  "mcpServers": {
    "localtrace": {
      "url": "http://127.0.0.1:4318/mcp"
    }
  }
}

Claude Code · .mcp.json

{
  "mcpServers": {
    "localtrace": {
      "type": "http",
      "url": "http://127.0.0.1:4318/mcp"
    }
  }
}

Quick start

Docker. One process. One file.

Open http://localhost:4318. Data lives in the localtrace-data volume. Early and local-only — wipe and re-ingest when the schema moves. That is intentional.

docker run --rm -p 4318:4318 -p 4317:4317 \
  -v localtrace-data:/app/data \
  ghcr.io/skaznowiecki/localtrace:0.4.0