0.0
The project is in a healthy, maintained state
Analyses your Gemfile for dependency health: checks if gems are actively maintained (last commit dates via GitHub and GitLab, release dates), outdated versions, archived repos, OpenSSF Scorecard security scores, known vulnerabilities via deps.dev, and libyear drift. Ruby version freshness with EOL detection. Handles rubygems, git, path, and GitHub Packages sources. Outputs coloured terminal tables, markdown, or JSON. CI quality gates with --fail-if-critical, --fail-if-warning, --fail-if-vulnerable, --fail-if-outdated, and --ignore. A comprehensive alternative to running bundle outdated, bundler-audit, and libyear-bundler separately.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies
 Project Readme

still_active

How do you know if your Ruby dependencies are still maintained?

bundle outdated tells you version drift. bundler-audit catches known CVEs. Neither tells you whether anyone is still working on the thing. still_active checks maintenance activity, version freshness, security scores, vulnerabilities, libyear drift, and archived repos for every gem in your Gemfile.

Findings ship as terminal / markdown / JSON / SARIF — the last lands in your GitHub Security tab and as inline PR annotations on Gemfile.lock. PR mode (--baseline=FILE) reports only what got worse since main, so reviewers see one line ("vcr newly archived") instead of an absolute snapshot of every dep.

Gem Version GitHub Action Code Quality analysis RSpec Rubocop analysis

Name                    Version          Activity  OpenSSF  Vulns
───────────────────────────────────────────────────────────────────
async                   2.36.0 (latest)  ok        7.1/10   0
backbone-rails          1.2.3 (latest)   archived  3.6/10   0
bootstrap-slider-rails  9.8.0 (latest)   critical  -        0
gitlab-markup           2.0.0 (latest)   ok        -        0
local_gem               0.1.0 (path)     -         -        0
nested_form             0.3.2 (git)      archived  3.3/10   0
remotipart              1.4.4 (git)      critical  3.1/10   0

7 gems: 4 up to date, 0 outdated · 2 active, 2 stale, 2 archived · 0 vulnerabilities
Ruby 4.0.1 (latest)

Why still_active?

still_active is complementary to -- not a replacement for -- the established Ruby tooling. bundle outdated, bundler-audit, and libyear-bundler are purpose-built and battle-tested at what they do. still_active answers a different question: is anyone still maintaining this gem? -- and folds in the version/CVE/libyear signals so you get one report instead of three.

bundle outdated bundler-audit libyear-bundler still_active
Outdated versions Yes - Yes Yes
Known vulnerabilities (CVEs) - Yes (ruby-advisory-db) - Yes (deps.dev)
Libyear drift - - Yes Yes
Last commit activity - - - Yes
Archived repo detection - - - Yes
OpenSSF Scorecard - - - Yes
Yanked version detection - - - Yes
Ruby version freshness - - - Yes (EOL + libyear)
GitLab support - - - Yes
CI quality gates - Exit code - Yes (4 flags)
Output formats Text Text Text Terminal, JSON, Markdown

The bolded rows are the gap still_active fills: nobody else answers "is the maintainer still around?" The CVE column is worth a closer look: bundler-audit and still_active use different data sources (ruby-advisory-db vs deps.dev), so coverage isn't identical. If you care about CVEs in CI, keep running bundler-audit alongside still_active.

Installation

gem install still_active

Quick Start

# audit your Gemfile (auto-detects output format)
still_active

# check specific gems
still_active --gems=rails,nokogiri,sidekiq

# CI pipeline: fail if any gem is critically stale or has vulnerabilities
still_active --fail-if-critical --fail-if-vulnerable

# ignore specific gems in CI checks
still_active --fail-if-warning --ignore=legacy_gem,internal_gem

# markdown table for pull requests or documentation
still_active --markdown

Usage

Authentication

