ctxman 3.0.0 → 3.1.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.
Files changed (223) hide show
  1. package/.ctxman/llm-profiles.json +1067 -39
  2. package/.ctxman/profiles/backend-team.json +13 -0
  3. package/.ctxman/profiles/default.json +12 -0
  4. package/.ctxman/profiles/devops-team.json +21 -0
  5. package/.ctxman/profiles/frontend-team.json +20 -0
  6. package/.ctxman/templates/bug-fix.json +17 -0
  7. package/.ctxman/templates/code-review.json +9 -0
  8. package/.ctxman/templates/documentation.json +9 -0
  9. package/.ctxman/templates/feature.json +9 -0
  10. package/.ctxman/templates/full-context.json +9 -0
  11. package/.ctxman/templates/refactoring.json +18 -0
  12. package/.ctxman/templates/testing.json +9 -0
  13. package/.ctxman/wizard-profiles/security-audit/profile.json +7 -1
  14. package/LICENSE +21 -0
  15. package/README.md +380 -136
  16. package/bin/cli.js +1880 -529
  17. package/bin/cm-ask.js +18 -13
  18. package/bin/cm-audit.js +124 -0
  19. package/bin/cm-count.js +151 -0
  20. package/bin/cm-gitingest.js +128 -115
  21. package/bin/cm-map.js +242 -0
  22. package/bin/cm-mcp.js +293 -0
  23. package/bin/cm-pack.js +405 -0
  24. package/bin/cm-policy.js +170 -0
  25. package/bin/cm-pr.js +248 -0
  26. package/bin/cm-search.js +178 -0
  27. package/bin/cm-update.js +128 -128
  28. package/bin/cm-why.js +197 -0
  29. package/bin/mcp-server.js +8 -24
  30. package/ctxman.js +237 -183
  31. package/examples/README.md +19 -4
  32. package/examples/github-actions/ctxman-check.yml +49 -0
  33. package/examples/wizard-profiles/security-audit/profile.json +7 -1
  34. package/index.d.ts +1422 -0
  35. package/index.js +55 -31
  36. package/lib/agents/pr-failure-agent.js +48 -45
  37. package/lib/analyzers/ai-suggester.js +451 -0
  38. package/lib/analyzers/dependency-scanner.js +505 -0
  39. package/lib/analyzers/duplicate-detector.js +264 -0
  40. package/lib/analyzers/go-method-analyzer.js +151 -110
  41. package/lib/analyzers/import-tracker.js +431 -0
  42. package/lib/analyzers/method-analyzer.js +1055 -434
  43. package/lib/analyzers/performance-dashboard.js +683 -0
  44. package/lib/analyzers/token-calculator.js +895 -504
  45. package/lib/analyzers/unused-exports-detector.js +336 -0
  46. package/lib/api/mcp/install.js +424 -0
  47. package/lib/api/mcp/prompts.js +281 -281
  48. package/lib/api/mcp/resources.js +300 -241
  49. package/lib/api/mcp/sandbox.js +89 -0
  50. package/lib/api/mcp/server.js +675 -312
  51. package/lib/api/mcp/start.js +125 -0
  52. package/lib/api/mcp/transports/HttpSseTransport.js +60 -52
  53. package/lib/api/rest/server.js +105 -28
  54. package/lib/cache/CacheManager.js +9 -17
  55. package/lib/core/Analyzer.js +16 -10
  56. package/lib/core/ContextBuilder.js +19 -28
  57. package/lib/core/Reporter.js +15 -14
  58. package/lib/core/Scanner.js +81 -12
  59. package/lib/count/index.js +100 -0
  60. package/lib/formatters/format-registry.js +394 -372
  61. package/lib/formatters/gitingest-formatter.js +656 -621
  62. package/lib/formatters/toon-formatter-v1.3.js +637 -632
  63. package/lib/formatters/toon-formatter.js +239 -240
  64. package/lib/integrations/git/BlameTracker.js +4 -4
  65. package/lib/integrations/git/DiffAnalyzer.js +38 -31
  66. package/lib/integrations/git/GitClient.js +71 -53
  67. package/lib/lsp/server.js +311 -0
  68. package/lib/map/graph.js +299 -0
  69. package/lib/map/imports.js +233 -0
  70. package/lib/map/index.js +33 -0
  71. package/lib/map/rank.js +253 -0
  72. package/lib/map/render.js +346 -0
  73. package/lib/map/resolver.js +574 -0
  74. package/lib/pack/budget.js +111 -0
  75. package/lib/pack/code-lexer.js +360 -0
  76. package/lib/pack/compress.js +414 -0
  77. package/lib/pack/index.js +354 -0
  78. package/lib/pack/renderers/common.js +134 -0
  79. package/lib/pack/renderers/index.js +24 -0
  80. package/lib/pack/renderers/json.js +47 -0
  81. package/lib/pack/renderers/markdown.js +54 -0
  82. package/lib/pack/renderers/plain.js +38 -0
  83. package/lib/pack/renderers/xml.js +85 -0
  84. package/lib/pack/select.js +177 -0
  85. package/lib/pack/split.js +182 -0
  86. package/lib/pack/tree.js +35 -0
  87. package/lib/parsers/gitignore-parser.js +113 -107
  88. package/lib/parsers/method-filter-parser.js +50 -33
  89. package/lib/plugins/ExporterPlugin.js +3 -3
  90. package/lib/plugins/LanguagePlugin.js +3 -3
  91. package/lib/plugins/PluginManager.js +7 -13
  92. package/lib/policy/audit.js +294 -0
  93. package/lib/policy/enforce.js +125 -0
  94. package/lib/policy/ignore-files.js +169 -0
  95. package/lib/policy/index.js +52 -0
  96. package/lib/policy/policy.js +489 -0
  97. package/lib/pr/diff-parser.js +267 -0
  98. package/lib/pr/method-mapper.js +148 -0
  99. package/lib/pr/pr-context.js +829 -0
  100. package/lib/pr/pr-git.js +149 -0
  101. package/lib/pr/pr-renderer.js +644 -0
  102. package/lib/pr/related-tests.js +296 -0
  103. package/lib/rag/DataSourcePlugin.js +5 -5
  104. package/lib/rag/EmbeddingProvider.js +19 -8
  105. package/lib/rag/Indexer.js +14 -5
  106. package/lib/rag/VectorStoreFactory.js +3 -3
  107. package/lib/rag/sources/FileDataSource.js +6 -6
  108. package/lib/rag/stores/BaseVectorStore.js +5 -5
  109. package/lib/rag/stores/ChromaDBStore.js +10 -10
  110. package/lib/rag/stores/LanceDBStore.js +29 -19
  111. package/lib/rag/stores/PineconeStore.js +11 -9
  112. package/lib/search/bm25.js +433 -0
  113. package/lib/search/code-units.js +201 -0
  114. package/lib/search/symbols.js +189 -0
  115. package/lib/ui/dashboard.js +120 -89
  116. package/lib/ui/index.js +1 -6
  117. package/lib/ui/init-wizard-ui.js +550 -0
  118. package/lib/ui/progress-bar.js +94 -88
  119. package/lib/ui/select-input.js +40 -32
  120. package/lib/ui/template-selector.js +99 -0
  121. package/lib/ui/wizard.js +374 -329
  122. package/lib/utils/claude-token-counter.js +151 -0
  123. package/lib/utils/cli-output.js +17 -0
  124. package/lib/utils/clipboard-utils.js +49 -50
  125. package/lib/utils/config-utils.js +81 -66
  126. package/lib/utils/context-versioning.js +532 -0
  127. package/lib/utils/error-handler.js +112 -112
  128. package/lib/utils/file-utils.js +153 -69
  129. package/lib/utils/format-converter.js +356 -283
  130. package/lib/utils/git-utils.js +366 -294
  131. package/lib/utils/llm-cost-estimator.js +281 -0
  132. package/lib/utils/llm-detector.js +242 -78
  133. package/lib/utils/logger.js +243 -237
  134. package/lib/utils/messages.js +355 -0
  135. package/lib/utils/multi-repo-manager.js +364 -0
  136. package/lib/utils/profile-manager.js +380 -0
  137. package/lib/utils/safe-read.js +61 -0
  138. package/lib/utils/secret-redactor.js +61 -0
  139. package/lib/utils/snapshot-manager.js +679 -0
  140. package/lib/utils/template-manager.js +378 -0
  141. package/lib/utils/token-utils.js +201 -170
  142. package/lib/utils/tokenizer-adapter.js +421 -377
  143. package/lib/utils/updater.js +539 -506
  144. package/lib/watch/FileWatcher.js +12 -8
  145. package/lib/watch/IncrementalAnalyzer.js +7 -7
  146. package/lib/why/coupling.js +81 -0
  147. package/lib/why/errors.js +23 -0
  148. package/lib/why/git.js +169 -0
  149. package/lib/why/history.js +108 -0
  150. package/lib/why/index.js +720 -0
  151. package/lib/why/ownership.js +79 -0
  152. package/lib/why/paths.js +207 -0
  153. package/lib/why/references.js +259 -0
  154. package/lib/why/render.js +722 -0
  155. package/lib/why/search.js +358 -0
  156. package/lib/why/target.js +389 -0
  157. package/lib/wizards/config-generator.js +255 -0
  158. package/lib/wizards/project-detector.js +571 -0
  159. package/package.json +44 -10
  160. package/.ctxman/logs/ctxman-2026-07-02.log +0 -156
  161. package/.ctxman/self-knowledge/documents.lance/_transactions/0-b3dd1558-f95b-44b9-a154-18e8c330ae7a.txn +0 -0
  162. package/.ctxman/self-knowledge/documents.lance/_transactions/1-44bff6d4-e552-4010-a769-e09ad822698d.txn +0 -0
  163. package/.ctxman/self-knowledge/documents.lance/_transactions/10-37260794-5947-4ecb-b4c8-d732f58f40f1.txn +0 -0
  164. package/.ctxman/self-knowledge/documents.lance/_transactions/11-0d52a883-5518-463c-9b6d-986c3af89dfd.txn +0 -0
  165. package/.ctxman/self-knowledge/documents.lance/_transactions/12-ae354646-52f2-49c9-90fb-2e6ed8932663.txn +0 -0
  166. package/.ctxman/self-knowledge/documents.lance/_transactions/13-5d7d5e57-27da-498b-b734-091b9d38da13.txn +0 -0
  167. package/.ctxman/self-knowledge/documents.lance/_transactions/14-558ce928-810b-4252-a364-fdd1ee6f8a25.txn +0 -0
  168. package/.ctxman/self-knowledge/documents.lance/_transactions/15-27e3a58f-8b64-43b8-a9f4-e3369446968b.txn +0 -0
  169. package/.ctxman/self-knowledge/documents.lance/_transactions/16-a110c390-e5c8-4464-b976-bc7f5195fa15.txn +0 -0
  170. package/.ctxman/self-knowledge/documents.lance/_transactions/17-97513225-53de-4216-b61a-6337bd0cc4ad.txn +0 -0
  171. package/.ctxman/self-knowledge/documents.lance/_transactions/18-5ba450f0-c527-459c-bf4f-6d79b5e4285f.txn +0 -0
  172. package/.ctxman/self-knowledge/documents.lance/_transactions/19-600d3a63-5225-49e9-b8b7-30e037b564ab.txn +0 -0
  173. package/.ctxman/self-knowledge/documents.lance/_transactions/2-48a61b4e-92cf-4342-8376-914c1b99a9f9.txn +0 -0
  174. package/.ctxman/self-knowledge/documents.lance/_transactions/20-121dd912-5410-410e-84ff-82c7a23604a0.txn +0 -0
  175. package/.ctxman/self-knowledge/documents.lance/_transactions/3-bc6844ab-7ea3-4bb3-9ee1-538ce5664a9c.txn +0 -0
  176. package/.ctxman/self-knowledge/documents.lance/_transactions/4-d5e1754f-dbb5-454e-a9be-2a7da8d7bcf9.txn +0 -0
  177. package/.ctxman/self-knowledge/documents.lance/_transactions/5-4fae93df-0568-4b6f-8acf-8bef4bba6047.txn +0 -0
  178. package/.ctxman/self-knowledge/documents.lance/_transactions/6-4b1b8b87-068e-49a3-ba2b-d8dae628b252.txn +0 -0
  179. package/.ctxman/self-knowledge/documents.lance/_transactions/7-63d040fb-d2fa-4c0f-bed0-53411918a7b0.txn +0 -0
  180. package/.ctxman/self-knowledge/documents.lance/_transactions/8-c5628cf6-264c-420f-aab8-bc96a9083591.txn +0 -0
  181. package/.ctxman/self-knowledge/documents.lance/_transactions/9-c94570aa-5e53-4fcb-971f-cecc1d1d5492.txn +0 -0
  182. package/.ctxman/self-knowledge/documents.lance/_versions/1.manifest +0 -0
  183. package/.ctxman/self-knowledge/documents.lance/_versions/10.manifest +0 -0
  184. package/.ctxman/self-knowledge/documents.lance/_versions/11.manifest +0 -0
  185. package/.ctxman/self-knowledge/documents.lance/_versions/12.manifest +0 -0
  186. package/.ctxman/self-knowledge/documents.lance/_versions/13.manifest +0 -0
  187. package/.ctxman/self-knowledge/documents.lance/_versions/14.manifest +0 -0
  188. package/.ctxman/self-knowledge/documents.lance/_versions/15.manifest +0 -0
  189. package/.ctxman/self-knowledge/documents.lance/_versions/16.manifest +0 -0
  190. package/.ctxman/self-knowledge/documents.lance/_versions/17.manifest +0 -0
  191. package/.ctxman/self-knowledge/documents.lance/_versions/18.manifest +0 -0
  192. package/.ctxman/self-knowledge/documents.lance/_versions/19.manifest +0 -0
  193. package/.ctxman/self-knowledge/documents.lance/_versions/2.manifest +0 -0
  194. package/.ctxman/self-knowledge/documents.lance/_versions/20.manifest +0 -0
  195. package/.ctxman/self-knowledge/documents.lance/_versions/21.manifest +0 -0
  196. package/.ctxman/self-knowledge/documents.lance/_versions/3.manifest +0 -0
  197. package/.ctxman/self-knowledge/documents.lance/_versions/4.manifest +0 -0
  198. package/.ctxman/self-knowledge/documents.lance/_versions/5.manifest +0 -0
  199. package/.ctxman/self-knowledge/documents.lance/_versions/6.manifest +0 -0
  200. package/.ctxman/self-knowledge/documents.lance/_versions/7.manifest +0 -0
  201. package/.ctxman/self-knowledge/documents.lance/_versions/8.manifest +0 -0
  202. package/.ctxman/self-knowledge/documents.lance/_versions/9.manifest +0 -0
  203. package/.ctxman/self-knowledge/documents.lance/data/000010010011011101000010de8621405d9d5cb06540dbf02c.lance +0 -0
  204. package/.ctxman/self-knowledge/documents.lance/data/0000101001011100011000003fb62a4aa8978974075c144f1c.lance +0 -0
  205. package/.ctxman/self-knowledge/documents.lance/data/000011010000100111001011c6cc824d628f3bb1f4e04cd5d0.lance +0 -0
  206. package/.ctxman/self-knowledge/documents.lance/data/001000001000011001011100d8f74349ada090b332cd1df669.lance +0 -0
  207. package/.ctxman/self-knowledge/documents.lance/data/01000001111010001000010045ab44467bb1e7e4d8ae06bd58.lance +0 -0
  208. package/.ctxman/self-knowledge/documents.lance/data/01000101101110111110011131ef904241a89e1ffb6ddaf8e3.lance +0 -0
  209. package/.ctxman/self-knowledge/documents.lance/data/010010110000010000011010fbfcc145c6a8a827b28057a07e.lance +0 -0
  210. package/.ctxman/self-knowledge/documents.lance/data/1000011000101010001110003fb4f045c3835982efa1405324.lance +0 -0
  211. package/.ctxman/self-knowledge/documents.lance/data/100111011101110111101011f4396b410fa06af3b028d204e6.lance +0 -0
  212. package/.ctxman/self-knowledge/documents.lance/data/100111100111101000001100596b174e00995d6cc2969cc8dc.lance +0 -0
  213. package/.ctxman/self-knowledge/documents.lance/data/1010001100011000110010102ea16b484d887c7c9725feffd6.lance +0 -0
  214. package/.ctxman/self-knowledge/documents.lance/data/101101100010101111110111c5230944d9b3af7301b6392dda.lance +0 -0
  215. package/.ctxman/self-knowledge/documents.lance/data/1011011100100111111110105892bf41b5a530fedd7cf516f1.lance +0 -0
  216. package/.ctxman/self-knowledge/documents.lance/data/10111110000010001011110164e8774742bade87b483c10f36.lance +0 -0
  217. package/.ctxman/self-knowledge/documents.lance/data/1100000100010110001110103ffaca40a2a42c85067ebaf9ae.lance +0 -0
  218. package/.ctxman/self-knowledge/documents.lance/data/110000010001110110101110664bde4c76a78dfc14b05e83b8.lance +0 -0
  219. package/.ctxman/self-knowledge/documents.lance/data/11001100111000010100110050645c4281b1f35b2022234f7f.lance +0 -0
  220. package/.ctxman/self-knowledge/documents.lance/data/1101111011001100110111017214924a368f5719eab2246619.lance +0 -0
  221. package/.ctxman/self-knowledge/documents.lance/data/1110000111001010001000002150c24dcab653d39d07032e63.lance +0 -0
  222. package/.ctxman/self-knowledge/documents.lance/data/1110100000000100000011014d20534967a18b5c87721659ff.lance +0 -0
  223. package/.ctxman/self-knowledge/documents.lance/data/11110101111010000101011135a0114ef2b35dc6f1297a3381.lance +0 -0
