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

composelint

v0.2.0

Published

Linter and formatter for Docker Compose files, with key ordering, style, and security checks

Readme

composelint

npm CI license

Linter and formatter for Docker Compose files, with key ordering, style, and security checks.

  • Validates against the Compose Specification. The official JSON schema is vendored, so unknown keys and wrong value types are caught at every level, not just at the top.
  • Understands inheritance. <<: *anchor, extends, include: and override files are resolved before rules run, so a setting hidden behind an anchor is still checked.
  • Fixes without churn. --fix edits the original text instead of re-serializing the document: comments, quoting style, line wrapping and CRLF endings survive untouched.
  • Fits a pipeline. Stylish, JSON, GitHub annotation and SARIF output; --max-warnings for a gate; documented exit codes.

Install

npm install --save-dev composelint

Or run it without installing:

npx composelint

Requires Node.js 22 or newer.

Quick start

composelint                  # walk the current directory
composelint compose.yaml     # lint one file
composelint stacks/          # lint a directory
composelint --fix            # apply fixes
compose.yaml
  1:1     error  Top-level "version" field is obsolete in modern Compose and should be removed  no-version-field [fixable]
  6:9     warn   Service "db": port "5432:5432" is published on all interfaces (0.0.0.0)        no-unbound-ports
  4:12    warn   Service "web": image "nginx" has no explicit tag (defaults to "latest")        image-require-tag

✖ 3 problems (1 error, 2 warnings)
  1 fixable with --fix

CLI

| Option | Description | | --- | --- | | --fix | Apply fixes and write the files back | | --format <name> | stylish (default), json, github, sarif | | --preset <name> | recommended (default) or strict | | --config <path> | Use a specific configuration file | | -q, --quiet | Print errors only (warnings are still counted) | | --max-warnings <n> | Fail when more than n warnings remain (-1, the default, disables the check) | | --version, --help | |

Exit codes:

| Code | Meaning | | --- | --- | | 0 | No errors, and warnings within --max-warnings | | 1 | At least one error, or too many warnings | | 2 | composelint could not run: bad option, unreadable file, broken configuration |

With no arguments the current directory is walked recursively for compose.yaml, docker-compose.yml, compose.prod.yaml, prod.compose.yaml and similar names. See which files are linted.

Configuration

composelint works with no configuration. To adjust it, add .composelintrc.json (or any supported location):

{
  "rules": {
    "no-unbound-ports": "error",
    "require-healthcheck": ["warn", { "exclude": ["migrate"] }]
  },
  "exclude": ["examples/**"]
}

Full reference: docs/configuration.md.

Rules

Legend: 💼 error in the preset · ⚠️ warning in the preset · 🔧 fixable with --fix · ⚙️ has options

| Rule | Category | recommended | strict | 🔧 | ⚙️ | | --- | --- | --- | --- | --- | --- | | spec-schema | spec | 💼 | 💼 | | | | top-level-order | style | ⚠️ | 💼 | 🔧 | ⚙️ | | service-key-order | style | ⚠️ | 💼 | 🔧 | ⚙️ | | no-version-field | style | 💼 | 💼 | 🔧 | | | no-privileged | security | ⚠️ | 💼 | | | | no-host-network | security | ⚠️ | 💼 | | | | no-cap-add-all | security | ⚠️ | 💼 | | | | no-unbound-ports | security | ⚠️ | 💼 | | ⚙️ | | image-require-tag | security | ⚠️ | 💼 | | ⚙️ | | require-name | best-practice | ⚠️ | 💼 | | | | require-healthcheck | best-practice | ⚠️ | 💼 | | ⚙️ |

Scope of the security checks

The security rules cover privilege escalation through privileged and cap_add: [ALL], loss of network isolation through network_mode: host and wildcard port publishing, and unpinned images. They are not a complete container security review: mounting the Docker socket, credentials in environment, running as root, missing no-new-privileges, host namespace sharing through pid/ipc/uts, and digest pinning are not checked. Treat composelint as one layer, alongside an image scanner and a review against the OWASP Docker Security Cheat Sheet.

Suppressing a rule for one line

services:
  runner:
    image: docker:27-dind
    privileged: true  # composelint-disable-line no-privileged -- dind needs it

disable-file, disable-next-line, disable-line and disable/enable ranges are all supported, and a directive that suppresses nothing is reported so stale exceptions do not accumulate. Full reference: docs/suppressions.md.

Continuous integration

name: composelint
on: [push, pull_request]

jobs:
  lint:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 22
      - run: npx composelint --format github --max-warnings 0

--format github turns each diagnostic into a workflow annotation on the offending line. To feed GitHub Code Scanning instead, emit SARIF and upload it:

      - run: npx composelint --format sarif > composelint.sarif
        continue-on-error: true
      - uses: github/codeql-action/upload-sarif@v4
        with:
          sarif_file: composelint.sarif

Node API

import { lintSource, lintAndFix, resolveConfig, allRules } from "composelint";

const config = resolveConfig({ rules: { "require-healthcheck": "off" } });

const { result } = lintSource(source, "compose.yaml", allRules, config);
for (const d of result.diagnostics) {
  console.log(`${d.range.start.line}:${d.range.start.column} ${d.severity} ${d.message} (${d.ruleId})`);
}

const { source: fixed } = lintAndFix(source, "compose.yaml", allRules, config);

resolveConfig takes the same object a configuration file holds and fills in the defaults; allRules is the built-in rule list. Both functions are pure: they never read or write files, so the caller decides what to do with the result.

Contributing

A rule consists of three files, following the ESLint convention:

src/rules/<category>/<name>.ts     the rule
tests/rules/<category>.test.ts     its tests
docs/rules/<name>.md               its documentation

Tests enforce that set: every rule must have a documentation file containing the standard sections, every option a rule declares must be documented, and the table above must match the rule metadata.

See CONTRIBUTING.md for the rule conventions, how fixes work, and the release process. Changes are listed in CHANGELOG.md.

A bug report needs the Compose file that reproduces it; a rule proposal needs an example that should stay quiet as well as one that should be reported. The issue forms ask for both. Vulnerabilities go through SECURITY.md rather than a public issue. Participation is covered by the Code of Conduct.

The Compose Specification schema is vendored in schemas/ and refreshed with pnpm schema:update.

License

MIT. The bundled Compose Specification schema is Apache-2.0; see NOTICE.