Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 1 addition & 2 deletions packages/cli/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -237,8 +237,7 @@ verbatim.
Apps must NEVER use JSON files for persistence. This is a project
convention (documented in the scaffold's CONVENTIONS.md).
4. **Template files are verbatim copies** with `{{APP_NAME}}` substitution.
When editing `templates/AGENTS.md`, `templates/CLAUDE.md`,
`templates/CONVENTIONS.md`, `.cursorrules`, etc., remember they ship
When editing `templates/AGENTS.md`, `templates/CONVENTIONS.md`, or `.agents/skills/webjs/`, remember they ship
into every scaffolded app. Write for the audience of an AI agent
working inside a freshly-scaffolded WebJs project. `templates/AGENTS.md`
is the one exception to "verbatim": it carries a `{{PLAYBOOK}}` marker
Expand Down
4 changes: 2 additions & 2 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ the CLI gives you `webjs ui` automatically. See

The scaffold seeds opinionated defaults so AI agents produce consistent code:

- `AGENTS.md` + `CONVENTIONS.md` (the machine-readable contract)
- `.claude/`, `.cursorrules`, `.agents/rules/workflow.md` (Antigravity), `.github/copilot-instructions.md`
- `AGENTS.md` + `CONVENTIONS.md` + `.agents/skills/webjs/` (single cross-agent source of truth)
- `.agents/rules/workflow.md` & `.claude/` protective hooks
- `test/<feature>/` (with optional `browser/` / `e2e/` subfolders per kind) with example tests
- Tailwind CSS via CLI (no browser runtime at build time)
- TypeScript, `.editorconfig`, `.gitignore`
Expand Down
18 changes: 2 additions & 16 deletions packages/cli/lib/create.js
Original file line number Diff line number Diff line change
Expand Up @@ -568,26 +568,12 @@ export async function scaffoldApp(name, cwd, opts = {}) {
// --- Templates (AGENTS.md, CONVENTIONS.md, CLAUDE.md, test files, Claude hooks) ---

const templateFiles = [
// Single cross-agent source: a thin AGENTS.md points at the skill; the
// Single cross-agent source: AGENTS.md points at .agents/skills/webjs/; the
// .agents/rules workflow rules and the Claude enforcement hooks back it up.
'AGENTS.md',
'CONVENTIONS.md',
'.agents/rules/workflow.md',
// Per-agent files. Content is single-source (AGENTS.md + the skill); these
// are thin bridges plus each tool's own config and commit-nudge hook. Claude
// Code (CLAUDE.md @-imports AGENTS.md), Gemini CLI (GEMINI.md), Copilot in VS
// Code (copilot-instructions.md). Cursor / opencode / Antigravity read
// AGENTS.md natively; Cursor also gets a .cursorrules bridge, and each of
// Cursor / Gemini / opencode ships a "commit often" nudge hook.
'CLAUDE.md',
'GEMINI.md',
'.github/copilot-instructions.md',
'.cursorrules',
'.cursor/hooks.json',
'.cursor/hooks/nudge-uncommitted.sh',
'.gemini/settings.json',
'.gemini/hooks/nudge-uncommitted.sh',
'.opencode/plugins/nudge-uncommitted.ts',
// Claude Code config + the protective enforcement hooks (no design ceremony).
'.claude.json',
'.claude/settings.json',
Expand Down Expand Up @@ -629,7 +615,7 @@ export async function scaffoldApp(name, cwd, opts = {}) {
// rewrites; the three infra files get their file-specific transform. On Node,
// every file is copied byte-identical (the map is empty).
const PROSE_REWRITE = new Set([
'AGENTS.md', 'CLAUDE.md', 'CONVENTIONS.md', '.cursorrules',
'AGENTS.md', 'CLAUDE.md', 'CONVENTIONS.md',
'.agents/rules/workflow.md',
'test/hello/browser/hello.test.js', 'test/hello/e2e/hello.test.ts',
]);
Expand Down
8 changes: 0 additions & 8 deletions packages/cli/templates/.cursor/hooks.json

This file was deleted.

38 changes: 0 additions & 38 deletions packages/cli/templates/.cursor/hooks/nudge-uncommitted.sh

This file was deleted.

21 changes: 0 additions & 21 deletions packages/cli/templates/.cursorrules

This file was deleted.

42 changes: 0 additions & 42 deletions packages/cli/templates/.gemini/hooks/nudge-uncommitted.sh

This file was deleted.

15 changes: 0 additions & 15 deletions packages/cli/templates/.gemini/settings.json

This file was deleted.

9 changes: 0 additions & 9 deletions packages/cli/templates/.github/copilot-instructions.md

This file was deleted.

62 changes: 0 additions & 62 deletions packages/cli/templates/.opencode/plugins/nudge-uncommitted.ts

This file was deleted.

11 changes: 0 additions & 11 deletions packages/cli/templates/GEMINI.md

This file was deleted.

18 changes: 7 additions & 11 deletions test/scaffolds/scaffold-integration.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,19 +87,16 @@ test('scaffoldApp full-stack: writes the canonical full-stack app layout', async
assert.ok(existsSync(join(appDir, 'tsconfig.json')));

// Single cross-agent source (AGENTS.md + the one skill + the .agents workflow
// rules), with a per-agent file for each tool: thin bridges for the ones that
// do not read AGENTS.md natively (CLAUDE.md, GEMINI.md, copilot), a .cursorrules
// bridge, CONVENTIONS.md, and a commit-nudge hook for Cursor / Gemini / opencode.
for (const f of ['AGENTS.md', '.agents/skills/webjs/SKILL.md', '.agents/rules/workflow.md', 'CLAUDE.md', 'GEMINI.md', '.github/copilot-instructions.md', 'CONVENTIONS.md', '.cursorrules', '.cursor/hooks/nudge-uncommitted.sh', '.gemini/hooks/nudge-uncommitted.sh', '.opencode/plugins/nudge-uncommitted.ts', '.claude/settings.json', '.editorconfig']) {
// rules), CONVENTIONS.md, CLAUDE.md bridge, and Claude protective hooks.
for (const f of ['AGENTS.md', '.agents/skills/webjs/SKILL.md', '.agents/rules/workflow.md', 'CLAUDE.md', 'CONVENTIONS.md', '.claude/settings.json', '.editorconfig']) {
assert.ok(existsSync(join(appDir, f)), `${f} should exist`);
}
// No design-distinctness ceremony (retired: gallery:clear does the reset job).
for (const f of ['LAYOUT-REFERENCE.md', '.claude/hooks/design-review-before-stop.sh', '.claude/skills/webjs-design-review']) {
// Per-agent files and design-distinctness ceremony removed.
for (const f of ['GEMINI.md', '.github/copilot-instructions.md', '.cursorrules', 'LAYOUT-REFERENCE.md', '.claude/hooks/design-review-before-stop.sh', '.claude/skills/webjs-design-review']) {
assert.ok(!existsSync(join(appDir, f)), `${f} should NOT exist in the scaffold`);
}
// The rule bridges are THIN (pointers to AGENTS.md / the skill), not full
// duplicates. .cursorrules + CONVENTIONS.md point at the skill.
for (const f of ['CLAUDE.md', 'GEMINI.md', '.github/copilot-instructions.md', '.cursorrules', 'CONVENTIONS.md']) {
// Thin bridges (pointers to AGENTS.md / the skill).
for (const f of ['CLAUDE.md', 'CONVENTIONS.md']) {
const src = readFileSync(join(appDir, f), 'utf8');
assert.ok(src.length < 2200, `${f} is a thin bridge, not a full rule duplicate`);
assert.match(src, /AGENTS\.md|\.agents\/skills\/webjs/, `${f} points at AGENTS.md or the skill`);
Expand Down Expand Up @@ -781,8 +778,7 @@ test('scaffoldApp: AGENTS.md build playbook is template-specific (#1076)', async
// and they must acknowledge the api showcase rather than only the UI gallery.
const apiConv = readFileSync(join(cwd, 'api-app', 'CONVENTIONS.md'), 'utf8');
const apiFlow = readFileSync(join(cwd, 'api-app', '.agents/rules/workflow.md'), 'utf8');
const apiCursor = readFileSync(join(cwd, 'api-app', '.cursorrules'), 'utf8');
for (const [label, md] of [['CONVENTIONS.md', apiConv], ['workflow.md', apiFlow], ['.cursorrules', apiCursor]]) {
for (const [label, md] of [['CONVENTIONS.md', apiConv], ['workflow.md', apiFlow]]) {
assert.doesNotMatch(md, /only while exploring|do not have to read|only (if|when) a task needs/i,
`api ${label}: no opt-out phrasing`);
}
Expand Down
Loading