captainhook/captainhook-phar
Composer installer for the CaptainHook PHAR. Adds CaptainHook to vendor/bin for use in projects and updates it automatically on composer update. See captainhook/captainhook for source, quick start, and full docs at captainhook.info.
Install the PHAR:
composer require --dev captainhook/captainhook-phar
This places the executable at vendor/bin/hook and updates it on composer update.
Initialize Hooks:
vendor/bin/hook init
This generates a default hooks/ directory in your project root (or .git/hooks/ if configured).
Define a Hook:
Create a hooks.yml (or hook.php) in your project root with a basic pre-commit hook:
hooks:
pre-commit:
- "php artisan test --env=testing"
- "php vendor/bin/pint"
Test Locally:
git commit -m "test hook"
Verify the commands run before the commit succeeds.
vendor/bin/hook --help for CLI options (e.g., hook list, hook run).# hooks.yml
hooks:
pre-commit:
- "php artisan test --env=testing --parallel"
- "php vendor/bin/psalm --no-cache"
Why?
Leverage Artisan commands in hooks for Laravel-centric workflows:
hooks:
pre-push:
- "php artisan migrate:status --env=production"
- "php artisan queue:work --once --env=testing"
Pattern: Use --env flags to target specific environments.
Skip hooks based on file changes or environment:
hooks:
pre-commit:
- "php artisan test --env=testing --filter=Unit"
- "php vendor/bin/pint --test" # Only lint changed files
Tool: Use git diff --name-only in a shell script wrapper if needed.
Trigger hooks in GitHub Actions or GitLab CI:
# .github/workflows/ci.yml
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: composer install
- run: vendor/bin/hook run pre-commit # Run hooks in CI
- run: php artisan test
Use a template repo or Git submodule to share hooks.yml:
git submodule add https://github.com/org/shared-hooks.git vendor/shared-hooks
Then symlink or merge the config into your project.
composer require --dev captainhook/captainhook-phar
vendor/bin/hook init
git commit -m "feat: add user auth" # Triggers pre-commit hooks
vendor/bin/hook run pre-commit --verbose
composer install --no-dev
composer require --dev captainhook/captainhook-phar
vendor/bin/hook run pre-commit
- name: Run Hooks
run: vendor/bin/hook run pre-commit || exit 1
Create a custom Artisan command to manage hooks:
php artisan make:command HookManager
// app/Console/Commands/HookManager.php
public function handle()
{
$this->call('hook:init');
$this->info('Hooks initialized!');
}
Register it in app/Console/Kernel.php:
protected $commands = [
\App\Console\Commands\HookManager::class,
];
Now run hooks via:
php artisan hook:init
Use Laravel’s config system to load hooks dynamically:
// config/hook.php
return [
'hooks' => [
'pre-commit' => [
env('APP_ENV') === 'local'
? ['php artisan test']
: ['php artisan test --env=staging'],
],
],
];
Redirect hook output to Laravel’s log:
hooks:
pre-commit:
- "php artisan test --env=testing | tee -a storage/logs/hook.log"
Or use a shell wrapper:
#!/bin/sh
php artisan test --env=testing >> storage/logs/hook.log 2>&1
Permission Issues:
.git/hooks/.chmod +x .git/hooks/*
hooks/ directory (configured in hook.yml):
hooks:
directory: ./hooks
PHAR Updates Breaking Hooks:
composer update may overwrite the PHAR, breaking custom logic.composer.json:
"extra": {
"phar-captainhook": "5.6.0"
}
Hook Conflicts:
.git/hooks/ files are overwritten.hooks:
directory: ./custom-hooks
hook --skip-existing.Slow Hooks in CI:
--skip in CI:
- run: vendor/bin/hook run pre-commit --skip
Laravel-Specific Gotchas:
.env or config.hooks:
pre-commit:
- ". .env && php artisan test"
Verbose Mode:
vendor/bin/hook run pre-commit --verbose
Reveals the exact commands being executed and their exit codes.
Dry Run:
vendor/bin/hook run pre-commit --dry-run
Lists commands without executing them.
Log Hook Output: Redirect output to a file:
hooks:
pre-commit:
- "php artisan test --env=testing > storage/logs/hook-test.log 2>&1"
Check PHAR Integrity: Verify the PHAR isn’t corrupted:
composer show captainhook/captainhook-phar
Look for checksum mismatches or missing files.
YAML vs. PHP Config:
hooks.yml).config/hook.php):
return [
'hooks' => [
'pre-commit' => [
'commands' => function () {
return ['php artisan test', 'php vendor/bin/pint'];
},
],
],
];
Hook Order: Hooks run in the order defined in the config. Use comments to document dependencies:
hooks:
pre-commit:
# 1. Run tests
- "php artisan test"
# 2. Lint code
- "php vendor/bin/pint"
Global vs. Local Hooks:
.git/hooks/ (default).hooks/ directory:
hooks:
directory: ./hooks
# hooks/custom-pre-commit.sh
#
How can I help you explore Laravel packages today?