CodeRadar · Errors · Traces · Alerts · for the whole Goodventures portfolio · v0.x · early

See every error before it sees you.

CodeRadar is the portfolio's error tracker, distributed tracer, and alerting plane. One ingest pipeline, every product, every environment. Search and filter the whole stack in real time.

Sentry tells you what broke. Datadog charges per host to do the same. CodeRadar is built for the inside of one venture studio: every product becomes a project under one Goodventures org, errors flow from each app's SDK into a unified backend, and the dashboard lets you scrub through traces and triage incidents across the entire fleet without a billing meter running in the background.

live · ingest · /v1/events
14 projects 2.4k/s 847,113 last 24h
14:22:08.421 error TypeError: Cannot read properties of undefined apps/dashboard/src/Errors.tsx:284 truecom
14:22:08.198 warning Slow database query (1240ms) apps/api/src/billing.py:91 veritize
14:22:07.913 fatal unhandled rejection: ECONNREFUSED redis:6379 packages/queue/dist/index.js:42 cloudswarm
14:22:07.602 info deploy completed: [email protected] scripts/release.go:118 relaygate
14:22:07.144 error SqlError: duplicate key value violates unique constraint apps/portal/src/users.go:212 relayone
14:22:06.811 warning Sampler dropped 12 events (rate-limit) packages/sdk/src/sampler.ts:67 framebright
14:22:06.402 error FetchError: invalid_grant packages/auth-clerk/src/refresh.ts:33 canadianclaw
14:22:06.018 fatal panic: runtime error: index out of range internal/parser/lex.go:88 heroa
selected event · ev_01HZRX4D2KQ7
projecttruecom
envproduction
levelerror
typeTypeError
messageCannot read properties of undefined (reading 'amount')
user.idu_RR91x...
runtimenode 22.5.0
trace_idb7f3...d201
fingerprintfp_e3a9c1
seen17 in last 5m · 3 users
first7m ago
illustrative — actual events flow at the rate your SDKs ship them. retention: 30d events · 90d traces · 1y aggregates
14 portfolio projects
·
4 first-class SDKs
·
W3C tracecontext distributed traces
·
Postgres + ClickHouse storage
·
$0 inside the org
What CodeRadar is

Error tracking, distributed tracing, and alerting — built for the whole portfolio at once.

One ingest, one query backend, one dashboard. Every product is a project, every project shares the same infrastructure, every error and trace is searchable across the fleet in real time. Built on the open CodeWatch core, repackaged as the portfolio's Sentry-equivalent.

SDK
node · browser
python · go
Ingest API
Hono · OTLP-native
ClickHouse
events · traces
fingerprint dedup
PostgreSQL
metadata
projects · users
Dashboard + Alerts
Next.js 15 · SSE
Real-time — SSE stream from ingest to dashboard, sub-second. Multi-tenant — one org, every product is a project, isolation by row + JWT. Open core — Apache 2.0 ingest + dashboard; MIT SDKs.
Capabilities

Twelve features that ship in the box.

CodeRadar absorbs the day-one Sentry workflow — capture, search, triage, alert — and adds the operating model the Goodventures portfolio actually needs: one org, every product as a project, sampling and quotas under your control, source-map auto-resolution from your release pipeline.

Ingest pipeline

Hono + TypeScript OTLP-native edge service. Accepts batched events from every SDK, fingerprints in ClickHouse, broadcasts via Redis pub/sub. Backpressure-aware with per-project quotas.

live · apps/ingest-api

Query backend

PostgreSQL for metadata (projects, users, releases, alert rules). ClickHouse for the high-volume event log. The split keeps the metadata store fast and the event store cheap to scale.

live · postgres + clickhouse

Real-time dashboard

Next.js 15 dashboard streams over Server-Sent Events. New errors appear in the feed within a second of being captured. Pin a query, watch it update live.

live · apps/dashboard

Search and filter

Query language: project:truecom level:error in:5m user.id:u_*. Filter on level, environment, release, runtime, browser, OS, tags, fingerprint, user, country.

live · /v1/query

Smart alerting

Threshold rules (rate, count, percent change) and pattern rules (new fingerprint, regression). Channels: Slack, email, generic webhook. PagerDuty integration on the roadmap.

live slack/email/webhook · roadmap pagerduty

Source-map auto-resolution

Upload source maps on every release via the SDK release hook, or have CodeRadar fetch them from a release URL. Browser stack traces resolve to original source by default.

live · /v1/sourcemaps

Breadcrumbs

Each captured error carries the last 100 client-side breadcrumbs: console messages, fetch calls, navigation events, custom tags. Configurable buffer per SDK.

live · packages/sdk-node, sdk-browser

Distributed traces

W3C tracecontext on every outbound request from the SDK. Cross-service traces through OTLP. View span tree, timing waterfall, service map for a single trace.

