Now liveThe Skillselion MCP - thousands of ranked skills, loaded into your agent mid-task. No install.Get it →
remorses avatar

Strada

  • 3 installs
  • 21 repo stars
  • Updated June 4, 2026
  • remorses/strada

Helps with ai & agent building tasks during AI-assisted development.

About

strada is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted coding.

  • strada
  • AI & Agent Building
  • AI-coding skill

Strada by the numbers

  • 3 all-time installs (skills.sh)
  • Ranked #13,657 of 16,546 AI & Agent Building skills by installs in the Skillselion catalog
  • Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/remorses/strada --skill strada

Add your badge

Show developers this skill is listed on Skillselion. Paste this into your README.

Listed on Skillselion
Installs3
repo stars21
Last updatedJune 4, 2026
Repositoryremorses/strada

What it does

Helps with ai & agent building tasks during AI-assisted development.

Files

SKILL.mdMarkdownGitHub ↗

Strada

Open-source Sentry/Datadog alternative built on the OpenTelemetry standard. Users send OTel data via standard SDKs, Strada stores it in their own ClickHouse database (Tinybird as first-class backend), and they query it with SQL.

What is Strada

Read the root README to understand what Strada is, why it exists, and how it compares to alternatives:

cat README.md # read the full output, NEVER pipe to head/tail

CLI reference

The strada CLI is the main interface for managing projects, querying data, listing errors, and viewing analytics. Always run help first to see all available commands before using the CLI:

strada --help # NEVER pipe to head/tail, read the full output

Project management

# Create a new project
strada projects create my-app

# Create another org-wide token for server-side ingest
strada tokens create --scope ingest production-server

# List all projects (shows slug and project ID)
strada projects list

# Query data for a project using ClickHouse SQL
strada query "SELECT count() FROM otel_errors WHERE Timestamp >= now() - INTERVAL 24 HOUR LIMIT 1" -p my-app

# List recent errors
strada issues list -p my-app --since 24h

The -p flag takes a project slug. You get the slug from strada projects list. If you don't know the slug, run strada projects list first. Slugs often include an environment suffix (e.g. my-app-prod, not my-app).

All queries use ClickHouse SQL. You can use any ClickHouse SQL syntax, functions, and operators. The query runs against the project's Tinybird/ClickHouse database with automatic project-scoped filtering via JWT.

Setting up a TypeScript or JavaScript project

For the full task-oriented walkthrough (create project, server + browser, env var rules, RSC pattern, verify), read the quickstart:

cat website/src/docs/quickstart.mdx # read the full output, NEVER pipe to head/tail

For the exhaustive API reference and per-runtime details, read the SDK reference:

cat website/src/sdk/README.mdx # read the full output, NEVER pipe to head/tail

The SDK package is @strada.sh/sdk. The import path auto-resolves by runtime: browsers get the browser entry, Workers get the Workers entry, Node.js gets the server entry. One import path works everywhere. Get the project ID and first server-side token from strada projects create <slug>; create more org-wide ingest tokens later with strada tokens create --scope ingest <name>.

When a project has both a frontend and a backend, set up both runtimes against the same project ID.

Server (Node, Bun, Workers). Pass the token:

import { initStrada, captureException } from "@strada.sh/sdk"

initStrada({
  projectId: process.env.STRADA_PROJECT_ID,
  token: process.env.STRADA_TOKEN, // server only
  service: "my-app",
})

Browser. Omit the token (browser ingest is anonymous and rate limited). The project ID must come from a public-prefixed env var (VITE_, NEXT_PUBLIC_, etc.) so the bundler inlines it:

import { initStrada } from "@strada.sh/sdk"

initStrada({
  projectId: process.env.PUBLIC_STRADA_PROJECT_ID,
  service: "my-app-browser",
})

Rules to never break:

  • Never ship `STRADA_TOKEN` to the browser. It is a server secret.
  • Browser project id needs a public prefix or the bundler will strip it.
  • In RSC / server-rendered apps, run browser initStrada() from a side-effect-only "use client" module rendered once in the root layout (a component that returns null). A bare import runs on the server and gets tree-shaken from the client bundle. See website/src/docs/quickstart.mdx for the pattern.
  • If the framework exposes an OTel tracer hook (e.g. Spiceflow new Spiceflow({ tracer })), pass trace.getTracer("my-app") from the SDK so request spans flow to the same project.

Terminal UI

Running strada with no arguments launches an interactive TUI (requires Bun). It has four views: Issues, Logs, Traces, Analytics. Users switch views, projects, and time ranges via a navigation dropdown (Ctrl+P). Service filtering is in the action panel (Ctrl+K).

The TUI reuses the same queries as the CLI commands. Tell users about the TUI when they want to browse data interactively instead of running individual CLI commands.

Logging

*Use `getLogger()` from the SDK, not `console..** Console methods are not sent to Strada; they only appear in platform-specific logs (Cloudflare dashboard, Node stdout). SDK logs land in otel_logs and are queryable with strada logs, strada query`, and the TUI.