still_active discovers a GitHub token in this order:

  1. --github-oauth-token=TOKEN CLI flag
  2. GITHUB_TOKEN environment variable (CI convention)
  3. GH_TOKEN environment variable (gh CLI convention)
  4. gh auth token (if gh is installed and authenticated)

Without a token, GitHub API calls are unauthenticated and rate-limited to 60 requests/hour — you will hit the limit on anything beyond a handful of gems. With a token the limit is 5000 requests/hour.

GitLab cascade mirrors GitHub: --gitlab-tokenGITLAB_TOKENglab auth status --show-token. Optional for public repos, required for private ones.

CLI options

Usage: still_active [options]

        all flags are optional

        --gemfile=GEMFILE            path to gemfile
        --gems=GEM,GEM2,...          Gem(s)
        --terminal                   Coloured terminal output (default in TTY)
        --markdown                   Markdown table output
        --json                       JSON output (default when piped)
        --sarif[=PATH]               SARIF 2.1.0 output for GitHub Code Scanning
        --baseline=PATH              Compare current state to baseline JSON; emit markdown deltas
        --github-oauth-token=TOKEN   GitHub OAuth token to make API calls
        --gitlab-token=TOKEN         GitLab personal access token for API calls
        --simultaneous-requests=QTY  Number of simultaneous requests made
        --safe-range-end=YEARS       maximum years since last activity considered safe (no warning)
        --warning-range-end=YEARS    maximum years since last activity that triggers a warning (beyond this is critical)
        --fail-if-critical           Exit 1 if any gem has critical activity warning
        --fail-if-warning            Exit 1 if any gem has warning or critical activity warning
        --fail-if-vulnerable[=SEVERITY]
                                     Exit 1 if any gem has vulnerabilities (optionally at or above SEVERITY)
        --fail-if-outdated=LIBYEARS  Exit 1 if any gem exceeds LIBYEARS behind latest
        --ignore=GEM,GEM2,...        Exclude gems from pass/fail checks (still shown in output)
        --critical-warning-emoji=EMOJI
        --futurist-emoji=EMOJI
        --success-emoji=EMOJI
        --unsure-emoji=EMOJI
        --warning-emoji=EMOJI
    -h, --help                       Show this message
    -v, --version                    Show version

Output formats

Terminal (default on TTY) -- coloured table with summary line. Shown above.

JSON (default when piped) -- structured data for automation:

still_active --json --gemfile=spec/still_active/edge_case_gemfile/Gemfile
{
  "gems": {
    "async": {
      "source_type": "rubygems",
      "version_used": "2.36.0",
      "latest_version": "2.36.0",
      "repository_url": "https://github.com/socketry/async",
      "last_commit_date": "2026-01-22 04:09:48 UTC",
      "archived": false,
      "scorecard_score": 7.1,
      "vulnerability_count": 0,
      "libyear": 0.0
    },
    "nested_form": {
      "source_type": "git",
      "version_used": "0.3.2",
      "repository_url": "https://github.com/ryanb/nested_form",
      "last_commit_date": "2021-12-11 21:47:02 UTC",
      "archived": true,
      "scorecard_score": 3.3,
      "vulnerability_count": 0
    },
    "local_gem": {
      "source_type": "path",
      "version_used": "0.1.0",
      "scorecard_score": null,
      "vulnerability_count": 0
    }
  },
  "ruby": {
    "version": "4.0.1",
    "eol": false,
    "latest_version": "4.0.1",
    "libyear": 0.0
  }
}

Markdown -- table for pull requests, documentation, or wikis:

still_active --markdown
activity up to date? OpenSSF vulns name version used latest version latest pre-release last commit libyear
7.1/10 async 2.36.0 (2026/01) 2.36.0 (2026/01) 2026/01 0.0y
🚩 3.6/10 backbone-rails 1.2.3 (2016/02) 1.2.3 (2016/02) 2016/02 0.0y
local_gem 0.1.0 (path) -
🚩 3.3/10 nested_form 0.3.2 (git) 2021/12 -

