ts-audit — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited ts-audit (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Audit TypeScript code against 9 expert-level references covering type safety, generics, advanced patterns, React integration, type transformations, and testing. The goal is to surface concrete improvements the author may not have considered — not to nitpick style, but to catch real type-safety gaps, missed narrowing opportunities, and patterns that would make the code more robust.
The user provides a target: a file path, directory, or glob pattern. Examples:
/ts-audit src/db/queries.ts/ts-audit src/pipeline//ts-audit src/**/*.tsxThis is a side-route skill for TypeScript code quality auditing, not a default pipeline step.
Use /ts-audit when you want to audit TypeScript or React code against expert-level patterns from the Total TypeScript library references — whether on a single file, a directory, or a glob of changed files.
Do not use it as a substitute for /pre-merge architectural review (which checks structural principles) or /tdd (which enforces red-green-refactor). It complements both by focusing specifically on type-safety gaps and TypeScript idiom improvements.
For TypeScript projects, /ts-audit pairs naturally with /pre-merge Phase 3 (Architectural Review) — running it on changed files provides type-safety analysis that complements the seven structural dimensions.
**/*.ts and **/*.tsx files within itFor large targets (>15 files), focus on files with the richest type-level code — interfaces, generics, service layers, component props. Skip auto-generated files (*.gen.ts, *.d.ts).
Resolve the library path:
echo "${CLAUDE_LIBRARY_DIR:-$([ -f "$HOME/.claude/library/index.json" ] && echo "$HOME/.claude/library" || echo "NOT_FOUND")}"Select which books to load based on what's in the target. This keeps context lean — only pay for what you need.
Always load (core):
| Book | What it covers |
|---|---|
total-typescript-book | Core type system — inference, narrowing, unions, satisfies, as const |
ts-essentials | Essential patterns — annotations, type guards, discriminated unions |
ts-generics | Generic scope, constraints, inference, overloads |
ts-type-transforms | Mapped types, conditional types, template literals, infer |
advanced-ts-patterns | Branded types, assertion functions, identity functions, const T |
Load if target contains `.tsx` files or files that import React:
| Book | What it covers |
|---|---|
react-ts-patterns | React props typing, hooks, ComponentProps, discriminated union props |
*Load if target contains test files (`.test.ts, .test.tsx`, `.spec.ts`):**
| Book | What it covers |
|---|---|
testing-fundamentals | Test structure, assertions, async testing |
advanced-vitest-patterns | Fixtures, custom assertions, performance testing |
mocking-techniques | MSW, dependency injection, fake timers, typed mocks |
Read each selected SKILL.md (path: {LIB}/books/<name>/SKILL.md) into context. These contain lookup tables, decision matrices, and anti-pattern catalogs that form the audit criteria.
Also consult these companion skills when the target uses Zod (these live in ~/.claude/skills/, not the library):
| Skill | Load when |
|---|---|
/zod | Any source file in target imports zod — covers schema design, safeParse, z.infer, refinements, transforms, codecs, branded types, and v3→v4 migration concerns |
/zod-testing | Test files in target import zod or reference zod schemas — covers schema correctness, error assertion patterns, z.toJSONSchema() snapshots, and mock-data generation |
Read each companion skill's SKILL.md (path: ~/.claude/skills/<name>/SKILL.md) and any rule files it points at. Treat them as authoritative for Zod-specific findings the same way Total TypeScript books are authoritative for general type-system findings.
Work through each file and check against the loaded references. The categories below describe what to look for — the specific rules come from the library references you just loaded.
status: string when only "approved" | "denied" | "tabled" are valid)any where unknown would be saferas type assertions that bypass narrowing — could the code use a type guard or discriminated union instead?string or number where branded types would prevent value confusionsatisfies LibraryReturnType, return a fresh object literal, or derive the local type via ReturnType<…> / Parameters<…>. Cite: ts-essentials Rule 31, "Use satisfies for type validation without losing inference precision."T with no extends)function declarations)const T parameter to preserve literal typesuserId vs orderId)typeof, mapped types, or conditional types would derive from a single source of truthReturnType<fn> instead of ReturnType<typeof fn>.tsx files or files importing ReactComponentProps<"element">useState, useRef/zod) — files importing zodparse() at trust boundaries where safeParse() would let the caller branch on validation failure without exceptionsz.infer<typeof Schema> would derive them from a single source of truthz.nativeEnum() in code targeting Zod v4 (removed — use z.enum() over the values, or z.literal unions).refine(...) regex when Zod v4's first-class formats (z.email(), z.url(), z.uuid(), z.iso.datetime(), etc.) apply.refine() chains that mask which check failed — splitting into multiple .refine() calls with distinct messages, or moving to .superRefine() with ctx.addIssue, surfaces clearer error paths.error.format() for programmatic handling where .error.issues (the flat array) is the v4-preferred shapetry/catch around parse() — the thrown value is ZodError, not generic; safeParse + discriminant check preserves the typed error channel/zod-testing) — test files referencing zod schemasexpect(result.success).toBe(false) without asserting on result.error.issues[i].code or path — the test passes for any rejection reason, not the intended onezod-schema-faker (or equivalent) would generate conforming fixtures from the schema itself.min()/.max() constraints (off-by-one edges)z.toJSONSchema(Schema) as a structural assertion instead of brittle object snapshotsAfter catching the obvious issues above, make a second pass specifically looking for opportunities to apply the non-obvious patterns from each loaded reference. These are the findings that differentiate this audit from what any TypeScript developer would notice:
From advanced-ts-patterns: Look for functions that accept string or number parameters where the values are semantically distinct (e.g., a userId and an orderId both typed as string). Suggest branded types at the boundaries. Look for assertion functions written as arrow functions — they must use function declarations. Check if any generic function would benefit from const T to preserve literal types from callers.
From ts-type-transforms: Look for manually duplicated type shapes across files (write-side vs read-side types, DTO vs entity). Suggest Pick, Omit, intersection types, or mapped types to derive from a single source of truth. Check for ReturnType<fn> that should be ReturnType<typeof fn>.
From ts-generics: Look for generics placed at class or module scope that could be narrowed to function scope. Look for functions returning different types based on input where overloads would make the contract clearer. Check for unconstrained T parameters that should have extends bounds.
From react-ts-patterns (if loaded): Look for components wrapping HTML elements that don't use ComponentProps<"element"> to forward props. Check for mutually exclusive prop combinations modeled as separate optional props instead of a discriminated union. Look for manual event handler types that could be derived from React's event types.
From testing books (if loaded): Look for test.extend() fixture opportunities where multiple tests share the same setup. Check for typed mock patterns — are mocks losing type information? Look for API calls being mocked inline that should use MSW for more realistic testing. Check if Effect-based code is being tested via runPromise + rejects.toThrow() instead of runPromiseExit which preserves the typed error channel.
From `/zod`, `/zod-testing` (if loaded): Look for places where a Zod schema and a manually-declared TS type describe the same shape — z.infer<typeof Schema> collapses the drift surface. Look for parse() calls at system boundaries (HTTP handlers, form submissions, env var parsing) where safeParse() would let the caller respond gracefully instead of throwing. Check for v3-isms in v4 code (nativeEnum, custom regex for emails/URLs, .error.format() for programmatic flow). In test files, check that error assertions inspect issues[i].code/path — not just success === false — so the test actually pins down which validation failed. Watch for schemas reconstructed inside hot paths (request handlers, render bodies) that should be hoisted to module scope, and for handler/integration tests that bypass the schema layer they exist to verify.
The goal of this second pass is to surface at least 1-2 findings per loaded library that go beyond what a developer would catch from general TypeScript knowledge alone. If a library's patterns genuinely don't apply to the target code, that's fine — skip it. But look carefully before deciding nothing applies.
The report quotes source code verbatim, and it is a portable artifact — users paste it into a PR, drop it in chat, or hand it to another agent. Source files routinely carry secrets, so masking is not optional and not best-effort: run this pass on every snippet before it goes into the report.
*_KEY, *_SECRET, *_TOKEN, *_PASSWORD, AKIA…, sk-…, ghp_…, xox[baprs]-…, bearer tokens, postgres://user:pass@… and other credentialed URIs, PEM blocks.STRIPE_SECRET_KEY=sk_live_•••••••• keeps the finding legible without leaking the credential. The type pattern is what the finding is about; the secret is not.Structure the report as markdown:
# TypeScript Audit Report
**Target:** <file or directory>
**Files analyzed:** <count>
**Findings:** <count>
---
## <Category Name>
_Source: <library book name(s)>_
### <Short description of the finding>
**File:** `<path>`:<line>
**Current code:**
\`\`\`ts
// the relevant snippet
\`\`\`
**Suggested change:**
\`\`\`ts
// the improved version
\`\`\`
**Why:** <1-2 sentences explaining what pattern this violates and why the suggestion is better, grounded in the library reference>
---Grouping: by category (Type Safety, Generics, etc.), not by file. Within each category, order findings by file path then line number.
What to include in each finding:
What to omit:
End with a summary table:
## Summary
| Category | Findings |
|----------|----------|
| Type Safety | N |
| Generics | N |
| ... | ... |
| **Total** | **N** |If no findings at all:
No issues found. The code aligns well with the patterns from the TypeScript library collection.
/execute when findings warrant code changes, or /pre-merge when the audit informs the architectural review conversation~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.