Skills DirectorySkills Directory
SkillsLearnSecurityCategoriesDocsCommunityBlog
Sign InSubmit Skill
Skills Directory

Security-tested agent skills for Claude, coding agents, and AI workflows.

Directory

  • Browse Skills
  • All Skills A–Z
  • Claude Skills
  • Claude Code Skills
  • Agent Skills
  • Categories
  • Submit a Skill

Learn

  • Learn Hub
  • Install Claude Skills
  • Write SKILL.md
  • Skills vs MCP
  • Directories Compared

Security

  • Security
  • Methodology
  • Secure Claude Skills
  • Security Badges

Company

  • About
  • Community
  • Blog
  • API Docs
  • Advertise

2026 Skills Directory. All rights reserved.

Back to skills

Sentry

ASecurity

Investigate a Sentry issue - retrieve the issue, latest event, stack trace, tags, and breadcrumbs from kangentic.sentry.io and diagnose it. Use when a task or the user says to investigate/look at/diagnose a Sentry issue or link, or to check what errors are arriving.

116 stars
0 votes
0 copies
0 views
Added 9/22/2026
developmentjavascriptrustgojavac++shellbashsqlreactnode

Works with

cliapimcp

Security Analysis

A100/100

Scanned 9/22/2026

Install to Claude Code

$npx -y skills add Kangentic/kangentic --skill sentry --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Sentry?

Add the live security badge to your README — it updates automatically with every re-scan.

