dsai-tools

CLI reference and build system documentation for the @dsai-io/tools package. Covers the `dsai` command, component/hook/util installation from registry, design-token pipeline, icon generation, configuration schema, and framework mappers.

@dsai-io/tools CLI & Build System

Package Overview

  • Package: @dsai-io/tools (v1.3.0)
  • CLI command: dsai
  • Dependencies: commander, cosmiconfig, deepmerge, fast-glob, ora, picocolors, svgo, zod
  • Config: cosmiconfig (dsai.config.mjs / .js / .ts)

CLI Commands

dsai init

Initialize DSAI in a project.

  • Creates dsai.config.mjs with sensible defaults
  • Sets up directory structure (collections/, generated/, scss/)

dsai add <items...>

Install components, hooks, or utilities from the registry.

dsai add button                    # Single component
dsai add button modal card         # Multiple components
dsai add --all                     # Everything
dsai add --type hook               # All hooks
dsai add --type util               # All utilities
dsai add --overwrite               # Overwrite existing files
dsai add --dry-run                 # Preview without writing
dsai add --registry ./path         # Custom registry path

How dsai add works internally

  1. Parse items & validate
  2. Load project config (dsai.config.mjs) for aliases + target dirs
  3. Find registry at node_modules/@dsai-io/tools/registry/
  4. Load <item>.json from registry/{components,hooks,utils,types}/
  5. BFS dependency resolution (transitive dependencies)
  6. Topological sort (Kahn's algorithm) — detects circular deps
  7. Collect npm dependencies
  8. Transform imports: relative (../../hooks/) → alias (@/hooks/)
  9. Write files to target directories
  10. Skip existing files unless --overwrite

Registry types

Registry typeConfig keyTarget directory
registry:uialiases.uicomponents/ui/<name>/
registry:hookaliases.hookshooks directory
registry:utilaliases.utilsutils directory
registry:libaliases.liblib directory
registry:componentaliases.componentscomponents directory
registry:typealiases.componentscomponents directory
registry:stylealiases.uiUI directory

dsai tokens build

Run the full token pipeline (12 steps). Pipeline is cached — only reruns changed steps.

StepNameDescription
1validateCheck DTCG JSON structure (colors: HEX/RGB/HSL, dimensions: px/rem/em, references)
2snapshotBackup current tokens
3preprocessExtract Figma modes (light/dark)
4transformFigma exports → DTCG format
5style-dictionaryBuild CSS/JS/TS/SCSS/JSON outputs
6syncCreate tokens-flat.ts
7sass-themeCompile Bootstrap SCSS theme (dsai-theme-bs.scssdsai-theme-bs.css)
8sass-theme-minifiedMinified variant
9postprocessReplace data-bs-themedata-dsai-theme in CSS
10sass-utilitiesCompile DSAI utilities SCSS
11sass-utilities-minifiedMinified utilities
12bundleFinal tsup packaging

dsai tokens validate

Validate token structure only (no build).

dsai tokens transform

Transform only (no build).

dsai icons

Run the icon pipeline.

  • Scan SVG files → Parse → Optimize (SVGO) → Generate React components + SVG sprites
  • Tracks: totalIcons, filesWritten, totalSizeReduction

dsai info

Display project info.

dsai config

Manage configuration.

dsai registry

Registry management (build, list).


Configuration Schema

File: dsai.config.mjs

import { defineConfig } from '@dsai-io/tools';
export default defineConfig({
  global: {
    debug: false,
    framework: 'react',       // 'react' | 'vue' | 'svelte'
  },
  tokens: {
    source: 'theme',
    sourceDir: './src/figma-exports',
    collectionsDir: './src',
    outputDir: './src/generated',
    outputDirs: {
      css: './src/generated/css',
      scss: './src/generated/scss',
      js: './src/generated/js',
      ts: './src/generated/ts',
      json: './src/generated/json',
    },
    prefix: '--dsai-',
    formats: ['css', 'scss', 'js', 'ts', 'json'],
    scss: {
      outputStyles: ['expanded', 'compressed'],
      themeEntry: 'src/scss/dsai-theme-bs.scss',
      cssOutputDir: 'src/generated/css',
      loadPaths: ['node_modules'],
      framework: 'bootstrap',     // 'bootstrap' | 'shadcn' | 'tailwind' | 'mui' | 'custom'
      variablesOutput: 'src/scss/_variables.scss',
    },
    postprocess: {
      enabled: true,
      cssDir: 'src/generated/css',
      files: ['dsai-theme-bs.css', 'dsai-theme-bs.min.css'],
      replacements: [{ from: /data-bs-theme/g, to: 'data-dsai-theme' }],
    },
    pipeline: {
      steps: [
        'validate', 'transform', 'multi-theme', 'sync',
        'sass-theme', 'sass-theme-minified', 'postprocess',
      ],
    },
    themes: {
      enabled: true,
      default: 'light',
      autoDetect: true,
      definitions: {
        light: {
          isDefault: true,
          selector: ':root',
          outputFiles: {
            css: 'tokens.css',
            scss: '_variables.scss',
            js: 'tokens.js',
            ts: 'tokens.d.ts',
            json: 'tokens.json',
          },
        },
        dark: {
          selector: '[data-dsai-theme="dark"]',
          mediaQuery: '(prefers-color-scheme: dark)',
          outputFiles: {
            css: 'tokens-dark.css',
            scss: '_variables-dark.scss',
          },
        },
      },
    },
    aliases: {
      importAlias: '@/',
      ui: 'src/client/components/ui',
      hooks: 'src/client/hooks',
      utils: 'src/client/lib/utils',
      components: 'src/client/components',
    },
    components: { enabled: true, tsx: true, overwrite: false },
  },
});

Framework Mappers

Bootstrap (default)

Maps DSAI tokens → Bootstrap SCSS variables.

CategoryDSAI TokenBootstrap Variable
Typographytext-basefont-size-base
Typographyheading-h1h1-font-size
Typographydisplay-d1display1-size
Font Weightsthinfont-weight-lighter
Font Weightssemi-boldfont-weight-semibold
Shadowsshadow-defaultbox-shadow
Shadowsshadow-lgbox-shadow-lg
Border Radiusborder-radius-defaultborder-radius

Other Supported Frameworks

  • shadcn — Pass-through (no mapping)
  • Tailwind — Generates config.js
  • MUI — Generates JS theme object
  • Custom — User-defined mappings

Output Formats

FormatFileContent
CSStokens.css:root { --dsai-*: value; }
CSS Darktokens-dark.css[data-dsai-theme="dark"] { --dsai-*: value; }
SCSS_variables.scss$token-name: value;
Bootstrapdsai-theme-bs.cssCompiled Bootstrap with token overrides
JStokens.jsexport const TokenName = "value";
TStokens.d.tsexport const TokenName: string;
JSONtokens.json{"TokenName": "value"}

Typical Workflow

# Initial setup
dsai init
dsai add button modal card tabs input

# After editing token JSON
dsai tokens build

# After Figma sync
dsai figma sync
dsai tokens build

# Add more components later
dsai add select checkbox dropdown

Default Configuration (No Config File)

Consumer projects can work without a dsai.config.mjs file. When no config file exists, dsai uses these defaults:

SettingDefault Value
aliases.importAlias@/
aliases.uisrc/client/components/ui
aliases.hookssrc/client/hooks
aliases.utilssrc/client/lib/utils
aliases.componentssrc/client/components
global.frameworkreact
components.tsxtrue
components.overwritefalse

If these defaults match your project structure, dsai add works out of the box — no dsai init required.

Example: draft_v0 uses the default paths and has no dsai.config.mjs file. Running dsai add button writes to src/client/components/ui/button/.

Only create dsai.config.mjs when you need to override defaults (custom paths, different framework, or token pipeline settings).


New Project Setup (End-to-End)

# 1. Install @dsai-io/tools as a dev dependency
npm install -D @dsai-io/tools

# 2. (Optional) Initialize config — skip if defaults match your project
dsai init

# 3. Add components you need
dsai add button modal card input select tabs

# 4. Verify files were written
ls src/client/components/ui/
#  → button/ card/ input/ modal/ select/ tabs/

# 5. Import and use in your app
// src/client/App.tsx
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';

function App() {
  return (
    <Card variant="elevated">
      <Card.Body>
        <Button variant="primary">Hello DSAI</Button>
      </Card.Body>
    </Card>
  );
}

Adding Token Pipeline (Optional)

If your project uses DSAI design tokens from Figma:

# 1. Install figma-tokens package
npm install -D @dsai-io/figma-tokens

# 2. Add scripts to package.json
# "figma:sync": "dsai figma sync"
# "tokens:build": "dsai tokens build"

# 3. Set Figma env vars
echo 'FIGMA_API_KEY=your-token' >> .env
echo 'FIGMA_FILE_ID=your-file-id' >> .env

# 4. Sync and build
dsai figma sync
dsai tokens build

# 5. Import generated CSS in main.tsx (order matters — see dsai-styling skill)

Troubleshooting

dsai add fails with "registry not found"

The CLI looks for registry files at node_modules/@dsai-io/tools/registry/. Ensure @dsai-io/tools is installed:

npm ls @dsai-io/tools

If missing, install it: npm install -D @dsai-io/tools

Imports don't resolve after dsai add

Verify your tsconfig.json has the @/ path alias:

{
  "compilerOptions": {
    "paths": {
      "@/*": ["./src/client/*"]
    }
  }
}

Also check your bundler (Vite, webpack) has matching alias configuration.

Components missing dependencies after dsai add

dsai add resolves transitive dependencies via BFS, but npm packages listed in each registry item's dependencies field must be installed separately:

# Check what a component needs
dsai add button --dry-run

# Install any missing npm packages
npm install <missing-package>

dsai tokens build fails

  • Verify token JSON files in src/collections/ follow DTCG format ($value, $type)
  • Check that Bootstrap SCSS entry file exists at the configured scss.themeEntry path
  • Run dsai tokens validate first to isolate schema errors