live · W3C tracecontext + OTLP

Session replay roadmap

Lightweight DOM snapshot + diff stream attached to errors so you can replay the user's last 30 seconds before the crash. Behind a feature flag in early-access. Off by default.

roadmap early-access

Quotas + sampling

Per-project event allowance. Per-environment sample rate. Adaptive sampling that holds error events at 100% and traces at the configured rate. Burn-rate alarms when a project nears its quota.

live · CODERADAR_SAMPLE_RATE

Multi-tenant routing

One Goodventures org, every product is a project. Project DSN routes events into the right tenant. Row-level isolation in Postgres + ClickHouse keyed on project_id.

live · one-org / many-projects

Auth + access

Clerk-backed sign-in at app.coderadar.app. [email protected] is org admin. Per-project member assignment via the org settings.

live · Clerk
Query

Search across every project. Filter to one. Pin it. Live-update it.

Fourteen products, one query box. Filter by project, level, environment, release, fingerprint, user, runtime, browser, country, tag, or any custom attribute the SDK shipped. Saved queries appear in the dashboard side panel; pinned queries stream new matches over SSE.

level:error project:truecom,relayone in:5m env:production
ev_4D2KerrorTypeError: Cannot read properties of undefined (reading 'amount')truecom17 events · 3 users
ev_91xRfatalunhandled rejection: ECONNREFUSED redis:6379cloudswarm4 · 1
ev_a3c1errorSqlError: duplicate key value violates unique constraint "users_email_key"relayone12 · 9
ev_7e2berrorFetchError: invalid_grant from clerk.relayone.ai/oauth/tokenrelayone8 · 6
ev_b801warningSlow database query (1240ms) on billing.invoice_itemsveritize22 · -
ev_d301errorRangeError: Maximum call stack size exceededcanadianclaw3 · 2
ev_9c12fatalpanic: runtime error: index out of range [3] with length 0heroa2 · -
71 events · 18 fingerprints · 18 users · last 5 minutes save query · pin to dashboard · create alert from query
The Goodventures org model

One org. Every product is a project. [email protected] is admin.

CodeRadar is portfolio-native. There isn't a separate Sentry account per product, no per-project billing meter, no SSO sprawl. Sign in with the Goodventures Clerk session, see every project, switch between them with a project picker. Members are added to projects, not to orgs — there is only ever one org.

org / admin Goodventures
heroanode + go
deeptappython
parentproofnode + browser
actiumnode + browser
attestiknode + browser
avitranode + browser
gvlabbrowser
Integrations

Five lines of code. Every error, every trace.

Install the SDK, set the DSN, instrument runs automatically. Express, Next.js, Hono, FastAPI, and net/http frameworks are auto-instrumented. Browser SDK is a single script tag. Detailed setup guides at /docs/sdks/.

// 1. install
// $ pnpm add @coderadar/sdk

// 2. init at process boot
import { init } from "@coderadar/sdk";

init({
  dsn:         process.env.CODERADAR_DSN,
  project:     "truecom",
  environment: process.env.NODE_ENV,
  release:     process.env.RELEASE_SHA,
  sampleRate:  1.0,           // errors always 100%
  tracesSampleRate: 0.2,    // 20% of traces
});

// 3. that's it. Errors auto-capture, traces auto-instrument,
// W3C tracecontext propagates across outbound fetch / undici.

// 4. (optional) Express / Hono middleware
import { errorHandler } from "@coderadar/sdk/express";
app.use(errorHandler());
// option A — script tag (autoload, ~12 KB gzipped)
<script
  src="https://cdn.coderadar.app/v1/sdk.js"
  data-project="truecom"
  data-env="production"
  data-release="[email protected]">
</script>

// option B — npm package (typed, tree-shakable)
// $ pnpm add @coderadar/browser

import { init } from "@coderadar/browser";
init({
  dsn:         "https://[email protected]/12",
  project:     "truecom",
  environment: "production",
  release:     "[email protected]",
});

// captures unhandled errors, unhandled promise rejections,
// console errors, and (optionally) fetch breadcrumbs.
# 1. install
# $ pip install coderadar

# 2. init at process boot
import coderadar
import os

coderadar.init(
    dsn         = os.environ["CODERADAR_DSN"],
    project     = "veritize",
    environment = os.environ.get("ENV", "dev"),
    release     = os.environ.get("RELEASE_SHA"),
    sample_rate = 1.0,
    traces_sample_rate = 0.2,
)

# 3. unhandled exceptions auto-capture.
#    FastAPI / Flask / Django middleware available:
from coderadar.fastapi import CodeRadarMiddleware
app.add_middleware(CodeRadarMiddleware)
// 1. install
// $ go get github.com/RelayOne/coderadar/sdks/go/coderadar

