RepoPilotOpen in app →

teampoltergeist/poltergeist

A PhantomJS driver for Capybara

Healthy

Healthy across all four use cases

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • 14 active contributors
  • MIT licensed
  • CI configured
Show 3 more →
  • Tests present
  • Stale — last commit 7y ago
  • Concentrated ownership — top contributor handles 79% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/teampoltergeist/poltergeist)](https://repopilot.app/r/teampoltergeist/poltergeist)

Paste at the top of your README.md — renders inline like a shields.io badge.

Preview social card (1200×630)

This card auto-renders when someone shares https://repopilot.app/r/teampoltergeist/poltergeist on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: teampoltergeist/poltergeist

Generated by RepoPilot · 2026-05-10 · Source

🤖Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/teampoltergeist/poltergeist shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

🎯Verdict

GO — Healthy across all four use cases

  • 14 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Stale — last commit 7y ago
  • ⚠ Concentrated ownership — top contributor handles 79% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live teampoltergeist/poltergeist repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/teampoltergeist/poltergeist.

What it runs against: a local clone of teampoltergeist/poltergeist — the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in teampoltergeist/poltergeist | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 2446 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>teampoltergeist/poltergeist</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of teampoltergeist/poltergeist. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/teampoltergeist/poltergeist.git
#   cd poltergeist
#
# Then paste this script. Every check is read-only — no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of teampoltergeist/poltergeist and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "teampoltergeist/poltergeist(\\.git)?\\b" \\
  && ok "origin remote is teampoltergeist/poltergeist" \\
  || miss "origin remote is not teampoltergeist/poltergeist (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "lib/capybara/poltergeist.rb" \\
  && ok "lib/capybara/poltergeist.rb" \\
  || miss "missing critical file: lib/capybara/poltergeist.rb"
test -f "lib/capybara/poltergeist/driver.rb" \\
  && ok "lib/capybara/poltergeist/driver.rb" \\
  || miss "missing critical file: lib/capybara/poltergeist/driver.rb"
test -f "lib/capybara/poltergeist/browser.rb" \\
  && ok "lib/capybara/poltergeist/browser.rb" \\
  || miss "missing critical file: lib/capybara/poltergeist/browser.rb"
test -f "lib/capybara/poltergeist/client/main.coffee" \\
  && ok "lib/capybara/poltergeist/client/main.coffee" \\
  || miss "missing critical file: lib/capybara/poltergeist/client/main.coffee"
test -f "lib/capybara/poltergeist/server.rb" \\
  && ok "lib/capybara/poltergeist/server.rb" \\
  || miss "missing critical file: lib/capybara/poltergeist/server.rb"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 2446 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~2416d)"
else
  miss "last commit was $days_since_last days ago — artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) — safe to trust"
else
  echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/teampoltergeist/poltergeist"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

