@simplysm/sd-cli
v13.0.67
Published
심플리즘 패키지 - CLI 도구
Downloads
8,332
Readme
@simplysm/sd-cli
The CLI tool for the Simplysm framework. It provides project initialization, ESLint/Stylelint linting, TypeScript type-checking, combined check (typecheck + lint + test), library/client/server package builds, development mode, deployment, Android device execution, and Electron desktop app build capabilities.
Installation
npm install --save-dev @simplysm/sd-cli
# or
pnpm add -D @simplysm/sd-cliMain Commands
The CLI binary name is sd-cli. All commands support the --debug option to output detailed logs.
lint
Runs ESLint and Stylelint. ESLint lints .ts/.tsx/.js/.jsx files; Stylelint lints .css files (only when a Stylelint config file is present). Extracts globalIgnores patterns from eslint.config.ts. Caches results in .cache/eslint.cache and .cache/stylelint.cache.
# Lint all
sd-cli lint
# Lint specific path
sd-cli lint packages/core-common
# Lint multiple paths
sd-cli lint packages/core-common tests/orm
# Auto-fix
sd-cli lint --fix
# Output rule execution times
sd-cli lint --timingOptions:
| Option | Description | Default |
| ---------- | ---------------------------------------------------------- | ------- |
| --fix | Auto-fix | false |
| --timing | Output rule execution times (sets ESLint TIMING env var) | false |
| --debug | Output debug logs | false |
typecheck
Runs TypeScript type-checking. It performs parallel type-checking per package environment (node/browser) based on tsconfig.json and sd.config.ts. Uses worker threads to run concurrently up to 7/8 of CPU cores.
# Type-check all
sd-cli typecheck
# Type-check specific path
sd-cli typecheck packages/core-common
# Type-check multiple paths
sd-cli typecheck packages/core-common tests/orm
# Pass options to sd.config.ts
sd-cli typecheck -o key=valueOptions:
| Option | Description | Default |
| ----------------- | ---------------------------------------------------------- | ------- |
| --options, -o | Additional options to pass to sd.config.ts (multi-use) | [] |
| --debug | Output debug logs | false |
Type-check environment by target:
| Target | Environment |
| ------------------- | ----------------------- |
| node | node environment once |
| browser, client | browser environment once |
| neutral | node + browser environment twice |
| scripts | Excluded from type-check |
check
Runs typecheck, lint, and test in parallel and prints a consolidated summary. Lint auto-fix is always enabled when run via check. Exits with code 1 if any check fails.
# Run all checks (typecheck + lint + test)
sd-cli check
# Run specific check types
sd-cli check --type typecheck,lint
# Filter paths
sd-cli check packages/core-commonOptions:
| Option | Description | Default |
| ---------- | -------------------------------------------------------------------- | ------------------------ |
| --type | Comma-separated list of check types to run: typecheck, lint, test | typecheck,lint,test |
| --debug | Output debug logs | false |
Output format:
Each check type prints a section header followed by its result summary. A final SUMMARY section lists overall pass/fail status and total error/warning counts.
watch
Watches library packages (node/browser/neutral targets) in watch mode. Automatically rebuilds on file changes and generates .d.ts type definition files.
Note: Use the
devcommand forclient/servertargets.
# Watch all library packages
sd-cli watch
# Watch specific package
sd-cli watch solid
# Watch multiple packages
sd-cli watch solid core-commonOptions:
| Option | Description | Default |
| ----------------- | ---------------------------------------------------------- | ------- |
| --options, -o | Additional options to pass to sd.config.ts (multi-use) | [] |
| --debug | Output debug logs | false |
dev
Runs Client and Server packages in development mode. client targets run with Vite dev server, and server targets run with Server Build Worker + Server Runtime Worker. Supports Server-Client proxy connection and Capacitor initialization.
# Run all client/server packages
sd-cli dev
# Run specific package
sd-cli dev solid-demo
# Run multiple packages
sd-cli dev solid-demo my-serverOptions:
| Option | Description | Default |
| ----------------- | ---------------------------------------------------------- | ------- |
| --options, -o | Additional options to pass to sd.config.ts (multi-use) | [] |
| --debug | Output debug logs | false |
How it works:
clienttarget: Starts Vite dev server. Ifserverconfig is a string (package name), connects proxy to that serverservertarget: Builds in esbuild watch mode, then runs server runtime in separate Worker. Auto-rebuilds and restarts server on file changes- Client packages with Capacitor config perform Capacitor initialization after build completes
- Client packages with Electron config launch Electron in dev mode after build completes
- Terminates on SIGINT/SIGTERM signals
Scope Package HMR:
When using replaceDeps to develop scope packages locally, the Vite dev server automatically watches scope package dist files and triggers HMR when they change. This allows changes to @simplysm/* packages to be reflected in the dev app without manual reload.
build
Runs production build. Performs lint, dist folder cleanup, and build sequentially.
# Build all packages
sd-cli build
# Build specific packages
sd-cli build solid core-commonOptions:
| Option | Description | Default |
| ----------------- | ---------------------------------------------------------- | ------- |
| --options, -o | Additional options to pass to sd.config.ts (multi-use) | [] |
| --debug | Output debug logs | false |
Build behavior by target:
| Target | JS build | .d.ts generation | Type-check | Note |
| -------------------------- | --------------- | ---------------- | ---------- | ------------------------------------- |
| node/browser/neutral | esbuild | O | O | Library package |
| client | Vite production | X | O | Client app (+ Capacitor/Electron build) |
| server | esbuild | X | X | Server app |
| scripts | Excluded | Excluded | Excluded | - |
Public Files & Assets:
Both client and server packages support serving static files from a public/ directory:
- Client packages (
devmode): Vite servespublic/at the configured base path (/{name}/) - Server packages (
devmode): Copiespublic/todist/, watches for changes, and automatically rebuilds - Server packages (
buildmode): Copiespublic/todist/(production deployment) - Client packages (
devmode only): Optionalpublic-dev/directory files are served with priority overpublic/files, allowing dev-specific overrides without affecting production builds
Directory structure:
packages/my-server/
├── public/ # Static files (both dev and build)
│ ├── index.html
│ ├── style.css
│ └── assets/
└── public-dev/ # Dev-only overrides (dev mode only, ignored in build)
└── index.html # Overrides public/index.html in devHow it works:
- In
devmode, bothpublic/andpublic-dev/are copied todist/, withpublic-dev/changes taking priority - If a
public-dev/file is deleted, the correspondingpublic/file is served as fallback - In
buildmode, onlypublic/is copied todist/(nopublic-dev/) - The copy operation preserves directory structure
Runtime Configuration File (.config.json):
If a server or client package defines a configs field in sd.config.ts, the build automatically generates dist/.config.json containing that configuration. This is useful for storing environment-specific settings (database config, API endpoints, etc.) that are read at runtime via ctx.getConfig() in service-server.
Server Build: Externals & Production Deployment Files:
Server builds (target: "server") automatically detect modules that cannot be bundled by esbuild and mark them as external. Three sources of externals are combined:
- Uninstalled optional peer dependencies — automatically detected via
peerDependenciesMeta - Native modules (node-gyp) — automatically detected by scanning for
binding.gypfiles in the dependency tree - Manual externals — specified via
externalsinsd.config.ts
During production build (sd-cli build), the following deployment files are generated in dist/:
| File | Description |
|------|-------------|
| package.json | Minimal package.json with externalized dependencies (version "*") for npm install on the deployment server |
| mise.toml | Node.js version specification (read from root mise.toml) — only generated when packageManager: "mise" is set |
| openssl.cnf | Legacy OpenSSL provider activation (required for MSSQL and other legacy TLS connections) |
| pm2.config.cjs | PM2 process manager config (only generated when pm2 is configured) |
Note: Production deployment files are only generated during
sd-cli build, not duringsd-cli dev(watch mode).
publish
Publishes packages. For safety, proceeds in the following order:
- Pre-validation (npm authentication, Git uncommitted changes check)
- Version upgrade (increment prerelease if prerelease, otherwise patch)
- Build (Git rollback on failure)
- Git commit/tag/push (Git rollback on failure)
- npm/FTP/local deployment
- postPublish script execution
# Publish all packages with publish config
sd-cli publish
# Publish specific packages
sd-cli publish solid core-common
# Publish without build (dangerous)
sd-cli publish --no-build
# Simulate without actual deployment
sd-cli publish --dry-runOptions:
| Option | Description | Default |
| ------------------------ | ---------------------------------------------------------- | ------- |
| --build / --no-build | Whether to run build (skip with --no-build) | true |
| --dry-run | Simulate without actual deployment | false |
| --options, -o | Additional options to pass to sd.config.ts (multi-use) | [] |
| --debug | Output debug logs | false |
init
Initializes a new Simplysm project in the current directory. The directory must be empty and the directory name must be a valid npm scope name (lowercase, numbers, hyphens only).
Creates a skeleton project with:
sd.config.ts,tsconfig.json,eslint.config.ts,pnpm-workspace.yaml.gitignore,.prettierrc.yaml,.prettierignore,mise.toml
After rendering templates, runs pnpm install automatically.
# Create an empty directory and run init
mkdir my-project && cd my-project
sd-cli initAfter initialization, use sd-cli add client and sd-cli add server to add packages.
Note: Claude Code skills/agents are automatically installed via
@simplysm/sd-claudepostinstall.
add client
Adds a client package to an existing project. Must be run from the project root (where sd.config.ts exists).
Runs an interactive prompt to collect:
- Client package name suffix (creates
client-{suffix}package) - Whether to use router
After collecting inputs, it:
- Renders client package from Handlebars templates into
packages/client-{suffix}/ - Adds the package entry to
sd.config.ts(via ts-morph AST editing) - Adds tailwind CSS settings to
eslint.config.ts(if first client) - Runs
pnpm install
sd-cli add clientadd server
Adds a server package to an existing project. Must be run from the project root (where sd.config.ts exists).
Runs an interactive prompt to collect:
- Server name suffix (leave empty for just
server, otherwise createsserver-{suffix}) - Which existing client packages this server should serve (multi-select)
After collecting inputs, it:
- Renders server package from Handlebars templates into
packages/{server-name}/ - Adds the server package entry to
sd.config.ts - Updates selected client packages'
serverfield insd.config.ts - Runs
pnpm install
sd-cli add serverreplace-deps
Sets up local dependency replacement according to replaceDeps configuration in sd.config.ts. Useful for local development of dependent packages across separate repositories.
# Set up replacements (symlink or copy mode based on config)
sd-cli replace-deps
# With additional options
sd-cli replace-deps -o key=valueOptions:
| Option | Description | Default |
| ----------------- | ---------------------------------------------------------- | ------- |
| --options, -o | Additional options to pass to sd.config.ts (multi-use) | [] |
| --debug | Output debug logs | false |
device
Runs Capacitor app on Android device. Only available for client target packages with capacitor config in sd.config.ts.
# Specify package (required)
sd-cli device -p my-app
# Specify dev server URL directly
sd-cli device -p my-app -u http://192.168.0.10:3000Options:
| Option | Description | Default |
| ----------------- | ------------------------------------------------------------------------- | ------- |
| --package, -p | Package name (required) | - |
| --url, -u | Dev server URL (uses server port from sd.config.ts if not specified) | - |
| --options, -o | Additional options to pass to sd.config.ts (multi-use) | [] |
| --debug | Output debug logs | false |
Exported Types and Utilities
This package exports configuration types for sd.config.ts and Vite utilities. All are importable from @simplysm/sd-cli.
import type {
SdConfigFn,
SdConfigParams,
SdConfig,
SdPackageConfig,
BuildTarget,
SdBuildPackageConfig,
SdClientPackageConfig,
SdServerPackageConfig,
SdScriptsPackageConfig,
SdPublishConfig,
SdLocalDirectoryPublishConfig,
SdStoragePublishConfig,
SdPostPublishScriptConfig,
SdCapacitorConfig,
SdCapacitorAndroidConfig,
SdCapacitorSignConfig,
SdCapacitorPermission,
SdCapacitorIntentFilter,
SdElectronConfig,
ViteConfigOptions,
} from "@simplysm/sd-cli";
import { createViteConfig } from "@simplysm/sd-cli";| Type | Description |
|------|-------------|
| SdConfigFn | Function type for sd.config.ts default export: (params: SdConfigParams) => SdConfig \| Promise<SdConfig> |
| SdConfigParams | Parameters passed to the config function (cwd, dev, opt) |
| SdConfig | Root configuration object (packages, replaceDeps?, postPublish?) |
| SdPackageConfig | Union of all package config types |
| BuildTarget | Library build target: "node" \| "browser" \| "neutral" |
| SdBuildPackageConfig | Config for library packages (node/browser/neutral targets) |
| SdClientPackageConfig | Config for client packages (client target) |
| SdServerPackageConfig | Config for server packages (server target, with externals and pm2 options) |
| SdScriptsPackageConfig | Config for scripts-only packages (scripts target) |
| SdPublishConfig | Deployment config: "npm" \| SdLocalDirectoryPublishConfig \| SdStoragePublishConfig |
| SdLocalDirectoryPublishConfig | Local directory deployment config (type: "local-directory", path) |
| SdStoragePublishConfig | FTP/FTPS/SFTP deployment config (type, host, port?, path?, user?, pass?) |
| SdPostPublishScriptConfig | Post-publish script config (type: "script", cmd, args) |
| SdCapacitorConfig | Capacitor config for Android app builds |
| SdCapacitorAndroidConfig | Android platform-specific Capacitor config |
| SdCapacitorSignConfig | APK/AAB signing config (keystore, storePassword, alias, password, keystoreType?) |
| SdCapacitorPermission | Android permission entry (name, maxSdkVersion?, ignore?) |
| SdCapacitorIntentFilter | Android intent filter entry (action?, category?) |
| SdElectronConfig | Electron desktop app build config |
| ViteConfigOptions | Options passed to createViteConfig() — see fields below |
Vite Utilities
createViteConfig
Creates pre-configured Vite configuration for Simplysm client packages.
import { createViteConfig, type ViteConfigOptions } from "@simplysm/sd-cli";
const options: ViteConfigOptions = {
pkgDir: "/path/to/package",
name: "my-app",
tsconfigPath: "/path/to/tsconfig.json",
compilerOptions: {},
mode: "build",
};
export default createViteConfig(options);ViteConfigOptions fields:
| Field | Type | Required | Description |
|-------|------|----------|-------------|
| pkgDir | string | Yes | Absolute path to the package directory |
| name | string | Yes | Package name used as Vite base path (/{name}/) |
| tsconfigPath | string | Yes | Absolute path to tsconfig.json |
| compilerOptions | Record<string, unknown> | Yes | TypeScript compiler options passed to esbuild |
| env | Record<string, string> | No | Environment variables to substitute for process.env at build time |
| mode | "build" \| "dev" | Yes | Build mode: "build" for production, "dev" for development server |
| serverPort | number | No | Dev server port (0 for auto-assign). Only used in "dev" mode |
| watchScopes | string[] | No | Scope package prefixes to watch for HMR (e.g., ["@simplysm"]) |
| onScopeRebuild | () => void | No | Callback invoked when a watched scope package dist file changes |
The createViteConfig() function configures:
- Development server configuration
- Production build optimization
- SolidJS + TailwindCSS plugin integration
- PWA (service worker + web app manifest) generation
- Environment variable substitution support
- Scope package watch/HMR (automatically watches scope package dist files and triggers HMR on changes via
replaceDeps)
Configuration (sd.config.ts)
Create an sd.config.ts file in the project root to define build targets and deployment settings per package. Used by typecheck, watch, dev, build, publish, and device commands.
The typecheck command treats all packages as neutral target if no config file exists. The watch, dev, build, and publish commands require this file.
Basic Example
import type { SdConfigFn } from "@simplysm/sd-cli";
const config: SdConfigFn = () => ({
packages: {
"core-common": { target: "neutral" },
"core-node": { target: "node" },
"core-browser": { target: "browser" },
"solid": { target: "browser", publish: "npm" },
"solid-demo": { target: "client", server: "solid-demo-server" },
"solid-demo-server": { target: "server" },
"my-scripts": { target: "scripts" },
},
});
export default config;Target Types
| Target | Description | Type-check | watch | dev | build |
| --------- | ------------------------------------------------------------------ | ------------------ | ----- | --- | ------------ |
| node | Node.js-only package. Removes DOM lib, includes @types/node | O (node) | O | X | O (JS + dts) |
| browser | Browser-only package. Keeps DOM lib, excludes @types/node | O (browser) | O | X | O (JS + dts) |
| neutral | Node/browser common. Keeps DOM lib, includes @types/node | O (node + browser) | O | X | O (JS + dts) |
| client | Vite dev server-based client app | O (browser) | X | O | O (Vite) |
| server | Fastify-based server app | X | X | O | O (JS) |
| scripts | Excluded from typecheck/watch/build | X | X | X | X |
Function Parameters
The sd.config.ts function receives a SdConfigParams object as an argument:
import type { SdConfigFn, SdConfigParams } from "@simplysm/sd-cli";
const config: SdConfigFn = (params: SdConfigParams) => {
// params.cwd - Current working directory
// params.dev - Whether in dev mode (true for dev command, false for build/publish)
// params.opt - Additional options array passed via CLI's -o flag
return {
packages: {
"my-app": {
target: "client",
server: params.dev ? 3000 : "my-server",
},
},
};
};
export default config;Package Configuration Types
Library Package (SdBuildPackageConfig)
{
target: "node" | "browser" | "neutral";
publish?: SdPublishConfig; // Deployment config (optional)
copySrc?: string[]; // Glob patterns for copying assets from src/ to dist/ (optional)
}Asset Copying (copySrc)
The copySrc option allows copying non-TypeScript files (CSS, images, etc.) from src/ to dist/ during build and watch mode:
"my-lib": {
target: "browser",
publish: "npm",
copySrc: ["**/*.css", "**/*.png"], // Copy all CSS and PNG files
}How it works:
- Glob patterns are relative to
src/directory - File directory structure is preserved during copy (e.g.,
src/styles/theme.css→dist/styles/theme.css) - Applied during both production build (
sd-cli build) and watch mode (sd-cli watch) - Useful for including CSS files with component libraries when consuming apps may not bundle them automatically
Client Package (SdClientPackageConfig)
{
target: "client";
server: string | number; // Server package name or direct port number
env?: Record<string, string>; // Environment variables to replace during build
publish?: SdPublishConfig; // Deployment config (optional)
capacitor?: SdCapacitorConfig; // Capacitor config (optional)
electron?: SdElectronConfig; // Electron config (optional)
configs?: Record<string, unknown>; // Runtime config (written to dist/.config.json during build)
}Progressive Web App (PWA) Support
All client packages automatically generate PWA files during build. No configuration is required to enable PWA.
Generated Files:
sw.js- Service worker (handles offline caching and precache of all build assets)manifest.webmanifest- Web app manifest (for app install/launch)registerSW.js- Service worker registration script (injected automatically)
Key behaviors:
- Build mode: Service worker is fully enabled with offline support and asset precaching via Workbox
- Dev mode: Service worker registration is disabled by default for safe development (no stale cache issues)
- Precache strategy: All build assets (
*.js,*.css,*.html,*.ico,*.png,*.svg,*.woff2) are precached for instant loading - HTTPS requirement: Service workers require HTTPS at runtime (localhost dev mode is exempt)
- Offline capability: Once cached, the app works offline with all precached resources available
Users can install the app on their home screen on supported browsers and devices. No additional code or dependencies are needed.
Server Package (SdServerPackageConfig)
{
target: "server";
env?: Record<string, string>; // Environment variables to replace during build
publish?: SdPublishConfig; // Deployment config (optional)
configs?: Record<string, unknown>; // Runtime config (written to dist/.config.json during build)
externals?: string[]; // Additional modules to exclude from bundle (optional)
packageManager?: "volta" | "mise"; // Package manager for Node.js version management (optional)
pm2?: { // PM2 config — generates dist/pm2.config.cjs (optional)
name?: string; // PM2 process name (defaults to package name)
ignoreWatchPaths?: string[]; // Paths to ignore in PM2 watch
};
}Scripts Package (SdScriptsPackageConfig)
{
target: "scripts";
}Deployment Configuration (SdPublishConfig)
Three deployment methods are supported:
| Method | Config Value | Description |
| ---------------- | ----------------------------------------------------------------------- | ------------------------------------- |
| npm | "npm" | Deploy to npm registry |
| Local directory | { type: "local-directory", path: "..." } | Copy dist to local path |
| Storage | { type: "ftp" \| "ftps" \| "sftp", host, port?, path?, user?, pass? } | Upload to FTP/FTPS/SFTP server |
Environment variable substitution is supported in path for local directory and storage: %VER% (version), %PROJECT% (project path).
// npm deployment
"core-common": { target: "neutral", publish: "npm" },
// Local directory deployment
"my-app": {
target: "client",
server: 3000,
publish: { type: "local-directory", path: "/deploy/%VER%/my-app" },
},
// SFTP upload
"my-server": {
target: "server",
publish: {
type: "sftp",
host: "deploy.example.com",
port: 22,
path: "/opt/app",
user: "deploy",
pass: "secret",
},
},Runtime Configuration (configs)
Define runtime configuration for server or client packages using the configs field. This configuration is automatically written to dist/.config.json during build and can be read at runtime via ctx.getConfig() in the service-server package.
import type { SdConfigFn } from "@simplysm/sd-cli";
const config: SdConfigFn = () => ({
packages: {
"my-server": {
target: "server",
configs: {
// Runtime configuration sections
orm: {
default: {
dialect: "mysql",
host: process.env.DB_HOST || "localhost",
port: 3306,
database: "mydb",
user: process.env.DB_USER || "root",
password: process.env.DB_PASSWORD,
},
},
smtp: {
default: {
host: "smtp.example.com",
port: 587,
secure: false,
user: process.env.SMTP_USER,
pass: process.env.SMTP_PASS,
},
},
},
},
"my-app": {
target: "client",
server: "my-server",
configs: {
api: {
baseUrl: process.env.API_URL || "http://localhost:3000",
timeout: 30000,
},
},
},
},
});
export default config;At runtime, services access configuration sections:
// In a service class
const ormConfig = await this.getConfig<Record<string, DbConfig>>("orm");
const dbConfig = ormConfig.default; // Access specific DB config by nameKey points:
- Configuration sections can be nested objects with any structure
- Environment variable substitution can be used in config values
- Generated
dist/.config.jsonfiles are not included in version control (add to.gitignore) - Client and server both support
configs, but typically only servers expose configuration viactx.getConfig()
Dependency Replacement (replaceDeps)
Replace node_modules packages with local source directories via symlinks. Useful for local development of dependent packages across separate repositories.
The key is a glob pattern to match packages in node_modules, and the value is the local source directory path. The * wildcard in the key is substituted into the * in the value.
import type { SdConfigFn } from "@simplysm/sd-cli";
const config: SdConfigFn = () => ({
packages: {
"my-app": { target: "client", server: "my-server" },
},
replaceDeps: {
// Replaces @simplysm/* packages in node_modules
// with symlinks to ../simplysm/packages/*/dist
"@simplysm/*": "../simplysm/packages/*",
},
});
export default config;postPublish Scripts
You can define scripts to run after deployment completes. Supports environment variable substitution (%VER%, %PROJECT%). On script failure, only a warning is printed and execution continues.
import type { SdConfigFn } from "@simplysm/sd-cli";
const config: SdConfigFn = () => ({
packages: {
/* ... */
},
postPublish: [
{
type: "script",
cmd: "curl",
args: ["-X", "POST", "https://hooks.example.com/deploy?version=%VER%"],
},
],
});
export default config;Capacitor Configuration (SdCapacitorConfig)
Capacitor configuration for Android app builds in client target packages.
"my-app": {
target: "client",
server: 3000,
capacitor: {
appId: "com.example.myapp",
appName: "My App",
icon: "resources/icon.png", // App icon (relative to package directory)
debug: true, // Whether debug build
plugins: { // Capacitor plugins
"@capacitor/camera": true,
"@capacitor/storage": { group: "myGroup" },
},
platform: {
android: {
config: { // AndroidManifest.xml application attributes
requestLegacyExternalStorage: "true",
},
bundle: true, // AAB bundle build (APK if false)
sdkVersion: 33, // Android SDK version
permissions: [ // Additional permissions
{ name: "CAMERA" },
{ name: "WRITE_EXTERNAL_STORAGE", maxSdkVersion: 29 },
],
intentFilters: [ // Intent Filters
{ action: "android.intent.action.VIEW", category: "android.intent.category.DEFAULT" },
],
sign: { // APK/AAB signing
keystore: "keystore.jks",
storePassword: "password",
alias: "key0",
password: "password",
keystoreType: "jks", // Keystore type (optional, defaults to "jks")
},
},
},
},
},Electron Configuration (SdElectronConfig)
Electron configuration for Windows desktop app builds in client target packages. Requires src/electron-main.ts entry point in the package directory.
"my-app": {
target: "client",
server: 3000,
electron: {
appId: "com.example.myapp", // Electron app ID (required)
portable: false, // true: portable .exe, false: NSIS installer
installerIcon: "resources/icon.ico", // Installer icon (.ico, relative to package directory)
reinstallDependencies: ["better-sqlite3"], // npm packages to include (native modules etc.)
postInstallScript: "node scripts/setup.js", // npm postinstall script
nsisOptions: {}, // NSIS options (when portable is false)
env: { // Environment variables (accessible via process.env in electron-main.ts)
API_URL: "https://api.example.com",
},
},
},How it works:
- Initialize: Creates
.electron/src/package.json, runsnpm install, rebuilds native modules withelectron-rebuild - Build: Bundles
electron-main.tswith esbuild, copies web assets, runselectron-builderfor Windows - Dev mode: Bundles
electron-main.ts, launches Electron pointing to Vite dev server URL
Server Externals & PM2 Configuration
Server packages can configure external modules, package manager selection, and PM2 deployment settings.
Externals
Native modules (with binding.gyp) are automatically detected and externalized. You can also manually specify additional modules to exclude from the bundle:
"my-server": {
target: "server",
externals: ["cpu-features", "ssh2"], // Manually externalize these modules
},Package Manager Selection
The packageManager field controls which Node.js version management tool is used in production deployment:
"my-server": {
target: "server",
packageManager: "volta", // Use Volta for Node.js version management
},Supported package managers:
| Value | Behavior | Generated Files |
|-------|----------|-----------------|
| "volta" | Uses Volta for Node.js version management. PM2 config will execute node directly (Volta manages version via package.json engines field). | package.json includes volta field with Node.js version |
| "mise" | Uses mise for Node.js version management. PM2 config will resolve interpreter path via mise which node. | mise.toml is copied to dist/ with Node.js version from root mise.toml |
| undefined | No version management tool. PM2 config will execute node directly from system PATH. | No additional version management files |
Examples:
// Using Volta
"my-server": {
target: "server",
packageManager: "volta",
pm2: {
name: "my-app-server",
},
},
// Using mise
"my-server": {
target: "server",
packageManager: "mise",
pm2: {
name: "my-app-server",
},
},
// No package manager (use system PATH node)
"my-server": {
target: "server",
pm2: {
name: "my-app-server",
},
},PM2 Configuration
When pm2 is configured, dist/pm2.config.cjs is generated during production build for use with PM2 process manager:
"my-server": {
target: "server",
packageManager: "mise", // Optional: specify package manager
env: {
CUSTOM_VAR: "value",
},
pm2: {
name: "my-app-server", // PM2 process name (optional)
ignoreWatchPaths: ["uploads"], // Additional paths to ignore in PM2 watch (optional)
},
},Generated pm2.config.cjs includes:
- Process name (from
pm2.nameor derived from package name) - Watch mode enabled with configurable ignore paths (
node_modules,www+ custom paths) - Node.js interpreter path (resolved via
mise which nodeifpackageManager: "mise", otherwisenodefrom PATH) --openssl-config=openssl.cnfinterpreter argument for legacy TLS support- Environment variables:
NODE_ENV=production,TZ=Asia/Seoul, plus customenvvalues
Deployment workflow:
# 1. Build the server
sd-cli build my-server
# 2. Copy dist/ to deployment server
# 3. On the deployment server:
cd /path/to/my-server/dist
# If using mise, install mise and activate
mise install # Only needed if packageManager: "mise"
# Install externalized dependencies
npm install
# Start with PM2
pm2 start pm2.config.cjsCache
| Command | Cache Path | Description |
| ------------- | ---------------------------------------------------- | ------------------------------------------------------------------ |
| lint | .cache/eslint.cache | ESLint cache |
| lint | .cache/stylelint.cache | Stylelint cache |
| typecheck | packages/{pkg}/.cache/typecheck-{env}.tsbuildinfo | Incremental type-check info ({env} is node or browser) |
| watch (dts) | packages/{pkg}/.cache/dts.tsbuildinfo | Incremental .d.ts build info |
To reset cache, delete the .cache directory:
# Delete all caches
rm -rf .cache packages/*/.cacheCaveats
sd.config.tsis required forwatch,dev,build,publish, anddevicecommands.typecheckandlintwork without a config file.- The
publishcommand automatically increments version and performs Git commit/tag/push. Execution is rejected if there are uncommitted changes. publish --no-builddeploys already-built artifacts as-is, so use with caution.- Before using the
devicecommand, runsd-cli devorsd-cli watchfirst to initialize the Capacitor project. - During build,
VER(project version) andDEV("true"or"false") environment variables are automatically set.
License
Apache-2.0
