feat(nx-plugin): emit AGENTS.md and CLAUDE.md from the app generator - #2465
Conversation
The preset generator seeded agent context files pointing at node_modules/@analogjs/platform/AGENTS.md, but the app generator emitted neither, so whether an Analog app had agent guidance depended on how it was created. The app generator now writes AGENTS.md and CLAUDE.md into the app folder, keeping the guidance scoped to the Analog app in a workspace that may hold other projects. Existing files are left alone, so re-running the generator or adding Analog to a project with hand-written agent docs is safe. The templates moved to the app generator and are shared with the preset, which still seeds them at the workspace root and now skips the app-level copies to avoid duplicating them in a preset generated workspace. Closes #2463 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SbfASDa35cNavxsHVBPpEP
✅ Deploy Preview for analog-blog ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for analog-docs ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for analog-app ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
📝 WalkthroughWalkthroughThe Nx app generator now creates missing Estimated code review effort: 3 (Moderate) | ~20 minutes 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/nx-plugin/src/generators/app/generator.spec.ts`:
- Around line 213-225: Update the “does not overwrite existing agent context in
the app” test to seed both AGENTS.md and CLAUDE.md with custom content before
calling generator. Assert that each file still exists and contains its
respective custom content after generation, preserving the existing test setup
and generator invocation.
In `@packages/nx-plugin/src/generators/preset/generator.ts`:
- Around line 18-23: Update the preset generator’s generateFiles call in
packages/nx-plugin/src/generators/preset/generator.ts:18-23 to use the
existing-file-safe agent context path/strategy already used by the app-level
generator, and add a regression test confirming root AGENTS.md and CLAUDE.md
files are preserved. Update
apps/docs-analog/src/content/integrations/nx/index.md:89-91 to state the
conditions under which existing root context files are preserved instead of
claiming they are never overwritten.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 05ff51fe-c7e7-42bc-a0ba-e2ded9488eee
📒 Files selected for processing (9)
apps/docs-analog/src/content/integrations/nx/index.mdpackages/nx-plugin/src/generators/app/files/agents/AGENTS.mdpackages/nx-plugin/src/generators/app/files/agents/CLAUDE.mdpackages/nx-plugin/src/generators/app/generator.spec.tspackages/nx-plugin/src/generators/app/generator.tspackages/nx-plugin/src/generators/app/lib/add-agent-context.tspackages/nx-plugin/src/generators/app/schema.d.tspackages/nx-plugin/src/generators/preset/generator.spec.tspackages/nx-plugin/src/generators/preset/generator.ts
| it('does not overwrite existing agent context in the app', async () => { | ||
| const analogAppName = 'existing-agents-app'; | ||
| const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); | ||
|
|
||
| addDependenciesToPackageJson(tree, {}, { nx: '21.0.0' }); | ||
| tree.write(`apps/${analogAppName}/AGENTS.md`, '# Custom guidance'); | ||
|
|
||
| await generator(tree, { analogAppName }); | ||
|
|
||
| expect(tree.read(`apps/${analogAppName}/AGENTS.md`).toString()).toContain( | ||
| '# Custom guidance', | ||
| ); | ||
| expect(tree.exists(`apps/${analogAppName}/CLAUDE.md`)).toBe(true); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Cover preservation for both agent files.
The test seeds only AGENTS.md. It does not prove that an existing CLAUDE.md survives. Seed both files and assert that both custom contents remain after generation.
Proposed test update
tree.write(`apps/${analogAppName}/AGENTS.md`, '# Custom guidance');
+ tree.write(
+ `apps/${analogAppName}/CLAUDE.md`,
+ '# Custom Claude guidance',
+ );
await generator(tree, { analogAppName });
expect(tree.read(`apps/${analogAppName}/AGENTS.md`).toString()).toContain(
'# Custom guidance',
);
+ expect(tree.read(`apps/${analogAppName}/CLAUDE.md`).toString()).toContain(
+ '# Custom Claude guidance',
+ );
expect(tree.exists(`apps/${analogAppName}/CLAUDE.md`)).toBe(true);As per coding guidelines, tests must validate behavior for new functionality.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| it('does not overwrite existing agent context in the app', async () => { | |
| const analogAppName = 'existing-agents-app'; | |
| const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); | |
| addDependenciesToPackageJson(tree, {}, { nx: '21.0.0' }); | |
| tree.write(`apps/${analogAppName}/AGENTS.md`, '# Custom guidance'); | |
| await generator(tree, { analogAppName }); | |
| expect(tree.read(`apps/${analogAppName}/AGENTS.md`).toString()).toContain( | |
| '# Custom guidance', | |
| ); | |
| expect(tree.exists(`apps/${analogAppName}/CLAUDE.md`)).toBe(true); | |
| it('does not overwrite existing agent context in the app', async () => { | |
| const analogAppName = 'existing-agents-app'; | |
| const tree = createTreeWithEmptyWorkspace({ layout: 'apps-libs' }); | |
| addDependenciesToPackageJson(tree, {}, { nx: '21.0.0' }); | |
| tree.write(`apps/${analogAppName}/AGENTS.md`, '# Custom guidance'); | |
| tree.write( | |
| `apps/${analogAppName}/CLAUDE.md`, | |
| '# Custom Claude guidance', | |
| ); | |
| await generator(tree, { analogAppName }); | |
| expect(tree.read(`apps/${analogAppName}/AGENTS.md`).toString()).toContain( | |
| '# Custom guidance', | |
| ); | |
| expect(tree.read(`apps/${analogAppName}/CLAUDE.md`).toString()).toContain( | |
| '# Custom Claude guidance', | |
| ); | |
| expect(tree.exists(`apps/${analogAppName}/CLAUDE.md`)).toBe(true); |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/nx-plugin/src/generators/app/generator.spec.ts` around lines 213 -
225, Update the “does not overwrite existing agent context in the app” test to
seed both AGENTS.md and CLAUDE.md with custom content before calling generator.
Assert that each file still exists and contains its respective custom content
after generation, preserving the existing test setup and generator invocation.
Source: Coding guidelines
| generateFiles( | ||
| tree, | ||
| join(__dirname, '..', 'app', 'files', 'agents'), | ||
| '.', | ||
| options, | ||
| ); |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== workspace files =="
git ls-files | rg '(^packages/nx-plugin/src/generators/preset/generator\.ts$|^apps/docs-analog/src/content/integrations/nx/index\.md$|^workspace\.json$|^nx\.json$|^package\.json$|jest|test|migrations|schematics|generators|agents|CLAUDE|AGENTS)' | head -200
echo
echo "== target preset generator =="
if [ -f packages/nx-plugin/src/generators/preset/generator.ts ]; then
cat -n packages/nx-plugin/src/generators/preset/generator.ts
fi
echo
echo "== generator files snippets =="
fd -t f 'generator\.ts$' packages/nx-plugin/src/generators | while read -r f; do
echo "--- $f"
rg -n "generateFiles|OverwriteStrategy|addAgentContext|CLAUDE|AGENTS|agents" "$f" || true
done
echo
echo "== app/agenerator files snippets =="
fd -t f 'generator\.ts$' packages/nx-plugin/src/generators | while read -r f; do
echo "--- $f"
rg -n "generateFiles\(|OverwriteStrategy|addAgentContext|AGENTS|CLAUDE|agents" "$f" || true
doneRepository: analogjs/analog
Length of output: 14279
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== package deps nx version =="
node - <<'JS'
const fs = require('fs');
const p = JSON.parse(fs.readFileSync('package.json','utf8'));
if (p.devDependencies?.nx) console.log('package.json devDependencies.nx:', p.devDependencies.nx);
if (p.dependencies?.nx) console.log('package.json dependencies.nx:', p.dependencies.nx);
JS
echo
echo "== preset generator =="
cat -n packages/nx-plugin/src/generators/preset/generator.ts
echo
echo "== app generator relevant sections =="
cat -n packages/nx-plugin/src/generators/app/generator.ts | sed -n '1,220p'
echo
echo "== references to generateFiles and KeepExisting =="rg
rg -n "generateFiles\(|OverwriteStrategy|KeepExisting|addAgentContext|AGENTS\.md|CLAUDE\.md|agents" packages/nx-plugin packages -g '*.ts' -g '*.json' | head -200
echo
echo "== tests relevant references =="
rg -n "preset|generateFiles|KeepExisting|AGENTS|CLAUDE|agent" packages/nx-plugin -g '*.spec.ts' -g '*.ts' | head -200Repository: analogjs/analog
Length of output: 21086
🌐 Web query:
Nx generateFiles default overwrite strategy OverwriteStrategy KeepExisting
💡 Result:
In Nx, the generateFiles function supports an optional configuration to control how existing files are handled using the OverwriteStrategy [1][2]. To use the KeepExisting strategy, you pass an options object as the final argument to generateFiles [1][3]: generateFiles(tree, srcFolder, target, substitutions, { overwriteStrategy: OverwriteStrategy.KeepExisting }); Available strategies in the OverwriteStrategy enumeration include [4][5]: OverwriteStrategy.Overwrite (default): Automatically overwrites existing files [1][3]. OverwriteStrategy.KeepExisting: Only creates files if the target does not already exist; existing files are preserved [1][3]. OverwriteStrategy.ThrowIfExisting: Throws an exception if a target file already exists, which is useful when a pristine environment is required [1][3].
Citations:
- 1: https://nx.dev/docs/extending-nx/creating-files
- 2: https://nx.dev/docs/reference/devkit/generateFiles
- 3: https://itnext.io/cherry-picked-nx-v19-2-updates-0c486fb2b112
- 4: https://nx.dev/docs/reference/devkit/OverwriteStrategy
- 5: https://master.nx.dev/docs/reference/devkit/OverwriteStrategy
Preserve existing root agent context files in preset-generated workspaces.
Preset agent context generation uses generateFiles with Nx’s default overwrite strategy, so root AGENTS.md or CLAUDE.md files can be replaced. Implement the same existing-file safeguard documented for app-level agent context at the workspace root, and add a regression test.
packages/nx-plugin/src/generators/preset/generator.ts#L18-L23: Use the existing-file-safe agent context path/strategy.apps/docs-analog/src/content/integrations/nx/index.md#L89-91: Update this claim to describe when existing root files are preserved rather than saying they are never overwritten.
📍 Affects 2 files
packages/nx-plugin/src/generators/preset/generator.ts#L18-L23(this comment)apps/docs-analog/src/content/integrations/nx/index.md#L89-L91
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/nx-plugin/src/generators/preset/generator.ts` around lines 18 - 23,
Update the preset generator’s generateFiles call in
packages/nx-plugin/src/generators/preset/generator.ts:18-23 to use the
existing-file-safe agent context path/strategy already used by the app-level
generator, and add a regression test confirming root AGENTS.md and CLAUDE.md
files are preserved. Update
apps/docs-analog/src/content/integrations/nx/index.md:89-91 to state the
conditions under which existing root context files are preserved instead of
claiming they are never overwritten.
Source: Path instructions
|
View your CI Pipeline Execution ↗ for commit 6c84b87
💡 Dealing with memory or CPU issues? See memory and CPU details with the resource usage add-on ↗. ☁️ Nx Cloud last updated this comment at |
PR Checklist
The
presetgenerator seedsAGENTS.mdandCLAUDE.mdpointing atnode_modules/@analogjs/platform/AGENTS.md, but theappgenerator emitted neither. Whether an Analog app shipped with agent guidance depended on how it was created.Closes #2463
Affected scope
nx-plugindocsRecommended merge strategy for maintainer [optional]
Commit preservation note [optional]
N/A
What is the new behavior?
nx g @analogjs/platform:application <name>now writesAGENTS.mdandCLAUDE.mdinto the app folder (apps/<name>/), so the guidance stays scoped to the Analog app in a workspace that may hold other projects.preset/files/toapp/files/agents/and are now shared by both generators, so there is one source of truth for the content.skipAgentContextflag into the app generator so a preset generated workspace does not end up with duplicate copies at the root and in the app folder.Test plan
nx format:checkpnpm build(rannx build nx-plugin, and verified the templates land atsrc/generators/app/files/agents/in the built package so the generator resolves them at runtime)pnpm test(rannx test nx-plugin, 25 tests passing)New tests cover the app generator emitting the files into the app folder and leaving an existing
AGENTS.mduntouched. The preset spec now also asserts no app level copies are created.nx lint nx-pluginreports only pre-existing warnings, none from the new code.Does this PR introduce a breaking change?
Other information
The placement split (preset at the workspace root, app generator in the app folder) is the decision the issue flagged as non-obvious. Root placement makes sense when the workspace exists for Analog, and app folder placement avoids putting Analog specific guidance at the root of a mixed workspace or overwriting a root
CLAUDE.mdthat is already there.🤖 Generated with Claude Code