@@ -0,0 +1,571 @@
1
+ /**
2
+ * Project Detector
3
+ * Automatically detects project type based on files and dependencies
4
+ * FEAT-001: Configuration Wizard
5
+ */
6
+
7
+ import fs from 'fs';
8
+ import path from 'path';
9
+
10
+ /**
11
+ * Project type detectors configuration
12
+ * Each detector has files to check, dependencies to look for, and priority
13
+ */
14
+ const DETECTORS = {
15
+ monorepo: {
16
+ name: 'Monorepo',
17
+ files: ['lerna.json', 'nx.json', 'pnpm-workspace.yaml', 'turbo.json'],
18
+ checkDirs: ['packages', 'apps'],
19
+ priority: 10,
20
+ patterns: ['**/packages/*', '**/apps/*'],
21
+ },
22
+ typescript: {
23
+ name: 'TypeScript',
24
+ files: ['tsconfig.json'],
25
+ extensions: ['.ts', '.tsx'],
26
+ priority: 5,
27
+ dependencies: ['typescript'],
28
+ },
29
+ react: {
30
+ name: 'React',
31
+ dependencies: ['react', 'react-dom'],
32
+ extensions: ['.jsx', '.tsx'],
33
+ files: ['.reactrc', 'react.config.js'],
34
+ priority: 4,
35
+ },
36
+ nextjs: {
37
+ name: 'Next.js',
38
+ dependencies: ['next'],
39
+ files: ['next.config.js', 'next.config.mjs', 'next.config.ts'],
40
+ priority: 6,
41
+ },
42
+ vue: {
43
+ name: 'Vue.js',
44
+ dependencies: ['vue'],
45
+ extensions: ['.vue'],
46
+ files: ['vue.config.js', 'vite.config.js'],
47
+ priority: 4,
48
+ },
49
+ svelte: {
50
+ name: 'Svelte',
51
+ dependencies: ['svelte'],
52
+ extensions: ['.svelte'],
53
+ files: ['svelte.config.js'],
54
+ priority: 4,
55
+ },
56
+ angular: {
57
+ name: 'Angular',
58
+ dependencies: ['@angular/core'],
59
+ files: ['angular.json'],
60
+ priority: 5,
61
+ },
62
+ nodejs: {
63
+ name: 'Node.js',
64
+ files: ['package.json'],
65
+ extensions: ['.js', '.mjs', '.cjs'],
66
+ priority: 1,
67
+ },
68
+ python: {
69
+ name: 'Python',
70
+ files: ['setup.py', 'pyproject.toml', 'requirements.txt', 'Pipfile', 'poetry.lock'],
71
+ extensions: ['.py'],
72
+ priority: 1,
73
+ },
74
+ rust: {
75
+ name: 'Rust',
76
+ files: ['Cargo.toml'],
77
+ extensions: ['.rs'],
78
+ priority: 1,
79
+ },
80
+ go: {
81
+ name: 'Go',
82
+ files: ['go.mod', 'go.sum'],
83
+ extensions: ['.go'],
84
+ priority: 1,
85
+ },
86
+ java: {
87
+ name: 'Java',
88
+ files: ['pom.xml', 'build.gradle', 'build.gradle.kts'],
89
+ extensions: ['.java'],
90
+ priority: 1,
91
+ },
92
+ ruby: {
93
+ name: 'Ruby',
94
+ files: ['Gemfile', 'Rakefile'],
95
+ extensions: ['.rb'],
96
+ priority: 1,
97
+ },
98
+ php: {
99
+ name: 'PHP',
100
+ files: ['composer.json'],
101
+ extensions: ['.php'],
102
+ priority: 1,
103
+ },
104
+ dotnet: {
105
+ name: '.NET',
106
+ files: ['*.sln', '*.csproj'],
107
+ extensions: ['.cs'],
108
+ priority: 1,
109
+ },
110
+ };
111
+
112
+ /**
113
+ * Default configuration templates for each project type
114
+ */
115
+ const CONFIG_TEMPLATES = {
116
+ monorepo: {
117
+ contextignore: [
118
+ 'node_modules/',
119
+ 'dist/',
120
+ 'build/',
121
+ 'coverage/',
122
+ '**/*.test.js',
123
+ '**/*.spec.js',
124
+ '**/test/',
125
+ '**/tests/',
126
+ '**/__tests__/',
127
+ '**/*.d.ts',
128
+ '.git/',
129
+ '.nx/',
130
+ '.turbo/',
131
+ ],
132
+ contextinclude: ['packages/**/src/**', 'apps/**/src/**', '**/README.md', '**/package.json'],
133
+ methodinclude: [],
134
+ },
135
+ typescript: {
136
+ contextignore: [
137
+ 'node_modules/',
138
+ 'dist/',
139
+ 'build/',
140
+ 'coverage/',
141
+ '*.test.ts',
142
+ '*.spec.ts',
143
+ '__tests__/',
144
+ '*.d.ts',
145
+ '.git/',
146
+ ],
147
+ contextinclude: ['src/**/*.ts', 'src/**/*.tsx', 'lib/**/*.ts', 'index.ts'],
148
+ methodinclude: [],
149
+ },
150
+ react: {
151
+ contextignore: [
152
+ 'node_modules/',
153
+ 'dist/',
154
+ 'build/',
155
+ 'coverage/',
156
+ '*.test.js',
157
+ '*.test.jsx',
158
+ '*.test.ts',
159
+ '*.test.tsx',
160
+ '*.spec.js',
161
+ '*.spec.jsx',
162
+ '*.spec.ts',
163
+ '*.spec.tsx',
164
+ '__tests__/',
165
+ '__snapshots__/',
166
+ '.git/',
167
+ ],
168
+ contextinclude: [
169
+ 'src/**/*.js',
170
+ 'src/**/*.jsx',
171
+ 'src/**/*.ts',
172
+ 'src/**/*.tsx',
173
+ 'src/**/*.css',
174
+ 'src/**/*.scss',
175
+ 'src/**/*.sass',
176
+ 'components/**',
177
+ 'pages/**',
178
+ 'hooks/**',
179
+ 'utils/**',
180
+ 'services/**',
181
+ ],
182
+ methodinclude: [],
183
+ },
184
+ nextjs: {
185
+ contextignore: [
186
+ 'node_modules/',
187
+ '.next/',
188
+ 'out/',
189
+ 'coverage/',
190
+ '*.test.js',
191
+ '*.test.ts',
192
+ '*.test.tsx',
193
+ '*.spec.*',
194
+ '__tests__/',
195
+ '.git/',
196
+ ],
197
+ contextinclude: [
198
+ 'src/**',
199
+ 'app/**',
200
+ 'pages/**',
201
+ 'components/**',
202
+ 'lib/**',
203
+ 'utils/**',
204
+ 'styles/**',
205
+ 'public/**',
206
+ 'middleware.ts',
207
+ 'next.config.*',
208
+ ],
209
+ methodinclude: [],
210
+ },
211
+ vue: {
212
+ contextignore: [
213
+ 'node_modules/',
214
+ 'dist/',
215
+ 'coverage/',
216
+ '*.test.js',
217
+ '*.spec.js',
218
+ '__tests__/',
219
+ '.git/',
220
+ ],
221
+ contextinclude: [
222
+ 'src/**/*.vue',
223
+ 'src/**/*.js',
224
+ 'src/**/*.ts',
225
+ 'src/**/*.css',
226
+ 'components/**',
227
+ 'views/**',
228
+ 'store/**',
229
+ 'router/**',
230
+ ],
231
+ methodinclude: [],
232
+ },
233
+ svelte: {
234
+ contextignore: [
235
+ 'node_modules/',
236
+ 'dist/',
237
+ '.svelte-kit/',
238
+ 'coverage/',
239
+ '*.test.js',
240
+ '*.spec.js',
241
+ '.git/',
242
+ ],
243
+ contextinclude: [
244
+ 'src/**/*.svelte',
245
+ 'src/**/*.js',
246
+ 'src/**/*.ts',
247
+ 'src/**/*.css',
248
+ 'routes/**',
249
+ 'lib/**',
250
+ ],
251
+ methodinclude: [],
252
+ },
253
+ angular: {
254
+ contextignore: [
255
+ 'node_modules/',
256
+ 'dist/',
257
+ 'coverage/',
258
+ '*.spec.ts',
259
+ '**/*.spec.ts',
260
+ '.git/',
261
+ '.angular/',
262
+ ],
263
+ contextinclude: [
264
+ 'src/**/*.ts',
265
+ 'src/**/*.html',
266
+ 'src/**/*.css',
267
+ 'src/**/*.scss',
268
+ 'app/**',
269
+ 'environments/**',
270
+ ],
271
+ methodinclude: [],
272
+ },
273
+ nodejs: {
274
+ contextignore: [
275
+ 'node_modules/',
276
+ 'dist/',
277
+ 'build/',
278
+ 'coverage/',
279
+ '*.test.js',
280
+ '*.spec.js',
281
+ '__tests__/',
282
+ '.git/',
283
+ '*.log',
284
+ ],
285
+ contextinclude: ['src/**/*.js', 'lib/**/*.js', 'index.js', 'bin/**'],
286
+ methodinclude: [],
287
+ },
288
+ python: {
289
+ contextignore: [
290
+ '__pycache__/',
291
+ '*.pyc',
292
+ '*.pyo',
293
+ '.pytest_cache/',
294
+ '.tox/',
295
+ '.venv/',
296
+ 'venv/',
297
+ 'env/',
298
+ '*.egg-info/',
299
+ 'dist/',
300
+ 'build/',
301
+ '.git/',
302
+ 'node_modules/',
303
+ ],
304
+ contextinclude: ['**/*.py', 'requirements.txt', 'pyproject.toml', 'setup.py'],
305
+ methodinclude: [],
306
+ },
307
+ rust: {
308
+ contextignore: ['target/', 'Cargo.lock', '.git/', '**/*.rs.bk'],
309
+ contextinclude: ['**/*.rs', 'Cargo.toml', 'src/**'],
310
+ methodinclude: [],
311
+ },
312
+ go: {
313
+ contextignore: ['vendor/', '.git/', '*.test', '*.out'],
314
+ contextinclude: ['**/*.go', 'go.mod', 'go.sum'],
315
+ methodinclude: [],
316
+ },
317
+ java: {
318
+ contextignore: ['target/', 'build/', '.gradle/', 'out/', '.git/', '*.class', '*.jar', '*.war'],
319
+ contextinclude: ['src/**/*.java', 'pom.xml', 'build.gradle', 'build.gradle.kts'],
320
+ methodinclude: [],
321
+ },
322
+ ruby: {
323
+ contextignore: ['vendor/', '.bundle/', 'coverage/', '.git/', 'node_modules/'],
324
+ contextinclude: ['**/*.rb', 'lib/**', 'app/**', 'Gemfile', 'Rakefile'],
325
+ methodinclude: [],
326
+ },
327
+ php: {
328
+ contextignore: ['vendor/', 'node_modules/', '.git/', 'storage/', 'bootstrap/cache/'],
329
+ contextinclude: ['**/*.php', 'app/**', 'src/**', 'config/**', 'routes/**', 'composer.json'],
330
+ methodinclude: [],
331
+ },
332
+ dotnet: {
333
+ contextignore: ['bin/', 'obj/', '.git/', 'node_modules/', '*.user', '*.suo'],
334
+ contextinclude: ['**/*.cs', '*.csproj', '*.sln', 'Program.cs', 'Startup.cs'],
335
+ methodinclude: [],
336
+ },
337
+ };
338
+
339
+ class ProjectDetector {
340
+ /**
341
+ * Create a ProjectDetector instance
342
+ * @param {string} projectRoot - Project root directory
343
+ */
344
+ constructor(projectRoot = process.cwd()) {
345
+ this.projectRoot = projectRoot;
346
+ this.packageJson = null;
347
+ }
348
+
349
+ /**
350
+ * Detect project types
351
+ * @returns {Promise<Array>} Array of detected project types with confidence scores
352
+ */
353
+ async detect() {
354
+ const results = [];
355
+
356
+ // Load package.json if exists
357
+ await this.loadPackageJson();
358
+
359
+ // Check each detector
360
+ for (const [type, config] of Object.entries(DETECTORS)) {
361
+ const detection = await this.checkDetector(type, config);
362
+ if (detection.score > 0) {
363
+ results.push({
364
+ type,
365
+ name: config.name,
366
+ score: detection.score,
367
+ evidence: detection.evidence,
368
+ config: CONFIG_TEMPLATES[type] || CONFIG_TEMPLATES.nodejs,
369
+ });
370
+ }
371
+ }
372
+
373
+ // Sort by priority/score
374
+ results.sort((a, b) => b.score - a.score);
375
+
376
+ return results;
377
+ }
378
+
379
+ /**
380
+ * Load package.json if it exists
381
+ */
382
+ async loadPackageJson() {
383
+ const packageJsonPath = path.join(this.projectRoot, 'package.json');
384
+ try {
385
+ if (fs.existsSync(packageJsonPath)) {
386
+ const content = fs.readFileSync(packageJsonPath, 'utf-8');
387
+ this.packageJson = JSON.parse(content);
388
+ }
389
+ } catch (_error) {
390
+ this.packageJson = null;
391
+ }
392
+ }
393
+
394
+ /**
395
+ * Check a single detector
396
+ * @param {string} type - Detector type
397
+ * @param {object} config - Detector configuration
398
+ * @returns {Promise<object>} Detection result with score and evidence
399
+ */
400
+ async checkDetector(type, config) {
401
+ let score = 0;
402
+ const evidence = [];
403
+
404
+ // Check files
405
+ if (config.files) {
406
+ for (const file of config.files) {
407
+ const filePath = path.join(this.projectRoot, file);
408
+ if (file.includes('*')) {
409
+ // Glob pattern - simple check
410
+ const dir = path.dirname(filePath);
411
+ const baseName = path.basename(file);
412
+ if (fs.existsSync(dir)) {
413
+ try {
414
+ const files = fs.readdirSync(dir);
415
+ if (files.some((f) => this.matchesGlob(f, baseName))) {
416
+ score += 2;
417
+ evidence.push(`Found ${file}`);
418
+ }
419
+ } catch (_e) {
420
+ // Directory not accessible
421
+ }
422
+ }
423
+ } else if (fs.existsSync(filePath)) {
424
+ score += 2;
425
+ evidence.push(`Found ${file}`);
426
+ }
427
+ }
428
+ }
429
+
430
+ // Check directories
431
+ if (config.checkDirs) {
432
+ for (const dir of config.checkDirs) {
433
+ const dirPath = path.join(this.projectRoot, dir);
434
+ if (fs.existsSync(dirPath)) {
435
+ score += 3;
436
+ evidence.push(`Found ${dir}/ directory`);
437
+ }
438
+ }
439
+ }
440
+
441
+ // Check dependencies in package.json
442
+ if (config.dependencies && this.packageJson) {
443
+ const allDeps = {
444
+ ...this.packageJson.dependencies,
445
+ ...this.packageJson.devDependencies,
446
+ ...this.packageJson.peerDependencies,
447
+ };
448
+
449
+ for (const dep of config.dependencies) {
450
+ if (allDeps[dep]) {
451
+ score += 3;
452
+ evidence.push(`Has ${dep} dependency`);
453
+ }
454
+ }
455
+ }
456
+
457
+ // Check file extensions
458
+ if (config.extensions) {
459
+ const hasExtensions = await this.hasFilesWithExtensions(config.extensions);
460
+ if (hasExtensions) {
461
+ score += 1;
462
+ evidence.push(`Has ${config.extensions.join(', ')} files`);
463
+ }
464
+ }
465
+
466
+ // Add priority weight
467
+ score = score * (config.priority || 1);
468
+
469
+ return { score, evidence };
470
+ }
471
+
472
+ /**
473
+ * Check if project has files with specific extensions
474
+ * @param {Array<string>} extensions - File extensions to check
475
+ * @returns {Promise<boolean>} True if files found
476
+ */
477
+ async hasFilesWithExtensions(extensions) {
478
+ const checkDir = (dir, depth = 0) => {
479
+ if (depth > 3) return false; // Limit depth
480
+
481
+ try {
482
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
483
+
484
+ for (const entry of entries) {
485
+ if (entry.name.startsWith('.') || entry.name === 'node_modules') {
486
+ continue;
487
+ }
488
+
489
+ if (entry.isFile()) {
490
+ const ext = path.extname(entry.name);
491
+ if (extensions.includes(ext)) {
492
+ return true;
493
+ }
494
+ } else if (entry.isDirectory()) {
495
+ if (checkDir(path.join(dir, entry.name), depth + 1)) {
496
+ return true;
497
+ }
498
+ }
499
+ }
500
+ } catch (_e) {
501
+ // Directory not accessible
502
+ }
503
+
504
+ return false;
505
+ };
506
+
507
+ return checkDir(this.projectRoot);
508
+ }
509
+
510
+ /**
511
+ * Simple glob matching
512
+ * @param {string} filename - Filename to check
513
+ * @param {string} pattern - Glob pattern
514
+ * @returns {boolean} True if matches
515
+ */
516
+ matchesGlob(filename, pattern) {
517
+ const regex = pattern.replace(/\./g, '\\.').replace(/\*/g, '.*');
518
+ return new RegExp(`^${regex}$`).test(filename);
519
+ }
520
+
521
+ /**
522
+ * Get merged configuration for detected project types
523
+ * @param {Array<string>} types - Detected project types
524
+ * @returns {object} Merged configuration
525
+ */
526
+ getMergedConfig(types) {
527
+ const merged = {
528
+ contextignore: new Set(),
529
+ contextinclude: new Set(),
530
+ methodinclude: new Set(),
531
+ };
532
+
533
+ // Add base ignores
534
+ merged.contextignore.add('.git/');
535
+ merged.contextignore.add('node_modules/');
536
+
537
+ // Merge configs from all detected types
538
+ for (const type of types) {
539
+ const config = CONFIG_TEMPLATES[type];
540
+ if (config) {
541
+ if (config.contextignore) {
542
+ config.contextignore.forEach((p) => merged.contextignore.add(p));
543
+ }
544
+ if (config.contextinclude) {
545
+ config.contextinclude.forEach((p) => merged.contextinclude.add(p));
546
+ }
547
+ if (config.methodinclude) {
548
+ config.methodinclude.forEach((p) => merged.methodinclude.add(p));
549
+ }
550
+ }
551
+ }
552
+
553
+ return {
554
+ contextignore: [...merged.contextignore],
555
+ contextinclude: [...merged.contextinclude],
556
+ methodinclude: [...merged.methodinclude],
557
+ };
558
+ }
559
+
560
+ /**
561
+ * Get configuration template for a specific type
562
+ * @param {string} type - Project type
563
+ * @returns {object} Configuration template
564
+ */
565
+ getConfigTemplate(type) {
566
+ return CONFIG_TEMPLATES[type] || CONFIG_TEMPLATES.nodejs;
567
+ }
568
+ }
569
+
570
+ export default ProjectDetector;
571
+ export { DETECTORS, CONFIG_TEMPLATES };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ctxman",
3
- "version": "3.0.0",
3
+ "version": "3.1.0",
4
4
  "description": "AI Development Platform with plugin architecture, Git integration, REST API, watch mode, LLM optimization, and support for 14+ languages. Features include TOON format (40-50% token reduction), real-time analysis, and comprehensive context generation.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -8,15 +8,22 @@
