duaer-spec 0.7.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/ADOPT.md CHANGED
@@ -32,13 +32,22 @@ npx duaer-spec init --here --ops
32
32
  npx duaer-spec update --method # rare; usually omit
33
33
  ```
34
34
 
35
- Works with **Cursor** and **Claude Code** (both hosts installed by default).
35
+ Works with **Cursor**, **Claude Code**, **Codex**, **GitHub Copilot**,
36
+ **Windsurf / Devin**, **Cline**, **Continue**, **Gemini CLI**, and **Aider**
37
+ (adapters installed by default).
36
38
 
37
39
  ## What you get
38
40
 
39
41
  - Autonomous job loop (ask → Brief → work → accept)
40
42
  - Cursor: `.cursor/rules` + `.cursor/skills`
41
43
  - Claude Code: `CLAUDE.md` + `.claude/rules` + `.claude/skills`
44
+ - Codex: `AGENTS.md` + `.agents/skills`
45
+ - Copilot: `.github/copilot-instructions.md`
46
+ - Windsurf / Devin: `.windsurf/rules`, `.devin/rules`
47
+ - Cline: `.clinerules/`
48
+ - Continue: `.continue/rules/`
49
+ - Gemini CLI: `GEMINI.md`
50
+ - Aider: `.aider.conf.yml` → reads `AGENTS.md`
42
51
  - `.duaer/handoff.json` + `duaer handoff` after worktree remove
43
52
  - Agent ops: `main` / `develop` / `feat` / `fix` + `.worktree/`
44
53
 
package/AGENTS.md CHANGED
@@ -19,6 +19,23 @@ documentation unless the adopting project explicitly overrides.
19
19
 
20
20
  Follow the project's [baseline](docs/baseline.md) (or its local equivalent).
21
21
 
22
+ ## Autonomous job loop (all hosts)
23
+
24
+ For product work (new behavior, fixes, refactors), **you** run Brief → work →
25
+ accept. Do **not** ask the human to type slash commands, phase names, or CLI
26
+ flags.
27
+
28
+ 1. Isolate: `feat|fix/<name>` + `.worktree/feat-<name>/` (or `fix-…`); never
29
+ reuse the Brief folder name as the worktree id.
30
+ 2. Follow the `duaer-do` skill under the host skill root (when the host has skills):
31
+ - Codex / shared: `.agents/skills/duaer-do/SKILL.md`
32
+ - Cursor: `.cursor/skills/duaer-do/SKILL.md`
33
+ - Claude Code: `.claude/skills/duaer-do/SKILL.md`
34
+ - Copilot / Windsurf / Cline / Continue / Gemini / Aider: follow this section
35
+ and the host adapter files installed by `duaer init`
36
+ 3. Briefs live in `.duaer/specs/<nnn-slug>/`. Method notes: [`DUADER.md`](DUADER.md).
37
+ 4. One handoff line; never claim done unless `delivery.json` is `accepted`.
38
+
22
39
  ## GitHub Issue Handling
23
40
 
24
41
  When the user provides a GitHub issue URL (or an unambiguous issue number for
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.0 — 2026-09-15
4
+
5
+ ### More common agent hosts
6
+
7
+ - GitHub Copilot: `.github/copilot-instructions.md`
8
+ - Windsurf + Devin: `.windsurf/rules/`, `.devin/rules/`
9
+ - Cline: `.clinerules/`
10
+ - Continue: `.continue/rules/`
11
+ - Gemini CLI: `GEMINI.md`
12
+ - Aider: `.aider.conf.yml` (reads `AGENTS.md`)
13
+ - Cursor / Claude Code / Codex unchanged
14
+
15
+ ## 0.8.0 — 2026-09-15
16
+
17
+ ### Codex host
18
+
19
+ - Mirror `duaer-*` skills to `.agents/skills/` (Codex discovery path)
20
+ - `AGENTS.md` always-on section names the Codex / Cursor / Claude skill roots
21
+ - Cursor and Claude Code installs unchanged
22
+
3
23
  ## 0.7.0 — 2026-09-15
4
24
 
5
25
  ### Claude Code host
package/CLAUDE.md CHANGED
@@ -13,12 +13,19 @@ This repository uses **duaer-spec**: coding agents are digital employees.
13
13
 
14
14
  ## Layout
15
15
 
16
- | Host | Rules | Skills |
16
+ | Host | Always-on | Skills / notes |
17
17
  |---|---|---|
18
- | Claude Code | `.claude/rules/` | `.claude/skills/` |
19
18
  | Cursor | `.cursor/rules/` | `.cursor/skills/` |
20
-
21
- Both are installed by `npx duaer-spec init --here` / `update`.
19
+ | Claude Code | `CLAUDE.md` + `.claude/rules/` | `.claude/skills/` |
20
+ | Codex | `AGENTS.md` | `.agents/skills/` |
21
+ | Copilot | `.github/copilot-instructions.md` | also reads `AGENTS.md` |
22
+ | Windsurf / Devin | `.windsurf/rules/`, `.devin/rules/` | — |
23
+ | Cline | `.clinerules/` | — |
24
+ | Continue | `.continue/rules/` | — |
25
+ | Gemini CLI | `GEMINI.md` | — |
26
+ | Aider | `.aider.conf.yml` | reads `AGENTS.md` |
27
+
28
+ Installed by `npx duaer-spec init --here` / `update`.
22
29
 
23
30
  ## Branches
24
31
 
package/DUADER.md CHANGED
@@ -14,7 +14,7 @@ runs Brief → work → accept. Humans are not the operators of the phase machin
14
14
 
15
15
  ## Agent procedure (autonomous)
16
16
 
17
- Follow the `duaer-do` skill (`.cursor/skills/` or `.claude/skills/`) on every product ask — **without**
17
+ Follow the `duaer-do` skill (`.cursor/skills/`, `.claude/skills/`, or `.agents/skills/`) on every product ask — **without**
18
18
  waiting for a slash invocation:
19
19
 
20
20
  1. Assign Brief + `active-job.json`
@@ -38,8 +38,13 @@ Humans need not configure it for everyday use.
38
38
  .duaer/active-job.json
39
39
  .duaer/specs/<nnn-slug>/ # Brief (≠ worktree folder name)
40
40
  spec.md | tasks.md | delivery.json
41
- .cursor/rules|skills/ # Cursor host
42
- .claude/rules|skills/ + CLAUDE.md # Claude Code host
41
+ .cursor/rules|skills/ # Cursor
42
+ .claude/rules|skills/ + CLAUDE.md # Claude Code
43
+ .agents/skills/ + AGENTS.md # Codex (+ shared skills)
44
+ .github/copilot-instructions.md # Copilot
45
+ .windsurf/rules/ + .devin/rules/ # Windsurf / Devin
46
+ .clinerules/ + .continue/rules/ # Cline / Continue
47
+ GEMINI.md + .aider.conf.yml # Gemini / Aider
43
48
  ```