Security grade badge for Sentry
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/kangentic-sentry/badge)](https://www.skillsdirectory.com/skills/kangentic-sentry)

More formats (shields.io, HTML) on the badges page.

Download Zip
Files
SKILL.md
---
description: Investigate a Sentry issue - retrieve the issue, latest event, stack trace, tags, and breadcrumbs from kangentic.sentry.io and diagnose it. Use when a task or the user says to investigate/look at/diagnose a Sentry issue or link, or to check what errors are arriving.
---

# Sentry

Retrieve and diagnose issues from the `kangentic` Sentry org (`kangentic.sentry.io`). Two
projects live there: `desktop` (this Electron app, numeric id `4511996066660352`) and `mobile`
(the React Native app, numeric id `4511808149651456`). Desktop error reporting is wired in
`src/main/analytics/error-reporting.ts`; docs/analytics.md ("Error Reporting") describes what
gets captured and how.

## Auth (never print the token)

Requests need a bearer token. Resolution order (Kangentic-scoped on purpose, so another
repo's generic `SENTRY_AUTH_TOKEN` is never picked up by mistake):

1. `KANGENTIC_SENTRY_TOKEN` environment variable, if set.
2. On Windows, the User-level registry value for the same name (covers a process tree started
   before the variable was set): `[Environment]::GetEnvironmentVariable('KANGENTIC_SENTRY_TOKEN','User')`.
3. The `token = ...` line in `~/.sentryclirc` (usually the CI upload token; reads 403 on it).

Read the token into a shell variable and pass it as a header in the SAME command; never echo
it, never write it to a file, never include it in a reply.

A persisted token doubles as a build switch: `scripts/build.js` and `vite.config.mts` activate
release sourcemap upload whenever `KANGENTIC_SENTRY_TOKEN` (or `SENTRY_AUTH_TOKEN`) is present
at build time. A Windows User-level value survives into every later `npm run build`, so store
the token that way only if local production builds attempting an upload is acceptable;
otherwise set it per-session. A local build that uploads writes real artifact bundles to the
`desktop` project under `Kangentic@<version>`, which is harmless (Sentry matches by debug id, so
bundles from a build nobody shipped simply go unused) but is not nothing.

Release builds run only on the CI matrix, so what actually decides whether a RELEASE gets symbols
is the `KANGENTIC_SENTRY_TOKEN` repository secret, not any local value. The `preflight-symbols`
job in `.github/workflows/release.yml` fails the release when that secret is missing.

Scopes: reading issues/events needs `event:read` + `project:read` + `org:read` (a User Auth
Token from Settings > Account > API > Auth Tokens; assigning and resolving issues additionally
need `event:write`). A `403` from every endpoint means the stored token is a CI-scoped one
(`org:ci` - it can only upload sourcemaps): stop and ask the user to mint a read-scoped token
rather than retrying. A `403` on the assign PUT alone means the token is read-only: report the
issues you could not mark and carry on, never let it block the triage itself.

## Retrieval

Parse the issue id from a pasted URL: `https://kangentic.sentry.io/issues/<ISSUE_ID>/?...`
(the `project=` query param is the numeric project id, useful for list queries).

PowerShell pattern (one call per request; substitute the endpoint):

```powershell
$token = $env:KANGENTIC_SENTRY_TOKEN; if (-not $token) { $token = [Environment]::GetEnvironmentVariable('KANGENTIC_SENTRY_TOKEN','User') }; if (-not $token) { $token = ((Get-Content "$env:USERPROFILE\.sentryclirc") | Where-Object { $_ -match '^token\s*=' }) -replace '^token\s*=\s*','' }; Invoke-RestMethod -Uri 'https://sentry.io/api/0/organizations/kangentic/issues/<ISSUE_ID>/' -Headers @{ Authorization = "Bearer $token" } | ConvertTo-Json -Depth 8
```

macOS/Linux (Bash, one command): `curl -s -H "Authorization: Bearer $KANGENTIC_SENTRY_TOKEN" <url>`.

The endpoints that matter:

| What | Endpoint |
|---|---|
| Issue summary (title, culprit, count, userCount, firstSeen/lastSeen, level, substatus) | `GET /api/0/organizations/kangentic/issues/<ISSUE_ID>/` |
| Latest event (stack trace, tags, breadcrumbs, contexts, release) | `GET /api/0/organizations/kangentic/issues/<ISSUE_ID>/events/latest/` |
| All events for the issue | `GET /api/0/organizations/kangentic/issues/<ISSUE_ID>/events/` |
| Search issues (e.g. new unresolved desktop issues) | `GET /api/0/organizations/kangentic/issues/?project=4511996066660352&query=is:unresolved&statsPeriod=14d` |
| Assign an issue (the triage marker, see below) | `PUT /api/0/organizations/kangentic/issues/<ISSUE_ID>/` body `{"assignedTo":"user:<USER_ID>"}` |
| Resolve an issue against a release (see Resolution markers) | `PUT /api/0/organizations/kangentic/issues/<ISSUE_ID>/` body `{"status":"resolved","statusDetails":{...}}` |
| Releases in the project, newest first (which versions Sentry knows) | `GET /api/0/organizations/kangentic/releases/?project=4511996066660352` |
| Org members (read `user.id` for the actor above) | `GET /api/0/organizations/kangentic/members/` |

The latest-event payload is large; extract what you need rather than dumping it: `entries`
with `type: "exception"` carries the stack frames, `type: "breadcrumbs"` the trail, `tags`
carries `source`/`reason` (stamped by `reportHandledError` for handled forwards), release,
environment, and the anonymous install id under `user.id` (non-reversible; `userCount` on the
issue = affected installs).

## Diagnosis

- **Mechanism first.** `mechanism` on the exception says how it was caught: `onunhandledrejection`
  / `onerror` (renderer globals), `generic` via `captureException` (a boundary or
  `reportHandledError` - check the `source` tag: `updater`, `pty_spawn`, `spawn`, `global_db_read`,
  `utility_process`). A `utility_process` event carries a `utility_process` context block under
  `contexts` with the worker's stderr tail; read that before the stack, since the stack is only the
  restart policy's report site and the tail is what the worker printed before it died.
- **Symbolication caveat:** packaged-release events resolve to real file/line only once a
  release build uploaded sourcemaps (`KANGENTIC_SENTRY_TOKEN` set during `npm run build`;
  `SENTRY_AUTH_TOKEN` is accepted as the fallback). A dev
  event's renderer frames are unminified module URLs (readable); a packaged event without
  uploaded maps shows minified positions - lean on message, mechanism, tags, and breadcrumbs.
- **Environment tag** separates `development` (forced-on dev/preview runs) from `production`
  (packaged installs). Do not chase dev-only test events (`Kangentic telemetry verification:` is
  the preview rig's own test error).
- **Exactly 50 frames means the stack is TRUNCATED, not complete.** The SDK caps a parsed stack
  at 50 (`STACKTRACE_FRAME_LIMIT` in `@sentry/core`, and `Error.stackTraceLimit = 50` set by
  `@sentry/browser`'s globalHandlers integration). It reads a V8 stack innermost-first and stops
  there, so the frames it discards are the OUTER ones: the app code that called into the library,
  and the timer or handler the whole thing ran under. Count the frames before concluding anything.
  At exactly 50, `in_app: false` on every frame does NOT mean the app is uninvolved, and the
  outermost frame is "the deepest point still visible", never "where it started". Once the
  release carrying `tagTruncatedStack` (`src/main/analytics/error-reporting.ts`) ships, a capped
  event carries a `stack_truncated: 'true'` tag; every event from before it must be counted by
  hand, and so must any event with no such tag, since its absence is ambiguous until that
  release is the only one reporting. DESKTOP-19 cost a whole investigation round to this: six
  events, fifty monaco frames each, no in-app frame, and the app frame that armed the call
  truncated away.
- **Read the `context` lines rather than reasoning from function names.** When sourcemaps are
  uploaded every frame carries `context` (the source line plus surrounding lines). That is
  authoritative and beats reading `node_modules` locally. Print it for the load-bearing frames:
  `$event.entries | Where-Object type -eq 'exception'` then each frame's `.context`.
- **Resolve library frames against the version the RELEASE shipped**, read from `package.json` at
  that git tag (`git show v0.41.0:package.json`), not from the current tree. A dependency bump
  between the first-seen release and today silently invalidates every line-number mapping and
  every prior "could not reproduce" measurement. DESKTOP-19 spans a monaco 0.55.1 -> 0.56.0 bump,
  which both rules the bump out as the cause and means the 0.55.1 measurement behind the earlier
  fix no longer describes the shipping code.
- **Same-timestamp event pairs are not always double reports.** Compare the pair's stacks before
  dividing the event count: DESKTOP-19's pairs have different outermost frames, so each incident
  threw twice rather than being reported twice.
- **The `mechanism` tag is evidence about the SCHEDULER, and it is checkable.**
  `auto.browser.browserapierrors.setTimeout` means the chain ran inside a real `setTimeout`
  callback, so enumerate the candidate timers in the implicated subsystem and rule them out one
  by one. On DESKTOP-19 the obvious suspect (Monaco's background tokenizer) was eliminated from
  source - it schedules with `runWhenGlobalIdle` and yields with `setTimeout0`, which uses
  `postMessage` in a renderer - which left exactly one app-owned timer.
- **A default-off setting can be the missing precondition.** When an issue hits very few installs,
  check whether the code path needs a non-default setting before concluding it is unreproducible.
  DESKTOP-19 needs "Collapse Unchanged Regions" on, which defaults to off.
- **Cross-reference locally:** the same failure usually has a local trail - `.kangentic/logs/`
  (crash JSONs, main console), `kangentic_tail_logs`, and the Aptabase `app_error` /
  `spawn_failed` counts are the volume view of the same signal.

## Native minidumps (`platform: native`, mechanism `minidump`)

A native crash's frames arrive as raw addresses with `function: null` for any module Sentry has
no debug file for (node-pty's `conpty.node` / `pty.node`, `better_sqlite3.node`). They can still
be resolved offline on a Windows machine, because node-pty ships the matching PDB in its npm
tarball (`node_modules/node-pty/prebuilds/win32-x64/conpty.pdb`):

1. Read the `debugmeta` entry: for the module, take `image_addr` (the load base) and `debug_id`.
2. Confirm the shipped PDB is the same build: `dumpbin /HEADERS <path to conpty.node>` prints the
   RSDS record (`{GUID}, age, pdb path`); it must equal `debug_id` (`<guid>-<age>`).
3. RVA = `instructionAddr - image_addr` for every frame in that module, `trust: scan` ones
   included (scanned frames are stale, but they name what ran on this stack recently).
4. Resolve the RVAs with dbghelp from PowerShell, no debugger install needed: P/Invoke
   `SymSetOptions` (undname, deferred loads, load lines), `SymInitializeW`,
   `SymLoadModuleExW(hProcess, 0, <path to conpty.node>, null, 0x180000000, <size of image>, 0, 0)`
   (the PDB is found next to the image), then `SymFromAddrW` and `SymGetLineFromAddrW64` at
   `0x180000000 + RVA`. Function plus source line come back; this is how DESKTOP-C resolved to
   `Napi::Error::ThrowAsJavaScriptException` inside `ThreadSafeFunction::CallJS`'s catch block.
5. Read the frames as a C++ story: `_CxxThrowException` is the throw site,
   `__FrameHandler4::CxxCallCatchBlock` above it means the throw happened inside a catch block,
   and `RtlDispatchException` / `RtlUnwindEx` further out mean an exception was already being
   handled when this one was raised.

The Windows release build uploads those PDBs as Sentry debug files when the token is present
(`scripts/build.js`), so a future event should symbolicate without this. `Kangentic.exe` frames
carry names only because Electron publishes its symbols.

Reading a native event, in order of what trips people up:

- **Check for a `native_crash` context first.** `beforeSend`
  (`src/main/analytics/native-crash-event.ts`) writes one from the dump itself: `crash_time`,
  `crashed_version`, `uploaded_by_version`, `main_module`, `module_count`, `found_at_startup`, and
  whether the release or the app context was corrected. Absence means one of two things: the event
  predates that filter, or its dump could not be parsed and was therefore kept untouched. Either
  way the two traps below still apply to it in full.
- **On an Electron OOM (`exit.reason: oom`, `mechanism: minidump`), read
  `contexts.chromium_stability_report.system_memory_state` before anything else.** It carries
  `system_commit_limit` and `system_commit_remaining` - the Windows commit charge, not physical
  RAM - alongside the crashing process's own `process_states[0].memory_state.windows_memory`
  (`process_private_usage`, `process_peak_pagefile_usage`, `process_allocation_attempt`). This one
  field answers "did the process grow, or did the host run out" without touching a single stack
  frame: DESKTOP-16 was a renderer holding 179 MB (smaller than a healthy long session) that died
  because the MACHINE had 2.15 MB of commit left out of an 89.8 GB limit, with 4.66 GB of physical
  RAM still free. Chromium's own OOM frames (`PartitionsOutOfMemoryUsingLessThan16M`,
  `PartitionOutOfMemoryCommitFailure`) name which allocation-size bucket failed and that it was a
  commit refusal, but they say nothing about whose growth caused it - `system_commit_remaining`
  is the only field that separates "renderer leak" from "host exhausted" and it takes one read to
  check. Also see `contexts.host_memory` if the event postdates DESKTOP-16's fix
  (`src/main/diagnostics/host-memory.ts`), which carries main's own periodic sample of the same
  Windows commit figures via a different, verified route (`process.getSystemMemoryInfo()`).
- **On an older event, the release tag is the UPLOADING build's, not the crashed one's.**
  Crashpad writes the dump and the next launch uploads it; if the user upgraded in between, the
  tag is a build that never crashed. `contexts.crashpad._version` is the build that did.
  DESKTOP-M cost a triage sweep a wrong conclusion this way.
- **A shifted stack re-groups into a new issue, so "no new event on this issue" does not mean
  the crash class is gone.** Native grouping keys off stack frames, and inlining, a different
  thread interleaving, or an ASLR-shifted offset can move the same underlying bug into a fresh
  shortId. Verifying a fix held on a later release needs a `release:Kangentic@X` query, not
  `firstRelease:`, which misses a group born on an older release that still carries events on X.
  Drop the `is:unresolved` and the `statsPeriod` that this skill's query examples carry. Both hide
  events the release genuinely produced, which breaks the count. Sum every returned group and
  check the total against that release's own event count from the releases endpoint. A match
  means every event the release produced is accounted for by a named group; read each group's
  title to confirm none is the crash class in question. A mismatch means the search was
  incomplete, not that a recurrence is hiding. Widen it and count again. Task #669
  (DESKTOP-Y/DESKTOP-Z) is where this mattered: 0.41.0's six new groups summed to its entire
  16-event volume, and none was a teardown crash.
- **Breadcrumbs on a startup-found dump are not the crashed session's.** On an older event they
  are the uploading launch's, wholly or partly; on a corrected one they are removed rather than
  left to mislead. Breadcrumbs on an event tagged `exit.reason` are trustworthy: that tag marks
  the two SDK paths that report a crash the running session watched happen.
- **A crash in a process Kangentic merely spawned no longer arrives at all.** On macOS, mach
  exception ports are inherited across exec, so an agent shelling out to ffmpeg, a headless
  browser, or a dotnet tool used to file its crashes as ours. Three sources have been seen:
  DESKTOP-K (Homebrew ffmpeg's `ffprobe`), DESKTOP-N (a Puppeteer `chrome-headless-shell`), and
  DESKTOP-Q (`/usr/local/share/dotnet/dotnet`, ten events). One filter covers all three, since it
  keys off whether the dump loaded a Kangentic image rather than off any binary's name. Task #604
  tracks DESKTOP-Q, though no commit names it. Those are dropped before upload now and counted as
  Aptabase `foreign_minidump_dropped` instead. If a native issue looks like someone else's binary,
  check that counter rather than expecting a Sentry issue.
- **Scope persists with a 500 ms write throttle**, so on any event the last half-second of
  breadcrumbs before the crash is missing. An entire quit sequence fits in that gap.

## Typical requests

**"Any new issues?" (triage scan).** Query each project (or the one named) for what needs
eyes, newest first:

```
GET /api/0/organizations/kangentic/issues/?project=4511996066660352&query=is:unresolved is:for_review&statsPeriod=14d&sort=date
```

Run it for both project ids unless the user scoped to one. Report a compact per-issue line:
shortId, title, count, userCount (affected installs), firstSeen, environment, and the link
(`https://kangentic.sentry.io/issues/<id>/`). Two filters keep the report honest:

- Treat `environment: development` events as dev/preview noise (the
  `Kangentic telemetry verification:` issues are the rig's own test errors) - list them
  separately or not at all, never alongside production issues without saying so.
- "New" means new to the user: an **unassigned** issue whose shortId appears in no board task.
  Assignment is the triage marker (see below), so start the sweep by reading `assignedTo` on
  each issue and treat an assigned one as already looked at. Still confirm with
  `kangentic_search_tasks` for the shortId, because assignment can be stale and a task can
  exist without one, but an assigned issue is never reported as new.

**"Investigate this issue / create a follow-up task."** Retrieve the issue and latest event,
diagnose (below), then - when asked for a task - create ONE task via the kangentic MCP tools,
routed by project: a DESKTOP-* issue goes on the `kangentic` board; a MOBILE-* issue (or a
REACT-NATIVE-* one - issues created before the 2026-08 slug rename keep their old prefix) on
`kangentic-mobile`. First search for an existing task carrying the shortId so a re-report never
duplicates. Title: `Fix DESKTOP-N: <issue title, trimmed>`. Description: the Sentry link,
shortId, level, event/affected-install counts, environment + release, the diagnosis, and the
few stack frames or tags that carry it. Default to To Do; the user decides when it spawns.

Three fields belong in that description because leaving them out is what sends the next
investigation down a wrong path:

- **The frame count, and whether the stack is truncated** (see Diagnosis). "50 frames, truncated,
  no app frame survived" and "47 frames, genuinely all third-party" call for completely different
  work, and the event itself does not say which.
- **The release-to-dependency-version mapping** for whatever library the stack lands in, read
  from `package.json` at each affected release's tag. It is what tells the next reader whether a
  version bump is a suspect or already ruled out.
- **Whether the event count is distinct incidents or paired reports**, and any non-default setting
  the path requires.

Never paste a stack frame's raw `file:///` URL or `absPath` into the task: those carry a
contributor's home directory, and the board is mirrored to a public repo. Cite frames by module
path and line (`viewModelImpl.js:145`).

**Then assign every issue the task covers.** Creating a board task and leaving the Sentry issue
unassigned means the next sweep re-derives the whole cross-reference from scratch, which is what
assignment exists to prevent here. Assignment is a triage marker, not a claim of ownership: it
says a human has looked at this and it has a home. Rules:

- Assign after the task is created, never before, so a failed create cannot leave a false marker.
- One task can cover several issues (a cluster, or several issues that resolve in one file).
  Assign all of them, not just the one that named the task.
- Assign issues covered by an EXISTING task too when a sweep turns one up unassigned. The signal
  is only useful if it is complete.
- Never assign an issue with no board task, and never assign dev/preview rig noise. An unassigned
  issue must keep meaning "nobody has dealt with this".
- Resolve nothing here. Assignment leaves the issue in the unresolved stream where a recurrence
  is still visible, which is the whole point: a fix that does not hold shows up as new events on
  an assigned issue rather than disappearing. A native crash is the exception, because a shifted
  stack re-groups into a fresh shortId and the assigned issue stays silent (see Native minidumps
  above). Assignment holds until the fix actually ships, so resolution is a release-time act, not
  a triage one. See Resolution markers below.

## Resolution markers

Resolution is a release-time act. The marker names the release that CARRIES THE FIX, never the one
the issue was last seen on. Which release that is depends on where you are standing. From triage,
before the fix has shipped, the newest release is always the wrong answer, because it predates the
fix. From `/release` Step 8, after the build is published, the version just shipped is the carrier
and is the right answer. Step 8 is where this normally happens; do it by hand only to correct a
marker that is already wrong.

Sentry keeps two resolution types, and they reopen an issue on different events:

- `in_release` against X: an event on X itself reopens the issue, and only releases older than X
  stay suppressed. Naming the current release therefore reopens the issue on exactly the builds
  that legitimately lack the fix.
- `in_next_release` against X: events on X and older stay suppressed, and anything newer reopens.
  That is what "fixed in the release after X" means.

Which body to send:

| Situation | Body of the resolve PUT |
|---|---|
| The release carrying the fix exists in Sentry | `{"status":"resolved","statusDetails":{"inRelease":"Kangentic@X.Y.Z"}}` |
| It does not exist yet (the normal case before that release builds) | `{"status":"resolved","statusDetails":{"inNextRelease":true}}` |

Use the `Kangentic@X.Y.Z` form, not the `vX.Y.Z` git tag. Each release object is created by the
bundler plugin during its own CI build (`scripts/build.js`, `vite.config.mts`), so the version a
pending fix will ship in does not exist yet, and `inRelease` on it fails with a 400 and
"Unable to find a release with the given version."

Four things bite:

1. **A resolve PUT against an already-resolved issue is silently a no-op.** It returns 200 with the
   full group payload and changes nothing. To correct a marker, PUT `{"status":"unresolved"}`
   first, then PUT the resolution. Both writes, in that order, every time.
2. **The read-back cannot tell the two types apart.** `statusDetails` renders
   `inRelease: Kangentic@0.39.0` both for a real `in_release` against 0.39.0 and for an
   `in_next_release` recorded against it, so it cannot confirm a write landed. Verify with the
   issue payload's own `activity` array: the newest `set_resolved_in_release` entry carries a
   populated `version` for an in-release resolution, and an empty `version` plus
   `current_release_version` for an in-next-release one.
3. **The GitHub integration resolves issues without being asked.** Merging a PR whose body names a
   shortId writes a `set_resolved_in_pull_request` entry, and commit-to-release association can
   follow it with a `set_resolved_in_release` naming whichever release was current then. DESKTOP-J
   carried a wrong marker from that path, not from a hand action. So expect an issue to arrive at
   the release step already resolved, and correct it rather than assuming a human chose it.
4. **A 403 on the resolve PUT means the token is read-only or CI-scoped.** Report which issues went
   unmarked and carry on. Never retry in a loop, and never let it block a release.

## Boundaries

- Diagnose and report; fix only when the task asks for a fix.
- Create a follow-up board task only when asked ("create a follow up task" style requests):
  include the Sentry link, shortId, affected-install count, and your diagnosis in the
  description.
- Assigning an issue you just filed a task for is sanctioned and expected, no separate ask
  needed. It is the one write this skill makes on its own.
- Do not resolve/archive issues in Sentry unless explicitly asked (needs `event:write`). Resolving
  belongs to `/release` Step 8, which marks the issues a release fixes once that release exists;
  from here, resolve only to correct a marker that names the wrong release. Either way follow
  Resolution markers above.
- Never paste the token or a full raw event dump into a task, commit, or reply; quote the
  frames and fields that carry the diagnosis.

Attribution

KangenticKangentic
View sourceMore from Kangentic →
SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments (0)

No comments yet. Be the first to comment!

SSkills DirectorySkills Directory

Ship a skill? Prove it's safe.

Free 120-pattern security scan, letter grade, and an embeddable README badge.

Submit a skill

Related Skills

Browser Extension Developer

Use this skill when developing or maintaining browser extension code in the `browser/` directory, including Chrome/Firefox/Edge compatibility, content scripts, background scripts, or i18n updates.

284072 votes

Seo Optimizer

SEO optimization with keyword analysis, readability assessment, technical validation, content quality. Use for search rankings, blog posts, content audits, or encountering keyword density, readability scores, meta tags, schema markup errors.

2192 votes

Google Official Seo Guide

Official Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation

1862 votes

Tanstack Start

Build a full-stack TanStack Start app on Cloudflare Workers from scratch — SSR, file-based routing, server functions, D1+Drizzle, better-auth, Tailwind v4+shadcn/ui. Use whenever the user mentions TanStack Start, asks to scaffold a full-stack Cloudflare app with SSR, wants an SSR dashboard, or asks for a React 19 + Cloudflare Workers app with file-based routing and server functions — even if they don't name TanStack Start specifically. No template repo — Claude generates every file fresh per ...

9881 votes

Pentest

PTES-aligned adversarial security audit for backend, frontend, and mobile applications. Produces a CVSS-scored Hacker Report with verified PoCs and phased remediation.

5491 votes
View all in development →