Quickstart
Install Technical Debt Radar, run your first scan, and fix violations in under 5 minutes.
Quickstart
This guide takes you from zero to a passing gate in five minutes. You will install the CLI, initialize your project config, run a scan, and optionally auto-fix violations.
Prerequisites
- Node.js 18+ installed
- A TypeScript or JavaScript project with source files in
src/(or similar) - Optional: an
ANTHROPIC_API_KEYenvironment variable for AI features
Step 1: Install the CLI
# Option A: Run directly with npx (no install needed)
npx @radar/cli scan .
# Option B: Install globally
npm install -g @radar/cli
Verify the installation:
radar --version
Technical Debt Radar v1.0.0
Step 2: Initialize Your Project
Run radar init from your project root. Radar auto-detects your stack, layers, modules, data volumes, and architecture pattern:
radar init
Expected output:
◉ Detecting project structure... done
✓ Stack: TypeScript + NestJS + Prisma
✓ Found 4 layers: api, application, domain, infrastructure
✓ Found 3 modules: orders, billing, identity
✓ Found 8 tables with estimated volumes
📦 Matching rule packs found:
1. nestjs-prisma-essentials — Core rules for NestJS + Prisma projects...
2. nestjs-ddd-boundaries — DDD boundary enforcement for NestJS...
Architecture detection:
DDD ··················· 87% confidence ← recommended
Layered ··············· 45% confidence
Feature-Module ······· 32% confidence
? Select architecture preset: DDD (Domain-Driven Design)
? Install matching rule packs? Yes
✓ Created radar.yml
✓ Created rules.yml
✓ Installed 2 rule packs
This generates two files in your project root:
radar.yml --- your project configuration:
stack:
language: TypeScript
framework: NestJS
orm: Prisma
runtime: node
structure: monolith
architecture: DDD
layers:
- name: api
path: "src/**/controllers/**"
- name: application
path: "src/**/use-cases/**"
- name: domain
path: "src/**/domain/**"
- name: infrastructure
path: "src/**/infra/**"
modules:
- name: orders
path: "src/orders/**"
- name: billing
path: "src/billing/**"
- name: identity
path: "src/identity/**"
data_volumes:
orders: L # 100K-1M rows
events: XL # 1M-50M rows
users: M # 10K-100K rows
companies: S # <10K rows
rules.yml --- your enforcement rules (auto-generated from the DDD preset):
rules:
- deny: domain -> infrastructure
- deny: domain -> api
- deny: application <- domain
- deny: cross-module direct imports
- allow: cross-module through "src/**/contracts/**"
gates:
block_merge:
- architecture_violations > 0
- circular_dependencies_introduced > 0
- runtime_risk_critical > 0
- reliability_critical > 0
- debt_delta_score > 15
warn:
- complexity_increase > 5
- maintainability_violations > 3
- debt_delta_score > 8
Tip: If your project uses a different structure, edit the
layerspaths inradar.yml. Radar uses glob patterns, sosrc/**/services/**matches anyservicesfolder at any depth.
Step 3: Run Your First Scan
radar scan .
Expected output:
Technical Debt Radar — Scan Report
══════════════════════════════════════════════════════════
Scanned 47 files in 2.3s
ARCHITECTURE 4 violations
──────────────────────────────────────────────────────────
BLOCK src/orders/domain/order.service.ts:3
layer-boundary-violation: domain imports from infrastructure
import { PrismaClient } from '@prisma/client'
BLOCK src/billing/application/create-invoice.ts:5
layer-boundary-violation: application imports from api layer
import { InvoiceController } from '../controllers/invoice.controller'
BLOCK src/orders/domain/order.entity.ts:2
circular-dependency: orders/domain ↔ billing/domain
Cycle: order.entity → billing.entity → order.entity
BLOCK src/identity/controllers/user.controller.ts:4
module-boundary-violation: cross-module import not through contracts
import { OrderService } from '../../orders/application/order.service'
RUNTIME RISK 2 violations
──────────────────────────────────────────────────────────
BLOCK src/orders/controllers/export.controller.ts:18
sync-fs-in-handler: fs.readFileSync blocks the event loop
in @Get('export') handler — use fs.readFile (async) instead
WARN src/identity/controllers/auth.controller.ts:42
unbounded-json-parse: JSON.parse on request body without size limit
in @Post('login') handler — add express.json({ limit: '1mb' })
PERFORMANCE 2 violations
──────────────────────────────────────────────────────────
BLOCK src/orders/application/list-orders.use-case.ts:15
unbounded-find-many: prisma.order.findMany() without pagination
Table 'orders' is L (100K-1M rows) — add take/skip
BLOCK src/billing/application/generate-report.ts:22
n-plus-one-query: query inside Promise.all loop
prisma.lineItem.findMany() called per order — use include or join
RELIABILITY 3 violations
──────────────────────────────────────────────────────────
BLOCK src/orders/application/send-notification.ts:8
unhandled-promise-rejection: fire-and-forget async call
emailService.send(user.email) — add await or .catch()
WARN src/billing/infra/stripe.adapter.ts:31
external-call-no-timeout: HTTP call without timeout
stripe.charges.create() — add timeout configuration
WARN src/identity/application/reset-password.ts:19
empty-catch-block: catch block swallows error silently
} catch (e) {} — log the error or rethrow
MAINTAINABILITY 1 violation
──────────────────────────────────────────────────────────
WARN src/orders/application/process-order.use-case.ts
high-complexity: cyclomatic complexity 24 (threshold: 10)
══════════════════════════════════════════════════════════
SUMMARY
Total violations: 12
Blocking: 7
Warnings: 5
Debt score: 58
GATE: ✗ FAIL — 7 blocking violations. Merge would be blocked.
══════════════════════════════════════════════════════════
Note: Your first scan will likely show many violations. This is expected and normal --- the "shock report" reveals debt that has been accumulating undetected. See Your First Scan for strategies to reduce your score incrementally.
Step 4: Fix Violations
You have three options for fixing violations:
Option A: Fix Manually
Read each violation, understand the issue, and fix the code. The scan output includes the file path, line number, rule ID, and a brief explanation.
Option B: Use radar fix with AI
If you have an ANTHROPIC_API_KEY set, Radar can generate and apply fixes automatically:
export ANTHROPIC_API_KEY=sk-ant-...
radar fix .
12 violations found. Generating fixes...
Fix 1/12: src/orders/domain/order.service.ts:3
layer-boundary-violation: domain imports from infrastructure
BEFORE:
import { PrismaClient } from '@prisma/client';
AFTER:
import { OrderRepository } from './order.repository.interface';
Apply fix? [y/n/all] y
✓ Applied
Fix 2/12: src/orders/controllers/export.controller.ts:18
sync-fs-in-handler: fs.readFileSync blocks the event loop
BEFORE:
const template = fs.readFileSync('./template.html', 'utf-8');
AFTER:
const template = await fs.readFile('./template.html', 'utf-8');
Apply fix? [y/n/all] all
✓ Applied remaining 11 fixes
Rescan recommended: radar scan .
Option C: Copy for AI Assistant
Generate an AI-friendly report and paste it into Claude, Cursor, or Copilot:
radar scan . --format ai-prompt
This outputs a structured prompt with exact file paths, line numbers, and fix instructions that AI tools can act on directly. Copy the output, paste it into your AI assistant, and let it fix everything. Then rescan:
radar scan .
Step 5: Verify --- Gate Passes
After fixing violations, run the scan again:
radar scan .
Technical Debt Radar — Scan Report
══════════════════════════════════════════════════════════
Scanned 47 files in 2.1s
MAINTAINABILITY 1 violation
──────────────────────────────────────────────────────────
WARN src/orders/application/process-order.use-case.ts
high-complexity: cyclomatic complexity 24 (threshold: 10)
══════════════════════════════════════════════════════════
SUMMARY
Total violations: 1
Blocking: 0
Warnings: 1
Debt score: 3
GATE: ✓ PASS — No blocking violations. Merge allowed.
══════════════════════════════════════════════════════════
The remaining warning (high complexity) does not block merges by default. You can address it later or adjust the threshold in rules.yml.
Step 6: Add to CI
To enforce Radar on every PR, add the GitHub Action to your workflow:
# .github/workflows/radar.yml
name: Technical Debt Radar
on:
pull_request:
branches: [main, develop]
permissions:
pull-requests: write
contents: read
jobs:
radar:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: technical-debt-radar/action@v1
with:
fail-on: critical
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Now every PR that introduces a blocking violation will fail the check and prevent merging.
Tip: See the full Installation guide for GitHub App, GitLab CI, and advanced GitHub Action configuration.
Available Commands
| Command | Description |
|---|---|
radar init | Auto-detect stack and generate radar.yml + rules.yml |
radar scan <path> | Scan files and report violations |
radar fix <path> | AI-powered auto-fix for violations |
radar gate | Run gate evaluation (pass/fail for CI) |
radar badge | Generate a dynamic architecture health badge |
radar pack list | List available rule packs for your stack |
radar pack info <name> | Show details of a rule pack |
radar pack install <name> | Install a rule pack into your rules.yml |
radar summary | Generate an AI-powered executive summary |
Available Output Formats
The radar scan command supports five output formats:
radar scan . --format text # Human-readable (default)
radar scan . --format json # Machine-readable JSON
radar scan . --format table # Compact table view
radar scan . --format ai-prompt # Paste into Claude/Cursor for AI fix
radar scan . --format ai-json # Structured JSON for AI tool integrations
Next Steps
- Installation --- Set up GitHub App, GitHub Action, or GitLab CI.
- Your First Scan --- Deep dive into interpreting scan results and reducing your initial debt score.
- Configuration --- Customize
radar.ymlandrules.ymlfor your project.