@@ -36,6 +36,23 @@ const DEFAULT_SUPPORTED_EXTENSIONS = [
3636 '.dockerfile' , '.tf' , '.hcl' ,
3737] ;
3838
39+ /**
40+ * Well-known extension-less filenames that should be indexed.
41+ * Users can extend this via CUSTOM_EXTENSIONLESS_FILENAMES env var (comma-separated).
42+ */
43+ const DEFAULT_EXTENSIONLESS_FILENAMES = new Set ( [
44+ 'Dockerfile' , 'dockerfile' ,
45+ 'Makefile' , 'makefile' , 'GNUmakefile' ,
46+ 'Jenkinsfile' ,
47+ 'Vagrantfile' ,
48+ 'Gemfile' , 'Rakefile' , 'Guardfile' ,
49+ 'Procfile' ,
50+ 'Brewfile' ,
51+ 'Caddyfile' ,
52+ 'Fastfile' ,
53+ 'Appfile' ,
54+ ] ) ;
55+
3956const DEFAULT_IGNORE_PATTERNS = [
4057 // Common build output and dependency directories
4158 'node_modules/**' ,
@@ -105,6 +122,7 @@ export class Context {
105122 private codeSplitter : Splitter ;
106123 private supportedExtensions : string [ ] ;
107124 private ignorePatterns : string [ ] ;
125+ private extensionlessFilenames : Set < string > ;
108126 private synchronizers = new Map < string , FileSynchronizer > ( ) ;
109127
110128 constructor ( config : ContextConfig = { } ) {
@@ -148,7 +166,14 @@ export class Context {
148166 // Remove duplicates
149167 this . ignorePatterns = [ ...new Set ( allIgnorePatterns ) ] ;
150168
151- console . log ( `[Context] 🔧 Initialized with ${ this . supportedExtensions . length } supported extensions and ${ this . ignorePatterns . length } ignore patterns` ) ;
169+ // Build extensionless filename set from defaults + env
170+ const envExtensionlessFilenames = this . getCustomExtensionlessFilenamesFromEnv ( ) ;
171+ this . extensionlessFilenames = new Set ( [
172+ ...DEFAULT_EXTENSIONLESS_FILENAMES ,
173+ ...envExtensionlessFilenames ,
174+ ] ) ;
175+
176+ console . log ( `[Context] 🔧 Initialized with ${ this . supportedExtensions . length } supported extensions, ${ this . extensionlessFilenames . size } extensionless filenames, and ${ this . ignorePatterns . length } ignore patterns` ) ;
152177 if ( envCustomExtensions . length > 0 ) {
153178 console . log ( `[Context] 📎 Loaded ${ envCustomExtensions . length } custom extensions from environment: ${ envCustomExtensions . join ( ', ' ) } ` ) ;
154179 }
@@ -680,7 +705,11 @@ export class Context {
680705 await traverseDirectory ( fullPath ) ;
681706 } else if ( entry . isFile ( ) ) {
682707 const ext = path . extname ( entry . name ) ;
683- if ( this . supportedExtensions . includes ( ext ) ) {
708+ if ( ext === '' ) {
709+ if ( this . extensionlessFilenames . has ( entry . name ) ) {
710+ files . push ( fullPath ) ;
711+ }
712+ } else if ( this . supportedExtensions . includes ( ext ) ) {
684713 files . push ( fullPath ) ;
685714 }
686715 }
@@ -1161,6 +1190,21 @@ export class Context {
11611190 }
11621191 }
11631192
1193+ /**
1194+ * Get custom extensionless filenames from environment variables.
1195+ * Supports CUSTOM_EXTENSIONLESS_FILENAMES as comma-separated list (e.g. "Dockerfile,Makefile").
1196+ */
1197+ private getCustomExtensionlessFilenamesFromEnv ( ) : string [ ] {
1198+ const envValue = envManager . get ( 'CUSTOM_EXTENSIONLESS_FILENAMES' ) ;
1199+ if ( ! envValue ) return [ ] ;
1200+ try {
1201+ return envValue . split ( ',' ) . map ( f => f . trim ( ) ) . filter ( f => f . length > 0 ) ;
1202+ } catch ( error ) {
1203+ console . warn ( `[Context] ⚠️ Failed to parse CUSTOM_EXTENSIONLESS_FILENAMES: ${ error } ` ) ;
1204+ return [ ] ;
1205+ }
1206+ }
1207+
11641208 /**
11651209 * Add custom extensions (from MCP or other sources) without replacing existing ones
11661210 * @param customExtensions Array of custom extensions to add
0 commit comments