@@ -58,7 +58,8 @@ export class ClineIgnoreController {
5858 }
5959
6060 /**
61- * Load custom patterns from .clineignore if it exists
61+ * Load custom patterns from .clineignore if it exists.
62+ * Supports "!include <filename>" to load additional ignore patterns from other files.
6263 */
6364 private async loadClineIgnore ( ) : Promise < void > {
6465 try {
@@ -68,7 +69,7 @@ export class ClineIgnoreController {
6869 if ( await fileExistsAtPath ( ignorePath ) ) {
6970 const content = await fs . readFile ( ignorePath , "utf8" )
7071 this . clineIgnoreContent = content
71- this . ignoreInstance . add ( content )
72+ await this . processIgnoreContent ( content )
7273 this . ignoreInstance . add ( ".clineignore" )
7374 } else {
7475 this . clineIgnoreContent = undefined
@@ -79,6 +80,61 @@ export class ClineIgnoreController {
7980 }
8081 }
8182
83+ /**
84+ * Process ignore content and apply all ignore patterns
85+ */
86+ private async processIgnoreContent ( content : string ) : Promise < void > {
87+ // Optimization: first check if there are any !include directives
88+ if ( ! content . includes ( "!include " ) ) {
89+ this . ignoreInstance . add ( content )
90+ return
91+ }
92+
93+ // Process !include directives
94+ const combinedContent = await this . processClineIgnoreIncludes ( content )
95+ this . ignoreInstance . add ( combinedContent )
96+ }
97+
98+ /**
99+ * Process !include directives and combine all included file contents
100+ */
101+ private async processClineIgnoreIncludes ( content : string ) : Promise < string > {
102+ let combinedContent = ""
103+ const lines = content . split ( / \r ? \n / )
104+
105+ for ( const line of lines ) {
106+ const trimmedLine = line . trim ( )
107+
108+ if ( ! trimmedLine . startsWith ( "!include " ) ) {
109+ combinedContent += "\n" + line
110+ continue
111+ }
112+
113+ // Process !include directive
114+ const includedContent = await this . readIncludedFile ( trimmedLine )
115+ if ( includedContent ) {
116+ combinedContent += "\n" + includedContent
117+ }
118+ }
119+
120+ return combinedContent
121+ }
122+
123+ /**
124+ * Read content from an included file specified by !include directive
125+ */
126+ private async readIncludedFile ( includeLine : string ) : Promise < string | null > {
127+ const includePath = includeLine . substring ( "!include " . length ) . trim ( )
128+ const resolvedIncludePath = path . join ( this . cwd , includePath )
129+
130+ if ( ! ( await fileExistsAtPath ( resolvedIncludePath ) ) ) {
131+ console . debug ( `[ClineIgnore] Included file not found: ${ resolvedIncludePath } ` )
132+ return null
133+ }
134+
135+ return await fs . readFile ( resolvedIncludePath , "utf8" )
136+ }
137+
82138 /**
83139 * Check if a file should be accessible to the LLM
84140 * @param filePath - Path to check (relative to cwd)
0 commit comments