Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
9fcd1ed
feat: bundle version-matched docs into app-tools and generate AGENTS.…
keepview Jul 13, 2026
900244e
feat: trim docs bundle to coding-essential sections
keepview Jul 15, 2026
7697bd0
ci: build i18n-utils before unit tests
keepview Jul 22, 2026
1ae2afe
fix(app-tools): generate docs bundle at build time so --ignore-script…
keepview Jul 24, 2026
04933d8
refactor(app-tools): flatten docs bundle to main-doc/ (drop docs/en n…
keepview Jul 24, 2026
9b5bd27
refactor(app-tools): rename docs bundle dir to docs/ and slim down AG…
keepview Jul 24, 2026
fb3095a
test(create): update AGENTS.md path assertion to docs/ bundle dir
keepview Jul 24, 2026
6701ca3
docs(ai-coding-agents): update bundled-docs path to docs/
keepview Jul 24, 2026
dfd470d
fix(app-tools): add docs source to nx build inputs so the bundle stay…
keepview Jul 24, 2026
9dcbda9
chore: minimize pnpm-lock.yaml diff to the create importer change only
keepview Jul 24, 2026
c0b0dc4
feat(create): add `agents-md` codemod for existing projects
keepview Jul 27, 2026
3345261
docs(ai-coding-agents): rewrite the bundled-docs & AGENTS.md section …
keepview Jul 27, 2026
5c16114
docs(ai-coding-agents): lead with bundled docs, reframe llms.txt as f…
keepview Jul 27, 2026
b46653b
docs(ai-coding-agents): restructure the AI section into distinct topics
keepview Jul 27, 2026
5fc54cf
docs(ai-coding-agents): tidy AGENTS.md heading, fix llms-full link, e…
keepview Jul 27, 2026
26b619b
fix(create): place the agent-rules block at the top of AGENTS.md
keepview Jul 27, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .changeset/agent-knowledge-supply.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@modern-js/app-tools': minor
'@modern-js/create': minor
---

feat: agent knowledge supply — bundle version-matched English docs into the app-tools tarball (`docs/`) on publish, and generate `AGENTS.md` / `CLAUDE.md` in new projects created by `@modern-js/create` (skip with `--no-agents-md`). Existing projects can run `npx @modern-js/create agents-md` to add or idempotently refresh these files after an upgrade (managed marker block is updated in place, user content is preserved). Also fixes boolean flags swallowing the following positional argument (e.g. `create --sub my-app`).

feat: Agent 知识供给 —— 发布时将版本匹配的英文文档打进 app-tools tarball(`docs/`),并在 `@modern-js/create` 新建项目时默认生成 `AGENTS.md` / `CLAUDE.md`(`--no-agents-md` 可跳过)。已有项目可运行 `npx @modern-js/create agents-md` 在升级后补齐或幂等更新这两个文件(就地更新托管标记块,保留用户自定义内容)。同时修复布尔参数吞掉后续位置参数的问题(如 `create --sub my-app`)。
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"prepare-build": "cross-env NX_DAEMON=false NX_REJECT_UNKNOWN_LOCAL_CACHE=0 nx run-many -t build -p @modern-js/* --exclude=@modern-js/main-doc,@modern-js/module-tools-docs --maxParallel=4",
"prepare": "npm run prepare-build && husky install",
"prepare-build-continue": "cross-env NX_DAEMON=false NX_REJECT_UNKNOWN_LOCAL_CACHE=0 nx run-many -t build -p @modern-js/* --exclude=@modern-js/main-doc,@modern-js/module-tools-docs --nxBail=false --maxParallel=4 || echo 'Build completed with some failures, continuing...'",
"build:required": "cross-env NX_DAEMON=false nx run-many -t build -p @modern-js/builder @modern-js/bff-core @modern-js/utils",
"build:required": "cross-env NX_DAEMON=false nx run-many -t build -p @modern-js/builder @modern-js/bff-core @modern-js/utils @modern-js/i18n-utils",
"lint": "biome check",
"change": "changeset add",
"bump": "changeset version",
Expand Down
23 changes: 19 additions & 4 deletions packages/document/docs/en/guides/get-started/ai-coding-agents.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,31 @@ sidebar_position: 6

# Modern.js For AI

Modern.js provides a toolkit for AI agents that helps developers use AI to efficiently complete feature development, dependency upgrades, and version migration for Modern.js applications.
Modern.js provides a toolkit for AI agents that makes your project agent-ready out of the box, helping you use AI to develop, upgrade, and migrate Modern.js applications more accurately and efficiently.

## Bundled docs

Modern.js ships the English docs that match your installed version together with `@modern-js/app-tools`. After you install or upgrade, they live at `node_modules/@modern-js/app-tools/docs/`, available offline with no extra setup.

AI agents use them to get APIs, config, and conventions that exactly match your framework version, rather than relying on potentially outdated training data.

## AGENTS.md

`AGENTS.md` gives AI coding agents project-level guidance — telling them to read the bundled docs before making changes and to follow Modern.js conventions. A `CLAUDE.md` is generated alongside it, reusing the same guidance for Claude Code via the `@AGENTS.md` import.

- **New projects**: `npx @modern-js/create` generates both files by default; pass `--no-agents-md` to skip them.
- **Existing projects**: run `npx @modern-js/create agents-md` at the project root to create or update them. Re-run it any time; your own additions are preserved.

Modern.js only maintains the content inside the `<!-- BEGIN:modernjs-agent-rules -->` markers in `AGENTS.md`; anything you write outside them is left untouched.

## llms.txt

Modern.js docs follow the [llms.txt specification](https://llmstxt.org/), auto-generated by [`@rspress/plugin-llms`](https://rspress.rs/plugin/official-plugins/llms), accessible via `/llms.txt` or `/llms-full.txt`:
llms.txt is an online documentation index following the [llms.txt specification](https://llmstxt.org/), auto-generated by [`@rspress/plugin-llms`](https://rspress.rs/plugin/official-plugins/llms) for AI tools to retrieve the full docs online:

- Index: [`https://modernjs.dev/llms.txt`](https://modernjs.dev/llms.txt)
- Full text: `https://modernjs.dev/llms-full.txt` (large — fetch on demand)
- Full text: [`https://modernjs.dev/llms-full.txt`](https://modernjs.dev/llms-full.txt) (large — fetch on demand)

Most "what is this API / config" questions can be answered from llms.txt. Just let your agent retrieve it on demand; no need to copy docs into your project.
Use it when you need content beyond the bundled docs — just let your agent retrieve it on demand, no need to copy docs into your project. Typical cases: looking up another framework version, a section not included in the bundle, or getting Modern.js information outside of a project (for example before a project exists, or when researching on its own).

## Skills

Expand Down
23 changes: 19 additions & 4 deletions packages/document/docs/zh/guides/get-started/ai-coding-agents.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,31 @@ sidebar_position: 6

# Modern.js For AI

Modern.js 为 AI Agent 提供了一套工具套件,帮助开发者利用 AI 高效完成 Modern.js 应用的功能开发、依赖升级与版本迁移工作。
Modern.js 为 AI Agent 提供了一套工具套件,让项目开箱即为 agent-ready,帮助你更准确、高效地用 AI 完成 Modern.js 应用的开发、升级与迁移。

## 随包文档

Modern.js 把与你安装版本一致的英文文档随 `@modern-js/app-tools` 一起分发。安装或升级后,文档即位于 `node_modules/@modern-js/app-tools/docs/`,离线可用、无需额外配置。

AI Agent 由此获取与当前框架版本严格匹配的 API、配置与约定,而不是依赖可能过时的训练数据。

## AGENTS.md

`AGENTS.md` 是给 AI 编码助手的项目指引,告诉它在动手前先阅读随包文档、并遵循 Modern.js 的约定;同时会生成 `CLAUDE.md`,通过 `@AGENTS.md` 让 Claude Code 复用同一份指引。

- **新建项目**:`npx @modern-js/create` 默认生成这两个文件,加 `--no-agents-md` 可跳过。
- **已有项目**:在项目根运行 `npx @modern-js/create agents-md` 生成或更新,可随时重复运行,你添加的自定义内容会被保留。

Modern.js 只维护 `AGENTS.md` 中 `<!-- BEGIN:modernjs-agent-rules -->` 标记内的内容,标记之外你写的内容不会被改动。

## llms.txt

Modern.js 文档遵循 [llms.txt 规范](https://llmstxt.org/),由 [`@rspress/plugin-llms`](https://rspress.rs/plugin/official-plugins/llms) 自动生成,可通过 `/llms.txt` 或 `/llms-full.txt` 供 AI 工具检索
llms.txt 是遵循 [llms.txt 规范](https://llmstxt.org/) 的在线文档索引,由 [`@rspress/plugin-llms`](https://rspress.rs/plugin/official-plugins/llms) 自动生成,供 AI 工具在线检索完整文档

- 索引:[`https://modernjs.dev/llms.txt`](https://modernjs.dev/llms.txt)
- 全文:`https://modernjs.dev/llms-full.txt`(体积较大,按需取片段)
- 全文:[`https://modernjs.dev/llms-full.txt`](https://modernjs.dev/llms-full.txt)(体积较大,按需取片段)

大部分「这个 API / 配置是什么」类问题,靠 llms.txt 即可解决。让你的 Agent 按需检索它即可,不必把文档复制进项目。
当需要查阅随包文档之外的内容时,让 Agent 在线检索它即可,不必把文档复制进项目。典型场景包括:查阅其他框架版本、随包未包含的章节,或在 Modern.js 项目之外获取信息(例如尚未创建项目、或独立查阅资料时)

## Skills

Expand Down
1 change: 1 addition & 0 deletions packages/solutions/app-tools/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
docs
4 changes: 4 additions & 0 deletions packages/solutions/app-tools/.npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,7 @@ jest.config.js
tsconfig.json
CHANGELOG.md


# docs bundle for AI agents (copy-main-doc.mjs) — re-include everything
!docs/
!docs/**
17 changes: 16 additions & 1 deletion packages/solutions/app-tools/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,25 @@
"modern": "./bin/modern.js",
"modern-app": "./bin/modern.js"
},
"nx": {
"targets": {
"build": {
"inputs": [
"build",
"^build",
"{workspaceRoot}/packages/document/docs/en/**/*"
],
"outputs": [
"{projectRoot}/dist",
"{projectRoot}/docs"
]
}
}
},
"scripts": {
"prepublishOnly": "only-allow-pnpm",
"dev": "rslib build --watch",
"build": "rslib build",
"build": "rslib build && node ./scripts/copy-main-doc.mjs",
"test": "rstest"
},
"dependencies": {
Expand Down
50 changes: 50 additions & 0 deletions packages/solutions/app-tools/scripts/copy-main-doc.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import fs from 'node:fs';
import path from 'node:path';
import { fileURLToPath } from 'node:url';

// Copies the English docs from packages/document into this package as
// `docs/`, so every project gets version-matched offline docs
// for AI coding agents (see AGENTS.md generated by @modern-js/create).
// Runs as part of `build` (see package.json build script + nx build
// outputs), so the bundle is produced whenever the package is built —
// including in CI/release where publish runs with `--ignore-scripts` and
// prepublishOnly would be skipped. The directory is gitignored, so it only
// materializes as a build output, never committed to the working tree.
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const pkgRoot = path.resolve(__dirname, '..');
const source = path.resolve(pkgRoot, '../../document/docs/en');
// Bundle root: docs land directly under `docs/` (no `docs/en` nesting) to
// keep the path agents read as short as possible.
const target = path.resolve(pkgRoot, 'docs');

// Top-level doc sections excluded from the bundle to keep it small.
// Agents rarely need these while coding (blog/showcase, narrative
// tutorials, framework-plugin authoring); llms.txt covers them online.
// Keep this list in sync with scripts/check-doc-bundle.mjs.
export const EXCLUDED_SECTIONS = ['community', 'tutorials', 'plugin'];

if (!fs.existsSync(source)) {
console.error(`[copy-main-doc] source docs not found: ${source}`);
process.exit(1);
}

fs.rmSync(target, { recursive: true, force: true });
fs.mkdirSync(path.dirname(target), { recursive: true });
fs.cpSync(source, target, {
recursive: true,
filter: src => {
const rel = path.relative(source, src);
const top = rel.split(path.sep)[0];
return rel === '' || !EXCLUDED_SECTIONS.includes(top);
},
});

const count = fs
.readdirSync(target, { recursive: true, withFileTypes: true })
.filter(entry => entry.isFile()).length;

if (count === 0) {
console.error('[copy-main-doc] no files copied');
process.exit(1);
}
console.log(`[copy-main-doc] bundled ${count} doc files into docs`);
4 changes: 3 additions & 1 deletion packages/toolkit/create/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,14 @@
"scripts": {
"build": "rslib build",
"dev": "rslib build -w",
"start": "node ./dist/index.js"
"start": "node ./dist/index.js",
"test": "rstest"
},
"devDependencies": {
"@modern-js/i18n-utils": "workspace:*",
"@modern-js/rslib": "workspace:*",
"@rslib/core": "0.23.2",
"@scripts/rstest-config": "workspace:*",
"@types/node": "^20",
"tsx": "^4.22.4",
"typescript": "^5"
Expand Down
7 changes: 7 additions & 0 deletions packages/toolkit/create/rstest.config.mts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { withTestPreset } from '@scripts/rstest-config';

export default withTestPreset({
root: __dirname,
testEnvironment: 'node',
globals: true,
});
102 changes: 102 additions & 0 deletions packages/toolkit/create/src/agents-md.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
import fs from 'node:fs';
import path from 'node:path';
import { i18n, localeKeys } from './locale';

// Codemod for existing projects: add or refresh AGENTS.md / CLAUDE.md so AI
// coding agents are pointed at the version-matched docs bundled in
// node_modules/@modern-js/app-tools/docs/. `@modern-js/create` only scaffolds
// these for new projects; this brings existing projects up to date on upgrade.
//
// The Modern.js-managed rules live between these markers. Everything outside
// them belongs to the user and is never touched, and the block itself is
// replaced in place on re-run, so this command is idempotent.
const BEGIN = '<!-- BEGIN:modernjs-agent-rules -->';
const END = '<!-- END:modernjs-agent-rules -->';
const CLAUDE_IMPORT = '@AGENTS.md';

// Read the managed block from the create template, so the codemod and the
// scaffolding share a single source of truth.
function readManagedBlock(templateDir: string): string {
const tpl = fs.readFileSync(path.join(templateDir, 'AGENTS.md'), 'utf-8');
const begin = tpl.indexOf(BEGIN);
const end = tpl.indexOf(END);
if (begin === -1 || end === -1 || end < begin) {
throw new Error(
'template/AGENTS.md is missing the modernjs-agent-rules markers',
);
}
return tpl.slice(begin, end + END.length);
}

function report(key: string, file: string): void {
console.log(i18n.t(key, { file }));
}

// Create AGENTS.md, refresh the managed block if present, or append it while
// preserving the user's own content.
function applyAgentsMd(targetDir: string, block: string): void {
const file = path.join(targetDir, 'AGENTS.md');
if (!fs.existsSync(file)) {
fs.writeFileSync(file, `${block}\n`, 'utf-8');
report(localeKeys.agentsCmd.created, 'AGENTS.md');
return;
}

const content = fs.readFileSync(file, 'utf-8');
const begin = content.indexOf(BEGIN);
const end = content.indexOf(END);
if (begin !== -1 && end !== -1 && end > begin) {
const next =
content.slice(0, begin) + block + content.slice(end + END.length);
if (next === content) {
report(localeKeys.agentsCmd.unchanged, 'AGENTS.md');
} else {
fs.writeFileSync(file, next, 'utf-8');
report(localeKeys.agentsCmd.updatedBlock, 'AGENTS.md');
}
return;
}

// No managed block yet: put ours at the top (the "read the docs first" rule
// should lead the file), keeping the user's existing content below it.
const rest = content.replace(/^\s*/, '');
fs.writeFileSync(file, rest ? `${block}\n\n${rest}` : `${block}\n`, 'utf-8');
report(localeKeys.agentsCmd.addedBlock, 'AGENTS.md');
}

// Create CLAUDE.md as an @AGENTS.md import, or add the import to an existing
// one (Claude Code reads CLAUDE.md, not AGENTS.md, so the bridge is required).
function applyClaudeMd(targetDir: string): void {
const file = path.join(targetDir, 'CLAUDE.md');
if (!fs.existsSync(file)) {
fs.writeFileSync(file, `${CLAUDE_IMPORT}\n`, 'utf-8');
report(localeKeys.agentsCmd.created, 'CLAUDE.md');
return;
}

const content = fs.readFileSync(file, 'utf-8');
if (content.split('\n').some(line => line.trim() === CLAUDE_IMPORT)) {
report(localeKeys.agentsCmd.unchanged, 'CLAUDE.md');
return;
}
fs.writeFileSync(
file,
`${CLAUDE_IMPORT}\n\n${content.replace(/^\s*/, '')}`,
'utf-8',
);
report(localeKeys.agentsCmd.linked, 'CLAUDE.md');
}

export function runAgentsMd(templateDir: string, targetDir: string): void {
if (!fs.existsSync(targetDir)) {
console.error(
i18n.t(localeKeys.agentsCmd.targetNotFound, { dir: targetDir }),
);
process.exit(1);
}
const block = readManagedBlock(templateDir);
applyAgentsMd(targetDir, block);
applyClaudeMd(targetDir);
console.log('');
console.log(i18n.t(localeKeys.agentsCmd.done));
}
Loading
Loading