8
8
  "ctxman": "bin/cli.js"
9
9
  },
10
10
  "exports": {
11
- ".": "./index.js"
11
+ ".": {
12
+ "types": "./index.d.ts",
13
+ "import": "./index.js"
14
+ }
12
15
  },
16
+ "types": "./index.d.ts",
13
17
  "scripts": {
14
18
  "test": "vitest run",
15
19
  "test:watch": "vitest",
16
20
  "test:coverage": "vitest run --coverage",
17
21
  "lint": "eslint .",
18
22
  "lint:fix": "eslint . --fix",
23
+ "lint:strict": "eslint . --max-warnings 0",
19
24
  "format": "prettier --write .",
25
+ "format:check": "prettier --check .",
26
+ "clean": "rm -rf coverage test-results",
20
27
  "analyze": "node bin/cli.js",
21
28
  "analyze:cli": "node bin/cli.js --cli",
22
29
  "analyze:methods": "node bin/cli.js --cli --method-level",
@@ -35,8 +42,12 @@
35
42
  "build": "echo 'No build step required'",
36
43
  "build:deb": "make build-deb",
37
44
  "prepublishOnly": "npm test",
45
+ "prepack": "npm run clean && npm test",
46
+ "prepare": "husky || true",
38
47
  "mcp": "node bin/mcp-server.js",
39
- "postinstall": "node -e \"console.log('\\n✅ Ctxman installed! Run: ctxman --help\\n')\""
48
+ "docs:dev": "npm run docs:dev --prefix website",
49
+ "docs:build": "npm run docs:build --prefix website",
50
+ "docs:preview": "npm run docs:preview --prefix website"
40
51
  },
