Download the PHP package gerard/claude-code-hooks without Composer

On this page you can find all versions of the php package gerard/claude-code-hooks. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package claude-code-hooks

# πŸͺ gerard/claude-code-hooks **Type-safe Claude Code hooks for PHP.** Every event, every tool input, every response β€” fully typed, mutation-tested, and kept in sync with the Anthropic spec by a daily drift job. [![PHP](https://img.shields.io/badge/PHP-8.3%2B-777BB4?logo=php&logoColor=white)](https://www.php.net/releases/8.3/) [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE) [![PHPStan](https://img.shields.io/badge/PHPStan-level%20max-1d3d4f)](https://phpstan.org/) [![Psalm](https://img.shields.io/badge/Psalm-errorLevel%201-blueviolet)](https://psalm.dev/) [![Coverage](https://img.shields.io/badge/Coverage-100%25-success)](#-quality-bar) [![MSI](https://img.shields.io/badge/Mutation%20MSI-%E2%89%A580%25-orange)](#-quality-bar) [![Doc-drift](https://img.shields.io/badge/Doc--drift-daily-blue)](#-staying-in-sync-with-the-anthropic-spec) [![Status](https://img.shields.io/badge/Status-alpha%20%E2%80%A2%20v0.0.1-yellow)](#-installation) [![PRs welcome](https://img.shields.io/badge/PRs-welcome-brightgreen)](CONTRIBUTING.md)

πŸ€” What is this?

Claude Code β€” Anthropic's official CLI for Claude β€” emits hook events at every interesting moment of a coding session: a tool is about to run, the user submitted a prompt, a session is starting, the context just got compacted, and so on. There are 29 documented events today, each with its own JSON wire shape and decision protocol.

If you want to observe, intercept, redirect, or veto what Claude Code does β€” from a PHP backend, a CLI, or a Symfony bundle β€” this package gives you a first-class SDK for it:

It's the layer you'd otherwise have to reinvent in every project that touches Claude Code from PHP.


✨ Highlights

🎯 29 typed events Every documented hook (Session, Turn, Tool, Perm, Compact, Ctx, Team) as an immutable DTO. Forward-compatible: unknown event names surface as UnknownHookEvent, never as exceptions.
🧰 12 typed tool inputs Bash, Edit, Write, Read, Glob, Grep, WebFetch, WebSearch, Agent, AskUserQuestion, TodoWrite, Skill. Plus a RawToolInput fallback that handles mcp__<server>__<tool> invocations and any first-party tool not yet modelled.
πŸ“€ 13 response builders Immutable, fluent. with*() clones, toArray() ships. Decision shapes match the docs exactly.
πŸͺœ Multi-source resolver Honours the documented precedence: Policy β†’ User β†’ Project β†’ Local β†’ Plugin β†’ Runtime. Filesystem and in-memory loaders included; bring your own by implementing SettingsLoader.
πŸ“œ Streaming transcripts Generator-based JSONL reader with an 8 MB per-line cap (SEC-02), compact_boundary events, and a sidechain grouper. Tail huge transcripts without loading them into memory.
πŸ’° Cost calculator Sonnet 4.5 price table out of the box; swap with your own PriceTable. Integer-cent arithmetic via a Money value object β€” no float drift.
πŸ”Ž Linter 6 core rules ship today (broad matchers in policy, unknown events, missing matchers, HTTP handlers without timeout, secret literals, broad matchers on prompt/agent hooks). 18 more on the roadmap (see CHANGELOG.md).
πŸ›‘οΈ Security-first realpath-based path-traversal protection (SEC-01), Authorization header redaction (SEC-09), single JsonDecoder chokepoint with JSON_THROW_ON_ERROR, safe-only YAML parsing (SEC-03), 10 MB body cap on the doc-drift fetch (SEC-06).
πŸ§ͺ 100 % covered, mutation-tested PHPStan max + strict, Psalm errorLevel 1, Deptrac layered architecture, MSI β‰₯ 80 / Covered MSI β‰₯ 85 β€” all enforced in CI.
πŸ“‘ Daily doc-drift Scheduled CI job re-fetches https://code.claude.com/docs/en/hooks and opens a GitHub issue the moment Anthropic ships a new event. SHA-256 sidecar pins captured fixtures against silent edits.

πŸš€ Quick start β€” 60 seconds

The whole loop is decode β†’ match β†’ respond:

That's it. No manual JSON spelunking, no copy-paste from the docs, no hand-rolled response builders.


πŸ“¦ Installation

Requirements

Runtime dependencies


πŸ“š Cookbook

🎯 Intercepting a tool call

PreToolUseEvent::toolInput is typed against the ToolInput interface β€” pattern-match on the concrete class to read the typed properties.

The four documented decisions β€” allow, deny, ask, defer β€” are static factories on PreToolUseResponse. Want to mutate the input before letting it through? ->withUpdatedInput($newInput).

πŸ“œ Streaming a transcript

TranscriptReader is a Generator β€” it never loads the file into memory.

πŸ’° Computing usage cost

Money is closed under addition; sum the cost of every assistant turn in a transcript by chaining ->add().

πŸͺœ Resolving multi-source settings.json

The resolver honours the full documented precedence chain and applies the allowManagedHooksOnly policy filter before merging.

πŸ› οΈ Building a settings.json fragment

Note: withHeader('Authorization', …) only accepts ${VAR} placeholders β€” this layer never holds real secrets. Resolution happens in the future Symfony bundle.

πŸ”Ž Linting a config

