From dx-core
Auto-detect project type, structure, build commands, and AEM values. Updates .ai/config.yaml with project profile and substitutes real values into installed .claude/rules/. Run after /dx-init and /aem-init. Re-run anytime to refresh detected values.
npx claudepluginhub easingthemes/dx-aem-flow --plugin dx-coreThis skill is limited to using the following tools:
You detect the project's technical profile from source files and update `.ai/config.yaml` with the `project:`, `toolchain:`, and additional `build:` fields. Then you substitute the detected values into `.claude/rules/` files (replacing generic placeholders with real project values).
Set up dotclaude in any project end-to-end. Bootstrap `.claude/` from the bundled template if missing, then customize every config file to match the project's actual tech stack, conventions, and patterns.
Initializes Claude Code projects by auto-detecting Node.js frameworks from package.json and lockfiles, replaces CLAUDE.md placeholders, installs rules, hooks, and scripts.
Setup wizard — scans codebase, builds confidence per data point, only asks what it can't figure out, generates SDLC files. Use for first-time setup or re-running setup.
Share bugs, ideas, or general feedback.
You detect the project's technical profile from source files and update .ai/config.yaml with the project:, toolchain:, and additional build: fields. Then you substitute the detected values into .claude/rules/ files (replacing generic placeholders with real project values).
Use ultrathink — project detection requires reading multiple source files and making accurate inferences.
Read .ai/config.yaml. If it doesn't exist: "Run /dx-init first." STOP.
Check if .ai/config.yaml already has a project: section with type field:
project: section: Go directly to Phase 1. (This is normal on first run or when called from dx-init.)project: section exists: Display the current values and ask: (A) Keep as-is, (B) Re-detect (re-reads source files), (C) Edit (re-confirm with current values pre-loaded). If A: skip to Phase 4 (rule substitution only).If the user provided an argument (aem-fullstack, aem-frontend, frontend), use it. Otherwise detect:
| Check | Type |
|---|---|
pom.xml exists AND contains com.adobe.cq or AEM uber-jar dependency | aem-fullstack |
pom.xml exists AND contains content-package-maven-plugin AND no Java source in src/main/java/ | aem-frontend |
package.json exists AND contains aem-clientlib-generator or clientlib.config.js exists | aem-frontend |
package.json exists AND no AEM indicators | frontend |
Only pom.xml (no AEM) | java |
For aem-fullstack:
# Find Java package root
find . -path "*/src/main/java/*.java" | head -1
# → extract package from first line of that file
# Find component namespace from filter.xml or .content.xml
grep -r "componentGroup" --include="*.xml" -l | head -5
# Find base branch
git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||'
# Find Maven modules
find . -maxdepth 3 -name "pom.xml" | grep -v "^./pom.xml"
Read 2-3 .content.xml files with componentGroup to extract:
componentGroup — the group name string (e.g., "MyProject General")componentPath — derive from the file path (e.g., /apps/myproject/components)componentSelector — from @Exporter annotation in any Java @Model classserviceVendor — from @Component(property = "service.vendor=...") in any Java classdialogPropertyPrefix — check if dialog XML uses ./data/ nesting or ./ directlyrteInheritancePath — search for sling:resourceSuperType containing rteConfigsauthorPort — from pom.xml properties (default 4502)Extract build commands from pom.xml and package.json (if frontend submodule exists):
build.full — mvn clean install -PautoInstallPackage (with correct -pl if multi-module)build.deploy — mvn clean install -PautoInstallPackage -DskipTests (quick deploy, no tests)build.compile — frontend compile if package.json submodule existsbuild.test — mvn test -pl <core-module>build.testSingle — mvn test -pl <core-module> -Dtest={className}build.lint — from package.json scripts if frontend submodule existsExtract modules list from child pom.xml files:
find . -maxdepth 3 -name "pom.xml" ! -path "./pom.xml" \
-exec grep -l "packaging" {} \; | sort
For each, read packaging type: bundle, content-package, jar.
Extract sourceRoots, testRoots, componentPaths from the module paths found.
For aem-frontend:
Read package.json scripts to extract build, lint, test commands.
Read webpack/clientlib config to find component output paths.
No Java extraction needed — omit aem.javaPackage, aem.componentSelector, etc.
For frontend:
Read package.json for framework, scripts (build, test, lint, dev).
Read tsconfig.json if present for TypeScript confirmation.
Read directory structure (src/, app/, pages/, components/) for source roots.
# Base branch
git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null | sed 's|refs/remotes/origin/||'
# Branch prefix from recent branches
git branch -r | grep -E "feature/|bugfix/" | head -5
Read scm.base-branch from .ai/config.yaml as fallback.
Print all detected values as a table. Ask: "Correct? Type 'yes' or correct any values."
## Detected: <project type>
| Property | Value |
|---|---|
| Project Type | <type> |
| Name | <name from config.yaml> |
| Build (full) | `<command>` |
| Build (compile) | `<command or "—">` |
| Test | `<command>` |
| Test (single) | `<pattern>` |
| Lint | `<command or "none">` |
| Base Branch | <branch> |
| Source Roots | <list> |
| Test Roots | <list> |
| Component Paths | <list> |
<AEM-only rows:>
| Java Package | <package> |
| Component Path | <path> |
| Component Group | <group> |
| Selector | <selector or "—"> |
| Service Vendor | <vendor or "—"> |
| Dialog Property Prefix | <prefix> |
| AEM Author Port | <port> |
Derive project.role from project.type:
| project.type | project.role |
|---|---|
| aem-fullstack | fullstack |
| aem-frontend | frontend |
| frontend | frontend |
| java | backend |
| (other) | Ask user to confirm |
Confirm with user: "Detected project role: {role}. Is this correct?"
Read .ai/config.yaml in full. You will append/update sections — never overwrite the entire file.
Add or update the following sections in .ai/config.yaml. Preserve all existing sections (dx:, scm:, build:, aem:, etc.) — only add/update the fields listed below.
Add project: section (add after dx: section, or update if it already exists):
project:
type: "{{type}}" # aem-fullstack | aem-frontend | frontend | java
role: "{{role}}" # fullstack | frontend | backend (derived above)
Add toolchain: section (add after project: section):
toolchain:
node-version: "{{version}}" # detected from .nvmrc, .node-version, or package.json engines
build-tool: "{{tool}}" # webpack | vite | maven | gradle | etc.
css-compiler: "{{compiler}}" # sass | less | postcss | none
component-base-class: "{{class}}" # e.g. "com.adobe.cq.export.json.ComponentExporter" (AEM only, omit if N/A)
Only include fields that were actually detected. Omit fields with no detected value.
Update build: section — append these granular fields to the existing build: section if detected:
build:
# ... existing fields (command, test, etc.) stay as-is ...
serve: "{{command}}" # dev server command (e.g. "npm run dev")
lint-js: "{{command}}" # JS/TS linting (e.g. "npm run lint:js")
lint-scss: "{{command}}" # SCSS/CSS linting (e.g. "npm run lint:scss")
lint-fix: "{{command}}" # auto-fix linting (e.g. "npm run lint:fix")
Only add fields that were detected from package.json scripts or build configs. Do not add fields with empty values.
Update aem: section — if project type is aem-fullstack or aem-frontend and the aem: section already exists, add/update component-prefix if a prefix was detected (e.g., from component group or path convention). Do NOT duplicate fields that already exist in the aem: section (java-package, component-path, component-group are already managed by /aem-init).
Fields NOT written (derivable from filesystem, dropped per spec): modules, sourceRoots, testRoots, componentPaths, source, output, component.registration.
Print: Updated .ai/config.yaml with project profile
Re-generate files seeded from plugin templates. These are the plugin's responsibility (not user-customized), so they always reflect the latest template.
Read templates/INDEX.md.template from the plugin directory. Replace {{PROJECT_NAME}} with dx.project-name from .ai/config.yaml. Write to agent.index.md (project root). Always overwrite.
Read templates/README.md.template from the plugin directory. Replace {{PROJECT_NAME}} with the project name. Write to .ai/README.md. Always overwrite.
Run scaffold.sh to pick up any new rule templates or utilities added since last init:
bash skills/dx-init/scripts/scaffold.sh
Each file is skipped if it already exists — only newly added templates are installed.
Read project.type from .ai/config.yaml.
| project.type | Action |
|---|---|
aem-fullstack | Keep all rules. No deletions. |
aem-frontend | Delete all be-*.md rules in .claude/rules/. Keep fe-*.md, accessibility.md, naming.md. |
frontend | Delete all be-*.md and fe-clientlibs.md rules. Keep accessibility.md, naming.md. |
java | Delete all fe-*.md rules. Keep be-*.md, accessibility.md, naming.md. |
Use Glob to list matching files, then delete those that don't apply. If no files match the deletion criteria, report "no rules to filter".
Read each .claude/rules/*.md file that was installed from an aem-init template. Verify that project-specific values from .ai/config.yaml are present — not generic placeholders. Check for:
aem.java-package from config.yaml aem: section)aem.component-path from config.yaml aem: section)aem.component-group from config.yaml aem: section)Other substitution values are read from .ai/config.yaml:
project.type, project.role — from the project: sectiontoolchain.* values — from the toolchain: sectionbuild.* values — from the build: sectionIf any file still contains generic examples instead of real project values, substitute them with values from .ai/config.yaml. If a file already has correct project-specific values, skip it silently.
## Project Adapted: <name>
**Type:** <type>
**Role:** <role>
**Config:** `.ai/config.yaml` updated (project + toolchain sections)
### Rules Updated
<list of .claude/rules/ files modified with substitutions made>
<list of files skipped (already customized)>
### Next Steps
- Review `project:` and `toolchain:` sections in `.ai/config.yaml` — edit and re-run `/dx-adapt` if any values need correction
- `/dx-init` — re-run if base config.yaml needs changes
- `/aem-init` — re-run if AEM rule templates need reinstalling
/dx-adapt — First run after /dx-init. Scans the codebase to detect 3 brands, 45 components, Node 10 with Gulp build. Updates config.yaml with project: and toolchain: sections, then substitutes placeholders in .claude/rules/ files (e.g., {{BRANDS}} becomes the actual brand list, {{BUILD_COMMAND}} becomes npm run build:new).
/dx-adapt (re-run after adding a new brand) — Detects existing project: section in config.yaml, asks whether to re-detect or keep existing values. User chooses re-detect. Finds the new brand directory, updates config.yaml, and re-runs Phase 4 substitution to update rules files with the expanded brand list.
/dx-adapt (AEM project) — Detects AEM project structure during Phase 1. After Phase 3 (config.yaml updated), automatically chains to /aem-init to install AEM-specific rules before Phase 4 runs substitution on all rule files including AEM ones.
"project profile already exists — re-detect or keep?"
Cause: /dx-adapt was run before and detection results are saved in config.yaml's project: section.
Fix: Choose "re-detect" if the project structure changed (new components, new brands). Choose "keep" if you only want to re-run the substitution phase (Phase 4) with existing values.
Placeholders left in rule files after adaptation
Cause: The value could not be extracted from the codebase (e.g., no brands found, build tool not recognized).
Fix: Check project: and toolchain: sections in .ai/config.yaml for missing values. Fill them in manually and re-run /dx-adapt — Phase 4 will substitute using the updated values.
Rule file skipped during substitution
Cause: The rule file has no remaining placeholders (already customized) or was manually edited.
Fix: This is expected behavior — /dx-adapt never overwrites user customizations. If you want to re-apply the template, delete the rule file and run /dx-adapt again (it will reinstall from the plugin template first).
project: section (unless user chooses re-detect)