Agent skill

Logging and Error Reporting for Warp

by warpdotdev in warpdotdev/warp

Guides log level choices and when to raise a structured Sentry event instead of a plain log line in the Warp Rust codebase, keeping secrets out of logs.

AGPL-3.0Auto-check passedDevelopment

Install Logging and Error Reporting for Warp

skills CLI
$ npx skills add warpdotdev/warp --skill logging-and-error-reporting -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install warpdotdev/warp logging-and-error-reporting --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/warpdotdev/warp.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/logging-and-error-reporting .claude/skills/logging-and-error-reporting && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
logging-and-error-reporting
GitHub stars
65k
Used in
1 other repo
Token cost
~5.6k tokens
SKILL.md length
2,644 words
Files
1
Skills in repo
46
Repo updated
First seen
Licence
AGPL-3.0

At a glance

Guides log level choices and when to raise a structured Sentry event instead of a plain log line in the Warp Rust codebase, keeping secrets out of logs.

  • Works in 7 steps: The error IS the payload — report it as… → Prefer Result-level .context() whenever… → Wrap a bare error value only when there… → …
  • Picking a log level for a new message in the Warp codebase
  • SKILL.md covers How logs reach Sentry…, Choosing: report_error! vs.…, Log levels and Sensitive data: safe_* macros, plus 9 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Warp has two ways to record what happens at runtime, and this skill explains how they differ. The standard log macros (error, warn, info, debug, trace) write local diagnostics. On crash-reporting builds the Error, Warn and Info lines also travel to Sentry, but only as breadcrumbs attached to a later event, while Debug and Trace lines never leave the machine.

The `report_error!` macro is the one that captures a structured Sentry event. The agent is taught that `log::error!` by itself never opens a Sentry issue, so a failure that engineers should track needs `report_error!`. Picking between the options depends on whose fault the failure is and what it means for the user. Because breadcrumbs are uploaded, the skill also insists that logs never carry secrets or personal data and points to the `safe_*` macros for that.

When your agent uses it

  • Picking a log level for a new message in the Warp codebase
  • Deciding whether a failure should be logged or sent through report_error!
  • Reviewing a change for secrets or personal data leaking into logs
  • Working out why an error never showed up as a Sentry issue

Example prompts

  • “Should this failed config load use log::warn! or report_error!?”
  • “Review my diff and flag any log line that could leak a user's file path or token.”
  • “Why does our log::error! call never appear as an issue in Sentry?”

Requirements

  • Access to the Warp repository

Workflow steps

