npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@electriccitizen/bolt

v0.26.0

Published

CLI tool for Drupal 11+ site testing and operations

Readme

Bolt

CLI tool for automated Drupal 11+ site testing, updates, and PR creation. Built by Electric Citizen.

Install once per site ("Bolt Certified"), pull updates via npm without re-initializing.

Principles

These guide every design decision in Bolt:

  • Non-invasive. You can remove Bolt from any project with no consequence. Bolt doesn't modify your site's code, config, or database beyond its own tracked test content (which it cleans up). Uninstalling the module and removing the Composer entry is a clean exit.
  • Transparent. Bolt tells you what it's doing at every step. Progress output, clear error messages, and no hidden side effects. If Bolt changes something, it says so.
  • Careful. When a destructive, ambiguous, or unexpected situation arises, Bolt warns you and asks before proceeding. It won't overwrite your database, force-push your code, or modify files outside its scope without explicit confirmation.
  • Idempotent. Every command is safe to re-run. bolt init skips steps already done. bolt suppress regenerates cleanly. bolt test leaves the site in the state it found it.
  • Automation-friendly. Predictable exit codes (0/1/2), structured output formats (JSON, markdown), no interactive prompts in test/CI paths. Humans and scripts get the same reliability.
  • Site-agnostic. Bolt adapts to what it finds. It reads your site's structure and tests accordingly — no hardcoded content types, no assumptions about your setup. Works on any Drupal 11+ site.

Requirements

  • Node.js 20+
  • DDEV
  • A Drupal 11+ site running in DDEV

Installation

# npm global install (recommended)
npm install -g @electriccitizen/bolt
npx playwright install chromium

# Verify
bolt --version
bolt doctor

Development install (for contributors):

git clone [email protected]:electriccitizen/bolt.git ~/projects/bolt
cd ~/projects/bolt
./scripts/setup.sh

Quick Start

# From your Drupal project directory (on main branch):
bolt init                     # installs module, creates config (run on main!)
bolt doctor                   # verify environment + coverage report
bolt test                     # full test suite

# Capture known issues as baseline
bolt suppress                 # creates .boltrc.yml
bolt test                     # now only NEW regressions cause failures

# Check site status and available updates
bolt status                   # git state, updates, AI risk assessment

# Before running updates, sync local environment
bolt refresh --db             # pull latest code + database
bolt update --dry-run --all   # preview updates with risk assessment
bolt update --all             # apply updates (each tested + rolled back on failure)
bolt pr --all                 # create PRs for review

Commands

bolt test

Run tests against a Drupal site. Auto-discovers what to test based on site structure.

bolt test [options]
  --url <url>             Site URL (auto-detected from DDEV if omitted)
  --mode <mode>           full | read-only | admin-only (default: full)
  --plugins <list>        Comma-separated plugin names to run
  --output <format>       text | json | markdown (default: text, auto-json when piped)
  --report <path>         Write report to file
  --exit-code             Non-zero exit on failure (for CI)
  --fail-on <severity>    Threshold: critical | major | minor (default: major)
  --headed                Show browser window
  --screenshots <dir>     Save failure screenshots
  --vr-baseline <dir>     Visual regression baseline directory
  --vr-threshold <n>      VR diff threshold percentage (default: 0.1)
  --content-types <list>  Limit to specific content types

Exit codes: 0 = pass, 1 = failure at or above threshold, 2 = error.

Execution modes:

  • full — generate test content, authenticate, run all plugins, cleanup
  • read-only — no auth, no content changes, only anonymous-safe plugins
  • admin-only — authenticate but don't generate content

Auto-JSON: When stdout is piped (non-TTY), bolt outputs JSON automatically.

Examples:

bolt test --screenshots=./screenshots            # full suite with failure screenshots
bolt test --mode=read-only                       # anonymous-only tests
bolt test --plugins=accessibility                # single plugin
bolt test --content-types=page,blog              # specific content types
bolt test --exit-code --fail-on=major            # CI mode
bolt test --output=markdown --report=report.md   # markdown report for a PR

