1
- import { confirm , intro , isCancel , log , multiselect , outro , select , spinner } from "@clack/prompts" ;
1
+ import { confirm , intro , isCancel , log , multiselect , outro } from "@clack/prompts" ;
2
+ import { ResolvedConfig } from "@trigger.dev/core/v3/build" ;
2
3
import chalk from "chalk" ;
3
4
import { Command , Option as CommandOption } from "commander" ;
5
+ import { join } from "node:path" ;
6
+ import * as semver from "semver" ;
4
7
import { z } from "zod" ;
5
8
import { OutroCommandError , wrapCommandAction } from "../cli/common.js" ;
6
- import {
7
- readConfigHasSeenRulesInstallPrompt ,
8
- readConfigLastRulesInstallPromptVersion ,
9
- writeConfigHasSeenRulesInstallPrompt ,
10
- writeConfigLastRulesInstallPromptVersion ,
11
- } from "../utilities/configFiles.js" ;
12
- import { printStandloneInitialBanner } from "../utilities/initialBanner.js" ;
9
+ import { loadConfig } from "../config.js" ;
13
10
import {
14
11
GithubRulesManifestLoader ,
15
12
loadRulesManifest ,
@@ -18,13 +15,16 @@ import {
18
15
RulesManifest ,
19
16
RulesManifestVersionOption ,
20
17
} from "../rules/manifest.js" ;
21
- import { logger } from "../utilities/logger.js" ;
22
- import { join } from "node:path" ;
23
- import { writeToFile } from "../utilities/fileSystem.js" ;
24
- import * as semver from "semver" ;
25
- import { loadConfig } from "../config.js" ;
26
- import { ResolvedConfig } from "@trigger.dev/core/v3/build" ;
27
18
import { cliLink } from "../utilities/cliOutput.js" ;
19
+ import {
20
+ readConfigHasSeenRulesInstallPrompt ,
21
+ readConfigLastRulesInstallPromptVersion ,
22
+ writeConfigHasSeenRulesInstallPrompt ,
23
+ writeConfigLastRulesInstallPromptVersion ,
24
+ } from "../utilities/configFiles.js" ;
25
+ import { pathExists , readFile , safeWriteFile } from "../utilities/fileSystem.js" ;
26
+ import { printStandloneInitialBanner } from "../utilities/initialBanner.js" ;
27
+ import { logger } from "../utilities/logger.js" ;
28
28
29
29
const clients = [
30
30
"claude-code" ,
@@ -372,16 +372,58 @@ async function performInstallDefaultOptionForClient(
372
372
373
373
// Try and read the existing rules file
374
374
const rulesFileAbsolutePath = join ( process . cwd ( ) , rulesFilePath ) ;
375
- await writeToFile ( rulesFileAbsolutePath , rulesFileContents , mergeStrategy ) ;
375
+ await writeToFile ( rulesFileAbsolutePath , rulesFileContents , mergeStrategy , option . name ) ;
376
376
377
377
return { option, location : rulesFilePath } ;
378
378
}
379
379
380
+ async function writeToFile (
381
+ path : string ,
382
+ contents : string ,
383
+ mergeStrategy : "overwrite" | "replace" = "overwrite" ,
384
+ sectionName : string
385
+ ) {
386
+ const exists = await pathExists ( path ) ;
387
+
388
+ if ( exists ) {
389
+ switch ( mergeStrategy ) {
390
+ case "overwrite" : {
391
+ await safeWriteFile ( path , contents ) ;
392
+ break ;
393
+ }
394
+ case "replace" : {
395
+ const existingContents = await readFile ( path ) ;
396
+
397
+ const pattern = new RegExp (
398
+ `<!-- TRIGGER.DEV ${ sectionName } START -->.*?<!-- TRIGGER.DEV ${ sectionName } END -->` ,
399
+ "gs"
400
+ ) ;
401
+
402
+ // If the section name is not found, just append the new content
403
+ if ( ! pattern . test ( existingContents ) ) {
404
+ await safeWriteFile ( path , existingContents + "\n\n" + contents ) ;
405
+ break ;
406
+ }
407
+
408
+ const updatedContent = existingContents . replace ( pattern , contents ) ;
409
+
410
+ await safeWriteFile ( path , updatedContent ) ;
411
+ break ;
412
+ }
413
+ default : {
414
+ throw new Error ( `Unknown merge strategy: ${ mergeStrategy } ` ) ;
415
+ }
416
+ }
417
+ } else {
418
+ await safeWriteFile ( path , contents ) ;
419
+ }
420
+ }
421
+
380
422
async function performInstallClaudeCodeSubagentOptionForClient ( option : RulesManifestVersionOption ) {
381
423
const rulesFilePath = ".claude/agents/trigger-dev-task-writer.md" ;
382
- const rulesFileContents = `# ${ option . title } \n\n ${ option . contents } ` ;
424
+ const rulesFileContents = option . contents ;
383
425
384
- await writeToFile ( rulesFilePath , rulesFileContents , "overwrite" ) ;
426
+ await writeToFile ( rulesFilePath , rulesFileContents , "overwrite" , option . name ) ;
385
427
386
428
return { option, location : rulesFilePath } ;
387
429
}
@@ -437,7 +479,7 @@ async function resolveRulesFileMergeStrategyForClient(clientName: (typeof client
437
479
case "agents.md" :
438
480
case "gemini-cli" :
439
481
case "claude-code" : {
440
- return "append " ;
482
+ return "replace " ;
441
483
}
442
484
default : {
443
485
return "overwrite" ;
@@ -478,7 +520,11 @@ async function resolveRulesFileContentsForClient(
478
520
) ;
479
521
}
480
522
default : {
481
- return option . contents ;
523
+ return $output (
524
+ `<!-- TRIGGER.DEV ${ option . name } START -->` ,
525
+ option . contents ,
526
+ `<!-- TRIGGER.DEV ${ option . name } END -->`
527
+ ) ;
482
528
}
483
529
}
484
530
}
0 commit comments