ctxman 3.0.0 → 3.1.1

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 (224) 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 +381 -136
  16. package/bin/cli.js +1880 -529
  17. package/bin/cm-ask.js +18 -67
  18. package/bin/cm-audit.js +121 -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 +687 -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 +772 -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 +116 -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 +312 -0
  93. package/lib/policy/enforce.js +125 -0
  94. package/lib/policy/ignore-files.js +169 -0
  95. package/lib/policy/index.js +53 -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/ask.js +122 -0
  108. package/lib/rag/sources/FileDataSource.js +12 -9
  109. package/lib/rag/stores/BaseVectorStore.js +5 -5
  110. package/lib/rag/stores/ChromaDBStore.js +10 -10
  111. package/lib/rag/stores/LanceDBStore.js +29 -19
  112. package/lib/rag/stores/PineconeStore.js +11 -9
  113. package/lib/search/bm25.js +433 -0
  114. package/lib/search/code-units.js +201 -0
  115. package/lib/search/symbols.js +189 -0
  116. package/lib/ui/dashboard.js +120 -89
  117. package/lib/ui/index.js +1 -6
  118. package/lib/ui/init-wizard-ui.js +550 -0
  119. package/lib/ui/progress-bar.js +94 -88
  120. package/lib/ui/select-input.js +40 -32
  121. package/lib/ui/template-selector.js +99 -0
  122. package/lib/ui/wizard.js +374 -329
  123. package/lib/utils/claude-token-counter.js +151 -0
  124. package/lib/utils/cli-output.js +17 -0
  125. package/lib/utils/clipboard-utils.js +49 -50
  126. package/lib/utils/config-utils.js +81 -66
  127. package/lib/utils/context-versioning.js +532 -0
  128. package/lib/utils/error-handler.js +112 -112
  129. package/lib/utils/file-utils.js +153 -69
  130. package/lib/utils/format-converter.js +356 -283
  131. package/lib/utils/git-utils.js +366 -294
  132. package/lib/utils/llm-cost-estimator.js +281 -0
  133. package/lib/utils/llm-detector.js +242 -78
  134. package/lib/utils/logger.js +246 -237
  135. package/lib/utils/messages.js +355 -0
  136. package/lib/utils/multi-repo-manager.js +364 -0
  137. package/lib/utils/profile-manager.js +380 -0
  138. package/lib/utils/safe-read.js +61 -0
  139. package/lib/utils/secret-redactor.js +61 -0
  140. package/lib/utils/snapshot-manager.js +679 -0
  141. package/lib/utils/template-manager.js +378 -0
  142. package/lib/utils/token-utils.js +201 -170
  143. package/lib/utils/tokenizer-adapter.js +421 -377
  144. package/lib/utils/updater.js +539 -506
  145. package/lib/watch/FileWatcher.js +12 -8
  146. package/lib/watch/IncrementalAnalyzer.js +7 -7
  147. package/lib/why/coupling.js +81 -0
  148. package/lib/why/errors.js +23 -0
  149. package/lib/why/git.js +169 -0
  150. package/lib/why/history.js +108 -0
  151. package/lib/why/index.js +720 -0
  152. package/lib/why/ownership.js +79 -0
  153. package/lib/why/paths.js +207 -0
  154. package/lib/why/references.js +259 -0
  155. package/lib/why/render.js +722 -0
  156. package/lib/why/search.js +358 -0
  157. package/lib/why/target.js +389 -0
  158. package/lib/wizards/config-generator.js +257 -0
  159. package/lib/wizards/project-detector.js +572 -0
  160. package/package.json +44 -10
  161. package/.ctxman/logs/ctxman-2026-07-02.log +0 -156
  162. package/.ctxman/self-knowledge/documents.lance/_transactions/0-b3dd1558-f95b-44b9-a154-18e8c330ae7a.txn +0 -0
  163. package/.ctxman/self-knowledge/documents.lance/_transactions/1-44bff6d4-e552-4010-a769-e09ad822698d.txn +0 -0
  164. package/.ctxman/self-knowledge/documents.lance/_transactions/10-37260794-5947-4ecb-b4c8-d732f58f40f1.txn +0 -0
  165. package/.ctxman/self-knowledge/documents.lance/_transactions/11-0d52a883-5518-463c-9b6d-986c3af89dfd.txn +0 -0
  166. package/.ctxman/self-knowledge/documents.lance/_transactions/12-ae354646-52f2-49c9-90fb-2e6ed8932663.txn +0 -0
  167. package/.ctxman/self-knowledge/documents.lance/_transactions/13-5d7d5e57-27da-498b-b734-091b9d38da13.txn +0 -0
  168. package/.ctxman/self-knowledge/documents.lance/_transactions/14-558ce928-810b-4252-a364-fdd1ee6f8a25.txn +0 -0
  169. package/.ctxman/self-knowledge/documents.lance/_transactions/15-27e3a58f-8b64-43b8-a9f4-e3369446968b.txn +0 -0
  170. package/.ctxman/self-knowledge/documents.lance/_transactions/16-a110c390-e5c8-4464-b976-bc7f5195fa15.txn +0 -0
  171. package/.ctxman/self-knowledge/documents.lance/_transactions/17-97513225-53de-4216-b61a-6337bd0cc4ad.txn +0 -0
  172. package/.ctxman/self-knowledge/documents.lance/_transactions/18-5ba450f0-c527-459c-bf4f-6d79b5e4285f.txn +0 -0
  173. package/.ctxman/self-knowledge/documents.lance/_transactions/19-600d3a63-5225-49e9-b8b7-30e037b564ab.txn +0 -0
  174. package/.ctxman/self-knowledge/documents.lance/_transactions/2-48a61b4e-92cf-4342-8376-914c1b99a9f9.txn +0 -0
  175. package/.ctxman/self-knowledge/documents.lance/_transactions/20-121dd912-5410-410e-84ff-82c7a23604a0.txn +0 -0
  176. package/.ctxman/self-knowledge/documents.lance/_transactions/3-bc6844ab-7ea3-4bb3-9ee1-538ce5664a9c.txn +0 -0
  177. package/.ctxman/self-knowledge/documents.lance/_transactions/4-d5e1754f-dbb5-454e-a9be-2a7da8d7bcf9.txn +0 -0
  178. package/.ctxman/self-knowledge/documents.lance/_transactions/5-4fae93df-0568-4b6f-8acf-8bef4bba6047.txn +0 -0
  179. package/.ctxman/self-knowledge/documents.lance/_transactions/6-4b1b8b87-068e-49a3-ba2b-d8dae628b252.txn +0 -0
  180. package/.ctxman/self-knowledge/documents.lance/_transactions/7-63d040fb-d2fa-4c0f-bed0-53411918a7b0.txn +0 -0
  181. package/.ctxman/self-knowledge/documents.lance/_transactions/8-c5628cf6-264c-420f-aab8-bc96a9083591.txn +0 -0
  182. package/.ctxman/self-knowledge/documents.lance/_transactions/9-c94570aa-5e53-4fcb-971f-cecc1d1d5492.txn +0 -0
  183. package/.ctxman/self-knowledge/documents.lance/_versions/1.manifest +0 -0
  184. package/.ctxman/self-knowledge/documents.lance/_versions/10.manifest +0 -0
  185. package/.ctxman/self-knowledge/documents.lance/_versions/11.manifest +0 -0
  186. package/.ctxman/self-knowledge/documents.lance/_versions/12.manifest +0 -0
  187. package/.ctxman/self-knowledge/documents.lance/_versions/13.manifest +0 -0
  188. package/.ctxman/self-knowledge/documents.lance/_versions/14.manifest +0 -0
  189. package/.ctxman/self-knowledge/documents.lance/_versions/15.manifest +0 -0
  190. package/.ctxman/self-knowledge/documents.lance/_versions/16.manifest +0 -0
  191. package/.ctxman/self-knowledge/documents.lance/_versions/17.manifest +0 -0
  192. package/.ctxman/self-knowledge/documents.lance/_versions/18.manifest +0 -0
  193. package/.ctxman/self-knowledge/documents.lance/_versions/19.manifest +0 -0
  194. package/.ctxman/self-knowledge/documents.lance/_versions/2.manifest +0 -0
  195. package/.ctxman/self-knowledge/documents.lance/_versions/20.manifest +0 -0
  196. package/.ctxman/self-knowledge/documents.lance/_versions/21.manifest +0 -0
  197. package/.ctxman/self-knowledge/documents.lance/_versions/3.manifest +0 -0
  198. package/.ctxman/self-knowledge/documents.lance/_versions/4.manifest +0 -0
  199. package/.ctxman/self-knowledge/documents.lance/_versions/5.manifest +0 -0
  200. package/.ctxman/self-knowledge/documents.lance/_versions/6.manifest +0 -0
  201. package/.ctxman/self-knowledge/documents.lance/_versions/7.manifest +0 -0
  202. package/.ctxman/self-knowledge/documents.lance/_versions/8.manifest +0 -0
  203. package/.ctxman/self-knowledge/documents.lance/_versions/9.manifest +0 -0
  204. package/.ctxman/self-knowledge/documents.lance/data/000010010011011101000010de8621405d9d5cb06540dbf02c.lance +0 -0
  205. package/.ctxman/self-knowledge/documents.lance/data/0000101001011100011000003fb62a4aa8978974075c144f1c.lance +0 -0
  206. package/.ctxman/self-knowledge/documents.lance/data/000011010000100111001011c6cc824d628f3bb1f4e04cd5d0.lance +0 -0
  207. package/.ctxman/self-knowledge/documents.lance/data/001000001000011001011100d8f74349ada090b332cd1df669.lance +0 -0
  208. package/.ctxman/self-knowledge/documents.lance/data/01000001111010001000010045ab44467bb1e7e4d8ae06bd58.lance +0 -0
  209. package/.ctxman/self-knowledge/documents.lance/data/01000101101110111110011131ef904241a89e1ffb6ddaf8e3.lance +0 -0
  210. package/.ctxman/self-knowledge/documents.lance/data/010010110000010000011010fbfcc145c6a8a827b28057a07e.lance +0 -0
  211. package/.ctxman/self-knowledge/documents.lance/data/1000011000101010001110003fb4f045c3835982efa1405324.lance +0 -0
  212. package/.ctxman/self-knowledge/documents.lance/data/100111011101110111101011f4396b410fa06af3b028d204e6.lance +0 -0
  213. package/.ctxman/self-knowledge/documents.lance/data/100111100111101000001100596b174e00995d6cc2969cc8dc.lance +0 -0
  214. package/.ctxman/self-knowledge/documents.lance/data/1010001100011000110010102ea16b484d887c7c9725feffd6.lance +0 -0
  215. package/.ctxman/self-knowledge/documents.lance/data/101101100010101111110111c5230944d9b3af7301b6392dda.lance +0 -0
  216. package/.ctxman/self-knowledge/documents.lance/data/1011011100100111111110105892bf41b5a530fedd7cf516f1.lance +0 -0
  217. package/.ctxman/self-knowledge/documents.lance/data/10111110000010001011110164e8774742bade87b483c10f36.lance +0 -0
  218. package/.ctxman/self-knowledge/documents.lance/data/1100000100010110001110103ffaca40a2a42c85067ebaf9ae.lance +0 -0
  219. package/.ctxman/self-knowledge/documents.lance/data/110000010001110110101110664bde4c76a78dfc14b05e83b8.lance +0 -0
  220. package/.ctxman/self-knowledge/documents.lance/data/11001100111000010100110050645c4281b1f35b2022234f7f.lance +0 -0
  221. package/.ctxman/self-knowledge/documents.lance/data/1101111011001100110111017214924a368f5719eab2246619.lance +0 -0
  222. package/.ctxman/self-knowledge/documents.lance/data/1110000111001010001000002150c24dcab653d39d07032e63.lance +0 -0
  223. package/.ctxman/self-knowledge/documents.lance/data/1110100000000100000011014d20534967a18b5c87721659ff.lance +0 -0
  224. package/.ctxman/self-knowledge/documents.lance/data/11110101111010000101011135a0114ef2b35dc6f1297a3381.lance +0 -0
