Poltergeist The ghost that keeps your builds fresh π»
A universal file watcher with auto-rebuild for any language or build system
Poltergeist is an AI-friendly universal file-watcher that auto-detects any project and rebuilds them as soon as a file has been changed. Think npm run dev for native apps, with automatic configuration, notifications and a smart build queue. It stands on the shoulders of giants and fills the glue layer that's been missing.
Works on macOS, Linux, and Windows. Available as a standalone binary (no Node.js required) or npm package.
π Read the story behind Poltergeist: The Ghost That Keeps Your Builds Fresh - Learn how this tool was built using Claude Code and why it's designed to accelerate both human and AI development workflows.
Installation
Homebrew (macOS, ARM64)
brew tap steipete/tap brew install poltergeist
npm (all platforms)
npm install -g @steipete/poltergeist
Requirements
Poltergeist requires Watchman to be installed:
macOS : brew install watchman
: Linux : Installation guide
: Installation guide Windows: Chocolatey package or manual install
Poltergeist offers both a CLI tool for universal development and a native macOS app for enhanced monitoring (coming soon).
Features
Universal Target System : Support for anything you can build - executables, app bundles, libraries, frameworks, tests, Docker containers, ...
: Support for anything you can build - executables, app bundles, libraries, frameworks, tests, Docker containers, ... Smart Execution Wrapper : polter command that waits for a build to complete, then starts it
: command that waits for a build to complete, then starts it Real-time Build Output : See build progress as it happens, no more waiting in the dark
: See build progress as it happens, no more waiting in the dark Inline Error Diagnostics : Build errors shown immediately with context and actionable suggestions
: Build errors shown immediately with context and actionable suggestions Manual Build Command : Trigger builds explicitly with poltergeist build [target]
: Trigger builds explicitly with Automatic Recovery : Recent build failures trigger automatic rebuild attempts
: Recent build failures trigger automatic rebuild attempts Efficient File Watching : Powered by Facebook's Watchman with smart exclusions and performance optimization
: Powered by Facebook's Watchman with smart exclusions and performance optimization Intelligent Build Prioritization : Having multiple projects that share code? Polgergeist will compile the right one first, based on which files you edited in the past
: Having multiple projects that share code? Polgergeist will compile the right one first, based on which files you edited in the past Automatic Project Configuration : Just type poltergeist init and it'll parse your folder and set up the config.
: Just type and it'll parse your folder and set up the config. Native Notifications : System notifications with customizable sounds and icon for build status
: System notifications with customizable sounds and icon for build status Concurrent Build Protection : Intelligent locking prevents overlapping builds
: Intelligent locking prevents overlapping builds Advanced State Management : Process tracking, build history, and heartbeat monitoring
: Process tracking, build history, and heartbeat monitoring Automatic Configuration Reloading: Changes to poltergeist.config.json are detected and applied without manual restart
Designed for Humans and Agents
Polgergeist has been designed with an agentic workflow in mind. As soon as your agent starts editing files, we'll start a background compile process. Further edits will cancel and re-compile as needed. Since agents are relatively slow, there's a good chance your project already finished compiling before the agent tries to even run it. Benefits:
Agents don't have to call build manually anymore
They call your executable directly with polter as prefix, which waits until the build is complete.
as prefix, which waits until the build is complete. Build errors are shown inline with actionable suggestions
Automatic rebuild attempts for recent failures
Real-time build output available with --verbose flag
flag Faster loops, fewer wasted tokens
Commands have been designed with the least surprises, the cli works just like what agents expect, and there's plenty aliases so things will just work, even if your agent gets confused.
Examples:
haunt is used to start the daemon, but start is also a valid alias
is used to start the daemon, but is also a valid alias Commands that are executed in a non-tty environment have added helpful messages for agents
Fuzzy matching will find targets even if they are misspelled
Build time is tracked, so agents can set their timeout correctly for waiting
Commands are token conservative by default and don't emit the full build log
Quick Start
Installation
Install globally via npm:
npm install -g @steipete/poltergeist
Basic Usage
Automatic Configuration - Let Poltergeist analyze your project:
poltergeist init
This automatically detects your project type (Swift, Node.js, Rust, Python, CMake, etc.) and creates an optimized configuration.
Start Watching - Begin auto-building on file changes:
poltergeist haunt # Runs as background daemon (default) poltergeist status # Check what's running poltergeist status --verbose # Show detailed status with build stats
Execute Fresh Builds - Use polter to ensure you never run stale code:
polter my-app # Waits for build, then runs fresh binary polter my-app --help # All arguments passed through
That's it! Poltergeist now watches your files and rebuilds automatically.
Each project gets its own background process, but poltergeist status shows everything through a shared state system in /tmp/poltergeist/ . One project crashing never affects others.
Table of Contents
Command Line Interface
Poltergeist provides two main commands: poltergeist for managing the file watcher daemon, and polter for executing fresh builds.
Core Commands (poltergeist)
Starting and Managing the Daemon
# Start watching (runs as background daemon by default) poltergeist haunt poltergeist start # Alias for haunt # Check what's running poltergeist status # Shows all active projects and their build status # Manually trigger a build poltergeist build # Build default target poltergeist build my-app # Build specific target poltergeist build --verbose # Show real-time build output # View build logs poltergeist logs # Recent logs poltergeist logs -f # Follow logs in real-time # Stop watching poltergeist stop # Stop all targets poltergeist stop --target my-app # Stop specific target
Project Management
# Initialize configuration poltergeist init # Auto-detect and create config poltergeist init --cmake # Specialized CMake detection # List configured targets poltergeist list # Shows all targets and their status # Clean up old state files poltergeist clean # Remove stale state files poltergeist clean --all # Remove all state files
Smart Execution with polter
The polter command ensures you always run fresh builds:
# Basic usage polter < target-name > [arguments...] # Examples polter my-app # Run after build completes polter my-app --port 8080 # All arguments passed through polter backend serve --watch # Complex commands work too # Options polter my-app --timeout 60000 # Wait up to 60 seconds polter my-app --force # Run even if build failed polter my-app --verbose # Show build progress
How it works:
Checks if target is currently building Waits for build to complete (with progress updates) Fails immediately if build failed Executes the fresh binary with your arguments
Daemon Mode Details
Since v1.4.0, Poltergeist runs as a daemon by default:
Non-blocking : Returns control immediately
: Returns control immediately Background builds : Continues watching/building after terminal closes
: Continues watching/building after terminal closes Multi-project : Each project runs independently
: Each project runs independently Persistent logs: Access logs anytime with poltergeist logs
To run in traditional foreground mode:
poltergeist haunt --foreground # Blocks terminal, shows output directly
Command Reference
Command Description Example haunt / start Start watching and building poltergeist haunt --target frontend --log-level debug stop / rest Stop the daemon poltergeist stop restart Restart the daemon poltergeist restart status Show build status poltergeist status --verbose logs View daemon logs poltergeist logs -f -n 100 list List all targets poltergeist list init Create configuration poltergeist init --cmake clean Clean state files poltergeist clean --dry-run polter Execute fresh builds polter my-app --help
Configuration
Poltergeist can automatically detect and configure most projects, but also supports detailed manual configuration.
Automatic Project Detection
Run poltergeist init to automatically:
Detect project type (Swift, Node.js, Rust, Python, CMake, etc.)
Find build commands and output paths
Configure optimal watch patterns
Set up smart exclusions
Generate poltergeist.config.json
Project detection looks for:
Package.swift β Swift Package Manager
β Swift Package Manager package.json β Node.js/npm
β Node.js/npm Cargo.toml β Rust/Cargo
β Rust/Cargo CMakeLists.txt β CMake projects
β CMake projects pyproject.toml β Python projects
β Python projects And more...
Configuration Schema
Essential configuration structure:
{ "version" : " 1.0 " , "projectType" : " swift|node|rust|python|cmake|mixed " , "targets" : [ { "name" : " my-app " , "type" : " executable|app-bundle|library|framework|test|docker|custom " , "buildCommand" : " cargo build --release " , "outputPath" : " ./target/release/myapp " , "watchPaths" : [ " src/**/*.rs " ] } ], "buildScheduling" : { "parallelization" : 2 }, "notifications" : { "enabled" : true }, "logging" : { "level" : " info " , "file" : " .poltergeist.log " } }
Logging Configuration
Control the verbosity and output of Poltergeist logging:
{ "logging" : { "level" : " debug " , // Options: debug, info, warn, error "file" : " .poltergeist.log " // Log file path (relative or absolute) } }
Setting Log Level
You can control logging verbosity through multiple methods (in order of priority):
CLI Flag: poltergeist haunt --log-level debug Verbose Flag: poltergeist haunt --verbose (sets level to debug) Configuration File: Set in poltergeist.config.json Default: Falls back to info level
Log Levels
debug : Detailed information for debugging (Watchman events, state changes, etc.)
: Detailed information for debugging (Watchman events, state changes, etc.) info : Standard operational messages (default)
: Standard operational messages (default) warn : Warning messages that don't prevent operation
: Warning messages that don't prevent operation error : Error messages only
Viewing Logs
poltergeist logs # View recent logs poltergeist logs -f # Follow logs in real-time poltergeist logs -n 100 # Show last 100 lines
Target Types
Poltergeist supports multiple target types with specific optimizations:
Type Use Case Key Properties executable CLI tools, binaries outputPath , standard execution app-bundle macOS/iOS apps bundleId , autoRelaunch , app lifecycle library Static/dynamic libs libraryType , linking optimization framework macOS/iOS frameworks Platform-specific builds test Test suites testCommand , coverageFile docker Containerized apps imageName , dockerfile , tags custom Custom builds Flexible config object cmake-executable CMake executables targetName , generator , buildType cmake-library CMake libraries targetName , libraryType , generator cmake-custom CMake custom targets targetName , custom CMake commands
Watch Path Patterns
Poltergeist supports glob patterns with brace expansion for more compact configurations:
Basic Patterns
"watchPaths" : [ " src/**/*.swift " , // All Swift files recursively " **/*.{js,ts} " , // All JavaScript and TypeScript files " tests/**/*Test.swift " // Test files with specific naming ]
Brace Expansion
Reduce repetition with brace expansion patterns:
// Instead of: "watchPaths" : [ " src/**/*.c " , " src/**/*.cpp " , " src/**/*.h " ] // Use: "watchPaths" : [ " src/**/*.{c,cpp,h} " // All C/C++ source and header files ]
Advanced Examples
"watchPaths" : [ // Multiple extensions " src/**/*.{swift,m,h} " , // Swift and Objective-C " {src,include}/**/*.{c,cpp,h} " , // Multiple directories " frontend/**/*.{ts,tsx,js,jsx,css} " , // Web assets // Multiple file patterns " {CMakeLists.txt,CMakePresets.json} " , // Specific files " config/{package,tsconfig}.json " , // Config files " **/*.{yaml,yml} " , // YAML files // Complex patterns " {src,test}/**/*.{c,cpp,h} " , // Source and test dirs " apps/{mac,ios}/**/*.swift " , // Platform-specific " **/{Makefile,*.mk} " // Make files ]
Smart Defaults
Poltergeist uses sensible defaults to keep configurations minimal. Only specify what differs from defaults:
Default Values (don't specify these):
enabled: true - Targets are enabled by default
- Targets are enabled by default settlingDelay: 1000 - 1 second delay before building
- 1 second delay before building debounceInterval: 3000 - 3 seconds between builds
- 3 seconds between builds useDefaultExclusions: true - Standard exclusions enabled
- Standard exclusions enabled profile: "balanced" - Balanced performance profile
- Balanced performance profile autoOptimize: true - Performance optimization enabled
- Performance optimization enabled notifications.enabled: true - Notifications are on
- Notifications are on buildStart: false - No notification on build start
- No notification on build start buildSuccess: true - Notify on successful builds
- Notify on successful builds buildFailed: true - Notify on failed builds
Only Specify What's Different:
{ "targets" : [{ "name" : " my-app " , "buildCommand" : " ./build.sh " , "watchPaths" : [ " src/**/*.{c,h} " ], "settlingDelay" : 2000 // Only if you need 2s instead of default 1s }] }
Example target configurations { "targets" : [ { "name" : " cli-tool " , "type" : " executable " , "buildCommand" : " cargo build --release " , "outputPath" : " ./target/release/myapp " }, { "name" : " mac-app " , "type" : " app-bundle " , "buildCommand" : " xcodebuild -scheme MyApp " , "bundleId" : " com.example.myapp " , "autoRelaunch" : true }, { "name" : " tests " , "type" : " test " , "testCommand" : " npm test " , "watchPaths" : [ " src/**/* " , " test/**/* " ] } ] }
Full configuration options (with defaults shown for reference) { "version" : " 1.0 " , "projectType" : " swift|node|rust|python|cmake|mixed " , "targets" : [ /* target configs */ ], "watchman" : { "useDefaultExclusions" : true , // default: true "excludeDirs" : [ " custom " , " exclusions " ], "maxFileEvents" : 10000 , // default: 10000 "rules" : [{ "pattern" : " **/test_output/** " , "action" : " ignore " }] }, "performance" : { "profile" : " balanced " , // default: "balanced" "autoOptimize" : true // default: true }, "buildScheduling" : { "parallelization" : 2 , // default: 2 "prioritization" : { "enabled" : true , // default: true "focusDetectionWindow" : 300000 // default: 300000 (5 min) } }, "notifications" : { "enabled" : true , // default: true "successSound" : " Glass " , "failureSound" : " Basso " }, "logging" : { "file" : " .poltergeist.log " , // default: ".poltergeist.log" "level" : " info " // default: "info" } }
Advanced Features
CMake Support
Poltergeist includes comprehensive CMake support with automatic target detection:
# Automatically detect and configure all CMake targets poltergeist init --cmake # Options poltergeist init --cmake --generator Ninja # Specify generator poltergeist init --cmake --preset debug # Use CMake preset poltergeist init --cmake --dry-run # Preview configuration
CMake Features
Automatic Target Detection : Parses CMakeLists.txt to find all targets
: Parses to find all targets Smart Reconfiguration : Automatically runs cmake when CMakeLists.txt changes
: Automatically runs when CMakeLists.txt changes Multi-Generator Support : Works with Ninja, Make, Visual Studio, Xcode
: Works with Ninja, Make, Visual Studio, Xcode Build Type Management : Supports Debug, Release, RelWithDebInfo, MinSizeRel
: Supports Debug, Release, RelWithDebInfo, MinSizeRel Preset Integration : Works with CMakePresets.json
: Works with Parallel Builds: Uses cmake --build --parallel by default
Example CMake Configuration
{ "version" : " 1.0 " , "projectType" : " cmake " , "targets" : [ { "name" : " spine-c-debug " , "type" : " cmake-executable " , "targetName" : " spine-c " , "buildType" : " Debug " , "watchPaths" : [ " **/CMakeLists.txt " , " src/**/*.{c,cpp,h} " , " cmake/**/*.cmake " ] } ] }
Watch Pattern Optimization
Poltergeist automatically optimizes watch patterns using brace expansion and redundancy elimination:
Brace Expansion : Consolidates similar paths (e.g., foo/{bar,baz}/**/*.c )
: Consolidates similar paths (e.g., ) Redundancy Elimination : Removes subdirectory patterns when parent is already watched
: Removes subdirectory patterns when parent is already watched Size Reduction: Typically reduces configuration size by 40-70%
// Before optimization: "watchPaths" : [ " spine-c-unit-tests/memory/**/*.{c,cpp,h} " , " spine-c-unit-tests/minicppunit/**/*.{c,cpp,h} " , " spine-c-unit-tests/tests/**/*.{c,cpp,h} " , " spine-c/include/**/*.{c,cpp,h} " , " spine-c/src/**/*.{c,cpp,h} " ] // After optimization (automatic): "watchPaths" : [ " spine-c-unit-tests/**/*.{c,cpp,h} " , " spine-c/include/**/*.{c,cpp,h} " , " spine-c/src/**/*.{c,cpp,h} " ]
This happens automatically during poltergeist init .
Performance Profiles
Optimize Poltergeist for your project size and needs:
{ "performance" : { "profile" : " conservative|balanced|aggressive " , "autoOptimize" : true } }
conservative : Maximum file coverage, small projects
: Maximum file coverage, small projects balanced : Default, good performance/coverage balance
: Default, good performance/coverage balance aggressive: Maximum performance, large projects
Intelligent Build Prioritization
Automatically builds what you're working on first using focus detection and priority scoring:
{ "buildScheduling" : { "parallelization" : 2 , "prioritization" : { "enabled" : true , "focusDetectionWindow" : 300000 } } }
How it works: Analyzes file change patterns β prioritizes active targets β builds in smart order β faster feedback loops
Smart Exclusions
Poltergeist includes 70+ optimized exclusion patterns:
Version Control : .git , .svn , .hg
: , , Build Artifacts : node_modules , DerivedData , target/ , build/
: , , , IDE Files : .vscode , .idea , *.xcworkspace
: , , OS Files : .DS_Store , Thumbs.db
: , Project-specific: Language and framework-specific patterns
Advanced Configuration Options
Custom exclusions, environment variables, timeouts { "watchman" : { "rules" : [{ "pattern" : " **/test_results/** " , "action" : " ignore " }] }, "targets" : [ { "name" : " backend " , "buildCommand" : " npm run build:prod " , "environment" : { "NODE_ENV" : " production " , "API_URL" : " https://api.com " }, "maxRetries" : 3 , "settlingDelay" : 2000 } ] }
Configuration Reloading
Poltergeist loads configuration once at startup. Configuration changes require a restart to take effect:
# Restart to apply configuration changes poltergeist restart # Or restart specific target only poltergeist restart --target my-app
When to Restart:
After changing build commands or watch paths
After modifying notification settings
After adjusting performance profiles
After updating exclusion rules
Examples
Project configuration examples Swift Package Manager Project { "version" : " 1.0 " , "projectType" : " swift " , "targets" : [ { "name" : " cli-tool " , "type" : " executable " , "buildCommand" : " swift build -c release " , "outputPath" : " ./.build/release/MyTool " , "watchPaths" : [ " {Sources,Tests}/**/*.swift " , " Package.swift " ] }, { "name" : " tests " , "type" : " test " , "testCommand" : " swift test " , "watchPaths" : [ " {Sources,Tests}/**/*.swift " , " Package.swift " ] } ] } Mixed Language Project (Swift + Node.js) { "version" : " 1.0 " , "projectType" : " mixed " , "targets" : [ { "name" : " swift-backend " , "type" : " executable " , "buildCommand" : " ./scripts/build-swift.sh " , "outputPath" : " ./bin/backend " , "watchPaths" : [ " {Backend,Shared}/**/*.swift " ] }, { "name" : " react-frontend " , "type" : " executable " , "buildCommand" : " npm run build " , "outputPath" : " ./frontend/dist " , "watchPaths" : [ " frontend/src/**/*.{ts,tsx,js,jsx,css,scss} " ] }, { "name" : " mac-app " , "type" : " app-bundle " , "bundleId" : " com.example.myapp " , "buildCommand" : " xcodebuild -scheme MyApp " , "autoRelaunch" : true , "watchPaths" : [ " {MacApp,Shared}/**/*.{swift,xib,storyboard} " ] } ] } Docker Development Environment { "version" : " 1.0 " , "projectType" : " node " , "targets" : [ { "name" : " api-dev " , "type" : " docker " , "imageName" : " myapp/api " , "buildCommand" : " docker build -f docker/Dockerfile.dev -t myapp/api:dev . " , "watchPaths" : [ " src/**/*.{js,ts} " , " {package,package-lock}.json " , " docker/Dockerfile.dev " ] } ] } C/C++ Project with CMake { "version" : " 1.0 " , "projectType" : " mixed " , "targets" : [ { "name" : " libspine-debug " , "type" : " library " , "buildCommand" : " ./build.sh " , "outputPath" : " ./build/libspine-c.a " , "watchPaths" : [ " {src,include}/**/*.{c,cpp,h} " , " {CMakeLists.txt,CMakePresets.json} " ], "environment" : { "CMAKE_BUILD_TYPE" : " Debug " } } ], "watchman" : { "excludeDirs" : [ " build " , " target " ] } } macOS/iOS Universal App { "version" : " 1.0 " , "projectType" : " swift " , "targets" : [ { "name" : " universal-app " , "type" : " app-bundle " , "buildCommand" : " xcodebuild -scheme UniversalApp -sdk macosx " , "watchPaths" : [ " **/*.{swift,m,h} " , " **/*.{xcodeproj,xcconfig,entitlements,plist} " , " **/*.{xib,storyboard,xcassets} " ], "settlingDelay" : 1500 // Only if needed, default is 1000ms } ] } Real-World Example: Peekaboo { "version" : " 1.0 " , "projectType" : " mixed " , "targets" : [ { "name" : " peekaboo-cli " , "type" : " executable " , "buildCommand" : " ./scripts/build-swift-debug.sh " , "outputPath" : " ./peekaboo " , "watchPaths" : [ " {Core,Apps/CLI}/**/*.swift " ], "icon" : " ./assets/[email protected] " }, { "name" : " peekaboo-mac " , "type" : " app-bundle " , "platform" : " macos " , "buildCommand" : " ./scripts/build-mac-debug.sh " , "bundleId" : " boo.peekaboo.mac.debug " , "autoRelaunch" : true , "watchPaths" : [ " Apps/Mac/**/*.{swift,storyboard,xib} " , " Core/**/*.swift " ] } ] }
Architecture
Multi-Project Process Model
Poltergeist uses a distributed architecture where each project runs its own independent background process:
Per-Project Processes
# Terminal 1 - Project A cd ~ /projects/my-app poltergeist haunt # Starts separate background process for my-app # Terminal 2 - Project B cd ~ /projects/spine-c poltergeist haunt # Starts separate background process for spine-c # Terminal 3 - From anywhere cd ~ poltergeist status # Shows ALL projects: my-app + spine-c
How It Works
Isolation: Each poltergeist haunt spawns an independent Node.js process State Discovery: Commands scan /tmp/poltergeist/ to find all active projects Global Commands: status , clean , etc. work across all projects simultaneously Per-Project Commands: stop --target , restart --target affect specific targets
Benefits
Reliability : One project crashing doesn't affect others
: One project crashing doesn't affect others Flexibility : Start/stop projects independently
: Start/stop projects independently Performance : No single bottleneck across all projects
: No single bottleneck across all projects Cross-Terminal : Start in one terminal, manage from another
: Start in one terminal, manage from another Scalability: Handle 10+ projects without performance degradation
Dual-Platform Communication
The Node.js CLI and macOS app communicate through shared state files, not direct IPC:
Node.js CLI Process macOS Native App β β Builds targets Monitors state Updates state Shows notifications β β βββββββββββββββββββββββββββββββ β /tmp/poltergeist/ β β βββ project-a.state β β βββ project-b.state β β βββ project-c.state β βββββββββββββββββββββββββββββββ Shared State Files
This design enables:
Platform Independence : CLI works without macOS app
: CLI works without macOS app Real-time Sync : macOS app instantly reflects CLI changes
: macOS app instantly reflects CLI changes Crash Resilience: Either component can restart independently
State Management & Logging
Atomic State System
Poltergeist uses a lock-free state management system with atomic file operations to ensure data consistency across multiple processes and tools.
State File Locations
Unix/Linux/macOS : /tmp/poltergeist/
: Windows : %TEMP%\poltergeist\
: File Pattern: {projectName}-{hash}-{target}.state
/tmp/poltergeist/ βββ my-app-abc123-frontend.state # Frontend target βββ my-app-abc123-backend.state # Backend target βββ spine-c-def456-debug.state # CMake debug build βββ another-project-ghi789-main.state # Main executable βββ ...
Atomic Write Operations
All state updates use atomic writes to prevent corruption:
Write to temp file: {target}.state.tmp.{pid} Atomic rename: mv temp β {target}.state Lock-free: No file locking, no deadlocks
This ensures state files are never partially written and can be safely read by multiple processes simultaneously.
State File Structure
{ "version" : " 1.0 " , "projectPath" : " /Users/dev/my-project " , "projectName" : " my-project " , "target" : " frontend " , "process" : { "pid" : 12345 , "hostname" : " MacBook-Pro.local " , "isActive" : true , "startTime" : " 2025-08-05T20:15:30.000Z " , "lastHeartbeat" : " 2025-08-05T20:16:00.000Z " }, "lastBuild" : { "status" : " success|failure|building|idle " , "timestamp" : " 2025-08-05T20:15:47.500Z " , "duration" : 2500 , "gitHash" : " abc123f " , "builder" : " CMake-Executable/Ninja " , "errorSummary" : " Optional error message " }, "appInfo" : { "bundleId" : " com.example.myapp " , "outputPath" : " ./build/Debug/MyApp.app " , "iconPath" : " ./assets/icon.png " } }
Heartbeat Monitoring
Each Poltergeist process updates its heartbeat every 30 seconds:
Active Process : lastHeartbeat within 30 seconds β isActive: true
: within 30 seconds β Stale Process : lastHeartbeat older than 30 seconds β isActive: false
: older than 30 seconds β Automatic Cleanup: poltergeist clean removes stale state files
Logging System
Structured JSON Logging
Poltergeist uses structured JSON logs with Winston for machine-readable output:
{ "timestamp" : " 2025-08-05T20:15:30.123Z " , "level" : " info " , "message" : " Build completed successfully " , "target" : " frontend " , "duration" : 2500 , "gitHash" : " abc123f " } { "timestamp" : " 2025-08-05T20:15:35.456Z " , "level" : " error " , "message" : " Build failed " , "target" : " backend " , "exitCode" : 1 , "errorSummary" : " Compilation error in main.cpp:42 " }
Log File Management
Location : .poltergeist.log in project root (configurable via logging.file )
: in project root (configurable via ) Rotation : Automatic rotation prevents unlimited growth
: Automatic rotation prevents unlimited growth Multi-Target : Single log file contains all targets with filtering support
: Single log file contains all targets with filtering support Real-time : poltergeist logs --follow for live monitoring
: for live monitoring Build Observation: Log files provide detailed build progress and error details beyond state files
Log Commands
# View recent logs poltergeist logs # Last 50 lines, all targets poltergeist logs --target frontend # Filter by target poltergeist logs --lines 100 # Show more lines # Follow logs in real-time poltergeist logs --follow # All targets poltergeist logs --follow --target backend # JSON output for processing poltergeist logs --json | jq ' .level == "error" '
Build Status Observation
Poltergeist provides multiple layers for observing build status and progress:
1. State Files (Current Status)
# Quick status check - current build state only jq -r ' .lastBuild.status ' /tmp/poltergeist/my-project- * -frontend.state # Output: "success" | "failure" | "building" | "idle" # Get build duration and error summary jq -r ' .lastBuild | "\(.status) - \(.duration)ms - \(.errorSummary // "no errors")" ' /tmp/poltergeist/ * .state
2. Log Files (Detailed History)
# Watch build progress in real-time poltergeist logs --follow --target frontend # Find recent build failures with details poltergeist logs --json | jq ' select(.level == "error" and .target == "frontend") ' # Monitor build times over time poltergeist logs --json | jq ' select(.message | contains("Build completed")) | {target, duration, timestamp} '
3. Combined Monitoring Workflow
# Terminal 1: Watch logs for detailed progress poltergeist logs --follow # Terminal 2: Check current status across all projects watch -n 2 ' poltergeist status ' # Terminal 3: Monitor specific build metrics watch -n 5 ' find /tmp/poltergeist -name "*.state" -exec jq -r "\"\\(.target): \\(.lastBuild.status) (\\(.lastBuild.duration // 0)ms)\"" {} \; '
Key Differences:
State Files : Current snapshot, fast access, minimal details
: Current snapshot, fast access, minimal details Log Files : Complete history, detailed errors, build output, timestamps
: Complete history, detailed errors, build output, timestamps Combined: State files for quick checks, logs for debugging and analysis
Cross-Tool Integration
The state files are designed for external tool integration:
Shell Scripts
# Check if project is building if jq -r ' .lastBuild.status ' /tmp/poltergeist/my-project- * .state | grep -q " building " ; then echo " Build in progress... " fi
IDEs and Editors
// VS Code extension example const stateFiles = glob ( '/tmp/poltergeist/*.state' ) ; const buildStatuses = stateFiles . map ( file => JSON . parse ( fs . readFileSync ( file ) ) ) ;
CI/CD Integration
# GitHub Actions example - name : Wait for Poltergeist build run : | while [[ $(jq -r '.lastBuild.status' /tmp/poltergeist/*-main.state) == "building" ]]; do sleep 5 done
This architecture enables rich integrations while maintaining simplicity and reliability across all supported platforms.
Development
Prerequisites
Node.js 20+ for CLI development
for CLI development Xcode 15+ for macOS app development
for macOS app development Watchman for file watching
CLI Development
# Build from source git clone https://github.com/steipete/poltergeist.git cd poltergeist && npm install && npm run build # Development commands npm test # Run tests npm run dev # Auto-rebuild mode npm run lint # Code quality checks npm run typecheck # Type validation
macOS App Development
# Navigate to macOS app cd apps/mac # Build and run xcodebuild -project Poltergeist.xcodeproj -scheme Poltergeist build open Poltergeist.xcodeproj # Code quality ./scripts/lint.sh # SwiftLint checks ./scripts/format.sh # swift-format fixes
CI/CD Pipeline
Our comprehensive CI/CD pipeline ensures code quality across both platforms:
Multi-platform testing : Node.js 20/22 on Ubuntu, macOS, and Windows
: Node.js 20/22 on Ubuntu, macOS, and Windows Swift 6 validation : Strict concurrency checking and modern Swift practices
: Strict concurrency checking and modern Swift practices Code quality : SwiftLint, swift-format, Biome, and TypeScript checks
: SwiftLint, swift-format, Biome, and TypeScript checks Automated releases : Dual-platform releases with both CLI (.tgz) and macOS app (.dmg/.zip)
: Dual-platform releases with both CLI (.tgz) and macOS app (.dmg/.zip) Test coverage: Comprehensive coverage reporting with Codecov
Project structure and contributing guidelines Project Structure poltergeist/ βββ src/ β βββ builders/ # Target-specific builders β βββ cli.ts # Command line interface β βββ poltergeist.ts # Core application logic β βββ priority-engine.ts # Intelligent priority scoring β βββ build-queue.ts # Smart build queue management β βββ state.ts # State management system β βββ watchman.ts # Watchman file watching βββ test/ # Vitest test files βββ dist/ # Compiled JavaScript output Contributing Contributions welcome! Requirements: Tests pass: npm test Code formatted: npm run format Linting passes: npm run lint Types check: npm run typecheck Development Philosophy No backwards compatibility : Clean breaks over legacy support
: Clean breaks over legacy support Type safety first : Compile-time safety over runtime flexibility
: Compile-time safety over runtime flexibility Performance over features : Optimize for large projects
: Optimize for large projects Simple over complex: Clean APIs over extensive configuration
Changelog
For detailed information about releases, bug fixes, and improvements, see CHANGELOG.md.
License
MIT License - see LICENSE file for details.
Author
Created and maintained by Peter Steinberger
Acknowledgments
Built with these excellent open source projects:
Core Dependencies
Watchman - Facebook's efficient file watching service
- Facebook's efficient file watching service Commander.js - Complete CLI framework
- Complete CLI framework Zod - TypeScript-first schema validation with static type inference
- TypeScript-first schema validation with static type inference Winston - Universal logging library with support for multiple transports
Build & Development
TypeScript - JavaScript with syntax for types
- JavaScript with syntax for types Vitest - Blazing fast unit test framework
- Blazing fast unit test framework Biome - Fast formatter and linter for JavaScript, TypeScript, and more
- Fast formatter and linter for JavaScript, TypeScript, and more TSX - TypeScript execute and REPL for Node.js
- TypeScript execute and REPL for Node.js TypeDoc - Documentation generator for TypeScript projects
User Experience
Chalk - Terminal string styling done right
- Terminal string styling done right Ora - Elegant terminal spinners
- Elegant terminal spinners Node Notifier - Cross-platform native notifications
Utilities
Picomatch - Blazing fast and accurate glob matcher
- Blazing fast and accurate glob matcher Write File Atomic - Write files atomically and reliably
- Write files atomically and reliably fb-watchman - JavaScript client for Facebook's Watchman service
Special Thanks
All contributors and users who have helped shape Poltergeist
The open source community for creating these amazing tools
Keep your builds fresh with Poltergeist