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" ;
23import chalk from "chalk" ;
34import { Command , Option as CommandOption } from "commander" ;
5+ import { join } from "node:path" ;
6+ import * as semver from "semver" ;
47import { z } from "zod" ;
58import { 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" ;
1310import {
1411 GithubRulesManifestLoader ,
1512 loadRulesManifest ,
@@ -18,13 +15,16 @@ import {
1815 RulesManifest ,
1916 RulesManifestVersionOption ,
2017} 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" ;
2718import { 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" ;
2828
2929const clients = [
3030 "claude-code" ,
@@ -372,16 +372,58 @@ async function performInstallDefaultOptionForClient(
372372
373373 // Try and read the existing rules file
374374 const rulesFileAbsolutePath = join ( process . cwd ( ) , rulesFilePath ) ;
375- await writeToFile ( rulesFileAbsolutePath , rulesFileContents , mergeStrategy ) ;
375+ await writeToFile ( rulesFileAbsolutePath , rulesFileContents , mergeStrategy , option . name ) ;
376376
377377 return { option, location : rulesFilePath } ;
378378}
379379
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+
380422async function performInstallClaudeCodeSubagentOptionForClient ( option : RulesManifestVersionOption ) {
381423 const rulesFilePath = ".claude/agents/trigger-dev-task-writer.md" ;
382- const rulesFileContents = `# ${ option . title } \n\n ${ option . contents } ` ;
424+ const rulesFileContents = option . contents ;
383425
384- await writeToFile ( rulesFilePath , rulesFileContents , "overwrite" ) ;
426+ await writeToFile ( rulesFilePath , rulesFileContents , "overwrite" , option . name ) ;
385427
386428 return { option, location : rulesFilePath } ;
387429}
@@ -437,7 +479,7 @@ async function resolveRulesFileMergeStrategyForClient(clientName: (typeof client
437479 case "agents.md" :
438480 case "gemini-cli" :
439481 case "claude-code" : {
440- return "append " ;
482+ return "replace " ;
441483 }
442484 default : {
443485 return "overwrite" ;
@@ -478,7 +520,11 @@ async function resolveRulesFileContentsForClient(
478520 ) ;
479521 }
480522 default : {
481- return option . contents ;
523+ return $output (
524+ `<!-- TRIGGER.DEV ${ option . name } START -->` ,
525+ option . contents ,
526+ `<!-- TRIGGER.DEV ${ option . name } END -->`
527+ ) ;
482528 }
483529 }
484530}
0 commit comments