πŸ“€ Producing a structured response

Every response builder is immutable: with*() returns a clone, toArray() ships.


πŸ—‚οΈ All supported events (29)

Family Events
Session SessionStart, SessionEnd, Setup
Turn UserPromptSubmit, UserPromptExpansion, Stop, StopFailure, SubagentStart, SubagentStop
Tool PreToolUse, PostToolUse, PostToolUseFailure, PostToolBatch
Perm PermissionRequest, PermissionDenied, Notification, Elicitation, ElicitationResult
Compact PreCompact, PostCompact
Ctx ConfigChange, CwdChanged, FileChanged, InstructionsLoaded, WorktreeCreate, WorktreeRemove
Team TaskCreated, TaskCompleted, TeammateIdle

Anything Anthropic ships after the pinned snapshot date surfaces as UnknownHookEvent β€” your code keeps running, the daily doc-drift job opens an issue, the next release adds the typed DTO.

πŸ› οΈ All supported tool inputs (12 + fallback)

DTO Wire tool_name Notable properties
BashInput Bash command, description, timeout, runInBackground
ReadInput Read filePath, offset, limit
WriteInput Write filePath, content
EditInput Edit filePath, oldString, newString, replaceAll
GlobInput Glob pattern, path
GrepInput Grep pattern, path, glob, outputMode, caseInsensitive, multiline
WebFetchInput WebFetch url, prompt
WebSearchInput WebSearch query, allowedDomains, blockedDomains
AgentInput Agent prompt, description, subagentType, model
AskUserQuestionInput AskUserQuestion questions, answers
TodoWriteInput TodoWrite todos[] (content, status, activeForm)
SkillInput Skill skill, args (#[\SensitiveParameter])
RawToolInput everything else name, payload β€” covers mcp__* + first-party tools without dedicated DTOs

πŸ”Œ Wire shapes β€” three quick references

The wire field names below match the actual shape Claude Code emits, verified against a real-corpus sample of 4 089 events.

PostToolUse
SessionEnd
Stop

πŸ’‘ One JSON entry point. JsonDecoder::decode() is the only sanctioned JSON parser in the package. It enforces JSON_THROW_ON_ERROR and a depth cap of 64. Raw json_decode() calls in src/ are forbidden by CI.


πŸ“‘ Staying in sync with the Anthropic spec

Two CLI binaries ship with the package and back the daily doc-drift.yml workflow:

Binary What it does Exit codes
bin/extract-anthropic-spec Fetches https://code.claude.com/docs/en/hooks (or, with --from-html-fixture <path>, parses a captured HTML fixture) and emits a canonicalised JSON spec on stdout or --output <path>. 0 ok β€’ 2 parse failure (NOT drift β€” the workflow surfaces this as "extractor failure" instead of opening phantom "events removed" issues)
bin/check-doc-drift Diffs the live spec against tests/Fixtures/anthropic-spec/snapshot.json. 0 no drift β€’ 1 drift detected β€’ 2 parse error

Reblessing the snapshot when Anthropic ships a new event:

Then bump AnthropicSpecExtractor::SNAPSHOT_VERSION to the new date. AnthropicSpecExtractorLiveShapeTest asserts the SHA-256 sidecar still matches.


πŸ§ͺ Quality bar

This is a security- and observability-critical package. The bar is set accordingly:

Run the full local gate:

Or the curated bundles:


πŸ” Security highlights

ID Mitigation
SEC-01 All scanner paths pass through realpath(); symlink escapes from ~/.claude/plugins etc. are rejected.
SEC-02 TranscriptReader caps every line at 8 MB; oversize lines surface as TranscriptLine{truncated: true} instead of OOM-ing.
SEC-03 YAML decoded only via Yaml::PARSE_EXCEPTION_ON_INVALID_TYPE. Object instantiation flags are forbidden (CI grep guard).
SEC-04 / 05 Decoder exceptions never embed the offending payload β€” only the source path and offset.
SEC-06 AnthropicSpecExtractor HTTP options are pinned: verify_peer/verify_host on, host allow-list, 10 MB body cap.
SEC-08 Linter Finding::$message is capped at 256 bytes and may never embed >8 contiguous chars from the offending input β€” invariant-tested.
SEC-09 HookConfig::__debugInfo() redacts the Authorization header.
SEC-15 Captured HTML fixtures are CI-scanned for Bearer, eyJ, gha_, glpat-, sk-, xoxb- patterns.

🀝 Contributing

Contributions are welcome β€” this is a community package and the API is intentionally narrow so it stays reviewable. Please read CONTRIBUTING.md for:

Found a bug or a missing event? Open an issue β€” a failing test fixture in tests/Fixtures/payloads/ is the fastest path to a fix.

See docs/adr/ for architectural decision records.


πŸ“„ License

Released under the MIT License. Copyright Β© 2026 SΓ©bastien Dieunidou and contributors.


πŸͺ **Built for the PHP community that ships with Claude Code.** [Report a bug](https://github.com/gerard-labs/claude-code-hooks/issues) β€’ [Read the changelog](CHANGELOG.md) β€’ [Contribute](CONTRIBUTING.md)

All versions of claude-code-hooks with dependencies

PHP Build Version
Package Version
Requires php Version ^8.3
ext-json Version *
ext-mbstring Version *
psr/log Version ^3.0
symfony/http-client Version ^7.0
symfony/http-client-contracts Version ^3.0
symfony/yaml Version ^7.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package gerard/claude-code-hooks contains the following files

Loading the files please wait ...