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

Peck Laravel Package

peckphp/peck

Peck is a fast CLI tool that finds spelling and wording mistakes across your PHP codebase—filenames, class, method and property names, docs, and more. Powered by GNU Aspell, it fits naturally into your workflow like Pint or Pest. Requires PHP 8.2+.

View on GitHub
Deep Wiki
Context7

Getting Started

1. Install the system dependency first — this is not optional.

Peck shells out to GNU Aspell, so Composer alone won't make it work:

# Debian/Ubuntu (also the basis for WSL)
sudo apt-get install aspell aspell-en

# macOS
brew install aspell

# Windows: use WSL, or Scoop
scoop install main/aspell

Verify with aspell dump dicts — if that command fails, nothing else will work either.

2. Install as a dev dependency and scaffold config.

composer require peckphp/peck --dev
./vendor/bin/peck --init

--init writes a peck.json in your project root. Open it immediately; this file is the whole control surface of the tool.

3. Look at peck.json before looking at output. A useful starting config is three keys:

{
    "preset": "laravel",
    "language": "en_US",
    "ignore": {
        "words": ["config", "namespace"],
        "paths": ["vendor", "node_modules", "storage", "bootstrap/cache"]
    }
}

The laravel preset pre-seeds common framework vocabulary so you don't hand-list middleware, eloquent, etc. yourself.

4. Baseline on the first run.

./vendor/bin/peck --ignore-all

A mature codebase will produce hundreds of hits on run one. --ignore-all writes them into the config in one pass so you start from green. Review the diff, commit it, and from then on you only see new mistakes. That ratchet is the actual day-to-day value of the tool.

5. Your first real use case: wire it next to Pint and Pest as composer test:typos and run it locally before pushing. Don't start by blocking CI — publish the count first.


Implementation Patterns

Composer script, advisory by default.

{
  "scripts": {
    "test:typos": "peck"
  }
}

Run composer test:typos manually, or chain it into a broader composer test alongside Pint and Pest. Keeping it a named script means CI and local dev use the identical invocation — no divergence between "works on my machine" and the runner.

CI: install Aspell explicitly, then run. Peck is not a self-contained binary; every job needs the system package. The README's GitHub Actions pattern is the one to copy:

- name: Install Aspell
  shell: bash
  run: |
      if [[ "$RUNNER_OS" == "Linux" ]]; then
        sudo apt-get update && sudo apt-get install -y aspell aspell-en
      elif [[ "$RUNNER_OS" == "macOS" ]]; then
        brew install aspell
      fi

- name: Check Typos
  shell: bash
  run: |
      if [[ "$RUNNER_OS" == "Linux" || "$RUNNER_OS" == "macOS" ]]; then
        composer test:typos
      fi

Keep the run step non-blocking initially (continue-on-error: true or a separate non-required job). Promote to a required check only once the ignore list has stopped churning for a couple of weeks.

The ratchet workflow. This is the pattern that makes Peck survivable on inherited code:

  1. Baseline with --ignore-all, commit.
  2. New typo arrives in a PR → check fails → author fixes or adds an explicit word/path ignore.
  3. Periodically prune the ignore list; a growing list is a signal that a preset needs extending upstream.

Scope discipline with ignore.paths and --path. Because the default path is now the project root (changed in v0.1.3), make sure vendor/, node_modules/, build output, and generated fixtures are ignored. For targeted runs on a single area:

./vendor/bin/peck --path app/Domain/Payments

This is also your debugging tool — run it on one directory or one file to isolate a confusing report.

Use --text for short strings. Commit messages, PR titles, or a proposed method name can be checked without a file:

./vendor/bin/peck --text "getRecieveAdress"

Handy as a quick "is this identifier actually spelled correctly" reflex before you commit to a public API name.

Monorepos and multiple configs. --config relative/path/to/peck.json lets one repository carry separate configs per package or app, each with its own preset and ignore list. Run Peck once per config in CI rather than trying to build one giant shared list.

Language switching. Set "language": "en_GB" (or de, fr, etc.) to match your team's spelling convention — but only after confirming the dictionary is installed via aspell dump dicts. Do this early: en_US vs en_GB disagreements produce false positives on every occurrence of colour/colour, behaviour, initialize/initialise.

Pre-commit feedback. Run Peck via a pre-commit hook (Captain Hook, Husky, or a plain .git/hooks/pre-commit) so developers see results in seconds rather than after a CI round trip. Feedback-loop ownership is the difference between a check developers tolerate and one they route around.


Gotchas and Tips

Aspell is the real adoption tax. Composer resolves the package fine; the tool then fails at runtime if Aspell is absent. Docker images, freshly provisioned CI runners, and Windows machines are the usual suspects. Add the install step to your dev container image, not just to CI, or onboarding will silently break.

Windows without WSL is a second-class path. Scoop works, but the README's own recommendation is WSL. If your team is mixed-platform, validate on a Windows machine early rather than discovering it during a sprint deadline.

Pre-1.0 software. The README states Peck is "not yet ready for production use." Treat that as a pinning instruction: lock a specific version in composer.json and upgrade deliberately, rather than floating on ^0.x and getting a changed default path or preset mid-sprint.

--ignore-all writes to your config — review the diff. It's generous by design and will happily add noise. Check that it hasn't added per-file entries where a single ignore.paths glob would do, and keep the list sorted so merges don't conflict. Assign one owner to peck.json; an unowned ignore list decays into a junk drawer within a quarter.

False positives cluster in specific places:

  • Camel-case identifiers are split into words, so getHttpReq or S3Client can trip the dictionary. Add the fragment to ignore.words, not the whole identifier.
  • Domain jargon, product names, and client names — always ignore-list these as words.
  • Acronyms and initialisms that Aspell doesn't recognise.
  • Union types: the | character was explicitly handled in v0.1.1's formatter, but complex union/intersection type expressions remain a place to check first if a strange report appears.

Misspellings with no suggestions are still reported. Since v0.2.0 these are surfaced as misspellings rather than silently skipped — so you may see an error line with no "did you mean" hint. That's expected; add the word to ignore.words or fix it manually.

peck.json is looked up in the project root by default. If you run Peck from a subdirectory or through a wrapper script that changes the working directory, it may not find your config and will fall back to auto-detecting the directory to check. If results suddenly change, pass --config explicitly.

--path overrides the config's path resolution. When debugging a surprising result, re-run with an explicit --path to a single file and compare against the full-project run — the difference usually tells you whether the issue is scope or a genuine false positive.

Extension points are limited to configuration. There is no custom-preset mechanism, no regex rules engine, and no naming-convention policy — Peck does dictionary checking plus word/path ignores, full stop. If you need architectural naming rules, that's PHPStan or a custom PHP-CS-Fixer rule, not Peck. The one lever you do have is upstream: if your organisation's Laravel vocabulary keeps landing in ignore.words, contributing those terms to the laravel preset is cheaper than maintaining a local list forever.

Polyglot repos get partial coverage. Peck targets PHP-adjacent assets and Markdown. TypeScript, Python, or Go files will not get the same treatment — don't advertise it as a repo-wide spell checker if the repo isn't predominantly PHP.

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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle