@kodus/cli 0.0.1 → 0.0.2

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.
package/index.js CHANGED
@@ -1,70 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { program } from "commander";
4
- import inquirer from "inquirer";
5
- import chalk from "chalk";
6
- import ora from "ora";
7
- import fs from "fs-extra";
8
- import path from "path";
9
- import { execSync } from "child_process";
10
- import { fileURLToPath } from "url";
11
- import { dirname } from "path";
12
- import crypto from "crypto";
13
- import fetch from "node-fetch";
14
-
15
- const __filename = fileURLToPath(import.meta.url);
16
- const __dirname = dirname(__filename);
17
-
18
- // Helper functions
19
- const generateSecretKey = () => crypto.randomBytes(32).toString("base64");
20
- const generateDbPassword = () =>
21
- crypto
22
- .randomBytes(16)
23
- .toString("base64")
24
- .replace(/[^a-zA-Z0-9]/g, "")
25
- .slice(0, 16);
26
-
27
- const backupEnv = () => {
28
- if (fs.existsSync(".env")) {
29
- const timestamp = new Date().toISOString().replace(/[:.]/g, "-");
30
- fs.copySync(".env", `.env.backup.${timestamp}`);
31
- return true;
32
- }
33
- return false;
34
- };
35
-
36
- const restoreEnv = (backupFile) => {
37
- if (fs.existsSync(backupFile)) {
38
- fs.copySync(backupFile, ".env");
39
- return true;
40
- }
41
- return false;
42
- };
43
-
44
- const getLatestVersion = () => {
45
- try {
46
- const result = execSync("git describe --tags --abbrev=0", { stdio: "pipe" })
47
- .toString()
48
- .trim();
49
- return result;
50
- } catch (error) {
51
- Y;
52
- return null;
53
- }
54
- };
55
-
56
- const getCurrentVersion = () => {
57
- try {
58
- const result = execSync("git rev-parse --abbrev-ref HEAD", {
59
- stdio: "pipe",
60
- })
61
- .toString()
62
- .trim();
63
- return result;
64
- } catch (error) {
65
- return null;
66
- }
67
- };
4
+ import setupEnvironment from "./src/commands/install.js";
68
5
 
69
6
  // CLI version
70
7
  program.version("1.0.0");
@@ -73,466 +10,6 @@ program.version("1.0.0");
73
10
  program
74
11
  .command("install")
75
12
  .description("Install and configure Kodus")
