Joe Bruechner
Projects

vdomains

A CLI that extends Vercel's domain management with interactive TUI search, health diagnostics, DNS reconciliation, transfer workflows, and JSON mode for scripting and agentic pipelines. Built with Ink for rich terminal UI.

v1.0Mar 5, 2026
01

Why This Exists

Vercel is building self-driving infrastructure — deployments, edge functions, observability, all converging toward a platform that manages itself. Their AI layer is getting smarter about how projects are built and shipped. But domains are still a manual step. You leave your editor, navigate the dashboard, search for availability, configure DNS, and hope you don't misconfigure a CNAME along the way.

vdomains closes that gap. It puts the full domain lifecycle in the terminal — search, buy, configure, diagnose, renew — so getting the domain you've been wanting for your project is one command, not a context switch. Every command supports --json, which means AI agents like Claude Code can manage domains programmatically as part of a larger workflow. The domain step stops being a manual interruption and becomes part of the pipeline.

Every command supports --json — AI agents like Claude Code can manage domains programmatically as part of a larger workflow.

The domain step stops being a manual interruption and becomes part of the pipeline.

02

See It Work

A CLI for the full Vercel Domains lifecycle — search, buy, manage, diagnose, transfer, and renew domains.

Interactive domain search, health diagnostics, and lifecycle management from the terminal.
04

Diagnostics

The health command replaces the dig-curl-openssl dance with a single invocation. It runs 7 checks in parallel: DNS resolution, nameserver verification (with Vercel detection), CNAME validation, SSL certificate inspection via raw TLS socket (not fetch — you need getPeerCertificate() for expiry and issuer data), HTTPS connectivity, HTTP-to-HTTPS redirect, and security headers. Each check is independently timed, and the overall status uses a fail > warn > pass > skip hierarchy.

The reconcile command was the more interesting problem. It loads expected domain state from a JSON config file and compares against live DNS, reporting ok, drift (with field-level diffs showing expected vs. actual), or extra (domains in Vercel but not in config). DNS comparison is order-agnostic and case-insensitive using Sets, with special handling for MX records (priority-exchange tuples) and TXT records (joined from split DNS buffers). It catches the manual changes that silently drift from your intended configuration.

domains.json
{
  "domains": [
    {
      "domain": "myapp.com",
      "vercel": true,
      "dns": {
        "CNAME": ["cname.vercel-dns.com"]
      }
    },
    {
      "domain": "myapp.dev",
      "vercel": true
    }
  ]
}
{
  "domains": [
    {
      "domain": "myapp.com",
      "vercel": true,
      "dns": {
        "CNAME": ["cname.vercel-dns.com"]
      }
    },
    {
      "domain": "myapp.dev",
      "vercel": true
    }
  ]
}
Domain config file for reconcile — define expected state, detect drift.
05

Auth & Lifecycle

Token resolution follows a three-tier hierarchy: --token flag, VERCEL_TOKEN environment variable, then OS keychain via keytar. This matters because interactive use should be seamless (keychain), CI/CD needs environment variables, and one-off commands need a flag override. The same pattern shows up in every CLI I build — it's the difference between a tool that works in your terminal and one that works everywhere.

Transfer workflows handle both directions with WHOIS contact management. Renewal tracking surfaces expiring domains with color-coded urgency (red for expired, yellow for <30 days). The goal was covering the full domain lifecycle so you never need to context-switch to a dashboard for routine operations.

Token resolution: --token flag > VERCEL_TOKEN env var > OS keychain

The same pattern shows up in every CLI I build — it's the difference between a tool that works in your terminal and one that works everywhere.

Built with
TypeScript/Node.js/React