Ruby 4.0.1 (latest) ✅

SARIF output (GitHub Code Scanning)

Emit findings as SARIF 2.1.0 — they show up in the GitHub Security tab and as inline annotations on Gemfile.lock in pull requests.

See it live: this repo audits itself on every push. Browse the live findings in the Code Scanning Security tab — currently 2× SA005 (low OpenSSF Scorecard).

still_active --sarif                       # writes still_active.sarif.json
still_active --sarif=path/to/out.sarif.json
still_active --sarif=-                     # stdout

Easy mode — use the still_active-action wrapper:

permissions:
  contents: read
  security-events: write   # required for SARIF upload

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: ruby/setup-ruby@v1
        with: { ruby-version: '3.4' }
      - uses: SeanLF/still_active-action@v0
        with:
          github-token: ${{ github.token }}
          sarif: still_active.sarif.json
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with: { sarif_file: still_active.sarif.json }

Plain bundle exec if you'd rather pin still_active in your Gemfile:

      - run: bundle exec still_active --sarif
        env:
          GITHUB_TOKEN: ${{ github.token }}
      - uses: github/codeql-action/upload-sarif@v3
        if: always()
        with: { sarif_file: still_active.sarif.json }

Rule reference (SA001–SA007) and how to suppress: see docs/rules.md.

Baseline diff (PR review)

--baseline=FILE compares the current run against a previously captured JSON snapshot and emits a markdown delta report. Designed for the PR question reviewers actually ask: what got worse?

# Locally — capture from main, compare to your branch
git checkout main && still_active --json > /tmp/main.json
git checkout my-branch && still_active --baseline=/tmp/main.json

In CI, capture a baseline on main and compare on PR branches. Exits 1 if any regression is detected (new vulns, newly-archived deps, scorecard drops crossing 7.0, libyear growth on unchanged versions, Ruby newly EOL, etc.).

The diff supersedes --sarif, --terminal, --markdown, and --json when set.

CI quality gating

Use exit-code flags to fail CI pipelines based on dependency status:

# fail on critically stale or archived gems
still_active --fail-if-critical --json

# fail on any stale, critical, or archived gem
still_active --fail-if-warning --json

# fail if any gem has known vulnerabilities
still_active --fail-if-vulnerable --json

# fail only on high/critical severity vulnerabilities
still_active --fail-if-vulnerable=high --json

# fail if any gem is more than 3 libyears behind
still_active --fail-if-outdated=3 --json

# combine flags and exclude known exceptions
still_active --fail-if-warning --fail-if-vulnerable --ignore=legacy_gem --json

Activity thresholds

Activity is determined by the most recent signal across last commit date, latest release date, and latest pre-release date:

  • ok: last activity within 1 year (configurable with --safe-range-end)
  • stale: last activity between 1 and 3 years ago (configurable with --warning-range-end)
  • critical: last activity over 3 years ago

Data sources

Configuration defaults

Option Default Description
output_format auto-detect Coloured terminal on TTY, JSON when piped
safe_range_end 1 year Last activity within this range is "ok"
warning_range_end 3 years Last activity within this range is "stale"; beyond is "critical"
simultaneous_requests 10 Concurrent API requests

Development

After checking out the repo, run bin/setup to install dependencies and wire git hooks. Then run rake to run the full lint + test suite (rake spec for just tests, rake rubocop for just lint). You can also run bin/console for an interactive prompt that will allow you to experiment.

A pre-push hook runs rake automatically before each git push, so cross-file rubocop rules don't escape to CI. Skip with git push --no-verify if you really need to.

To install this gem onto your local machine, run bundle exec rake install. New versions are published automatically to rubygems.org when a GitHub Release is created (via trusted publishing).

Contributing

Bug reports and pull requests are welcome.

License

The gem is available as open source under the terms of the MIT License.