diversified-design / php-blueprint
Generates a JSON blueprint of a PHP library's class signatures — optimised for coding-agent contexts.
Installs: 17
Dependents: 3
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/diversified-design/php-blueprint
Requires
- php: >=8.2
- helgesverre/toon: ^3.1
- phpstan/phpdoc-parser: ^2.3
- roave/better-reflection: ^6.69
- symfony/console: ^8.0
- symfony/filesystem: ^8.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.94
- pestphp/pest: ^4.4
- phpstan/phpstan: ^2.1
README
A reflection-based tool that generates a JSON blueprint of a PHP library's class signatures, optimised for use as LLM context.
Purpose
When providing library context to coding agents (like Claude Code), you want the class signatures (methods, types, docblocks) without the implementation noise. This tool gives you the equivalent of TypeScript .d.ts files or C/C++ headers — the public contract without implementation details.
Installation
composer require --dev diversified-design/php-blueprint
Usage
# Basic — extract all classes from a directory vendor/bin/blueprint src/ # Filter by namespace (recommended) vendor/bin/blueprint src/ --namespace="Vendor\\Package" # Specify output file vendor/bin/blueprint src/ --namespace="Vendor\\Package" -o blueprint.json # Include private/protected members vendor/bin/blueprint src/ --namespace="Vendor\\Package" --include-private # Truncate docs to first sentence vendor/bin/blueprint src/ --namespace="Vendor\\Package" --short-docs # All options vendor/bin/blueprint src/ \ --namespace="Vendor\\Package" \ -o blueprint.json \ -f json \ --include-private \ --include-internal \ --short-docs \ --compact-enums
Options
| Option | Short | Description |
|---|---|---|
--output |
-o |
Output JSON file path (default: blueprint.json in working directory) |
--namespace |
Filter by namespace prefix (e.g. Vendor\\Package) |
|
--exclude |
Exclude namespace prefix (repeatable) | |
--include-private |
Include private/protected members | |
--include-internal |
Include \Internal\ namespace classes |
|
--short-docs |
Truncate doc summaries to first sentence | |
--compact-enums |
Truncate large constant/enum lists (>5 entries) | |
--format |
-f |
Output format: json, toon (experimental), or both (default: json) |
--config |
-c |
Path to config file |
--no-config |
Ignore config file |
Configuration
Create a .blueprint.config.php in your project root:
<?php return [ 'path' => 'src/', 'output' => 'blueprint.json', 'format' => 'json', 'namespace' => 'Vendor\\Package', 'exclude' => [ 'Vendor\\Package\\Internal\\', 'Vendor\\Package\\Debug\\', ], 'include-private' => false, 'include-internal' => false, 'short-docs' => true, 'compact-enums' => false, ];
All keys are optional. When a config file is present, you can run Blueprint with no arguments:
vendor/bin/blueprint
CLI arguments always override config values. Use --no-config to ignore the config file, or --config path/to/config.php to use a different one.
Composer Scripts
Add to your project's composer.json:
{
"scripts": {
"blueprint": "blueprint src/ --namespace=Vendor\\\\Package -o blueprint.json"
}
}
Then run with composer blueprint.
CI/CD
# GitHub Actions example - name: Generate PHP library blueprint run: vendor/bin/blueprint src/ --namespace="Vendor\\Package" -o blueprint.json - name: Upload as artifact uses: actions/upload-artifact@v4 with: name: php-blueprint path: blueprint.json
Output Format
The extractor generates pretty-printed JSON:
{
"Namespace\\ClassName": {
"doc": "Class summary from docblock.",
"extends": "ParentClass",
"implements": ["Interface1"],
"uses": ["Trait1"],
"constants": {
"CONSTANT_NAME": "value"
},
"properties": [
"static readonly string $name"
],
"methods": [
"__construct(string $arg, int $count = 0)",
"doSomething(string $input): bool — Brief description"
]
}
}
Only non-empty fields are included. The type field is omitted for plain classes (only shown for interfaces, traits, and enums).
Output Modes
Public-Only (Default)
Extracts only public methods and properties — the true public API surface.
Use for: LLM context (most token-efficient), API documentation, public interface contracts.
Full Mode (--include-private)
Includes private and protected members.
Use for: Internal refactoring analysis, understanding implementation details, migration planning.
Writing Code That Blueprints Well
Blueprint extracts what's in your source — it can't invent context that isn't there. The more information your code carries in its signatures and docblocks, the more useful the blueprint is to an LLM agent. Here's what matters most:
Type everything
Blueprint captures parameter types, return types, and property types. When a PHPStan/Psalm @param, @return, or @var docblock type is present, Blueprint uses it instead of the native type hint — giving agents the full picture.
// Weak — agent has to guess function fetch($url, $options) { ... } // Better — agent knows the basic types function fetch(string $url, array $options = [], int $timeout = 30): Response { ... } // Best — agent knows the exact shape /** @param array{timeout: int, retries: int, base_uri: string} $options */ function fetch(string $url, array $options = [], int $timeout = 30): Response { ... }
Write summary docblocks
Blueprint extracts the first paragraph of each class and method docblock (everything before the first @tag or blank line). This becomes the — description in the output. One or two sentences that explain what the method does and when you'd use it:
/** * Atomically write content to a file using a temp-file-and-rename strategy. * * Detailed implementation notes go here — Blueprint ignores * everything after the first blank line or @tag. */ public function dumpFile(string $filename, string $content): void
Document parameters with @param
Blueprint extracts @param descriptions and appends them as inline comments next to each parameter. This is especially valuable for parameters whose purpose isn't obvious from the type alone:
/** * @param int $mode The new file mode (octal, e.g. 0755) * @param bool $recursive Whether to apply recursively to subdirectories */ public function chmod(string $path, int $mode, bool $recursive = false): void
In the blueprint, this becomes:
"chmod(string $path, int $mode /*The new file mode (octal, e.g. 0755)*/, bool $recursive = false /*Whether to apply recursively to subdirectories*/): void"
Declare @throws
Blueprint appends @throws types to method signatures. This tells agents which exceptions to handle:
/** * @throws FileNotFoundException * @throws IOException */ public function copy(string $origin, string $target): void
Use meaningful names
Parameter names appear directly in the blueprint. $baseDirectory communicates more than $dir. $overwriteNewerFiles communicates more than $force. Since the blueprint may be the only context an agent has, every name carries weight.
Use constants and enums
Blueprint extracts constant names and values, and enum cases with their backing values. Well-named constants tell an agent what valid states and options exist:
const STATUS_PENDING = 'pending'; const STATUS_ACTIVE = 'active'; enum Suit: string { case Hearts = 'H'; case Diamonds = 'D'; }
Define clear interfaces
Blueprint captures the full class hierarchy — extends, implements, and uses. Well-defined interfaces and abstract classes give agents the contract to code against without needing to read implementations.
How It Works
Blueprint uses static analysis via BetterReflection (which builds on nikic/php-parser) to extract class signatures. No code is executed — source files are parsed, not loaded. This means:
- No side effects from target code
- No dependency resolution failures
- No PHP version coupling between Blueprint and the target package
- Works on any valid PHP source, even if dependencies aren't installed
Token Efficiency
For LLM context, token efficiency matters:
Full source code: ~50,000 lines, ~2MB
Public API JSON: 1,935 lines, 72KB (97% reduction)
Full API JSON: 2,528 lines, 92KB (95% reduction)
Requirements
- PHP 8.2+
- Composer
Limitations
- Doesn't extract standalone function signatures (only classes/interfaces/traits/enums)
- Docblocks are cleaned but not fully parsed (no structured
@paramextraction beyond inline hints) - Complex constant expressions (runtime-evaluated) are shown as
<expr>rather than resolved values
License
MIT