Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

MaxKless
Copy link
Collaborator

@MaxKless MaxKless commented Aug 21, 2025

This pull request introduces a new generator to automatically set up AI agent configuration files and Nx MCP server integration when creating a new Nx workspace. It ensures that guidelines and configuration for common AI assistants (Claude and Gemini) are included by default, improving developer experience and AI integration. The changes also update documentation to reflect these enhancements.

AI Agent Setup and Integration

  • Added a new hidden generator, set-up-ai-agents, to packages/workspace/generators.json that generates configuration files (CLAUDE.md, GEMINI.md, .mcp.json, and .gemini/settings.json) with guidelines and Nx MCP server settings for AI assistants. [1] [2] [3] [4] [5]
  • Integrated the new generator into the workspace creation flow by invoking setupAiAgentsGenerator in generate-workspace-files.ts, ensuring these files are created for every new workspace. [1] [2]

Documentation Updates

  • Enhanced documentation in both astro-docs and shared docs to mention the inclusion of AI agent configuration files (CLAUDE.md, GEMINI.md) during workspace creation. [1] [2]
  • Added a new reference entry for the AI agent setup generator in the documentation sitemap.

Internal Improvements

  • Refactored package manager utilities to allow skipping configuration file copying when creating a workspace from scratch, supporting the new generator's requirements.

These changes collectively streamline AI assistant onboarding for Nx users and ensure that new workspaces are ready for advanced AI-powered development workflows.

Copy link

vercel bot commented Aug 21, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Preview Updated (UTC)
nx-dev Ready Ready Preview Sep 11, 2025 0:30am

@MaxKless MaxKless force-pushed the ai-files-generation branch from 8715f7a to 65e4cb2 Compare August 21, 2025 11:33
@MaxKless MaxKless changed the title feat(core): generate AI files on create-nx-workspace feat(core): generate AI files in create-nx-workspace Aug 21, 2025
@MaxKless MaxKless force-pushed the ai-files-generation branch from 65e4cb2 to 7f328ca Compare August 21, 2025 12:30
Copy link
Contributor

nx-cloud bot commented Aug 21, 2025

View your CI Pipeline Execution ↗ for commit 7e8a0b2

Command Status Duration Result
nx affected --targets=lint,test,build,e2e,e2e-c... ✅ Succeeded 24m 54s View ↗
nx run-many -t check-imports check-commit check... ✅ Succeeded 2m 36s View ↗
nx-cloud record -- nx-cloud conformance:check ✅ Succeeded 2s View ↗
nx-cloud record -- nx format:check ✅ Succeeded 9s View ↗
nx-cloud record -- nx sync:check ✅ Succeeded 7s View ↗
nx documentation ✅ Succeeded 2m 29s View ↗

☁️ Nx Cloud last updated this comment at 2025-09-11 16:16:20 UTC

Copy link
Contributor

🐳 We have a release for that!

This PR has a release associated with it. You can try it out using this command:

npx [email protected] my-workspace

Or just copy this version and use it in your own command:

0.0.0-pr-32442-762aea2
Release details 📑
Published version 0.0.0-pr-32442-762aea2
Triggered by @MaxKless
Branch ai-files-generation
Commit 762aea2
Workflow run 17159589491

To request a new release for this pull request, mention someone from the Nx team or the @nrwl/nx-pipelines-reviewers.

