berget 2.2.11 → 2.2.13

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.
@@ -1,14 +1,8 @@
1
- import chalk from 'chalk';
2
1
  import { Command } from 'commander';
3
- import { spawn } from 'node:child_process';
4
- import * as fs from 'node:fs';
5
- import { readFile, writeFile } from 'node:fs/promises';
6
- import path from 'node:path';
7
- import readline from 'node:readline';
8
2
 
9
3
  import { COMMAND_GROUPS, SUBCOMMANDS } from '../constants/command-structure';
10
4
  import { handleError } from '../utils/error-handler';
11
- import { runSetupCommand } from './code/setup';
5
+ import { runInitCommand } from './code/init';
12
6
 
13
7
  /**
14
8
  * Register code commands
@@ -18,611 +12,14 @@ export function registerCodeCommands(program: Command): void {
18
12
  .command(COMMAND_GROUPS.CODE)
19
13
  .description('AI-powered coding assistant with OpenCode');
20
14
 
21
- if (process.env.BERGET_EXPERIMENTAL) {
22
- code
23
- .command('setup')
24
- .description('Interactive setup for Berget AI coding tools')
25
- .action(async () => {
26
- try {
27
- await runSetupCommand();
28
- } catch (error) {
29
- handleError('Setup failed', error);
30
- }
31
- });
32
- }
33
-
34
15
  code
35
16
  .command(SUBCOMMANDS.CODE.INIT)
36
- .description('Initialize project for AI coding assistant')
37
- .option('-n, --name <name>', 'Project name (defaults to directory name)')
38
- .option('-f, --force', 'Overwrite existing configuration')
39
- .option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
40
- .action(async (options) => {
41
- try {
42
- const projectName = options.name || getProjectName();
43
- const configPath = path.join(process.cwd(), 'opencode.json');
44
-
45
- // Check if already initialized
46
- if (fs.existsSync(configPath) && !options.force) {
47
- if (!options.yes) {
48
- console.log(chalk.yellow('Project already initialized for OpenCode.'));
49
- console.log(chalk.dim(`Config file: ${configPath}`));
50
- }
51
-
52
- if (await confirm('Do you want to reinitialize? (Y/n): ', options.yes)) {
53
- // Continue with reinitialization
54
- } else {
55
- return;
56
- }
57
- }
58
-
59
- // Ensure opencode is installed
60
- if (!(await ensureOpencodeInstalled(options.yes))) {
61
- return;
62
- }
63
-
64
- console.log(chalk.cyan(`Initializing OpenCode for project: ${projectName}`));
65
-
66
- const config = {
67
- $schema: 'https://opencode.ai/config.json',
68
- plugin: ['@bergetai/opencode-auth@1.0.16'],
69
- };
70
-
71
- const agentsDir = path.join(process.cwd(), '.opencode', 'agents');
72
- const templatesDir = getAgentTemplatesDir();
73
-
74
- if (!options.yes) {
75
- console.log(chalk.blue('\nAbout to create configuration files:'));
76
- console.log(chalk.dim(`Config: ${configPath}`));
77
- console.log(chalk.dim(`Agents: ${agentsDir}/`));
78
- console.log(chalk.dim('This will configure OpenCode with the Berget auth plugin.'));
79
- }
80
-
81
- if (await confirm('\nCreate configuration files? (Y/n): ', options.yes)) {
82
- try {
83
- await writeFile(configPath, JSON.stringify(config, null, 2));
84
- console.log(chalk.green('✓ Created opencode.json'));
85
- console.log(chalk.dim(' Plugin: @bergetai/opencode-auth'));
86
-
87
- fs.mkdirSync(agentsDir, { recursive: true });
88
- const templateFiles = fs.readdirSync(templatesDir).filter((f) => f.endsWith('.md'));
89
- for (const file of templateFiles) {
90
- const source = path.join(templatesDir, file);
91
- const destination = path.join(agentsDir, file);
92
- fs.copyFileSync(source, destination);
93
- }
94
- console.log(
95
- chalk.green(
96
- `✓ Created ${templateFiles.length} agent definitions in .opencode/agents/`,
97
- ),
98
- );
99
- } catch (error) {
100
- console.error(chalk.red('Failed to create config files:'));
101
- handleError('Config file creation failed', error);
102
- return;
103
- }
104
- } else {
105
- console.log(chalk.yellow('Configuration file creation cancelled.'));
106
- return;
107
- }
108
-
109
- console.log(chalk.green('\n✅ Project initialized successfully!'));
110
- console.log(chalk.blue('\nNext steps:'));
111
- console.log(chalk.cyan(' 1. Run: opencode'));
112
- console.log(chalk.cyan(' 2. Type: /connect'));
113
- console.log(chalk.cyan(' 3. Choose your auth method:'));
114
- console.log(chalk.dim(' • "Login with Berget" — Berget Code team members (SSO)'));
115
- console.log(chalk.dim(' • "Enter API Key" — API key users (console.berget.ai)'));
116
- } catch (error) {
117
- handleError('Failed to initialize project', error);
118
- }
119
- });
120
-
121
- code
122
- .command(SUBCOMMANDS.CODE.RUN)
123
- .description('Run AI coding assistant')
124
- .argument('[prompt]', 'Prompt to send directly to OpenCode')
125
- .option('-m, --model <model>', 'Model to use (overrides config)')
126
- .option('-a, --analysis', 'Use fast analysis model for context building')
127
- .option('--no-config', 'Run without loading project config')
128
- .option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
129
- .action(async (prompt: string, options: any) => {
130
- try {
131
- const configPath = path.join(process.cwd(), 'opencode.json');
132
-
133
- // Ensure opencode is installed
134
- if (!(await ensureOpencodeInstalled(options.yes))) {
135
- return;
136
- }
137
-
138
- let config: any = null;
139
- if (!options.noConfig && fs.existsSync(configPath)) {
140
- try {
141
- const configContent = await readFile(configPath, 'utf8');
142
- config = JSON.parse(configContent);
143
- console.log(chalk.dim(`Loaded config for project: ${config.projectName}`));
144
- console.log(
145
- chalk.dim(`Models: Analysis=${config.analysisModel}, Build=${config.buildModel}`),
146
- );
147
- } catch {
148
- console.log(chalk.yellow('Warning: Failed to load opencode.json'));
149
- }
150
- }
151
-
152
- if (!config) {
153
- console.log(chalk.yellow('No project configuration found.'));
154
- console.log(
155
- chalk.blue(
156
- `Run ${chalk.bold(`berget ${COMMAND_GROUPS.CODE} ${SUBCOMMANDS.CODE.INIT}`)} first.`,
157
- ),
158
- );
159
- return;
160
- }
161
-
162
- // Prepare opencode command
163
- const environment = { ...process.env };
164
- const opencodeArguments: string[] = [];
165
-
166
- // Read --stage and --local from root program options
167
- // (these flags are registered at program level, not subcommand level)
168
- const isStage = process.argv.includes('--stage');
169
- const isLocal = process.argv.includes('--local');
170
-
171
- if (isStage) {
172
- console.log(chalk.cyan('Using Berget stage environment'));
173
- environment.BERGET_API_URL = 'https://api.stage.berget.ai';
174
- environment.BERGET_INFERENCE_URL = 'https://api.stage.berget.ai/v1';
175
- } else if (isLocal) {
176
- console.log(chalk.cyan('Using local development environment'));
177
- environment.BERGET_API_URL = 'http://localhost:3000';
178
- environment.BERGET_INFERENCE_URL = 'http://localhost:3000/v1';
179
- }
180
-
181
- if (prompt) {
182
- opencodeArguments.push('run', prompt);
183
- }
184
-
185
- // Choose model based on analysis flag or override
186
- let selectedModel = options.model || config.buildModel;
187
- if (options.analysis && !options.model) {
188
- selectedModel = config.analysisModel;
189
- }
190
-
191
- if (selectedModel) {
192
- opencodeArguments.push('--model', selectedModel);
193
- }
194
-
195
- console.log(chalk.cyan('Starting OpenCode...'));
196
-
197
- // Spawn opencode process
198
- const opencode = spawn('opencode', opencodeArguments, {
199
- env: environment,
200
- stdio: 'inherit',
201
- });
202
-
203
- opencode.on('close', (code) => {
204
- if (code !== 0) {
205
- console.log(chalk.red(`OpenCode exited with code ${code}`));
206
- }
207
- });
208
-
209
- opencode.on('error', (error) => {
210
- console.error(chalk.red('Failed to start OpenCode:'));
211
- console.error(error.message);
212
- });
213
- } catch (error) {
214
- handleError('Failed to run OpenCode', error);
215
- }
216
- });
217
-
218
- code
219
- .command(SUBCOMMANDS.CODE.SERVE)
220
- .description('Start OpenCode web server')
221
- .option('-p, --port <port>', 'Port to run the server on (default: 3000)')
222
- .option('-h, --host <host>', 'Host to bind the server to (default: localhost)')
223
- .option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
224
- .action(async (options) => {
17
+ .description('Interactive setup for Berget AI coding tools')
18
+ .action(async () => {
225
19
  try {
226
- // Ensure opencode is installed
227
- if (!(await ensureOpencodeInstalled(options.yes))) {
228
- return;
229
- }
230
-
231
- console.log(chalk.cyan('🚀 Starting OpenCode web server...'));
232
-
233
- // Prepare opencode serve command
234
- const serveArguments: string[] = ['serve'];
235
-
236
- if (options.port) {
237
- serveArguments.push('--port', options.port);
238
- }
239
-
240
- if (options.host) {
241
- serveArguments.push('--host', options.host);
242
- }
243
-
244
- // Spawn opencode serve process
245
- const opencode = spawn('opencode', serveArguments, {
246
- stdio: 'inherit',
247
- });
248
-
249
- opencode.on('close', (code) => {
250
- if (code !== 0) {
251
- console.log(chalk.red(`OpenCode server exited with code ${code}`));
252
- }
253
- });
254
-
255
- opencode.on('error', (error) => {
256
- console.error(chalk.red('Failed to start OpenCode server:'));
257
- console.error(error.message);
258
- });
20
+ await runInitCommand();
259
21
  } catch (error) {
260
- handleError('Failed to start OpenCode server', error);
261
- }
262
- });
263
-
264
- code
265
- .command(SUBCOMMANDS.CODE.UPDATE)
266
- .description('Update OpenCode and agents to latest versions')
267
- .option('-f, --force', 'Force update even if already latest')
268
- .option('-y, --yes', 'Automatically answer yes to all prompts (for automation)')
269
- .action(async (options) => {
270
- try {
271
- console.log(chalk.cyan('🔄 Updating OpenCode configuration...'));
272
-
273
- // Ensure opencode is installed first
274
- if (!(await ensureOpencodeInstalled(options.yes))) {
275
- return;
276
- }
277
-
278
- const configPath = path.join(process.cwd(), 'opencode.json');
279
-
280
- // Check if project is initialized
281
- if (!fs.existsSync(configPath)) {
282
- console.log(chalk.red('❌ No OpenCode configuration found.'));
283
- console.log(
284
- chalk.blue(
285
- `Run ${chalk.bold(`berget ${COMMAND_GROUPS.CODE} ${SUBCOMMANDS.CODE.INIT}`)} first.`,
286
- ),
287
- );
288
- return;
289
- }
290
-
291
- // Read current configuration
292
- let currentConfig: any;
293
- try {
294
- const configContent = await readFile(configPath, 'utf8');
295
- currentConfig = JSON.parse(configContent);
296
- } catch (error) {
297
- console.error(chalk.red('Failed to read current opencode.json:'));
298
- handleError('Config read failed', error);
299
- return;
300
- }
301
-
302
- console.log(chalk.blue('📋 Current configuration:'));
303
- if (currentConfig.model) {
304
- console.log(chalk.dim(` Model: ${currentConfig.model}`));
305
- }
306
-
307
- const agentsDir = path.join(process.cwd(), '.opencode', 'agents');
308
- const templatesDir = getAgentTemplatesDir();
309
- const templateFiles = fs.readdirSync(templatesDir).filter((f) => f.endsWith('.md'));
310
-
311
- // Check if agent definitions need updating
312
- let agentsNeedUpdate = false;
313
-
314
- for (const file of templateFiles) {
315
- const source = path.join(templatesDir, file);
316
- const destination = path.join(agentsDir, file);
317
- if (!fs.existsSync(destination)) {
318
- agentsNeedUpdate = true;
319
- break;
320
- }
321
- const sourceContent = fs.readFileSync(source, 'utf8');
322
- const destinationContent = fs.readFileSync(destination, 'utf8');
323
- if (sourceContent !== destinationContent) {
324
- agentsNeedUpdate = true;
325
- break;
326
- }
327
- }
328
-
329
- // Check if opencode.json still has inline agent config (needs migration)
330
- const needsMigration = !!currentConfig.agent;
331
-
332
- if (!agentsNeedUpdate && !needsMigration && !options.force) {
333
- console.log(chalk.green('✅ Already using the latest configuration!'));
334
- return;
335
- }
336
-
337
- if (agentsNeedUpdate || needsMigration) {
338
- console.log(chalk.blue('\n🔄 Updates available:'));
339
-
340
- if (needsMigration) {
341
- console.log(chalk.cyan(' • Migrate agents from opencode.json to .opencode/agents/'));
342
- }
343
-
344
- if (agentsNeedUpdate) {
345
- console.log(chalk.cyan(' • Latest agent prompts and improvements'));
346
- }
347
- }
348
-
349
- if (options.force) {
350
- console.log(chalk.yellow('🔧 Force update requested'));
351
- }
352
-
353
- if (!options.yes) {
354
- console.log(
355
- chalk.blue('\nThis will update your agent definitions and OpenCode configuration.'),
356
- );
357
-
358
- const hasGitRepo = hasGit();
359
- if (hasGitRepo) {
360
- console.log(chalk.green('✓ Git repository detected - changes are tracked'));
361
- } else {
362
- console.log(chalk.yellow('⚠️ No .git repository detected - backup will be created'));
363
- }
364
- }
365
-
366
- if (await confirm('\nProceed with update? (Y/n): ', options.yes)) {
367
- try {
368
- let backupPath: null | string = null;
369
-
370
- if (!hasGit()) {
371
- backupPath = `${configPath}.backup.${Date.now()}`;
372
- await writeFile(backupPath, JSON.stringify(currentConfig, null, 2));
373
- console.log(
374
- chalk.green(`✓ Backed up current config to ${path.basename(backupPath)}`),
375
- );
376
- }
377
-
378
- // Remove inline agent section from opencode.json if present
379
- if (currentConfig.agent) {
380
- delete currentConfig.agent;
381
- await writeFile(configPath, JSON.stringify(currentConfig, null, 2));
382
- console.log(chalk.green('✓ Removed inline agent config from opencode.json'));
383
- }
384
-
385
- // Sync agent markdown files from templates
386
- fs.mkdirSync(agentsDir, { recursive: true });
387
- let updatedCount = 0;
388
- for (const file of templateFiles) {
389
- const source = path.join(templatesDir, file);
390
- const destination = path.join(agentsDir, file);
391
- const agentName = path.basename(file, '.md');
392
-
393
- if (
394
- !fs.existsSync(destination) ||
395
- fs.readFileSync(source, 'utf8') !== fs.readFileSync(destination, 'utf8')
396
- ) {
397
- fs.copyFileSync(source, destination);
398
- updatedCount++;
399
- console.log(chalk.cyan(` • Updated agent: ${agentName}`));
400
- }
401
- }
402
-
403
- if (updatedCount > 0) {
404
- console.log(chalk.green(`✓ Updated ${updatedCount} agent definition(s)`));
405
- }
406
-
407
- // Update AGENTS.md if it doesn't exist
408
- const agentsMdPath = path.join(process.cwd(), 'AGENTS.md');
409
- if (!fs.existsSync(agentsMdPath)) {
410
- const agentsMdContent = `# Berget Code Agents
411
-
412
- This document describes the specialized agents available in this project for use with OpenCode.
413
-
414
- Agents are defined as markdown files in \`.opencode/agents/\` with YAML frontmatter.
415
-
416
- ## Available Agents
417
-
418
- ### Primary Agents
419
-
420
- | Agent | Description | Temperature |
421
- |-------|-------------|-------------|
422
- | fullstack | Router/coordinator for full-stack development | 0.3 |
423
- | frontend | Scandinavian, type-safe UIs with React, Tailwind, Shadcn | 0.4 |
424
- | backend | Functional, modular Koa + TypeScript services | 0.3 |
425
- | devops | Declarative GitOps infra with FluxCD, Kustomize, Helm | 0.3 |
426
- | app | Expo + React Native apps; props-first, offline-aware | 0.4 |
427
-
428
- ### Subagents
429
-
430
- | Agent | Description | Temperature |
431
- |-------|-------------|-------------|
432
- | security | Security specialist for pentesting and OWASP compliance | 0.2 |
433
- | quality | QA specialist for testing, building, and PR management | 0.1 |
434
-
435
- ## Usage
436
-
437
- - **Tab** key to cycle between primary agents
438
- - **@mention** to invoke subagents (e.g. \`@security review this code\`)
439
- - \`/fullstack\`, \`/frontend\`, \`/backend\`, \`/devops\`, \`/app\` to switch agents
440
-
441
- ## Routing Rules
442
-
443
- The fullstack agent automatically routes tasks based on file patterns:
444
-
445
- - \`/apps/frontend\` or \`.tsx\` files → frontend
446
- - \`/apps/app\` or Expo/React Native → app
447
- - \`/infra\`, \`/k8s\`, FluxCD, Helm → devops
448
- - \`/services\`, Koa routers → backend
449
-
450
- ## Customization
451
-
452
- Edit the markdown files in \`.opencode/agents/\` to customize agent behavior.
453
- See https://opencode.ai/docs/agents/ for available options.
454
-
455
- ---
456
-
457
- *Updated by berget code update*
458
- `;
459
-
460
- await writeFile(agentsMdPath, agentsMdContent);
461
- console.log(chalk.green('✓ Created AGENTS.md documentation'));
462
- }
463
-
464
- console.log(chalk.green('\n✅ Update completed successfully!'));
465
- } catch (error) {
466
- console.error(chalk.red('Failed to update configuration:'));
467
- handleError('Update failed', error);
468
-
469
- try {
470
- await writeFile(configPath, JSON.stringify(currentConfig, null, 2));
471
- console.log(chalk.yellow('📁 Restored original configuration from backup'));
472
- } catch {
473
- console.error(chalk.red('Failed to restore backup:'));
474
- }
475
- }
476
- } else {
477
- console.log(chalk.yellow('Update cancelled.'));
478
- }
479
- } catch {
480
- console.error(chalk.red('Failed to update OpenCode configuration'));
481
- }
482
- });
483
- }
484
-
485
- /**
486
- * Check if opencode is installed
487
- */
488
- function checkOpencodeInstalled(): Promise<boolean> {
489
- return new Promise((resolve) => {
490
- const child = spawn('which', ['opencode'], {
491
- stdio: 'pipe',
492
- });
493
-
494
- child.on('close', (code) => {
495
- resolve(code === 0);
496
- });
497
-
498
- child.on('error', () => {
499
- resolve(false);
500
- });
501
- });
502
- }
503
-
504
- /**
505
- * Helper function to get user confirmation
506
- */
507
- async function confirm(question: string, autoYes = false): Promise<boolean> {
508
- if (autoYes) {
509
- return true;
510
- }
511
-
512
- return new Promise((resolve) => {
513
- const rl = readline.createInterface({
514
- input: process.stdin,
515
- output: process.stdout,
516
- });
517
-
518
- rl.question(question, (answer) => {
519
- rl.close();
520
- resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes' || answer === '');
521
- });
522
- });
523
- }
524
-
525
- /**
526
- * Ensure opencode is installed, offering to install if not
527
- */
528
- async function ensureOpencodeInstalled(autoYes = false): Promise<boolean> {
529
- let opencodeInstalled = await checkOpencodeInstalled();
530
- if (!opencodeInstalled) {
531
- if (!autoYes) {
532
- console.log(chalk.red('OpenCode is not installed.'));
533
- console.log(chalk.blue('OpenCode is required for the AI coding assistant.'));
534
- }
535
-
536
- if (await confirm('Would you like to install OpenCode automatically? (Y/n): ', autoYes)) {
537
- opencodeInstalled = await installOpencode();
538
- } else {
539
- if (!autoYes) {
540
- console.log(chalk.blue('\nInstallation cancelled.'));
541
- console.log(
542
- chalk.blue('To install manually: curl -fsSL https://opencode.ai/install | bash'),
543
- );
544
- console.log(chalk.blue('Or visit: https://opencode.ai/docs'));
22
+ handleError('Setup failed', error);
545
23
  }
546
- }
547
- }
548
-
549
- return opencodeInstalled;
550
- }
551
-
552
- /**
553
- * Get the path to the bundled agent templates directory
554
- */
555
- function getAgentTemplatesDir(): string {
556
- return path.resolve(__dirname, '../../templates/agents');
557
- }
558
-
559
- /**
560
- * Get project name from current directory or package.json
561
- */
562
- function getProjectName(): string {
563
- try {
564
- const packageJsonPath = path.join(process.cwd(), 'package.json');
565
- if (fs.existsSync(packageJsonPath)) {
566
- const packageJsonContent = fs.readFileSync(packageJsonPath, 'utf8');
567
- const packageJson = JSON.parse(packageJsonContent);
568
- return packageJson.name || path.basename(process.cwd());
569
- }
570
- } catch {
571
- // Ignore error and fallback to directory name
572
- }
573
- return path.basename(process.cwd());
574
- }
575
-
576
- /**
577
- * Check if current directory has git
578
- */
579
- function hasGit(): boolean {
580
- try {
581
- return fs.existsSync(path.join(process.cwd(), '.git'));
582
- } catch {
583
- return false;
584
- }
585
- }
586
-
587
- /**
588
- * Install opencode via npm
589
- */
590
- async function installOpencode(): Promise<boolean> {
591
- console.log(chalk.cyan('Installing OpenCode via npm...'));
592
-
593
- try {
594
- await new Promise<void>((resolve, reject) => {
595
- const install = spawn('npm', ['install', '-g', 'opencode-ai@1.3'], {
596
- stdio: 'inherit',
597
- });
598
-
599
- install.on('close', (code) => {
600
- if (code === 0) {
601
- console.log(chalk.green('✓ OpenCode installed successfully!'));
602
- resolve();
603
- } else {
604
- reject(new Error(`Installation failed with code ${code}`));
605
- }
606
- });
607
-
608
- install.on('error', reject);
609
24
  });
610
-
611
- // Verify installation
612
- const opencodeInstalled = await checkOpencodeInstalled();
613
- if (!opencodeInstalled) {
614
- console.log(chalk.yellow('Installation completed but opencode command not found.'));
615
- console.log(chalk.yellow('You may need to restart your terminal or check your PATH.'));
616
- return false;
617
- }
618
-
619
- return true;
620
- } catch (error) {
621
- console.error(chalk.red('Failed to install OpenCode:'));
622
- console.error(error instanceof Error ? error.message : String(error));
623
- console.log(chalk.blue('\nAlternative installation methods:'));
624
- console.log(chalk.blue(' curl -fsSL https://opencode.ai/install | sh'));
625
- console.log(chalk.blue(' Or visit: https://opencode.ai/docs'));
626
- return false;
627
- }
628
25
  }