76
- .action(async () => {
77
- try {
78
- // Check prerequisites
79
- console.log(chalk.blue("\nšŸ” Checking prerequisites..."));
80
- const spinner = ora("Checking Docker installation").start();
81
-
82
- try {
83
- execSync("docker --version", { stdio: "ignore" });
84
- spinner.succeed("Docker is installed");
85
- } catch (error) {
86
- spinner.fail("Docker is not installed");
87
- console.error(
88
- chalk.red(
89
- "\nPlease install Docker first: https://docs.docker.com/get-docker/"
90
- )
91
- );
92
- process.exit(1);
93
- }
94
-
95
- // Environment type selection
96
- const { envType } = await inquirer.prompt([
97
- {
98
- type: "list",
99
- name: "envType",
100
- message: "What type of environment are you setting up?",
101
- choices: [
102
- { name: "Local (localhost)", value: "local" },
103
- { name: "External (with public URL)", value: "external" },
104
- ],
105
- default: "local",
106
- },
107
- ]);
108
-
109
- let baseUrl = "http://localhost:3000";
110
- if (envType === "external") {
111
- const { url } = await inquirer.prompt([
112
- {
113
- type: "input",
114
- name: "url",
115
- message: "Enter your public URL (e.g., https://kodus.yourdomain.com):",
116
- validate: (input) => {
117
- try {
118
- const url = new URL(input);
119
- if (!url.protocol.startsWith('http')) {
120
- return "URL must start with http:// or https://";
121
- }
122
- if (!url.hostname.includes('.')) {
123
- return "URL must include a valid domain name";
124
- }
125
- return true;
126
- } catch (e) {
127
- return "Please enter a valid URL (e.g., https://kodus.yourdomain.com)";
128
- }
129
- },
130
- },
131
- ]);
132
- baseUrl = url;
133
- }
134
-
135
- // Git service selection
136
- const { gitService } = await inquirer.prompt([
137
- {
138
- type: "list",
139
- name: "gitService",
140
- message: "Which Git service will you use?",
141
- choices: [
142
- { name: "GitHub", value: "github" },
143
- { name: "GitLab", value: "gitlab" },
144
- { name: "Bitbucket", value: "bitbucket" },
145
- ],
146
- },
147
- ]);
148
-
149
- // Git service configuration
150
- let gitConfig = {};
151
-
152
- if (envType === "local") {
153
- console.log(chalk.yellow("\nāš ļø IMPORTANT: If you're using a cloud Git service (GitHub, GitLab, Bitbucket), you'll need to configure the webhook manually."));
154
- console.log(chalk.yellow("For local or self-hosted Git instances, no additional configuration is needed."));
155
- console.log(chalk.yellow("The webhook URL will be:"));
156
- console.log(chalk.white(`${baseUrl}/api/webhook/${gitService}`));
157
- }
158
-
159
- // Configure webhook URL based on the selected Git service
160
- if (gitService === "github") {
161
- gitConfig = {
162
- API_GITHUB_CODE_MANAGEMENT_WEBHOOK: `${baseUrl}/api/webhook/${gitService}`,
163
- };
164
- } else if (gitService === "gitlab") {
165
- gitConfig = {
166
- API_GITLAB_CODE_MANAGEMENT_WEBHOOK: `${baseUrl}/api/webhook/${gitService}`,
167
- };
168
- } else if (gitService === "bitbucket") {
169
- gitConfig = {
170
- GLOBAL_BITBUCKET_CODE_MANAGEMENT_WEBHOOK: `${baseUrl}/api/webhook/${gitService}`,
171
- };
172
- }
173
-
174
- // Database configuration
175
- const { useDefaultDb } = await inquirer.prompt([
176
- {
177
- type: "confirm",
178
- name: "useDefaultDb",
179
- message: "Would you like to use default database configurations?",
180
- default: true,
181
- },
182
- ]);
183
-
184
- // LLM API Keys configuration
185
- console.log(chalk.blue("\nšŸ”‘ Configuring LLM API Keys..."));
186
- const llmKeys = await inquirer.prompt([
187
- {
188
- type: "input",
189
- name: "openAiKey",
190
- message: "Enter your OpenAI API key (optional):",
191
- default: "",
192
- },
193
- {
194
- type: "input",
195
- name: "googleAiKey",
196
- message: "Enter your Google AI API key (optional):",
197
- default: "",
198
- },
199
- {
200
- type: "input",
201
- name: "anthropicKey",
202
- message: "Enter your Anthropic API key (optional):",
203
- default: "",
204
- },
205
- {
206
- type: "input",
207
- name: "fireworksKey",
208
- message: "Enter your Fireworks API key (optional):",
209
- default: "",
210
- },
211
- {
212
- type: "input",
213
- name: "novitaKey",
214
- message: "Enter your Novita AI API key (optional):",
215
- default: "",
216
- },
217
- {
218
- type: "input",
219
- name: "vertexKey",
220
- message: "Enter your Vertex AI API key (optional):",
221
- default: "",
222
- },
223
- ]);
224
-
225
- // Start installation
226
- console.log(chalk.blue("\nšŸš€ Starting installation..."));
227
-
228
- // Generate .env content
229
- const envContent = {
230
- // Base configuration
231
- WEB_NODE_ENV: "development",
232
- WEB_HOSTNAME_API: "localhost",
233
- WEB_PORT_API: "3001",
234
- WEB_PORT: "3000",
235
- WEB_NEXTAUTH_URL: "http://localhost:3000",
236
- WEB_NEXTAUTH_SECRET: generateSecretKey(),
237
- WEB_JWT_SECRET_KEY: generateSecretKey(),
238
-
239
- API_NODE_ENV: "development",
240
- API_LOG_LEVEL: "error",
241
- API_LOG_PRETTY: "true",
242
- API_HOST: "0.0.0.0",
243
- API_PORT: "3001",
244
- API_RATE_MAX_REQUEST: "100",
245
- API_RATE_INTERVAL: "1000",
246
- API_JWT_EXPIRES_IN: "365d",
247
- API_JWT_SECRET: generateSecretKey(),
248
- API_JWT_REFRESHSECRET: generateSecretKey(),
249
- API_JWT_REFRESH_EXPIRES_IN: "7d",
250
-
251
- GLOBAL_API_CONTAINER_NAME: "kodus-orchestrator-prod",
252
-
253
- // Database
254
- API_DATABASE_ENV: "development",
255
- API_PG_DB_USERNAME: "kodusdev",
256
- API_PG_DB_PASSWORD: generateDbPassword(),
257
- API_PG_DB_DATABASE: "kodus_db",
258
- API_PG_DB_HOST: "db_kodus_postgres",
259
- API_PG_DB_PORT: "5432",
260
-
261
- API_MG_DB_USERNAME: "kodusdev",
262
- API_MG_DB_PASSWORD: generateDbPassword(),
263
- API_MG_DB_DATABASE: "kodus_db",
264
- API_MG_DB_HOST: "db_kodus_mongodb",
265
- API_MG_DB_PORT: "27017",
266
- API_MG_DB_PRODUCTION_CONFIG: "",
267
-
268
- // LLM API Keys
269
- API_OPEN_AI_APIKEY: llmKeys.openAiKey,
270
- API_GOOGLE_AI_API_KEY: llmKeys.googleAiKey,
271
- API_ANTHROPIC_API_KEY: llmKeys.anthropicKey,
272
- API_FIREWORKS_API_KEY: llmKeys.fireworksKey,
273
- API_NOVITA_AI_API_KEY: llmKeys.novitaKey,
274
- API_VERTEX_AI_API_KEY: llmKeys.vertexKey,
275
-
276
- // LLM Models
277
- API_LLM_MODEL_CHATGPT_3_5_TURBO: "gpt-4o-mini",
278
- API_LLM_MODEL_CHATGPT_3_5_TURBO_16K: "gpt-4o-mini",
279
- API_LLM_MODEL_CHATGPT_4: "gpt-4o-mini",
280
- API_LLM_MODEL_CHATGPT_4_TURBO: "gpt-4o-mini",
281
- API_LLM_MODEL_CHATGPT_4_ALL: "gpt-4o",
282
- API_LLM_MODEL_CHATGPT_4_ALL_MINI: "gpt-4o-mini",
283
- API_LLM_MODEL_CLAUDE_3_5_SONNET: "claude-3-5-sonnet-20241022",
284
- API_LLM_MODEL_CLAUDE_3_5_SONNET_20241022: "claude-3-5-sonnet-20241022",
285
- API_LLM_MODEL_GEMINI_1_5_PRO: "gpt-4o-mini",
286
- API_LLM_MODEL_GEMINI_1_5_PRO_EXP: "gpt-4o-mini",
287
-
288
- // Git service configuration
289
- ...gitConfig,
290
-
291
- // Ports
292
- WEB_PORT: "3000",
293
- API_PORT: "3001",
294
-
295
- // RabbitMQ
296
- RABBITMQ_DEFAULT_USER: "kodus",
297
- RABBITMQ_DEFAULT_PASS: generateDbPassword(),
298
-
299
- // Monitoring
300
- GRAFANA_ADMIN_PASSWORD: generateDbPassword(),
301
- };
302
-
303
- // Create .env file
304
- const envSpinner = ora("Creating .env file").start();
305
- const envContentString = Object.entries(envContent)
306
- .map(([key, value]) => `${key}=${value}`)
307
- .join("\n");
308
- fs.writeFileSync(".env", envContentString);
309
- envSpinner.succeed("Created .env file");
310
-
311
- // Start containers
312
- const dockerSpinner = ora("Starting containers").start();
313
- try {
314
- execSync("docker-compose up -d", { stdio: "pipe" });
315
- dockerSpinner.succeed("Containers started");
316
- } catch (error) {
317
- dockerSpinner.fail("Failed to start containers");
318
- console.error(chalk.red("\nError details:"));
319
- console.error(chalk.white(error.stdout?.toString() || error.message));
320
- process.exit(1);
321
- }
322
-
323
- const maxAttempts = 30; // 5 minutes with 10 second intervals
324
-
325
- // Wait for PostgreSQL to be ready
326
- const pgSpinner = ora("Waiting for PostgreSQL to be ready").start();
327
- let isPgReady = false;
328
- let pgAttempts = 0;
329
-
330
- while (!isPgReady && pgAttempts < maxAttempts) {
331
- try {
332
- const logs = execSync("docker-compose logs db_kodus_postgres", { stdio: "pipe" }).toString();
333
- if (logs.includes("database system is ready to accept connections")) {
334
- isPgReady = true;
335
- pgSpinner.succeed("PostgreSQL is ready");
336
- } else {
337
- pgAttempts++;
338
- await new Promise(resolve => setTimeout(resolve, 10000));
339
- }
340
- } catch (error) {
341
- pgAttempts++;
342
- await new Promise(resolve => setTimeout(resolve, 10000));
343
- }
344
- }
345
-
346
- if (!isPgReady) {
347
- pgSpinner.fail("PostgreSQL failed to start");
348
- console.error(chalk.red("\nError: PostgreSQL failed to start properly"));
349
- console.error(chalk.yellow("\nTroubleshooting steps:"));
350
- console.error(chalk.white("1. Check PostgreSQL logs: docker-compose logs db_kodus_postgres"));
351
- console.error(chalk.white("2. Verify PostgreSQL container is running: docker-compose ps db_kodus_postgres"));
352
- process.exit(1);
353
- }
354
-
355
- // Wait for MongoDB to be ready
356
- const mongoSpinner = ora("Waiting for MongoDB to be ready").start();
357
- let isMongoReady = false;
358
- let mongoAttempts = 0;
359
-
360
- while (!isMongoReady && mongoAttempts < maxAttempts) {
361
- try {
362
- const logs = execSync("docker-compose logs db_kodus_mongodb", { stdio: "pipe" }).toString();
363
- if (logs.includes("Waiting for connections") || logs.includes("Connection accepted")) {
364
- isMongoReady = true;
365
- mongoSpinner.succeed("MongoDB is ready");
366
- } else {
367
- mongoAttempts++;
368
- await new Promise(resolve => setTimeout(resolve, 10000));
369
- }
370
- } catch (error) {
371
- mongoAttempts++;
372
- await new Promise(resolve => setTimeout(resolve, 10000));
373
- }
374
- }
375
-
376
- if (!isMongoReady) {
377
- mongoSpinner.fail("MongoDB failed to start");
378
- console.error(chalk.red("\nError: MongoDB failed to start properly"));
379
- console.error(chalk.yellow("\nTroubleshooting steps:"));
380
- console.error(chalk.white("1. Check MongoDB logs: docker-compose logs db_kodus_mongodb"));
381
- console.error(chalk.white("2. Verify MongoDB container is running: docker-compose ps db_kodus_mongodb"));
382
- process.exit(1);
383
- }
384
-
385
- // Now wait for orchestrator to be ready
386
- const healthSpinner = ora("Waiting for orchestrator to be ready").start();
387
- let isOrchestratorReady = false;
388
- let attempts = 0;
389
-
390
- const criticalErrors = [
391
- "password authentication failed",
392
- "Unable to connect to the database",
393
- "FATAL:",
394
- "MongoServerError:",
395
- "connection refused"
396
- ];
397
-
398
- while (!isOrchestratorReady && attempts < maxAttempts) {
399
- try {
400
- // Check if container is running
401
- const containerStatus = execSync("docker-compose ps orchestrator --format json", { stdio: "pipe" }).toString();
402
- const status = JSON.parse(containerStatus)[0];
403
-
404
- if (status.State === "running") {
405
- // Check logs for any errors
406
- const logs = execSync("docker-compose logs --tail=50 orchestrator", { stdio: "pipe" }).toString();
407
-
408
- // Check for critical errors that should stop the process
409
- const foundCriticalError = criticalErrors.find(error => logs.includes(error));
410
- if (foundCriticalError) {
411
- healthSpinner.fail("Critical error detected");
412
- console.error(chalk.red("\nError: Database connection failed"));
413
- console.error(chalk.yellow("\nTroubleshooting steps:"));
414
- console.error(chalk.white("1. Check if the database passwords in .env match the ones in your database"));
415
- console.error(chalk.white("2. Verify if the database containers are running: docker-compose ps"));
416
- console.error(chalk.white("3. Check database logs: docker-compose logs db_kodus_postgres db_kodus_mongodb"));
417
- console.error(chalk.white("\nFull error log:"));
418
- console.error(chalk.white(logs));
419
- process.exit(1);
420
- }
421
-
422
- // If no critical errors and we see successful connection messages, proceed
423
- if (logs.includes("Database connection established") || logs.includes("Connected to MongoDB")) {
424
- isOrchestratorReady = true;
425
- healthSpinner.succeed("Orchestrator is ready");
426
- } else {
427
- attempts++;
428
- await new Promise(resolve => setTimeout(resolve, 10000)); // Wait 10 seconds
429
- }
430
- } else {
431
- attempts++;
432
- await new Promise(resolve => setTimeout(resolve, 10000)); // Wait 10 seconds
433
- }
434
- } catch (error) {
435
- attempts++;
436
- await new Promise(resolve => setTimeout(resolve, 10000)); // Wait 10 seconds
437
- }
438
- }
439
-
440
- if (!isOrchestratorReady) {
441
- healthSpinner.fail("Orchestrator failed to start");
442
- console.error(chalk.red("\nError: The orchestrator service failed to start properly."));
443
- console.error(chalk.yellow("\nTroubleshooting steps:"));
444
- console.error(chalk.white("1. Check the orchestrator logs: docker-compose logs orchestrator"));
445
- console.error(chalk.white("2. Verify all required services are running: docker-compose ps"));
446
- console.error(chalk.white("3. Try restarting the services: docker-compose restart"));
447
- process.exit(1);
448
- }
449
-
450
- // Setup database
451
- const dbSpinner = ora("Setting up database").start();
452
- try {
453
- execSync("./scripts/setup-db.sh", { stdio: "pipe" });
454
- dbSpinner.succeed("Database setup completed");
455
- } catch (error) {
456
- dbSpinner.fail("Failed to setup database");
457
- console.error(chalk.red("\nError details:"));
458
- console.error(chalk.white(error.stdout?.toString() || error.message));
459
- process.exit(1);
460
- }
461
-
462
- // Verify database connection by checking orchestrator logs
463
- const dbCheckSpinner = ora("Verifying database connection").start();
464
- try {
465
- const logs = execSync("docker-compose logs --tail=50 orchestrator", { stdio: "pipe" }).toString();
466
-
467
- // Look for database connection errors in logs
468
- if (logs.includes("database connection error") || logs.includes("Database connection failed")) {
469
- throw new Error("Database connection errors found in logs");
470
- }
471
-
472
- dbCheckSpinner.succeed("Database connection verified");
473
- } catch (error) {
474
- dbCheckSpinner.fail("Failed to verify database connection");
475
- console.error(chalk.red("\nError: Could not verify database connection."));
476
- console.error(chalk.yellow("Please check the logs with: docker-compose logs orchestrator"));
477
- process.exit(1);
478
- }
479
-
480
- // Installation complete
481
- console.log(chalk.green("\n✨ Installation completed successfully!"));
482
-
483
- console.log(chalk.blue("\nšŸ“ Installation Summary:"));
484
- console.log(
485
- chalk.white(
486
- ` - Environment: ${envType === "local" ? "Local" : "External"}`
487
- )
488
- );
489
- if (envType === "external") {
490
- console.log(chalk.white(` - Base URL: ${baseUrl}`));
491
- }
492
- console.log(
493
- chalk.white(
494
- ` - Git Service: ${
495
- gitService.charAt(0).toUpperCase() + gitService.slice(1)
496
- }`
497
- )
498
- );
499
- console.log(
500
- chalk.white(
501
- ` - Database: ${
502
- useDefaultDb ? "Default configuration" : "Custom configuration"
503
- }`
504
- )
505
- );
506
-
507
- console.log(chalk.blue("\nšŸ”— Access URLs:"));
508
- console.log(chalk.white(` - Web Interface: ${baseUrl}`));
509
- console.log(chalk.white(" - Grafana Dashboard: http://localhost:3001"));
510
- console.log(
511
- chalk.white(" - RabbitMQ Management: http://localhost:15672")
512
- );
513
-
514
- console.log(chalk.blue("\nšŸ“š Next Steps:"));
515
- console.log(chalk.white(" 1. Access the web interface"));
516
- console.log(chalk.white(" 2. Set up your first user"));
517
- console.log(chalk.white(" 3. Start using Kodus!"));
518
-
519
- const { startServices } = await inquirer.prompt([
520
- {
521
- type: "confirm",
522
- name: "startServices",
523
- message: "Would you like to start the services now?",
524
- default: true,
525
- },
526
- ]);
527
-
528
- if (startServices) {
529
- execSync("docker-compose up -d", { stdio: "ignore" });
530
- console.log(chalk.green("\nServices started successfully!"));
531
- }
532
- } catch (error) {
533
- console.error(chalk.red("\nāŒ Installation failed:"), error.message);
534
- process.exit(1);
535
- }
536
- });
13
+ .action(setupEnvironment);
537
14
 
