Skip to content

Local Development

Prerequisites

Monorepo Structure

The project is a Bun workspaces monorepo. Each subproject has its own package.json with workspace-scoped dependencies, while the root package.json provides global proxy scripts and a single bun.lock.

WorkspacePathDescription
@mithrandir/clicli/Bun/Ink terminal CLI
@mithrandir/docsdocs/VitePress documentation site
@mithrandir/uiui/TanStack Start web dashboard

Getting Started

bash
git clone https://github.com/Joel-Mercier/mithrandir.git && cd mithrandir
bun install

Available Scripts

CommandDescription
bun run cli:startRun the CLI in dev mode (unbundled)
bun run cli:buildBundle into cli/dist/mithrandir.js
bun run cli:testRun CLI unit and snapshot tests
bun run cli:typecheckTypeScript type checking for CLI
bun run ui:devLocal Vite dev server with hot reload
bun run ui:buildBuild the UI for production
bun run ui:previewPreview the built UI
bun run ui:testRun UI unit and snapshot tests
bun run ui:formatFormat all UI files
bun run ui:lintLint all UI files
bun run ui:checkBiome checking for UI
bun run ui:typecheckTypeScript type checking for UI
bun run buildBuild all workspaces
bun run testRun tests across all workspaces
bun run typecheckTypeScript type checking for all workspaces
bun run docs:devLocal VitePress dev server with hot reload
bun run docs:buildBuild the documentation site for production
bun run docs:previewPreview the built documentation site
bun run release <version>Create a new release

Creating a Release

bash
scripts/release.sh 1.1.0    # Bumps version, generates changelog, commits, and tags
git push && git push --tags  # Push the release

The release script bumps the version in cli/package.json and docs/.vitepress/config.ts, regenerates docs/changelog.md from git tags, creates a commit, and tags it. The changelog groups commits by tag, with unreleased commits shown at the top.

You can also regenerate the changelog manually at any time:

bash
scripts/generate-changelog.sh

UI Dashboard

The web dashboard is a TanStack Start app in the ui/ workspace. For an overview of features and production deployment, see the Web Dashboard page.

Dev Server

bash
bun run ui:dev          # Dev server on port 3000 with hot reload

Create a ui/.env.local file for development:

env
BETTER_AUTH_URL=http://localhost:3000
BETTER_AUTH_SECRET=  # openssl rand -base64 32

Building

bash
bun run ui:build        # Build for production
bun run ui:preview      # Preview the production build

Testing and Linting

bash
bun run ui:test         # Run Vitest unit tests
bun run ui:typecheck    # TypeScript type checking
bun run ui:lint         # Lint with Biome
bun run ui:format       # Format with Biome
bun run ui:check        # Biome check (lint + format)

Unit Tests

Tests use Bun's built-in test runner. Test files are in cli/src/__tests__/:

  • App registry (apps.test.ts) — validates app lookups, container names, config paths, conflict filtering, stacks, and registry integrity
  • Config parsing (config.test.ts) — tests .env loading (KEY=VALUE, quotes, export prefix, comments) and backup config defaults
  • Compose generation (compose.test.ts) — snapshot tests for docker-compose.yml output across all app types (standard, host-networked, secrets, healthchecks, capabilities, multi-config, port remapping, rawCompose)
  • Caddy generation (caddy.test.ts) — tests domain derivation, Caddyfile generation, 404 page, and Dockerfile output
  • Backup utilities (backup-utils.test.ts) — archive suffix stripping, backup archive detection, and archive filename generation
  • Crypto (crypto.test.ts) — encrypted backup file detection
  • Systemd (systemd.test.ts) — service and timer unit generation with snapshot tests
  • Swap (swap.test.ts) — swap size formatting (GB/MB thresholds, edge cases)
  • Logger (logger.test.ts) — log message formatting, timestamp pattern validation, and log path constants

Snapshots

Snapshot files are stored in cli/src/__tests__/__snapshots__/ and committed to git. When compose or caddy generation logic changes, update snapshots with:

bash
bun test --update-snapshots

Integration Tests

VM-based end-to-end tests live in cli/integration-tests/ using nix-vm-test. Debian 13 VMs are spun up via QEMU to test critical CLI paths. All tests use Prowlarr as the test app.

Test Suite

TestDescription
getting-startedClone → install.shmithrandir --help
docker-installmithrandir install docker + idempotency
app-lifecycleInstall / status / stop / start / restart / uninstall
backup-restoreBackup, verify, verify --extract, restore
diagnosticsversion, config, health, doctor, capacity, status
updatemithrandir update prowlarr --yes + backup verification

Requirements

  • Linux host with KVM support (cannot run on macOS directly)
  • Nix package manager

See cli/integration-tests/README.md for details on running locally and writing new tests.

CI Pipeline

A GitHub Actions workflow runs on every push and pull request to main:

  1. bun install
  2. bun run typecheck — type checks all workspaces
  3. bun run build — builds all workspaces
  4. bun run test — runs tests across all workspaces
  5. Integration tests (parallel matrix of 6 jobs): enables KVM, installs Nix, runs each VM test with Nix store caching