Imported from netresearch/php-ast-edit-skill (
AGENTS.md). Install upstream withnpx skills add netresearch/php-ast-edit-skill. Copyright stays with the author.
AGENTS.md — php-ast-edit-skill
PHP CLI plus Agent Skill for AST-native PHP source mutations.
Repo Structure
.
├── skills/php-structured-edit/
│ ├── SKILL.md # Agent runtime instructions
│ ├── agents/openai.yaml # OpenAI-style agent descriptor
│ ├── evals/evals.json # Outcome evals; eval_queries.json tests routing
│ ├── references/operations.md # Edit schema, parseAs contexts, operation catalog
│ ├── references/enforcement.md # PreToolUse gate wiring
│ └── scripts/php-ast-edit # Wrapper: repo bin, vendor/bin, PHAR, or PATH
├── src/
│ ├── MethodRenameCommand.php # Named method intent → unique guarded declaration
│ ├── Application.php # CLI dispatch (inspect, apply, validate, contexts, help)
│ ├── Editor.php # Transaction engine, primitives and convenience ops
│ ├── CanonicalPrinter.php # Width-aware canonical printing
│ ├── RepositoryConfig.php # Canonical, formatter and verification settings
│ ├── EditorConfig.php # max_line_length — the project's own declaration
│ ├── Formatter.php # format / normalize over a tree
│ ├── AtomicWriter.php # temp file + rename, symlink-aware
│ ├── Doctor.php # Is the repository set up for the contract?
│ ├── FileTransaction.php # One file's state through the transaction phases
│ ├── FileRestorer.php # Restore bytes, modes and symlink identity on failure
│ ├── EditReport.php # Per-file effects, warnings and validation status
│ ├── PhpLint.php # Host-runtime compile check without executing source
│ ├── RenameVariable.php # Lexical scope and collision preflight
│ ├── RenameMethod.php # Conservative method dispatch and collision checks
│ ├── NodeLocator.php # Position → AST ancestry; ref → node
│ ├── NodeLocation.php # Container mutation: replace, delete, insert_into
│ ├── ContextParser.php # Snippet → AST via synthetic host contexts
│ ├── SnippetParser.php # Deprecated facade over ContextParser
│ └── Exception/EditException.php # Typed failure
├── bin/php-ast-edit # CLI entrypoint
├── hooks/php-ast-only.py # PreToolUse gate: no text mutation of .php
├── scripts/
│ ├── check.php # php -l over every shipped PHP file
│ ├── build-phar.php # Package a runtime-only Composer installation
│ └── build-release.sh # Isolated production build and executable archives
├── tests/
│ ├── run.sh # Test entrypoint (syntax gate, round-trip, matrix, CLI)
│ ├── run.php # Inspect/apply integration test
│ ├── matrix.php # Table-driven grammar and failure-mode matrix
│ ├── renames.php # Binding collisions and dispatch boundaries
│ ├── transactions.php # Configuration, guards, rollback, validation reports
│ ├── distribution.sh # Clean consumer installs and extracted archives
│ ├── distribution.php # PHAR contents and runtime dependency assertions
│ ├── cli.sh # CLI surface: arguments, output fields, exit codes
│ ├── catalog.php # Dispatcher, `contexts` output and docs must agree
│ ├── formatting.php # Printer width, printer choice, fallback, doctor
│ ├── php-floor.php # Dereferenced `new` needs parentheses below PHP 8.4
│ ├── corpus.php # Round trip over php-parser's own source
│ ├── hook.py # Enforcement gate behaviour table
│ └── fixtures/sample.php # Fixture for the round-trip
├── plugin.json # Portable Agent Plugins 1.0.0 manifest (source of truth)
├── .claude-plugin/plugin.json # Generated Claude Code manifest
├── composer.json # PHP distribution
├── benchmarks/ # Reproducible CLI samples and agent outcome oracles
├── docs/ # Executable quickstart, installation, FAQ and limits
├── .github/workflows/ # Shared skill gates and local engine/distribution gates
└── README.md
Commands
composer install— installnikic/php-parser; required for every parsing commandbash tests/run.sh— full runtime suite, executable docs, task oracles, clean install and artifact checksbash tests/run.sh --runtime-only— omit the separately matrix-tested distribution suitecomposer cgl— canonical print plus the project's formatting rules; run before committing PHPphp scripts/check.php—php -loversrc/and the named entrypoints inbin/,scripts/andtests/bash scripts/build-release.sh— builddist/releases/with isolated production dependencies; output directory must be emptybin/php-ast-edit inspect --file <path> --line <n> --column <n>— AST ancestry at a positionbin/php-ast-edit apply --input edits.json— guarded transaction; exit 1 retains edits when project checks failbin/php-ast-edit rename --method Class::old --to new— discover the declaration and run one guarded rename with project callers and checksbin/php-ast-edit validate --file <path>— parse and host PHP lint; check explicit skip status for newer target syntaxbin/php-ast-edit contexts --operation rename_variable— the contract for one operationbin/php-ast-edit doctor— canonical-mode setup diagnostics; ordinary edits support format preservationbin/php-ast-edit normalize— optional canonical print plus declaration; width comes from.editorconfigbin/php-ast-edit format— canonical print onlybash docs/quickstart.sh— the documented first edit, checked at runtimepython3 benchmarks/agent_benchmark.py self-test— task oracles and imported evidence validation; no model callsphp tests/matrix.php— grammar and operation coverage matrix on its ownbash tests/cli.sh— CLI arguments, output fields and exit codesphp tests/catalog.php— operation and context catalog parity across code, CLI and docsphp tests/corpus.php— print-and-reparse fidelity over 270 real filesphp tests/formatting.php— printer width, printer choice, the fallback, doctorphp tests/php-floor.php— the one version-dependent construct that has broken CI twice (new X()->y()below PHP 8.4); it is not a general compatibility check, for which the floor interpreter has to runpython3 tests/hook.py— what the enforcement gate denies and allows
Rules
- Any creation, modification, replacement, deletion or movement of PHP syntax goes through
bin/php-ast-edit— neversed, regex, raw string replacement,apply_patch, or writing a.phpfile directly. Never fall back to text mutation when an AST operation looks unsupported: the primitives (replace_node,delete_node,insert_into,replace_child,delete_child,move_node) plus theparseAscontexts reach every construct, andmode: create/mode: deletecover the file lifecycle. This repository's own source is subject to the rule it ships.hooks/php-ast-only.pyenforces it before the write for harnesses that supportPreToolUse. Automated tests and benchmarks may create, reset, or patch disposable fixtures in a temporary directory, including deliberately invalid PHP and contextual-patch baselines. This exception never permits text edits to tracked PHP implementation or test source. It makes parser failures and fair alternative-tool comparisons testable. plugin.jsonat the repo root is the source of truth. After changing it, regenerate the Claude manifest — never hand-edit.claude-plugin/plugin.json.composer.jsonnamemust equal the GitHub repository name (netresearch/php-ast-edit-skill); the skill validator fails otherwise.- No
composer.lock— this is a library plus skill package, not an application. 4b. This repository is on the canonical fixed point..php-ast-edit.jsondeclares it,.php-cs-fixer.phpcarries the token-level rules, and.github/workflows/formatting.ymlgates it. Before committing PHP:composer cgl— that isphp-ast-edit formatfollowed byphp-cs-fixer fix. Neither half is a check on its own; the clean tree is.tests/fixtures/is excluded on purpose: a fixture exists to be code the printer has not seen. - Version lives in
plugin.jsonand is mirrored into.claude-plugin/plugin.json; both must agree before a tag. - Bump the version only in a PR, tag only after that PR merges.
- Every
references/*.mdstays reachable fromSKILL.md— orphaned reference files fail the audit. SKILL.mdbody stays under 500 lines (warning past 300) — the limitskill-repo-skill'svalidate-skill.shactually enforces; detail belongs inreferences/.- A
doctorobservation that no run of this tool can fix goes beside the findings, never among them.statusanswers one question — is this repository set up for the contract — and every entry infindingsflips it towarn. Something the repository cannot change by runningnormalize,formatorapplyis therefore a field of its own with its own advice, the wayresolverandoverWidthare. Reported as a finding it would call a correctly-prepared repository unprepared: this repository itself carries hundreds of lines over its own declared width — runbin/php-ast-edit doctor --path .for today's count — and isready, which is the truth. The rule is easy to break because a finding is the obvious place to put something worth saying — an earlier draft ofoverWidthdid exactly that and flipped a fixture fromreadytowarn;tests/formatting.phpcatches it.
CI
| Workflow | Source |
|---|---|
validate.yml, pr-quality.yml, harness-verify.yml, eval-validate.yml, tests.yml |
netresearch/skill-repo-skill reusables |
auto-merge-deps.yml |
netresearch/.github reusable |
formatting.yml |
repo-local — the two-step canonical gate |
php-tests.yml |
repo-local — the reusable runs one PHP version; this carries the 8.2/8.3/8.4/8.5 matrix |
distribution.yml |
repo-local — clean Composer installations and executable artifacts on PHP 8.2 and 8.5 |
release.yml |
repo-local — build and test executable artifacts before signing and publishing those exact bytes |
The local release workflow is an explicit engine-packaging exception to the generic skill-only reusable: the reusable has no pre-package runtime build hook. It retains annotated signed-tag verification, checksums, Cosign verification and provenance, and publishes only after the exact artifacts pass installation tests. Return to the reusable when it supports this build/test contract.
The repository's default GITHUB_TOKEN is read-only, so every caller job declares its own permissions: block matching what the reusable requires. A caller without one fails at startup with no logs.
References
- SKILL.md — agent runtime instructions and workflow
- operations.md — edit schema, targets, guards, parseAs contexts, operation catalog
- formatting-contract.md — the precondition, the tools that can and cannot canonicalise, the fallback
- enforcement.md — wiring the PreToolUse gate
- README.md — installation, usage, transaction safety
- installation.md — source, Composer and executable release installations
- benchmarks — fair comparison protocol and evidence requirements
- skill invocation — whether the model reaches for the skill at all
- CHANGELOG.md — released versions