// 2. init at main()
package main

import (
    "os"
    "github.com/RelayOne/coderadar/sdks/go/coderadar"
)

func main() {
    client, _ := coderadar.NewClient(coderadar.Config{
        DSN:         os.Getenv("CODERADAR_DSN"),
        Project:     "relaygate",
        Environment: os.Getenv("ENV"),
        Release:     os.Getenv("RELEASE_SHA"),
        SampleRate:        1.0,
        TracesSampleRate:  0.2,
    })
    defer client.Flush()

    // net/http auto-wrap; chi / gin / echo helpers in submodules
    handler := coderadar.WrapHandler(yourMux)
    http.ListenAndServe(":8080", handler)
}
SDK package names live: @coderadar/sdk, @coderadar/browser, coderadar (PyPI), github.com/RelayOne/coderadar/sdks/go/coderadar. Each SDK ships its own setup page.
Alerts

Rules and channels. No magic, no inscrutable ML.

Alert rules are explicit: a query, a threshold, a channel. Two kinds: threshold rules (fire when an event count or rate crosses a number) and pattern rules (fire on new fingerprints, regressions, or burn-rate spikes). The rule list is a checklist. The channel list is a checklist. Wire them up in the dashboard or via YAML in the project repo.

Fatal in production — page on-call
when level:fatal env:production count > 0 in 1m
Spike in any project (rate > 50/min)
when level:error count > 50 in 5m group_by:project
New fingerprint in production
when fingerprint:new env:production
Regression of a previously resolved issue
when fingerprint.was_resolved == true
Quota burn rate > 2x
when project.quota_remaining_pct < 20 in 24h
Slow span p95 > 1s
when span.duration_p95 > 1000ms group_by:operation
Channels
SL Slack #alerts-prod webhook
WH Custom webhook https://...
PD PagerDuty roadmap
MS Microsoft Teams roadmap
SM SMS / Twilio roadmap
Compared to

CodeRadar vs Sentry vs Datadog — honest table.

CodeRadar is younger, narrower, and free inside the org. Sentry is the gold standard for error tracking; Datadog is broader and pricier. The table below tries not to oversell.

Capability CodeRadar Sentry Datadog APM
Error tracking yes yes via separate "Error Tracking" SKU
Distributed traces (W3C) yes yes yes
Real-time SSE feed yes live mode in newer plans yes
Source-map auto-resolution yes yes browser only
Smart alerting (rules + channels) yes (slack/email/webhook) yes (15+ channels) yes (20+ channels)
PagerDuty roadmap yes yes
Session replay roadmap (early-access) yes yes (RUM)
Self-host (Apache 2.0) yes (CodeWatch core) Functional Source License no
Cost inside Goodventures org $0 / always Team plan ~$26/mo + per-event ~$31/host/mo + per-span
Auto-fix PRs (AI pipeline) via CodeWatch core (off by default) no no
SOC 2 in progress yes yes
Maturity v0.x — early 12 years 15+ years
Honest framing

CodeRadar is replacing Sentry inside our portfolio for one reason: cost-and-control. We are not pretending CodeRadar matches Sentry's depth on day one. We are saying we can get to 80% of the workflow on infrastructure we already operate, charge ourselves nothing, and skip the per-event meter that punishes high-throughput services. If you are not Goodventures, Sentry is still the right call.

Portfolio seams

CodeRadar fits with the rest of the stack.

Every Goodventures product can stand alone, but the seams between them compound. Here are the four CodeRadar absorbs first. Graceful degradation is the rule — none of these is required.

CodeRadar + RelayGate
RelayGate emits OTLP traces for every AI request that passes through. CodeRadar ingests them so you can see model latency, backend driver, route decision, and signed-receipt status in the same trace tree as the rest of your app.
live
CodeRadar + RelayOne
RelayOne fleet events (deploys, config changes, gateway restarts) write to CodeRadar as level:info events, so deployment correlation with errors is a single query.
live
CodeRadar + Veritize
Veritize drift events (model output drift, schema drift) post to a Veritize project in CodeRadar. Alert rules fire on drift the same way they fire on TypeErrors.
live
CodeRadar + CodeWatch core
CodeRadar is the operating shell on top of the open CodeWatch Apache 2.0 core. The AI-fix pipeline (triage → diagnosis → multi-pass voting → PR) ships in CodeWatch and is opt-in inside CodeRadar — off by default.
live + roadmap
CodeRadar + Actium Studio
Frontend-published Actium Studio sites embed the browser SDK so authoring-time errors and end-user crashes both flow into the same dashboard.
roadmap
CodeRadar + CloudSwarm
CloudSwarm agent runs emit per-step events tagged with the agent template. Failed agent runs surface as CodeRadar errors with the full plan + tool-call trace.
roadmap
CodeRadar + TrueCom
x402 settlement failures (rejected receipts, signature mismatches, retry-budget exhaustion) post as CodeRadar events in the truecom project so settlement health is a first-class alert source.
live
CodeRadar + Heroa
Sovereign BC-Canadian deployments of CodeRadar run on the Heroa substrate so customer data never leaves the jurisdiction. Available on the Enterprise track when CodeRadar is offered externally.
roadmap
Pricing