538
15
  program.parse(process.argv);
package/license.md ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Kodus CLI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kodus/cli",
3
- "version": "0.0.1",
3
+ "version": "0.0.2",
4
4
  "description": "CLI tool for Kodus installation and management",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -8,6 +8,10 @@
8
8
  "bin": {
9
9
  "kodus": "./index.js"
10
10
  },
11
+ "files": [
12
+ "index.js",
13
+ "templates/**/*"
14
+ ],
11
15
  "scripts": {
12
16
  "test": "echo \"Error: no test specified\" && exit 1"
13
17
  },
package/readme.md ADDED
@@ -0,0 +1,128 @@
1
+ <div align="center">
2
+
3
+ <p align="center">
4
+ <img src="https://kodus.io/wp-content/uploads/2025/04/koduscli.png" alt="Kodus CLI Banner" />
5
+ </p>
6
+
7
+ **Deploy and manage Kodus AI Code Review Agents in your infrastructure**
8
+
9
+ [![GitHub license](https://img.shields.io/github/license/kodustech/kodus-cli)](https://github.com/yourusername/kodus-cli/blob/main/LICENSE)
10
+ [![npm version](https://img.shields.io/npm/v/@kodus/cli)](https://www.npmjs.com/package/@kodus/cli)
11
+ [![Downloads](https://img.shields.io/npm/dm/@kodus/cli)](https://www.npmjs.com/package/@kodus/cli)
12
+
13
+ </div>
14
+
15
+ ## 🌟 Overview
16
+
17
+ Kodus CLI is your gateway to running Kodus AI Code Review Agents in your own infrastructure. With a single command, deploy and manage your code review automation system, keeping your code quality high while maintaining full control over your data and infrastructure.
18
+
19
+ ## ✨ Features
20
+
21
+ - šŸ”„ **One-Command Deployment**: Deploy your entire Kodus infrastructure in minutes
22
+ - šŸ”’ **Self-Hosted**: Keep your code and data within your infrastructure
23
+ - šŸ¤– **AI-Powered Reviews**: Leverage advanced AI models for code review automation
24
+ - šŸ”„ **Git Integration**: Seamless integration with GitHub, GitLab, and Bitbucket
25
+ - šŸ“Š **Monitoring & Analytics**: Built-in Grafana dashboards for insights
26
+ - 🐳 **Docker-Powered**: Containerized for consistency and easy management
27
+ - šŸ” **Secure by Default**: Enterprise-grade security with auto-generated credentials
28
+
29
+ ## šŸš€ Quick Start
30
+
31
+ ```bash
32
+ # Install globally
33
+ npm install -g kodus-cli
34
+
35
+ # Deploy Kodus in your infrastructure
36
+ kodus install
37
+ ```
38
+
39
+ ## šŸ“– Documentation
40
+
41
+ ### Basic Usage
42
+
43
+ ```bash
44
+ # Deploy Kodus
45
+ kodus install
46
+
47
+ # Follow the interactive prompts to configure:
48
+ # - Environment type (local/external)
49
+ # - Git service integration
50
+ # - AI provider settings
51
+ # - Infrastructure preferences
52
+ ```
53
+
54
+ ### Environment Types
55
+
56
+ - **Local Development**
57
+
58
+ - Perfect for testing and development
59
+ - Runs everything on localhost
60
+ - Ideal for small teams and individual developers
61
+
62
+ - **External Deployment**
63
+ - Production-ready setup
64
+ - Configurable for any domain
65
+ - Suitable for enterprise environments
66
+
67
+ ### Supported Git Services
68
+
69
+ | Service | Features |
70
+ | --------- | ------------------------------------------- |
71
+ | GitHub | Pull Request Reviews, Issue Analysis |
72
+ | GitLab | Merge Request Reviews, Pipeline Integration |
73
+ | Bitbucket | Pull Request Reviews, Repository Analysis |
74
+
75
+ ### AI Integration
76
+
77
+ Kodus supports multiple AI providers for code review:
78
+
79
+ - OpenAI (GPT-4)
80
+ - Google AI
81
+ - Anthropic (Claude)
82
+ - Novita AI
83
+ - Vertex AI
84
+
85
+ ## šŸ”’ Security
86
+
87
+ - All data stays within your infrastructure
88
+ - No code or sensitive information is sent to external servers
89
+ - Enterprise-grade encryption for all communications
90
+ - Role-based access control
91
+ - Audit logging for all operations
92
+
93
+ ## šŸ¤ Contributing
94
+
95
+ We welcome contributions!
96
+
97
+ ```bash
98
+ # Clone the repository
99
+ git clone https://github.com/yourusername/kodus-cli.git
100
+
101
+ # Install dependencies
102
+ npm install
103
+
104
+ # Run tests
105
+ npm test
106
+ ```
107
+
108
+ ## šŸ“œ License
109
+
110
+ MIT Ā© Kodus
111
+
112
+ ## 🌟 Star History
113
+
114
+ [![Star History Chart](https://api.star-history.com/svg?repos=yourusername/kodus-cli&type=Date)](https://star-history.com/#yourusername/kodus-cli&Date)
115
+
116
+ ## šŸ™ Acknowledgments
117
+
118
+ Special thanks to all our contributors and the amazing open-source community.
119
+
120
+ ---
121
+
122
+ <div align="center">
123
+
124
+ **[Website](https://kodus.ios)** • **[Documentation](https://docs.kodus.io)** • **[Twitter](https://twitter.com/kodustech)** • **[Discord](https://discord.gg/VkbfjbZr)**
125
+
126
+ Made with ā¤ļø by the Kodus Team
127
+
128
+ </div>
@@ -0,0 +1,159 @@
1
+ services:
2
+ kodus-web:
3
+ image: ghcr.io/kodustech/kodus-web:latest
4
+ container_name: kodus-web-prod
5
+ ports:
6
+ - "${WEB_PORT}:${WEB_PORT}"
7
+ networks:
8
+ - shared-network
9
+ - kodus-backend-services
10
+ restart: unless-stopped
11
+ env_file:
12
+ - .env
13
+
14
+ kodus-orchestrator:
15
+ image: ghcr.io/kodustech/kodus-ai:latest
16
+ platform: linux/amd64
17
+ container_name: ${GLOBAL_API_CONTAINER_NAME}
18
+ volumes:
19
+ - log_volume:/app/logs
20
+ logging:
21
+ options:
22
+ max-size: "200m"
23
+ max-file: "10"
24
+ ports:
25
+ - "3001:3001"
26
+ - "9229:9229"
27
+ environment:
28
+ - ENV=production
29
+ - NODE_ENV=production
30
+ networks:
31
+ - shared-network
32
+ - kodus-backend-services
33
+ restart: unless-stopped
34
+ env_file:
35
+ - .env
36
+
37
+ rabbitmq:
38
+ image: localhost:5000/rabbitmq:prod
39
+ container_name: rabbitmq-prod
40
+ hostname: rabbitmq
41
+ ports:
42
+ - "5672:5672"
43
+ - "15672:15672"
44
+ networks:
45
+ - monitoring-network
46
+ - shared-network
47
+ environment:
48
+ - RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS=-rabbit heartbeat 60
49
+ restart: unless-stopped
50
+ env_file:
51
+ - .env
52
+
53
+ db_kodus_postgres:
54
+ image: postgres:latest
55
+ container_name: db_kodus_postgres
56
+ ports:
57
+ - "5432:5432"
58
+ environment:
59
+ # These variables must be defined in the .env file
60
+ POSTGRES_USER: ${API_PG_DB_USERNAME}
61
+ POSTGRES_PASSWORD: ${API_PG_DB_PASSWORD}
62
+ POSTGRES_DB: ${API_PG_DB_DATABASE}
63
+ volumes:
64
+ - pgdata:/var/lib/postgresql/data
65
+ networks:
66
+ - kodus-backend-services
67
+
68
+ db_kodus_mongodb:
69
+ image: mongo:7
70
+ container_name: db_kodus_mongodb
71
+ ports:
72
+ - "27017:27017"
73
+ volumes:
74
+ - mongodbdata:/data/db
75
+ environment:
76
+ # These variables must be defined in the .env file
77
+ MONGO_INITDB_ROOT_USERNAME: ${API_MG_DB_USERNAME}
78
+ MONGO_INITDB_ROOT_PASSWORD: ${API_MG_DB_PASSWORD}
79
+ MONGO_INITDB_DATABASE: ${API_MG_DB_DATABASE}
80
+ networks:
81
+ - kodus-backend-services
82
+
83
+ prometheus:
84
+ container_name: prometheus-prod
85
+ image: prom/prometheus:latest
86
+ environment:
87
+ - ENV=production
88
+ command:
89
+ - "--config.file=/etc/prometheus/prometheus.yml"
90
+ - "--storage.tsdb.retention.time=30d"
91
+ - "--storage.tsdb.retention.size=50GB"
92
+ - "--web.enable-lifecycle"
93
+ - "--web.enable-admin-api"
94
+ deploy:
95
+ resources:
96
+ limits:
97
+ cpus: "1"
98
+ memory: 4G
99
+ reservations:
100
+ cpus: "0.75"
101
+ memory: 2G
102
+
103
+ migration:
104
+ image: ghcr.io/kodustech/kodus-ai:latest
105
+ platform: linux/amd64
106
+ container_name: migration
107
+ depends_on:
108
+ - db_kodus_postgres
109
+ environment:
110
+ - ENV=${API_DATABASE_ENV}
111
+ - NODE_ENV=${API_NODE_ENV}
112
+ - API_PG_DB_HOST=${API_PG_DB_HOST}
113
+ - API_PG_DB_PORT=${API_PG_DB_PORT}
114
+ - API_PG_DB_USERNAME=${API_PG_DB_USERNAME}
115
+ - API_PG_DB_PASSWORD=${API_PG_DB_PASSWORD}
116
+ - API_PG_DB_DATABASE=${API_PG_DB_DATABASE}
117
+ - PGSSLMODE=disable
118
+ command: >
119
+ sh -c '
120
+ echo "Debug: Printing environment variables..." &&
121
+ echo "API_PG_DB_HOST=" $$API_PG_DB_HOST &&
122
+ echo "Creating temporary datasource file..." &&
123
+ echo "const { DataSource } = require(\"typeorm\");
124
+ module.exports = new DataSource({
125
+ type: \"postgres\",
126
+ host: \"db_kodus_postgres\",
127
+ port: 5432,
128
+ username: \"$$API_PG_DB_USERNAME\",
129
+ password: \"$$API_PG_DB_PASSWORD\",
130
+ database: \"$$API_PG_DB_DATABASE\",
131
+ ssl: false,
132
+ entities: [\"./dist/modules/**/infra/typeorm/entities/*.js\"],
133
+ migrations: [\"./dist/config/database/typeorm/migrations/*.js\"]
134
+ });" > datasource.js &&
135
+ yarn typeorm migration:run -d datasource.js
136
+ '
137
+ networks:
138
+ - kodus-backend-services
139
+ env_file:
140
+ - .env
141
+
142
+ volumes:
143
+ log_volume:
144
+ rabbitmq-data-prod:
145
+ name: rabbitmq-data-prod
146
+ pgdata:
147
+ mongodbdata:
148
+
149
+ networks:
150
+ shared-network:
151
+ external: true
152
+ monitoring-network:
153
+ driver: bridge
154
+ name: monitoring-network
155
+ external: true
156
+ kodus-backend-services:
157
+ driver: bridge
158
+ name: kodus-backend-services
159
+ external: true