Skip to content

Claude Code Skill

Autotel includes a Claude Code skill that gives AI coding agents deep knowledge of the instrumentation API. When the skill is active, Claude Code can:

  • Wrap functions with trace() and set semantic attributes
  • Convert console.log calls to getRequestLogger() wide events
  • Add createStructuredError() with why, fix, and link fields
  • Set up init() with the correct configuration
  • Review code for observability anti-patterns

The skill lives at .claude/skills/autotel/ in the repository root. Claude Code discovers it automatically when you work inside the repo. No extra configuration needed.

For other projects that use Autotel, copy the .claude/skills/autotel/ directory into your repo’s .claude/skills/ folder.

.claude/skills/autotel/
├── SKILL.md # Main skill entry point
└── references/
├── wide-events.md # Canonical log lines guide
├── structured-errors.md # Error handling patterns
├── request-logger.md # Request-scoped logging
└── code-review.md # Anti-pattern detection checklist

File: .claude/skills/autotel/references/wide-events.md

A wide event is a single structured record per request containing all context accumulated during processing. Instead of 10 scattered log lines, you get one queryable event with 25+ fields.

Covers:

  • Anatomy of a canonical log line (core fields, trace identifiers, duration)
  • Context grouping with dot-prefixed keys
  • Configuration options (keep, shouldEmit, pretty, drain, attributeRedactor)
  • Drain pipeline for production fan-out with batching and retry
  • SQL query examples for analyzing wide events
init({
service: 'my-app',
canonicalLogLines: {
enabled: true,
rootSpansOnly: true,
keep: [
{ status: 500 },
{ durationMs: 1000 },
],
pretty: true,
drain: (event) => sendToAnalytics(event),
},
});

File: .claude/skills/autotel/references/structured-errors.md

Covers three APIs:

APIPurpose
createStructuredError()Create errors with message, why, fix, link, code, status, details
recordStructuredError()Record a structured error onto a trace context (sets status + exception + attributes)
parseError()Normalize any thrown value to a consistent shape for API responses

Common patterns:

  • API endpoint error responses
  • Wrapping third-party errors (Stripe, etc.)
  • Domain validation errors
  • Span attribute mapping (error.type, error.why, error.fix, etc.)
throw createStructuredError({
message: 'Payment declined',
why: 'Card has insufficient funds for the requested amount',
fix: 'Prompt the user to update their payment method',
code: 'CARD_DECLINED',
status: 402,
link: 'https://docs.stripe.com/declines/codes#insufficient-funds',
});

File: .claude/skills/autotel/references/request-logger.md

Covers the getRequestLogger() API and framework adapters:

  • log.set(fields) — merge fields onto the span (nested objects flatten automatically)
  • log.info(message, fields?) — span event at info level
  • log.warn(message, fields?) — span event at warn level, promotes canonical log line
  • log.error(error, fields?) — record structured error on span
  • log.getContext() — snapshot of all accumulated fields
  • log.emitNow(overrides?) — emit snapshot immediately with onEmit fan-out

Framework adapters:

  • useLogger() with withAutotel() (Next.js, Nitro, Cloudflare Workers)
  • useLogger() alone when middleware already creates the span (Hono)
  • Custom adapters via createUseLogger()
const log = getRequestLogger(ctx);
log.set({ feature: 'checkout', tier: req.user.tier });
const cart = await loadCart(req.cartId);
log.set({ cart_items: cart.items.length, cart_total: cart.total });

File: .claude/skills/autotel/references/code-review.md

Anti-pattern detection table with severity levels and fixes:

Anti-PatternSeverityFix
console.log for request contextHighgetRequestLogger(ctx) with log.set()
console.error in catch blocksHighlog.error(err) or recordStructuredError()
throw new Error('...') without contextMediumcreateStructuredError({ message, why, fix })
catch (e) { throw e } without recordingMediumAdd log.error(e) before rethrowing
JSON.stringify for log outputHighlog.set() — attributes flatten automatically
Manual request ID generationLowctx.correlationId from trace context

Also includes a 4-step migration path from console.log to fully instrumented Autotel code.