$0 for Goodventures projects. No event meter.

CodeRadar is operated by us, for us. Every product in the portfolio gets a project at no cost. Hard quota per project keeps any one app from drinking the lake; the limits are sized for normal-shaped traffic, not tuned to push you onto a paid tier.

Portfolio internal

$0/ project / forever — for any product under the Goodventures org

The full feature set with no event meter, no per-host fee, and no support tier upsell. Sized for the portfolio, paid for by the portfolio.

included quotas (per project)
  • 5M events / month — soft burn-rate alarm at 80%
  • 1M traces / month — adaptive sampling kicks in over the cap
  • 30-day event retention, 90-day trace retention, 1-year aggregates
  • Unlimited projects within the org
  • Unlimited members via the Goodventures Clerk session
  • Real-time event stream (SSE)
  • W3C tracecontext distributed traces
  • Source-map auto-resolution
  • Smart alerts (Slack, email, webhook)
  • Per-project sampling and quotas
  • Source code links from stack traces
  • Release tagging + regression detection
  • API access for ingest + query
  • Member-level project access controls
  • SOC 2 evidence pack on request in progress
Outside the org

If you are not a Goodventures product, CodeRadar is not currently offered as a paid product. The open CodeWatch core is Apache 2.0 and you can self-host the same pipeline. A managed CodeRadar tier for portfolio adjacent companies (Goodventures alums, partners) is on the roadmap.

Architecture

Polyglot monorepo. TypeScript at the edge, Python in the middle, TypeScript at the surface.

CodeRadar is built on the open CodeWatch Apache 2.0 core. The data path is intentionally simple: capture at the edge, store in two databases optimized for their workload, surface in a streaming dashboard, route alerts. The optional AI auto-fix pipeline lives in its own Python service so it can scale independently and stay off when not in use.

SDK layer

Per-language clients with a shared wire format. Node + Browser written in TypeScript, Python in pure Python (no C extension), Go in pure Go. All four use the same OTLP-shaped event envelope so the ingest API treats them identically.

live · packages/sdk-node, sdk-browser, sdk-python; sdks/go

Ingest API

Hono on Node. Accepts batched events on POST /v1/events. Writes to ClickHouse via the native binary protocol. Publishes a Redis pub/sub message per accepted event so the dashboard SSE can pick it up. Backpressure-aware with per-project rate buckets.

live · apps/ingest-api

ClickHouse

Single-table event log keyed on (project_id, timestamp, fingerprint). Columnar, mergeable, queryable in tens of milliseconds for million-row windows. Materialized views for the most common dashboards (top errors, count-per-minute, p95 latency).

live · events + traces + spans

PostgreSQL

Metadata. Projects, members, alert rules, releases, comments, saved queries. Postgres because alert evaluation joins these every minute and Postgres is faster than ClickHouse for that shape. Migrations live in sql/migrations/ and run on boot.

live · Postgres 16

Dashboard

Next.js 15 App Router. Streams the live feed over Server-Sent Events, paginates historical queries through a server action that hits ClickHouse directly. Shadcn-style component primitives, no client-side global state framework, JS bundle stays under 180 KB.

live · apps/dashboard

Fix pipeline (opt-in)

Optional AI fix pipeline lives in apps/fix-pipeline as a FastAPI service. Triages incoming errors with Claude Haiku, diagnoses with Claude Sonnet, generates three candidate fixes, votes, validates against test runners, and opens a PR via GitHub App. Off by default. Enable per-project.

opt-in · CODERADAR_AI_PIPELINE_ENABLED
Why two databases

An error tracker writes a lot more than it reads (most events are never opened). ClickHouse is great at that shape. An alert engine reads a lot more than it writes (every minute, evaluate every rule against the recent window). Postgres is great at that shape. Putting them in one database compromises both. Keeping them separated keeps each in the workload it was built for.

Data model

One event, one trace, one breadcrumb. Plain.

CodeRadar's wire format is a strict subset of OpenTelemetry's log-record + span model with a few additions for error-tracker workflows (fingerprint, release, breadcrumbs, user context). Anyone fluent in Sentry's or OTLP's data shapes is at home in five minutes.