bolt suppress

Capture current test failures as a suppression baseline. Creates .boltrc.yml.

bolt suppress [options]
  --url <url>             Site URL (auto-detected from DDEV)
  --dry-run               Preview without writing file
  --mode <mode>           Execution mode (default: full)

Suppressed results appear in output but don't affect exit codes. Only new regressions cause failures. Safe to re-run — always captures the full current state.

bolt refresh

Sync local environment to match production before running updates.

bolt refresh [options]
  --db                Pull fresh database (prompted if omitted)
  --skip-db           Skip database pull entirely
  --source <env>      Database source environment (default: live)
  --yes               Skip confirmation prompts
  --branch <name>     Base branch to checkout (default: main)

What it does:

  1. Checks for uncommitted changes (warns, prompts to continue)
  2. Checks out base branch and pulls latest
  3. Starts DDEV if not running
  4. Runs composer install (sync to lockfile)
  5. Optionally pulls database from hosting provider
  6. Runs drush cr, drush updb, drush cim, drush cr

Each step logs its duration. Exits early on failure.

Examples:

bolt refresh --db                    # full refresh with database
bolt refresh --skip-db               # code-only refresh
bolt refresh --db --yes              # non-interactive (for scripting)
bolt refresh --branch=develop --db   # refresh from a different branch

bolt update

Run Drupal module/core updates with baseline testing, regression detection, and a single commit on a dated feature branch.

Two ways to run it:

Interactive (Claude Code, recommended): Invoke /bolt:update — Claude orchestrates the flow turn-by-turn via primitive subcommands (below), pausing for your input on risky judgment calls.

Non-interactive (terminal or CI): Run bolt update directly — does the same flow end-to-end and reports at the end.

bolt update [options]
  --module <name>       Update a specific module (Composer package name)
  --all                 Update all outdated packages
  --security-only       Only security updates
  --dry-run             Show what would be updated without doing it
  --skip-refresh        Skip the pre-update refresh step
  --skip-test           Skip the baseline test
  --no-ai               Disable AI reasoning (use scripted fallback)
  --yes                 Skip confirmation prompts
  --on-main             Allow running on main/master (not recommended)
  --conservative        Hold back every major-version jump even when AI
                        has read release notes and deemed the update safe.
                        Restores the pre-v0.16 pattern-match behavior for
                        a single run.
  --strict              Block on any dirty state including untracked
                        files. Default behavior (since v0.18) is to block
                        only on modified tracked files and preserve
                        untracked files across rollback.

What it does:

  1. Pre-flight — refresh (unless --skip-refresh), verify vendor/ is in sync with composer.lock, run baseline test + capture VR baselines
  2. Plan — list outdated packages, security advisories, patched packages; present with an AI risk assessment
  3. Batch applycomposer update across the approved packages, run drush updb/cr/cex, run regression tests (with VR comparison)
  4. Commit — single commit on a dated feature branch like drupal-updates-MMDDYYYY
  5. Report — summary of updated + held-back packages, saved to .bolt/logs/update-<ts>.json

Visual regression: Before updates begin, bolt captures screenshots of representative pages. Post-update tests compare against those baselines; any pixel diff flags a failure. VR runs automatically during updates even if skipped in .bolt.yml.

Exit codes: 0 = at least one update succeeded, 1 = all failed, 2 = error.

Primitive subcommands (Claude-facing)

For fine-grained orchestration (used by /bolt:update in Claude Code, or for scripting), each step is its own subcommand that emits JSON on stdout:

bolt update:plan                                # gather plan JSON (read-only); creates a session
bolt update:baseline --session=<id>             # run baseline test, capture VR baselines
bolt update:apply    --session=<id> --packages=<csv>  # composer update + regression tests (no commit)
bolt update:rollback --session=<id>             # discard uncommitted changes
bolt update:commit   --session=<id> [--message="..."] # stage + commit
bolt update:session  list|show <id>|cleanup     # session hygiene

Sessions persist under .bolt/sessions/<id>/ so Claude can drive a multi-turn workflow, pausing between applies to surface failures for triage. See docs/PLAN-MVP.md → MVP-10 for the full design.

Examples:

bolt update --dry-run --all                # see what would be updated
bolt update --module=drupal/token          # update a single module
bolt update --all --security-only          # only security updates
bolt update --all --yes                    # non-interactive, all updates
bolt update --all --skip-refresh           # skip the git pull / composer install step
bolt update --all --conservative           # hold back every major jump (old behavior)
bolt update --strict                       # block on any dirty state including untracked

Untracked files (v0.18+): bolt update no longer blocks on untracked files. Working notes, scratch docs, and other random untracked content in your working tree are captured at session-start and excluded from any rollback's git clean, so they survive a failed update. Modified tracked files still block (rollback's git checkout -- . would destroy them). Use --strict to restore the pre-v0.18 block-on-any-dirty behavior.

Constraint-aware planning (v0.19+): The AI assessment reads the current constraint in composer.json for every outdated package and targets the highest version that composer update can actually resolve. Examples: composer/installers 1.x → 2.x under ^1.9 gets held back with a clear "bump the constraint via composer require in a focused PR" note rather than silently no-opping; drupal/gin 4.x under ^4.0 targets 4.1.3 (the achievable bump) rather than 5.0.12 (the aspirational latest), with a postUpdateCheck noting the ^5.0 upgrade path. No more silent-no-op recommendations in the plan.

Autonomous constraint rewrites (v0.20+): Extends the preflight-remediation agent to handle safe major-version bumps where the only blocker is a composer.json constraint. If the AI reads release notes and determines a major bump is safe for the site (no site-affecting breaking changes, no cascading dep conflicts), it emits a constraint-rewrite preflightAction. The remediation agent edits composer.json, verifies with composer validate + composer install --dry-run, and the normal apply step's composer update picks up the widened constraint — all in one batch commit. Packages like drupal/field_group 3.x → 4.x ("no breaking changes" per notes) now land in a single run instead of requiring a follow-up PR. Cascading conflicts (phpunit under core-dev, etc.) and unverified packages still hold back — no guessing.

Module-enablement awareness + deprecation nuance (v0.21+): The assessment now knows which Drupal modules are installed-but-disabled (via drush pm:list) and treats their updates as low-risk — a disabled module's major bump is a runtime no-op, so the real signal is "consider drush pm:uninstall + composer remove if the feature was abandoned." Separately, when release notes frame a major bump as "no new features" / "internal modernization" and all documented breaks are deprecation removals (not behavioral changes), the assessment prefers a constraint-rewrite preflightAction + targeted smoke-test postUpdateCheck over holdBack, even when the package is consumed by enabled custom modules. Behavioral API changes (response shape, routing, query semantics) still hold back.

Interactive decision prompts (v0.22+): When a clear remediation exists but the right answer depends on user intent, bolt update prompts you mid-run rather than passively surfacing a postUpdateCheck. Two prompt patterns ship today: (1) abandoned-module cleanup — "drupal/quicklink is disabled; uninstall and remove now? (y/N)" — answers yes runs drush pm:uninstall + composer remove inline; (2) aspirational major-version upgrades — when constraint-aware routing picks drupal/gin 4.1.3 over 5.0.12, you get asked "target 4.1.3 (achievable) or 5.0.12 (constraint widen)?" with the security and support tradeoff spelled out. Yes triggers a constraint-rewrite preflightAction through the existing remediation pipeline. --yes takes defaults non-interactively.

AI release-notes analysis (v0.16+): The AI risk step fetches actual release notes (drupal.org, GitHub, CHANGELOG) for non-trivial updates and decides hold-back based on documented, site-affecting breaking changes — not version-number guesses. Defaults to "include in batch"; use --conservative for one-off caution, --no-ai to skip the whole step.

