CLI

Scaffold a project, add blocks, generate a static brand theme, validate code against the design system, and connect AI agents with the astralis command-line tool.

Running it#

Every command runs through npx, so there's nothing to install:

npx astralis-cli <command> [options]

Or install it once and call astralis directly:

pnpm add -g astralis-cli
astralis <command>

It needs Node ^22.18 or >=24.11. Run astralis --help for the command list, or astralis <command> --help for a command's options. The option tables on this page are generated from the same source as --help.

create: start a new project#

Scaffolds a fresh app with the official create-next-app / create-vite prompts, then wires Astralis into it.

npx astralis-cli create my-app

It asks which framework you want (Next.js, or React via Vite), then hands off to that scaffolder's own prompts, so you get the official setup rather than a copy of it that drifts. When it finishes, the stylesheet is imported, the provider is mounted, and a welcome page you can delete replaces the scaffolder's demo. Run npm run dev (or your package manager's equivalent) inside the new folder to start it.

Option
--framework <next|vite>Skip the framework prompt.
--no-starterKeep the scaffolder's demo page instead of the Astralis welcome screen.
--no-devtoolsLeave out the Astralis DevTools overlay, which new projects get in development.

With --yes it asks nothing: pass --framework, and it tells the scaffolder to take its defaults too.

init: add Astralis to an existing project#

Wires astralis-ui into a project you already have (Next.js or Vite): installs the package, adds the astralis-ui/styles.css import, and mounts <AstralisProvider> at your app's entry point: the same manual steps, done for you.

npx astralis-cli init
Option
--dry-runShow the changes without writing anything.
--ciAlso check every pull request: pin astralis-cli, add a validate script and write a GitHub Actions workflow.
--forceWith --ci, replace an existing astralis-validate.yml.
--devtoolsAlso add the Astralis DevTools overlay (development only): install astralis-devtools and wire it into the root layout or vite.config.

It reads your entry file rather than pattern-matching it, so an import that is already there (however it's quoted or wrapped) isn't added twice, and it never writes a file that no longer parses. If your entry file is a shape it can't edit safely, it prints the manual steps instead. Running it twice is safe.

With --ci it also sets up a check on every pull request: it pins astralis-cli as a devDependency, adds a validate script and writes a GitHub Actions workflow. Validate in CI covers that, and a pre-commit hook.

add: copy a block into your project#

Writes a block's source into your codebase. Blocks aren't imported from a package: the file lands in your repo and you own it, so editing it is editing your own code.

npx astralis-cli add dashboard-01

Name as many as you like. To see what's available without opening the browser:

npx astralis-cli add --list
Option
--listPrint every available block, by category, and exit.
--dir <path>Where to write. Default: src/components/blocks, or components/blocks without a src/.
--overwriteReplace existing files without asking.
--dry-runShow what would be written; write nothing.
--registry <url>Read blocks from a different registry host.

This command is deliberately small compared with the equivalent in other libraries, and the reason is architectural: a block imports only astralis-ui, React, or a sibling file (the registry builder rejects anything else), and the stylesheet is precompiled. So there are no import paths to rewrite, no dependency graph between blocks, and no Tailwind config to merge. It fetches text and writes files, and refuses any file path that would land outside the target folder.

theme: generate a static theme#

Produces a plain CSS stylesheet from a brand seed, for when you want your theme baked into a file rather than derived at runtime by the provider. See Theming for how the two approaches compare, or build a seed visually in the theme builder.

npx astralis-cli theme "#6d3bf5"
Option
--brand <hex>Brand hue, e.g. "#8b5cf6". A bare hex argument means the same.
--gray <hex>Neutral hue: every surface, label and border.
--error <hex>Seeds the error palette. Default: red.
--warning <hex>Seeds the warning palette. Default: orange.
--success <hex>Seeds the success palette. Default: green.
--info <hex>Seeds the info palette. Default: blue.
--font-heading <stack>Heading font stack.
--font-body <stack>Body font stack.
--font-mono <stack>Monospace font stack.
--radius <n>Border-radius multiplier. Default: 1.
--spacing <n>Spacing multiplier: the density dial. Default: 1.
--font-scale <n>Font-size multiplier. Default: 1.
--motion <n>Duration multiplier; 0 turns transitions off. Default: 1.
--out <file>Where to write the stylesheet. Default: src/astralis-theme.css, or astralis-theme.css without a src/.
--forceOverwrite an existing file.
--no-importWrite the file but leave the entry file alone.
--strict-contrastExit 1, writing nothing, if any promised pairing fails WCAG AA.

It uses your project's own astralis-ui for the colour maths, so the file matches the version it's loaded next to, and imports the file into your entry point after the library stylesheet. Before writing, it checks every text and fill pairing the theme promises against WCAG AA in light and dark mode; failures are warnings unless you pass --strict-contrast.

validate: check code against the design system#

Checks your TSX and JSX against the machine-readable spec of the astralis-ui version you have installed. It catches what type-checks and still fails: components and compound parts that don't exist, prop values outside their token sets, astralis:* classes missing from the compiled CSS (they render as nothing), undeclared token variables, illegal breakpoint and state keys, compound parts outside their root, Tabs triggers with no panel, and accessibility mistakes such as misspelled aria-* attributes, invalid roles, and images with no alt.

npx astralis-cli validate              # the current directory
npx astralis-cli validate src/app      # a folder, or single files
npx astralis-cli validate --json       # one JSON report, for CI and tools
Option
--format <text|json|github>How to report: text for people, json for tools, github for inline pull-request annotations. Default: github inside GitHub Actions, text elsewhere.
--jsonSame as --format json.
--spec <path>Validate against this system-spec.json. Default: the installed astralis-ui's.
--strict-tokensAlso warn on raw colors that bypass the tokens.

It skips node_modules, .git, .next, dist, build and out. Each finding names the file, line and column, a rule code, and, where there's a closed set, the nearest valid value.

Exit codes#

CodeMeaning
0No errors. Warnings alone never fail the run.
1At least one error, or the run couldn't start: no spec found, no .tsx/.jsx files, a path that doesn't exist.

JSON output#

--json prints a single object. results lists only files with findings; every finding has the same five fields.

{
  "spec": { "name": "astralis-ui", "version": "0.8.0", "specVersion": 3 },
  "files": 12,
  "errors": 1,
  "warnings": 0,
  "results": [
    {
      "file": "src/app/page.tsx",
      "errors": [
        {
          "code": "invalid-recipe-value",
          "file": "src/app/page.tsx",
          "line": 8,
          "column": 15,
          "message": "Button: \"primary\" is not a variant value (valid: link, text, subtle, solid, surface, outline)"
        }
      ],
      "warnings": []
    }
  ]
}

Raw colours: --strict-tokens#

Arbitrary values are a feature: bg="#ff0000" is valid CSS and renders. But a raw colour won't follow the theme or dark mode. --strict-tokens adds an off-token-color warning for each one, as a drift check, without failing the run.

To run it on every pull request and before each commit, see Validate in CI.

The same validator runs inside the MCP server as the validate_code tool, so an AI agent checks its own output against the rules you run in CI.

report: report a problem to the maintainers#

Builds an issue snapshot from the files that show the problem and sends it to the Astralis issue platform as a draft, where you sign in with GitHub, check it and submit it. The snapshot records the astralis-ui components in those files with their literal props, the validator's findings for them, and the versions of astralis-ui, your framework and React. It is the same snapshot the DevTools build from a page.

npx astralis-cli report app/page.tsx
npx astralis-cli report src/App.tsx --title "Card loses its border" --out snapshot.json
Option
--title <text>The report's title. Asked for when omitted; required with --yes.
--happened <text>What happened.
--expected <text>What you expected instead.
--include-textKeep the text in your JSX; by default it is replaced by placeholders.
--no-findingsLeave out the validator's findings for these files.
--out <file>Write the snapshot to a file instead of sending it.
--dry-runPrint the snapshot and send nothing.
--spec <path>Build against this system-spec.json. Default: the installed astralis-ui's.

It prints the exact JSON first and sends nothing until you confirm. Only props the spec describes are recorded, and only literal values: a value computed at run time, a link, an image source or an event handler never is. Text in your JSX becomes a placeholder unless you pass --include-text.

connect-mcp: connect an AI coding agent#

Connects one AI client to the Astralis MCP server so its agent reads your current component docs instead of guessing. It prompts for the client, tells you exactly what it will do, and, once you confirm, does it.

npx astralis-cli connect-mcp
Option
--client <claude-code|codex|cursor|claude-desktop|antigravity>Skip the prompt and configure this client.

For Claude Code and Codex it runs the client's own mcp add command; for Cursor, Claude Desktop, and Antigravity it writes the client's JSON config (backing up any existing one first, never over an earlier backup). Full details on the AI Agents page.

Global options#

Every command takes these, and astralis --version prints the CLI's version.

Option
-y, --yesNever prompt; take the default answer. Replacing files still needs --overwrite or --force.
-h, --helpShow this command's options.
--debugPrint the stack trace if something fails unexpectedly.

Without a terminal (in CI, say), a command that needs an answer stops and tells you which flag supplies it, rather than guessing.