MCPcopy Create free account
hub / github.com/QodeXcli/QodeX / bootstrap

Function bootstrap

src/index.ts:40–147  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

38import { fileURLToPath } from 'url';
39import { logger } from './utils/logger.js';
40
41async function bootstrap(): Promise<{
42 config: Awaited<ReturnType<typeof loadConfig>>;
43 router: ModelRouter;
44 registry: ToolRegistry;
45 permissions: PermissionEngine;
46 mcpManager: MCPManager;
47 codeGraph: CodeGraphDB;
48 indexer: Indexer;
49 hooks: HooksManager;
50}> {
51 await ensureQodexHome();
52 await logger.init('info');
53 logger.info('QodeX starting', { node: process.version, cwd: process.cwd() });
54
55 // Load any API keys stored in ~/.qodex/.env (written by `qodex provider add`) into the
56 // environment BEFORE the router reads them. An explicit `export` in the user's shell still
57 // wins, so this never overrides a key they set themselves.
58 try {
59 const { loadEnvFileIntoProcess } = await import('./setup/env-writer.js');
60 const n = await loadEnvFileIntoProcess();
61 if (n > 0) logger.info(`Loaded ${n} API key(s) from ~/.qodex/.env`);
62 } catch (e: any) {
63 logger.debug('No ~/.qodex/.env loaded', { err: e?.message });
64 }
65
66 // Warm the real BPE tokenizer in the background (gpt-tokenizer, if installed).
67 // Non-blocking: token counts use the calibrated heuristic until this resolves.
68 void import('./utils/tokenizer.js').then(t => t.warmTokenizer()).catch((err) => logger.debug('tokenizer warm-up failed', { err }));
69
70 const config = await loadConfig(process.cwd());
71 // Import Claude Code plugins/standalone assets: agents → dispatchable roles (for the
72 // `task` tool + plugin commands like /review-pr), plus plugin-declared MCP servers and
73 // hooks. User config always wins on collisions. (Skills/commands are loaded separately
74 // by their own loaders.) Disable all of this with QODEX_DISABLE_CLAUDE_PLUGINS=1.
75 try {
76 const { applyClaudeCodeIntegration } = await import('./integrations/claude-plugins.js');
77 const r = await applyClaudeCodeIntegration(config, process.cwd());
78 if (r.agents || r.mcp || r.hooks) {
79 logger.info('Claude Code integration applied', r);
80 }
81 } catch (e: any) {
82 logger.debug('Claude Code integration skipped', { err: e?.message });
83 }
84 setActiveConfig(config);
85 // Browser CDP attach: if configured, the browser_* tools attach to the user's running
86 // browser instead of launching a fresh headless one. (QODEX_BROWSER_CDP_URL env wins.)
87 if ((config as any).browser?.cdpUrl) {
88 try {
89 const { setBrowserCdpUrl } = await import('./tools/browser/session.js');
90 setBrowserCdpUrl((config as any).browser.cdpUrl);
91 } catch { /* browser module optional */ }
92 }
93 const router = new ModelRouter(config);
94 const registry = new ToolRegistry();
95 const permissions = new PermissionEngine(config);
96
97 // Code graph — project-local SQLite

Callers 1

index.tsFile · 0.85

Calls 15

initializeMethod · 0.95
startAllMethod · 0.95
ensureQodexHomeFunction · 0.85
loadEnvFileIntoProcessFunction · 0.85
loadConfigFunction · 0.85
setActiveConfigFunction · 0.85
setBrowserCdpUrlFunction · 0.85
setCodeGraphDBFunction · 0.85
setIndexerFunction · 0.85
setHooksManagerFunction · 0.85
setMCPManagerFunction · 0.85

Tested by

no test coverage detected