skills/typescript-build-tools/SKILL.md
TypeScript project tooling with Bun, tsgo, Vitest, Biome, and Turborepo. Use when setting up package.json scripts, running builds, typechecking, configuring tests, linting, formatting, or orchestrating monorepo development.
npx skillsauth add martinffx/claude-code-atelier typescript-build-toolsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Modern TypeScript build tooling stack: Bun for package management and task running, tsgo for typechecking, Vitest for testing, Biome for linting/formatting, and Turborepo for monorepo orchestration.
# Install dependencies
bun add -D vitest @vitest/coverage-v8 @biomejs/biome
# For monorepos
bun add -D turbo
{
"scripts": {
"dev": "bun run --watch src/index.ts",
"build": "bun build ./src/index.ts --outdir ./dist --target bun",
"typecheck": "tsgo --noEmit",
"test": "vitest run",
"test:watch": "vitest",
"test:coverage": "vitest run --coverage",
"lint": "biome check .",
"lint:fix": "biome check --write .",
"format": "biome format --write .",
"check": "bun run typecheck && bun run lint && bun run test"
}
}
{
"scripts": {
"dev": "turbo dev",
"build": "turbo build",
"typecheck": "turbo typecheck",
"test": "turbo test",
"lint": "turbo lint",
"check": "turbo typecheck lint test"
}
}
# Install dependencies
bun install
# Add dependencies
bun add fastify drizzle-orm
bun add -D vitest @biomejs/biome
# Remove dependency
bun remove package-name
# Update dependencies
bun update
Important: Use bun run test (not bun test) on Node projects. bun test invokes Bun's native test runner, not your package.json test script.
# Run script from package.json
bun run dev
bun run test
bun run build
# Run TypeScript directly (no build step)
bun run src/index.ts
# Watch mode
bun run --watch src/index.ts
# With environment variables
bun run --env-file .env src/index.ts
# Basic build for Bun runtime
bun build ./src/index.ts --outdir ./dist --target bun
# For Node.js runtime
bun build ./src/index.ts --outdir ./dist --target node
# With minification
bun build ./src/index.ts --outdir ./dist --target bun --minify
# Multiple entry points
bun build ./src/index.ts ./src/worker.ts --outdir ./dist --target bun
See references/bun.md for bunfig.toml configuration and advanced patterns.
tsgo is a fast TypeScript typechecker. Use it instead of tsc for faster CI builds.
# Typecheck without emitting
tsgo --noEmit
# Typecheck specific files
tsgo --noEmit src/**/*.ts
# With project reference
tsgo --noEmit -p tsconfig.json
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"strict": true,
"skipLibCheck": true,
"noEmit": true,
"esModuleInterop": true,
"resolveJsonModule": true,
"isolatedModules": true,
"verbatimModuleSyntax": true,
"lib": ["ESNext"],
"types": ["bun-types"]
},
"include": ["src/**/*.ts"],
"exclude": ["node_modules", "dist"]
}
// vitest.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true,
environment: 'node',
include: ['src/**/*.test.ts', 'test/**/*.test.ts'],
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html'],
include: ['src/**/*.ts'],
exclude: ['src/**/*.test.ts', 'src/types/**'],
},
},
})
// vitest.config.ts
import { defineConfig } from 'vitest/config'
import tsconfigPaths from 'vite-tsconfig-paths'
export default defineConfig({
plugins: [tsconfigPaths()],
test: {
globals: true,
},
})
// vitest.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true,
globalSetup: './test/global-setup.ts',
setupFiles: ['./test/setup.ts'],
},
})
// test/global-setup.ts
import { execSync } from 'node:child_process'
export async function setup() {
console.log('Running database migrations...')
execSync('drizzle-kit migrate', { stdio: 'inherit' })
}
export async function teardown() {
console.log('Test teardown complete')
}
See references/vitest.md for workspace configs, benchmarks, and Cloudflare Workers pool.
{
"$schema": "https://biomejs.dev/schemas/2.0.0/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": true,
"ignore": ["dist", "node_modules", "*.gen.ts"]
},
"formatter": {
"enabled": true,
"indentStyle": "tab",
"lineWidth": 100
},
"javascript": {
"formatter": {
"quoteStyle": "double",
"trailingCommas": "es5"
}
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"organizeImports": {
"enabled": true
}
}
{
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"complexity": {
"noForEach": "error"
},
"performance": {
"noDelete": "error"
},
"style": {
"useNodejsImportProtocol": "error"
}
}
}
}
See references/biome.md for rule explanations, shareable configs, and CLI commands.
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"dependsOn": ["^build"],
"outputs": ["dist/**"]
},
"typecheck": {
"dependsOn": ["^typecheck"]
},
"lint": {},
"test": {
"dependsOn": ["^build"],
"env": ["DATABASE_URL"]
},
"dev": {
"cache": false,
"persistent": true
}
}
}
my-monorepo/
├── package.json # Root with turbo scripts
├── turbo.json # Turbo configuration
├── biome.json # Shared Biome config
├── packages/
│ ├── config-biome/ # Shareable Biome package
│ └── shared/ # Shared utilities
├── apps/
│ ├── api/ # Fastify API
│ └── web/ # React app
└── bun.lock
See references/turborepo.md for caching strategies, filtering, and CI setup.
// vite.config.ts
import { cloudflare } from '@cloudflare/vite-plugin'
import { reactRouter } from '@react-router/dev/vite'
import tailwindcss from '@tailwindcss/vite'
import tsconfigPaths from 'vite-tsconfig-paths'
import { defineConfig } from 'vite'
export default defineConfig({
plugins: [
cloudflare({ viteEnvironment: { name: 'ssr' } }),
tailwindcss(),
reactRouter(),
tsconfigPaths(),
],
})
// vitest.config.ts
import { defineWorkersConfig } from '@cloudflare/vitest-pool-workers/config'
export default defineWorkersConfig({
test: {
globals: true,
pool: '@cloudflare/vitest-pool-workers',
poolOptions: {
workers: {
wrangler: { configPath: './wrangler.jsonc' },
},
},
},
})
name: typescript-build-tools
on:
push:
branches: [main]
pull_request:
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- run: bun install --frozen-lockfile
- run: bun run typecheck
- run: bun run lint
- run: bun run test
name: typescript-build-tools
on:
push:
branches: [main]
pull_request:
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun run check # turbo typecheck lint test
env:
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ vars.TURBO_TEAM }}
bun install) and task runner (bun run)bun run test (not bun test) - bun test runs Bun's native test runnertsc for CI--frozen-lockfile in CI for reproducible buildsdevelopment
Security architecture and threat modeling knowledge. Auto-invokes when designing features that handle untrusted data, authentication, authorization, external integrations, file uploads, or sensitive data. Provides risk assessment frameworks, trust boundary analysis, and security design principles — not implementation code.
testing
Adversarial review of non-trivial decisions using fresh-context scrutiny. Use when correctness matters more than speed, when stakes are high (production, security-sensitive logic, irreversible operations), or before committing significant architectural or implementation choices.
development
Compact the current conversation into a handoff document for another agent to pick up.
testing
Socratic interrogation of plans against the project's domain model and documented decisions. Use when the user wants to stress-test a plan, clarify terminology, or validate assumptions against existing domain language. Updates CONTEXT.md and ADRs inline as decisions crystallise.