// POST /v1/events
{
  "event_id":    "ev_01HZRX4D2KQ7",
  "project":     "truecom",
  "timestamp":   "2026-04-26T14:22:08.421Z",
  "level":       "error",             // fatal | error | warning | info | debug
  "environment": "production",
  "release":     "[email protected]",
  "runtime":     { "name": "node", "version": "22.5.0" },
  "exception": {
    "type":    "TypeError",
    "value":   "Cannot read properties of undefined (reading 'amount')",
    "stacktrace": [
      { "file": "apps/dashboard/src/Errors.tsx", "line": 284, "function": "renderRow" },
      // ... more frames
    ]
  },
  "user":        { "id": "u_RR91xK", "email_hash": "sha256:..." },
  "trace_id":    "b7f3a44d8e21c3d201",
  "span_id":     "8e21c3d201",
  "breadcrumbs": [ /* up to 100 — see Breadcrumb tab */ ],
  "tags":        { "region": "us-central1", "customer": "acme" },
  "fingerprint": [ "TypeError", "Errors.tsx", "renderRow" ]   // optional override
}
// trace = collection of spans sharing trace_id
{
  "trace_id": "b7f3a44d8e21c3d201",
  "spans": [
    {
      "span_id":    "5a2c",
      "parent_id":  null,
      "name":       "GET /api/billing/invoices",
      "start":      "...:08.150Z",
      "end":        "...:08.421Z",
      "attributes": { "http.status_code": 500, "http.route": "/api/billing/invoices" }
    },
    {
      "span_id":    "5a2d",
      "parent_id":  "5a2c",
      "name":       "db.query: select * from invoices...",
      "start":      "...:08.180Z",
      "end":        "...:08.395Z",
      "attributes": { "db.system": "postgresql", "db.statement": "SELECT ..." }
    },
    {
      "span_id":    "5a2e",
      "parent_id":  "5a2c",
      "name":       "render: dashboard.Errors",
      "start":      "...:08.398Z",
      "end":        "...:08.421Z",
      "events": [
        { "name": "exception", "event_id": "ev_01HZRX4D2KQ7" }
      ]
    }
  ]
}
// up to 100 breadcrumbs are attached to each captured event
[
  { "t": "...:08.041Z", "category": "navigation", "message": "/dashboard → /dashboard/billing" },
  { "t": "...:08.085Z", "category": "http",       "data": { "method": "GET", "url": "/api/billing/invoices", "status": 500 } },
  { "t": "...:08.140Z", "category": "console",    "level": "warn", "message": "Falling back to cached invoices" },
  { "t": "...:08.205Z", "category": "ui.click",   "data": { "target": "button.retry", "text": "Retry" } },
  { "t": "...:08.298Z", "category": "http",       "data": { "method": "GET", "url": "/api/billing/invoices", "status": 500 } },
  { "t": "...:08.420Z", "category": "render",     "message": "Errors.tsx unmount → mount with empty rows" }
]
// Categories: navigation, http, console, ui.click, ui.input, render, custom.*
# YAML — checked into the project repo, applied by `coderadar alerts apply`
# Or configure in the dashboard at /alerts/new

version: 1
project: truecom

rules:
  - name:     fatal_in_production
    when:     level:fatal env:production
    threshold: count > 0 in 1m
    channels: [slack-prod, email-eric]
    cooldown: 5m

  - name:     spike_any
    when:     level:error
    threshold: count > 50 in 5m
    group_by: [project]
    channels: [slack-prod]

  - name:     new_fingerprint
    when:     fingerprint:new env:production
    channels: [slack-prod]

channels:
  - id: slack-prod
    type: slack
    webhook: ${SLACK_WEBHOOK_URL}
  - id: email-eric
    type: email
    to:   [[email protected]]
Full schemas in the API reference. OTLP-compat endpoint at /v1/otlp for non-CodeRadar SDKs.
More integrations

Frameworks. Logging. Custom captures.

If your framework is not auto-instrumented, you can capture errors with captureException(). If you have a logger, the SDK exposes a transport for popular ones (pino, winston, structlog, zap). Browser-side fetch wraps cleanly. Below: the patterns we hit most often inside the portfolio.

// instrumentation.ts — Next.js 15 App Router
export async function register() {
  if (process.env.NEXT_RUNTIME === "nodejs") {
    const { init } = await import("@coderadar/sdk");
    init({
      dsn: process.env.CODERADAR_DSN,
      project: "truecom",
      release: process.env.VERCEL_GIT_COMMIT_SHA,
    });
  }
}

// app/global-error.tsx — Next 15 server error boundary
"use client";
import { captureException } from "@coderadar/sdk";
export default function GlobalError({ error }) {
  captureException(error);
  return <html>...</html>;
}
import { Hono } from "hono";
import { honoMiddleware } from "@coderadar/sdk/hono";

