What Framework Powers the DESIGN.md CLI? Inside the Citty Architecture
The DESIGN.md CLI is built entirely on top of the Citty command-line framework, a type-safe, lightweight library for defining commands and sub-commands.
The DESIGN.md CLI, part of the google-labs-code/design.md repository, provides a robust command-line interface for managing design system documentation. Understanding the underlying DESIGN.md CLI framework helps developers extend its functionality and adopt similar patterns for their own tools. At its core, the project leverages Citty to handle argument parsing, help generation, and command routing.
Why Citty? The Core DESIGN.md CLI Framework
The CLI relies on Citty as its sole command-line framework. Unlike larger alternatives, Citty offers a minimal, type-safe API specifically designed for modern Node.js applications.
In packages/cli/src/index.ts, the entry point imports defineCommand and runMain directly from the citty package. These two functions form the backbone of the entire application structure. The defineCommand function creates type-safe command definitions, while runMain executes the command tree and handles process exit codes.
According to packages/cli/package.json, Citty is listed as a runtime dependency, cementing its role as the primary framework driving the interface.
Architecture: How Citty Drives the CLI
The DESIGN.md CLI organizes functionality into modular sub-commands, all registered through Citty's unified API.
Entry Point and Command Registration
The main entry point in packages/cli/src/index.ts demonstrates Citty's declarative approach. It defines the root command with metadata and registers four sub-commands: lint, diff, export, and spec.
import { defineCommand, runMain } from 'citty';
import { VERSION } from './version.js';
import lintCommand from './commands/lint.js';
import diffCommand from './commands/diff.js';
import exportCommand from './commands/export.js';
import specCommand from './commands/spec.js';
const main = defineCommand({
meta: {
name: 'design.md',
version: VERSION,
description: 'Agent‑first CLI for DESIGN.md — the hands and eyes for design system work.',
},
subCommands: {
lint: lintCommand,
diff: diffCommand,
export: exportCommand,
spec: specCommand,
},
});
runMain(main);
Sub-command Implementation Pattern
Each sub-command follows an identical pattern using defineCommand. The lint command in packages/cli/src/commands/lint.ts illustrates how Citty handles positional arguments, optional flags, and async execution.
import { defineCommand } from 'citty';
import { lint } from '../linter/index.js';
import { readInput, formatOutput, FileReadError } from '../utils.js';
export default defineCommand({
meta: {
name: 'lint',
description: 'Validate a DESIGN.md file for structural correctness.',
},
args: {
file: { type: 'positional', description: 'Path to DESIGN.md (use "-" for stdin)', required: true },
format: { type: 'string', description: 'Output format: json or text', default: 'json' },
},
async run({ args }) {
// Command implementation
},
});
Dependencies and Ecosystem
While Citty provides the CLI framework, the project combines it with specialized libraries for content processing. Alongside Citty, packages/cli/package.json lists unified, remark plugins, and zod for schema validation.
Citty remains exclusively responsible for:
- Command-line argument parsing and validation
- Automatic help text generation
- Sub-command routing and execution
- Process exit code management
Usage Examples
Once built, the CLI leverages Citty's automatic wiring to provide a seamless interface:
# Lint a DESIGN.md file
npx design.md lint path/to/file.md
# Export a DESIGN.md file to JSON
npx design.md export path/to/file.md --format=json
Citty automatically generates help menus and validates required arguments before executing the run function defined in each command file.
Summary
- The DESIGN.md CLI framework is Citty, a type-safe command-line library for Node.js.
- The entry point in
packages/cli/src/index.tsusesdefineCommandandrunMainfrom Citty to bootstrap the application. - Sub-commands like
lint,diff,export, andspecare defined using Citty's declarative API inpackages/cli/src/commands/. - Citty handles argument parsing, help generation, and command routing automatically, allowing developers to focus on business logic.
Frequently Asked Questions
What is Citty?
Citty is a lightweight, type-safe command-line framework for Node.js that provides a minimal API for defining commands, sub-commands, arguments, and automatic help output. It is designed to be smaller and more modern than traditional CLI frameworks like Commander or Yargs.
How does the DESIGN.md CLI use Citty for argument parsing?
The CLI defines arguments within each command's defineCommand configuration object. For example, in packages/cli/src/commands/lint.ts, the args property specifies positional arguments like file and optional flags like format, which Citty automatically parses and validates before passing to the run function.
Can I extend the DESIGN.md CLI with custom commands?
Yes. Following the pattern in packages/cli/src/index.ts, you can create a new file in packages/cli/src/commands/ that exports a defineCommand object, then register it in the subCommands object of the main command. Citty will automatically wire up the new command and its help text.
What other libraries does the DESIGN.md CLI depend on besides Citty?
While Citty powers the CLI framework itself, the project also uses unified and remark plugins for Markdown processing, and zod for runtime schema validation. These handle the content parsing logic, while Citty manages the command-line interface layer.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →