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.
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.
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
| Setup | CODING_SH_STORE_URL | Blobs |
|---|---|---|
| One box | sqlite:///data/index.db | file:///data/blobs |
| Real traffic | postgres://… | same database |
| Large payloads | postgres://… | 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:
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):
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:
coding.sh sessions --store postgres://… --project myapp
coding.sh search "timeout" --store postgres://… Operate it
/healthzis up,/readyzis ready to write,/metricsis 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=metadatadrops 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.