opencode-wp-settings
AGENTS.md4 starsChanged 3 days agoMITView on GitHub
Coding standards and guardrails for AI-assisted WordPress development — enterprise-grade plugins and classic themes, no vibe coding. Works with OpenCode, Claude Code, Codex, Cursor, Copilot, Windsurf, and any AGENTS.md-compatible tool. Make the codebase legible to agents. Written-down conventions, skills, and rules are the debt you owe your human engineers; every entry pays it down for both audiences at once. WordPress specifics: we ship production code that survives Theme Review and Plugin Review, works on PHP 8.2+, respects the plugin/theme contract…
- Reads credentials
- Commits and pushes
Where files are headingNew AGENTS.md files have more rules about keeping secrets out of the code, and fewer about code style.
Of the AGENTS.md files we read, the 31,439 first seen in the last six months, against the older ones: the kind of rule that gained most share, and the kind that lost most. About files like this in general, not this one, and an estimate, since a kind is a pattern in the words.
In this repository44 other files it gives its agents.
- diagnosing-bugsSkill
- domain-modelingSkill
- fixSkill
- frontend-designSkill
- grill-meSkill
- grill-with-docsSkill
- gsap-coreSkill
- gsap-performanceSkill
- gsap-pluginsSkill
- gsap-scrolltriggerSkill
- gsap-timelineSkill
- gsap-utilsSkill
- handoffSkill
- landing-page-conversion-auditSkill
- refactorSkill
- researchSkill
- reviewSkill
- share-learningSkill
- tddSkill
- threejs-animationSkill
- threejs-fundamentalsSkill
- threejs-geometrySkill
- threejs-interactionSkill
- threejs-lightingSkill
- threejs-loadersSkill
- threejs-materialsSkill
- threejs-postprocessingSkill
- threejs-shadersSkill
- threejs-texturesSkill
- to-specSkill
- to-ticketsSkill
- verifySkill
- wp-accessibilitySkill
- wp-accessibility-standardsSkill
- wp-css-standardsSkill
- wp-github-actions-standardsSkill
- wp-html-standardsSkill
- wp-i18nSkill
- wp-js-standardsSkill
- wp-performanceSkill
- wp-php-standardsSkill
- wp-pluginSkill
- wp-security-auditSkill
- wp-themeSkill
The file
Show its rules and text
We split this AGENTS.md into the rules it gives an agent
44 rules. About 0 are common, 30 are distinctive, and 14 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈30
Distinctive · estimate
This author's own choices. Worth a look.
14
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- could be automatic: a setting could enforce it
- Distinctive: line 37
Do not over-engineer the workflow.
- Distinctive: line 68
Default to deletion over addition, boring over clever, fewest files possible.
- Distinctive: line 83
If an approach fails after 2 attempts, STOP:
- Distinctive: line 87
Ask which direction to take
- Distinctive: line 89
Never burn 6+ attempts on the same strategy.
- Distinctive: line 93
When fixing a bug, stay confined to files directly related to the bug:
- Distinctive: line 95
Don't refactor adjacent code "while you're in there"
- Distinctive: line 96
Don't upgrade dependencies as part of a bug fix
- Distinctive: line 97
Don't touch files outside the immediate blast radius
- Distinctive: line 102
When the complete version of the thing you're already building costs minutes more than the shortcut, do the complete thing — every edge …
- Distinctive: line 110
Run the verification chain after any fix and confirm it passes before moving on.
- Distinctive: line 133
When you can't tell which case it is, treat it as a regression and stop to confirm.
- Distinctive: line 138
NEVER fabricate output from Lighthouse, bundle-size tools, performance profilers, test runners, or build systems.
- Very specific: line 152
Before committing a fix, you must be able to name the specific cause in one sentence.
- Distinctive: line 167
Default to surfacing uncertainty — the cheapest bugs to fix are the ones the user hears about before they ship.
- Distinctive: line 172
When two existing patterns contradict (two escaping styles, two query patterns, two enqueue strategies), pick one — usually the more recent …
- Distinctive: line 178
After any compaction or context reset, before continuing work:
- Distinctive: line 182
Run git diff --stat to see what's changed
- Distinctive: line 183
Only then continue implementation
- Distinctive: line 187
When investigating code (auditing, reviewing, exploring), use neutral prompts that don't bias toward a specific outcome: "analyze the logic …
- Very specific: line 193
When you encounter a TODO, FIXME, or HACK comment, implement it — don't delete it.
- Distinctive: line 205
Before upgrading major dependencies, check for breaking changes (Context7 MCP first).
- Distinctive: line 218
When given a bug report, fix it immediately.
- Very specific: line 225
Default stack for Snoozle Studio WordPress work.
- Very specific: line 269
Always check latest version before installing: npm info <package> / composer show.
- Very specific: line 313
SQL: never concatenate values into SQL — always $wpdb->prepare() with unquoted %s/%d/%f/%i placeholders.
- Very specific: line 323
Never commit secrets; no API keys in code.
- Very specific: line 327
Every user-facing string passes through a translation function with the text domain as the LAST argument: __( 'Text', 'domain' ), …
- Very specific: line 337
Use core hook timing correctly: after_setup_theme (theme setup), init (CPTs, rewrites), wp_enqueue_scripts, admin_enqueue_scripts, …
- Very specific: line 378
Use h-dvh not h-screen; touch targets ≥ 44×44px.
- Very specific: line 395
Never commit node_modules, dist/, .env, or local DB dumps
- Distinctive: line 399
No AI fingerprints in git history, PRs, or descriptions.
- Distinctive: line 403
Commit messages: conventional format, nothing else
- Very specific: line 436
Verification: run /docs-check (inventory vs filesystem drift) or /audit pass 3 before committing documentation-affecting changes to this …
- Very specific: line 448
Check latest version (npm info <package>, composer show)
- Distinctive: line 449
Verify it plays well with WordPress enqueueing (no global jQuery assumptions)
- Distinctive: line 457
When a tool returns output exceeding ~2000 tokens (large search results, verbose logs), write it to a scratch file and return a summary …
- Distinctive: line 463
Place critical information at the beginning and end of context.
- Distinctive: line 479
Use this table to decide where a piece of knowledge belongs:
- Distinctive: line 490
Rule of thumb: if another project's agent would benefit from knowing it, record it in the learnings log.
- Distinctive: line 496
After completing a session, if you hit a non-obvious bug, discovered a useful pattern, or found an edge case, append a dated entry to the …
- Distinctive: line 506
Keep entries terse and factual — one line each.
- Very specific: line 583
After any config-rewrite commit, git-diff the mcp block for enabled: false regressions.
- Very specific: line 600
Keep vendored skills text — npx skills update refreshes normalize on git add.
≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
WordPress Enterprise Engineering — Snoozle Studio
Coding standards and guardrails for AI-assisted WordPress development — enterprise-grade plugins and classic themes, no vibe coding. Works with OpenCode, Claude Code, Codex, Cursor, Copilot, Windsurf, and any AGENTS.md-compatible tool.
Philosophy
Make the codebase legible to agents. Written-down conventions, skills, and rules are the debt you owe your human engineers; every entry pays it down for both audiences at once.
WordPress specifics: we ship production code that survives Theme Review and Plugin Review, works on PHP 8.2+, respects the plugin/theme contract (hooks, escaping, i18n, a11y, perf), and never leaks unescaped output, raw SQL, or missing capability checks.
Compatibility
This repo targets OpenCode v1 — tested with OpenCode 1.19.5 and
@opencode-ai/plugin 1.18.33. The config shape, plugin export contract, and
instructions resolution are v1 behavior. OpenCode v2 has a different surface;
migrate deliberately. The AGENTS.md standards themselves stay portable.
Getting Started
- Read this file — it's the baseline for how we work
- Use your tools naturally — read files, search code, run builds directly
- Delegate when triggered — multi-file exploration, security-sensitive code, and verification MUST go to subagents; don't reason your way out of it
- Learn the guardrails — they exist because we hit every one of these problems
Do not over-engineer the workflow. Start simple, add complexity only when you feel friction.
Response Calibration
Match output length to what was asked: a lookup gets a sentence and a file:line, a
multi-file change gets a brief plan and a short summary of what landed. Lead with the
answer; skip the preamble announcing what you're about to do and the recap restating the diff.
Number multi-step work as it proceeds; restate progress each turn. No AI fingerprints in commits, PRs, or descriptions — ever (see Git).
Guardrails
These rules exist because we've seen them violated repeatedly. Non-negotiable.
Laziness Ladder (Before Writing Code)
The best code is the code you don't write. Before generating anything, stop at the first rung that holds:
- Does this need to exist? — if no, skip it (YAGNI). Question the request before solving it.
- Does this codebase already do it? — reuse it; extend before you re-create.
- Does WordPress core already do it? — use it. There is a WP function for almost everything.
- Does an already-installed dependency solve it? — use it; don't add a new one.
- Can it be one line? — make it one line.
- Only then — write the minimum that works.
Default to deletion over addition, boring over clever, fewest files possible. No abstractions, dependencies, or boilerplate nobody asked for.
Lazy, not negligent. The ladder never applies to trust-boundary/input validation, error handling that prevents data loss, security, accessibility, i18n, or anything explicitly requested — those are always built in full.
Read Before Edit
Never change code you haven't read. Research the codebase before editing — open the file, trace the callers, understand the context. Edit-first behavior produces shallow fixes and regressions.
2-Iteration Limit
If an approach fails after 2 attempts, STOP:
- Summarize what you tried and why it failed
- Present 2-3 alternative approaches with trade-offs
- Ask which direction to take
Never burn 6+ attempts on the same strategy. Fail fast, pivot deliberately.
Bug Fix Scope
When fixing a bug, stay confined to files directly related to the bug:
- Don't refactor adjacent code "while you're in there"
- Don't upgrade dependencies as part of a bug fix
- Don't touch files outside the immediate blast radius
- A bug fix PR should be reviewable in under 2 minutes
Completeness Is Cheap
When the complete version of the thing you're already building costs minutes more than the shortcut, do the complete thing — every edge case, error path, and security check. Bounded by scope: finish the unit you're deliberately touching; flag adjacent systems as out of scope. The ladder decides whether to build; completeness decides how thoroughly to finish what you've decided to build.
Verify After Every Fix
Run the verification chain after any fix and confirm it passes before moving on. Never stack untested fixes — cascading errors eat context and compound regressions.
Pre-Commit Verification Chain (WordPress)
Never commit code that fails the verification chain. The chain — build →
format:all:check → phpcs → phpstan, in order, stopping at the first red — is defined
once in docs/verification-chain.md. Run it and fix what
it surfaces before committing — not after. The
proof-of-work plugin gates git commit/git push on these checks; never bypass it.
The gate is scoped to the session directory: git -C <repo> is honored, cd-style
command chains are exempt (use git -C to gate another repo explicitly).
Failing Tests: Regression vs. Contract Change
A failing check after your change is a fork in the road:
- Regression — the assertion still describes correct behavior and your change broke it. Fix the code, never relax the check to go green.
- Intentional contract change — the requirement explicitly supersedes it. Update implementation and assertion together in the same diff, and say which contract changed and why.
When you can't tell which case it is, treat it as a regression and stop to confirm. A green suite that blesses wrong behavior is worse than a red one that caught it.
Never Fake Measurements
NEVER fabricate output from Lighthouse, bundle-size tools, performance profilers, test runners, or build systems. If you can't run a tool, say so.
Visual/Spatial Honesty
For WebGL, canvas, complex animations, or sub-pixel rendering — acknowledge limitations
upfront. Provide best-effort with clear TODOs, and suggest the user validate visually in
the browser (WordPress context: npm run dev + browser; PHP changes need a reload).
For CSS/visual bugs: if a fix doesn't work after 2 attempts, propose 3 fundamentally different approaches and let the user pick.
Name the Cause
Before committing a fix, you must be able to name the specific cause in one sentence. If you can't, you have a guess, not a cause. Especially true for CSS and viewport bugs (Lenis/ScrollTrigger/fixed-element interactions). If the sentence requires "I think" or "maybe," gather more signal — screenshot the broken element, inspect computed styles — before editing.
Fail Loud
"Done" is wrong if anything was skipped, mocked, or unverified. State it explicitly when:
- A check was skipped or relaxed
- A feature was implemented but not exercised end-to-end (e.g. UI shipped without browser verification)
- A claim relies on a tool, command, or service you didn't actually run
Default to surfacing uncertainty — the cheapest bugs to fix are the ones the user hears about before they ship.
Surface Conflicts, Don't Average
When two existing patterns contradict (two escaping styles, two query patterns, two enqueue strategies), pick one — usually the more recent or more tested — and flag the other for follow-up cleanup. Do not write code that satisfies both.
Post-Compaction Recovery
After any compaction or context reset, before continuing work:
- Re-read the task plan (todo, plan file, or issue)
- Re-read the files you're actively modifying
- Run
git diff --statto see what's changed - Only then continue implementation
Neutral Exploration
When investigating code (auditing, reviewing, exploring), use neutral prompts that don't bias toward a specific outcome: "analyze the logic and report all findings" — not "find the bug". Biased prompts cause agents to manufacture issues that don't exist.
TODO Comments Are Instructions
When you encounter a TODO, FIXME, or HACK comment, implement it — don't delete
it. Removing a TODO without doing the work is marking your own homework complete by
erasing the assignment.
Plan Before Multi-File Changes
Once a change is broad enough that a wrong approach would mean a full rollback, state the plan before executing it — which files you'll touch and what could break. State it, don't ask permission for it; reversible in-scope work still proceeds without approval.
Dependency Upgrades
Before upgrading major dependencies, check for breaking changes (Context7 MCP first). If an upgrade breaks the build, rollback immediately to the working version. Rollback first, research the migration, then try again with a plan. Never upgrade dependencies as part of a bug fix.
Recommend, Don't Override
You recommend; the user decides. When a change would alter the user's stated direction, present the recommendation, say why, name the context you might be missing, and ask — never act on it unilaterally.
Bug Reports
When given a bug report, fix it immediately. No "should I?" questions. If something goes sideways, stop and re-plan — don't keep pushing.
Tech Stack
Default stack for Snoozle Studio WordPress work. Framework depth lives in the
wp-plugin / wp-theme skills and docs/.
Core
- WordPress 6.8+ (7.0 verified) — classic themes and plugins (not block themes unless asked)
- PHP 8.2+ — typed where possible, PHP 8.0+ compatible syntax
- ACF Pro — field groups, option pages,
acf-json/sync - Composer — dev tooling only (WPCS, Pint, stubs)
Front-End Build
- Vite 8 (Rolldown) — build tool;
baseset to the theme/plugindist/URL,build.manifest: true, code-splitting viarolldownOptions - Tailwind CSS v4 — CSS-first config:
@import "tailwindcss",@themetokens in CSS, notailwind.config.js - Prettier +
prettier-plugin-tailwindcss— JS/CSS/JSON formatting
Animation & Graphics
- Lenis — smooth scroll (
autoRaf: false, driven by Tempus,data-lenis-preventfor nested scrollables) - Tempus — single rAF manager (
order: -1producers,order: 1renders) - GSAP — complex animations;
gsap.context()+revert()for cleanup;gsap.matchMedia()for reduced-motion - Three.js — WebGL (dynamic
import()chunks, dispose everything) - swup — optional page transitions; re-init/destroy all libs on
content:replace
Quality
- WPCS 3.0 —
phpcs.xmlwithWordPress-Extra+WordPress-Docs+PHPCompatibility(testVersion8.2-) + the two WPCS 3.x opt-ins:WordPress.Security.ValidatedSanitizedInputandWordPress.NamingConventions.PrefixAllGlobalswith theprefixesproperty (≥4 chars — neverref="Universal"wholesale) - Laravel Pint — PHP formatter
- PHPStan —
phpstan.neonat level 8 withszepeviktor/phpstan-wordpress(WP globals/functions stubs); theme neon scansphp-stubs/acf-pro-stubs - ESLint +
@wordpress/eslint-plugin(flat config) — JS standard lint gate; rides insideformat:all:check;.prettierrcshipsuseTabs: true(WP JS/CSS/HTML standards mandate tabs) - Husky — pre-commit gate (build + format + lint + phpcs + phpstan)
- PHPUnit/wp-env — not standard; lint + build is the proof-of-work
Always check latest version before installing: npm info <package> / composer show.
WordPress Coding Standards (Non-Negotiable)
Full reference in docs/wordpress-php-standards.md. Load it when writing or reviewing PHP.
Standards questions route to the six standards skills — wp-php-standards,
wp-js-standards, wp-css-standards, wp-html-standards,
wp-accessibility-standards, wp-github-actions-standards (each distilled from the
official developer.wordpress.org pages; the PHP skill owns the deep doc).
The standards are mandatory for Core, recommended for themes/plugins; third-party
libraries are exempt.
The summary that must never be violated:
Naming & Structure
- Functions: lowercase
snake_case, always prefixed with the project prefix (≥4 chars, e.g.snoozle_,mytheme_) — neverwp_,__, or_prefixes - Classes:
Class_Namewith underscores, one class per file, file namedclass-{class-name}.php; namespacePrefix\Module\Sub_Module(uppercase words, underscores);wp/WordPressnamespace reserved for core - Constants:
ALL_CAPS_WITH_UNDERSCORES - File names: lowercase, hyphens; text domain matches slug with dashes
- Global variables, options, transients, hook names: ALL prefixed
Syntax
- Tabs for indentation (never spaces); spaces around operators and inside control structure parens
- Long array syntax
array( ... )— short[ ... ]is prohibited by WPCS - Yoda conditions for
==/!=/===/!==(constant on left) - Braces always used,
elseifneverelse if, noextract()/eval()/create_function() - Single quotes unless interpolating; no
@error suppression; no closures as action/filter callbacks (they can't be removed)
Security (escape at output, never at store)
- Escaping matrix (see
docs/wordpress-security.md):esc_html()(text),esc_attr()(attributes),esc_url()(URLs — neveresc_attr( $url )),esc_textarea(),wp_kses_post()(trusted-HTML content),esc_html_e()/esc_attr_e()for i18n - Sanitize input:
sanitize_text_field(),absint(),sanitize_email(),sanitize_key(),sanitize_title()— alwayswp_unslash()request data FIRST, then sanitize; validate before sanitize (safelists,in_array( $x, $allowed, true )) - SQL: never concatenate values into SQL — always
$wpdb->prepare()with unquoted%s/%d/%f/%iplaceholders; prefer WP APIs (get_post_meta,WP_Query) over raw SQL - CSRF:
wp_nonce_field()/wp_nonce_url()/wp_create_nonce()on every state-changing form; verify withcheck_admin_referer(),check_ajax_referer(),wp_verify_nonce(); nonce action strings as specific as possible (include IDs) - Authorization: nonces are NOT authorization — always pair with
current_user_can( 'capability' );is_admin()is not an auth check - File guards:
if ( ! defined( 'ABSPATH' ) ) { exit; }at the top of every file with top-level code;uninstall.phpguarded byWP_UNINSTALL_PLUGIN - Redirects:
wp_safe_redirect()for user-influenced URLs - Never commit secrets; no API keys in code; use
wp-config.phpconstants or env vars
i18n (translation-ready, always)
- Every user-facing string passes through a translation function with the text domain as
the LAST argument:
__( 'Text', 'domain' ),esc_html_e( 'Text', 'domain' ) - Escape + translate for attributes:
esc_attr__()/esc_attr_e(); no raw__()in HTML - Numbered placeholders with translators comments:
/* translators: %s: Name */ load_theme_textdomain()/load_plugin_textdomain()wired on the right hook
Hooks
- Custom hook names prefixed (
snoozle_), documented with full DocBlock abovedo_action()/apply_filters(); filters have no side effects - Use core hook timing correctly:
after_setup_theme(theme setup),init(CPTs, rewrites),wp_enqueue_scripts,admin_enqueue_scripts,plugins_loaded,rest_api_init,register_activation_hook/deactivation/uninstall
Data
- Options API with
autoload: falsefor anything large/rarely used; Transients for cached computed data - REST routes:
permission_callbackrequired for non-public data,sanitize_callbackvalidate_callbackper arg,WP_Errorwith machine-readable codes +status
- Activation: set defaults, register CPTs,
flush_rewrite_rules(). Deactivation: clear temp data, flush rewrites. Deactivation is NOT uninstall — permanent data removal only inuninstall.php
Front-End Standards
Full reference in docs/frontend-stack.md. Load it when writing or reviewing JS/CSS.
JavaScript
- ES modules,
const/let(novar), no jQuery - Component pattern: an init function guarded by element existence, Tempus-driven rAF,
prefers-reduced-motiongate, and a cleanup function returned for teardown (Lenis.destroy(),gsap.context().revert(), Tempus unsubscribe, Three.jsdispose()) - Heavy work lazy: dynamic
import()chunks (Three.js, QR), IntersectionObserver-based init, frame-budget checks viaTempusstate.budget - GSAP: wrap all animations in
gsap.context()scoped to the component; animate onlytransform/opacity; nowill-change: transformon ancestors ofposition: fixed - Lenis:
new Lenis({ autoRaf: false })+Tempus.add(({ time }) => lenis.raf(time), { order: -1 });lenis.on('scroll', ScrollTrigger.update);data-lenis-preventfor nested scrollables; gate whole init behind reduced-motion - ScrollTrigger:
ScrollTrigger.refresh()after fonts/images/DOM changes; never animate apinped element itself
CSS
- Tailwind v4 CSS-first: tokens in
@theme,@sourcefor PHP template dirs if auto-detection misses them, custom utilities via@utility - Fonts:
@font-facewithfont-display: swap, local woff2,unicode-rangesubsets - Use
h-dvhnoth-screen; touch targets ≥ 44×44px; contrast ≥ 4.5:1; honorprefers-reduced-motion; relative units; no* { transition: all }
Accessibility (WCAG 2.2 AA)
- Skip link first in body (
wp_body_open()), visible on keyboard focus - Semantic elements: no
<div onClick>;aria-labelon icon-only buttons; labels on all inputs (placeholder is NOT a label);aria-current="page"on active nav; focus styles never removed without a more visible replacement; content usable with JS disabled - Images: descriptive
alt(decorative:alt=""oraria-hidden)
Git
- Conventional commits:
feat:,fix:,refactor:,docs:,chore:,perf:,style:,test: - Small, atomic commits; never force push to
main - Never commit
node_modules,dist/,.env, or local DB dumps
Stealth Mode (Mandatory)
No AI fingerprints in git history, PRs, or descriptions. Ever.
- No
Co-Authored-Bylines mentioning any AI - No "Generated with AI", robot emoji, or "automated by" language
- Commit messages: conventional format, nothing else
Documentation Contract (This Repo)
Every change to THIS repo (agents/, skills/, commands/, plugins/, templates/, scripts/, .github/workflows/, opencode.json, tui.json, setup.ps1, scaffold.cmd, scaffold.sh) must update the documentation in the same change. A change without its doc sync is incomplete — do not report it done.
Documentation lives in: README.md (front door), docs/README.md (hub + inventory),
docs/guide-beginners.md (Level 1), docs/guide-pro.md (Level 2),
docs/guide-advanced.md (Level 3), and the reference docs in docs/. The full
contract with per-component targets: docs/README.md
"Documentation Contract".
Mandatory sync targets (summary):
| Changed | Also update |
| agent / skill | its description frontmatter (the routing table) + hub inventory row |
| command | its description + hub inventory row + guide examples that use it |
| plugin | its docblock + hub inventory row + guide-pro § Plugins |
| template | hub inventory row + guide-pro § Templates + scaffolder agent if flow changed |
| setup.ps1 / scaffold.cmd / scaffold.sh | hub scripts table + README scaffolding section + guide-pro § Scaffolding |
| opencode.json / tui.json | README "What's inside" + guide-pro § Permissions/MCP |
| anything user-facing | Level 1 guide examples (they must not lie) |
New components are not done until listed in: the hub inventory, README "What's inside" (and skills/commands indexes), and a guide if a human invokes it.
Verification: run /docs-check (inventory vs filesystem drift) or /audit pass 3
before committing documentation-affecting changes to this repo. Drift is a finding,
not a nit. setup.ps1 -Validate additionally enforces frontmatter/name rules.
External Libraries
Search before building — does WP core, an installed dependency, or a one-liner cover it? Before implementing with any external library:
- Fetch current docs via Context7 MCP — don't assume API knowledge
- Check latest version (
npm info <package>,composer show) - Verify it plays well with WordPress enqueueing (no global jQuery assumptions)
Context Hygiene
Tool Output Offloading
When a tool returns output exceeding ~2000 tokens (large search results, verbose logs), write it to a scratch file and return a summary with the file path instead of carrying the full output in context.
Information Placement
Place critical information at the beginning and end of context. The middle receives less attention (lost-in-middle effect).
Documentation Loading
opencode.json loads ~/.config/opencode/docs/README.md as ambient instructions.
That file is the index, not the full reference set: every other doc under
~/.config/opencode/docs/ is linked from it. Read the specific doc a task needs
on demand — do not preload the whole docs/ tree. Resolve the hub's relative
links against ~/.config/opencode/docs/, and treat a loaded doc as mandatory
guidance for that task.
Knowledge Routing
Use this table to decide where a piece of knowledge belongs:
| Situation | Where it belongs |
| Personal workflow preference | auto-memory (user/feedback) |
| Active project state, deadlines, blockers | auto-memory (project) |
| Architecture decision the team must follow | AGENTS.md "Self-Evolving Learnings" + /share-learning |
| Library gotcha that affects everyone | AGENTS.md learnings log + /share-learning |
| Convention ("All template output is escaped at echo time") | AGENTS.md learnings log + /share-learning |
| Incident postmortem worth team awareness | AGENTS.md learnings log + /share-learning |
Rule of thumb: if another project's agent would benefit from knowing it, record it in the learnings log. Otherwise let auto-memory handle it.
Self-Evolving Learnings (agent convention)
After completing a session, if you hit a non-obvious bug, discovered a useful pattern, or
found an edge case, append a dated entry to the project's AGENTS.md under
`
Self-Evolving Learnings`:
- [YYYY-MM-DD] <category>: <one-line learning>Categories: wordpress, php, security, gsap, lenis, vite, tailwind, build, tooling. Keep entries terse and factual — one line each.
- [2026-08-04] tooling: Pint's laravel preset conflicts with WPCS (spaces/tabs,
array()vs[], Yoda,array( $x )spacing,new self()parens, function/class brace placement) — pint.json must disable indentation_type, array_indentation, statement_indentation, spaces_inside_parentheses, no_spaces_around_offset, array_syntax, yoda_style, unary_operator_spaces, phpdoc_no_package, function_declaration, braces_position, class_definition, new_with_parentheses, trim_array_spaces, binary_operator_spaces, blank_line_after_opening_tag; set concat_space to "one". phpcs is the style authority. - [2026-08-04] tooling:
ref="Universal"in phpcs.xml loads EVERY sniff in the namespace — including the mutually exclusive RequireExitDieParentheses/DisallowExitDieParentheses pair. WordPress-Extra already includes a curated Universal subset; PHPCompatibilityWP exists as a separate package but is unmaintained against the php-compatibility 9.x line (its master requires ^10@dev) — use plain PHPCompatibility with testVersion. - [2026-08-04] wordpress: enqueueing Vite hashed assets with $ver = null trips WordPress.WP.EnqueuedResourceParameters.MissingVersion — the hash IS the cache-buster; wrap in phpcs:disable/enable with a comment instead of passing a fake version.
- [2026-08-04] tooling: Local by Flywheel's bundled PHP has openssl disabled in php.ini —
composer install fails TLS; enable per-invocation with a temp php.ini
(extension=openssl + mbstring) instead of editing Local's php.ini. SUPERSEDED 2026-09-06:
appended
extension=openssl+extension=curl(DLLs already ship in ext/) toC:\Program Files (x86)\Local\resources\extraResources\lightning-services\php-8.2.29+0\bin\win64\php.ini(backupphp.ini.bak) — composer on the PATH php now works with no override; re-apply the two lines if a Local update resets that ini or switches the PATH PHP version. Note the APPDATA site-runtime root has no ini (per-site rendered config) — site PHP still lacks openssl/curl, which only matters if a site needs HTTPS calls from PHP. - [2026-08-04] tooling: PowerShell 5.1 Set-Content -Encoding UTF8 writes a BOM which breaks JSON.parse — use [IO.File]::WriteAllText with UTF8Encoding($false); Get-Content defaults to ANSI and mangles UTF-8 — keep .ps1 and template files ASCII-only.
- [2026-08-04] tooling: PowerShell 5.1 parses
$var:as a drive reference (use${var}:) and hashtable keys are case-insensitive ({PREFIX} vs {Prefix} collide — use a Dictionary[string,string]); piping a native command to Select-Object -First kills the upstream process early. - [2026-08-04] tooling: Local's Windows "Site Shell" opens cmd.exe by default —
&call syntax dies with "& was unexpected at this time" and$HOMEisn't expanded. Shell- agnostic entry point: a .cmd wrapper forwarding %* topowershell -NoProfile -ExecutionPolicy Bypass -File. - [2026-08-04] tooling: Local bundles PHP under two roots — %APPDATA%\Local\lightning-
services... (site-shell PATH) and Program Files (x86)\Local\resources\extraResources
lightning-services... — detect Local's PHP by matching "lightning-services" anywhere in the path, never a fixed prefix. - [2026-08-04] tooling: templates/theme package.json must call
php vendor/bin/pint— a barevendor/bin/pint(forward slash) fails under npm scripts on Windows cmd, breaking format:all:check and the pre-commit gate. - [2026-08-04] tooling: templates/theme pint.json must disable phpdoc_align + no_blank_lines_after_phpdoc, and docblocks must use single-space @param with exactly one blank line after the file comment — the template's aligned style failed its own phpcs (Squiz.Commenting.FileComment.SpacingAfterComment).
- [2026-08-04] wordpress: functions.php requires configure/nav-walker.php — the template must ship a WPCS-compliant stub ({Prefix}_Header_Nav_Walker extends Walker_Nav_Menu) with phpcs:disable WordPress.Files.FileName; the filename is fixed by the boot chain, and the sniff fires at line 0 so only phpcs:disable (not :ignore) suppresses it.
- [2026-08-04] tooling:
npx skills add ... -a opencode -g(skills CLI 1.5.x) writes to~\.agents\skills\despite the docs' global-path table — move the skill dirs into~/.config/opencode/skills/after install so they're git-tracked and docs-checkable. Vendored gsap-* skills: never edit in place; refresh vianpx skills update -a opencode -g. - [2026-08-05] tooling: bun's text bun.lock is JSON-with-trailing-commas by design in
every bun version — never strict JSON; validate it with bun itself
(
bun install --frozen-lockfile --dry-run), never jq. Resync a stale lockfile withbun install --lockfile-only(no --frozen-lockfile — frozen rejects the rewrite). - [2026-08-05] tooling: cmd.exe splits an executable token at
/—vendor/bin/phpcsparses as the commandvendorplus a switch; composer bins must run asvendor\bin\<tool>.baton win32 (backslash extensionless forms DO resolve via PATHEXT — probe-verified — but the forward-slash canonical form never does). - [2026-08-05] tooling: a trigger regex
git(\.exe)?\s+(push|commit)silently missesgit -C <path> push/commit— the option precedes the verb. Gate/trigger patterns need an optional-C <path>clause; verified end-to-end by driving proof-of-work.ts via bun against fake gated repos (per-target cache keyed by HEAD + porcelain, cache hits within 120s, invalidation on new HEAD). - [2026-08-07] tooling: template JS must avoid template-literal
${ident}interpolation — setup.ps1's dry-run stray-token guard regex\{[a-zA-Z_][a-zA-Z0-9_-]*\}flags{ident}inside it (comments included, so don't write brace-token examples in template comments either); use string concatenation. The shipped hero.js example documents this in place. - [2026-08-07] tooling: MCP servers silently die via
"enabled": false— the 2026-08-04 opencode.json rewrite disabled chrome-devtools at birth and every session for 3 days had no browser tools while docs still referenced them. After any config-rewrite commit, git-diff the mcp block forenabled: falseregressions; MCP servers only spawn at session start, so a config fix needs a restart to take effect. Both servers are now version-pinned (chrome-devtools-mcp@1.6.0,@upstash/context7-mcp@4.0.0) so a breaking release can't silently break the stack, and the pinned npx caches are warm. - [2026-08-07] tooling: PowerShell 5.1 renders native-command stderr as red
ErrorRecord noise under
2>&1— git push progress goes to stderr BY DESIGN (exit code is the truth; the push succeeded). Run git/native commands WITHOUT2>&1(stderr passes through plain); when merged capture is needed, use2>&1 | ForEach-Object { "$_" }—$LASTEXITCODEis unaffected. - [2026-08-07] tooling: this repo is LF-canonical via
.gitattributes(* text=auto+ per-typeeol=lf); without it, globalcore.autocrlf=truematerializes CRLF working copies (6 vendoredskills/gsap-*/SKILL.mdfiles were CRLF) and warns on every agent-written LF file. After an attribute change:git add --renormalize .(blobs already LF — no-op), then flush mixed endings per file —git checkout-index -f -ais a stat-cache NO-OP here; delete the file andgit checkout -- <file>(or bump mtime first). Keep vendored skills text —npx skills updaterefreshes normalize ongit add. - [2026-08-10] tooling: a shipped
.husky/pre-commitwithout a"prepare": "husky"package.json script is dormant — hooks never install onnpm install; andisGatedProjectin plugins/proof-of-work.ts requires abuildscript, so build-less plugin scaffolds were never gate-protected. Both templates now carryprepare: husky; the plugin template ships"build": "exit 0"as a documented no-op (plugins have no compiled assets) so the gate's four-step chain runs for plugin projects too. - [2026-09-21] tooling: nixie-fx (azakhary/nixie-fx) evaluated for creative-UI particles - deferred. Two opencode-compatible skills (nixie-fx-runtime, nixie-fx-authoring) install via
npx skills add https://github.com/azakhary/nixie-fx; if adopted: vendor gsap-style into skills/ + house rules in frontend-stack.md (Tempus-driven update once per frame, reduced-motion gate, dynamic import chunk, dispose on scope end, editor-to-out/vfx export pipeline). - [2026-09-24] wordpress: WPCS 3.x has two silent opt-ins:
ValidatedSanitizedInputis not referenced by Core/Extra/Docs anymore (input boundary unenforced by default), andPrefixAllGlobalsno-ops at runtime without theprefixesproperty (WPCS 3.2+ requires ≥4 chars;wp/_/php/wordpressblocklisted). Both must be added explicitly to phpcs.xml — templates now ship them with a{prefix}scaffold token. - [2026-09-24] tooling: the GitHub Actions Workflow Standard (developer.wordpress.org,
Apr 2026) mandates actionlint + zizmor, SHA-pinned actions with version comments,
persist-credentials: falseon checkout,permissions: {}+ per-job grants, and env-var injection for untrusted expressions. Verified pins in this repo's ci.yml: checkout v4.4.011d5960..., setup-bun v2.2.00c5077e..., setup-php 2.37.2f3e473d..., actionlint 1.7.12, zizmor 1.30.1. - [2026-09-24] wordpress: WP JS/CSS/HTML standards mandate tabs; Prettier must ship
useTabs: true, tabWidth: 4. ESLint +@wordpress/eslint-plugin(v27, flat configeslint.config.mjs,...wordpress.configs.recommended) is the JS lint gate and rides insideformat:all:check— the 4-step proof-of-work chain is unchanged. - [2026-09-24] tooling: production-theme drift — a scaffolded theme's phpcs.xml had
been replaced with an i18n-only ruleset (no Core/Extra/Docs/PHPCompatibility) and
phpcompatibility/php-compatibilitywas missing from composer.json, so the gate enforced nothing./audit-style checks must diff live projects against the templates, not assume scaffolds stay pristine. WPCS 3.4.x PrefixAllGlobals requires a ≥4-char prefix — a 2-char prefix (e.g.ss) forces a prefix migration or a documented error-code exclusion. - [2026-09-24] wordpress:
setup_postdata()does NOT assign the global$post— verified on WP 7.1.2 and documented on developer.wordpress.org (the global is only set byWP_Query::the_post();WP_Query::setup_postdata()sets only$id/$authordata/$pages/...). The ACF-tutorial patternforeach ( $posts as $p ) { setup_postdata( $p ); get_the_title(); }therefore renders the MAIN QUERY post (e.g. "Homepage" on a static front page) for every item. Always pass the post explicitly —get_the_title( $p ),get_field( 'name', $id ),have_rows( 'name', $id )— or assignglobal $post; $post = $p;first. Fixing one production theme section this way took 26 items from "Homepage" to their real titles. - [2026-09-24] tooling: cross-platform pass — setup.ps1 now runs on pwsh 7
(macOS/Linux) and Windows PowerShell 5.1+. Two latent bugs fixed:
Join-Pathwith backslash literals (app\public,wp-content\themes\{x}) created literal backslash-named dirs on POSIX (useJoin-Pathchains only), andTrimStart('\')left a leading/on POSIX relative paths (trim both separators).scaffold.sh(POSIX sh,dirname-based) is the macOS/Linux counterpart ofscaffold.cmd(which now resolves its own directory). Local PHP detection (lightning-servicespath match) already worked on macOS; Linux has no Local — explicit-dir scaffolding. CI smoke job now exercisesscaffold.shon Ubuntu as the cross-platform proof. - [2026-11-05] tooling: OpenCode 1.19.5 parses bash with tree-sitter and matches each command node separately; the guide-pro "whole-string glob" residual was stale. Permission rules are last-match-wins, not "most specific wins".
- [2026-11-05] wordpress: WPCS PrefixAllGlobals has MIN_PREFIX_LENGTH = 4 (since 3.2);
setup.ps1 now rejects short and reserved (
wp/wordpress/php) prefixes, and every doc example uses a ≥4-char base. The scaffold CI smoke test usestest_. - [2026-11-05] tooling: template Prettier config had
useTabs: truewhile template sources were 2-space formatted, so every fresh scaffold failednpm run format:all:check. Templates are now formatted with their own config and ship.prettierignorefordist/,vendor/,node_modules/. - [2026-11-05] tooling: phpcs-watch rejected every Windows absolute path because
SAFE_FILE_PATHexcluded:; it now normalizes to project-relative paths, parsesapply_patchpatchTextmarkers, and reads theFOUND N ERRORSsummary. - [2026-11-05] wordpress: removed the empty, unwired nav-walker stub from the theme
template; numbered
nav__item--Nclasses come from thenav_menu_css_classfilter inconfigure/utilities.php, and WordPress core suppliesaria-current. - [2026-11-05] tooling: proof-of-work regex capture groups are load-bearing — making
(\.exe)?non-capturing shifted thegit -Ctarget to group 1, soresolveGateTargetsilently readundefined.tests/gate.test.ts(run by CI) now pins trigger, skip,-C/-c, quoted-message,~, andcdbehavior. - [2026-11-05] tooling: OpenCode v1 resolves relative
opencode.jsoninstructionspaths withglobUpfrom the current project/worktree, not from the global config directory — a global config must use~/...(or an absolute path). The docs hub is ambient via~/.config/opencode/docs/README.md; reference docs stay on demand. - [2026-11-05] tooling: OpenCode v1 invokes every named export in
plugins/*.tsas a plugin factory. Exporting test helpers (isGateCandidate, …) fromproof-of-work.tsmade the loader call them with{ directory }, socommand.replacethrew and the gate silently failed to load. Pure helpers live inplugins/lib/gate.ts;proof-of-work.tsexports onlyProofOfWork, andtests/gate.test.tspins the export shape.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

