cntx-ui 3.0.8 → 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 (36) hide show
  1. package/dist/bin/cntx-ui.js +89 -0
  2. package/dist/lib/agent-runtime.js +269 -0
  3. package/dist/lib/agent-tools.js +162 -0
  4. package/dist/lib/api-router.js +387 -0
  5. package/dist/lib/bundle-manager.js +236 -0
  6. package/dist/lib/configuration-manager.js +230 -0
  7. package/dist/lib/database-manager.js +277 -0
  8. package/dist/lib/file-system-manager.js +305 -0
  9. package/dist/lib/function-level-chunker.js +144 -0
  10. package/dist/lib/heuristics-manager.js +491 -0
  11. package/dist/lib/mcp-server.js +159 -0
  12. package/dist/lib/mcp-transport.js +10 -0
  13. package/dist/lib/semantic-splitter.js +335 -0
  14. package/dist/lib/simple-vector-store.js +98 -0
  15. package/dist/lib/treesitter-semantic-chunker.js +277 -0
  16. package/dist/lib/websocket-manager.js +268 -0
  17. package/dist/server.js +413 -0
  18. package/package.json +17 -8
  19. package/bin/cntx-ui-mcp.sh +0 -3
  20. package/bin/cntx-ui.js +0 -123
  21. package/lib/agent-runtime.js +0 -371
  22. package/lib/agent-tools.js +0 -370
  23. package/lib/api-router.js +0 -1026
  24. package/lib/bundle-manager.js +0 -326
  25. package/lib/configuration-manager.js +0 -760
  26. package/lib/database-manager.js +0 -397
  27. package/lib/file-system-manager.js +0 -489
  28. package/lib/function-level-chunker.js +0 -406
  29. package/lib/heuristics-manager.js +0 -529
  30. package/lib/mcp-server.js +0 -1380
  31. package/lib/mcp-transport.js +0 -97
  32. package/lib/semantic-splitter.js +0 -347
  33. package/lib/simple-vector-store.js +0 -108
  34. package/lib/treesitter-semantic-chunker.js +0 -1557
  35. package/lib/websocket-manager.js +0 -470
  36. package/server.js +0 -687