7 steps, taken from the first numbered list in SKILL.md.

  1. The error IS the payload — report it as an error, never demote it into extra:. extra: is only for genuinely incidental data (ids, paths…
  2. Prefer Result-level .context() whenever a Result is in hand. This is the preferred, most succinct style — reach for it before an…
  3. Wrap a bare error value only when there is no Result to hang .context() on (closure/callback params, match arms that special-case other…
  4. Non-Error payload — a String/&str message, a const, format_args!, or an opaque value that isn't std::error::Error — has no typed chain to…
  5. The error must be reused or returned, so it can't be consumed — but first treat this as a smell. The sink (where the error stops…
  6. Non-error bindings (no error object — let ... else, None => arms, count/id mismatches): static message + extra:.
  7. If a crate lacks an anyhow dependency, either use the extra: form (needs no anyhow at the call site) or add anyhow.workspace = true — do…

What it can do on your machine

Read from SKILL.md and the folder at commit f571865. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are rust).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Logging and Error Reporting for Warp loads about 5.6k tokens when it runs. Until then it costs about 82 tokens; SKILL.md has 2,644 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~82
When it runs · the whole SKILL.md, loaded when a task matches
~5.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from warpdotdev/warp at commit f571865, republished under its AGPL-3.0 licence (© warpdotdev). 2,644 words, ~5,622 tokens.

Download SKILL.mdSave it as .claude/skills/logging-and-error-reporting/SKILL.md (or your agent's skills folder).
name
logging-and-error-reporting
description
How and when to log (log::* levels, safe_* macros) and report errors to Sentry (report_error!) in the Warp codebase. Use when adding or reviewing any logging or error reporting — picking a log level, deciding log vs. report_error!, keeping sensitive data out of logs, or surfacing an error to Sentry.

logging-and-error-reporting

Warp has two related ways to surface what happened at runtime:

  • log::* (error!/warn!/info!/debug!/trace!) — local diagnostics written to the terminal/log file and, on crash-reporting builds, uploaded to Sentry as breadcrumbs (context attached to the next captured event).
  • report_error! — captures a structured Sentry event (an actual issue) for errors worth engineering attention.

How logs reach Sentry (important)

On crash-reporting builds a SentryLogger wraps the logger (warp_logging). The filter:

  • Error / Warn / Info → breadcrumb only (not their own Sentry issue).
  • Debug / Trace → dropped from Sentry entirely (local-only).
  • The Error-level line emitted by report_error! itself → ignored by Sentry (the macro already captured a structured event; the log line would double-report).
  • A few noisy targets (wgpu, panic, redraw-frame, the crash-reporting module) are dropped.

Consequences:

  • log::error! does NOT create a Sentry issue — it's only a breadcrumb. If a failure should be tracked in Sentry, use report_error!. Only report_error! and panics create Sentry events.
  • Breadcrumbs (Info and above) are uploaded, so they must never contain secrets or PII — see "Sensitive data: safe_* macros" below.

Choosing: report_error! vs. log::error! vs. log::warn!

Pick based on whose fault the failure is and what it means for the user, not on how bad it feels. Remember only report_error! reaches Sentry (see above) — the two log levels are local/breadcrumb-only, so choosing between them is about log severity, not about paging anyone.

  • report_error! — actionable; an engineer should fix something. Use it when the failure means our code is wrong: an invariant was violated, an assumption that should always hold didn't, or execution reached a state that shouldn't be possible. Also use it when the cause isn't our bug but the user-facing impact is severe enough that we need to build a workaround — this covers failures in a critical subsystem (a core startup/lifecycle path, or a fallback that itself guards a critical path), where even an externally-caused failure is worth an engineer's eyes. One further exception: when we're programming against an external system whose behavior is uncertain — its quirks aren't fully understood, or a failure might actually mean we're using it wrong — prefer report_error! over a plain log, since the "external" failure may be our bug in disguise. This is the only form that becomes a Sentry issue, so reserve it for failures worth an engineer's attention.
  • log::error! — a genuine failure that is not our code's fault. The operation we intended couldn't be completed, but the cause is external (the environment or an external system), not a bug we can fix. It's a real failure, so it's error severity — but there's nothing to act on, so it does not page us. (Exception: if it's a critical subsystem, or the external system's behavior is uncertain enough that the failure might be our fault, escalate to report_error! per the bullet above.)
  • log::warn! — non-ideal but largely expected. The app can still proceed with the functionality generally intact, perhaps with a degraded experience. Recoverable/handled conditions, fallbacks, retries, and skipped work belong here.

For everything else — lifecycle/state info, expected or handled conditions, and diagnostic "loud logs" (e.g. listing valid options after a lookup miss) — use plain log::* at the level that fits (see "Log levels"). If a function's name/doc says it logs (or it emits a header line plus one entry per item), it should use log::*, not report_error!.

Don't signal the same failure twice. Report it once, at the sink where it stops propagating; log::* breadcrumbs on the way there are useful context (see "Report once, at the sink").

Log levels

The default filter is Info, so debug!/trace! are off unless RUST_LOG enables them.

  • error! — a genuine failure whose cause is external, not a bug in our code: the environment or an external system prevented the operation we intended. Nothing for us to fix, so it's not report_error!; still a real failure, so it's error severity. Only a breadcrumb — if it turns out to be actionable, use report_error! instead.
  • warn! — non-ideal but largely expected: the app proceeds with the functionality generally intact (possibly degraded). Recoverable/handled paths, retries, fallbacks, skipped work.
  • info! — coarse lifecycle/state milestones (startup, connection up/down, feature enabled). On by default and uploaded as breadcrumbs, so keep it low-volume and free of per-item spam.
  • debug! — verbose diagnostics for local development; off by default; never sent to Sentry.
  • trace! — very fine-grained / hot-path detail; off by default; never sent to Sentry.

Guidance:

  • Hot loops, per-frame render paths, and per-message handlers must log at debug!/trace! (never info!+), or they flood the log file and breadcrumb buffer.
  • Prefer static, greppable message prefixes with structured key=value detail (e.g. "[Remote codebase indexing] … repo_path={} state={:?}"), matching the surrounding module.
  • Use inline format args (log::warn!("… {err:#}")) per the workspace clippy config; format an error chain with {err:#}.

Sensitive data: safe_* macros

Never log secrets, tokens, or credentials at any level. For messages whose useful detail is sensitive-ish — file paths, response payloads, user-generated content — that you want locally but must NOT ship in release-channel logs (which get bundled and become breadcrumbs), use the safe_* macros instead of log::*.

safe_error!, safe_warn!, safe_info!, safe_debug! (plus safe_anyhow! to build an anyhow::Error, and safe_eprintln!) each take a safe: and a full: arm. Dogfood builds log full:; release channels log safe::

rust
use warp_core::safe_error;

safe_error!(
    safe: ("Remote server unexpected response for Initialize"),
    full: ("Remote server unexpected response for Initialize: response={other:?}")
);
  • The safe: arm must stand on its own and contain no sensitive/verbose detail; put those bits only in full:.

Reporting errors with report_error!

report_error! is the explicit way to send an error to Sentry as a structured event. Reserve it for actionable failures — an invariant or always-true assumption was violated, or the code reached a state it shouldn't, i.e. a bug we should FIX — or for cases where the cause isn't our bug but the user-facing impact is severe enough to warrant a workaround. A failure that's merely an external error (nothing to fix) or an expected/degraded condition belongs at log::error! / log::warn! instead (see "Choosing" above).

At runtime it checks err.is_actionable():

  • actionable → captured to Sentry AND logged at Error level.
  • not actionable (e.g. registered network errors: reqwest connect/5xx/429, tokio JoinError cancelled) → logged at Warn level only, never sent to Sentry.

This classification only works if the typed error reaches the macro. Sentry buckets events into issues by a fingerprint (its grouping key); because these events are stacktrace-less, Sentry derives that fingerprint from the message text. Interpolating instance-specific data (ids, paths, counts, a stringified error) into the message changes the fingerprint on every occurrence, so one logical error fragments into countless separate issues (and burns through quota). Keep the message a static string so the fingerprint stays stable; per-instance data goes in the error chain (via .context()) or a structured extra: block — neither of which affects the fingerprint — never interpolated into the message.

Bad (fragments Sentry grouping into one group per distinct value, and — when it stringifies a typed error — hides it from is_actionable):

rust
report_error!("Failed to read persisted data: {err}");

Good (canonical in-tree example, app/src/persistence/sqlite.rs):

rust
report_error!(anyhow::Error::new(err).context("Failed to read persisted data"));

Prefer typed error enums over anyhow when it makes sense

Don't default to anyhow. The conventional Rust guidance is "anyhow for applications, thiserror for libraries," but the sharper question is: does anything downstream need to tell the failures apart? If yes, define a typed error enum (thiserror), impl ErrorExt, and register_error! it. In Warp that "downstream" includes the Sentry reporting layer, not just calling code — so typed errors pay off more often than the plain app-vs-library rule suggests.

Reach for a typed error enum when these hold:

  • A caller branches on the failure — it matches to recover, retry, fall back, render a specific message/state, or map to a status. This is the classic reason and the strongest signal: an anyhow::Error is opaque, so callers can essentially only print it.
  • Mixed actionability — some variants are real bugs worth a Sentry issue and others are expected/environmental (network, auth-expired, user-cancelled, not-found). Per-variant is_actionable() reports the bugs and stays silent on the noise; anyhow is all-or-nothing.
  • A fixed, known set of failure modes worth naming — it makes a function's failure surface visible in its signature and gives Sentry stable, meaningful groups (one per variant) instead of one catch-all bucket.
  • The same failure recurs across many call sites — define the message and classification once on the type, then report once at the sink.

Default to anyhow when these hold:

  • The error is only propagated (? / .context("…")) up to a sink that logs/reports/displays it — nobody matches on its kind.
  • The failure modes are open-ended or not worth enumerating.
  • A static .context("…") string carries enough for a human reading the Sentry event or log.
  • It's leaf/glue code, not an API boundary other code depends on.

It's not either/or: a typed enum can keep an anyhow escape hatch for the genuinely-unexpected case (an Unexpected(#[from] anyhow::Error) variant), classifying the known failures precisely while still absorbing the rest. Group variants by failure mode (what went wrong / what the caller does about it), not by which crate produced the error.

Real example (UserAuthenticationError, crates/warp_server_client/src/auth/mod.rs):

rust
#[derive(thiserror::Error, Debug)]
pub enum UserAuthenticationError {
    #[error("Firebase returned a token error when fetching an ID token")]
    DeniedAccessToken(FirebaseError),
    #[error("unexpected error occurred when fetching an ID token: {0:#}")]
    Unexpected(#[from] anyhow::Error),
    // …
}

impl ErrorExt for UserAuthenticationError {
    fn is_actionable(&self) -> bool {
        match self {
            UserAuthenticationError::DeniedAccessToken(_) => false,
            UserAuthenticationError::Unexpected(e) => e.is_actionable(),
            // …
        }
    }
}
register_error!(UserAuthenticationError);
Show full SKILL.md (1,201 more words)Show less

Choosing the form (variable data out of the grouped message)

Never stringify an already-typed error. report_error!(anyhow::anyhow!("{e}")) flattens e to a String, which erases the typed source chain and defeats is_actionable() (so registered non-actionable network errors get over-reported). Reserve anyhow!("…") for values that are genuinely not errors (see rule 4).

Rules, in priority order:

  1. The error IS the payload — report it as an error, never demote it into extra:. extra: is only for genuinely incidental data (ids, paths, counts, durations).
  2. Prefer Result-level .context() whenever a Result is in hand. This is the preferred, most succinct style — reach for it before an anyhow::Error::new(..) / anyhow!(..) wrapper whenever practical. Works for any Result<_, E: std::error::Error> and for anyhow::Result; add use anyhow::Context for the trait method. Don't add an anyhow::Error::new(..) / anyhow!(..) wrapper when .context() on the Result will do. Avoid the UFCS form anyhow::Context::context(result, "msg") — it reads poorly; import the trait, or if you'd rather not import it, restructure to own the error and use the inherent method: if let Err(e) = some_call() { report_error!(e.context("msg")); }.
    rust
    let data = some_call().context("Failed to load data")?;
  3. Wrap a bare error value only when there is no Result to hang .context() on (closure/callback params, match arms that special-case other variants):
    • e is a std::error::Error but not anyhow: report_error!(anyhow::Error::new(e).context("msg")).
    • e is already an anyhow::Error: report_error!(e.context("msg")).
    • e is a registered error (register_error!): pass it directly — report_error!(e) — which keeps it fully typed.
    • Error type differs by feature/config (sometimes anyhow, sometimes StdError): use the Result-level .context() above, or report_error!(anyhow::Error::from(e).context("msg")) which compiles for both (do NOT use Error::from where e is unconditionally anyhow — clippy flags it as a useless conversion; use e.context() there).
  4. Non-Error payload — a String/&str message, a const, format_args!, or an opaque value that isn't std::error::Error — has no typed chain to preserve, so anyhow::anyhow!("{value}") (or "static", extra: { .. }) is correct here.
  5. The error must be reused or returned, so it can't be consumed — but first treat this as a smell. The sink (where the error stops propagating) should normally be the one reporting, and it should own the error so it can move it into report_error! fully typed and with .context(). Needing to report a borrowed error usually means you're reporting away from the true sink, or reporting an error you also return (see "Report once, at the sink") — prefer restructuring so the owner reports. When you genuinely can't take ownership, report it borrowed, which still keeps it typed:
    • e is an anyhow::Error or a registered error → report_error!(&e) (optionally report_error!(&e, extra: { .. })). Note this drops any static .context("…") message, so &e groups by the error's own message.
    • If the later use is itself a borrow (building a format!/detail string, calling a &e method), reorder so that borrow runs first and then move e into the report last — report_error!(anyhow::Error::new(e).context("msg")) (StdError) or report_error!(e.context("msg")) (anyhow). This keeps the typed chain AND the static context.
    • inspect_err(|e| report_error!(..)) only hands you &e (a borrow), which forces the stringified anyhow!("{e}") form. When you're reporting-and-swallowing (.ok() / .ok()?) or otherwise discarding the error, switch to map_err(|e| report_error!(anyhow::Error::new(e).context("msg"))) so e is owned and stays typed — the closure returns (), which composes with a trailing .ok()/?. (Clippy's manual_inspect only fires when a map_err closure returns e unchanged; returning () is fine.)
    • Prefer to make the error reportable while typed before falling back to stringify: a Display-only enum or other unregistered concrete error should be upgraded to #[derive(thiserror::Error)] (or register_error!-ed) so you can report_error!(anyhow::Error::new(e).context("msg")) / report_error!(&e). Only when that isn't feasible is report_error!(anyhow::anyhow!("{e}").context("msg")) unavoidable.
  6. Non-error bindings (no error object — let ... else, None => arms, count/id mismatches): static message + extra:.
  7. If a crate lacks an anyhow dependency, either use the extra: form (needs no anyhow at the call site) or add anyhow.workspace = true — do not dump a real error into extra: just to avoid the dep.

Report once, at the sink

Report a failure where it stops propagating, not at every layer it flows through. If a function returns or propagates the error (?, return Err(..)), don't also report_error! it there — whoever ultimately handles or swallows it reports it. Reporting in both the callee and the sink double-counts the same failure in Sentry.

  • A callee that wants a local breadcrumb while still returning the error should use log::warn!/log::error!, and leave the report_error! to the sink.
  • inspect_err(|e| report_error!(..)).ok() (report-and-swallow) is a legitimate terminal decision — the error is consumed there, not returned.
  • For a registered error surfaced through many internal failure points, implement is_actionable on the type and report_error! it once at the top-level sink (e.g. a driver's run), instead of reporting at each internal Err.

report_if_error! for report-and-continue

When you have a Result and simply want to report_error! it if it's Err and otherwise carry on — without binding the error yourself — reach for report_if_error!(<expr returning a Result>). It's the succinct form of if let Err(e) = expr { report_error!(e); }, so prefer it whenever you'd otherwise hand-write that pattern at a sink. It's underused; keep it in mind to make error handling more concise. Pair it with a Result-level .context("…") to attach a static grouping message:

rust
report_if_error!(some_fallible_call().context("Failed to do the thing"));

It reports (and logs) an actionable error and is a no-op on Ok, so it fits "report once, at the sink" for a call whose error you don't otherwise need to bind.

extra: syntax

Attach incidental data as a structured Sentry "details" context block. % forces Display, ? forces Debug, a bare expr defaults to Display:

rust
report_error!(
    "Could not find data for pane",
    extra: { "pane_id" => ?pane_id, "count" => %count }
);

Combine a real error with incidental data:

rust
report_error!(
    anyhow::Error::new(e).context("Failed to write attachment"),
    extra: { "path" => %path.display() }
);

Throttling with ReportErrorLogMode::OncePerRun

Sites that can fire repeatedly (hot loops, per-frame paths, enum-fallback conversions from GraphQL/protobuf) should report only once per app run so they don't flood Sentry. Default is EveryTime.

rust
use warp_errors::ReportErrorLogMode;

report_error!(err, ReportErrorLogMode::OncePerRun);
// with a static message + incidental data:
report_error!(
    "Invalid LlmProvider; update client GraphQL types",
    extra: { "provider" => %value },
    ReportErrorLogMode::OncePerRun
);

No secrets or PII

This applies to report_error! messages/extra: AND to log::* at Info and above (both are uploaded to Sentry — the report as an event, the log as a breadcrumb). Never place secrets, tokens, credentials, or user-generated content (file contents, prompts, command text, personal data) in any of them — Sentry retains everything sent. Limit reported/logged data to non-sensitive diagnostics: ids, paths, counts, durations, and error types. When the useful detail is sensitive but helpful locally, use the safe_* macros (see "Sensitive data" above) so it only appears in dogfood logs.

Best practices

  • Static, descriptive grouping message; variable data via .context() or extra:.
  • When the grouping message is static, put the inputs that explain why this instance fired in extra: — the offending values, not just identifiers (e.g. an invalid-geometry report carries the sizes/offsets that produced it; a bounds violation carries the actual min/max). A static message with no diagnostic extra: is hard to act on.
  • Preserve the typed error chain (.context() / anyhow::Error::new) so is_actionable() can suppress registered non-actionable (network) errors — stringifying with anyhow!("{e}") defeats this.
  • Prefer Result-level .context() at the sink over an anyhow::Error::new(e).context(..) wrapper whenever a Result is in hand — it's the most succinct, idiomatic form (see "Choosing the form" rule 2). Reach for report_if_error! when you'd otherwise write if let Err(e) = expr { report_error!(e); }.
  • Prefer a typed, registered error enum (thiserror + ErrorExt + register_error!) over anyhow when a caller or the Sentry layer needs to tell failures apart (branching, or mixed actionability); reserve anyhow for errors that are only propagated and reported (see "Prefer typed error enums over anyhow when it makes sense").
  • Match log level to volume and audience: hot paths at debug!/trace!, milestones at info!, and reserve report_error! for Sentry-worthy failures.

Anti-patterns

rust
// Interpolates variable data into the grouped message.
report_error!("Failed for user {user_id}: {e}");

// Stringifies an owned, typed error — erases the source chain and defeats
// is_actionable(). Use anyhow::Error::new(e).context("msg") instead.
report_error!(anyhow::anyhow!("{e:#}").context("msg"));

// Demotes a real, typed error into extra: (loses is_actionable classification).
report_error!("Request failed", extra: { "error" => %e });

// UFCS .context() reads poorly — import anyhow::Context, or `if let Err(e)` and
// report e.context("msg").
report_error!(anyhow::Context::context(some_call(), "msg").unwrap_err());

// Redundant wrapper when a Result is in hand — use .context() on the Result.
report_error!(anyhow::Error::new(some_call().unwrap_err()).context("msg"));

// log::error! for a Sentry-worthy failure — this is only a breadcrumb, not an
// issue. Use report_error! if it should be tracked in Sentry.
log::error!("Failed to sync: {e:#}");

// Sensitive detail logged unconditionally — ships to release-channel logs and
// breadcrumbs. Use safe_error!(safe: (..), full: (..)) instead.
log::warn!("Bad response body={body:?}");

// info! (or higher) in a hot/per-frame path — floods logs and breadcrumbs.
// Use debug!/trace! for high-frequency diagnostics.
log::info!("rendered frame {n}");

© warpdotdev, AGPL-3.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/logging-and-error-reporting of warpdotdev/warp.

Open the folder on GitHubat commit f571865

Used in 1 other repository

We found 1 copy of this SKILL.md (exact, near-identical or edited) in other folders, from 1 other GitHub owner. This page covers the copy in warpdotdev/warp, which our catalogue first saw on October 7, 2026.

Compare with similar skills

Logging and Error Reporting for Warp next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Logging and Error Reporting for Warp compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Logging and Error Reporting for Warp this skillwarpdotdev/warp65k1 repos~5.6kAutomated safety check: PassAGPL-3.0
Rust SkillsJMBeresford/retrom2.1k1 repos~9.5kAutomated safety check: PassMIT
Logging Observabilitygetsentry/toolkit917—~2.6kAutomated safety check: PassCustom licence
Sentry v8 Error Trackingdiet103/claude-code-infrastructure-showcase10k2 repos~2.3kAutomated safety check: NotesMIT
Error HandlerEliasOulkadi/shokunin114—~3.6kAutomated safety check: NotesMIT
Rust Best Practicesfarm-fe/farm5.6k3 repos~1.1kAutomated safety check: PassMIT

Similar skills

  • Rust Skills

    JMBeresford/retrom

    Comprehensive Rust coding guidelines with 265 rules across 26 categories.

    2.1k GitHub starsUsed in 1 repo~9.5k tokens
    DevelopmentAuto-check passed
  • Logging Observability

    getsentry/toolkit

    Official

    Review code for correct logging and error handling patterns.

    917 GitHub stars~2.6k tokensUpdated today
    DevOps & CloudAuto-check passed
  • Sentry v8 Error Tracking

    diet103/claude-code-infrastructure-showcase

    Enforces that every error in a service is captured to Sentry v8, with patterns for controllers, routes, cron jobs and database performance spans instead of console logging alone.

    10k GitHub starsUsed in 2 repos~2.3k tokens
    Backend & APIsAuto-check: notes
  • Error Handler

    EliasOulkadi/shokunin

    Design error handling, structured logging, and observability with OpenTelemetry (traces, metrics, logs), error classification, recovery patterns (retry with jitter, circuit breaker, bulkhead…

    114 GitHub stars~3.6k tokensUpdated 2 days ago
    DevOps & CloudAuto-check: notes
  • Guide for writing idiomatic Rust code based on Apollo GraphQL's best practices handbook.

    5.6k GitHub starsUsed in 3 repos~1.1k tokens
    DevelopmentAuto-check passed
  • SeekDB Code Review

    oceanbase/seekdb

    Reviews seekdb pull requests and diffs for real defects in correctness, resources, concurrency, security and tests, reporting only Blocker or Major findings.

    3.1k GitHub stars~2.1k tokensUpdated 4 days ago
    DevelopmentAuto-check passed

More from warpdotdev/warp

All 46 skills in this repo
  • Builds or updates a design system in Figma from a codebase in ordered phases: discovery, variables and tokens, components, theming and documentation, with checkpoints.

    65k GitHub starsUsed in 2 repos~4.4k tokens
    Auto-check passed
  • Required groundwork before any use_figma call: the rules and reference files for running JavaScript in a Figma file through the Plugin API without common failures.

    65k GitHub starsUsed in 4 repos~4.4k tokens
    Auto-check passed
  • Warp Factory Files

    warpdotdev/warp

    Authors and edits file-based Warp software factory definitions rooted at factory.yaml, covering agents, automations, scorers and webhooks, and validates them before a pull request.

    65k GitHub starsUsed in 1 repo~2.5k tokens
    Auto-check passed
  • Figma Design to Code

    warpdotdev/warp

    Turns a Figma frame or component into production code that matches the design, using the Figma MCP server and the project's own design system.

    65k GitHub starsUsed in 4 repos~2.9k tokens
    Auto-check passed
  • Migrates the compatible subset of settings and global file-based MCP servers from the Warp desktop app into Warp Agent CLI without exposing credentials or state.

    65k GitHub starsUsed in 1 repo~2.1k tokens
    Auto-check passed
  • Creates project-specific design system rules from your codebase so coding agents implement Figma designs with your components, naming and tokens.

    65k GitHub starsUsed in 3 repos~4.6k tokens
    Auto-check passed

Works with

Categories

Questions about Logging and Error Reporting for Warp

What does Logging and Error Reporting for Warp do?

Guides log level choices and when to raise a structured Sentry event instead of a plain log line in the Warp Rust codebase, keeping secrets out of logs. Warp has two ways to record what happens at runtime, and this skill explains how they differ. The standard log macros (error, warn, info, debug, trace) write local diagnostics.

When should I use Logging and Error Reporting for Warp?

Logging and Error Reporting for Warp fits situations like: picking a log level for a new message in the Warp codebase; deciding whether a failure should be logged or sent through report_error!; reviewing a change for secrets or personal data leaking into logs; working out why an error never showed up as a Sentry issue.

How do I install Logging and Error Reporting for Warp in Claude Code?

Run `npx skills add warpdotdev/warp --skill logging-and-error-reporting -a claude-code`. Or copy the skill folder (.agents/skills/logging-and-error-reporting in warpdotdev/warp) into .claude/skills/logging-and-error-reporting in your project. Claude Code loads it when a task matches its description.

How do I install Logging and Error Reporting for Warp in Codex?

Run `npx skills add warpdotdev/warp --skill logging-and-error-reporting -a codex`. Or copy the skill folder (.agents/skills/logging-and-error-reporting in warpdotdev/warp) into .agents/skills/logging-and-error-reporting in your project. Codex loads it when a task matches its description.

Can I use Logging and Error Reporting for Warp in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add warpdotdev/warp --skill logging-and-error-reporting -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/logging-and-error-reporting, .gemini/skills/logging-and-error-reporting, .github/skills/logging-and-error-reporting and .opencode/skills/logging-and-error-reporting in your project.

What does Logging and Error Reporting for Warp need to run?

SKILL.md names no scripts, command-line tools or credentials: Logging and Error Reporting for Warp is instructions for the agent only. Our summary lists: Access to the Warp repository.

Does Logging and Error Reporting for Warp access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Logging and Error Reporting for Warp safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Logging and Error Reporting for Warp use?

Logging and Error Reporting for Warp is published under the AGPL-3.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Logging and Error Reporting for Warp use?

About 5.6k tokens (SKILL.md is roughly 22k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Logging and Error Reporting for Warp?

Skills that share tags, products or a category with Logging and Error Reporting for Warp: Rust Skills (JMBeresford/retrom, 2.1k stars), Logging Observability (getsentry/toolkit, 917 stars), Sentry v8 Error Tracking (diet103/claude-code-infrastructure-showcase, 10k stars) and Error Handler (EliasOulkadi/shokunin, 114 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Logging and Error Reporting for Warp?

warpdotdev (a GitHub organization) maintains it in warpdotdev/warp, which has 65,380 GitHub stars. The repository holds 46 skills in this directory. The repository was last updated on October 7, 2026.

Source: warpdotdev/warp on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.