This document explains the Socket CLI build system and how to create various build artifacts.
The Socket CLI has two main build outputs:
| Build Type | Description | Output Location |
|---|---|---|
| CLI Bundle | JavaScript bundle for npm distribution | packages/cli/dist/ |
| SEA Binaries | Standalone executables (no Node.js required) | packages/package-builder/build/{dev|prod}/out/socketbin-* |
| Requirement | Version | Notes |
|---|---|---|
| Node.js | >= 25.8.1 | Monorepo development (building, testing) |
| Node.js | >= 18.0.0 | Running published CLI package |
| pnpm | >= 10.22.0 | Package manager |
# Standard development build
pnpm build
# Force full rebuild + SEA for current platform
pnpm build --force
# Build SEA binaries for all platforms
pnpm build:sea
# Build SEA for specific platform (two equivalent forms)
pnpm build --target darwin-arm64
pnpm build --platform=darwin --arch=arm64
# Watch mode (auto-rebuild on changes)
pnpm devsocket-cli/
├── packages/
│ ├── cli/ # Main CLI package
│ │ ├── src/ # TypeScript source
│ │ ├── build/ # Intermediate build files
│ │ │ └── cli.js # Bundled CLI (esbuild output)
│ │ └── dist/ # Distribution files
│ │ ├── index.js # Entry point loader
│ │ ├── cli.js # CLI bundle (copied from build/)
│ ├── package-builder/ # Package generation and build outputs
│ │ ├── build/
│ │ │ └── {dev|prod}/out/ # Build outputs by mode
│ │ │ ├── socketbin-cli-darwin-arm64/
│ │ │ │ └── socket # SEA binary
│ │ │ ├── socketbin-cli-linux-x64/
│ │ │ │ └── socket
│ │ │ └── ... # Other platform binaries
│ ├── build-infra/ # Build infrastructure
│ │ └── build/
│ │ └── downloaded/ # Cached downloads
│ │ ├── node-smol/ # Node.js binaries
│ │ ├── binject/ # Binary injection tool
│ │ └── models/ # AI models
│ └── package-builder/ # Package generation templates
└── scripts/ # Monorepo build scripts
The CLI build executes in four phases:
Phase 1: Clean (optional, with --force)
└── Removes dist/ directory
Phase 2: Prepare (parallel)
├── Generate CLI packages from templates
└── Download assets from socket-btm releases
├── node-smol (minimal Node.js binaries)
├── binject (binary injection tool)
└── models (AI models for analysis)
Phase 3: Build variants (parallel)
├── CLI bundle (esbuild → build/cli.js)
└── Index loader (esbuild → dist/index.js)
Phase 4: Post-processing (parallel)
├── Copy cli.js to dist/
├── Fix node-gyp strings
└── Copy assets (logos, LICENSE, CHANGELOG)
The standard build creates a JavaScript bundle for npm distribution.
# From monorepo root
pnpm build
# Or target CLI specifically
pnpm build:cli
# Force rebuild (ignores cache)
pnpm build --forceOutput: packages/cli/dist/index.js (entry point)
What it includes:
- Bundled CLI code (all dependencies inlined)
- Shadow npm/npx wrappers
- Terminal rendering (Ink/Yoga)
Single Executable Applications bundle Node.js + CLI into one binary.
# Build for all platforms
pnpm build:sea
# Build for current platform only
pnpm build --force # Includes SEA for current platform
# Build specific platform
pnpm build --target darwin-arm64
pnpm build --platform darwin --arch arm64Output: packages/package-builder/build/{dev|prod}/out/socketbin-cli-<platform>-<arch>/socket
| Target | Platform | Architecture | Notes |
|---|---|---|---|
darwin-arm64 |
macOS | Apple Silicon | Native ARM64 |
darwin-x64 |
macOS | Intel | Native x86_64 |
linux-arm64 |
Linux | ARM64 | glibc |
linux-arm64-musl |
Linux | ARM64 | musl (Alpine) |
linux-x64 |
Linux | x86_64 | glibc |
linux-x64-musl |
Linux | x86_64 | musl (Alpine) |
win32-arm64 |
Windows | ARM64 | Native |
win32-x64 |
Windows | x86_64 | Native |
1. Download node-smol binary (minimal Node.js)
└── From socket-btm GitHub releases
2. Download security tools (optional)
├── Python runtime
├── Trivy (vulnerability scanner)
├── TruffleHog (secret detection)
└── OpenGrep (SAST engine)
3. Generate SEA configuration
└── sea-config.json with blob settings
4. Inject using binject
├── CLI blob (JavaScript bundle)
└── VFS (Virtual File System with tools)
Automatically rebuilds on source changes.
pnpm dev
# or
pnpm build:watchWhat it does:
- Starts esbuild in watch mode
- Rebuilds
build/cli.json changes
Note: Watch mode only rebuilds the CLI bundle, not SEA binaries.
| Command | Description |
|---|---|
pnpm build |
Smart build (skips unchanged) |
pnpm build --force |
Force rebuild + SEA for current platform |
pnpm build:cli |
Build CLI package only |
pnpm build:sea |
Build SEA for all platforms |
pnpm dev |
Watch mode |
# Build SEA for specific platform using --target
pnpm build --target darwin-arm64
pnpm build --target linux-x64
pnpm build --target linux-x64-musl # Linux with musl libc (Alpine)
pnpm build --target win32-x64
# Build SEA for specific platform using --platform and --arch
pnpm build --platform=darwin --arch=arm64
pnpm build --platform=linux --arch=x64 --libc=musl
# Build SEA for all platforms
pnpm build:seaRun from packages/cli/:
| Command | Description |
|---|---|
pnpm run build |
Build CLI |
pnpm run build:force |
Force rebuild |
pnpm run build:watch |
Watch mode |
pnpm run build:sea |
Build SEA binaries |
pnpm run build:sea --platform=darwin --arch=arm64 |
Specific platform |
Assets are downloaded from socket-btm releases and cached in packages/build-infra/build/downloaded/.
| Asset | Purpose | Cache Location |
|---|---|---|
node-smol |
Minimal Node.js for SEA | node-smol/<platform>-<arch>/node |
binject |
Binary injection tool | binject/<platform>-<arch>/binject |
models |
AI models for analysis | models/ |
# Clear download cache
pnpm run clean-cache
# Clear CLI build cache
pnpm --filter @socketsecurity/cli run clean
# Clear all caches
pnpm clean| Variable | Description |
|---|---|
SOCKET_CLI_GITHUB_TOKEN |
GitHub token (preferred) |
GITHUB_TOKEN |
GitHub token (fallback if SOCKET_CLI_GITHUB_TOKEN not set) |
GH_TOKEN |
GitHub token (fallback if above not set) |
SOCKET_CLI_LOCAL_NODE_SMOL |
Use local node-smol binary |
SOCKET_CLI_FORCE_BUILD |
Force rebuild (set by --force) |
Located in packages/cli/.config/:
| Config | Output | Description |
|---|---|---|
esbuild.cli.mjs |
build/cli.js |
Main CLI bundle — bundles all source into one JS |
esbuild.index.mjs |
dist/index.js |
Entry point loader — thin shim that loads cli.js |
esbuild.build.mjs |
(orchestrator) | Runs both cli and index builds in parallel |
The orchestrator (esbuild.build.mjs) accepts an optional variant argument:
# Build all variants (default)
node .config/esbuild.build.mjs
# Build only the CLI bundle
node .config/esbuild.build.mjs cli
# Build only the entry point loader
node .config/esbuild.build.mjs index# Build CLI first
pnpm build:cli
# Then build SEA
pnpm build:sea# Set GitHub token for higher rate limits
export GH_TOKEN=your_github_token
pnpm buildSEA binaries include security tools (~140 MB compressed). For smaller binaries without tools:
# Build without security tools (modify orchestration.mjs)
# Or use the npm-distributed version instead# Clear all caches and rebuild
pnpm clean
pnpm build --forcemacOS: Binaries may need code signing for distribution.
Linux musl: Use --libc=musl for Alpine/musl-based systems.
Windows: Output has .exe extension automatically.
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- uses: actions/setup-node@v4
with:
node-version: '25'
cache: 'pnpm'
- run: pnpm install
- run: pnpm build
- run: pnpm test
build-sea:
needs: build
strategy:
matrix:
target:
[
darwin-arm64,
darwin-x64,
linux-arm64,
linux-arm64-musl,
linux-x64,
linux-x64-musl,
win32-arm64,
win32-x64,
]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- uses: actions/setup-node@v4
with:
node-version: '25'
cache: 'pnpm'
- run: pnpm install
- run: pnpm build:cli
- run: pnpm build --target ${{ matrix.target }}| Goal | Command |
|---|---|
| Development build | pnpm build |
| Full rebuild | pnpm build --force |
| Watch mode | pnpm dev |
| All SEA binaries | pnpm build:sea |
| Specific platform SEA | pnpm build --target darwin-arm64 |
| Run tests | pnpm test |
| Clean rebuild | pnpm clean && pnpm build --force |