Poltergeist is a Capybara WebDriver for PhantomJS that enables headless browser automation in Ruby test suites. It allows developers to run Capybara integration tests against a headless WebKit engine without needing a display server, using a WebSocket bridge between Ruby (client) and PhantomJS (server) to execute DOM interactions and assertions. Client-server architecture: lib/capybara/poltergeist/driver.rb is the Capybara driver entry point; lib/capybara/poltergeist/browser.rb and lib/capybara/poltergeist/client.rb manage the Ruby side, while lib/capybara/poltergeist/client/*.coffee (compiled to compiled/*.js) runs inside PhantomJS. WebSocket server (web_socket_server.rb) bridges Ruby-to-PhantomJS communication; spec tests in spec/integration/ validate driver behavior.

👥Who it's for

Rails and Ruby developers writing Capybara integration tests who need to run JavaScript-heavy acceptance tests in CI/CD environments. Specifically QA engineers and developers maintaining test suites that require browser automation without display overhead.

🌱Maturity & risk

Production-ready but historically maintained. The repo shows mature patterns (v1.18.1 released, Travis CI configured, comprehensive gemfile variants for Capybara 2+), but the lack of recent commits and PhantomJS itself being deprecated (in favor of headless Chrome/Puppeteer) means this project is in legacy-maintenance mode. README explicitly notes users should consider Cuprite for headless Chrome instead.

Moderate risk: PhantomJS is discontinued and unmaintained upstream, creating long-term sustainability concerns. The codebase depends on a specific PhantomJS binary version (≥1.8.1) that may not compile on modern systems. Single-maintainer (@teampoltergeist org) with no visible recent commits suggests limited active development; however, the stable API and test coverage mitigate immediate breakage.

Active areas of work

No visible active development. The README points users to Cuprite as the modern alternative. The codebase appears to be in maintenance-only mode with no recent commits or merged PRs evident from the file structure.

🚀Get running

git clone https://github.com/teampoltergeist/poltergeist.git && cd poltergeist && bundle install && phantomjs --version (to verify PhantomJS ≥1.8.1 is installed). Then run tests with bundle exec rspec.

Daily commands: bundle exec rspec spec/integration/ to run test suite. The driver is invoked in user code via Capybara.javascript_driver = :poltergeist in test setup; no separate daemon needed (PhantomJS spawned per session).

🗺️Map of the codebase

  • lib/capybara/poltergeist.rb — Main entry point that registers Poltergeist as a Capybara driver; all contributors must understand this initialization pattern
  • lib/capybara/poltergeist/driver.rb — Core driver implementation implementing Capybara's driver interface; central to understanding how Poltergeist interacts with Capybara
  • lib/capybara/poltergeist/browser.rb — Browser abstraction layer managing PhantomJS process lifecycle and command execution; load-bearing for all browser interactions
  • lib/capybara/poltergeist/client/main.coffee — PhantomJS-side JavaScript that runs in the headless browser; defines core communication protocol with Ruby driver
  • lib/capybara/poltergeist/server.rb — WebSocket server managing bidirectional communication between Ruby driver and PhantomJS; critical for request/response flow
  • lib/capybara/poltergeist/command.rb — Command execution abstraction wrapping all communication with PhantomJS; essential for understanding async patterns
  • lib/capybara/poltergeist/node.rb — DOM node wrapper providing Capybara interface for element interaction; fundamental to how tests interact with page elements

🛠️How to make changes

Add a new Capybara session action (e.g., visit, click, fill_in)

  1. Add handler method to lib/capybara/poltergeist/driver.rb implementing the action logic (e.g., return result of browser command) (lib/capybara/poltergeist/driver.rb)
  2. Add corresponding command handler in lib/capybara/poltergeist/client/cmd.coffee that executes the action in PhantomJS context (lib/capybara/poltergeist/client/cmd.coffee)
  3. Compile CoffeeScript to JavaScript using existing build process (lib/capybara/poltergeist/client/compiled/cmd.js)
  4. Add integration test in spec/integration/session_spec.rb verifying the action works end-to-end (spec/integration/session_spec.rb)

Add a new browser capability or feature flag

  1. Define capability constant and initialization in lib/capybara/poltergeist/browser.rb (lib/capybara/poltergeist/browser.rb)
  2. Implement feature logic in lib/capybara/poltergeist/client/web_page.coffee or lib/capybara/poltergeist/client/main.coffee (lib/capybara/poltergeist/client/web_page.coffee)
  3. Recompile and test with spec/unit/browser_spec.rb (spec/unit/browser_spec.rb)

Add custom error handling or exception type

  1. Define new exception class inheriting from Poltergeist::Error in lib/capybara/poltergeist/errors.rb (lib/capybara/poltergeist/errors.rb)
  2. Raise the exception in appropriate handler (driver.rb, browser.rb, or client command handlers) (lib/capybara/poltergeist/driver.rb)
  3. Add test case to spec/unit/driver_spec.rb or spec/integration/driver_spec.rb (spec/unit/driver_spec.rb)

Modify network traffic inspection or filtering

  1. Update network event handlers in lib/capybara/poltergeist/client/web_page.coffee to capture/filter traffic (lib/capybara/poltergeist/client/web_page.coffee)
  2. Adjust request/response objects in lib/capybara/poltergeist/network_traffic/request.rb and lib/capybara/poltergeist/network_traffic/response.rb as needed (lib/capybara/poltergeist/network_traffic/request.rb)
  3. Test with spec/integration/session_spec.rb network traffic tests (spec/integration/session_spec.rb)

🔧Why these technologies

  • PhantomJS headless browser — Provides scriptable, headless WebKit engine for running browser tests without GUI; allows parallel test execution
  • CoffeeScript for client code — Compiles to JavaScript to run in PhantomJS context; cleaner syntax than raw JS while targeting legacy PhantomJS environment
  • WebSocket bidirectional communication — Enables efficient two-way communication between Ruby driver and PhantomJS process; avoids polling overhead
  • Capybara driver interface (Ruby gem) — Plugs into Capybara's test abstraction layer; allows tests to switch between different browser drivers with minimal code changes

⚖️Trade-offs already made

  • Reliance on PhantomJS (now deprecated)

    • Why: PhantomJS was mature, scriptable, and lightweight when Poltergeist was created
    • Consequence: Project is now in maintenance mode; modern alternative is Cuprite using headless Chrome/Chromium via CDP protocol
  • Synchronous Ruby driver API wrapping async PhantomJS commands

    • Why: Capybara and test suites expect synchronous calls; easier for test authors to reason about
    • Consequence: Ruby driver must block waiting for command responses; potential timeout complexity when JS takes long
  • Full page DOM inspection via JavaScript execution

    • Why: Provides access to computed styles, event handlers, and JavaScript runtime state that HTTP APIs cannot
    • Consequence: Every element inspection or interaction crosses process boundary; potential performance bottleneck for large pages
  • JSON serialization for request/response payloads

    • Why: Human-readable, widely supported, debuggable
    • Consequence: Slower than binary protocols; limits ability to serialize complex objects or circular references

🚫Non-goals (don't propose these)

  • Not a real-time database or data persistence layer
  • Does not handle authentication or authorization (delegates to Capybara/test setup)
  • Not a JavaScript unit test framework (targets Capybara integration tests only)
  • Does not support modern headless Chrome/Chromium (PhantomJS-only; see Cuprite for Chrome support)

🪤Traps & gotchas

PhantomJS binary requirement: tests and driver assume phantomjs is in PATH; CI must have PhantomJS ≥1.8.1 installed separately (not bundled). CoffeeScript compilation: modifying any .coffee files in lib/capybara/poltergeist/client/ requires running rake to recompile to compiled/ JavaScript; uncommitted compiled files will cause test failures. WebSocket server binding: driver auto-spawns a WebSocket server; port conflicts in CI can cause flaky tests. Transactional tests: README warns that Poltergeist runs app in separate thread, breaking transactional_fixtures in some test setups.

🏗️Architecture

💡Concepts to learn

  • WebSocket bidirectional communication — Poltergeist's core mechanism for real-time command/response between Ruby driver and PhantomJS; understanding WebSocket framing and message serialization is essential to debug protocol issues
  • Headless browser automation — The fundamental pattern this library enables—driving a browser without a display server, critical for CI/CD acceptance testing
  • CoffeeScript compilation to JavaScript — Poltergeist's client code is written in CoffeeScript in lib/capybara/poltergeist/client/ and compiled to JavaScript; contributors must understand the compilation step and .coffee syntax
  • WebKit DOM API and page evaluation — PhantomJS exposes WebKit's page object with methods like evaluateJavaScript() and injectJs(); core to how Poltergeist inspects and manipulates the DOM
  • Capybara driver interface — Poltergeist implements Capybara's driver spec (session, find, click, fill_in, etc.); understanding this contract is essential for adding new capabilities or fixing driver behavior
  • Process lifecycle management and timeout handling — The driver spawns PhantomJS as a child process and must handle timeouts, cleanup, and graceful shutdown; browser.rb demonstrates these patterns
  • Network traffic interception — Poltergeist can capture HTTP requests/responses and errors via PhantomJS's onResourceRequested and onResourceReceived callbacks; useful for debugging and testing external API calls
  • machinio/cuprite — Direct successor to Poltergeist; provides the same Capybara integration but uses Chrome DevTools Protocol instead of PhantomJS, recommended for new projects
  • jnicklas/capybara — Core dependency; Poltergeist is a driver plugin for Capybara's acceptance testing framework
  • ariya/phantomjs — Upstream PhantomJS project (now archived); Poltergeist bridges to this headless browser engine
  • SeleniumHQ/selenium — Alternative browser automation library; Capybara supports multiple drivers (Selenium, Rack::Test) alongside Poltergeist

🪄PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add comprehensive unit tests for lib/capybara/poltergeist/network_traffic module

The network_traffic directory contains three classes (Request, Response, Error) but there are no dedicated unit tests visible in spec/. Network traffic is a critical feature for testing HTTP interactions, and adding focused unit tests would improve reliability and serve as documentation for the module's API. This is especially important given the PhantomJS deprecation context where maintainers need high confidence in core features.

  • [ ] Create spec/unit/network_traffic/ directory
  • [ ] Add spec/unit/network_traffic/request_spec.rb to test Request class initialization, attribute access, and response association
  • [ ] Add spec/unit/network_traffic/response_spec.rb to test Response class including status codes, headers parsing, and content
  • [ ] Add spec/unit/network_traffic/error_spec.rb to test Error class initialization and error message formatting
  • [ ] Run tests against existing integration tests in spec/integration/ to ensure compatibility

Add integration tests for CoffeeScript client layer compilation and communication

The lib/capybara/poltergeist/client/ directory contains CoffeeScript source files (.coffee) that compile to JavaScript in the compiled/ subdirectory, but there's no visible test coverage for the compilation step or for verifying the compiled output matches the source. This is critical infrastructure that could break silently. Adding tests would ensure the client-server communication layer remains reliable.

  • [ ] Create spec/unit/client/ directory structure
  • [ ] Add a test that verifies each .coffee file in lib/capybara/poltergeist/client/ compiles to corresponding .js in compiled/
  • [ ] Add spec/unit/client/compilation_spec.rb to check that CoffeeScript compilation produces valid JavaScript
  • [ ] Add basic validation tests for compiled/main.js initialization without PhantomJS (mocking the connection)
  • [ ] Document the compilation process in CONTRIBUTING.md with a section on running client tests

Add GitHub Actions workflow for testing against multiple Ruby and Capybara versions

The repo has .travis.yml and gemfiles/ for multiple Capybara versions (Gemfile.capy2, Gemfile.capybara_master), but no modern GitHub Actions workflow. Since Travis CI has transitioned to paid models, adding a GitHub Actions workflow would improve CI accessibility and provide faster feedback. The gemfiles directory suggests the project already tests multiple Capybara versions—this should be formalized in Actions.

  • [ ] Create .github/workflows/test.yml with matrix strategy for Ruby versions (2.6+) and Capybara versions (capy2, master branch)
  • [ ] Configure the workflow to run bundle exec rspec using each gemfile in gemfiles/
  • [ ] Add job to verify CoffeeScript compilation (./lib/capybara/poltergeist/client/*.coffee compiles correctly)
  • [ ] Add RuboCop linting job referencing .rubocop.yml
  • [ ] Document the CI setup in CONTRIBUTING.md, noting which versions are tested and how to run tests locally

🌿Good first issues

  • Add missing test coverage for lib/capybara/poltergeist/cookie.rb (visible in structure but no corresponding spec found); write specs for cookie get/set/delete operations with domain/expiry handling.
  • Extend spec/integration/driver_spec.rb with test cases for the network_traffic module (request capture, response inspection, error logging); currently files exist under network_traffic/ but integration test coverage is unclear.
  • Add documentation to lib/capybara/poltergeist/inspector.rb explaining the debugging mode and add a guide to README showing how to enable inspector for troubleshooting (currently no README section on this feature).

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 6a27b00 — Update README [ci skip] (route)
  • 54c33e1 — Merge pull request #931 from teampoltergeist/updates (twalpole)
  • 94fad56 — Merge pull request #933 from semaperepelitsa/patch-1 (route)
  • 25044ec — Update Homebrew installation instruction (semaperepelitsa)
  • ed85f0d — Refactor normalize_keys and fix for edge case now tested for in Capybara (twalpole)
  • 5aa5d96 — Add Node#clickable? (twalpole)
  • f8f872b — Ignore test expected to fail (twalpole)
  • fb42c01 — Fix typo (twalpole)
  • 361c979 — No support for fullscreen window (twalpole)
  • 38b1128 — Skip Capybaras download tests because its unsupported in Poltergeist (twalpole)

🔒Security observations

Poltergeist has moderate security concerns primarily centered on its dependency on the unmaintained PhantomJS browser engine, which no longer receives security updates and has known vulnerabilities. Additional risks include custom WebSocket server implementation and potential command injection in browser process handling. The project itself acknowledges the PhantomJS situation in its README by recommending Cuprite as an alternative. For security-sensitive applications, migration away from Poltergeist is strongly recommended. If continued use is necessary, implement strict input validation, keep PhantomJS isolated in containers with minimal privileges, and audit the custom WebSocket and browser communication code thoroughly.

  • High · PhantomJS Dependency - Unmaintained Browser Engine — lib/capybara/poltergeist - Core dependency. Poltergeist relies on PhantomJS, which is no longer actively maintained (last update 2016). PhantomJS has known unpatched security vulnerabilities and no longer receives security updates. This creates significant risk for running untrusted web content or accessing sensitive websites. Fix: Migrate to maintained alternatives such as Cuprite (Chromium-based), Selenium with Chrome/Firefox, or Playwright. The README itself suggests Cuprite as a compatible replacement.
  • High · Missing Dependency Pinning in Gemfile — Gemfile, gemfiles/. The Gemfile structure shows multiple gemfiles (Gemfile.capy2, Gemfile.capybara_master) indicating version flexibility, but without explicit dependency version constraints visible, there's risk of pulling in vulnerable gem versions automatically. Fix: Pin gem versions with specific version numbers or use conservative version constraints. Regularly audit dependencies with 'bundle audit' or similar tools.
  • Medium · Client-Side Code in CoffeeScript - Compilation Risks — lib/capybara/poltergeist/client/ directory. Multiple CoffeeScript files (lib/capybara/poltergeist/client/*.coffee) are compiled to JavaScript. Compilation process and transpiled code may introduce security issues if not properly validated. The compiled JavaScript is committed to version control, which could mask malicious changes. Fix: Regenerate compiled files from source during build process rather than committing pre-compiled assets. Use build tools to ensure integrity of compiled output.
  • Medium · Potential Command Injection via Server/Driver — lib/capybara/poltergeist/browser.rb, lib/capybara/poltergeist/driver.rb, lib/capybara/poltergeist/server.rb. The browser.rb, driver.rb, and server.rb files handle browser process execution. If user input is passed to browser commands or configuration without proper sanitization, command injection attacks are possible. Fix: Review all process spawning code to ensure proper argument escaping. Use array-based process invocation rather than string concatenation. Validate all user-controlled configuration parameters.
  • Medium · WebSocket Server Implementation — lib/capybara/poltergeist/web_socket_server.rb. The custom WebSocket server implementation (lib/capybara/poltergeist/web_socket_server.rb) may have security implications if not properly validating incoming connections and messages. Fix: Audit WebSocket implementation for: origin validation, message size limits, rate limiting, and proper authentication. Consider using established WebSocket libraries rather than custom implementation.
  • Low · Test Fixtures May Expose Attack Patterns — spec/support/views/. Test views directory (spec/support/views/) contains various test cases including js_error.erb, basic_auth.erb, and others. While intended for testing, these patterns could inadvertently document insecure patterns. Fix: Ensure test fixtures are not deployed to production. Add documentation explaining these are test-only and insecure by design.
  • Low · Debug/Inspector Functionality in Production — lib/capybara/poltergeist/inspector.rb. The lib/capybara/poltergeist/inspector.rb file suggests debug/inspection capabilities that should not be exposed in production environments. Fix: Ensure inspector functionality is only enabled during development/testing. Add environment checks and disable by default for production usage.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · teampoltergeist/poltergeist — RepoPilot