const app = new Hono();
app.use("*", honoMiddleware({
  project: "relayone",
  release: process.env.RELEASE_SHA,
}));

app.get("/api/me", async (c) => {
  const u = await getUser(c);   // throws? auto-captured.
  return c.json(u);
});
from fastapi import FastAPI
from coderadar.fastapi import CodeRadarMiddleware
import coderadar
import os

coderadar.init(
    dsn=os.environ["CODERADAR_DSN"],
    project="veritize",
    release=os.environ.get("RELEASE_SHA"),
)

app = FastAPI()
app.add_middleware(CodeRadarMiddleware)

# manual capture inside a handler
from coderadar import capture_exception, capture_message, set_user

@app.get("/billing/{id}")
async def billing(id: str):
    try:
        return await get_invoice(id)
    except InvoiceMissing as e:
        capture_exception(e, tags={"invoice_id": id})
        raise
package main

import (
    "github.com/go-chi/chi/v5"
    "github.com/RelayOne/coderadar/sdks/go/coderadar"
    "github.com/RelayOne/coderadar/sdks/go/coderadar/chimid"
)

func main() {
    coderadar.NewClient(coderadar.Config{
        DSN: os.Getenv("CODERADAR_DSN"),
        Project: "relaygate",
    })

    r := chi.NewRouter()
    r.Use(chimid.Middleware())  // captures panics + 500s
    r.Get("/healthz", healthz)
    http.ListenAndServe(":8080", r)
}
// every SDK exposes capture* helpers

// node / browser
import { captureException, captureMessage, setUser, addBreadcrumb } from "@coderadar/sdk";

setUser({ id: user.id, segment: user.tier });
addBreadcrumb({ category: "checkout", message: "opened cart" });

try {
  await finalizeCheckout(cart);
} catch (err) {
  captureException(err, { tags: { stage: "checkout" } });
  throw err;
}

captureMessage("Inventory desync detected", { level: "warning" });
Tab switcher reuses the same engine as the SDK init block above.
Shape

The shape of one observability plane.

Every cell below is a feature that ships in the box, with the file path or service name where it lives. Roadmap items are flagged. No magic, no reading-tea-leaves about what is and isn't in v0.

Ingest endpoint

OTLP-shape, batched, idempotent.

apps/ingest-api/src/routes/events.ts

Trace ingest

OTLP /v1/traces.

apps/ingest-api/src/routes/traces.ts

Source-map upload

POST /v1/sourcemaps.

apps/ingest-api/src/routes/sourcemaps.ts

Release tagging

POST /v1/releases.

apps/ingest-api/src/routes/releases.ts

Fingerprinting

Stable, type+frame-based.

packages/shared/fingerprint.ts

Dedup

ClickHouse ReplacingMergeTree.

sql/clickhouse/events.sql

Live SSE

Per-project topic, sub-second.

apps/dashboard/app/api/stream

Search query lang

field:value op:val + lucene-ish.

packages/shared/query.ts

Saved queries

Per-user, per-project.

postgres.saved_queries

Pinned queries

Streaming, dashboard widget.

apps/dashboard/components/PinnedQuery

Breadcrumbs

Up to 100, configurable.

packages/sdk-*/breadcrumbs

User context

id + email_hash + tier.

packages/sdk-*/user.ts

Tags / attributes

Per-event arbitrary k/v.

packages/sdk-*/tags.ts

Releases

SHA, environment, deployed_at.

postgres.releases

Regression detect

Was-resolved + new-event.

apps/alert-engine/regression.ts

Alert rules

Threshold + pattern.

postgres.alert_rules

Slack channel

Webhook + block-kit body.

packages/channels/slack.ts

Email channel

Resend + templated body.

packages/channels/email.ts

Webhook channel

HTTP POST, retry+jitter.

packages/channels/webhook.ts

PagerDuty roadmap

Events API v2.

packages/channels/pagerduty.ts

Quota engine

Per-project hard + soft.

apps/ingest-api/quota.ts

Sampling

Adaptive + manual.

packages/sdk-*/sampler.ts

Auth (Clerk)

Org + projects + members.

apps/dashboard/middleware.ts

REST API

Read-only ingest + query.

apps/ingest-api/src/routes/v1

Session replay roadmap

DOM snapshot diff stream.

packages/replay-browser

AI fix pipeline

Triage → diagnose → vote → PR.

apps/fix-pipeline (FastAPI)

Self-host (Helm)

Compose + Helm chart.

deploy/helm/coderadar

Audit log

Who-did-what on rules + projects.

postgres.audit_log
Operating model

A real example of CodeRadar set up across the portfolio.

Everything below is the actual configuration the Goodventures portfolio uses — pasted from the project repos with secrets redacted. Same pattern for every product: SDK at boot, environment per deploy target, release tagged on each push, alert rules in .coderadar/alerts.yaml, source maps uploaded by CI.

