{"id":30308387,"url":"https://github.com/steipete/poltergeist","last_synced_at":"2025-08-17T12:03:39.692Z","repository":{"id":307183583,"uuid":"1028635470","full_name":"steipete/poltergeist","owner":"steipete","description":"The ghost that keeps your builds fresh - Universal file watcher and build automation for any language.","archived":false,"fork":false,"pushed_at":"2025-08-12T01:31:04.000Z","size":36890,"stargazers_count":115,"open_issues_count":3,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-17T12:02:08.138Z","etag":null,"topics":["automation","build","filewatcher"],"latest_commit_sha":null,"homepage":"http://polter.build","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/steipete.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-07-29T20:36:49.000Z","updated_at":"2025-08-17T04:47:15.000Z","dependencies_parsed_at":"2025-07-29T23:06:14.918Z","dependency_job_id":"a08a16ff-3a9f-42c7-889f-abe66a4d6fef","html_url":"https://github.com/steipete/poltergeist","commit_stats":null,"previous_names":["steipete/poltergeist"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/steipete/poltergeist","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/steipete%2Fpoltergeist","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/steipete%2Fpoltergeist/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/steipete%2Fpoltergeist/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/steipete%2Fpoltergeist/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/steipete","download_url":"https://codeload.github.com/steipete/poltergeist/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/steipete%2Fpoltergeist/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270843625,"owners_count":24655424,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-17T02:00:09.016Z","response_time":129,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["automation","build","filewatcher"],"created_at":"2025-08-17T12:01:52.391Z","updated_at":"2025-08-17T12:03:39.667Z","avatar_url":"https://github.com/steipete.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"assets/poltergeist-logo.png\" alt=\"Poltergeist Logo\" width=\"200\"\u003e\n  \n  # Poltergeist\n\n  \u003ca href=\"https://nodejs.org\"\u003e\u003cimg src=\"https://img.shields.io/badge/Node.js-20%2B-339933?style=for-the-badge\u0026logo=node.js\u0026logoColor=white\" alt=\"Node.js 20+\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/steipete/poltergeist\"\u003e\u003cimg src=\"https://img.shields.io/badge/platforms-macOS%20%7C%20Linux%20%7C%20Windows-blue?style=for-the-badge\" alt=\"Platforms\"\u003e\u003c/a\u003e\n  \u003ca href=\"LICENSE\"\u003e\u003cimg src=\"https://img.shields.io/badge/license-MIT-green?style=for-the-badge\" alt=\"MIT License\"\u003e\u003c/a\u003e\n  \u003ca href=\"https://github.com/steipete/poltergeist/actions/workflows/ci.yml\"\u003e\u003cimg src=\"https://img.shields.io/github/actions/workflow/status/steipete/poltergeist/ci.yml?style=for-the-badge\u0026logo=github\u0026label=CI\" alt=\"CI Status\"\u003e\u003c/a\u003e\n\n  **The ghost that keeps your builds fresh** 👻  \n  A universal file watcher with auto-rebuild for any language or build system\n\u003c/div\u003e\n\nPoltergeist 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](https://facebook.github.io/watchman/) and fills the glue layer that's been missing.\n\nWorks on macOS, Linux, and Windows. Available as a standalone binary (no Node.js required) or npm package.\n\n\u003e **📖 Read the story behind Poltergeist**: [The Ghost That Keeps Your Builds Fresh](https://steipete.me/posts/2025/poltergeist-ghost-keeps-builds-fresh) - Learn how this tool was built using Claude Code and why it's designed to accelerate both human and AI development workflows.\n\n## Installation\n\n### Homebrew (macOS, ARM64)\n\n```bash\nbrew tap steipete/tap\nbrew install poltergeist\n```\n\n### npm (all platforms)\n\n```bash\nnpm install -g @steipete/poltergeist\n```\n\n### Requirements\n\nPoltergeist requires [Watchman](https://facebook.github.io/watchman/) to be installed:\n  - **macOS**: `brew install watchman`\n  - **Linux**: [Installation guide](https://facebook.github.io/watchman/docs/install#linux)\n  - **Windows**: [Chocolatey package](https://facebook.github.io/watchman/docs/install#windows) or manual install\n\nPoltergeist offers both a **CLI tool** for universal development and a **native macOS app** for enhanced monitoring (coming soon).\n\n## Features\n\n- **Universal Target System**: Support for anything you can build - executables, app bundles, libraries, frameworks, tests, Docker containers, ...\n- **Smart Execution Wrapper**: `polter` command that waits for a build to complete, then starts it\n- **Real-time Build Output**: See build progress as it happens, no more waiting in the dark\n- **Inline Error Diagnostics**: Build errors shown immediately with context and actionable suggestions\n- **Manual Build Command**: Trigger builds explicitly with `poltergeist build [target]`\n- **Automatic Recovery**: Recent build failures trigger automatic rebuild attempts\n- **Efficient File Watching**: Powered by Facebook's Watchman with smart exclusions and performance optimization\n- **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\n- **Automatic Project Configuration**: Just type `poltergeist init` and it'll parse your folder and set up the config.\n- **Native Notifications**: System notifications with customizable sounds and icon for build status\n- **Concurrent Build Protection**: Intelligent locking prevents overlapping builds\n- **Advanced State Management**: Process tracking, build history, and heartbeat monitoring\n- **Automatic Configuration Reloading**: Changes to `poltergeist.config.json` are detected and applied without manual restart\n\n## Designed for Humans and Agents\n\nPolgergeist 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:\n\n- Agents don't have to call build manually anymore\n- They call your executable directly with `polter` as prefix, which waits until the build is complete.\n- Build errors are shown inline with actionable suggestions\n- Automatic rebuild attempts for recent failures\n- Real-time build output available with `--verbose` flag\n- Faster loops, fewer wasted tokens\n\nCommands 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.\n\nExamples:\n- `haunt` is used to start the daemon, but `start` is also a valid alias\n- Commands that are executed in a non-tty environment have added helpful messages for agents\n- Fuzzy matching will find targets even if they are misspelled\n- Build time is tracked, so agents can set their timeout correctly for waiting\n- Commands are token conservative by default and don't emit the full build log\n\n## Quick Start\n\n### Installation\n\nInstall globally via npm:\n\n```bash\nnpm install -g @steipete/poltergeist\n```\n\n### Basic Usage\n\n1. **Automatic Configuration** - Let Poltergeist analyze your project:\n\n```bash\npoltergeist init\n```\n\nThis automatically detects your project type (Swift, Node.js, Rust, Python, CMake, etc.) and creates an optimized configuration.\n\n2. **Start Watching** - Begin auto-building on file changes:\n\n```bash\npoltergeist haunt             # Runs as background daemon (default)\npoltergeist status            # Check what's running\npoltergeist status --verbose  # Show detailed status with build stats\n```\n\n\n3. **Execute Fresh Builds** - Use `polter` to ensure you never run stale code:\n\n```bash\npolter my-app            # Waits for build, then runs fresh binary\npolter my-app --help     # All arguments passed through\n```\n\nThat's it! Poltergeist now watches your files and rebuilds automatically.\n\nEach 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.\n\n## Table of Contents\n\n- [Features](#features)\n- [Designed for Humans and Agents](#designed-for-humans-and-agents)\n- [Quick Start](#quick-start)\n- [Command Line Interface](#command-line-interface)\n  - [Core Commands](#core-commands-poltergeist)\n  - [Smart Execution](#smart-execution-with-polter)\n- [Configuration](#configuration)\n  - [Automatic Detection](#automatic-project-detection)\n  - [Configuration Schema](#configuration-schema)\n  - [Target Types](#target-types)\n  - [Watch Patterns](#watch-path-patterns)\n- [Advanced Features](#advanced-features)\n  - [Smart Defaults](#smart-defaults)\n  - [CMake Support](#cmake-support)\n  - [Performance Profiles](#performance-profiles)\n  - [Build Prioritization](#intelligent-build-prioritization)\n- [Architecture](#architecture)\n- [Examples](#examples)\n- [Development](#development)\n- [License](#license)\n\n## Command Line Interface\n\nPoltergeist provides two main commands: `poltergeist` for managing the file watcher daemon, and `polter` for executing fresh builds.\n\n### Core Commands (poltergeist)\n\n#### Starting and Managing the Daemon\n\n```bash\n# Start watching (runs as background daemon by default)\npoltergeist haunt\npoltergeist start         # Alias for haunt\n\n# Check what's running\npoltergeist status        # Shows all active projects and their build status\n\n# Manually trigger a build\npoltergeist build         # Build default target\npoltergeist build my-app  # Build specific target\npoltergeist build --verbose  # Show real-time build output\n\n# View build logs\npoltergeist logs          # Recent logs\npoltergeist logs -f       # Follow logs in real-time\n\n# Stop watching\npoltergeist stop          # Stop all targets\npoltergeist stop --target my-app  # Stop specific target\n```\n\n#### Project Management\n\n```bash\n# Initialize configuration\npoltergeist init          # Auto-detect and create config\npoltergeist init --cmake  # Specialized CMake detection\n\n# List configured targets\npoltergeist list          # Shows all targets and their status\n\n# Clean up old state files\npoltergeist clean         # Remove stale state files\npoltergeist clean --all   # Remove all state files\n```\n\n### Smart Execution with polter\n\nThe `polter` command ensures you always run fresh builds:\n\n```bash\n# Basic usage\npolter \u003ctarget-name\u003e [arguments...]\n\n# Examples\npolter my-app                    # Run after build completes\npolter my-app --port 8080       # All arguments passed through\npolter backend serve --watch    # Complex commands work too\n\n# Options\npolter my-app --timeout 60000   # Wait up to 60 seconds\npolter my-app --force           # Run even if build failed\npolter my-app --verbose         # Show build progress\n```\n\n**How it works:**\n1. Checks if target is currently building\n2. Waits for build to complete (with progress updates)\n3. Fails immediately if build failed\n4. Executes the fresh binary with your arguments\n\n### Daemon Mode Details\n\nSince v1.4.0, Poltergeist runs as a **daemon by default**:\n\n- **Non-blocking**: Returns control immediately\n- **Background builds**: Continues watching/building after terminal closes\n- **Multi-project**: Each project runs independently\n- **Persistent logs**: Access logs anytime with `poltergeist logs`\n\nTo run in traditional foreground mode:\n```bash\npoltergeist haunt --foreground   # Blocks terminal, shows output directly\n```\n\n### Command Reference\n\n| Command | Description | Example |\n|---------|-------------|---------|\n| `haunt` / `start` | Start watching and building | `poltergeist haunt --target frontend --log-level debug` |\n| `stop` / `rest` | Stop the daemon | `poltergeist stop` |\n| `restart` | Restart the daemon | `poltergeist restart` |\n| `status` | Show build status | `poltergeist status --verbose` |\n| `logs` | View daemon logs | `poltergeist logs -f -n 100` |\n| `list` | List all targets | `poltergeist list` |\n| `init` | Create configuration | `poltergeist init --cmake` |\n| `clean` | Clean state files | `poltergeist clean --dry-run` |\n| `polter` | Execute fresh builds | `polter my-app --help` |\n\n## Configuration\n\nPoltergeist can automatically detect and configure most projects, but also supports detailed manual configuration.\n\n### Automatic Project Detection\n\nRun `poltergeist init` to automatically:\n- Detect project type (Swift, Node.js, Rust, Python, CMake, etc.)\n- Find build commands and output paths\n- Configure optimal watch patterns\n- Set up smart exclusions\n- Generate `poltergeist.config.json`\n\nProject detection looks for:\n- `Package.swift` → Swift Package Manager\n- `package.json` → Node.js/npm\n- `Cargo.toml` → Rust/Cargo\n- `CMakeLists.txt` → CMake projects\n- `pyproject.toml` → Python projects\n- And more...\n\n### Configuration Schema\n\nEssential configuration structure:\n\n```json\n{\n  \"version\": \"1.0\",\n  \"projectType\": \"swift|node|rust|python|cmake|mixed\",\n  \"targets\": [\n    {\n      \"name\": \"my-app\",\n      \"type\": \"executable|app-bundle|library|framework|test|docker|custom\",\n      \"buildCommand\": \"cargo build --release\",\n      \"outputPath\": \"./target/release/myapp\",\n      \"watchPaths\": [\"src/**/*.rs\"]\n    }\n  ],\n  \"buildScheduling\": { \"parallelization\": 2 },\n  \"notifications\": { \"enabled\": true },\n  \"logging\": { \"level\": \"info\", \"file\": \".poltergeist.log\" }\n}\n```\n\n### Logging System (v1.8.0+)\n\nPoltergeist uses a highly efficient target-specific logging system:\n\n#### Log File Structure\n- **Separate files per target**: Each target gets its own log file\n- **Location**: `/tmp/poltergeist/{projectName}-{hash}-{target}.log`\n- **Plain text format**: Simple, parseable: `timestamp level: message`\n- **One log per build**: Fresh log for each build session (no rotation)\n\n#### Benefits\n- **80% smaller** than JSON format\n- **Zero parsing overhead** when reading logs\n- **Natural filtering** - each target has its own file\n- **No redundancy** - target name never repeated in logs\n\n#### Configuration\n\n```json\n{\n  \"logging\": {\n    \"level\": \"debug\"  // Options: debug, info, warn, error\n  }\n}\n```\n\n#### Setting Log Level\n\nYou can control logging verbosity through multiple methods (in order of priority):\n\n1. **CLI Flag**: `poltergeist haunt --log-level debug`\n2. **Verbose Flag**: `poltergeist haunt --verbose` (sets level to debug)\n3. **Configuration File**: Set in `poltergeist.config.json`\n4. **Default**: Falls back to `info` level\n\n#### Log Levels\n\n- **`debug`**: Detailed information for debugging (Watchman events, state changes, etc.)\n- **`info`**: Standard operational messages (default)\n- **`warn`**: Warning messages that don't prevent operation\n- **`error`**: Error messages only\n\n#### Viewing Logs\n\n```bash\npoltergeist logs              # View recent logs for active target\npoltergeist logs myapp        # View logs for specific target\npoltergeist logs -f           # Follow logs in real-time\npoltergeist logs -n 100       # Show last 100 lines\n```\n\n### Target Types\n\nPoltergeist supports multiple target types with specific optimizations:\n\n| Type | Use Case | Key Properties |\n|------|----------|----------------|\n| `executable` | CLI tools, binaries | `outputPath`, standard execution |\n| `app-bundle` | macOS/iOS apps | `bundleId`, `autoRelaunch`, app lifecycle |\n| `library` | Static/dynamic libs | `libraryType`, linking optimization |\n| `framework` | macOS/iOS frameworks | Platform-specific builds |\n| `test` | Test suites | `testCommand`, `coverageFile` |\n| `docker` | Containerized apps | `imageName`, `dockerfile`, `tags` |\n| `custom` | Custom builds | Flexible `config` object |\n| `cmake-executable` | CMake executables | `targetName`, `generator`, `buildType` |\n| `cmake-library` | CMake libraries | `targetName`, `libraryType`, `generator` |\n| `cmake-custom` | CMake custom targets | `targetName`, custom CMake commands |\n\n### Watch Path Patterns\n\nPoltergeist supports glob patterns with brace expansion for more compact configurations:\n\n#### Basic Patterns\n```json\n\"watchPaths\": [\n  \"src/**/*.swift\",           // All Swift files recursively\n  \"**/*.{js,ts}\",            // All JavaScript and TypeScript files\n  \"tests/**/*Test.swift\"      // Test files with specific naming\n]\n```\n\n#### Brace Expansion\nReduce repetition with brace expansion patterns:\n```json\n// Instead of:\n\"watchPaths\": [\n  \"src/**/*.c\",\n  \"src/**/*.cpp\", \n  \"src/**/*.h\"\n]\n\n// Use:\n\"watchPaths\": [\n  \"src/**/*.{c,cpp,h}\"      // All C/C++ source and header files\n]\n```\n\n#### Advanced Examples\n```json\n\"watchPaths\": [\n  // Multiple extensions\n  \"src/**/*.{swift,m,h}\",                    // Swift and Objective-C\n  \"{src,include}/**/*.{c,cpp,h}\",           // Multiple directories\n  \"frontend/**/*.{ts,tsx,js,jsx,css}\",      // Web assets\n  \n  // Multiple file patterns\n  \"{CMakeLists.txt,CMakePresets.json}\",     // Specific files\n  \"config/{package,tsconfig}.json\",         // Config files\n  \"**/*.{yaml,yml}\",                        // YAML files\n  \n  // Complex patterns\n  \"{src,test}/**/*.{c,cpp,h}\",             // Source and test dirs\n  \"apps/{mac,ios}/**/*.swift\",              // Platform-specific\n  \"**/{Makefile,*.mk}\"                      // Make files\n]\n```\n\n### Smart Defaults\n\nPoltergeist uses sensible defaults to keep configurations minimal. Only specify what differs from defaults:\n\n#### Default Values (don't specify these):\n- `enabled: true` - Targets are enabled by default\n- `settlingDelay: 1000` - 1 second delay before building\n- `debounceInterval: 3000` - 3 seconds between builds\n- `useDefaultExclusions: true` - Standard exclusions enabled\n- `profile: \"balanced\"` - Balanced performance profile\n- `autoOptimize: true` - Performance optimization enabled\n- `notifications.enabled: true` - Notifications are on\n- `buildStart: false` - No notification on build start\n- `buildSuccess: true` - Notify on successful builds\n- `buildFailed: true` - Notify on failed builds\n\n#### Only Specify What's Different:\n```json\n{\n  \"targets\": [{\n    \"name\": \"my-app\",\n    \"buildCommand\": \"./build.sh\",\n    \"watchPaths\": [\"src/**/*.{c,h}\"],\n    \"settlingDelay\": 2000  // Only if you need 2s instead of default 1s\n  }]\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eExample target configurations\u003c/summary\u003e\n\n```json\n{\n  \"targets\": [\n    {\n      \"name\": \"cli-tool\",\n      \"type\": \"executable\",\n      \"buildCommand\": \"cargo build --release\",\n      \"outputPath\": \"./target/release/myapp\"\n    },\n    {\n      \"name\": \"mac-app\",\n      \"type\": \"app-bundle\",\n      \"buildCommand\": \"xcodebuild -scheme MyApp\",\n      \"bundleId\": \"com.example.myapp\",\n      \"autoRelaunch\": true\n    },\n    {\n      \"name\": \"tests\",\n      \"type\": \"test\",\n      \"testCommand\": \"npm test\",\n      \"watchPaths\": [\"src/**/*\", \"test/**/*\"]\n    }\n  ]\n}\n```\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eFull configuration options (with defaults shown for reference)\u003c/summary\u003e\n\n```json\n{\n  \"version\": \"1.0\",\n  \"projectType\": \"swift|node|rust|python|cmake|mixed\",\n  \"targets\": [/* target configs */],\n  \"watchman\": {\n    \"useDefaultExclusions\": true,        // default: true\n    \"excludeDirs\": [\"custom\", \"exclusions\"],\n    \"maxFileEvents\": 10000,              // default: 10000\n    \"rules\": [{\"pattern\": \"**/test_output/**\", \"action\": \"ignore\"}]\n  },\n  \"performance\": {\n    \"profile\": \"balanced\",               // default: \"balanced\"\n    \"autoOptimize\": true                 // default: true\n  },\n  \"buildScheduling\": {\n    \"parallelization\": 2,                // default: 2\n    \"prioritization\": {\n      \"enabled\": true,                   // default: true\n      \"focusDetectionWindow\": 300000     // default: 300000 (5 min)\n    }\n  },\n  \"notifications\": {\n    \"enabled\": true,                     // default: true\n    \"successSound\": \"Glass\",\n    \"failureSound\": \"Basso\"\n  },\n  \"logging\": {\n    \"file\": \".poltergeist.log\",         // default: \".poltergeist.log\"\n    \"level\": \"info\"                     // default: \"info\"\n  }\n}\n```\n\u003c/details\u003e\n\n## Advanced Features\n\n### CMake Support\n\nPoltergeist includes comprehensive CMake support with automatic target detection:\n\n#### Auto-Initialization\n```bash\n# Automatically detect and configure all CMake targets\npoltergeist init --cmake\n\n# Options\npoltergeist init --cmake --generator Ninja    # Specify generator\npoltergeist init --cmake --preset debug        # Use CMake preset\npoltergeist init --cmake --dry-run            # Preview configuration\n```\n\n#### CMake Features\n- **Automatic Target Detection**: Parses `CMakeLists.txt` to find all targets\n- **Smart Reconfiguration**: Automatically runs `cmake` when CMakeLists.txt changes  \n- **Multi-Generator Support**: Works with Ninja, Make, Visual Studio, Xcode\n- **Build Type Management**: Supports Debug, Release, RelWithDebInfo, MinSizeRel\n- **Preset Integration**: Works with `CMakePresets.json`\n- **Parallel Builds**: Uses `cmake --build --parallel` by default\n\n#### Example CMake Configuration\n```json\n{\n  \"version\": \"1.0\",\n  \"projectType\": \"cmake\",\n  \"targets\": [\n    {\n      \"name\": \"spine-c-debug\",\n      \"type\": \"cmake-executable\",\n      \"targetName\": \"spine-c\",\n      \"buildType\": \"Debug\",\n      \"watchPaths\": [\n        \"**/CMakeLists.txt\",\n        \"src/**/*.{c,cpp,h}\",\n        \"cmake/**/*.cmake\"\n      ]\n    }\n  ]\n}\n```\n\n### Watch Pattern Optimization\n\nPoltergeist automatically optimizes watch patterns using brace expansion and redundancy elimination:\n\n- **Brace Expansion**: Consolidates similar paths (e.g., `foo/{bar,baz}/**/*.c`)\n- **Redundancy Elimination**: Removes subdirectory patterns when parent is already watched\n- **Size Reduction**: Typically reduces configuration size by 40-70%\n\n```json\n// Before optimization:\n\"watchPaths\": [\n  \"spine-c-unit-tests/memory/**/*.{c,cpp,h}\",\n  \"spine-c-unit-tests/minicppunit/**/*.{c,cpp,h}\",\n  \"spine-c-unit-tests/tests/**/*.{c,cpp,h}\",\n  \"spine-c/include/**/*.{c,cpp,h}\",\n  \"spine-c/src/**/*.{c,cpp,h}\"\n]\n\n// After optimization (automatic):\n\"watchPaths\": [\n  \"spine-c-unit-tests/**/*.{c,cpp,h}\",\n  \"spine-c/include/**/*.{c,cpp,h}\",\n  \"spine-c/src/**/*.{c,cpp,h}\"\n]\n```\n\nThis happens automatically during `poltergeist init`.\n\n### Performance Profiles\n\nOptimize Poltergeist for your project size and needs:\n\n```json\n{\n  \"performance\": {\"profile\": \"conservative|balanced|aggressive\", \"autoOptimize\": true}\n}\n```\n\n- **conservative**: Maximum file coverage, small projects\n- **balanced**: Default, good performance/coverage balance  \n- **aggressive**: Maximum performance, large projects\n\n### Intelligent Build Prioritization\n\nAutomatically builds what you're working on first using focus detection and priority scoring:\n\n```json\n{\n  \"buildScheduling\": {\n    \"parallelization\": 2,\n    \"prioritization\": {\"enabled\": true, \"focusDetectionWindow\": 300000}\n  }\n}\n```\n\n**How it works**: Analyzes file change patterns → prioritizes active targets → builds in smart order → faster feedback loops\n\n### Smart Exclusions\n\nPoltergeist includes 70+ optimized exclusion patterns:\n- **Version Control**: `.git`, `.svn`, `.hg`\n- **Build Artifacts**: `node_modules`, `DerivedData`, `target/`, `build/`\n- **IDE Files**: `.vscode`, `.idea`, `*.xcworkspace`\n- **OS Files**: `.DS_Store`, `Thumbs.db`\n- **Project-specific**: Language and framework-specific patterns\n\n### Advanced Configuration Options\n\n\u003cdetails\u003e\n\u003csummary\u003eCustom exclusions, environment variables, timeouts\u003c/summary\u003e\n\n```json\n{\n  \"watchman\": {\n    \"rules\": [{\"pattern\": \"**/test_results/**\", \"action\": \"ignore\"}]\n  },\n  \"targets\": [\n    {\n      \"name\": \"backend\",\n      \"buildCommand\": \"npm run build:prod\",\n      \"environment\": {\"NODE_ENV\": \"production\", \"API_URL\": \"https://api.com\"},\n      \"maxRetries\": 3,\n      \"settlingDelay\": 2000\n    }\n  ]\n}\n```\n\u003c/details\u003e\n\n### Configuration Reloading\n\nPoltergeist loads configuration once at startup. **Configuration changes require a restart** to take effect:\n\n```bash\n# Restart to apply configuration changes\npoltergeist restart\n\n# Or restart specific target only\npoltergeist restart --target my-app\n```\n\n**When to Restart:**\n- After changing build commands or watch paths\n- After modifying notification settings\n- After adjusting performance profiles\n- After updating exclusion rules\n\n\n\n## Examples\n\n\u003cdetails\u003e\n\u003csummary\u003eProject configuration examples\u003c/summary\u003e\n\n### Swift Package Manager Project\n```json\n{\n  \"version\": \"1.0\",\n  \"projectType\": \"swift\",\n  \"targets\": [\n    {\n      \"name\": \"cli-tool\",\n      \"type\": \"executable\",\n      \"buildCommand\": \"swift build -c release\",\n      \"outputPath\": \"./.build/release/MyTool\",\n      \"watchPaths\": [\"{Sources,Tests}/**/*.swift\", \"Package.swift\"]\n    },\n    {\n      \"name\": \"tests\",\n      \"type\": \"test\",\n      \"testCommand\": \"swift test\",\n      \"watchPaths\": [\"{Sources,Tests}/**/*.swift\", \"Package.swift\"]\n    }\n  ]\n}\n```\n\n### Mixed Language Project (Swift + Node.js)\n```json\n{\n  \"version\": \"1.0\",\n  \"projectType\": \"mixed\",\n  \"targets\": [\n    {\n      \"name\": \"swift-backend\",\n      \"type\": \"executable\",\n      \"buildCommand\": \"./scripts/build-swift.sh\",\n      \"outputPath\": \"./bin/backend\",\n      \"watchPaths\": [\"{Backend,Shared}/**/*.swift\"]\n    },\n    {\n      \"name\": \"react-frontend\", \n      \"type\": \"executable\",\n      \"buildCommand\": \"npm run build\",\n      \"outputPath\": \"./frontend/dist\",\n      \"watchPaths\": [\"frontend/src/**/*.{ts,tsx,js,jsx,css,scss}\"]\n    },\n    {\n      \"name\": \"mac-app\",\n      \"type\": \"app-bundle\",\n      \"bundleId\": \"com.example.myapp\",\n      \"buildCommand\": \"xcodebuild -scheme MyApp\",\n      \"autoRelaunch\": true,\n      \"watchPaths\": [\"{MacApp,Shared}/**/*.{swift,xib,storyboard}\"]\n    }\n  ]\n}\n```\n\n### Docker Development Environment\n```json\n{\n  \"version\": \"1.0\",\n  \"projectType\": \"node\",\n  \"targets\": [\n    {\n      \"name\": \"api-dev\",\n      \"type\": \"docker\",\n      \"imageName\": \"myapp/api\",\n      \"buildCommand\": \"docker build -f docker/Dockerfile.dev -t myapp/api:dev .\",\n      \"watchPaths\": [\"src/**/*.{js,ts}\", \"{package,package-lock}.json\", \"docker/Dockerfile.dev\"]\n    }\n  ]\n}\n```\n\n### C/C++ Project with CMake\n```json\n{\n  \"version\": \"1.0\",\n  \"projectType\": \"mixed\",\n  \"targets\": [\n    {\n      \"name\": \"libspine-debug\",\n      \"type\": \"library\",\n      \"buildCommand\": \"./build.sh\",\n      \"outputPath\": \"./build/libspine-c.a\",\n      \"watchPaths\": [\n        \"{src,include}/**/*.{c,cpp,h}\",\n        \"{CMakeLists.txt,CMakePresets.json}\"\n      ],\n      \"environment\": { \"CMAKE_BUILD_TYPE\": \"Debug\" }\n    }\n  ],\n  \"watchman\": {\n    \"excludeDirs\": [\"build\", \"target\"]\n  }\n}\n```\n\n### macOS/iOS Universal App\n```json\n{\n  \"version\": \"1.0\",\n  \"projectType\": \"swift\",\n  \"targets\": [\n    {\n      \"name\": \"universal-app\",\n      \"type\": \"app-bundle\",\n      \"buildCommand\": \"xcodebuild -scheme UniversalApp -sdk macosx\",\n      \"watchPaths\": [\n        \"**/*.{swift,m,h}\",\n        \"**/*.{xcodeproj,xcconfig,entitlements,plist}\",\n        \"**/*.{xib,storyboard,xcassets}\"\n      ],\n      \"settlingDelay\": 1500  // Only if needed, default is 1000ms\n    }\n  ]\n}\n```\n\n### Real-World Example: Peekaboo\n```json\n{\n  \"version\": \"1.0\",\n  \"projectType\": \"mixed\",\n  \"targets\": [\n    {\n      \"name\": \"peekaboo-cli\",\n      \"type\": \"executable\",\n      \"buildCommand\": \"./scripts/build-swift-debug.sh\",\n      \"outputPath\": \"./peekaboo\",\n      \"watchPaths\": [\n        \"{Core,Apps/CLI}/**/*.swift\"\n      ],\n      \"icon\": \"./assets/icon_512x512@2x.png\"\n    },\n    {\n      \"name\": \"peekaboo-mac\",\n      \"type\": \"app-bundle\",\n      \"platform\": \"macos\",\n      \"buildCommand\": \"./scripts/build-mac-debug.sh\",\n      \"bundleId\": \"boo.peekaboo.mac.debug\",\n      \"autoRelaunch\": true,\n      \"watchPaths\": [\n        \"Apps/Mac/**/*.{swift,storyboard,xib}\",\n        \"Core/**/*.swift\"\n      ]\n    }\n  ]\n}\n```\n\n\u003c/details\u003e\n\n## Architecture\n\n### Multi-Project Process Model\n\nPoltergeist uses a **distributed architecture** where each project runs its own independent background process:\n\n#### Per-Project Processes\n```bash\n# Terminal 1 - Project A\ncd ~/projects/my-app\npoltergeist haunt  # Starts separate background process for my-app\n\n# Terminal 2 - Project B  \ncd ~/projects/spine-c\npoltergeist haunt  # Starts separate background process for spine-c\n\n# Terminal 3 - From anywhere\ncd ~\npoltergeist status  # Shows ALL projects: my-app + spine-c\n```\n\n#### How It Works\n1. **Isolation**: Each `poltergeist haunt` spawns an independent Node.js process\n2. **State Discovery**: Commands scan `/tmp/poltergeist/` to find all active projects\n3. **Global Commands**: `status`, `clean`, etc. work across all projects simultaneously\n4. **Per-Project Commands**: `stop --target`, `restart --target` affect specific targets\n\n#### Benefits\n- **Reliability**: One project crashing doesn't affect others\n- **Flexibility**: Start/stop projects independently  \n- **Performance**: No single bottleneck across all projects\n- **Cross-Terminal**: Start in one terminal, manage from another\n- **Scalability**: Handle 10+ projects without performance degradation\n\n### Dual-Platform Communication\n\nThe **Node.js CLI** and **macOS app** communicate through shared state files, not direct IPC:\n\n```\nNode.js CLI Process          macOS Native App\n       ↓                            ↓\n   Builds targets              Monitors state\n   Updates state               Shows notifications\n       ↓                            ↓\n       ┌─────────────────────────────┐\n       │   /tmp/poltergeist/         │\n       │   ├── project-a.state       │\n       │   ├── project-b.state       │\n       │   └── project-c.state       │\n       └─────────────────────────────┘\n                Shared State Files\n```\n\nThis design enables:\n- **Platform Independence**: CLI works without macOS app\n- **Real-time Sync**: macOS app instantly reflects CLI changes\n- **Crash Resilience**: Either component can restart independently\n\n## State Management \u0026 Logging\n\n### Atomic State System\n\nPoltergeist uses a **lock-free state management system** with atomic file operations to ensure data consistency across multiple processes and tools.\n\n#### State File Locations\n- **Unix/Linux/macOS**: `/tmp/poltergeist/`\n- **Windows**: `%TEMP%\\poltergeist\\`\n- **File Pattern**: `{projectName}-{hash}-{target}.state`\n\n```bash\n/tmp/poltergeist/\n├── my-app-abc123-frontend.state      # Frontend target\n├── my-app-abc123-backend.state       # Backend target  \n├── spine-c-def456-debug.state        # CMake debug build\n├── another-project-ghi789-main.state # Main executable\n└── ...\n```\n\n#### Atomic Write Operations\n\nAll state updates use **atomic writes** to prevent corruption:\n\n1. **Write to temp file**: `{target}.state.tmp.{pid}`\n2. **Atomic rename**: `mv temp → {target}.state` \n3. **Lock-free**: No file locking, no deadlocks\n\nThis ensures state files are **never partially written** and can be safely read by multiple processes simultaneously.\n\n#### State File Structure\n\n```json\n{\n  \"version\": \"1.0\",\n  \"projectPath\": \"/Users/dev/my-project\",\n  \"projectName\": \"my-project\", \n  \"target\": \"frontend\",\n  \"process\": {\n    \"pid\": 12345,\n    \"hostname\": \"MacBook-Pro.local\",\n    \"isActive\": true,\n    \"startTime\": \"2025-08-05T20:15:30.000Z\",\n    \"lastHeartbeat\": \"2025-08-05T20:16:00.000Z\"\n  },\n  \"lastBuild\": {\n    \"status\": \"success|failure|building|idle\",\n    \"timestamp\": \"2025-08-05T20:15:47.500Z\",\n    \"duration\": 2500,\n    \"gitHash\": \"abc123f\",\n    \"builder\": \"CMake-Executable/Ninja\",\n    \"errorSummary\": \"Optional error message\"\n  },\n  \"appInfo\": {\n    \"bundleId\": \"com.example.myapp\",\n    \"outputPath\": \"./build/Debug/MyApp.app\",\n    \"iconPath\": \"./assets/icon.png\"\n  }\n}\n```\n\n#### Heartbeat Monitoring\n\nEach Poltergeist process updates its heartbeat every **30 seconds**:\n\n- **Active Process**: `lastHeartbeat` within 30 seconds → `isActive: true`\n- **Stale Process**: `lastHeartbeat` older than 30 seconds → `isActive: false`\n- **Automatic Cleanup**: `poltergeist clean` removes stale state files\n\n### Logging System\n\n#### Structured JSON Logging\n\nPoltergeist uses **structured JSON logs** with Winston for machine-readable output:\n\n```json\n{\"timestamp\":\"2025-08-05T20:15:30.123Z\",\"level\":\"info\",\"message\":\"Build completed successfully\",\"target\":\"frontend\",\"duration\":2500,\"gitHash\":\"abc123f\"}\n{\"timestamp\":\"2025-08-05T20:15:35.456Z\",\"level\":\"error\",\"message\":\"Build failed\",\"target\":\"backend\",\"exitCode\":1,\"errorSummary\":\"Compilation error in main.cpp:42\"}\n```\n\n#### Log File Management\n\n- **Location**: `.poltergeist.log` in project root (configurable via `logging.file`)\n- **Rotation**: Automatic rotation prevents unlimited growth\n- **Multi-Target**: Single log file contains all targets with filtering support\n- **Real-time**: `poltergeist logs --follow` for live monitoring\n- **Build Observation**: Log files provide detailed build progress and error details beyond state files\n\n#### Log Commands\n\n```bash\n# View recent logs\npoltergeist logs                    # Last 50 lines, all targets\npoltergeist logs --target frontend  # Filter by target\npoltergeist logs --lines 100        # Show more lines\n\n# Follow logs in real-time\npoltergeist logs --follow           # All targets\npoltergeist logs --follow --target backend\n\n# JSON output for processing\npoltergeist logs --json | jq '.level == \"error\"'\n```\n\n#### Build Status Observation\n\nPoltergeist provides **multiple layers** for observing build status and progress:\n\n##### 1. State Files (Current Status)\n```bash\n# Quick status check - current build state only\njq -r '.lastBuild.status' /tmp/poltergeist/my-project-*-frontend.state\n# Output: \"success\" | \"failure\" | \"building\" | \"idle\"\n\n# Get build duration and error summary\njq -r '.lastBuild | \"\\(.status) - \\(.duration)ms - \\(.errorSummary // \"no errors\")\"' /tmp/poltergeist/*.state\n```\n\n##### 2. Log Files (Detailed History)\n```bash\n# Watch build progress in real-time\npoltergeist logs --follow --target frontend\n\n# Find recent build failures with details\npoltergeist logs --json | jq 'select(.level == \"error\" and .target == \"frontend\")'\n\n# Monitor build times over time\npoltergeist logs --json | jq 'select(.message | contains(\"Build completed\")) | {target, duration, timestamp}'\n```\n\n##### 3. Combined Monitoring Workflow\n```bash\n# Terminal 1: Watch logs for detailed progress\npoltergeist logs --follow\n\n# Terminal 2: Check current status across all projects  \nwatch -n 2 'poltergeist status'\n\n# Terminal 3: Monitor specific build metrics\nwatch -n 5 'find /tmp/poltergeist -name \"*.state\" -exec jq -r \"\\\"\\\\(.target): \\\\(.lastBuild.status) (\\\\(.lastBuild.duration // 0)ms)\\\"\" {} \\;'\n```\n\n**Key Differences:**\n- **State Files**: Current snapshot, fast access, minimal details\n- **Log Files**: Complete history, detailed errors, build output, timestamps\n- **Combined**: State files for quick checks, logs for debugging and analysis\n\n### Cross-Tool Integration\n\nThe state files are designed for **external tool integration**:\n\n#### Shell Scripts\n```bash\n# Check if project is building\nif jq -r '.lastBuild.status' /tmp/poltergeist/my-project-*.state | grep -q \"building\"; then\n  echo \"Build in progress...\"\nfi\n```\n\n#### IDEs and Editors\n```javascript\n// VS Code extension example\nconst stateFiles = glob('/tmp/poltergeist/*.state');\nconst buildStatuses = stateFiles.map(file =\u003e JSON.parse(fs.readFileSync(file)));\n```\n\n#### CI/CD Integration\n```yaml\n# GitHub Actions example\n- name: Wait for Poltergeist build\n  run: |\n    while [[ $(jq -r '.lastBuild.status' /tmp/poltergeist/*-main.state) == \"building\" ]]; do\n      sleep 5\n    done\n```\n\nThis architecture enables rich integrations while maintaining simplicity and reliability across all supported platforms.\n\n## Development\n\n### Prerequisites\n- **Node.js 20+** for CLI development\n- **Xcode 15+** for macOS app development\n- **Watchman** for file watching\n\n### CLI Development\n```bash\n# Build from source\ngit clone https://github.com/steipete/poltergeist.git\ncd poltergeist \u0026\u0026 npm install \u0026\u0026 npm run build\n\n# Development commands\nnpm test                    # Run tests\nnpm run dev                 # Auto-rebuild mode\nnpm run lint                # Code quality checks\nnpm run typecheck           # Type validation\n```\n\n### macOS App Development\n```bash\n# Navigate to macOS app\ncd apps/mac\n\n# Build and run\nxcodebuild -project Poltergeist.xcodeproj -scheme Poltergeist build\nopen Poltergeist.xcodeproj\n\n# Code quality\n./scripts/lint.sh           # SwiftLint checks\n./scripts/format.sh         # swift-format fixes\n```\n\n### CI/CD Pipeline\n\nOur comprehensive CI/CD pipeline ensures code quality across both platforms:\n\n- **Multi-platform testing**: Node.js 20/22 on Ubuntu, macOS, and Windows\n- **Swift 6 validation**: Strict concurrency checking and modern Swift practices\n- **Code quality**: SwiftLint, swift-format, Biome, and TypeScript checks\n- **Automated releases**: Dual-platform releases with both CLI (.tgz) and macOS app (.dmg/.zip)\n- **Test coverage**: Comprehensive coverage reporting with Codecov\n\n\u003cdetails\u003e\n\u003csummary\u003eProject structure and contributing guidelines\u003c/summary\u003e\n\n### Project Structure\n```\npoltergeist/\n├── src/\n│   ├── builders/           # Target-specific builders\n│   ├── cli.ts             # Command line interface  \n│   ├── poltergeist.ts     # Core application logic\n│   ├── priority-engine.ts # Intelligent priority scoring\n│   ├── build-queue.ts     # Smart build queue management\n│   ├── state.ts           # State management system\n│   └── watchman.ts        # Watchman file watching\n├── test/                  # Vitest test files\n└── dist/                  # Compiled JavaScript output\n```\n\n### Contributing\nContributions welcome! Requirements:\n1. Tests pass: `npm test`\n2. Code formatted: `npm run format` \n3. Linting passes: `npm run lint`\n4. Types check: `npm run typecheck`\n\n### Development Philosophy\n- **No backwards compatibility**: Clean breaks over legacy support\n- **Type safety first**: Compile-time safety over runtime flexibility\n- **Performance over features**: Optimize for large projects\n- **Simple over complex**: Clean APIs over extensive configuration\n\n\u003c/details\u003e\n\n## Changelog\n\nFor detailed information about releases, bug fixes, and improvements, see [CHANGELOG.md](CHANGELOG.md).\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n## Author\n\nCreated and maintained by [Peter Steinberger](https://github.com/steipete)\n\n## Acknowledgments\n\nBuilt with these excellent open source projects:\n\n### Core Dependencies\n- **[Watchman](https://facebook.github.io/watchman/)** - Facebook's efficient file watching service\n- **[Commander.js](https://github.com/tj/commander.js)** - Complete CLI framework\n- **[Zod](https://zod.dev/)** - TypeScript-first schema validation with static type inference\n- **[Winston](https://github.com/winstonjs/winston)** - Universal logging library with support for multiple transports\n\n### Build \u0026 Development\n- **[TypeScript](https://www.typescriptlang.org/)** - JavaScript with syntax for types\n- **[Vitest](https://vitest.dev/)** - Blazing fast unit test framework\n- **[Biome](https://biomejs.dev/)** - Fast formatter and linter for JavaScript, TypeScript, and more\n- **[TSX](https://github.com/privatenumber/tsx)** - TypeScript execute and REPL for Node.js\n- **[TypeDoc](https://typedoc.org/)** - Documentation generator for TypeScript projects\n\n### User Experience\n- **[Chalk](https://github.com/chalk/chalk)** - Terminal string styling done right\n- **[Ora](https://github.com/sindresorhus/ora)** - Elegant terminal spinners\n- **[Node Notifier](https://github.com/mikaelbr/node-notifier)** - Cross-platform native notifications\n\n### Utilities\n- **[Picomatch](https://github.com/micromatch/picomatch)** - Blazing fast and accurate glob matcher\n- **[Write File Atomic](https://github.com/npm/write-file-atomic)** - Write files atomically and reliably\n- **[fb-watchman](https://github.com/facebook/watchman)** - JavaScript client for Facebook's Watchman service\n\n### Special Thanks\n- All contributors and users who have helped shape Poltergeist\n- The open source community for creating these amazing tools\n\n---\n\n\u003cdiv align=\"center\"\u003e\n  \u003cstrong\u003eKeep your builds fresh with Poltergeist\u003c/strong\u003e\n\u003c/div\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsteipete%2Fpoltergeist","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsteipete%2Fpoltergeist","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsteipete%2Fpoltergeist/lists"}