@MaxKless MaxKless marked this pull request as ready for review August 25, 2025 12:03
Comment on lines 27 to 43
try {
const getLatestGeneratorResult = await getLatestGeneratorUsingInstall(
normalizedOptions
);
const { module: latestGeneratorModule, cleanup } = getLatestGeneratorResult;
const setupAiAgentsGeneratorResult =
await latestGeneratorModule.setupAiAgentsGeneratorImpl(tree, options);
await cleanup();
return setupAiAgentsGeneratorResult;
} catch (error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a potential null reference issue in this code. The getLatestGeneratorUsingInstall function can return undefined, but the code immediately destructures the result without checking. If getLatestGeneratorResult is undefined, the line const { module: latestGeneratorModule, cleanup } = getLatestGeneratorResult; will throw a runtime error.

Consider adding a null check before destructuring:

const getLatestGeneratorResult = await getLatestGeneratorUsingInstall(normalizedOptions);
if (getLatestGeneratorResult) {
  const { module: latestGeneratorModule, cleanup } = getLatestGeneratorResult;
  const setupAiAgentsGeneratorResult = 
    await latestGeneratorModule.setupAiAgentsGeneratorImpl(tree, options);
  await cleanup();
  return setupAiAgentsGeneratorResult;
}
Suggested change
try {
const getLatestGeneratorResult = await getLatestGeneratorUsingInstall(
normalizedOptions
);
const { module: latestGeneratorModule, cleanup } = getLatestGeneratorResult;
const setupAiAgentsGeneratorResult =
await latestGeneratorModule.setupAiAgentsGeneratorImpl(tree, options);
await cleanup();
return setupAiAgentsGeneratorResult;
} catch (error) {
try {
const getLatestGeneratorResult = await getLatestGeneratorUsingInstall(
normalizedOptions
);
if (getLatestGeneratorResult) {
const { module: latestGeneratorModule, cleanup } = getLatestGeneratorResult;
const setupAiAgentsGeneratorResult =
await latestGeneratorModule.setupAiAgentsGeneratorImpl(tree, options);
await cleanup();
return setupAiAgentsGeneratorResult;
}
} catch (error) {

Spotted by Diamond

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

@@ -6,7 +6,7 @@ sidebar:
label: AI Integration
---

Nx provides deep integration with AI coding assistants through the **Nx Model Context Protocol (MCP) server**, giving your AI assistant comprehensive understanding of your monorepo structure, running processes, and development workflows.
Nx provides deep integration with AI coding assistants through the **Nx Model Context Protocol (MCP) server**, giving your AI assistant comprehensive understanding of your monorepo structure, running processes, and development workflows. When you create a new Nx workspace, it includes AI agent configuration files (`CLAUDE.md` and `GEMINI.md`) that provide guidelines for working with Nx and the Nx MCP server.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation mentions only CLAUDE.md and GEMINI.md files, but the implementation also creates an AGENTS.md file. This creates an inconsistency between what's documented and what's actually generated. Consider either updating the documentation to mention all generated files or adjusting the implementation to match what's documented to ensure users have accurate information about the workspace setup.

Suggested change
Nx provides deep integration with AI coding assistants through the **Nx Model Context Protocol (MCP) server**, giving your AI assistant comprehensive understanding of your monorepo structure, running processes, and development workflows. When you create a new Nx workspace, it includes AI agent configuration files (`CLAUDE.md` and `GEMINI.md`) that provide guidelines for working with Nx and the Nx MCP server.
Nx provides deep integration with AI coding assistants through the **Nx Model Context Protocol (MCP) server**, giving your AI assistant comprehensive understanding of your monorepo structure, running processes, and development workflows. When you create a new Nx workspace, it includes AI agent configuration files (`AGENTS.md`, `CLAUDE.md`, and `GEMINI.md`) that provide guidelines for working with Nx and the Nx MCP server.

Spotted by Diamond

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

@MaxKless MaxKless removed the PR status: do not merge This will block a PR from being merged until this tag is removed. label Sep 10, 2025
Comment on lines 109 to 114
const geminPath = join(options.directory, '.gemini', 'settings.json');
addMcpConfigToJson(tree, geminPath);
updateJson(tree, geminPath, (json) => ({
...json,
contextFileName: 'AGENTS.md',
}));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There appears to be a naming inconsistency in the AI agent file configuration. The code sets contextFileName: 'AGENTS.md' for Gemini configuration, but the documentation and tests reference both CLAUDE.md and GEMINI.md files.

The implementation generates files with different names:

  1. In the file generation section, it creates CLAUDE.md and AGENTS.md
  2. In the tests, it expects CLAUDE.md and GEMINI.md
  3. The documentation mentions CLAUDE.md and AGENTS.md

This inconsistency could lead to confusion for users and potential issues with AI assistant integration. Consider standardizing the naming convention across the codebase to ensure that the generated files, configuration settings, and documentation all align with the same file naming pattern.

Suggested change
const geminPath = join(options.directory, '.gemini', 'settings.json');
addMcpConfigToJson(tree, geminPath);
updateJson(tree, geminPath, (json) => ({
...json,
contextFileName: 'AGENTS.md',
}));
const geminPath = join(options.directory, '.gemini', 'settings.json');
addMcpConfigToJson(tree, geminPath);
updateJson(tree, geminPath, (json) => ({
...json,
contextFileName: 'GEMINI.md',
}));

Spotted by Diamond

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

Comment on lines +120 to +144
function addMcpConfigToJson(tree: Tree, path: string) {
let mcpConfig: any = {};

if (tree.exists(path)) {
const mcpContent = tree.read(path).toString();
mcpConfig = JSON.parse(mcpContent);
}

if (mcpConfig.mcpServers) {
mcpConfig.mcpServers['nx-mcp'] = {
type: 'stdio',
command: 'npx',
args: ['nx', 'mcp'],
};
} else {
mcpConfig.mcpServers = {
'nx-mcp': {
type: 'stdio',
command: 'npx',
args: ['nx', 'mcp'],
},
};
}
tree.write(path, JSON.stringify(mcpConfig, null, 2));
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addMcpConfigToJson function lacks error handling for JSON parsing. If an existing configuration file contains invalid JSON, the JSON.parse(mcpContent) call will throw an exception, potentially leaving the tree in an inconsistent state. Consider adding a try/catch block to gracefully handle malformed JSON:

try {
  mcpConfig = JSON.parse(mcpContent);
} catch (error) {
  // Either log the error and continue with empty config
  // or throw a more descriptive error
  console.warn(`Invalid JSON in ${path}, creating new configuration`);
  // mcpConfig remains an empty object
}

This would prevent configuration corruption when encountering invalid JSON files.

Suggested change
function addMcpConfigToJson(tree: Tree, path: string) {
let mcpConfig: any = {};
if (tree.exists(path)) {
const mcpContent = tree.read(path).toString();
mcpConfig = JSON.parse(mcpContent);
}
if (mcpConfig.mcpServers) {
mcpConfig.mcpServers['nx-mcp'] = {
type: 'stdio',
command: 'npx',
args: ['nx', 'mcp'],
};
} else {
mcpConfig.mcpServers = {
'nx-mcp': {
type: 'stdio',
command: 'npx',
args: ['nx', 'mcp'],
},
};
}
tree.write(path, JSON.stringify(mcpConfig, null, 2));
}
function addMcpConfigToJson(tree: Tree, path: string) {
let mcpConfig: any = {};
if (tree.exists(path)) {
const mcpContent = tree.read(path).toString();
try {
mcpConfig = JSON.parse(mcpContent);
} catch (error) {
console.warn(`Invalid JSON in ${path}, creating new configuration`);
// mcpConfig remains an empty object
}
}
if (mcpConfig.mcpServers) {
mcpConfig.mcpServers['nx-mcp'] = {
type: 'stdio',
command: 'npx',
args: ['nx', 'mcp'],
};
} else {
mcpConfig.mcpServers = {
'nx-mcp': {
type: 'stdio',
command: 'npx',
args: ['nx', 'mcp'],
},
};
}
tree.write(path, JSON.stringify(mcpConfig, null, 2));
}

Spotted by Diamond

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

Copy link
Contributor

@nx-cloud nx-cloud bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nx Cloud is proposing a fix for your failed CI:

We've identified and fixed the issue where the setupAiAgentsGenerator was not generating the GEMINI.md file as expected by the tests. The generator now includes logic to generate the GEMINI.md file when it doesn't exist, matching the pattern used for CLAUDE.md and AGENTS.md files.

We verified this fix by re-running workspace:test.

diff --git a/packages/workspace/src/generators/set-up-ai-agents/set-up-ai-agents.ts b/packages/workspace/src/generators/set-up-ai-agents/set-up-ai-agents.ts
index 0bf106c..9fa95e5 100644
--- a/packages/workspace/src/generators/set-up-ai-agents/set-up-ai-agents.ts
+++ b/packages/workspace/src/generators/set-up-ai-agents/set-up-ai-agents.ts
@@ -97,6 +97,12 @@ export async function setupAiAgentsGeneratorImpl(
       agent: 'CLAUDE',
     });
   }
+  if (!tree.exists(join(options.directory, 'GEMINI.md'))) {
+    generateFiles(tree, join(__dirname, './files'), options.directory, {
+      writeNxCloudRules: options.writeNxCloudRules,
+      agent: 'GEMINI',
+    });
+  }
   if (!tree.exists(join(options.directory, 'AGENTS.md'))) {
     generateFiles(tree, join(__dirname, './files'), options.directory, {
       writeNxCloudRules: options.writeNxCloudRules,

Apply fix via Nx Cloud  Reject fix via Nx Cloud  Nx CloudView interactive diff and more actions ↗


⚙️ An Nx Cloud workspace admin can disable these reviews in workspace settings.

Comment on lines +87 to +89
} catch {
await cleanup();
return undefined;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Potential resource leak: The error handling in this catch block returns undefined after calling cleanup(), but the caller at line 44 will attempt to destructure and call cleanup() again on this undefined value, resulting in a runtime error. Consider either:

  1. Rethrowing the error after cleanup:
try {
  // ...
} catch (error) {
  await cleanup();
  throw error;
}
  1. Or returning an object with a no-op cleanup function:
try {
  // ...
} catch (error) {
  await cleanup();
  return { module: null, cleanup: async () => {} };
}

This ensures the caller can safely destructure and call the cleanup function regardless of whether the import succeeds.

Suggested change
} catch {
await cleanup();
return undefined;
} catch (error) {
await cleanup()
return { module: null, cleanup: async () => {} }

Spotted by Diamond

Fix in Graphite


Is this helpful? React 👍 or 👎 to let us know.

@@ -16,7 +16,8 @@ export async function ensurePackageHasProvenance(
): Promise<void> {
// this is used for locally released versions without provenance
// do not set this for other reasons or you might be exposed to security risks
if (process.env.NX_SKIP_PROVENANCE_CHECK) {
// also skip this check during e2e tests because those rely on local packages without provenance
if (process.env.NX_SKIP_PROVENANCE_CHECK || process.env.NX_E2E_RUN_E2E) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just set NX_SKIP_PROVENANCE_CHECK in e2e

@@ -0,0 +1,154 @@
import { formatFiles, generateFiles, Tree } from '@nx/devkit';
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forego generateFiles and we can move this into nx

async function getLatestGeneratorUsingInstall(
options: NormalizedSetupAiAgentsGeneratorSchema
): Promise<{ module: any; cleanup: () => Promise<void> } | undefined> {
const { dir, cleanup } = createTempNpmDirectory(true);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use ensurePackage for this.

},
};
}
tree.write(path, JSON.stringify(mcpConfig, null, 2));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use writeJson or updateJson which will handle trailing commas and comments in the JSON files.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants