ALWAYS invoke this skill when writing or fixing implementation code for TypeScript.
From typescriptnpx claudepluginhub outcomeeng/claude --plugin typescriptThis skill is limited to using the following tools:
references/outcome-engineering-patterns.mdreferences/test-patterns.mdreferences/verification-checklist.mdworkflows/implementation.mdworkflows/remediation.mdSearches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Searches prompts.chat for AI prompt templates by keyword or category, retrieves by ID with variable handling, and improves prompts via AI. Use for discovering or enhancing prompts.
Creates consistent pitch decks, one-pagers, investor memos, financial models, accelerator apps, and fundraising materials from a single source of truth.
<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>