RepoPilotOpen in app →

bbc/wraith

Wraith — A responsive screenshot comparison tool

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.

  • Last commit 4mo ago
  • 19 active contributors
  • Distributed ownership (top contributor 48% of recent commits)
Show 4 more →
  • Apache-2.0 licensed
  • CI configured
  • Tests present
  • Slowing — last commit 4mo ago

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/bbc/wraith)](https://repopilot.app/r/bbc/wraith)

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/bbc/wraith on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: bbc/wraith

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/bbc/wraith 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

  • Last commit 4mo ago
  • 19 active contributors
  • Distributed ownership (top contributor 48% of recent commits)
  • Apache-2.0 licensed
  • CI configured
  • Tests present
  • ⚠ Slowing — last commit 4mo ago

<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 bbc/wraith repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/bbc/wraith.

What it runs against: a local clone of bbc/wraith — 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 bbc/wraith | Confirms the artifact applies here, not a fork | | 2 | License is still Apache-2.0 | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | Last commit ≤ 144 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>bbc/wraith</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of bbc/wraith. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/bbc/wraith.git
#   cd wraith
#
# 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 bbc/wraith and re-run."
  exit 2
fi

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

# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
  && ok "license is Apache-2.0" \\
  || miss "license drift — was Apache-2.0 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"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 144 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~114d)"
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/bbc/wraith"
  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

Wraith is a BBC News–developed screenshot comparison tool that captures webpages using headless browsers (PhantomJS, CasperJS, Chrome) at different resolutions or points in time, then uses ImageMagick to diff the images and highlight pixel changes in blue. It automates visual regression testing by generating diff PNGs and a gallery.html report, with configurable pixel-change thresholds for CI integration. Monolithic Ruby gem structure: lib/wraith/ contains the core engine (compare_images.rb, save_images.rb, spider.rb, crop.rb), lib/wraith/cli.rb is the command router, lib/wraith/javascript/ holds headless browser scripts (phantom.js, casper.js), lib/wraith/gallery_template/ holds ERB templates for HTML reports, and spec/ mirrors the lib structure with parallel test files.

👥Who it's for

QA engineers and frontend developers at news organizations or large media sites who need to detect unintended visual changes across responsive breakpoints or deployments without manual pixel-by-pixel review. Users configure YAML files to specify domains, paths, viewport widths, and tolerance thresholds.

🌱Maturity & risk

Archived and no longer maintained (clearly stated in README). The project has a mature structure with Travis CI configured, RuboCop linting, and a full test suite (spec/ directory), but it is frozen—no active development, no issue/PR triage. Suitable only for reference or legacy projects already using it.

High risk for new projects: this is an abandoned repository with no maintainer response to issues or PRs. It depends on aging headless browser APIs (PhantomJS reached EOL in 2018, CasperJS is unmaintained). Newer alternatives like Cypress, Playwright, or Percy handle visual regression more robustly; using Wraith locks you into outdated tooling.

Active areas of work

Nothing. The repository is archived and dormant. The README explicitly states 'This repository is no longer maintained. It remains available for reference, but issues and pull requests are not monitored.' No active branches, milestones, or discussions.

🚀Get running

git clone https://github.com/bbc/wraith.git
cd wraith
bundle install
bundle exec wraith capture configs/test_config--phantom.yaml

(Requires Ruby, Bundler, ImageMagick, and at least one headless browser installed locally.)

Daily commands: Wraith is not a server—it is a CLI tool invoked via wraith capture <config.yaml>, wraith history, wraith latest, wraith compare, wraith multi_capture, or wraith spider. Each command reads a YAML config, executes headless browser scripts, runs ImageMagick diffing, and outputs a gallery.html in the configured output directory.

🗺️Map of the codebase

  • lib/wraith/cli.rb: Entry point for all CLI commands; routes user input (capture, history, spider, compare, multi_capture) to respective handlers
  • lib/wraith/save_images.rb: Orchestrates headless browser script execution and screenshot capture; must integrate with phantom.js, casper.js, and Chrome drivers
  • lib/wraith/compare_images.rb: Core diff logic; wraps ImageMagick commands to compare two PNGs and produce diff output with pixel-change metrics
  • lib/wraith/spider.rb: Crawls target domains when no explicit paths are configured; discovers pages for automated regression testing
  • lib/wraith/gallery.rb: Generates gallery.html and slideshow reports from diff results and metadata; uses ERB templates in lib/wraith/gallery_template/
  • lib/wraith/javascript/phantom.js: PhantomJS script that captures screenshots at specified viewport widths; injected and run in headless browser context
  • lib/wraith/wraith.rb: Main Wraith class; manages configuration loading, file paths, and delegates to sub-modules
  • lib/wraith/validate.rb: Validates YAML config syntax and required parameters before execution; catches configuration errors early

🛠️How to make changes

For screenshot capture logic, edit lib/wraith/save_images.rb and the headless browser drivers in lib/wraith/javascript/. For diff/comparison, modify lib/wraith/compare_images.rb (ImageMagick wrapping). For gallery HTML output, edit lib/wraith/gallery_template/*.erb. For CLI commands, modify lib/wraith/cli.rb. Add specs in spec/ mirroring the file structure (e.g., spec/compare_images_spec.rb tests lib/wraith/compare_images.rb).

🪤Traps & gotchas

PhantomJS (default) is EOL and no longer available for download on modern systems—you must pre-install it or use CasperJS/Chrome instead. Config YAML paths must match exactly (case-sensitive, forward slashes). ImageMagick must be installed and on PATH; compare_images.rb shells out to compare and convert commands—missing binaries fail silently. Headless browser drivers (phantom.js, casper.js) are injected as inline JavaScript; if your site has strict CSP or requires authentication, screenshot capture will fail with cryptic errors. The spider feature requires write access to the file system for temp files. No environment variables are used for configuration—all settings come from YAML.

💡Concepts to learn

  • Headless browser automation — Wraith's core capability depends on scripting PhantomJS/CasperJS/Chrome to navigate pages and capture screenshots without a GUI; understanding how save_images.rb injects and executes JavaScript in these browsers is critical to extending capture logic
  • Image diff algorithms (ImageMagick compare) — compare_images.rb shells out to ImageMagick's compare command to quantify pixel differences; understanding the fuzz threshold, metric types (AE, RMSE, PAE), and diff output format is essential to tuning sensitivity and interpreting results
  • Visual regression testing — Wraith automates screenshot-based regression detection across viewports and deployments; this pattern (capture baseline, compare new, highlight deltas) is foundational to responsive web testing and CI/CD validation pipelines
  • Responsive design breakpoints — Wraith's core workflow involves capturing the same pages at multiple viewport widths (defined in config YAML); understanding how CSS media queries and layout shifts at breakpoints affect diff output is necessary to configure meaningful test suites
  • ERB templating (Ruby) — gallery.rb uses ERB to generate gallery.html reports from diff metadata; modifying report appearance requires editing lib/wraith/gallery_template/*.erb files and understanding Ruby string interpolation and loops in templates
  • YAML configuration files — All Wraith behavior (domains, paths, viewports, browser drivers, thresholds) is defined in YAML config files loaded by wraith.rb; YAML syntax errors or missing keys are common failure points, and understanding the schema is required to onboard new test suites
  • Web crawling and spidering — spider.rb discovers pages on a target domain when no explicit path list is provided; understanding link extraction, robots.txt parsing, and recursive traversal helps configure automated multi-page regression testing without manual path enumeration
  • percy/percy-cli — Modern replacement for Wraith; Percy is a SaaS visual regression platform with CLI integration, handling browser compatibility and baseline management without DevOps overhead
  • BackstopJS/backstopjs — Open-source visual regression testing tool using Puppeteer/Chrome; more actively maintained and easier to integrate with modern CI/CD than Wraith's aging headless drivers
  • pixelmatch/pixelmatch — Lightweight Node.js image diffing library (alternative to ImageMagick backend); if Wraith were modernized, this could replace the shell-based compare_images.rb logic
  • puppeteer/puppeteer — Modern headless Chrome/Chromium library that supersedes PhantomJS/CasperJS; Wraith's screenshot capture could be rewritten to use Puppeteer instead of aging browser drivers
  • bbc/gel — BBC's own open-source component library (Global Experience Language); many BBC projects use both Wraith for regression testing and GEL for responsive UI components

🪄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/wraith/compare_images.rb

The compare_images.rb module is core to Wraith's functionality (image diffing), but there are no dedicated tests for it in spec/. Given the test infrastructure exists (spec/base/ has test images, spec/*_spec.rb files show the testing pattern), this is a high-impact gap. Testing image comparison logic with the existing test assets (spec/base/global.png, spec/base/path.png, assets/invalid1.jpg, assets/invalid2.jpg) would catch regressions and improve maintainability.

  • [ ] Create spec/compare_images_spec.rb following the pattern of existing spec files
  • [ ] Add test cases for valid image comparison using spec/base/global.png and spec/base/path.png
  • [ ] Add test cases for invalid/corrupted images using assets/invalid1.jpg and assets/invalid2.jpg
  • [ ] Test edge cases: missing files, zero-size images, dimension mismatches
  • [ ] Verify tests run with existing test infrastructure (likely RSpec based on file names)

Add missing unit tests for lib/wraith/spider.rb

The spider.rb module handles web crawling for the tool, but there's a config test (test_config--spider.yaml exists) yet no corresponding spec/spider_spec.rb. This is a critical gap for a feature with dedicated configuration support. The spec/ directory shows the testing pattern is established, making this a straightforward high-value addition.

  • [ ] Create spec/spider_spec.rb with proper test structure
  • [ ] Use spec/configs/test_config--spider.yaml to test spider initialization and configuration parsing
  • [ ] Test URL discovery and filtering logic with mock URLs
  • [ ] Test depth limiting and domain constraint features
  • [ ] Add tests for common spider failure modes (timeout, invalid domains, etc.)

Add GitHub Actions workflow to replace deprecated Travis CI (.travis.yml)

The repo still uses .travis.yml for CI (shown in file structure), but Travis CI has deprecated and is sunsetting free tier support. The README shows a Travis build badge, and the repository includes Ruby version management (.ruby-version, .gemset, Gemfile), making a GitHub Actions migration straightforward. This unblocks future contributors and ensures the build badge works.

  • [ ] Create .github/workflows/test.yml with Ruby/Bundler setup matching .ruby-version
  • [ ] Configure the workflow to run existing test suite (Rakefile and spec/ structure suggest rake test or rspec)
  • [ ] Test across multiple Ruby versions specified in .ruby-version
  • [ ] Include linting with .rubocop.yml configuration already present
  • [ ] Update README.md to replace Travis CI badge with GitHub Actions badge

🌿Good first issues

  • Write integration tests for lib/wraith/crop.rb; currently no spec/crop_spec.rb exists, leaving image cropping logic untested. Add test coverage for edge cases like zero-width crops and rotated images.
  • Add documentation examples for CasperJS selector targeting (mentioned in README but no config example in spec/configs/test_config--casper.yaml); users struggle to find syntax for DOM element screenshot scoping.
  • Refactor lib/wraith/helpers/logger.rb to support structured logging (JSON output); currently only prints to stdout, making CI log parsing and error aggregation difficult for multi_capture runs.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • 93e2eee — chore: adding archived noe (nicholasgriffintn)
  • 4f6eb0b — Update version number for release (Simon Taylor)
  • f4859e5 — Merge pull request #578 from BBC-News/chromification (bigmartyn)
  • bf07cfd — Change 'timeout_ms' to 'settle' (how long the browser should wait for the dust to settle). (bigmartyn)
  • c9730e2 — Fix typo. (bigmartyn)
  • 51f72ea — Address Jodi's comments. (bigmartyn)
  • b6a09f7 — Improve ability to build Wraith as a Gem. (bigmartyn)
  • 601113c — Update rspec tests and adapt for chrome-related changes. (bigmartyn)
  • 546c713 — Merge branch 'master' into chromification (bigmartyn)
  • 0fcd526 — Merge pull request #412 from envato/save_image_threads_config (bigmartyn)

🔒Security observations

  • Critical · Outdated Ruby Version with Known Vulnerabilities — Dockerfile (line 1: FROM ruby:2.1.2). The Dockerfile specifies Ruby 2.1.2, released in 2013, which is extremely outdated and contains numerous known security vulnerabilities. Ruby 2.1 reached end-of-life in December 2014. Running this version exposes the application to CVEs that have been patched in newer versions. Fix: Update to a supported Ruby version (3.1+ or 3.2+). Ruby 2.1.2 is no longer maintained and should never be used in production.
  • Critical · Vulnerable PhantomJS Version — Dockerfile (line 12: npm install -g phantomjs@2.1.7). PhantomJS 2.1.7 is no longer maintained (project abandoned in 2018) and contains unpatched security vulnerabilities. PhantomJS has known vulnerabilities in JavaScript execution and rendering that could be exploited. Fix: Migrate to maintained alternatives such as Puppeteer, Playwright, or Chrome/Chromium headless mode. If PhantomJS must be used, switch to a maintained fork or upgrade to the latest available version with security patches.
  • Critical · Vulnerable CasperJS Version — Dockerfile (line 12: npm install -g casperjs@1.1.1). CasperJS 1.1.1 is outdated and no longer actively maintained. The project has known vulnerabilities and lacks security updates. Using deprecated testing/automation frameworks increases attack surface. Fix: Consider migrating to modern alternatives like Puppeteer or Playwright. If continued use is necessary, evaluate security implications and implement additional security controls.
  • High · Insecure APT Repository Configuration — Dockerfile (lines 17-19). The Dockerfile uses plain HTTP (not HTTPS) for Debian repository sources and appends to /etc/apt/sources.list without verification. Additionally, contrib and non-free repos are added, increasing the attack surface. Fix: Use HTTPS for all package repository URLs. Verify GPG signatures of packages. Use only main/security repositories unless strictly necessary. Pin specific versions of packages.
  • High · Missing Security Updates in Base Image — Dockerfile (general - missing apt-get upgrade step). The Dockerfile does not run security updates after initial package installation. Running apt-get update && apt-get upgrade -y before final image creation is critical for patching known vulnerabilities. Fix: Add RUN apt-get update && apt-get upgrade -y before finalizing the Docker image to ensure all security patches are applied.
  • High · Repository Marked as Unmaintained — README.md (notice at top). The README clearly states 'This repository is no longer maintained.' This project is no longer receiving security updates, bug fixes, or vulnerability patches. Dependencies will accumulate unpatched CVEs over time. Fix: Consider using maintained alternatives for screenshot comparison testing. If using this tool, implement additional security controls and regularly audit dependencies for CVEs.
  • High · Unnecessary npm Global Install — Dockerfile (line 11: RUN npm install npm). The Dockerfile runs npm install npm globally, which is unusual and unnecessary. This could potentially introduce supply chain risks and makes reproducibility harder. Fix: Remove this line. npm is already included with Node.js. If a specific npm version is required, pin it explicitly in package.json or use npm version constraints.
  • Medium · Missing HEALTHCHECK in Dockerfile — Dockerfile (general - missing HEALTHCHECK instruction). The Dockerfile does not define a HEALTHCHECK instruction, making it difficult to detect if the container is in a healthy state. This could allow unhealthy containers to remain running. Fix: Add a HEALTHCHECK instruction to verify container health, or document requirements for external health monitoring.
  • Medium · No Non-Root User Defined — Dockerfile (general - no USER instruction). The Dockerfile does not create or specify a non-root user. Applications running as root have elevated privileges and pose a greater security risk if compromised. Fix: Create a dedicated non-root user and use

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 · bbc/wraith — RepoPilot