41
52
  "keywords": [
42
53
  "code",
@@ -72,35 +83,56 @@
72
83
  ],
73
84
  "author": "Hakkı Sağdıç",
74
85
  "license": "MIT",
86
+ "homepage": "https://github.com/hakkisagdic/ctxman#readme",
87
+ "repository": {
88
+ "type": "git",
89
+ "url": "git+https://github.com/hakkisagdic/ctxman.git"
90
+ },
91
+ "bugs": {
92
+ "url": "https://github.com/hakkisagdic/ctxman/issues"
93
+ },
75
94
  "engines": {
76
- "node": ">=20.0.0"
95
+ "node": ">=22.0.0"
77
96
  },
78
97
  "dependencies": {
79
- "@lancedb/lancedb": "^0.23.0",
80
98
  "@modelcontextprotocol/sdk": "^1.21.1",
81
- "@toon-format/toon": "^0.7.0",
82
- "@xenova/transformers": "^2.17.2",
99
+ "@toon-format/toon": "^4.1.1",
83
100
  "cors": "^2.8.5",
84
101
  "express": "^5.1.0",
85
102
  "ink": "^6.4.0",
86
103
  "ink-spinner": "^5.0.0",
87
104
  "ink-text-input": "^6.0.0",
88
105
  "react": "^19.2.0",
89
- "vitest": "^4.0.18",
106
+ "tiktoken": "^1.0.22",
90
107
  "zod": "^4.1.12"
91
108
  },
