What it isAlways-on coding rules. GitHub Copilot applies them to files matching **/core/src/**/*.java,**/ui.apps/**,**/ui.config/**,**/ui.frontend/**,**/dispatcher/**; the Claude Code version is a path-scoped rule generated from the same file. Why use instructions →
Install
This repository (recommended)
Adds .github/instructions/aem.instructions.md — commit it so everyone's Copilot follows the same rules.
Nothing to invoke — edit a matching file and Copilot picks the rules up. Adjust applyTo if your repository layout differs.
This repository (recommended)
Adds .claude/rules/aem.md — commit it. Claude loads it when it reads a matching file.
npx -y github:AGCO-Global/org-skills add instructions aem --tool claude
Just for me, every repository
Save it in your user profile instead.
npx -y github:AGCO-Global/org-skills add instructions aem --tool claude --user
Use it
Nothing to invoke. Adjust the paths globs if your repository layout differs.
Commands run in your repository folder and need Node.js 20+. They use your normal git sign-in to GitHub, so they work while the repository is private. Run npx -y github:AGCO-Global/org-skills list to see everything available.
Settings
name: "AEM"
description: "Always-on rules for AEM as a Cloud Service Java bundles, HTL components, OSGi configs, front-end clientlibs and dispatcher configuration."
applyTo: "**/core/src/**/*.java,**/ui.apps/**,**/ui.config/**,**/ui.frontend/**,**/dispatcher/**"
Instructions Copilot follows
AEM rules
Write for AEM as a Cloud Service first: immutable /apps, no admin sessions, auto-scaled disposable publish pods.
HTL and components
Never use @ context='unsafe'. It disables XSS protection and is a review blocker.
Use the right XSS context: context='html' for RTE output, 'uri' for links, 'attribute'/'text' where the default is not inferred, 'scriptString'/'styleString' inside <script>/<style>.
Keep logic out of HTL: no string-built markup or URLs; compute them in the Sling Model.
Build standard elements as proxies of a pinned Core Component version (sling:resourceSuperType=".../v3/..."); never reference core/wcm/components directly from content.
Use the Style System for visual variants, not new components or dialog dropdowns.
Set allowed components on the layout container policy, not in code.
Sling Models
Adapt component models from SlingHttpServletRequest, expose an interface, and keep the Impl in an internal package.
Use injector annotations (@ValueMapValue, @ChildResource, @OSGiService) with DefaultInjectionStrategy.OPTIONAL, and handle missing values. Authors leave fields empty.
Keep @PostConstruct cheap: no queries, remote calls or writes during render.
Extend Core Components through delegation (@Via(type = ResourceSuperType.class)), not by copying their code.
OSGi services and access
Components are singletons: no request state in fields; ResourceResolver and Session are not thread-safe.
Never use getAdministrativeResourceResolver or loginAdministrative. Use a service user mapping with least-privilege ACLs defined in repoinit.
Close every service resolver you open (try-with-resources). Leaked sessions degrade the instance.
Configure services with @Designate/@ObjectClassDefinition and .cfg.json in ui.config under the fixed runmodes (config.author, config.publish.prod, ...).
Keep secrets out of Git: use $[secret:NAME] and $[env:NAME] set via Cloud Manager variables.
Register servlets by resource type (@SlingServletResourceTypes), not by path; use SlingSafeMethodsServlet for GET.
Avoid unindexed queries; add a versioned <name>-custom-<n> Oak index in code when a query needs one.
Run long or scheduled work as Sling Jobs, and make it safe to run on any pod; never write /apps or /libs at runtime.
Dispatcher
Start filters from deny-all (/0001 { /type "deny" /url "*" }) and allow only needed paths, extensions and selectors.
Never allow /crx, /system, /bin wholesale, .infinity.json, .query.json or unrestricted selectors on publish.
Cache static and clientlib content with long TTLs; set invalidation rules deliberately and never cache personalized or authenticated responses.
Validate changes with the SDK dispatcher validator before pushing; Cloud Manager rejects invalid configs.
Front end and clientlibs
Set allowProxy="{Boolean}true" on clientlibs and reference them via /etc.clientlibs; publish denies reads on /apps.
Embed component clientlibs into the site clientlib; do not include them per component in HTL.
Load CSS in <head> and JS with defer; keep author-only code in cq.authoring.* categories.
Never hand-edit generated clientlib folders; change sources in ui.frontend.
Make scripts work in the page editor: initialize on DOM content, tolerate components being added or removed.
Go deeper: for larger tasks use the aem-component-development, aem-backend-development, aem-frontend-development, aem-dispatcher, aem-testing and aem-code-review skills.
---
name: "AEM"
description: "Always-on rules for AEM as a Cloud Service Java bundles, HTL components, OSGi configs, front-end clientlibs and dispatcher configuration."
applyTo: "**/core/src/**/*.java,**/ui.apps/**,**/ui.config/**,**/ui.frontend/**,**/dispatcher/**"
---
# AEM rules
Write for AEM as a Cloud Service first: immutable `/apps`, no admin sessions, auto-scaled disposable publish pods.
## HTL and components
- Never use `@ context='unsafe'`. It disables XSS protection and is a review blocker.
- Use the right XSS context: `context='html'` for RTE output, `'uri'` for links, `'attribute'`/`'text'` where the default is not inferred, `'scriptString'`/`'styleString'` inside `<script>`/`<style>`.
- Keep logic out of HTL: no string-built markup or URLs; compute them in the Sling Model.
- Build standard elements as proxies of a pinned Core Component version (`sling:resourceSuperType=".../v3/..."`); never reference `core/wcm/components` directly from content.
- Use the Style System for visual variants, not new components or dialog dropdowns.
- Set allowed components on the layout container policy, not in code.
## Sling Models
- Adapt component models from `SlingHttpServletRequest`, expose an interface, and keep the `Impl` in an internal package.
- Use injector annotations (`@ValueMapValue`, `@ChildResource`, `@OSGiService`) with `DefaultInjectionStrategy.OPTIONAL`, and handle missing values. Authors leave fields empty.
- Keep `@PostConstruct` cheap: no queries, remote calls or writes during render.
- Extend Core Components through delegation (`@Via(type = ResourceSuperType.class)`), not by copying their code.
## OSGi services and access
- Components are singletons: no request state in fields; `ResourceResolver` and `Session` are not thread-safe.
- Never use `getAdministrativeResourceResolver` or `loginAdministrative`. Use a service user mapping with least-privilege ACLs defined in repoinit.
- Close every service resolver you open (try-with-resources). Leaked sessions degrade the instance.
- Configure services with `@Designate`/`@ObjectClassDefinition` and `.cfg.json` in `ui.config` under the fixed runmodes (`config.author`, `config.publish.prod`, ...).
- Keep secrets out of Git: use `$[secret:NAME]` and `$[env:NAME]` set via Cloud Manager variables.
- Register servlets by resource type (`@SlingServletResourceTypes`), not by path; use `SlingSafeMethodsServlet` for GET.
- Avoid unindexed queries; add a versioned `<name>-custom-<n>` Oak index in code when a query needs one.
- Run long or scheduled work as Sling Jobs, and make it safe to run on any pod; never write `/apps` or `/libs` at runtime.
## Dispatcher
- Start filters from deny-all (`/0001 { /type "deny" /url "*" }`) and allow only needed paths, extensions and selectors.
- Never allow `/crx`, `/system`, `/bin` wholesale, `.infinity.json`, `.query.json` or unrestricted selectors on publish.
- Cache static and clientlib content with long TTLs; set invalidation rules deliberately and never cache personalized or authenticated responses.
- Validate changes with the SDK dispatcher validator before pushing; Cloud Manager rejects invalid configs.
## Front end and clientlibs
- Set `allowProxy="{Boolean}true"` on clientlibs and reference them via `/etc.clientlibs`; publish denies reads on `/apps`.
- Embed component clientlibs into the site clientlib; do not include them per component in HTL.
- Load CSS in `<head>` and JS with `defer`; keep author-only code in `cq.authoring.*` categories.
- Never hand-edit generated clientlib folders; change sources in `ui.frontend`.
- Make scripts work in the page editor: initialize on DOM content, tolerate components being added or removed.
Go deeper: for larger tasks use the aem-component-development, aem-backend-development, aem-frontend-development, aem-dispatcher, aem-testing and aem-code-review skills.
---
paths:
- "**/core/src/**/*.java"
- "**/ui.apps/**"
- "**/ui.config/**"
- "**/ui.frontend/**"
- "**/dispatcher/**"
---
<!-- AEM — generated from instructions/aem/aem.instructions.md for Claude Code. Edit that file, not this one. -->
# AEM rules
Write for AEM as a Cloud Service first: immutable `/apps`, no admin sessions, auto-scaled disposable publish pods.
## HTL and components
- Never use `@ context='unsafe'`. It disables XSS protection and is a review blocker.
- Use the right XSS context: `context='html'` for RTE output, `'uri'` for links, `'attribute'`/`'text'` where the default is not inferred, `'scriptString'`/`'styleString'` inside `<script>`/`<style>`.
- Keep logic out of HTL: no string-built markup or URLs; compute them in the Sling Model.
- Build standard elements as proxies of a pinned Core Component version (`sling:resourceSuperType=".../v3/..."`); never reference `core/wcm/components` directly from content.
- Use the Style System for visual variants, not new components or dialog dropdowns.
- Set allowed components on the layout container policy, not in code.
## Sling Models
- Adapt component models from `SlingHttpServletRequest`, expose an interface, and keep the `Impl` in an internal package.
- Use injector annotations (`@ValueMapValue`, `@ChildResource`, `@OSGiService`) with `DefaultInjectionStrategy.OPTIONAL`, and handle missing values. Authors leave fields empty.
- Keep `@PostConstruct` cheap: no queries, remote calls or writes during render.
- Extend Core Components through delegation (`@Via(type = ResourceSuperType.class)`), not by copying their code.
## OSGi services and access
- Components are singletons: no request state in fields; `ResourceResolver` and `Session` are not thread-safe.
- Never use `getAdministrativeResourceResolver` or `loginAdministrative`. Use a service user mapping with least-privilege ACLs defined in repoinit.
- Close every service resolver you open (try-with-resources). Leaked sessions degrade the instance.
- Configure services with `@Designate`/`@ObjectClassDefinition` and `.cfg.json` in `ui.config` under the fixed runmodes (`config.author`, `config.publish.prod`, ...).
- Keep secrets out of Git: use `$[secret:NAME]` and `$[env:NAME]` set via Cloud Manager variables.
- Register servlets by resource type (`@SlingServletResourceTypes`), not by path; use `SlingSafeMethodsServlet` for GET.
- Avoid unindexed queries; add a versioned `<name>-custom-<n>` Oak index in code when a query needs one.
- Run long or scheduled work as Sling Jobs, and make it safe to run on any pod; never write `/apps` or `/libs` at runtime.
## Dispatcher
- Start filters from deny-all (`/0001 { /type "deny" /url "*" }`) and allow only needed paths, extensions and selectors.
- Never allow `/crx`, `/system`, `/bin` wholesale, `.infinity.json`, `.query.json` or unrestricted selectors on publish.
- Cache static and clientlib content with long TTLs; set invalidation rules deliberately and never cache personalized or authenticated responses.
- Validate changes with the SDK dispatcher validator before pushing; Cloud Manager rejects invalid configs.
## Front end and clientlibs
- Set `allowProxy="{Boolean}true"` on clientlibs and reference them via `/etc.clientlibs`; publish denies reads on `/apps`.
- Embed component clientlibs into the site clientlib; do not include them per component in HTL.
- Load CSS in `<head>` and JS with `defer`; keep author-only code in `cq.authoring.*` categories.
- Never hand-edit generated clientlib folders; change sources in `ui.frontend`.
- Make scripts work in the page editor: initialize on DOM content, tolerate components being added or removed.
Go deeper: for larger tasks use the aem-component-development, aem-backend-development, aem-frontend-development, aem-dispatcher, aem-testing and aem-code-review skills.