package/dist/server.js ADDED
@@ -0,0 +1,413 @@
1
+ /**
2
+ * Refactored cntx-ui Server
3
+ * Lean orchestration layer using modular architecture
4
+ */
5
+ import { createServer } from 'http';
6
+ import { join, dirname, extname } from 'path';
7
+ import { fileURLToPath, parse } from 'url';
8
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync, cpSync } from 'fs';
9
+ import { homedir } from 'os';
10
+ // Import our modular components
11
+ import ConfigurationManager from './lib/configuration-manager.js';
12
+ import FileSystemManager from './lib/file-system-manager.js';
13
+ import BundleManager from './lib/bundle-manager.js';
14
+ import APIRouter from './lib/api-router.js';
15
+ import WebSocketManager from './lib/websocket-manager.js';
16
+ // Import existing lib modules
17
+ import SemanticSplitter from './lib/semantic-splitter.js';
18
+ import SimpleVectorStore from './lib/simple-vector-store.js';
19
+ import { MCPServer } from './lib/mcp-server.js';
20
+ import AgentRuntime from './lib/agent-runtime.js';
21
+ const __dirname = dirname(fileURLToPath(import.meta.url));
22
+ export class CntxServer {
23
+ CWD;
24
+ CNTX_DIR;
25
+ verbose;
26
+ mcpServerStarted;
27
+ mcpServer;
28
+ initMessages;
29
+ configManager;
30
+ databaseManager;
31
+ fileSystemManager;
32
+ bundleManager;
33
+ webSocketManager;
34
+ apiRouter;
35
+ semanticSplitter;
36
+ vectorStore;
37
+ agentRuntime;
38
+ semanticCache;
39
+ lastSemanticAnalysis;
40
+ vectorStoreInitialized;
41
+ semanticAnalysisManager;
42
+ activityManager;
43
+ constructor(cwd = process.cwd(), options = {}) {
44
+ this.CWD = cwd;
45
+ this.CNTX_DIR = join(cwd, '.cntx');
46
+ this.verbose = options.verbose || false;
47
+ this.mcpServerStarted = false;
48
+ this.mcpServer = null;
49
+ this.initMessages = [];
50
+ // Ensure directory exists
51
+ if (!existsSync(this.CNTX_DIR))
52
+ mkdirSync(this.CNTX_DIR, { recursive: true });
53
+ // Initialize modular components
54
+ this.configManager = new ConfigurationManager(cwd, { verbose: this.verbose });
55
+ this.databaseManager = this.configManager.dbManager;
56
+ this.fileSystemManager = new FileSystemManager(cwd, { verbose: this.verbose });
57
+ this.bundleManager = new BundleManager(this.configManager, this.fileSystemManager, this.verbose);
58
+ this.webSocketManager = new WebSocketManager(this.bundleManager, this.configManager, { verbose: this.verbose });
59
+ // AI Components
60
+ this.semanticSplitter = new SemanticSplitter({
61
+ maxChunkSize: 2000,
62
+ includeContext: true,
63
+ minFunctionSize: 50
64
+ });
65
+ this.vectorStore = new SimpleVectorStore(this.databaseManager, {
66
+ modelName: 'Xenova/all-MiniLM-L6-v2'
67
+ });
68
+ this.semanticCache = null;
69
+ this.lastSemanticAnalysis = null;
70
+ this.vectorStoreInitialized = false;
71
+ // Initialize Agent Runtime
72
+ this.agentRuntime = new AgentRuntime(this);
73
+ this.semanticAnalysisManager = this; // Self as manager
74
+ this.activityManager = this; // Simple mock for now
75
+ // Initialize API router
76
+ this.apiRouter = new APIRouter(this, this.configManager, this.bundleManager, this.fileSystemManager, this.semanticAnalysisManager, this.vectorStore, this.activityManager);
77
+ // Cross-module linkage
78
+ this.bundleManager.fileSystemManager = this.fileSystemManager;
79
+ this.bundleManager.webSocketManager = this.webSocketManager;
80
+ }
81
+ async init(options = {}) {
82
+ const { skipFileWatcher = false, skipBundleGeneration = false } = options;
83
+ // Load configs
84
+ this.configManager.loadConfig();
85
+ this.configManager.loadHiddenFilesConfig();
86
+ this.configManager.loadIgnorePatterns();
87
+ this.configManager.loadBundleStates();
88
+ if (!skipFileWatcher) {
89
+ this.startWatching();
90
+ // Trigger semantic analysis
91
+ if (!this.semanticCache) {
92
+ this.getSemanticAnalysis().catch(err => console.error('Initial semantic analysis failed:', err.message));
93
+ }
94
+ if (!skipBundleGeneration) {
95
+ await this.bundleManager.generateAllBundles();
96
+ }
97
+ }
98
+ // Load reasoning/manifest
99
+ await this.agentRuntime.generateAgentManifest();
100
+ }
101
+ startWatching() {
102
+ this.fileSystemManager.startWatching((eventType, filename) => {
103
+ this.bundleManager.markBundlesChanged(filename);
104
+ this.webSocketManager.onFileChanged(filename, eventType);
105
+ });
106
+ }
107
+ async getSemanticAnalysis() {
108
+ // Try SQLite first
109
+ try {
110
+ const dbChunks = this.databaseManager.db.prepare('SELECT * FROM semantic_chunks').all();
111
+ if (dbChunks.length > 0) {
112
+ if (!this.semanticCache) {
113
+ this.semanticCache = {
114
+ chunks: dbChunks.map(row => this.databaseManager.mapChunkRow(row)),
115
+ summary: { totalChunks: dbChunks.length }
116
+ };
117
+ }
118
+ return this.semanticCache;
119
+ }
120
+ }
121
+ catch (e) { }
122
+ // Fresh analysis
123
+ const files = this.fileSystemManager.getAllFiles().map(f => this.fileSystemManager.relativePath(f))
124
+ .filter(f => ['.js', '.jsx', '.ts', '.tsx', '.rs'].includes(extname(f).toLowerCase()));
125
+ let bundleConfig = null;
126
+ if (existsSync(this.configManager.CONFIG_FILE)) {
127
+ bundleConfig = JSON.parse(readFileSync(this.configManager.CONFIG_FILE, 'utf8'));
128
+ }
129
+ this.semanticCache = await this.semanticSplitter.extractSemanticChunks(this.CWD, files, bundleConfig);
130
+ this.lastSemanticAnalysis = Date.now();
131
+ if (this.semanticCache.chunks.length > 0) {
132
+ this.databaseManager.saveChunks(this.semanticCache.chunks);
133
+ }
134
+ this.enhanceSemanticChunksIfNeeded(this.semanticCache);
135
+ return this.semanticCache;
136
+ }
137
+ async enhanceSemanticChunksIfNeeded(analysis) {
138
+ if (!analysis || !analysis.chunks)
139
+ return;
140
+ if (!this.vectorStoreInitialized) {
141
+ await this.vectorStore.init();
142
+ this.vectorStoreInitialized = true;
143
+ }
144
+ for (const chunk of analysis.chunks) {
145
+ if (!this.databaseManager.getEmbedding(chunk.id)) {
146
+ await this.vectorStore.upsertChunk(chunk);
147
+ }
148
+ }
149
+ }
150
+ async refreshSemanticAnalysis() {
151
+ this.databaseManager.db.prepare('DELETE FROM semantic_chunks').run();
152
+ this.databaseManager.db.prepare('DELETE FROM vector_embeddings').run();
153
+ this.semanticCache = null;
154
+ return this.getSemanticAnalysis();
155
+ }
156
+ startMCPServer() {
157
+ if (!this.mcpServer) {
158
+ this.mcpServer = new MCPServer(this);
159
+ this.mcpServerStarted = true;
160
+ }
161
+ }
162
+ async listen(port = 3333, host = 'localhost') {
163
+ const server = createServer((req, res) => {
164
+ const url = parse(req.url || '/', true);
165
+ // Serve static files from web/dist
166
+ if (!url.pathname?.startsWith('/api/')) {
167
+ return this.handleStaticFile(req, res, url);
168
+ }
169
+ // Route API requests
170
+ this.apiRouter.handleRequest(req, res, url);
171
+ });
172
+ this.webSocketManager.initialize(server);
173
+ return new Promise((resolve) => {
174
+ server.listen(port, host, () => {
175
+ console.log(`🚀 cntx-ui server running at http://${host}:${port}`);
176
+ resolve(server);
177
+ });
178
+ });
179
+ }
180
+ handleStaticFile(req, res, url) {
181
+ const webDir = join(__dirname, 'web/dist');
182
+ let filePath = join(webDir, url.pathname === '/' ? 'index.html' : url.pathname);
183
+ if (!existsSync(filePath)) {
184
+ filePath = join(webDir, 'index.html');
185
+ }
186
+ try {
187
+ const content = readFileSync(filePath);
188
+ const ext = extname(filePath).toLowerCase();
189
+ const contentType = this.getContentType(ext);
190
+ res.writeHead(200, { 'Content-Type': contentType });
191
+ res.end(content);
192
+ }
193
+ catch (e) {
194
+ res.writeHead(404);
195
+ res.end('Not Found');
196
+ }
197
+ }
198
+ getContentType(ext) {
199
+ const types = {
200
+ '.html': 'text/html',
201
+ '.js': 'application/javascript',
202
+ '.css': 'text/css',
203
+ '.json': 'application/json',
204
+ '.png': 'image/png',
205
+ '.jpg': 'image/jpeg',
206
+ '.svg': 'image/svg+xml'
207
+ };
208
+ return types[ext] || 'text/plain';
209
+ }
210
+ // Activity Manager Mock
211
+ async loadActivities() {
212
+ return [];
213
+ }
214
+ }
215
+ export async function startServer(options = {}) {
216
+ const server = new CntxServer(options.cwd, options);
217
+ await server.init(options);
218
+ if (options.withMcp !== false)
219
+ server.startMCPServer();
220
+ return await server.listen(options.port, options.host);
221
+ }
222
+ // Initialize project configuration
223
+ export async function initConfig(cwd = process.cwd()) {
224
+ const server = new CntxServer(cwd);
225
+ // 1. Initialize directory structure
226
+ if (!existsSync(server.CNTX_DIR)) {
227
+ mkdirSync(server.CNTX_DIR, { recursive: true });
228
+ console.log('📁 Created .cntx directory');
229
+ }
230
+ // 2. Create .mcp.json for Claude Code discovery
231
+ const mcpConfigPath = join(cwd, '.mcp.json');
232
+ const mcpConfig = {
233
+ mcpServers: {
234
+ "cntx-ui": {
235
+ command: "cntx-ui",
236
+ args: ["mcp"],
237
+ cwd: "."
238
+ }
239
+ }
240
+ };
241
+ writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2), 'utf8');
242
+ console.log('📄 Created .mcp.json for agent auto-discovery');
243
+ // 3. Initialize basic configuration with better defaults and auto-suggestions
244
+ server.configManager.loadConfig();
245
+ const suggestedBundles = {
246
+ master: ['**/*']
247
+ };
248
+ // Directory-based auto-suggestions
249
+ const commonDirs = [
250
+ { dir: 'src/components', name: 'ui-components' },
251
+ { dir: 'src/services', name: 'services' },
252
+ { dir: 'src/lib', name: 'libraries' },
253
+ { dir: 'src/hooks', name: 'react-hooks' },
254
+ { dir: 'server', name: 'backend-api' },
255
+ { dir: 'tests', name: 'test-suite' }
256
+ ];
257
+ commonDirs.forEach(d => {
258
+ if (existsSync(join(cwd, d.dir))) {
259
+ suggestedBundles[d.name] = [`${d.dir}/**`];
260
+ console.log(`💡 Suggested bundle: ${d.name} (${d.dir}/**)`);
261
+ }
262
+ });
263
+ server.configManager.saveConfig({
264
+ bundles: suggestedBundles
265
+ });
266
+ // 4. Create robust default .cntxignore
267
+ const ignorePath = join(cwd, '.cntxignore');
268
+ if (!existsSync(ignorePath)) {
269
+ const defaultIgnore = `# Binary files
270
+ *.db
271
+ *.db-journal
272
+ *.png
273
+ *.jpg
274
+ *.jpeg
275
+ *.ico
276
+ *.icns
277
+ *.gif
278
+ *.zip
279
+ *.tar.gz
280
+
281
+ # Generated files
282
+ **/gen/**
283
+ **/dist/**
284
+ **/build/**
285
+ **/node_modules/**
286
+ **/.next/**
287
+ **/.cache/**
288
+
289
+ # cntx-ui internals
290
+ .cntx/**
291
+ .mcp.json
292
+ `;
293
+ writeFileSync(ignorePath, defaultIgnore, 'utf8');
294
+ console.log('📄 Created .cntxignore with smart defaults');
295
+ }
296
+ console.log('⚙️ Basic configuration initialized');
297
+ const templateDir = join(__dirname, 'templates');
298
+ // Copy agent configuration files
299
+ const agentFiles = [
300
+ 'agent-config.yaml',
301
+ 'agent-instructions.md'
302
+ ];
303
+ for (const file of agentFiles) {
304
+ const sourcePath = join(templateDir, file);
305
+ const destPath = join(server.CNTX_DIR, file);
306
+ if (existsSync(sourcePath) && !existsSync(destPath)) {
307
+ copyFileSync(sourcePath, destPath);
308
+ console.log(`📄 Created ${file}`);
309
+ }
310
+ }
311
+ // Copy agent-rules directory structure
312
+ const agentRulesSource = join(templateDir, 'agent-rules');
313
+ const agentRulesDest = join(server.CNTX_DIR, 'agent-rules');
314
+ if (existsSync(agentRulesSource) && !existsSync(agentRulesDest)) {
315
+ cpSync(agentRulesSource, agentRulesDest, { recursive: true });
316
+ console.log('📁 Created agent-rules directory with templates');
317
+ }
318
+ // Copy activities framework
319
+ const activitiesDir = join(server.CNTX_DIR, 'activities');
320
+ if (!existsSync(activitiesDir)) {
321
+ mkdirSync(activitiesDir, { recursive: true });
322
+ }
323
+ // Copy activities README
324
+ const activitiesReadmeSource = join(templateDir, 'activities', 'README.md');
325
+ const activitiesReadmeDest = join(activitiesDir, 'README.md');
326
+ if (existsSync(activitiesReadmeSource) && !existsSync(activitiesReadmeDest)) {
327
+ copyFileSync(activitiesReadmeSource, activitiesReadmeDest);
328
+ console.log('📄 Created activities/README.md');
329
+ }
330
+ // Copy activities lib directory (MDC templates)
331
+ const activitiesLibSource = join(templateDir, 'activities', 'lib');
332
+ const activitiesLibDest = join(activitiesDir, 'lib');
333
+ if (existsSync(activitiesLibSource) && !existsSync(activitiesLibDest)) {
334
+ cpSync(activitiesLibSource, activitiesLibDest, { recursive: true });
335
+ console.log('📁 Created activities/lib with MDC templates');
336
+ }
337
+ // Copy activities.json from templates
338
+ const activitiesJsonPath = join(activitiesDir, 'activities.json');
339
+ const templateActivitiesJsonPath = join(templateDir, 'activities', 'activities.json');
340
+ if (!existsSync(activitiesJsonPath) && existsSync(templateActivitiesJsonPath)) {
341
+ copyFileSync(templateActivitiesJsonPath, activitiesJsonPath);
342
+ console.log('📄 Created activities.json with bundle example activity');
343
+ }
344
+ // Copy example activity from templates
345
+ const activitiesDestDir = join(activitiesDir, 'activities');
346
+ const templateActivitiesDir = join(templateDir, 'activities', 'activities');
347
+ if (!existsSync(activitiesDestDir) && existsSync(templateActivitiesDir)) {
348
+ cpSync(templateActivitiesDir, activitiesDestDir, { recursive: true });
349
+ console.log('📁 Created example activity with templates');
350
+ }
351
+ return server.initMessages;
352
+ }
353
+ export async function generateBundle(name) {
354
+ const server = new CntxServer(process.cwd());
355
+ await server.init({ skipFileWatcher: true });
356
+ return await server.bundleManager.regenerateBundle(name);
357
+ }
358
+ export async function getStatus() {
359
+ const server = new CntxServer(process.cwd());
360
+ await server.init({ skipFileWatcher: true });
361
+ const bundles = server.bundleManager.getAllBundleInfo();
362
+ const totalFiles = server.fileSystemManager.getAllFiles().length;
363
+ console.log('📊 cntx-ui Status');
364
+ console.log('================');
365
+ console.log(`Total files: ${totalFiles}`);
366
+ console.log(`Bundles: ${bundles.length}`);
367
+ bundles.forEach(bundle => {
368
+ console.log(` • ${bundle.name}: ${bundle.fileCount} files (${Math.round(bundle.size / 1024)}KB)`);
369
+ });
370
+ return {
371
+ totalFiles,
372
+ bundles: bundles.length,
373
+ bundleDetails: bundles
374
+ };
375
+ }
376
+ export function setupMCP() {
377
+ const configPath = join(homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json');
378
+ const projectPath = process.cwd();
379
+ console.log('🔧 Setting up MCP integration...');
380
+ console.log(`Project: ${projectPath}`);
381
+ console.log(`Claude config: ${configPath}`);
382
+ try {
383
+ let config = {};
384
+ if (existsSync(configPath)) {
385
+ config = JSON.parse(readFileSync(configPath, 'utf8'));
386
+ }
387
+ if (!config.mcpServers) {
388
+ config.mcpServers = {};
389
+ }
390
+ config.mcpServers['cntx-ui'] = {
391
+ command: 'npx',
392
+ args: ['cntx-ui', 'mcp'],
393
+ cwd: projectPath
394
+ };
395
+ // Ensure directory exists
396
+ mkdirSync(dirname(configPath), { recursive: true });
397
+ writeFileSync(configPath, JSON.stringify(config, null, 2));
398
+ console.log('✅ MCP integration configured');
399
+ console.log('💡 Restart Claude Desktop to apply changes');
400
+ }
401
+ catch (error) {
402
+ console.error('❌ Failed to setup MCP:', error.message);
403
+ console.log('💡 You may need to manually add the configuration to Claude Desktop');
404
+ }
405
+ }
406
+ // Auto-start server when run directly
407
+ const isMainModule = import.meta.url === `file://${process.argv[1]}`;
408
+ if (isMainModule) {
409
+ console.log('🚀 Starting cntx-ui server...');
410
+ const server = new CntxServer();
411
+ server.init();
412
+ server.listen(3333, 'localhost');
413
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "cntx-ui",
3
3
  "type": "module",
4
- "version": "3.0.8",
4
+ "version": "3.1.0",
5
5
  "description": "Autonomous Repository Intelligence engine with web UI and MCP server. Unified semantic code understanding, local RAG, and agent working memory.",
6
6
  "keywords": [
7
7
  "repository-intelligence",
@@ -20,13 +20,12 @@
20
20
  },
21
21
  "author": "whaleen",
22
22
  "license": "MIT",
23
+ "main": "dist/server.js",
23
24
  "bin": {
24
- "cntx-ui": "./bin/cntx-ui.js"
25
+ "cntx-ui": "./dist/bin/cntx-ui.js"
25
26
  },
26
27
  "files": [
27
- "bin/",
28
- "server.js",
29
- "lib/",
28
+ "dist/",
30
29
  "templates/",
31
30
  "web/dist/",
32
31
  "README.md",
@@ -36,12 +35,14 @@
36
35
  "node": ">=18.0.0"
37
36
  },
38
37
  "scripts": {
39
- "dev": "node server.js",
40
- "build": "cd web && npm install && npm run build",
38
+ "dev": "ts-node --esm bin/cntx-ui.ts",
39
+ "build:backend": "tsc && chmod +x dist/bin/cntx-ui.js",
40
+ "build:web": "cd web && npm install && npm run build",
41
+ "build": "npm run build:backend && npm run build:web",
41
42
  "check:version-sync": "node scripts/check-version-sync.mjs",
42
43
  "release:ci": "node scripts/release-from-package.mjs",
43
44
  "prepublishOnly": "npm run build",
44
- "test:local": "npm pack && npm install -g ./cntx-ui-3.0.0.tgz"
45
+ "test:local": "npm pack && npm install -g ./cntx-ui-3.1.0.tgz"
45
46
  },
46
47
  "dependencies": {
47
48
  "@xenova/transformers": "^2.17.2",
@@ -52,5 +53,13 @@
52
53
  "tree-sitter-rust": "^0.21.0",
53
54
  "tree-sitter-typescript": "^0.23.2",
54
55
  "ws": "^8.13.0"
56
+ },
57
+ "devDependencies": {
58
+ "@types/better-sqlite3": "^7.6.13",
59
+ "@types/glob": "^8.1.0",
60
+ "@types/node": "^25.3.2",
61
+ "@types/ws": "^8.18.1",
62
+ "ts-node": "^10.9.2",
63
+ "typescript": "^5.9.3"
55
64
  }
56
65
  }
@@ -1,3 +0,0 @@
1
- #!/bin/bash
2
- # Wrapper script to run cntx-ui MCP server in current directory
3
- cd "$(pwd)" && npx cntx-ui mcp
package/bin/cntx-ui.js DELETED
@@ -1,123 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { readFileSync } from 'fs';
4
- import { dirname, join } from 'path';
5
- import { fileURLToPath } from 'url';
6
- import { autoInitAndStart, startMCPServer, generateBundle, initConfig, getStatus } from '../server.js';
7
-
8
- const __dirname = dirname(fileURLToPath(import.meta.url));
9
- const packagePath = join(__dirname, '..', 'package.json');
10
- const packageJson = JSON.parse(readFileSync(packagePath, 'utf8'));
11
-
12
- const args = process.argv.slice(2);
13
- const command = args[0] || 'start';
14
- const isVerbose = args.includes('--verbose');
15
-
16
- // Graceful shutdown
17
- process.on('SIGINT', () => {
18
- console.log('\n Shutting down cntx-ui...');
19
- process.exit(0);
20
- });
21
-
22
- function showHelp() {
23
- console.log(`cntx-ui v${packageJson.version}
24
-
25
- ${packageJson.description}
26
-
27
- Usage:
28
- cntx-ui [command] [options]
29
-
30
- Commands:
31
- (default) Auto-init if needed, then start web server
32
- init Initialize configuration in current directory
33
- mcp Start MCP server (stdio transport)
34
- bundle [name] Generate specific bundle (default: master)
35
- status Show current project status
36
-
37
- Options:
38
- --verbose Enable detailed logging
39
- --version, -v Show version number
40
- --help, -h Show this help message
41
-
42
- Examples:
43
- cntx-ui Start server (auto-inits if needed)
44
- cntx-ui init Initialize a new project
45
- cntx-ui mcp Start MCP server on stdio
46
- cntx-ui bundle api Generate 'api' bundle
47
- cntx-ui status Show project status
48
-
49
- MCP Integration:
50
- Running 'cntx-ui init' creates a .mcp.json file so Claude Code
51
- can auto-discover the MCP server. Run 'cntx-ui mcp' for stdio mode.
52
-
53
- Repository: ${packageJson.repository.url}
54
- Author: ${packageJson.author}
55
- License: ${packageJson.license}`);
56
- }
57
-
58
- function showVersion() {
59
- console.log(`cntx-ui v${packageJson.version}`);
60
- }
61
-
62
- async function main() {
63
- // Handle version flags
64
- if (args.includes('--version') || args.includes('-v')) {
65
- return showVersion();
66
- }
67
-
68
- // Handle help flags
69
- if (args.includes('--help') || args.includes('-h') || command === 'help') {
70
- return showHelp();
71
- }
72
-
73
- try {
74
- switch (command) {
75
- case 'start':
76
- case 'watch':
77
- case 'w':
78
- const port = parseInt(args[1]) || 3333;
79
- await autoInitAndStart({ port, verbose: isVerbose });
80
- break;
81
-
82
- case 'mcp':
83
- // MCP server mode - runs on stdio
84
- await startMCPServer({ cwd: process.cwd(), verbose: isVerbose });
85
- break;
86
-
87
- case 'bundle':
88
- case 'b':
89
- const bundleName = args[1] || 'master';
90
- try {
91
- await generateBundle(bundleName);
92
- console.log(`Bundle '${bundleName}' generated successfully`);
93
- } catch (error) {
94
- console.error(`Failed to generate bundle '${bundleName}': ${error.message}`);
95
- process.exit(1);
96
- }
97
- break;
98
-
99
- case 'init':
100
- case 'i':
101
- await initConfig();
102
- break;
103
-
104
- case 'status':
105
- case 's':
106
- await getStatus();
107
- break;
108
-
109
- default:
110
- console.error(`Unknown command: ${command}`);
111
- console.log('Run "cntx-ui --help" for usage information.');
112
- process.exit(1);
113
- }
114
- } catch (error) {
115
- console.error(`Error: ${error.message}`);
116
- if (isVerbose) {
117
- console.error(error.stack);
118
- }
119
- process.exit(1);
120
- }
121
- }
122
-
123
- main().catch(console.error);