truecom — Node + Browser, Express + Next.js
// apps/portal/instrumentation.ts
import { init } from "@coderadar/sdk";

export async function register() {
  if (process.env.NEXT_RUNTIME === "nodejs") {
    init({
      dsn:         process.env.CODERADAR_DSN_TRUECOM,
      project:     "truecom",
      environment: process.env.NODE_ENV ?? "development",
      release:     process.env.RELEASE_SHA,
      tracesSampleRate: 0.2,
    });
  }
}
relaygate — Go binary, net/http
// cmd/relaygate/main.go
import "github.com/RelayOne/coderadar/sdks/go/coderadar"

func main() {
    cr, _ := coderadar.NewClient(coderadar.Config{
        DSN:         os.Getenv("CODERADAR_DSN_RELAYGATE"),
        Project:     "relaygate",
        Environment: os.Getenv("ENV"),
        Release:     buildVersion + "@" + buildCommit,
        SampleRate:        1.0,
        TracesSampleRate:  0.2,
    })
    defer cr.Flush()

    // wraps every HTTP handler with capture-on-panic + 500-detect
    handler := coderadar.WrapHandler(router)
    http.ListenAndServe(":8080", handler)
}
veritize — Python FastAPI + cron workers
# apps/api/src/main.py
import coderadar
from coderadar.fastapi import CodeRadarMiddleware
from fastapi import FastAPI

coderadar.init(
    dsn=os.environ["CODERADAR_DSN_VERITIZE"],
    project="veritize",
    environment=os.environ.get("ENV"),
    release=os.environ.get("RELEASE_SHA"),
    traces_sample_rate=0.2,
)

app = FastAPI()
app.add_middleware(CodeRadarMiddleware)

# cron worker — manual capture for non-HTTP runs
from coderadar import capture_exception, set_tag

def drift_scan_job():
    set_tag("job", "drift_scan")
    try:
        run_drift_scan()
    except Exception as e:
        capture_exception(e)
        raise
.coderadar/alerts.yaml — checked into every project repo
version: 1
project: truecom

rules:
  - name: fatal_in_production
    when: level:fatal env:production
    threshold: count > 0 in 1m
    channels: [slack-prod, email-eric]
    cooldown: 5m

  - name: spike_5x
    when: level:error env:production
    threshold: rate > baseline * 5 in 5m
    channels: [slack-prod]

  - name: new_fingerprint
    when: fingerprint:new env:production
    channels: [slack-prod]

  - name: regression
    when: fingerprint.was_resolved == true
    channels: [slack-prod, email-eric]

channels:
  - id: slack-prod
    type: slack
    webhook: ${SLACK_WEBHOOK_URL}
  - id: email-eric
    type: email
    to:   [[email protected]]
CI — upload source maps + tag release on push
# cloudbuild.yaml — runs after the deploy step
- name: 'gcr.io/google.com/cloudsdktool/cloud-sdk:slim'
  entrypoint: 'bash'
  args:
    - '-c'
    - |
      pnpm dlx @coderadar/cli releases create \
        --project=truecom \
        --release=truecom@$SHORT_SHA \
        --commit=$COMMIT_SHA

      pnpm dlx @coderadar/cli sourcemaps upload \
        --project=truecom \
        --release=truecom@$SHORT_SHA \
        --rewrite \
        --strip-common-prefix \
        dist/static/js/

      pnpm dlx @coderadar/cli alerts apply \
        --file=.coderadar/alerts.yaml
Incident workflow

From error fired to fingerprint resolved.

An error doesn't disappear when an alert fires. It travels through a small but explicit lifecycle so the same fingerprint doesn't burn the on-call twice. Below: the eight states the system understands, and what triggers each transition.

1. captured   SDK ships event to ingest
SDK buffers locally, ships in batches every 5s or every 100 events. Idempotent on event_id so retries don't double-count.
2. ingested   written to ClickHouse
Fingerprint computed from (type, file, function, line). Existing fingerprint? increment counters. New fingerprint? insert and emit fingerprint:new pub/sub.
3. alerted   rule matched, channel notified
Alert engine evaluates rules every minute (default) and on pub/sub topics for instant rules. Cooldown per rule prevents storm.
4. acknowledged   on-call clicks "ack" in dashboard or Slack
Quiets future alerts on the same fingerprint until the next state transition. Records who-and-when in audit log.
5. triaged   assigned and tagged with severity
Assignee gets the dashboard mention. Severity is freeform (low / med / high / sev1 — projects pick their own scheme).
6. fix in flight   PR linked or AI pipeline started
Manual link to a PR, or trigger the optional AI fix pipeline (off by default; reads source, generates candidates, runs tests, opens PR).
7. resolved   PR merged or manually closed
If linked PR merged, auto-resolves. Manual close is allowed with a note. Resolved fingerprints stop alerting until step 8.
8. regressed   resolved fingerprint fires again
Pattern rule fingerprint.was_resolved == true triggers. Reopens the issue, alerts again, marks the release-window for visibility.
All states are optional

