This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Before making changes:
pnpm nx affected -t build- Build affected packagespnpm nx affected -t test- Test affected packages
After making changes:
./packages/repopo/bin/dev.js check --fix- Fix policy violationspnpm format- Format code
Package-specific work:
- Use
pnpm nx run <pkg>:<task>for targeted execution - Check
packages/<name>/CLAUDE.mdfor package guidance
This is a TypeScript monorepo containing personal tools and CLI utilities, managed with pnpm workspaces and Nx for build orchestration.
Key Technologies:
- Package Manager: pnpm 10.10.0 (required - do not use npm or yarn)
- Build Orchestration: Nx (task caching, parallel execution, affected detection, and plugin-based inference)
- Testing: Vitest with coverage support
- Formatting/Linting: Biome (unified toolchain replacing ESLint/Prettier)
- CLI Framework: OCLIF for command-line tools
- Policy Enforcement: repopo (custom repository policy tool)
Note on Task Naming: Root scripts use user-friendly names (pnpm build, pnpm test) which run Nx targets across packages (e.g., nx run-many -t build). Individual packages define implementation tasks like build:compile, build:api, etc. See Architecture Patterns section for details.
# Install dependencies (always use pnpm, never npm/yarn)
pnpm install
# Build all packages (runs nx run-many -t build)
pnpm build
# Run all tests (runs nx run-many -t test)
pnpm test
# Run all checks (format, lint, policy)
pnpm check
# Format code with Biome
pnpm format
# Lint code
pnpm lint
pnpm lint:fix # Auto-fix issues
# CI pipeline (runs on affected projects only)
pnpm run ci
# CI pipeline on ALL projects (useful for verification)
pnpm run ci:all
# CI pipeline on local changes only (since last commit)
pnpm run ci:localNote: The CI task list (check, build, lint, test:coverage) is centralized in nx.json targetDefaults. To update which tasks run in CI, modify the ci target's dependsOn array in nx.json - all projects will automatically use the updated configuration.
The monorepo uses Nx for intelligent task orchestration:
# Run affected tasks (compares to main branch)
pnpm nx affected -t build
pnpm nx affected -t test
pnpm nx affected -t ci
# Run tasks on all projects
pnpm nx run-many -t build
pnpm nx run-many -t test
# Run task on specific project
pnpm nx run cli:build
pnpm nx run cli:test
# View project details and task configuration
pnpm nx show project cli --web
# Visualize project graph
pnpm nx graphEach package can be built/tested independently:
cd packages/<package-name>
# Build single package
pnpm build
# Test single package
pnpm test
# Run package-specific commands
pnpm run <script># Check repository policies
pnpm run check:policy
./packages/repopo/bin/dev.js check
# Fix policy violations
pnpm run fix:policy
# Sync package.json dependencies
pnpm syncpack:fix
# Update dependencies interactively
pnpm depsThis section documents the top-level tasks. See Architecture Patterns for how the two-tier task system (orchestration vs implementation) works.
Purpose: Compile, bundle, and prepare all packages for distribution Orchestration: Runs implementation tasks based on package type Common implementations:
build:compile- TypeScript compilation (tsc)build:api- API Extractor documentation generationbuild:docs- TypeDoc documentation generationbuild:manifest- OCLIF manifest generation for CLI toolsbuild:readme- OCLIF readme generation for CLI toolsbuild:site- Astro/Vite site buildsbuild:vite- Vite builds for Svelte apps
Usage:
pnpm build # Build all packages
pnpm nx run cli:build # Build specific package
pnpm nx affected -t build # Build only affected packagesPurpose: Run test suites to verify code correctness
Orchestration: Runs build:compile first, then test implementations
Common implementations:
test:vitest- Vitest unit teststest:unit- Unit teststest:coverage- Tests with coverage reportingtest:e2e- End-to-end teststest:snapshots- OCLIF command snapshot tests
Usage:
pnpm test # Test all packages
pnpm test:coverage # Test with coverage
pnpm nx run cli:test # Test specific package
pnpm nx affected -t test # Test only affected packagesPurpose: Validate code quality without modification Orchestration: Runs various validation tasks Common implementations:
check:format- Biome format checkingcheck:types- TypeScript type checkingcheck:deps- Dependency version synchronizationcheck:policy- Repository policy validation (repopo)check:astro- Astro project validationcheck:svelte- Svelte component validation
Usage:
pnpm check # Check all packages
pnpm nx run cli:check # Check specific packagePurpose: Analyze code for potential errors and style issues Implementation: Typically runs Biome linter directly (not orchestration) Common scripts:
lint- Run Biome linterlint:fix- Auto-fix linting issues
Usage:
pnpm lint # Lint all packages
pnpm lint:fix # Fix lint issuesPurpose: Auto-format code to match style guidelines Implementation: Typically runs Biome formatter directly
Usage:
pnpm format # Format all packagesPurpose: Run complete CI pipeline (check, build, lint, test:coverage)
Orchestration: Centralized in nx.json - all packages inherit same pipeline
Task list: Defined once in nx.json targetDefaults, used by all packages
Usage:
pnpm run ci # CI on affected packages
pnpm run ci:all # CI on all packages
pnpm run ci:local # CI on local changesPurpose: Remove build artifacts and generated files Implementations: Package-specific cleanup scripts
Usage:
pnpm clean # Clean all packagesSome packages have specialized tasks:
OCLIF CLI packages (cli, dill-cli, repopo, sort-tsconfig):
build:manifest- Generate OCLIF command manifestbuild:readme- Generate README from command helpbuild:generate- Generate command snapshots for testing
Documentation sites (ccl-docs, dill-docs, repopo-docs):
build:site- Build Astro static sitecheck:astro- Validate Astro configurationdev- Development server with hot reloadpreview- Preview production build
Library packages:
build:api- Generate API documentation with API Extractorbuild:docs- Generate TypeDoc documentation
Example: Running pnpm nx run cli:build
- Nx reads
clipackage.json and findsnx.targets.build: {} - Nx checks
nx.jsontargetDefaults forbuilddependencies - Nx sees
dependsOn: ["^build", "build:compile", "build:manifest", "build:readme", ...] - Nx runs
buildon workspace dependencies first (^build) - Nx runs implementation tasks in parallel where possible:
build:compile(TypeScript compilation)- After compile:
build:manifest(OCLIF manifest) - After manifest:
build:readme(OCLIF readme)
- All tasks use caching - unchanged inputs skip execution
To add a task to a package:
-
Add implementation script to package.json:
"scripts": { "build:custom": "your-command-here" }
-
Add to orchestration in nx.json targetDefaults:
"build": { "dependsOn": [ "^build", "build:compile", "build:custom" // Add your task ] }
-
Enable orchestration in package.json:
"nx": { "targets": { "build": {} // Synthetic target using nx.json orchestration } }
The monorepo contains these key packages:
CLI Tools (OCLIF-based):
packages/cli- @tylerbu/cli - Personal CLI tool (bin:tbu)packages/dill-cli- dill-cli - File download/extraction utilitypackages/repopo- Repository policy enforcement toolpackages/sort-tsconfig- TypeScript config sorting utility
Libraries:
packages/fundamentals- Shared utilities (array, git, etc.) with zero dependenciespackages/cli-api- Shared CLI command infrastructure for OCLIF projectspackages/levee-client- HTTP client librarypackages/xkcd2-api- XKCD API wrapperpackages/lilconfig-loader-ts- TypeScript loader for lilconfig
Documentation Sites (Astro/Starlight):
packages/ccl-docs- CCL documentation (deployed to ccl.tylerbutler.com)packages/dill-docs- Dill documentationpackages/repopo-docs- Repopo documentation
Shared Configuration:
config/- Base TypeScript configs and API Extractor settings
Nx orchestrates builds using pure dependency-based orchestration - no shell scripts, just dependency graphs.
This monorepo uses a two-tier task architecture:
-
Orchestration Targets (no prefix) - Defined in
nx.jsontargetDefaults- Examples:
build,test,check,ci,release - Purpose: Coordinate multiple implementation tasks via
dependsOn - Configuration: Only dependencies, no inputs/outputs (delegates to implementation tasks)
- Location: Centralized in
nx.jsontargetDefaults
- Examples:
-
Implementation Tasks (with
:prefix) - Defined in package.json scripts- Examples:
build:compile,test:unit,check:format - Purpose: Perform actual work (compile, test, lint, etc.)
- Configuration: Specific inputs, outputs, and caching rules
- Location: Package-specific in package.json, orchestrated via
nx.json
- Examples:
Why This Matters:
- Orchestration targets provide simple commands (
pnpm build) that run complex pipelines - Implementation tasks enable granular caching (change README → only
build:readmereruns) - Clear separation makes it easy to understand what runs when and why
Orchestration via nx.json, Implementation via package.json scripts
Orchestration Targets (defined in nx.json targetDefaults):
ci- Full CI pipeline (centralized task list: check, build, lint, test:coverage)- Configured once in
nx.jsontargetDefaults - Each package enables via minimal package.json entry
- Update task list in ONE place (nx.json) to affect all projects
- Configured once in
build- Coordinates all build implementation tasks viadependsOntest- Coordinates compile + all test variants (unit, vitest, snapshots)check- Coordinates all quality checks (format, types, deps, policy)release- Prepares releases (build + license generation)
Implementation Tasks (package-specific, defined in package.json):
build:compile- TypeScript compilation (src → esm/)build:api- API Extractor documentationbuild:docs- TypeDoc documentationbuild:manifest- OCLIF manifest generationbuild:readme- OCLIF readme generationbuild:generate- OCLIF command snapshotsbuild:site- Astro/Vite site buildsbuild:vite/build:tauri- Svelte/Tauri buildstest:unit,test:coverage,test:e2e- Testing variantscheck:format,check:types,check:deps,check:policy- Quality checks
Plugin-Inferred Tasks (auto-detected by Nx plugins):
test:vitest- Auto-inferred from vitest.config.ts (via @nx/vite plugin)
Package-Specific Pipelines:
- Libraries: build:compile → build:api → build:docs
- CLI tools: build:compile → build:manifest → build:readme → build:generate
- Astro sites: build:site only
- Svelte apps: build:vite (or build:vite → build:tauri for desktop)
Key Principles:
- Orchestration in
nx.json- Dependency chains defined viadependsOn - Implementation in package.json - Actual work performed by scripts
- No orchestrator scripts - Package.json contains minimal entries (e.g.,
"build": "") to register targets - Granular caching - Each implementation task caches independently with specific inputs/outputs
- Parallel execution - Nx runs tasks without dependencies concurrently (up to 8 parallel tasks)
- Colon separator - Implementation tasks use
:(e.g.,build:compile,test:unit) - Plugin inference - Nx plugins auto-detect tasks from config files (vitest.config.ts, etc.)
- Centralized config - All orchestration in root
nx.json(no package-level project.json files)
Benefits:
- Precise caching: Change README → only
build:readmeruns (others use cache) - Smart rebuilds: Change source → only affected tasks rebuild
- Parallel execution: API Extractor configs run in parallel across packages
- Performance: 60-80% faster CI for isolated changes due to granular caching
- Maintainability: Update CI tasks once in
nx.json, all packages inherit changes
All packages extend base tsconfig files from config/:
tsconfig.base.json- Common compiler optionstsconfig.strict.json- Strict type checkingtsconfig.super-strict.json- Maximum strictnesstsconfig.node.json- Node-specific settings
Important: This monorepo uses explicit .mjs/.cjs extensions - no ambiguous .js files allowed. This is enforced via the NoJsFileExtensions policy in repopo.
Nx uses plugins to automatically infer tasks from configuration files, reducing manual configuration:
Active Plugins:
@nx/vite/plugin- Auto-infers test tasks fromvitest.config.tsfiles
Plugin Exclusions (projects with non-standard configurations):
packages/ccl-test-viewer/**- Svelte app with custom Vite setuppackages/ccl-docs/**- Astro site (uses Vite internally but different structure)packages/dill-docs/**- Astro sitepackages/repopo-docs/**- Astro site
Inferred Targets:
test:vitest- Automatically created for packages withvitest.config.ts- Uses same caching and configuration as manually defined tasks
- Available on: fundamentals, cli-api, cli, repopo, sort-tsconfig, xkcd2-api, dill
Why Use Plugins?
- Automatic task discovery when adding new packages
- Less manual configuration in
nx.json - Consistent task naming across projects
- Better IDE/Nx Console integration
Configuration Location: See nx.json → plugins array
CLI packages follow OCLIF conventions:
- Commands in
src/commands/(compiled toesm/commands/) - Binary entry point in
bin/run.js(production) orbin/dev.js(development) - Manifest auto-generated in
oclif.manifest.json - README auto-generated from command help text
Testing CLI Commands:
- Use
@oclif/plugin-command-snapshotfor snapshot testing - Generate snapshots:
./bin/dev.js snapshot:generate - Compare snapshots:
./bin/dev.js snapshot:compare
The monorepo enforces consistency via repopo.config.ts:
- NoJsFileExtensions - No .js files (use .mjs/.cjs)
- PackageJsonProperties - Standardized package.json fields
- PackageJsonSorted - Sorted package.json (via sort-package-json)
- SortTsconfigsPolicy - Sorted tsconfig files
Run ./packages/repopo/bin/dev.js check --fix to auto-fix violations.
Each package uses Vitest with a shared base configuration:
- Base config:
config/vitest.config.ts - Per-package:
packages/*/vitest.config.ts(merges base config) - Test files:
test/**/*.test.ts - Coverage output:
.coverage/ - JUnit reports:
_temp/junit.xml
Run tests:
# All packages
pnpm test
# Single package
cd packages/<name> && pnpm test
# With coverage
pnpm test:coverageWorkspace Dependencies:
- Internal packages use
workspace:^protocol - Versions synchronized via syncpack
- Peer dependencies configured in root package.json
Key Constraints:
- Node >= 18.0.0
- TypeScript ~5.5.4 (pinned minor version)
- Biome 2.0.4 (shared across all packages)
- Create
packages/<name>/directory - Add
package.jsonwith required fields (license, author, bugs, repository) - Add to
pnpm-workspace.yaml(already includespackages/*) - Extend base tsconfig:
{ "extends": "../../config/tsconfig.strict.json" } - Run
pnpm installfrom root - Run
pnpm run repopoto verify compliance (orpnpm run fix:policyto auto-fix)
# Development mode (uses TypeScript source)
./bin/dev.js <command>
# Production mode (uses compiled JavaScript)
./bin/run.js <command>
# Update README after command changes (runs build:readme task)
pnpm nx run cli:build:readme
# Update manifest (runs build:manifest task)
pnpm nx run cli:build:manifest
# Generate command snapshots (runs build:generate task)
pnpm nx run cli:build:generateNx caches based on inputs/outputs, so repeated builds are fast:
# Build with cache
pnpm build
# Force rebuild without cache
pnpm nx reset && pnpm build
# See what would be built
pnpm nx run-many -t build --dry-runBiome replaces both ESLint and Prettier:
# Check formatting only (no linting)
pnpm run check:format
# Fix formatting
pnpm format
# Lint code
pnpm lint
# Fix lint issues
pnpm lint:fix
# Both format and lint
pnpm checkCI Mode:
# GitHub Actions reporter
pnpm run ci:lint- Always use pnpm - The
packageManagerfield enforces pnpm 10.10.0 - No .js files - Use .mjs or .cjs for JavaScript files (enforced by repopo)
- Use pathe for path handling - Always use
patheinstead ofnode:pathfor cross-platform path operations - Async file I/O - Prefer
fs/promisesover sync fs operations (e.g.,readFileoverreadFileSync) - Workspace protocol - Internal deps use
workspace:^ - Synchronized versions - Run
pnpm syncpack:fixto sync dependency versions - Sorted configs - package.json and tsconfig.json must be sorted
- Biome formatting - Code must pass Biome checks before commit
- Policy compliance - All packages must pass repopo policy checks
- Tabs for indentation - This project uses tabs, not spaces
- No re-exports - Always import from the module directly, not through barrel files
- Vitest for specific tests - Use
pnpm vitestto run specific tests;pnpm testruns all tests
tools-monorepo/
├── packages/ # All packages
│ ├── cli/ # OCLIF CLI tools
│ ├── */src/ # TypeScript source
│ ├── */esm/ # Compiled output
│ ├── */test/ # Test files
│ └── */docs/ # Generated docs
├── config/ # Shared configs
│ ├── tsconfig*.json # Base TypeScript configs
│ ├── vitest.config.ts
│ └── api-extractor.base.json
├── nx.json # Nx task configuration
├── biome.jsonc # Biome configuration
├── repopo.config.ts # Repository policies
└── syncpack.config.cjs # Dependency version sync
Build failures:
- Clear Nx cache:
pnpm nx reset - Clear package builds:
pnpm clean - Reinstall:
rm -rf node_modules && pnpm install
Policy violations:
- Auto-fix:
pnpm run fix:policy(runsrepopo check --fix) - Check specific package:
./packages/repopo/bin/dev.js check --path packages/<name>
Version mismatches:
- Sync dependencies:
pnpm syncpack:fix - Check for mismatches:
pnpm nx run-many -t syncpack
TypeScript errors:
- Ensure you're extending the correct base config
- Check that
esm/output is current:pnpm compile - Verify imports use explicit extensions (.mjs/.cjs)
- When running tasks (for example build, lint, test, e2e, etc.), always prefer running the task through
nx(i.e.pnpm nx run,pnpm nx run-many,pnpm nx affected) instead of using the underlying tooling directly - You have access to the Nx MCP server and its tools, use them to help the user
- When answering questions about the repository, use the
nx_workspacetool first to gain an understanding of the workspace architecture where applicable. - When working in individual projects, use the
nx_project_detailsmcp tool to analyze and understand the specific project structure and dependencies - For questions around nx configuration, best practices or if you're unsure, use the
nx_docstool to get relevant, up-to-date docs. Always use this instead of assuming things about nx configuration - If the user needs help with an Nx configuration or project graph error, use the
nx_workspacetool to get any errors
If the user wants help with fixing an error in their CI pipeline, use the following flow:
- Retrieve the list of current CI Pipeline Executions (CIPEs) using the
nx_cloud_cipe_detailstool - If there are any errors, use the
nx_cloud_fix_cipe_failuretool to retrieve the logs for a specific task - Use the task logs to see what's wrong and help the user fix their problem. Use the appropriate tools if necessary
- Make sure that the problem is fixed by running the task that you passed into the
nx_cloud_fix_cipe_failuretool