Getting Started

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_KEY environment 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 layers paths in radar.yml. Radar uses glob patterns, so src/**/services/** matches any services folder 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

CommandDescription
radar initAuto-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 gateRun gate evaluation (pass/fail for CI)
radar badgeGenerate a dynamic architecture health badge
radar pack listList 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 summaryGenerate 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.yml and rules.yml for your project.
Technical Debt Radar Documentation