If your project doesn't want triage, you can stop after step 3. If you want to skip alert ack, default cooldowns work. The lifecycle is a tool, not a process you're forced to run.

Quick reference

Environment variables and DSN format.

CodeRadar SDKs read configuration from explicit init params or environment variables. The DSN encodes the project, ingest host, and public token. Tokens are scoped to a project + an ingest write capability — never grant query access.

// DSN — public token for write-only ingest
https://PUBLIC_KEY@ingest.coderadar.app/PROJECT_ID

// example
https://[email protected]/12

// the public key is safe to expose in browser bundles.
// it is per-project, write-only, and rate-limited per origin.
// rotate any time at app.coderadar.app/settings/keys.

// for stricter setups, use the IP-allowlisted "server-only" DSN
// which won't accept events without a Bearer token cookie.
https://PUBLIC_KEY:SECRET@ingest.coderadar.app/PROJECT_ID?mode=server
# every SDK reads these env vars by default

CODERADAR_DSN="https://[email protected]/12"
CODERADAR_PROJECT="truecom"            # or set in init() — env var wins
CODERADAR_ENVIRONMENT="production"     # dev | staging | production | preview-* | ...
CODERADAR_RELEASE="[email protected]"    # SHA or semver tag
CODERADAR_SAMPLE_RATE="1.0"            # 0.0–1.0 — errors
CODERADAR_TRACES_SAMPLE_RATE="0.2"     # 0.0–1.0 — traces
CODERADAR_DEBUG="false"               # SDK self-logging
CODERADAR_BUFFER_SIZE="1048576"        # bytes, server SDKs only
CODERADAR_FLUSH_INTERVAL="5000"        # ms

# dual-accept legacy CODEWATCH_* env vars (90-day window)
CODEWATCH_DSN=# still accepted; logs deprecation warning at boot
# the coderadar CLI
$ pnpm add -g @coderadar/cli

# list projects you can see
$ coderadar projects list

# tail events from one project
$ coderadar tail --project=truecom --level=error

# upload a sourcemap manually
$ coderadar sourcemaps upload \
    --project=truecom \
    [email protected] \
    --file=dist/static/js/main.abc123.js.map

# apply alert rules from a YAML file
$ coderadar alerts apply --file=.coderadar/alerts.yaml

# open a project in the dashboard
$ coderadar open truecom
CLI is shipped as @coderadar/cli. Source at apps/cli in the CodeWatch repo.
FAQ

Common questions, honest answers.

Is CodeRadar a Sentry replacement?

For Goodventures-internal use, yes — that is the entire reason it exists. For everyone else, Sentry is more mature, deeper on session replay, deeper on integrations. We are not pretending otherwise.

How is this different from CodeWatch?

CodeWatch is the open-source error-tracking + AI-fix-pipeline core. CodeRadar is the operating shell on top of it: domain, branding, portfolio-aware project model, alerting workflows. Same code path; different presentation.

Why $0?

Because the portfolio is the customer. The infrastructure is shared, the operations team is shared, the storage is shared. Adding a per-event meter on top would be us paying ourselves to count events. We just put a hard quota on each project instead.

What about scale?

ClickHouse handles billions of events per day per cluster. The bottleneck is the ingest API's egress to ClickHouse, which is horizontally scalable. Today we run one ingest pod and one Postgres; both scale before quota turns into a real problem.

Where does data live?

GCP us-central1 by default. EU and BC-Canadian regions on the roadmap (BC via the Heroa substrate). No data leaves the cluster except via webhook/email channels you configured.

Will external companies be able to use it?

Roadmap. The CodeWatch core is Apache 2.0 today and you can self-host. A managed CodeRadar tier for portfolio-adjacent companies (alums, partners) is being scoped, but the priority is portfolio-internal stability first.

PII / data sensitivity?

SDKs ship with a default scrub list (auth headers, password fields, common PII patterns). The scrub list is overridable per project. Receipts are stored hashed, not in plaintext. Full posture in /security.

What happens when CodeRadar is down?

SDKs have a 1 MB / 5-minute local buffer with on-disk persistence (server SDKs only). Browser SDKs drop oldest events first. Either way the application keeps running — capture is fire-and-forget by design.

Ship the SDK today. See errors by tomorrow.

Five lines in your bootstrap. The Goodventures Clerk session takes you straight into the dashboard. If you are setting up a new project, the quickstart walks you through DSN provisioning, source-map upload, and the first alert in under five minutes.