Configuring Horizon
coollabsio/coolify
A skill your agent uses whenever the user mentions Horizon by name in a Laravel context.
A skill your agent uses when writing, reviewing or modernizing PHP (8.3-8.5) outside Laravel — strict types, union and intersection types, readonly classes, backed enums, property hooks and…
$ npx skills add ericrisco/rsc-harness --skill php -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install ericrisco/rsc-harness php --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/php .claude/skills/php && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "php" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/php into .claude/skills/php/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "php", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/ericrisco/rsc-harness/tree/main/skills/phpType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add ericrisco/rsc-harness --skill php -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install ericrisco/rsc-harness php --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/php .agents/skills/php && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "php" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/php into .agents/skills/php/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "php", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add ericrisco/rsc-harness --skill php -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install ericrisco/rsc-harness php --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/php .cursor/skills/php && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "php" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/php into .cursor/skills/php/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "php", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/ericrisco/rsc-harness.git --path skills/php--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add ericrisco/rsc-harness --skill php -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install ericrisco/rsc-harness php --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/php .gemini/skills/php && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "php" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/php into .gemini/skills/php/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "php", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install ericrisco/rsc-harness phpInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add ericrisco/rsc-harness --skill php -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/php .github/skills/php && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "php" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/php into .github/skills/php/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "php", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add ericrisco/rsc-harness --skill php -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install ericrisco/rsc-harness php --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/ericrisco/rsc-harness.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/php .opencode/skills/php && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "php" agent skill from https://github.com/ericrisco/rsc-harness/tree/main/skills/php into .opencode/skills/php/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "php", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
phpA skill your agent uses when writing, reviewing or modernizing PHP (8.3-8.5) outside Laravel — strict types, union and intersection types, readonly classes, backed enums, property hooks and…
Php is an agent skill from ericrisco/rsc-harness. Use when writing, reviewing or modernizing PHP (8.3-8.5) outside Laravel — strict types, union and intersection types, readonly classes, backed enums, property hooks and asymmetric visibility, the pipe operator and clone-with, Composer with PSR-4, PER-CS style, PSR interop, and the quality toolchain (PHPStan, Pint, Rector, PHPUnit/Pest). NOT Eloquent, Blade or Artisan (that is laravel).
Its SKILL.md is about 4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 8 other files, including scripts and reference files (for example `evals/README.md`, `evals/cases.yaml` and `references/tooling.md`).
It sits in Backend & APIs, covering Backend development. It works with PHP, Laravel and Shopify. The repository describes itself as: Your agent invents things because it has no memory, and can't touch your database because it has no arms. rsc is the meta-harness that gives it both, plus the trade to know the… The licence is MIT.
6 steps, taken from the first numbered list in SKILL.md.
Read from SKILL.md and the folder at commit 92fde8f. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Ships 1 file in scripts/ (Shell), which the agent can run.
Shell commands in SKILL.md call:
composerFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Php loads about 4k tokens when it runs, and up to ~6.8k if it reads all its reference files. Until then it costs about 99 tokens; SKILL.md has 1,204 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); the scripts in this folder are not scanned.
The full file from ericrisco/rsc-harness at commit 92fde8f, republished under its MIT licence (© ericrisco). 1,204 words, ~3,954 tokens.
.claude/skills/php/SKILL.md (or your agent's skills folder). This skill also uses 5 other files; get the full folder from GitHub.Write PHP the way the 2025-2026 ecosystem does: declare(strict_types=1) at the top of
every file, typed everything, Composer-first, statically analyzed at the top level — not
the way a 2015 WordPress plugin did. This skill owns the language and its
framework-agnostic ecosystem: the type system, Composer + PSR-4, PER-CS style, the PSR
interop interfaces, and the quality toolchain.
Version targeting. Floor is 8.3 (security-only, the lowest you should support).
Default new code to 8.4 (property hooks, asymmetric visibility). Use 8.5 features
(|>, clone with, array_first/array_last, #[\NoDiscard]) only when the deploy
runtime is confirmed 8.5+ — 8.5 released 2025-11-20. 7.x and 8.0-8.2 are EOL; never target
them.
.php file or a composer.json.| The ask is about | Route to | This skill keeps |
|---|---|---|
| Eloquent, Blade, Artisan, container bindings, queues | laravel | the PHP underneath Laravel only |
WP hooks, the loop, wp_*, $wpdb | wordpress | nothing WP-specific |
| Shopify app/theme SDK work | shopify | nothing Shopify-specific |
| OWASP threat modeling, authz/abuse review | secure-coding | PHP-native controls (PDO, password_hash, escaping) |
| REST resource naming, status-code contract as a discipline | api-design | PHP request/response code only |
| DB schema/index tuning | mysql / postgresdb | PDO usage from the PHP side |
The type system, Composer, PSR, and the static-analysis toolchain are canonical here and nowhere else in the catalog.
declare(strict_types=1); is the first statement in every .php file. Without it
PHP silently coerces "5" to 5, 1 to true — bugs that type hints exist to stop.mixed you
did not ask for; PHPStan cannot reason about it.require_once chains, no
hand-rolled autoloaders. PSR-0 is deprecated.final by default. Open a class for extension only when you have designed the
extension point. Inheritance you did not plan for is a maintenance bill.composer.lock for applications (reproducible installs); libraries commit it
for dev too but do not ship it in the package.| Tool | Use it for | One-line why |
|---|---|---|
Union A|B | a value that is genuinely one of N types | beats mixed; PHPStan narrows it |
Intersection A&B | a value that must satisfy several interfaces | expresses "Countable and Traversable" without a marker type |
readonly property | a field set once in the constructor | immutability the engine enforces, no manual guard |
readonly class (8.2+) | a whole value object | every property readonly; can only build a changed copy |
| Pure enum | a closed set with no scalar backing | replaces stringly-typed class constants |
Backed enum (: string/: int) | a closed set that maps to a DB/JSON value | from()/tryFrom() give safe parsing |
never return | a function that always throws/exits | tells the analyzer the path is dead |
true/false literal types (8.2+) | a method that only ever returns one | precise contracts |
Nullable ?T | "may be absent" | distinct from "optional argument with a default" |
@template docblock generics | typed collections/containers | PHPStan reads them; the engine does not have native generics |
<?php
declare(strict_types=1);
// Bad: stringly-typed, untyped, mutable, coercible.
class Order {
public $status; // untyped -> mixed
public function setStatus($s) { $this->status = $s; } // accepts anything
}
// Good: backed enum + readonly + typed signatures.
enum OrderStatus: string {
case Pending = 'pending';
case Paid = 'paid';
case Shipped = 'shipped';
public function isFinal(): bool {
return $this === self::Shipped;
}
}
final readonly class Order {
public function __construct(
public string $id,
public OrderStatus $status,
) {}
}
$status = OrderStatus::tryFrom($raw) ?? OrderStatus::Pending; // safe parse, never throws on bad inputGenerics live in docblocks until the engine ships them — PHPStan enforces them:
<?php
declare(strict_types=1);
/**
* @template T
*/
final class Collection {
/** @var list<T> */
private array $items = [];
/** @param T $item */
public function add(mixed $item): void { $this->items[] = $item; }
/** @return list<T> */
public function all(): array { return $this->items; }
}See references/type-system.md for enum-with-interface patterns,
variance, the asymmetric-visibility matrix, and readonly edge cases.
<?php
declare(strict_types=1);
final class PriceCalculator {
// Constructor property promotion: declare + assign in one place.
public function __construct(private readonly TaxRate $rate) {}
public function total(Money $net): Money {
// match (not switch): expression, strict ===, no fall-through, exhaustive-ish.
$multiplier = match ($this->rate->region) {
Region::EU => 1.21,
Region::US => 1.00,
};
return $net->times($multiplier);
}
}
// Named arguments: skip optional params, self-document call sites.
$client = new HttpClient(timeout: 5, retries: 3);
// First-class callable syntax: pass a method as a callable without a closure wrapper.
$ids = array_map($repo->idOf(...), $orders);Rules: promote constructor properties; prefer match over switch; enums over class
constants; immutable DTOs over mutable bags; $fn(...) over Closure::fromCallable.
Property hooks give computed/guarded properties the engine and PHPStan can see — no docblock getters. Asymmetric visibility lets a property be read widely but written narrowly, killing get/set boilerplate.
<?php
declare(strict_types=1);
// Bad: manual getter/setter pair, invisible to static analysis as a "property".
final class Temperature {
private float $celsius = 0.0;
public function getFahrenheit(): float { return $this->celsius * 9 / 5 + 32; }
public function setCelsius(float $c): void {
if ($c < -273.15) { throw new \InvalidArgumentException('below absolute zero'); }
$this->celsius = $c;
}
}
// Good: a computed property hook + a guarded set hook (PHP 8.4+).
final class Temperature {
public float $celsius = 0.0 {
set (float $value) {
if ($value < -273.15) { throw new \InvalidArgumentException('below absolute zero'); }
$this->celsius = $value;
}
}
public float $fahrenheit {
get => $this->celsius * 9 / 5 + 32;
}
}
// Asymmetric visibility: readable everywhere, writable only inside the class.
final class Account {
public function __construct(public private(set) int $balance) {}
public function deposit(int $amount): void { $this->balance += $amount; }
}Trap: keep hooks pure-ish. A get hook that runs a query or mutates state turns a
field access into a hidden side effect. For lazy initialization or I/O, use an explicit
method, not a hook.
Only reach for these when the deploy target is confirmed 8.5+ (released 2025-11-20).
<?php
declare(strict_types=1);
// Bad: deeply nested calls read inside-out.
$result = array_sum(array_filter(array_map(strlen(...), $words), fn($n) => $n > 3));
// Good: pipe operator |> reads left-to-right as a transform pipeline (8.5+).
$result = $words
|> fn($w) => array_map(strlen(...), $w)
|> fn($n) => array_filter($n, fn($x) => $x > 3)
|> array_sum(...);
// clone with: a with-er for readonly objects in one expression (8.5+).
$shipped = clone $order with ['status' => OrderStatus::Shipped];
// array_first / array_last: no more reset()/end() side effects (8.5+).
$head = array_first($items);
$tail = array_last($items);#[\NoDiscard] (8.5+) marks a return value that must be used — the engine warns if a caller
ignores it. Put it on a method whose result is the whole point (a built value, a Result).
my-package/
├── composer.json
├── composer.lock # commit it for apps
├── src/ # PSR-4 root -> namespace App\
├── tests/
└── phpstan.neon{
"name": "acme/my-package",
"type": "library",
"require": {
"php": ">=8.3",
"psr/log": "^3.0"
},
"require-dev": {
"phpstan/phpstan": "^2.1",
"laravel/pint": "^1.18",
"pestphp/pest": "^4.0",
"rector/rector": "^2.0"
},
"autoload": {
"psr-4": { "App\\": "src/" }
},
"autoload-dev": {
"psr-4": { "App\\Tests\\": "tests/" }
},
"scripts": {
"lint": "pint --test",
"stan": "phpstan analyse",
"test": "pest",
"check": ["@lint", "@stan", "@test"]
},
"config": { "sort-packages": true }
}Rules: require = runtime deps, require-dev = tools/tests; the psr-4 map points a
namespace prefix at a base dir (PSR-0 is dead); composer check is your one-shot gate.
<?php
declare(strict_types=1);
// A typed hierarchy lets callers catch by meaning, not by string matching.
abstract class DomainException extends \RuntimeException {}
final class OrderNotFound extends DomainException {}
final class PaymentDeclined extends DomainException {}
try {
$order = $repo->find($id) ?? throw new OrderNotFound("order {$id}");
} catch (PaymentDeclined $e) {
$logger->warning('payment declined', ['order' => $id, 'reason' => $e->getMessage()]);
throw $e; // rethrow; do not swallow
} finally {
$lock->release(); // runs whether or not we threw
}Rules: throw typed exceptions, never bare \Exception; never swallow (no empty catch);
never use the @ error-suppression operator — it hides fatals from the analyzer; clean up
in finally; catch \Throwable only at a process boundary (CLI entry, request handler).
Generic appsec (OWASP, authz, threat modeling) is ../secure-coding/SKILL.md. The PHP-specific controls below stay here.
| Control | API | Why |
|---|---|---|
| Parametrized SQL | PDO prepared statements | the only safe defense against SQLi; never interpolate |
| Password storage | password_hash() / password_verify() | bcrypt/argon2 with per-hash salt; never md5/sha1 |
| Tokens / secrets | random_bytes() / random_int() | cryptographically secure; rand()/mt_rand() are not |
| Output to HTML | htmlspecialchars($s, ENT_QUOTES, 'UTF-8') | stops reflected/stored XSS at the boundary |
unserialize() | ['allowed_classes' => false] | blocks object-injection gadget chains |
| Comparing secrets | hash_equals() | constant-time; === leaks length/timing |
<?php
declare(strict_types=1);
// Bad: string interpolation = SQL injection.
$pdo->query("SELECT * FROM users WHERE email = '{$email}'");
// Good: prepared statement with a bound parameter.
$stmt = $pdo->prepare('SELECT * FROM users WHERE email = :email');
$stmt->execute(['email' => $email]);
$user = $stmt->fetch(\PDO::FETCH_ASSOC);Depend on PSR interfaces, not concrete vendors, so code stays portable:
Psr\Log\LoggerInterface — type-hint this; inject Monolog as the impl.RequestInterface/ResponseInterface — HTTP messages; Guzzle/Nyholm implement them.ContainerInterface — a container contract with get()/has().process(Request, Handler): Response.<?php
declare(strict_types=1);
use Psr\Log\LoggerInterface;
final class Mailer {
public function __construct(private readonly LoggerInterface $log) {} // PSR-3, not "new Monolog"
}level: max (Psalm at max is the alternative) — your type contract.
2.1+ understands 8.4 property hooks.--test/--dry-run in CI.Wire them as Composer scripts (above) so composer check and CI run the same gate. Full
configs — phpstan.neon, pint.json, rector.php, phpunit.xml — are in
references/tooling.md.
| Pattern | Why it is bad | Do instead |
|---|---|---|
| Associative array as a DTO | no types, no autocomplete, typo = silent null | a readonly class or backed enum |
Missing declare(strict_types=1) | silent scalar coercion defeats your type hints | first line of every file |
| Untyped property/param/return | every one is an invisible mixed | type everything; let PHPStan reason |
@ error suppression | hides fatals and warnings from you and the analyzer | handle the error or let it throw |
String-interpolated SQL / mysql_* | SQL injection; mysql_* removed in PHP 7 | PDO prepared statements |
Global state / static mutable singletons | untestable, order-dependent, hidden coupling | constructor injection |
| Fat static "helper" classes | a namespace masquerading as an object; no DI, no mocking | small injected services |
mixed everywhere | abandons the type system you are paying for | precise union/intersection types |
| Manual getter/setter pairs (on 8.4+) | boilerplate the engine can express natively | property hooks / private(set) |
switch with fall-through | accidental fall-through bugs; statement not expression | match (strict, exhaustive) |
readonly/clone with, property-hook edge cases, the
asymmetric-visibility matrix.phpstan.neon, pint.json,
.php-cs-fixer.dist.php, rector.php, phpunit.xml / Pest, composer scripts, CI snippet.© ericrisco, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 5 other files (scripts, references) in skills/php of ericrisco/rsc-harness.
Open the folder on GitHubat commit 92fde8f
Php next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Php this skillericrisco/rsc-harness | 156 | — | ~4k | Automated safety check: Pass | MIT | |
| Configuring Horizoncoollabsio/coolify | 63k | 4 repos | ~898 | Automated safety check: Pass | MIT | |
| Fortify Developmentcoollabsio/coolify | 63k | 4 repos | ~1.9k | Automated safety check: Pass | MIT | |
| Laravel Best Practicesanonaddy/anonaddy | 4.9k | 13 repos | ~1.2k | Automated safety check: Pass | MIT | |
| Geoflowyaojingang/GEOFlow | 3.8k | — | ~722 | Automated safety check: Pass | AGPL-3.0 | |
| Livewire Developmentcoollabsio/coolify | 63k | — | ~964 | Automated safety check: Pass | MIT |
coollabsio/coolify
A skill your agent uses whenever the user mentions Horizon by name in a Laravel context.
coollabsio/coolify
ACTIVATE when the user works on authentication in Laravel. An agent skill from coollabsio/coolify.
anonaddy/anonaddy
Apply this skill whenever writing, reviewing, or refactoring Laravel PHP code.
yaojingang/GEOFlow
Operate/develop GEOFlow CLI/Laravel/admin/API, topics/专题 and topic tasks, theme libraries/replication, sites/leads/Agent, channel sync and legacy yao-geoflow-cli/design/template migration.
coollabsio/coolify
A skill your agent uses for any task or question involving Livewire.
yungifez/skuul
A skill your agent uses for any task or question involving Livewire.
ericrisco/rsc-harness
A skill your agent uses when designing or analyzing a controlled experiment — falsifiable hypothesis, sample size from an MDE, reading significance/CI/power, CUPED, or rescuing tests that won't go…
ericrisco/rsc-harness
A skill your agent uses when making a web UI conform to WCAG 2.2 Level AA — axe-core or Lighthouse a11y violations, keyboard operability, focus management, ARIA roles/names/live regions, contrast…
ericrisco/rsc-harness
A skill your agent uses when running or fixing paid acquisition on Google or Meta — campaign structure (Performance Max, Demand Gen, Search, Advantage+), platform-fit creative, budget/scaling rules…
ericrisco/rsc-harness
A skill your agent uses when measuring whether an LLM or agent system actually got better and gating merges on it: golden sets, fixing an inflated LLM-as-judge, scoring RAG (faithfulness, contextual…
ericrisco/rsc-harness
A skill your agent uses when a creative goal must become a finished media file: pick and order generative-media models per modality — AI voiceover, image-to-video clips, score — then glue them with…
ericrisco/rsc-harness
A skill your agent uses when instrumenting product or web analytics — GA4/PostHog SDK wiring, event taxonomy, funnels, double-counted events, consent gating, PII scrubbing.
Categories
A skill your agent uses when writing, reviewing or modernizing PHP (8.3-8.5) outside Laravel — strict types, union and intersection types, readonly classes, backed enums, property hooks and…. Php is an agent skill from ericrisco/rsc-harness.5) outside Laravel — strict types, union and intersection types, readonly classes, backed enums, property hooks and asymmetric visibility, the pipe operator and clone-with, Composer with PSR-4, PER-CS style, PSR interop, and the quality toolchain (PHPStan, Pint, Rector, PHPUnit/Pest).
Php fits situations like: modernizing PHP (8.3-8; outside Laravel — strict types; union and intersection types; readonly classes.
Run `npx skills add ericrisco/rsc-harness --skill php -a claude-code`. Or copy the skill folder (skills/php in ericrisco/rsc-harness) into .claude/skills/php in your project. Claude Code loads it when a task matches its description.
Run `npx skills add ericrisco/rsc-harness --skill php -a codex`. Or copy the skill folder (skills/php in ericrisco/rsc-harness) into .agents/skills/php in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add ericrisco/rsc-harness --skill php -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/php, .gemini/skills/php, .github/skills/php and .opencode/skills/php in your project.
Going by SKILL.md and its folder, Php needs a shell for the scripts in its folder and the command-line tools its instructions call (composer). Our summary lists: A Bash shell.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. The check reads SKILL.md only: the scripts in the folder are not scanned, so read them before running anything.
Php is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 4k tokens (SKILL.md is roughly 16k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 2.9k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Php: Configuring Horizon (coollabsio/coolify, 63k stars), Fortify Development (coollabsio/coolify, 63k stars), Laravel Best Practices (anonaddy/anonaddy, 4.9k stars) and Geoflow (yaojingang/GEOFlow, 3.8k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
ericrisco (a GitHub user) maintains it in ericrisco/rsc-harness, which has 156 GitHub stars. The repository holds 229 skills in this directory. The repository was last updated on October 6, 2026.
Source: ericrisco/rsc-harness on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.