sickbay

April 19, 2026 · View on GitHub

The terminal interface for Sickbay. Published to npm as the unscoped sickbay package. Built with Ink (React for terminals) and Commander.

Quickstart

# Terminal
npx sickbay

# Web
npx sickbay --web

# TUI
npx sickbay --tui

Usage

sickbay [options]

Commands

CommandDescription
init [options]Scaffold .sickbay/, run baseline scan, seed history
fix [options]Interactively fix issues found by sickbay scan
trend [options]Show score history and trends over time
stats [options]Show a quick codebase overview and project summary
doctor [options]Diagnose project setup and configuration issues
tui [options]Persistent live dashboard with file watching and activity tracking

Flags

FlagDefaultDescription
-p, --path <path>process.cwd()Path to the project to analyze
-c, --checks <names>allComma-separated check IDs to run
--package <name>Scope to a single named package (monorepo only)
--jsonfalseOutput raw JSON to stdout (no UI)
--webfalseOpen web dashboard after scan
--no-aiDisable AI features even if ANTHROPIC_API_KEY is set
--no-quotesSuppress personality quotes in output
--verbosefalseShow tool output during checks
-V, --versionPrint version
-h, --helpShow help

Examples

# Analyze current directory
sickbay

# Analyze another project
sickbay -p ~/projects/my-app

# Run specific checks only
sickbay --checks knip,npm-audit,depcheck

# JSON output for CI
sickbay --json | jq '.overallScore'

# Get just the summary
sickbay --json | jq '.summary'

# List all check names and their scores
sickbay --json | jq '.checks[] | {name, score}'

# Get only failing checks
sickbay --json | jq '.checks[] | select(.status == "fail")'

# Open web dashboard
sickbay --web

# Initialize .sickbay/ folder with baseline scan
sickbay init

# Initialize for a specific project
sickbay init --path ~/projects/my-app

# Interactively fix issues
sickbay fix

# View score history and trends
sickbay trend

# Get quick project stats
sickbay stats

# Diagnose project setup
sickbay doctor

# Launch tui dashboard (current directory, file watching enabled)
sickbay tui

# TUI for a specific project, disable file watching
sickbay tui --path ~/projects/my-app --no-watch

# TUI with faster auto-refresh (60 seconds) and specific checks only
sickbay tui --path ~/projects/my-app --refresh 60 --checks knip,npm-audit,eslint

sickbay init vs sickbay

Run sickbay init once when setting up a project for the first time.

It scaffolds the .sickbay/ data folder, saves a baseline.json snapshot of the project's current health, and wires up .gitignore entries so history.json doesn't pollute your repo. Think of it as "onboarding" Sickbay to a project.

Run sickbay for every subsequent scan.

Each scan automatically appends an entry to .sickbay/history.json, so your score trend builds up over time without any extra steps. The History tab in the web dashboard (sickbay --web) reads from this file.

First timeOngoing
Commandsickbay initsickbay
Creates .sickbay/✓ (if missing)
Saves baseline.json
Updates root .gitignore
Appends to history.json

If you skip sickbay init and go straight to sickbay, history will still accumulate — you just won't have a baseline snapshot or gitignore entries for .sickbay/. But you can always ignore it manually.

TUI Dashboard

sickbay tui opens a persistent split-pane TUI that continuously monitors your project. Unlike a one-shot scan, it stays running, watches for file changes, and lets you interact with results in real time.

TUI Flags

FlagDefaultDescription
-p, --path <path>process.cwd()Project path to monitor
--no-watchwatch enabledDisable file-watching auto-refresh
--refresh <seconds>300Auto-refresh interval in seconds
-c, --checks <checks>allComma-separated list of checks to run

Panels

The tui displays six panels arranged in a responsive grid:

PanelKeyContent
HealthhAll check results with status icons, names, and score bars
ScoreOverall score (0–100), color-coded status, issue counts, score delta
TrendtSparkline charts for overall score and each category (last 10 scans)
GitgBranch, commits ahead/behind, modified/staged/untracked files, last commit
Quick WinsqTop 5 actionable fixes prioritized by severity
ActivityaTime-stamped event log (scans, file changes, regressions, git changes)

Keyboard Controls

KeyAction
rManually trigger a rescan
wLaunch web dashboard (without AI)
WLaunch web dashboard with AI analysis
fExpand focused panel to fullscreen
EscapeUnfocus current panel
↑ / ↓Scroll Health Panel results (when focused)
hFocus Health panel
gFocus Git panel
tFocus Trend panel
qFocus Quick Wins panel
aFocus Activity panel

Automatic Triggers

  • Startup — Initial scan runs immediately
  • File watch — Rescans when TypeScript, JavaScript, or JSON files change (debounced 2s)
  • Auto-refresh — Periodic rescan at the configured interval (default 5 minutes)
  • Regression detection — Activity panel flags category score decreases automatically

Architecture

src/
├── index.ts              # Commander entry — parses flags, renders Ink <App>
├── commands/
│   └── web.ts            # HTTP server (Node built-in) for the dashboard
└── components/
    ├── App.tsx            # Root Ink component — manages phases & state
    ├── Header.tsx         # ASCII art banner + project name
    ├── ProgressList.tsx   # Animated check progress (pending → running → done)
    ├── CheckResult.tsx    # Single check: name, status, score bar, issues
    ├── ScoreBar.tsx       # Colored horizontal bar (green/yellow/red)
    ├── Summary.tsx        # Overall score + issue counts
    ├── QuickWins.tsx      # Top actionable fix suggestions
    └── tui/
        ├── TUIApp.tsx         # TUI root — layout, keyboard input, state
        ├── HealthPanel.tsx        # Check results with status icons and score bars
        ├── ScorePanel.tsx         # Overall score, issue counts, delta from last scan
        ├── TrendPanel.tsx         # Sparkline charts for score history (last 10 scans)
        ├── GitPanel.tsx           # Branch, ahead/behind, staged/modified file counts
        ├── QuickWinsPanel.tsx     # Top 5 actionable fixes by severity
        ├── ActivityPanel.tsx      # Timestamped event log
        ├── HotkeyBar.tsx          # Fixed footer with keyboard shortcut reference
        ├── PanelBorder.tsx        # Focused/unfocused border styling
        └── hooks/
            ├── useSickbayRunner.ts  # Manages check execution and scan state
            ├── useFileWatcher.ts   # chokidar file watcher with debounce
            ├── useGitStatus.ts     # Polls git status every 10 seconds
            └── useTerminalSize.ts  # Tracks terminal dimensions for responsive layout

UI Phases

The <App> component cycles through phases:

  1. loading — Shows progress list with animated spinners while checks run
  2. results — Displays all check results + summary + quick wins
  3. opening-web — Starts HTTP server, opens browser, stays alive until Ctrl+C
  4. error — Shows error message and exits

--web flag flow

When --web is passed:

  1. Scan completes normally
  2. serveWeb(report) starts an HTTP server on port 3030 (or next free port)
  3. Server serves packages/web/dist/ as static files
  4. Server responds to GET /sickbay-report.json with the in-memory report
  5. open package opens the browser
  6. Process stays alive until Ctrl+C

--json flag flow

Skips the Ink UI entirely, writes JSON.stringify(report, null, 2) to stdout, then exits.

Local Development

# Watch mode — rebuilds on file changes
pnpm dev

# Test against a project
node dist/index.js --path ~/Desktop/sickbay-test-app
node dist/index.js --path ~/Desktop/sickbay-test-app --web
node dist/index.js --path ~/Desktop/sickbay-test-app --json

Build

pnpm build   # tsdown → dist/index.js + dist/web-*.js (code-split)
pnpm clean   # rm -rf dist/