Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Composer License Checker Laravel Package

dominikb/composer-license-checker

A Composer plugin that checks your project's dependency licenses against configurable allow and deny lists, helping you spot incompatible or risky packages early and keep releases compliant.

Deep Wiki
Context7

Getting Started

  1. Install it as a dev-only tool so it never ships in your production artifact:

    composer require --dev dominikb/composer-license-checker
    
  2. Look at the package's own command list first — it's a small Symfony Console app, so --help tells you everything it supports for your version:

    vendor/bin/license-checker --help
    vendor/bin/license-checker check --help
    
  3. Create a policy file in the project root (default name license-checker.php). Start permissive — you want to discover what you already depend on before you start failing builds:

    <?php
    // license-checker.php
    return [
        'allow' => [
            'MIT',
            'Apache-2.0',
            'BSD-2-Clause',
            'BSD-3-Clause',
            'ISC',
        ],
        'deny' => [
            'GPL-3.0',
            'AGPL-3.0',
        ],
        'exclude' => [
            // 'some/internal-package',
        ],
    ];
    
  4. Run the check and read the output. It scans your installed packages (from composer.lock / vendor/composer/installed.json), so composer install must have run first:

    vendor/bin/license-checker check
    
  5. First real use case: turn it into a merge gate. Add a Composer script so everyone runs the same thing:

    {
        "scripts": {
            "licenses": "license-checker check"
        }
    }
    

    Then composer licenses becomes your team-wide entry point, and the command's non-zero exit code is the CI signal.

Implementation Patterns

Discover-then-tighten workflow. On a legacy codebase, don't write the allow list from memory. Run the checker, dump every license it found, then paste the safe ones into allow and open a ticket for anything ambiguous. Re-run after each dependency bump to catch drift.

Two-tier CI: PR check vs. production artifact check. Dev dependencies often carry copyleft licenses you never distribute. Run the checker twice with different scopes:

# .github/workflows/licenses.yml
- run: composer install --no-interaction --prefer-dist
- run: vendor/bin/license-checker check          # full tree incl. dev
- run: vendor/bin/license-checker check --no-dev # what actually ships

The second invocation is the one that matters for distribution obligations; the first keeps the repo honest.

Allow-list over deny-list for enforcement. A deny list only catches licenses you already thought of. For a hard gate, treat allow as the primary mechanism and use deny for explicitly unacceptable licenses you want a loud error on. Everything unknown should fail by default — see the "unknown license" gotcha below.

Gate upgrades, not just new packages. Pair the checker with Dependabot/Renovate. When a transitive bump changes a license (rare, but it happens during major version jumps), the license job fails in the same PR that introduced the change, which is exactly where you want the conversation.

Pre-commit / local guard. Add a short git hook or a Make target so contributors catch a violation before pushing:

# Makefile
.PHONY: licenses
licenses:
	vendor/bin/license-checker check

Exclude the exceptions explicitly. Internal/proprietary packages and forks with broken license metadata go in exclude — but leave a comment beside each entry explaining why, or the file rots into a pile of unexplained bypasses.

Inventory reporting. Use the plain listing output (or composer licenses) to produce a human-readable license inventory for compliance reviews, and reserve the check command for the machine gate. Two audiences, two commands.

Programmatic use. It's a normal PHP package, so if you need the data in a custom report you can bootstrap its classes from a script rather than shelling out and re-parsing text. Prefer the CLI until you actually need this.

Gotchas and Tips

  • Packages with no license field are the real risk. Packages marked proprietary, missing a license key, or with unknown will not be covered by your allow list — make sure they fail rather than silently passing, and handle internal packages via exclude, not by widening allow.
  • SPDX expressions break naive matching. A dependency declaring MIT OR Apache-2.0 or (MIT AND GPL-3.0) is not the string MIT. Verify how your installed version treats compound expressions before you trust a green build; if it doesn't decompose them, either allow the exact expression or exclude the package with a comment.
  • Normalize to SPDX IDs. BSD-3-Clause vs BSD 3-Clause vs BSD-3-clause are different strings. Copy IDs verbatim from the tool's output into your config; don't retype them.
  • Config file is resolved from the working directory. Running from a subdirectory, a Docker image with an unexpected WORKDIR, or a monorepo subproject can silently load no config and default to "everything passes." Always cd to the project root (or set the path explicitly if the version supports it) and confirm the config was actually loaded on the first run.
  • It reads installed packages, so install state matters. Run it after composer install in CI, and be aware that a stale vendor/ on a developer machine produces stale results. When in doubt, composer install first.
  • Don't swallow the exit code. vendor/bin/license-checker check || true in a CI script makes the whole exercise decorative. Let non-zero fail the job, and place the step right after install so builds fail fast.
  • Config key names are version-sensitive. Depending on the release you pin, the keys may be allow/deny or allowed/denied, and exclude may be named differently. Check the README shipped with your exact installed version rather than a blog post.
  • Pin the version. A 58-star, single-maintainer tool is a perfectly good utility but not something to float on ^x. Pin it in require-dev, let your bot open PRs, and read the changelog on majors — config schema changes are the most likely breaking change.
  • Prefer per-project install over a global binary. A globally installed copy can resolve the wrong composer.json/vendor/ depending on where you invoke it. As a dev dependency in require-dev, resolution is unambiguous.
  • Complement composer licenses, don't replace it. Composer's built-in command prints a table and never fails; this tool adds the policy and the exit code. Keep both: the built-in for humans, this one for the gate.
  • Debugging a failure: run the listing command first to see the package → license mapping, then compare against your config string-by-string. Nine times out of ten the mismatch is whitespace, casing, or a compound SPDX expression rather than an actually disallowed license.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast