Skip to content

Claude Code plugin

Claude writes TypeScript. TypeScript Patterns Enforcer checks every edit.

An inline skill, a review subagent, and a hook that runs ten checks after every .ts edit and sends violations back to Claude.

/plugin marketplace add gagoar/typescript-patterns-enforcer
/plugin install typescript-patterns-enforcer@typescript-patterns-enforcer
/reload-plugins

See it work

Claude writes it. The hook flags it. Claude fixes it.

Toggle the same function before and after the hook runs. Each file below is one of the failing and passing fixtures from engine/test/fixtures/.

PostToolUse · node engine/dist/check.js
1 violation clean
describeStatus.ts
export function describeStatus(status: string): string {  return status === "active" ? "Active" : status === "paused" ? "Paused" : "Unknown";}
const STATUS_LABELS: Record<string, string> = { active: "Active", paused: "Paused" };export function describeStatus(status: string): string {  return STATUS_LABELS[status] ?? "Unknown";}
Hook output
ts-patterns: 1 mechanical violation(s) in describeStatus.ts:
  L2:10  no-nested-ternary  nested ternary — flatten, or convert to a Record/.find() lookup (see SKILL.md Data Over Logic).  → SKILL.md Data Over Logic — flatten or convert nested ternaries to a Record/.find() lookup
Fix these to satisfy the TypeScript patterns before continuing.

exit code 2  (stderr goes back to Claude)
clean  no output

exit code 0

Automatic

Runs after every edit.

The hook reads the file Claude just edited. If a check fails, the message goes to Claude and Claude fixes the file before moving on. Clean files produce no output.

  • TriggerOne PostToolUse hook, in hooks/hooks.json. It runs node engine/dist/check.js.
  • ScopeOnly .ts and .tsx files.
  • OutputViolations go to stderr with exit code 2, which sends them back to Claude.
  • Side effectsNone: the engine's own code writes nothing to disk, makes no network calls, and starts no other process.
  • No NodeIf Node is missing or the check cannot run, the hook exits with no output. The skill's written rules then remain the only enforcement.

What you get

Three parts, one standard.

Skill

/typescript-patterns-enforcer:check is active while Claude writes or edits TypeScript. It gives inline guidance on type safety, patterns, and anti-patterns.

Agent

typescript-patterns-enforcer:review handles full PR reviews, large refactors, and JavaScript to TypeScript conversions.

Hook

A bundled checker runs after every .ts or .tsx edit. It brings its own parser, and it ignores your repo's config.

The core rules

Eleven rules for the skill to enforce.

The skill also covers data over logic, validation at the boundary, and comment discipline. A hook tag marks a rule the hook also checks mechanically.

  1. No anyhookUse unknown and narrow, or write a precise type.
  2. Explicit return typesAnnotate public functions.
  3. interface vs typeinterface for extendable shapes. type for unions, intersections, and mapped types.
  4. readonly by defaultMutable only when mutation is required.
  5. async/await onlyhookNo .then() chains. Return Promise<T> explicitly.
  6. Typed errorsCustom error classes or discriminated-union results.
  7. Constrained generics<TEntity extends BaseEntity>, not <T>.
  8. Composition over inheritancePlain functions and utility types first.
  9. No magic valueshook: numbersName repeated or meaningful literals in comparisons or branching.
  10. Coerce over compareif (!items.length), not items.length === 0.
  11. Every regex carries an examplehookA comment directly above it: plain words, a quoted match and reject, and a pre-filled regex101 link.

The ten mechanical checks

The checks find the pattern. Rewriting it well stays with Claude and the skill, because a linter can ban a switch but cannot rewrite one.

CheckCatches
no-explicit-anyA bare any
ban-ts-comment@ts-ignore with no description
no-magic-numbersUnnamed numeric literals
prefer-await-to-then.then() chains
no-switch-statementswitch statements
no-param-reassignParameter mutation
no-loop-statementsRaw for and while loops
no-nested-ternaryNested ternaries
require-regex-exampleA regex literal with no plain-words comment, example, or tester link above it. Advisory: it checks for a quoted string and an https:// link.
no-narrative-commentComments that narrate history. Advisory: it matches a list of phrases, so it misses some and flags some.

Evidence

Tested before it ships.

10 checks

Each has a failing fixture and a passing fixture. The test suite runs against the built hook.

0 config

The engine bundles its own parser and rules. It never reads or writes your repo's setup.

MIT

Open source. Fixtures live in engine/test/fixtures/.

Install it in 10 seconds.

/plugin marketplace add gagoar/typescript-patterns-enforcer
/plugin install typescript-patterns-enforcer@typescript-patterns-enforcer
/reload-plugins

Formerly ts-patterns. Installed that one? Run /plugin uninstall ts-patterns@gago-plugins, then install the new name. Details