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