@@ -76,10 +76,6 @@ export const SUBCOMMANDS = {
76
76
  // Code commands
77
77
  CODE: {
78
78
  INIT: 'init',
79
- RUN: 'run',
80
- SERVE: 'serve',
81
- SETUP: 'setup',
82
- UPDATE: 'update',
83
79
  },
84
80
 
85
81
  // Flux commands
@@ -164,14 +160,8 @@ export const COMMAND_DESCRIPTIONS = {
164
160
  [`${COMMAND_GROUPS.CLUSTERS} ${SUBCOMMANDS.CLUSTERS.GET_USAGE}`]:
165
161
  'Get resource usage for a cluster',
166
162
  [`${COMMAND_GROUPS.CLUSTERS} ${SUBCOMMANDS.CLUSTERS.LIST}`]: 'List all clusters',
167
- [`${COMMAND_GROUPS.CODE} ${SUBCOMMANDS.CODE.INIT}`]: 'Initialize project for AI coding assistant',
168
-
169
- [`${COMMAND_GROUPS.CODE} ${SUBCOMMANDS.CODE.RUN}`]: 'Run AI coding assistant',
170
- [`${COMMAND_GROUPS.CODE} ${SUBCOMMANDS.CODE.SERVE}`]: 'Start OpenCode web server',
171
- [`${COMMAND_GROUPS.CODE} ${SUBCOMMANDS.CODE.SETUP}`]:
163
+ [`${COMMAND_GROUPS.CODE} ${SUBCOMMANDS.CODE.INIT}`]:
172
164
  'Interactive setup for Berget AI coding tools',
173
- [`${COMMAND_GROUPS.CODE} ${SUBCOMMANDS.CODE.UPDATE}`]:
174
- 'Update OpenCode and agents to latest versions',
175
165
 
176
166
  [`${COMMAND_GROUPS.FLUX} ${SUBCOMMANDS.FLUX.BOOTSTRAP}`]: 'Bootstrap Flux CD',
177
167
  [`${COMMAND_GROUPS.FLUX} ${SUBCOMMANDS.FLUX.INSTALL}`]: 'Install Flux CD',
@@ -85,7 +85,7 @@ export class AuthService {
85
85
 
86
86
  console.log(chalk.cyan('\nNext steps:'));
87
87
  console.log(chalk.cyan(' • Create an API key: berget api-keys create'));
88
- console.log(chalk.cyan(' • Setup OpenCode: berget code init'));
88
+ console.log(chalk.cyan(' • Initialize OpenCode: berget code init'));
89
89
 
90
90
  return true;
91
91
  } catch (error) {