12 KiB
VibeTunnel NPM Package Distribution
This document explains the npm package build process, native module handling, and prebuild system for VibeTunnel.
Overview
VibeTunnel is distributed as an npm package that includes:
- Full web server with terminal sharing capabilities
- Native modules for terminal (PTY) and authentication (PAM) support
- Cross-platform prebuilt binaries to avoid requiring build tools
- Command-line tools (
vibetunnelandvt)
Package Structure
vibetunnel/
├── dist/ # Compiled server code
├── public/ # Web interface assets
├── bin/ # CLI entry points
│ ├── vibetunnel # Main server executable
│ └── vt # Terminal wrapper command
├── node-pty/ # Vendored PTY implementation
│ ├── lib/ # TypeScript compiled code
│ └── package.json # PTY package configuration
├── prebuilds/ # Native module prebuilt binaries
│ ├── node-pty-* # PTY binaries for all platforms/Node versions
│ └── authenticate-pam-* # PAM binaries for all platforms/Node versions
└── README.md # Package documentation
Native Modules
VibeTunnel requires two native modules:
1. node-pty (Terminal Support)
- Purpose: Provides pseudo-terminal (PTY) functionality
- Components:
pty.node: Main Node.js addon for terminal operationsspawn-helper: macOS-only C helper binary for process spawning
- Platforms: All (macOS, Linux)
- Dependencies: None (vendored implementation)
2. authenticate-pam (Authentication)
- Purpose: PAM (Pluggable Authentication Modules) integration
- Components:
authenticate_pam.node: Node.js addon for system authentication
- Platforms: Linux primarily, macOS for compatibility
- Dependencies: System PAM libraries
Prebuild System
Overview
We use prebuild and prebuild-install to provide precompiled native modules, eliminating the need for users to have build tools installed.
Coverage
- Node.js versions: 20, 22, 23, 24
- Platforms: macOS (x64, arm64), Linux (x64, arm64)
- Total prebuilds: 32 binaries (16 per native module)
Prebuild Files
prebuilds/
├── node-pty-v1.0.0-node-v115-darwin-arm64.tar.gz
├── node-pty-v1.0.0-node-v115-darwin-x64.tar.gz
├── node-pty-v1.0.0-node-v115-linux-arm64.tar.gz
├── node-pty-v1.0.0-node-v115-linux-x64.tar.gz
├── authenticate-pam-v1.0.5-node-v115-darwin-arm64.tar.gz
├── authenticate-pam-v1.0.5-node-v115-darwin-x64.tar.gz
├── authenticate-pam-v1.0.5-node-v115-linux-arm64.tar.gz
├── authenticate-pam-v1.0.5-node-v115-linux-x64.tar.gz
└── ... (similar for node versions 22, 23, 24)
Note: Node version numbers map to internal versions (v115=Node 20, v127=Node 22, v131=Node 23, v134=Node 24)
Build Process
Unified Build (Multi-Platform by Default)
npm run build:npm
- Compiles TypeScript and bundles client code
- Builds native modules for all supported platforms (macOS x64/arm64, Linux x64/arm64)
- Creates comprehensive prebuilds for zero-dependency installation
- Generates npm README optimized for package distribution
Build Options
The unified build script supports flexible targeting:
# Default: All platforms
npm run build:npm
# Current platform only (faster for development)
node scripts/build-npm.js --current-only
# Specific platform/architecture
node scripts/build-npm.js --platform darwin --arch arm64
node scripts/build-npm.js --platform linux
# Skip Docker (Linux builds will be skipped)
node scripts/build-npm.js --no-docker
Docker Requirements
For Linux builds, Docker is required:
- Recommended: OrbStack
- Alternative: Docker Desktop
The build will fail with helpful error messages if Docker is not available.
Installation Process
For End Users
- Install package:
npm install -g vibetunnel - Prebuild-install runs: Attempts to download prebuilt binaries
- Fallback compilation: If prebuilds fail, compiles from source
- Result: Working VibeTunnel installation
Installation Scripts
The package uses a multi-stage installation approach:
{
"scripts": {
"install": "prebuild-install || node scripts/postinstall-npm.js"
}
}
Stage 1: prebuild-install
- Downloads appropriate prebuilt binary for current platform/Node version
- Installs to standard locations
- Success: Installation complete, no compilation needed
- Failure: Proceeds to Stage 2
Stage 2: postinstall-npm.js
- node-pty: Essential module, installation fails if build fails
- authenticate-pam: Optional module, warns if build fails
- Provides helpful error messages about required build tools
Platform-Specific Details
macOS
- spawn-helper: Additional C binary needed for proper PTY operations
- Built during install: spawn-helper compiles via node-gyp when needed
- Architecture: Supports both Intel (x64) and Apple Silicon (arm64)
- Build tools: Requires Xcode Command Line Tools for source compilation
Linux
- PAM libraries: Requires
libpam0g-devfor authenticate-pam compilation - spawn-helper: Not used on Linux (macOS-only)
- Build tools: Requires
build-essentialpackage for source compilation
Docker Build Environment
Linux prebuilds are created using Docker with:
- Base image:
node:22-bookworm - Dependencies:
python3 make g++ git libpam0g-dev - Package manager: pnpm (more reliable than npm in Docker)
- Environment:
CI=trueto avoid interactive prompts
spawn-helper Binary
What is spawn-helper?
spawn-helper is a small C helper binary used by node-pty for proper terminal process spawning on macOS.
Key Facts
- Size: ~70KB pure C binary
- Platform: macOS only (Linux doesn't use it)
- Purpose: Handles terminal device attachment for spawned processes
- Dependencies: None (pure C, no Node.js dependencies)
- Architecture: Platform-specific (x64 vs arm64)
Source Code
// Simplified version of spawn-helper functionality
int main (int argc, char** argv) {
char *slave_path = ttyname(STDIN_FILENO);
close(open(slave_path, O_RDWR)); // Attach to terminal
char *cwd = argv[1];
char *file = argv[2];
argv = &argv[2];
if (strlen(cwd) && chdir(cwd) == -1) {
_exit(1);
}
execvp(file, argv); // Execute the target command
return 1;
}
Installation Handling
- Current approach: Universal spawn-helper binary included in prebuilds (macOS only)
- Benefits: No compilation needed, faster installation, works without build tools
- Fallback path: If prebuild fails, compilation happens automatically via node-gyp
- Error handling: Non-fatal if missing (warns but continues)
Universal Binary Implementation
spawn-helper is now shipped as a prebuilt universal binary in all macOS prebuilds:
Implementation:
- Built for both x64 and arm64 architectures using clang++
- Combined into universal binary with
lipo - Included in every macOS node-pty prebuild automatically
Benefits:
- ✅ Faster installation (no compilation needed)
- ✅ Works without build tools (Xcode Command Line Tools)
- ✅ Universal compatibility across Intel and Apple Silicon Macs
- ✅ Smaller download than compiling during install
Build process:
# Build for both architectures
clang++ -arch x86_64 -o spawn-helper-x64 spawn-helper.cc
clang++ -arch arm64 -o spawn-helper-arm64 spawn-helper.cc
# Create universal binary
lipo -create spawn-helper-x64 spawn-helper-arm64 -output spawn-helper-universal
# Include in all macOS prebuilds
Package Optimization
File Exclusions
Development artifacts are excluded from the final package:
- Test files (
public/bundle/test.js,public/test/directory) - Recording files (
*.castprevented by .gitignore) - Build artifacts (
dist/selectively included via package.jsonfilesfield)
Note: screencap.js is kept as it provides screen capture functionality for the web interface.
Size Optimization
- Final size: ~8.5 MB
- File count: ~275 files
- Prebuilds: Included for zero-build installation experience
- Source code: Minimal, compiled assets only
Development Commands
Local Development
# Multi-platform build with prebuilds (default)
npm run build:npm
# Single-platform build for local testing
node scripts/build-npm.js --current-only
# Test package locally
npm pack
# Verify package contents
tar -tzf vibetunnel-*.tgz | head -20
Quality Checks
Always run before publishing:
pnpm run lint # Check code style
pnpm run typecheck # Verify TypeScript
Publishing
Prerequisites
- Update version in
package.json - Run multi-platform build
- Test package locally
- Verify all prebuilds are included
Publish Command
npm publish
Usage After Installation
Installation
# Install globally
npm install -g vibetunnel
Starting the Server
# Start with default settings (port 4020)
vibetunnel
# Start with custom port
vibetunnel --port 8080
# Start without authentication
vibetunnel --no-auth
Then open http://localhost:4020 in your browser to access the web interface.
Using the vt Command
# Monitor AI agents with automatic activity tracking
vt claude
vt claude --dangerously-skip-permissions
# Run commands with output visible in VibeTunnel
vt npm test
vt python script.py
vt top
# Launch interactive shell
vt --shell
vt -i
# Update session title (inside a session)
vt title "My Project"
Command Forwarding
# Basic usage
vibetunnel fwd <session-id> <command> [args...]
# Examples
vibetunnel fwd --session-id abc123 ls -la
vibetunnel fwd --session-id abc123 npm test
vibetunnel fwd --session-id abc123 python script.py
Coexistence with Mac App
The npm package works seamlessly alongside the Mac app:
Command Routing
- The
vtcommand from npm automatically detects if the Mac app is installed - If Mac app found at
/Applications/VibeTunnel.app, npmvtdefers to it - Ensures you always get the best available implementation
Installation Behavior
- Won't overwrite existing
/usr/local/bin/vtfrom other tools - Provides helpful warnings if conflicts exist
- Installation always succeeds, even if
vtsymlink can't be created - Use
vibetunnelornpx vtas alternatives
Troubleshooting
Common Issues
Missing Build Tools
Error: gyp ERR! stack Error: not found: make
Solution: Install build tools:
- macOS:
xcode-select --install - Linux:
apt-get install build-essential
Missing PAM Development Libraries
Error: fatal error: security/pam_appl.h: No such file or directory
Solution: Install PAM development libraries:
- Linux:
apt-get install libpam0g-dev - macOS: Usually available by default
Docker Not Available
Error: Docker is required for multi-platform builds
Solution: Install Docker using OrbStack or Docker Desktop
Prebuild Download Failures
Error: prebuild-install warn install No prebuilt binaries found
Cause: Network issues or unsupported platform/Node version
Result: Automatic fallback to source compilation
Debugging Installation
# Verbose npm install
npm install -g vibetunnel --verbose
# Check prebuild availability
npx prebuild-install --list
# Force source compilation
npm install -g vibetunnel --build-from-source
Architecture Decisions
Why Prebuilds?
- User experience: No build tools required for most users
- Installation speed: Pre-compiled binaries install much faster
- Reliability: Eliminates compilation errors in user environments
- Cross-platform: Supports all target platforms without user setup
Why Docker for Linux Builds?
- Cross-compilation: Build Linux binaries from macOS development machine
- Consistency: Reproducible build environment
- Dependencies: Proper PAM library versions for Linux
Why Vendored node-pty?
- Control: Custom modifications for VibeTunnel's needs
- Reliability: Avoid external dependency issues
- Optimization: Minimal implementation without unnecessary features
Related Files
scripts/build-npm.js- Unified npm build process with multi-platform supportscripts/postinstall-npm.js- Fallback compilation logic.prebuildrc- Prebuild configuration for target platformspackage.json- Package configuration and file inclusions