sickbay
v1.16.5
Published
Zero-config health check CLI for JavaScript and TypeScript projects
Readme
sickbay
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 --tuiUsage
sickbay [options]Commands
| Command | Description |
| ------------------ | ------------------------------------------------------------------ |
| 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
| Flag | Default | Description |
| ---------------------- | --------------- | -------------------------------------------------- |
| -p, --path <path> | process.cwd() | Path to the project to analyze |
| -c, --checks <names> | all | Comma-separated check IDs to run |
| --package <name> | | Scope to a single named package (monorepo only) |
| --json | false | Output raw JSON to stdout (no UI) |
| --web | false | Open web dashboard after scan |
| --no-ai | | Disable AI features even if ANTHROPIC_API_KEY is set |
| --no-quotes | | Suppress personality quotes in output |
| --verbose | false | Show tool output during checks |
| -V, --version | | Print version |
| -h, --help | | Show 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,eslintsickbay 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 time | Ongoing |
| ------------------------- | -------------- | -------------- |
| Command | sickbay init | sickbay |
| Creates .sickbay/ | ✓ | ✓ (if missing) |
| Saves baseline.json | ✓ | ✗ |
| Updates root .gitignore | ✓ | ✗ |
| Appends to history.json | ✓ | ✓ |
If you skip
sickbay initand go straight tosickbay, 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
| Flag | Default | Description |
| ----------------------- | --------------- | ------------------------------------- |
| -p, --path <path> | process.cwd() | Project path to monitor |
| --no-watch | watch enabled | Disable file-watching auto-refresh |
| --refresh <seconds> | 300 | Auto-refresh interval in seconds |
| -c, --checks <checks> | all | Comma-separated list of checks to run |
Panels
The tui displays six panels arranged in a responsive grid:
| Panel | Key | Content |
| -------------- | --- | -------------------------------------------------------------------------- |
| Health | h | All check results with status icons, names, and score bars |
| Score | — | Overall score (0–100), color-coded status, issue counts, score delta |
| Trend | t | Sparkline charts for overall score and each category (last 10 scans) |
| Git | g | Branch, commits ahead/behind, modified/staged/untracked files, last commit |
| Quick Wins | q | Top 5 actionable fixes prioritized by severity |
| Activity | a | Time-stamped event log (scans, file changes, regressions, git changes) |
Keyboard Controls
| Key | Action |
| -------- | ------------------------------------------ |
| r | Manually trigger a rescan |
| w | Launch web dashboard (without AI) |
| W | Launch web dashboard with AI analysis |
| f | Expand focused panel to fullscreen |
| Escape | Unfocus current panel |
| ↑ / ↓ | Scroll Health Panel results (when focused) |
| h | Focus Health panel |
| g | Focus Git panel |
| t | Focus Trend panel |
| q | Focus Quick Wins panel |
| a | Focus 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 layoutUI Phases
The <App> component cycles through phases:
loading— Shows progress list with animated spinners while checks runresults— Displays all check results + summary + quick winsopening-web— Starts HTTP server, opens browser, stays alive until Ctrl+Cerror— Shows error message and exits
--web flag flow
When --web is passed:
- Scan completes normally
serveWeb(report)starts an HTTP server on port 3030 (or next free port)- Server serves
packages/web/dist/as static files - Server responds to
GET /sickbay-report.jsonwith the in-memory report openpackage opens the browser- 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 --jsonBuild
pnpm build # tsdown → dist/index.js + dist/web-*.js (code-split)
pnpm clean # rm -rf dist/