44
49
 
45
50
  Worktree and Brief are different layers. Prefer
package/GEMINI.md ADDED
@@ -0,0 +1,9 @@
1
+ # GEMINI.md — duaer-spec
2
+
3
+ This project uses **duaer-spec**: coding agents are digital employees.
4
+
5
+ **Precedence:** `AGENTS.md` (ops) wins over `DUADER.md` / `.duaer/` (method).
6
+
7
+ - Follow `AGENTS.md` § Autonomous job loop
8
+ - Job skill (when available): `.agents/skills/duaer-do/SKILL.md`
9
+ - Branches / worktrees: `docs/agent/branching-and-release.md`
package/README.md CHANGED
@@ -19,9 +19,9 @@ npx duaer-spec init --here
19
19
  npx duaer-spec update
20
20
  ```
21
21
 
22
- Then use **Cursor** or **Claude Code** as usual — describe what you want.
22
+ Then use **Cursor**, **Claude Code**, **Codex**, **Copilot**, **Windsurf**, **Cline**, **Continue**, **Gemini**, or **Aider** — describe what you want.
23
23
 
24
- Install writes both `.cursor/` and `.claude/` (plus `CLAUDE.md`).
24
+ Install writes host adapters for each (see [`ADOPT.md`](ADOPT.md)).
25
25
 
26
26
  中文说明:[`README.zh-CN.md`](README.zh-CN.md)
27
27
 
package/README.zh-CN.md CHANGED
@@ -2,9 +2,9 @@
2
2
 
3
3
  **Duaer** 把 AI 编程助手变成**数字员工**:你用自然语言提需求,它自己跑 Spec → 实现 → 验收;只有交接干净才算完成。
4
4
 
5
- 你**不用**操作流程。装一次之后,在 **Cursor** **Claude Code** 里说话即可。
5
+ 你**不用**操作流程。装一次之后,在 **Cursor** / **Claude Code** / **Codex** / **Copilot** / **Windsurf** / **Cline** / **Continue** / **Gemini** / **Aider** 里说话即可。
6
6
 
7
- `init` / `update` 会同时写入 `.cursor/` 与 `.claude/`(以及 `CLAUDE.md`)。
7
+ `init` / `update` 会写入各宿主适配文件(详见 [`ADOPT.md`](ADOPT.md))。
8
8
 
9
9
  ## 安装
10
10
 
package/bin/duaer.mjs CHANGED
@@ -211,20 +211,25 @@ function installMethod(target, opts) {
211
211
 
212
212
  installCursorMethod(target, opts)
213
213
  installClaudeMethod(target, opts)
214
+ installCodexMethod(target, opts)
214
215
 
215
216
  copyPath(join(PKG_ROOT, 'DUADER.md'), join(target, 'DUADER.md'), opts)
216
217
  console.log(' DUADER.md')
217
218
  ensureWorktreeGitignore(target)
218
219
  }
219
220
 
220
- function installCursorMethod(target, opts) {
221
- ensureDir(join(target, '.cursor', 'skills'))
221
+ function mirrorDuaerSkills(target, skillsDir, opts, label) {
222
+ ensureDir(skillsDir)
222
223
  const skillsRoot = join(PKG_ROOT, '.cursor', 'skills')
223
224
  for (const name of readdirSync(skillsRoot)) {
224
225
  if (!name.startsWith('duaer-')) continue
225
- copyPath(join(skillsRoot, name), join(target, '.cursor', 'skills', name), opts)
226
+ copyPath(join(skillsRoot, name), join(skillsDir, name), opts)
226
227
  }
227
- console.log(' .cursor/skills/duaer-*')
228
+ console.log(` ${label}`)
229
+ }
230
+
231
+ function installCursorMethod(target, opts) {
232
+ mirrorDuaerSkills(target, join(target, '.cursor', 'skills'), opts, '.cursor/skills/duaer-*')
228
233
 
229
234
  ensureDir(join(target, '.cursor', 'rules'))
230
235
  copyPath(
@@ -236,13 +241,12 @@ function installCursorMethod(target, opts) {
236
241
  }
237
242
 
238
243
  function installClaudeMethod(target, opts) {
239
- ensureDir(join(target, '.claude', 'skills'))
240
- const skillsRoot = join(PKG_ROOT, '.cursor', 'skills')
241
- for (const name of readdirSync(skillsRoot)) {
242
- if (!name.startsWith('duaer-')) continue
243
- copyPath(join(skillsRoot, name), join(target, '.claude', 'skills', name), opts)
244
- }
245
- console.log(' .claude/skills/duaer-* (mirrored from .cursor/skills)')
244
+ mirrorDuaerSkills(
245
+ target,
246
+ join(target, '.claude', 'skills'),
247
+ opts,
248
+ '.claude/skills/duaer-* (mirrored from .cursor/skills)',
249
+ )
246
250
 
247
251
  ensureDir(join(target, '.claude', 'rules'))
248
252
  const claudeRule = join(PKG_ROOT, '.claude', 'rules', 'duaer-spec.md')
@@ -269,6 +273,155 @@ function installClaudeMethod(target, opts) {
269
273
  console.log(' CLAUDE.md')
270
274
  }
271
275
 
276
+ function installCodexMethod(target, opts) {
277
+ // Codex discovers repo skills under .agents/skills (not .codex/skills).
278
+ // Always-on guidance is AGENTS.md (installed with ops).
279
+ mirrorDuaerSkills(
280
+ target,
281
+ join(target, '.agents', 'skills'),
282
+ opts,
283
+ '.agents/skills/duaer-* (Codex; mirrored from .cursor/skills)',
284
+ )
285
+ }
286
+
287
+ function stripRuleComment(md) {
288
+ return md.replace(/^<!--[\s\S]*?-->\s*/, '').trim()
289
+ }
290
+
291
+ function withYamlFrontmatter(body, lines) {
292
+ return `---\n${lines.join('\n')}\n---\n\n${stripRuleComment(body)}\n`
293
+ }
294
+
295
+ function loadPackagedRule(name) {
296
+ const claudePath = join(PKG_ROOT, '.claude', 'rules', name)
297
+ if (existsSync(claudePath)) return readFileSync(claudePath, 'utf8')
298
+ const mdc = name.replace(/\.md$/, '.mdc')
299
+ return cursorRuleToClaude(readFileSync(join(PKG_ROOT, '.cursor', 'rules', mdc), 'utf8'), '.claude')
300
+ }
301
+
302
+ function genericHostRuleBody(name) {
303
+ let body = loadPackagedRule(name)
304
+ body = body.replaceAll(
305
+ '.claude/skills/duaer-do/SKILL.md',
306
+ 'AGENTS.md § Autonomous job loop (and `.agents/skills/duaer-do/SKILL.md` when present)',
307
+ )
308
+ body = body.replaceAll('.claude/skills/', '.agents/skills/')
309
+ return body
310
+ }
311
+
312
+ function defaultGeminiMd() {
313
+ return `# GEMINI.md — duaer-spec
314
+
315
+ This project uses **duaer-spec**: coding agents are digital employees.
316
+
317
+ **Precedence:** \`AGENTS.md\` (ops) wins over \`DUADER.md\` / \`.duaer/\` (method).
318
+
319
+ - Follow \`AGENTS.md\` § Autonomous job loop
320
+ - Job skill (when available): \`.agents/skills/duaer-do/SKILL.md\`
321
+ - Branches / worktrees: \`docs/agent/branching-and-release.md\`
322
+ `
323
+ }
324
+
325
+ function defaultCopilotInstructions() {
326
+ return `# GitHub Copilot — duaer-spec
327
+
328
+ Treat agents as **digital employees**. Humans state intent; you run Brief → work → accept.
329
+
330
+ **Precedence:** \`AGENTS.md\` > \`DUADER.md\` / \`.duaer/\`
331
+
332
+ 1. Isolate on \`feat|fix/<name>\` under \`.worktree/feat-<name>/\` (never name the worktree after \`.duaer/specs/<nnn-slug>/\`).
333
+ 2. Follow \`AGENTS.md\` § Autonomous job loop (skill: \`.agents/skills/duaer-do/SKILL.md\` when present).
334
+ 3. Do not ask the human to operate slash commands or phase names.
335
+ 4. One handoff line; never claim done unless \`delivery.json\` is \`accepted\`.
336
+
337
+ See also: \`DUADER.md\`, \`docs/agent/branching-and-release.md\`.
338
+ `
339
+ }
340
+
341
+ function defaultAiderConf() {
342
+ return `# duaer-spec — point Aider at the shared agent contract
343
+ read: [AGENTS.md, DUADER.md]
344
+ `
345
+ }
346
+
347
+ function installRuleSet(target, relDir, names, frontmatterLines, opts, label) {
348
+ const dir = join(target, ...relDir.split('/'))
349
+ ensureDir(dir)
350
+ for (const name of names) {
351
+ const dest = join(dir, name)
352
+ if (existsSync(dest) && !opts.force) {
353
+ console.log(`skip (exists): ${dest} (use --force to overwrite)`)
354
+ continue
355
+ }
356
+ const body = genericHostRuleBody(name)
357
+ const content = frontmatterLines?.length
358
+ ? withYamlFrontmatter(body, frontmatterLines)
359
+ : `${stripRuleComment(body)}\n`
360
+ ensureDir(dirname(dest))
361
+ writeFileSync(dest, content, 'utf8')
362
+ }
363
+ console.log(` ${label}`)
364
+ }
365
+
366
+ function installExtraHosts(target, opts) {
367
+ console.log('Installing common host adapters…')
368
+
369
+ // GitHub Copilot
370
+ ensureDir(join(target, '.github'))
371
+ writeIfNeeded(
372
+ join(target, '.github', 'copilot-instructions.md'),
373
+ defaultCopilotInstructions(),
374
+ opts,
375
+ )
376
+ console.log(' .github/copilot-instructions.md')
377
+
378
+ // Gemini CLI
379
+ const geminiSrc = join(PKG_ROOT, 'GEMINI.md')
380
+ if (existsSync(geminiSrc)) {
381
+ copyPath(geminiSrc, join(target, 'GEMINI.md'), opts)
382
+ } else {
383
+ writeIfNeeded(join(target, 'GEMINI.md'), defaultGeminiMd(), opts)
384
+ }
385
+ console.log(' GEMINI.md')
386
+
387
+ // Aider
388
+ writeIfNeeded(join(target, '.aider.conf.yml'), defaultAiderConf(), opts)
389
+ console.log(' .aider.conf.yml')
390
+
391
+ const ruleNames = ['duaer-spec.md', 'agents-workflow.md', 'ai-ui-copy.md']
392
+
393
+ // Windsurf (Cascade) + Devin Desktop
394
+ installRuleSet(
395
+ target,
396
+ '.windsurf/rules',
397
+ ruleNames,
398
+ ['trigger: always_on'],
399
+ opts,
400
+ '.windsurf/rules/*',
401
+ )
402
+ installRuleSet(
403
+ target,
404
+ '.devin/rules',
405
+ ruleNames,
406
+ ['trigger: always_on'],
407
+ opts,
408
+ '.devin/rules/*',
409
+ )
410
+
411
+ // Cline
412
+ installRuleSet(target, '.clinerules', ruleNames, null, opts, '.clinerules/*')
413
+
414
+ // Continue.dev
415
+ installRuleSet(
416
+ target,
417
+ '.continue/rules',
418
+ ruleNames,
419
+ ['alwaysApply: true'],
420
+ opts,
421
+ '.continue/rules/*',
422
+ )
423
+ }
424
+
272
425
  function cursorRuleToClaude(mdc, skillHost) {
273
426
  let body = mdc.replace(/^---\n[\s\S]*?\n---\n+/, (fm) => {
274
427
  const desc = (fm.match(/^description:\s*(.+)$/m) || [])[1]
@@ -406,6 +559,9 @@ function cmdInit(opts) {
406
559
  if (opts.mode === 'all' || opts.mode === 'ops') {
407
560
  installOps(target, opts)
408
561
  }
562
+ if (opts.mode === 'all' || opts.mode === 'method' || opts.mode === 'ops') {
563
+ installExtraHosts(target, opts)
564
+ }
409
565
  if (opts.mode === 'all' || opts.mode === 'method') {
410
566
  writeInitMarker(target, opts)
411
567
  }
@@ -413,7 +569,7 @@ function cmdInit(opts) {
413
569
  console.log(`
414
570
  Hired.
415
571
 
416
- Talk to the agent in plain language.
572
+ Talk to the agent in plain language (Cursor, Claude, Codex, Copilot, and more).
417
573
  Later update: npx duaer-spec update
418
574
  `)
419
575
  }
@@ -551,7 +707,14 @@ function checkWorkplace(target) {
551
707
  ['.cursor/skills/duaer-specify/SKILL.md', 'method'],
552
708
  ['.claude/rules/duaer-spec.md', 'method'],
553
709
  ['.claude/skills/duaer-do/SKILL.md', 'method'],
710
+ ['.agents/skills/duaer-do/SKILL.md', 'method'],
554
711
  ['CLAUDE.md', 'method'],
712
+ ['GEMINI.md', 'method'],
713
+ ['.github/copilot-instructions.md', 'method'],
714
+ ['.windsurf/rules/duaer-spec.md', 'method'],
715
+ ['.clinerules/duaer-spec.md', 'method'],
716
+ ['.continue/rules/duaer-spec.md', 'method'],
717
+ ['.aider.conf.yml', 'method'],
555
718
  ['AGENTS.md', 'ops'],
556
719
  ['.cursor/rules/agents-workflow.mdc', 'ops'],
557
720
  ['.claude/rules/agents-workflow.md', 'ops'],
@@ -39,6 +39,8 @@ the table for their app.
39
39
  | E2E-012 | `README.zh-CN.md` covers install, update, branch model | manual |
40
40
  | E2E-013 | Worktree id ≠ Brief `<nnn-slug>`; path is `.worktree/feat-…/.duaer/specs/…` | manual |
41
41
  | E2E-014 | Init installs Cursor + Claude hosts (`CLAUDE.md`, `.claude/skills`) | manual |
42
+ | E2E-015 | Init installs Codex skills under `.agents/skills/` | manual |
43
+ | E2E-016 | Init installs Copilot/Windsurf/Cline/Continue/Gemini/Aider adapters | manual |
42
44
 
43
45
  ## Traceability
44
46
 
@@ -58,3 +60,5 @@ the table for their app.
58
60
  | E2E-012 | `README.zh-CN.md` | Chinese 说明文档 |
59
61
  | E2E-013 | AGENTS / branching naming | Avoid double `<nnn-slug>` |
60
62
  | E2E-014 | Claude + Cursor install | Dual host |
63
+ | E2E-015 | Codex `.agents/skills` | Triple host |
64
+ | E2E-016 | Extra host adapters | Copilot+Windsurf+Cline+… |
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "duaer-spec",
3
- "version": "0.7.0",
4
- "description": "Digital employees for Cursor and Claude Code; main/develop/feat/fix",
3
+ "version": "0.9.0",
4
+ "description": "Digital employees for Cursor, Claude, Codex, Copilot, Windsurf, Cline, Continue, Gemini, Aider",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "duaer": "bin/duaer.mjs",
@@ -14,6 +14,7 @@
14
14
  ".claude",
15
15
  "AGENTS.md",
16
16
  "CLAUDE.md",
17
+ "GEMINI.md",
17
18
  "DUADER.md",
18
19
  "ADOPT.md",
19
20
  "CHANGELOG.md",
@@ -47,7 +48,16 @@
47
48
  "ai-engineering",
48
49
  "controllable-delivery",
49
50
  "claude",
50
- "claude-code"
51
+ "claude-code",
52
+ "codex",
53
+ "openai-codex",
54
+ "copilot",
55
+ "windsurf",
56
+ "cline",
57
+ "continue",
58
+ "gemini",
59
+ "aider",
60
+ "devin"
51
61
  ],
52
62
  "license": "MIT",
53
63
  "scripts": {