Autonomous preflight + manual spot-checks (v0.17+): The AI assessment also runs scoped diagnostic commands (composer show / why-not, drush pm:list) instead of writing vague warnings for things it can answer itself. When a release-note mandates a small deterministic composer.json edit (example: cweagans/composer-patches 2.0 removing patches-dependencies), a separate remediation agent applies the edit, verifies with composer validate + composer install --dry-run, and includes the change in the same batch commit. On verification failure, the triggering package moves to hold-back and the file is reverted. Manual checks the AI genuinely can't verify (e.g. external-service integrations, release notes behind 404s) are collected in a "Manual checks after update" block printed to stderr, added to the HTML report, and appended to the commit message body.

Typical cost/runtime: ~$0.20–0.50 and ~6–12 min per bolt update AI run, depending on how many release notes get fetched and whether any preflight remediations fire.

bolt pr

Create GitHub PRs from update branches produced by bolt update. Requires GitHub CLI.

bolt pr [options]
  --base <branch>       Base branch for PR (default: main)
  --reviewers <list>    Comma-separated GitHub usernames
  --draft               Create as draft PR
  --all                 Create PRs for all update/* branches
  --no-ai               Disable AI-generated PR descriptions
  --yes                 Skip confirmation prompts

What it does:

  1. Warns if uncommitted changes exist (PRs only include committed state)
  2. Finds update branches (current branch or --all for all update/* branches)
  3. Confirms before pushing (lists branches that will be pushed)
  4. Parses commit messages for update details (package, versions, test results)
  5. Pushes branch to remote
  6. Creates PR with structured body via gh pr create
  7. Checks for existing PRs to avoid duplicates

Examples:

bolt update --module=drupal/token      # batch update on current dated branch
bolt pr --reviewers=broeker            # creates PR for current branch

bolt update --all                      # batch update all outdated on current branch
bolt pr --reviewers=broeker --draft    # draft PR with reviewer pre-filled

bolt analyze

AI-powered ticket analysis — produces an investigation plan from a Jira ticket or description.

bolt analyze [options]
  --ticket <key>          Jira ticket key (e.g. PROJ-123) — pulls via Jira MCP
  --description <text>    Bug description (manual, no Jira needed)
  --url <url>             Site URL (auto-detected from DDEV if omitted)
  --output <format>       text | json | markdown (default: text)
  --report <path>         Write analysis to file

Requires AI — there is no --no-ai fallback for this command, since analysis IS the AI.

Input methods:

  • --ticket PROJ-123 — pulls from Jira via Atlassian MCP (configured per user)
  • --description "..." — manual text input
  • cat ticket.txt | bolt analyze — stdin

Output includes: problem summary, likely root causes (ranked), investigation steps with specific commands, risk assessment, suggested bolt tests to run after fix, and a confidence assessment for whether the issue can be fixed autonomously.

Examples:

bolt analyze --ticket EC-42                          # Jira integration
bolt analyze --description "Media upload broken"     # manual input
bolt analyze --ticket EC-42 --output markdown --report analysis.md

bolt fix

Autonomous ticket resolution — analyze, fix, test, and create a PR.

bolt fix [options]
  --ticket <key>          Jira ticket key (runs analysis internally)
  --description <text>    Bug description (manual, no Jira needed)
  --analysis <path>       Path to saved bolt analyze report (JSON)
  --context <text>        Additional context (answers to questions from analyze)
  --interactive           Launch interactive Claude session (converse instead of autonomous)
  --dry-run               Show planned changes without modifying files
  --skip-test             Skip post-fix test run
  --skip-pr               Skip PR creation
  --branch <name>         Branch name (default: fix/<ticket-key>)
  --yes                   Skip confirmation prompts

Requires AI — no --no-ai fallback.

Two modes:

  • Autonomous (default): Claude runs unattended with full tool access (ddev, drush, file editing). The confidence model from bolt analyze gates entry — if it says "needs info" or "needs human", bolt exits with instructions.
  • Interactive (--interactive): Launches a live Claude session with the ticket analysis, site profile, and Drupal knowledge pre-loaded. You converse with Claude to guide the fix.

Examples:

# Full autonomous flow
bolt fix --ticket EC-42                              # analyze → fix → test → PR

# Provide answers to questions from analyze
bolt fix --ticket EC-42 --context "Chrome only, content_editor role"

# Interactive — converse with Claude
bolt fix --ticket EC-42 --interactive

# Dry run — see what would change
bolt fix --description "footer logo broken" --dry-run

bolt init

Connect bolt to a client site. Run from the site's project root.

bolt init [options]
  --skip-composer         Skip Composer setup
  --skip-module           Skip module enable
  --upgrade               Update bolt-inspect module via Composer
  --yes                   Skip confirmation prompts

What it does:

  1. Warns if NOT on main/master branch (init belongs on main so all branches inherit setup)
  2. Installs electriccitizen/bolt-inspect via Composer (from Packagist)
  3. Enables bolt_inspect Drupal module
  4. Creates .bolt.yml config template
  5. Adds bolt artifacts to .gitignore

Other developers on the same project just run composer install — the module is in composer.json like any other dependency. No additional setup needed beyond installing the bolt CLI globally.

Idempotent — safe to re-run.

bolt status

AI-enhanced site status overview — git state, available updates with risk assessment, recommended update order.

bolt status [options]
  --no-ai                 Disable AI risk assessment
  --output <format>       text | json (default: text)

Example output:

Git:
  ✓ Branch: main
  ✓ Working tree clean

Site:
  ✓ DDEV running: https://acme.ddev.site
  ✓ Drupal 11.1.5, PHP 8.3
  ✓ 6 content types, 25 paragraph bundles

Available updates:
  ✗ 1 security update(s):
      drupal/core: 11.1.3 → 11.1.5 [SECURITY]
  ! 3 other update(s):
      drupal/webform: 6.2-beta8 → 6.2-beta9 (patch)
      drupal/token: 1.14.0 → 1.15.0 (minor/major)
      drupal/paragraphs: 1.17.0 → 1.18.0 (minor/major)

AI assessment:
  ! Risk: medium — Security fix plus minor version bumps
  Recommended update order:
    1. drupal/core — Security fix, apply first
    2. drupal/paragraphs — Dependency of multiple content types
    3. drupal/webform — Patch update, low risk
    4. drupal/token — Leaf dependency, safe last
  Next steps:
    → Run bolt update --security-only first
    → Run bolt test after core update before proceeding

bolt doctor

Validate the environment.

bolt doctor

Checks: bolt version, Node.js, Playwright, DDEV, module status, CLI/module version compatibility, .bolt.yml validity, full test coverage report (content types, fields, paragraph bundles, plugins), and bolt-managed Claude Code skill drift (see below).

bolt skills:sync / bolt skills:status

Bolt distributes Claude Code skills (/bolt:update, /bolt:status, etc.) under .claude/skills/bolt:*. Every bolt command now auto-syncs these from the installed CLI version, so skill content always matches the running bolt — closing the gap where bolt init copied them once and they then silently drifted as bolt evolved.

bolt skills:sync     # Force a sync (auto-runs at the top of every command anyway)
bolt skills:status   # Report drift / user-modified / orphaned skills

Hand-edits under .claude/skills/bolt:* are preserved — bolt detects user modifications via a content-hash registry of every skill version it has shipped. To restore a hand-edited skill to the latest shipped copy: rm -rf .claude/skills/bolt:<name> && bolt skills:sync.

.claude/skills/bolt:* is added to .gitignore by bolt init. On existing projects where these files are tracked, bolt prints a one-time migration hint (git rm -r --cached ...); it does not auto-modify your git state.

Each skill also includes an "activation check" at the top of its body: when invoked from Claude Code, the skill verifies its own boltVersion: matches the installed CLI and halts with a clear "run bolt skills:sync then re-invoke" message on mismatch — so even a stale skill that loads into context before auto-sync runs cannot produce a wrong recommendation.

Test Plugins

| Plugin | What it tests | Mode | |--------|--------------|------| | structural-smoke | Create + render nodes for every content type via Drush | full | | browser-smoke | Visit URLs, check HTTP status, JS errors, broken images | all | | accessibility | axe-core WCAG 2.0 AA scan on all representative URLs | all | | visual-regression | Screenshot comparison across 3 viewports per URL | all | | field-interaction | Fill and submit admin forms for each content type | full, admin | | media-browser | Upload media via library interface | full, admin | | wysiwyg | CKEditor 5 toolbar, formatting, media embed | full, admin | | linkit | LinkIt autocomplete in CKEditor | full, admin | | menu-admin | Create, edit, delete menu links via admin UI | full, admin |

Plugins skip gracefully when their required modules aren't installed.

Configuration

.bolt.yml

Per-site test configuration, created by bolt init.

adapter: ddev

plugins:
  skip:
    - visual-regression
  config:
    accessibility:
      rules_to_skip: [color-contrast]
    visual-regression:
      threshold: 0.5
      mask:
        - selector: ".block-current-date"

custom_routes:
  - /products
  - /about

refresh:
  base_branch: main
  db:
    source: pantheon          # pantheon | file (or any ddev pull provider)
    pantheon_site: mysite     # Terminus site name
    pantheon_env: live        # Environment to pull from
    # source: file
    # file_path: /path/to/dump.sql.gz

update:
  ignore:
    - drupal/core-*          # Update core manually
  priority:
    - drupal/core-recommended

pr:
  base_branch: main
  default_reviewers:
    - broeker
  draft: false
  remote: origin

.boltrc.yml

Per-site suppression rules, created by bolt suppress.

suppress:
  js_errors:
    - pattern: "Siteimprove"
      reason: "Analytics script, fails locally"
  urls:
    - path: "/admin/orphan"
      reason: "Known 403, will be removed"
  accessibility:
    - rule: "color-contrast"
      reason: "Design fix scheduled Q2"
  plugins:
    - name: "visual-regression"
      reason: "Baselines not captured yet"

Severity Levels

| Severity | Meaning | Example | |----------|---------|---------| | critical | Site broken | CKEditor toolbar missing, node creation fails | | major | Significant functionality broken | Media upload fails, form validation errors | | minor | Cosmetic or edge-case issue | Broken image on one page, minor a11y violation | | info | Informational | Test passed, baseline captured |

--fail-on controls which severities trigger non-zero exit. Default is major.

Upgrading

# Update bolt CLI
npm update -g @electriccitizen/bolt

# Update the Drupal module on each site
cd ~/projects/client-acme
bolt init --upgrade
bolt doctor    # verify versions match

bolt init --upgrade runs composer update electriccitizen/bolt-inspect and clears caches — no config changes, no re-init.

Skills under .claude/skills/bolt:* are auto-synced on every bolt command, so they always match the installed CLI. After a CLI upgrade you can run bolt skills:status to confirm the sync, but no manual step is required.

Complementary tools

Bolt focuses on Drupal update / PR / deploy / fix orchestration with deterministic safety scaffolding (lock-diff verification, drift detection, auto-rollback, audit trail) plus AI-driven judgment (risk assessment, ticket diagnosis, autonomous fixes). For broader Drupal expertise — writing modules, code review, hook design, debugging — pair bolt with a Drupal-skill library that runs inside Claude Code:

  • edutrul/drupal-ai — 35+ Drupal topical skills (drupal-hooks, drupal-entity-api, drupal-caching, drupal-twig, etc.) plus 10 specialized sub-agents (drupal-backend-dev, code-reviewer, drupal-test-writer, etc.). Drop the .claude/ directory into your Drupal project; Claude Code picks it up automatically alongside bolt's skills.
  • Build your own per-site skill library under .claude/skills/ — Claude Code's skill discovery is compatible.

Bolt's AI commands (bolt analyze, bolt fix, /bolt:update) will use whatever skills the agent's session has access to. Installing complementary libraries makes those commands richer with no bolt-side configuration.

Roadmap

See docs/PLAN-MVP.md for the post-MVP roadmap.

Development

See docs/CONTRIBUTING.md for architecture, dev setup, and how to add plugins.

License

Proprietary - Electric Citizen