Help us improve
Share bugs, ideas, or general feedback.
From typescript
ALWAYS invoke this skill when writing or fixing implementation code for TypeScript.
npx claudepluginhub outcomeeng/claude --plugin typescriptHow this skill is triggered — by the user, by Claude, or both
Slash command
/typescript:coding-typescriptThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
<accessing_skill_files>
Enforces TypeScript strict mode configs, Vitest testing with 95%+ coverage, ESLint rules, and CI/CD quality check commands for TS projects.
TypeScript deep-dive skill covering type-level programming, performance optimization, monorepo patterns, and migration strategies. Also redirects to specialized subagents for bundler/module/type issues.
Guides technical evaluation of code review feedback: read fully, restate for understanding, verify against codebase, respond with reasoning or pushback before implementing.
Share bugs, ideas, or general feedback.
<accessing_skill_files> When this skill is invoked, Claude Code provides the base directory in the loading message:
Base directory for this skill: {skill_dir}
Use this path to access skill files:
{skill_dir}/references/{skill_dir}/workflows/IMPORTANT: Do NOT search the project directory for skill files. </accessing_skill_files>
<essential_principles> NO MOCKING. DEPENDENCY INJECTION. BEHAVIOR ONLY. TEST FIRST.
strict: true, no any without justification</essential_principles>
<mandatory_code_patterns> These patterns are enforced by the reviewer. Violations will be REJECTED.
All literal values (strings, numbers) must be module-level constants:
// ❌ REJECTED: Magic values inline
function validateScore(score: number): boolean {
return score >= 0 && score <= 100;
}
// ✅ REQUIRED: Named constants
const MIN_SCORE = 0;
const MAX_SCORE = 100;
function validateScore(score: number): boolean {
return score >= MIN_SCORE && score <= MAX_SCORE;
}
Share constants between code and tests — tests import from the module under test:
// src/scoring.ts
export const MIN_SCORE = 0;
export const MAX_SCORE = 100;
// spx/.../tests/scoring.unit.test.ts
import { MIN_SCORE, validateScore } from "@/scoring";
it("rejects below minimum", () => {
expect(validateScore(MIN_SCORE - 1)).toBe(false);
});
External dependencies must be injected, not imported directly:
// ❌ REJECTED: Direct import
import { execa } from "execa";
async function syncFiles(src: string, dest: string): Promise<boolean> {
const result = await execa("rsync", [src, dest]);
return result.exitCode === 0;
}
// ✅ REQUIRED: Dependency injection
interface SyncDeps {
execa: typeof execa;
}
async function syncFiles(
src: string,
dest: string,
deps: SyncDeps,
): Promise<boolean> {
const result = await deps.execa("rsync", [src, dest]);
return result.exitCode === 0;
}
</mandatory_code_patterns>
<hierarchy_of_authority> Where to look for guidance, in order of precedence:
| Priority | Source | What It Provides |
|---|---|---|
| 1 | docs/, README.md | Project architecture, design decisions, intended APIs |
| 2 | CLAUDE.md | Project-specific rules for Claude |
| 3 | ADRs/PDRs, specs | Documented decisions and requirements |
| 4 | This skill (SKILL.md) | Generic TypeScript best practices |
| 5 | Existing code (reference) | Evidence of implementation, NOT authority |
CRITICAL: Existing code is NOT authoritative.
Never copy patterns from existing code without verifying they match documented intent.
</hierarchy_of_authority>
<codebase_discovery> BEFORE writing any code, discover what already exists.
Run these searches before implementation:
# 1. Read project documentation
Read: README.md, docs/, CLAUDE.md, CONTRIBUTING.md
# 2. Check available dependencies (don't add what exists)
Read: package.json → dependencies, devDependencies
# 3. Find prior art for what you're building
Grep: function names, class names, patterns similar to your task
Glob: files in similar directories (src/utils/, src/services/, etc.)
# 4. Detect project conventions
Read: existing files in the same directory you'll write to
| Question | How to Find |
|---|---|
| What libraries are available? | package.json → dependencies |
| How does this project handle X? | Grep for similar patterns |
| What utilities already exist? | Glob for **/utils/**, **/helpers/**, **/fixtures/**, **/harnesses/** |
| What's the naming convention? | Read 3-5 files in the target directory |
| What error classes exist? | Grep for extends Error |
| What logging pattern is used? | Grep for logger, console.log, debug |
| How are configs structured? | Glob for **/*.config.*, **/config/** |
// ❌ WRONG: Adding lodash when ramda is already used
import _ from "lodash"; // package.json has ramda, not lodash
// ❌ WRONG: Creating new logger when one exists
const logger = console; // Project has @lib/logger
// ❌ WRONG: Inventing naming convention
function fetch_user_by_id() {} // Project uses camelCase
// ❌ WRONG: New error class when domain errors exist
class MyError extends Error {} // Project has @/errors
Before writing code, confirm:
package.json — know what libraries are availableIf discovery reveals existing patterns that conflict with this skill's guidance, follow the project's documented patterns.
</codebase_discovery>
<testing_methodology>
For complete testing methodology, invoke /testing-typescript skill.
The /testing-typescript skill provides:
Quick Reference - Testing Levels:
| Level | Infrastructure | When to Use |
|---|---|---|
| 1 (Unit) | Node.js + Git + temp fixtures | Pure logic, FS ops, git operations |
| 2 (Integration) | Project-specific binaries/tools | Claude Code, Hugo, Caddy, TypeScript compiler |
| 3 (E2E) | External deps (GitHub, network, Chrome) | Full workflows with external services |
NO MOCKING — Use Dependency Injection Instead:
// ❌ FORBIDDEN: Mocking
vi.mock("execa", () => ({ execa: vi.fn() }));
// ✅ REQUIRED: Dependency Injection
interface CommandDeps {
execa: typeof execa;
}
it("GIVEN valid args WHEN running THEN returns success", async () => {
const deps: CommandDeps = {
execa: vi.fn().mockResolvedValue({ exitCode: 0 }),
};
const result = await runCommand(args, deps);
expect(result.success).toBe(true); // Tests behavior
});
</testing_levels>
<context_loading> BEFORE ANY IMPLEMENTATION: Load complete specification context.
If working on a spec-tree work item (enabler/outcome):
spec-tree:contextualizing FIRST with the node pathThe spec-tree:contextualizing skill provides:
Example invocation:
# By node path
spec-tree:contextualizing spx/32-cli.enabler/54-commands.outcome
If spec-tree:contextualizing returns an error: The error message will specify which document is missing and how to create it. Create the missing document before proceeding with implementation.
If NOT working on spec-tree work item: Proceed directly to implementation mode with provided spec. </context_loading>
<two_modes> You operate in one of two modes depending on your input:
| Input | Mode | Workflow |
|---|---|---|
| Spec (ADR/PDR, node spec) | Implementation | workflows/implementation.md |
| Rejection feedback from reviewer | Remediation | workflows/remediation.md |
Determine your mode from the input, then follow the appropriate workflow. </two_modes>
<core_principles>
Spec Is Law: The specification is your contract. Implement exactly what it says.
Test-Driven Development: Write tests first or alongside code. Tests prove correctness.
Type Safety First: Use strict TypeScript with strict: true. No any without justification.
Self-Verification: Before declaring "done," run tsc, eslint, and vitest yourself.
Humility: Your code must pass review. Write code that will survive adversarial review.
Clean Architecture: Dependency injection, single responsibility, no circular imports, no deep relative imports.
</core_principles>
<reference_index>
| File | Purpose |
|---|---|
references/outcome-engineering-patterns.md | Subprocess, resource cleanup, config |
references/test-patterns.md | Debuggability-first test organization |
references/verification-checklist.md | Pre-submission verification |
</reference_index>
<workflows_index>
| Workflow | Purpose |
|---|---|
workflows/implementation.md | TDD phases, code standards |
workflows/remediation.md | Fix issues from review feedback |
</workflows_index>
<what_not_to_do> Never Self-Approve: Always submit for review.
Never Skip Tests: Write tests first. No exceptions.
Never Ignore Type Errors:
// WRONG
const result = someFunction(); // @ts-ignore
// RIGHT
const result: ExpectedType = someFunction();
Never Hardcode Secrets:
// WRONG
const API_KEY = "sk-1234567890abcdef";
// RIGHT
const API_KEY = process.env.API_KEY;
if (!API_KEY) throw new Error("API_KEY required");
Never Use Deep Relative Imports:
Before writing any import, ask: "Is this a module-internal file (same module, moves together) or infrastructure (lib/, tests/helpers/, shared/)?"
// WRONG: Deep relatives to stable locations — will REJECT in review
import { helper } from "../../../../../../tests/helpers/tree-builder";
import { Logger } from "../../../../lib/logging";
import { Config } from "../../../shared/config";
// RIGHT: Configure path aliases in tsconfig.json
import { Logger } from "@lib/logging";
import { Config } from "@shared/config";
import { helper } from "@testing/helpers/tree-builder";
Depth Rules:
./sibling — ✅ OK (same directory, module-internal)../parent — ⚠️ Review (is it truly module-internal?)../../ or deeper — ❌ REJECT (use path alias)Configure tsconfig.json:
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["src/*"],
"@testing/*": ["tests/*"],
"@lib/*": ["lib/*"]
}
}
}
</what_not_to_do>
<tool_invocation>
# Type checking
npx tsc --noEmit
# Linting
npx eslint src/ test/
npx eslint src/ test/ --fix
# Testing
npx vitest run --coverage
</tool_invocation>
<success_criteria> Your implementation is ready for review when:
Your code will face an adversarial reviewer with zero tolerance. Write code that will survive that scrutiny. </success_criteria>