Docs Production

Production: API apps

Run coding.sh serve on SQLite or Postgres and send traces from API apps with the SDKs or OpenTelemetry.

Run one coding.sh serve process, point it at a database, and send traces from your API apps: OpenAI, Anthropic, the AI SDK, an LLM gateway such as Vercel AI Gateway or OpenRouter, or any OpenTelemetry app. The viewer, CLI, MCP tools, datasets and experiments work on the same database.

For a team's coding agents on one machine, start with Self-host for a team: one docker run, no keys to make.

Run serve (built)

Make one ingest key per app and one read key for people. Each key is printed once.

shell
coding.sh serve keygen --project myapp          # csh_ik_… for the app
coding.sh serve keygen --project myapp --read   # csh_rk_… for people

Then start serve with a store URL. It creates its tables on first start. With a volume on /data and no keys set, the first start makes a key pair there and prints it instead.

shell
docker run -d -p 4318:4318 \
  -e CODING_SH_STORE_URL='postgres://user:pass@db.example.com:5432/coding?sslmode=require' \
  -e CODING_SH_INGEST_KEYS='myapp:csh_ik_…' \
  -e CODING_SH_READ_KEYS='*:csh_rk_…' \
  ghcr.io/jackulau/coding.sh
curl -s http://127.0.0.1:4318/readyz

Pick a store

SetupCODING_SH_STORE_URLBlobs
One boxsqlite:///data/index.dbfile:///data/blobs
Real trafficpostgres://…same database
Large payloadspostgres://…s3://bucket/blobs?region=… (S3, R2, MinIO)

Postgres and S3 come from plugin packages, so the core stays dependency-free. The Docker image includes both.

Send traces

Node, with @codingdotsh/sdk:

ts
import OpenAI from "openai";
import { observe } from "@codingdotsh/sdk";

// CODING_SH_URL=https://obs.example.com  CODING_SH_INGEST_KEY=csh_ik_…
const openai = observe(new OpenAI()); // or new Anthropic()

Python: coding_sh.observe(client). Any OpenTelemetry SDK, a Vercel AI Gateway trace drain, or a gateway's own OpenTelemetry export (LiteLLM, Cloudflare, Portkey):

shell
OTEL_EXPORTER_OTLP_ENDPOINT=https://obs.example.com
OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer%20csh_ik_…"

The key decides the project. Group a conversation with sessionId or gen_ai.conversation.id.

Use it

Open https://obs.example.com/?t=csh_rk_… for the viewer. The CLI and MCP server read the same store:

shell
coding.sh sessions --store postgres://… --project myapp
coding.sh search "timeout" --store postgres://…

Operate it

  • /healthz is up, /readyz is ready to write, /metrics is Prometheus.
  • One writer replica. Add read-only replicas with --role viewer.
  • A full queue answers 429 with Retry-After. Retries never duplicate.
  • Secrets are redacted before writing. CODING_SH_CAPTURE_MODE=metadata drops message text.
  • Recipes for Compose, Fly, Railway and Render are in docs/production.

Packages: @codingdotsh/sdk and the store plugins are on npm, and the image ghcr.io/jackulau/coding.sh is published for each release from 0.1.2 on. The Python SDK, coding-sh, is not on PyPI yet: install it from a checkout with pip install -e packages/sdk-python.