@@ -0,0 +1,572 @@
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
+ // Every regex character is literal except `*`, which matches any run of characters
518
+ const regex = pattern.replace(/[.+?^${}()|[\]\\]/g, '\\$&').replace(/\*/g, '.*');
519
+ return new RegExp(`^${regex}$`).test(filename);
520
+ }
521
+
522
+ /**
523
+ * Get merged configuration for detected project types
524
+ * @param {Array<string>} types - Detected project types
525
+ * @returns {object} Merged configuration
526
+ */
527
+ getMergedConfig(types) {
528
+ const merged = {
529
+ contextignore: new Set(),
530
+ contextinclude: new Set(),
531
+ methodinclude: new Set(),
532
+ };
533
+
534
+ // Add base ignores
535
+ merged.contextignore.add('.git/');
536
+ merged.contextignore.add('node_modules/');
537
+
538
+ // Merge configs from all detected types
539
+ for (const type of types) {
540
+ const config = CONFIG_TEMPLATES[type];
541
+ if (config) {
542
+ if (config.contextignore) {
543
+ config.contextignore.forEach((p) => merged.contextignore.add(p));
544
+ }
545
+ if (config.contextinclude) {
546
+ config.contextinclude.forEach((p) => merged.contextinclude.add(p));
547
+ }
548
+ if (config.methodinclude) {
549
+ config.methodinclude.forEach((p) => merged.methodinclude.add(p));
550
+ }
551
+ }
552
+ }
553
+
554
+ return {
555
+ contextignore: [...merged.contextignore],
556
+ contextinclude: [...merged.contextinclude],
557
+ methodinclude: [...merged.methodinclude],
558
+ };
559
+ }
560
+
561
+ /**
562
+ * Get configuration template for a specific type
563
+ * @param {string} type - Project type
564
+ * @returns {object} Configuration template
565
+ */
566
+ getConfigTemplate(type) {
567
+ return CONFIG_TEMPLATES[type] || CONFIG_TEMPLATES.nodejs;
568
+ }
569
+ }
570
+
571
+ export default ProjectDetector;
572
+ 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.1",
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://hakkisagdic.github.io/ctxman/",
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
  }