This file provides shared guidance to Claude Code and Codex when working with this repository. CLAUDE.md imports it; keep the instructions here.
This repository contains plugins for the Nette Framework ecosystem, shared by Claude Code and Codex:
plugins/nette/- For developers building Nette Framework applications (skills only)plugins/nette-lint/- Automatic validation hooks for PHP, Latte, NEON and JavaScript/TypeScriptplugins/nette-dev/- For Nette Framework contributors (coding standards and conventions)plugins/php-fixer/- Optional automatic PHP style fixing using nette/coding-standard
Each plugin contains:
.claude-plugin/plugin.json- Plugin metadata, supported by both clientsskills/- Contextual documentation that activates based on conversation
Some plugins also include:
hooks/- PostToolUse hooks for file validation/fixing (nette-lint,php-fixer)
Duplicated across plugins:
hooks/hook-input.php- Adapts Claude Codetool_input.file_pathand Codexapply_patch(tool_input.command, relative to eventcwd) to the single-file hooks. Direct edits and one-file patches run without a subprocess. Multi-file patches run only matching extensions, preserve the PHP ini, and aggregate errors and rewrite feedback. Do not resolve symlinks when finding per-project configuration. Keep both copies identical;tests/hook-input.phptchecks this.hooks/hook-config.php- Helper required by each plugin's hooks (require __DIR__ . '/hook-config.php'). Reads the project's.nette-claude.jsonand locates project tools/configs viafindUpwards(). Plugins install independently (each into its owncache/<marketplace>/<plugin>/<version>/directory - a siblingshared/folder is NOT copied), so this file is copied into every hook-carrying plugin (nette-lint,php-fixer). Keep the copies in sync.
Enable plugins in development:
# In a project directory, add this repo as a local plugin source
claude --plugin-dir /path-to/agent-plugins/plugins/netteCodex uses the same marketplace and plugin manifests (verified with CLI 0.156.1); do not duplicate them into a second catalog without a demonstrated compatibility need:
codex plugin marketplace add /path-to/agent-plugins
codex plugin add nette@netteFor hook plugins, review and trust their definitions with /hooks. Run the PHP regression suite with php vendor/bin/tester tests -s. docs/compatibility.md records the client checks and their limits.
Standalone PHP scripts run on PostToolUse (Edit|Write, which also matches Codex apply_patch). Shell-based edits are not covered. Each one:
- Reads JSON input from stdin through
readHookFile()inhook-input.php; multi-file patches are dispatched to the same script with individualfile_pathinputs - Checks the file extension and skips non-matching files (exit 0)
- Skips paths excluded in the project's
.nette-claude.jsonviaisExcluded()from the plugin's ownhooks/hook-config.php - Locates its project tool/config (
latte-lint,vendor/bin/neon-lint, ESLint config) viafindUpwards()- searched upwards from the edited file, so monorepo sessions rooted above the app directory work too; the search stops one level above the nearest.gitroot - Runs its tool, then exits 0 on success or exit 2 on error (with stderr output)
Hooks run in parallel and in non-deterministic order, so each must be robust on its own - do not rely on one hook running before another. For example fix-php-style runs php -l itself and silently skips invalid PHP instead of depending on lint-php.
Read exclusively by the hooks, looked up upwards from the edited file (like .gitignore). Each top-level key is a hook name (lint-php, lint-latte, lint-neon, lint-json, lint-js, fix-php-style) with an exclude list of gitignore-like patterns resolved relative to the config directory. lint-json additionally accepts a jsonc list marking extra files as JSONC (comments + trailing commas allowed):
{
"fix-php-style": {
"exclude": ["fixtures*"]
}
}Each skill is a directory containing a SKILL.md file with YAML frontmatter:
---
name: skill-name
description: When to activate this skill (used for contextual matching)
---Detailed reference documentation goes into the references/ subdirectory within each skill.
Keep skill bodies portable between clients. Preserve manual-only installation using Claude Code's disable-model-invocation and Codex's agents/openai.yaml policy. Do not assume a particular shell syntax or client-specific tool name in shared instructions.
Where projects legitimately differ (where secrets live, how the app is deployed), a skill does not prescribe one way: it tells the model to follow the project's existing convention and, when there is none, to offer the user the options. Nette's own conventions (directory structure, database schema, the frontend stack) remain prescriptive.
Both clients use the marketplace configuration in .claude-plugin/marketplace.json. Claude Code users install with:
/plugin marketplace add nette/agent-plugins
/plugin install nette@nette
Codex users run codex plugin marketplace add nette/agent-plugins and codex plugin add nette@nette. Bump versions in the manifests of changed plugins before release so cached installations can be refreshed.