109
+ "optionalDependencies": {
110
+ "@lancedb/lancedb": "^0.23.0",
111
+ "@xenova/transformers": "^2.17.2"
112
+ },
92
113
  "files": [
93
114
  "index.js",
115
+ "index.d.ts",
94
116
  "ctxman.js",
95
117
  "lib/",
96
118
  "bin/",
97
- ".ctxman/",
119
+ ".ctxman/profiles/",
120
+ ".ctxman/templates/",
121
+ ".ctxman/wizard-profiles/",
122
+ ".ctxman/llm-profiles.json",
123
+ ".ctxman/custom-profiles.example.json",
98
124
  "examples/",
99
125
  "README.md",
100
126
  "LICENSE"
101
127
  ],
128
+ "overrides": {
129
+ "protobufjs": "^7.5.0",
130
+ "sharp": "^0.35.0"
131
+ },
102
132
  "devDependencies": {
103
133
  "@anthropic-ai/tokenizer": "^0.0.4",
134
+ "@commitlint/cli": "^21.2.2",
135
+ "@commitlint/config-conventional": "^21.2.2",
104
136
  "@playwright/test": "^1.58.1",
105
137
  "@vitejs/plugin-vue": "^6.0.2",
106
138
  "@vitest/coverage-v8": "^4.0.18",
@@ -108,11 +140,13 @@
108
140
  "@vue/test-utils": "^2.4.6",
109
141
  "c8": "^10.1.3",
110
142
  "eslint": "^9.39.1",
143
+ "husky": "^9.1.7",
144
+ "lint-staged": "^17.3.0",
111
145
  "llama3-tokenizer-js": "^1.2.0",
112
146
  "prettier": "^3.6.2",
113
147
  "supertest": "^7.2.2",
114
- "tiktoken": "^1.0.22",
115
148
  "vite": "^7.2.4",
149
+ "vitest": "^4.0.18",
116
150
  "vue": "^3.5.24"
117
151
  }
118
152
  }