When you ask Claude Code to instrument code, review for observability, or work with errors/logging, the skill activates and loads the relevant reference guides. Claude Code then applies the patterns directly — wrapping functions with trace(), replacing console.log with request loggers, and adding structured error context.

  • “Add tracing to this handler”
  • “Convert the console.logs in this file to use request logger”
  • “Add structured errors to the catch blocks”
  • “Review this file for observability anti-patterns”
  • “Set up canonical log lines for this service”

The skill described above teaches Claude Code how to write instrumented code. A second class of agent task — investigating telemetry (querying traces, diagnosing errors, ranking expensive LLM calls) — is served by two interchangeable mechanisms:

  1. autotel-mcp — an MCP server the user wires into .mcp.json.
  2. The autotel CLI itself — the same investigation surface as one-shot subcommands that emit JSON on stdout.

Both share the same backends (packages/autotel-mcp/src/backends/) and the same query helpers, so the answers are identical. The CLI route is useful when you’d rather not configure an MCP server, or when you’re driving an agent harness that doesn’t speak MCP.

MCP tool groupCLI equivalent
health.backend_healthautotel health
health.backend_capabilitiesautotel capabilities
discovery.discover_servicesautotel discover services
discovery.discover_trace_fieldsautotel discover trace-fields
discovery.discover_log_fieldsautotel discover log-fields
investigation.search_tracesautotel query traces
investigation.search_spansautotel query spans
investigation.get_traceautotel trace get <id>
investigation.summarize_traceautotel trace summary <id>
signals.list_metricsautotel query metrics
signals.search_logsautotel query logs
topology.list_servicesautotel topology services
topology.list_operationsautotel topology operations <name>
topology.service_mapautotel topology map
diagnosis.find_anomaliesautotel diagnose anomalies
diagnosis.find_root_causeautotel diagnose root-cause <id>
diagnosis.find_errorsautotel diagnose errors
diagnosis.check_slosautotel diagnose slos --service <name>
correlation.correlateautotel correlate trace <id>
correlation.explain_slowdownautotel correlate explain-slowdown --service <name>
llm-analytics.get_llm_usageautotel llm usage
llm-analytics.list_llm_modelsautotel llm models
llm-analytics.get_llm_model_statsautotel llm model-stats --model-name <name>
llm-analytics.get_llm_expensive_tracesautotel llm expensive
llm-analytics.get_llm_slow_tracesautotel llm slow
llm-analytics.list_llm_toolsautotel llm tools
semantic-conventions.*autotel semconv list | get <ns> | refresh
instrumentation.score_span_instrumentationautotel score (JSON span on stdin)
instrumentation.explain_instrumentation_scoreautotel score explain
collector-config.*autotel collector validate | suggest | explain
collector-schema.*autotel collector versions | components | schema | readme | validate-component | refresh

Every backend-touching command accepts the same flags as the MCP server’s env vars, with flags winning over env when both are set:

Terminal window
autotel query traces \
--backend tempo \
--tempo-base-url http://localhost:3200 \
--service-name checkout \
--error-only \
--limit 20

Available backends: collector (built-in OTLP receiver, in-memory or libsql-persisted) · jaeger · tempo · prometheus · loki · stack (composite) · auto (probe localhost) · fixture (JSON file).

Every investigate command emits one JSON document on stdout. Success:

{ "ok": true, "command": "query traces", "data": { /* … */ } }

Failure:

{
"ok": false,
"error": {
"type": "validation" | "runtime",
"code": "AUTOTEL_E_INVALID_INPUT" | "AUTOTEL_E_UNKNOWN",
"message": "",
"retryable": false
}
}

Exit code is 0 on success, 2 on validation, 1 on runtime. Agents check result.ok and read data (or error).

MCP serverCLI subcommands
Install stepEdit .mcp.json, restart clientnpm i -g autotel
Transportstdio / HTTP per clientShell exec
Streaming resultsYesOne-shot per command
Cross-tool stateServer holds backend connectionEach call re-opens
Works in non-MCP agentsNoYes
DiscoverabilityMCP tool listautotel <group> --help

For an agent driving a single investigation prompt the CLI is usually faster — no MCP handshake, no per-tool round-trip. For an interactive incident review with many follow-up queries against a heavy backend, the MCP server’s persistent backend connection wins.

A ready-made skill that maps prompts → CLI commands ships at .claude/skills/autotel-investigate/SKILL.md. Claude Code discovers it automatically when you work inside the repo; copy the directory into another project’s .claude/skills/ to use it elsewhere.