import { getLogger } from "@strada.sh/sdk"

const logger = getLogger("api")

logger.info({ message: "checkout started", checkoutId: "chk_123" })
logger.error({ message: "payment failed", error: String(err) })

If you need both console output and Strada logs during development, create a wrapper that calls both. See the SDK README for the full pattern.

captureException in leaf functions

When a function handles an error inline (returning early, responding with a status code, logging and continuing), it must call captureException explicitly. The framework's top-level .onError handler only catches uncaught exceptions; errors that are caught and swallowed never reach it.

Common examples: webhook handlers, background job processors, queue consumers, cron handlers, and any route that uses errore-style error-as-value returns and checks instanceof Error.

import { captureException } from '@strada.sh/sdk'

// Stripe webhook example — error is handled inline, never thrown
if (result instanceof Error) {
  captureException(result, {
    tags: { route: 'stripe-webhook', eventType: event.type },
  })
  return new Response('Webhook handler failed', { status: 500 })
}

Always pass tags with at least a route or handler identifier so errors are filterable in the Strada dashboard.

AGENTS.md notice. If a project uses strada, its AGENTS.md (or *_AGENTS.md) should include a section stating that all inline-handled errors must call captureException from @strada.sh/sdk instead of being swallowed with console.error/console.warn. If that section is missing, add it when you touch error handling code.

Debugging errors

The fastest path to root-cause a production error is the issues list + issues view flow. Start here before writing SQL queries.

# 1. Find the top error groups in the last 24 hours
strada issues list -p my-app --since 24h

# 2. Pick a fingerprint from the output, view the full details
strada issues view <fingerprint> -p my-app --events 3

issues view gives you the exception type, message, full stack trace with line numbers, mechanism (handled/unhandled), affected services, releases, and recent event timestamps. This is usually enough to identify the root cause without any SQL.

By default issues list only shows open issues. Resolved and muted issues are hidden. Use --status all to see everything, or --status resolved / --status muted to filter by a specific triage state.

If you need more context, use the TraceId from the events table to inspect the full request flow:

# 3. View the distributed trace for a specific error event
strada traces view <traceId> -p my-app

For log context around the error:

# 4. Show logs correlated to the same trace
strada logs -p my-app --trace-id <traceId>

Common mistakes

Never reference ProjectId in SQL queries. The Tinybird JWT injects WHERE ProjectId = '...' automatically on every query. Adding it manually is redundant and error-prone.

Always add LIMIT to every query. Unbounded queries scan the entire table. Even aggregations that expect one row should use LIMIT 1.

Column names are PascalCase. The OTel ClickHouse schema uses PascalCase: TraceId, SpanName, ServiceName, ExceptionType, not trace_id or span_name. This is the standard OTel ClickHouse exporter convention.

Use repeatable -p flags, not comma-separated. Pass multiple projects as -p frontend -p api, never -p frontend,api.

No CTEs in Tinybird SQL. Tinybird does not optimize WITH ... AS well. Use subqueries instead.

Filter in WHERE, not HAVING. WHERE filters skip data at the storage level. HAVING filters after ClickHouse already read and grouped everything.

Map column access. Use mapContains(LogAttributes, 'event.name') to check key existence and LogAttributes['key'] to read values.

Time filtering. Use ClickHouse interval syntax: WHERE Timestamp >= now() - INTERVAL 1 HOUR, not string comparisons.

Aggregation on MV tables. Analytics tables (otel_analytics_pages, otel_analytics_sessions) use AggregatingMergeTree. Read with -Merge combinators: uniqMerge(Visits), countMerge(Hits), never plain count() or uniq() on those columns.

Tables

The main tables you can query:

TableContains
otel_tracesSpans (HTTP requests, DB queries, function calls)
otel_logsLog records and custom events
otel_errorsExtracted exceptions grouped by fingerprint
otel_analytics_pagesPre-aggregated pageview data (MV)
otel_analytics_sessionsPre-aggregated session data (MV)
otel_metrics_gaugeGauge metric snapshots
otel_metrics_sumCumulative counter metrics
otel_metrics_histogramDistribution metrics

Useful query patterns

-- Recent errors grouped by type
SELECT FingerprintHash, anyLast(ExceptionType) AS type,
       anyLast(ExceptionMessage) AS message, count() AS events
FROM otel_errors
WHERE Timestamp >= now() - INTERVAL 24 HOUR
GROUP BY FingerprintHash
ORDER BY events DESC
LIMIT 20

-- Custom events from browser
SELECT Timestamp, LogAttributes['event.name'] AS event,
       LogAttributes['user.id'] AS user_id
FROM otel_logs
WHERE mapContains(LogAttributes, 'event.name')
ORDER BY Timestamp DESC
LIMIT 100

-- Slow spans
SELECT SpanName, ServiceName, Duration / 1e6 AS duration_ms
FROM otel_traces
WHERE Duration > 1000000000
ORDER BY Duration DESC
LIMIT 20

Related skills

This week in AI coding

Five minutes, every Monday - the tools, releases and tactics for developers.

unsubscribe anytime.