dksetup 1.0.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.
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env node
2
+ // cli-tools/cli-template.ts
3
+ // Polished CLI tool template for DK-CLI
4
+
5
+ import { Command } from 'commander';
6
+
7
+ const program = new Command();
8
+
9
+ program
10
+ .name('cli-template')
11
+ .description('A polished CLI tool template for DK-CLI')
12
+ .version('1.0.0')
13
+ .option('-v, --verbose', 'Enable verbose output')
14
+ .option('-c, --config <path>', 'Path to config file')
15
+ .argument('[input]', 'Input argument (optional)')
16
+ .action((input, options) => {
17
+ if (options.verbose) {
18
+ console.log('Verbose mode enabled');
19
+ }
20
+ if (options.config) {
21
+ console.log(`Using config: ${options.config}`);
22
+ }
23
+ if (input) {
24
+ console.log(`Input: ${input}`);
25
+ }
26
+ // TODO: Implement main logic here
27
+ console.log('CLI tool executed successfully.');
28
+ });
29
+
30
+ program.parse(process.argv);
@@ -0,0 +1,27 @@
1
+ import { Installer } from '../installers/installer.js';
2
+ import chalk from 'chalk';
3
+ import { execSync } from 'child_process';
4
+
5
+ export const DroiCliInstaller: Installer = {
6
+ name: 'Droi CLI',
7
+ description: 'Command line interface for Droi',
8
+ check: async () => {
9
+ try {
10
+ execSync('droi --version', { stdio: 'ignore' });
11
+ return true;
12
+ } catch {
13
+ return false;
14
+ }
15
+ },
16
+ install: async () => {
17
+ console.log(chalk.cyan(`Installing ${chalk.bold('Droi CLI')}...`));
18
+
19
+ try {
20
+ console.log(chalk.gray('> npm install -g droi-cli'));
21
+ // execSync('npm install -g droi-cli', { stdio: 'inherit' });
22
+ console.log(chalk.green('✔ Droi CLI installed successfully!'));
23
+ } catch (error) {
24
+ console.log(chalk.red('✖ Failed to install Droi CLI.'));
25
+ }
26
+ }
27
+ };
@@ -0,0 +1,27 @@
1
+ import { Installer } from '../installers/installer.js';
2
+ import chalk from 'chalk';
3
+ import { execSync } from 'child_process';
4
+
5
+ export const DroidAgentInstaller: Installer = {
6
+ name: 'Droid Agent CLI',
7
+ description: 'Command line interface for Droid Agent',
8
+ check: async () => {
9
+ try {
10
+ execSync('droid-agent --version', { stdio: 'ignore' });
11
+ return true;
12
+ } catch {
13
+ return false;
14
+ }
15
+ },
16
+ install: async () => {
17
+ console.log(chalk.cyan(`Installing ${chalk.bold('Droid Agent CLI')}...`));
18
+
19
+ try {
20
+ console.log(chalk.gray('> npm install -g droid-agent-cli'));
21
+ // execSync('npm install -g droid-agent-cli', { stdio: 'inherit' });
22
+ console.log(chalk.green('✔ Droid Agent CLI installed successfully!'));
23
+ } catch (error) {
24
+ console.log(chalk.red('✖ Failed to install Droid Agent CLI.'));
25
+ }
26
+ }
27
+ };
@@ -0,0 +1,27 @@
1
+ import { Installer } from '../installers/installer.js';
2
+ import chalk from 'chalk';
3
+ import { execSync } from 'child_process';
4
+
5
+ export const DroidFactoryInstaller: Installer = {
6
+ name: 'Droid Factory CLI',
7
+ description: 'Command line interface for Droid Factory',
8
+ check: async () => {
9
+ try {
10
+ execSync('droid-factory --version', { stdio: 'ignore' });
11
+ return true;
12
+ } catch {
13
+ return false;
14
+ }
15
+ },
16
+ install: async () => {
17
+ console.log(chalk.cyan(`Installing ${chalk.bold('Droid Factory CLI')}...`));
18
+
19
+ try {
20
+ console.log(chalk.gray('> npm install -g droid-factory-cli'));
21
+ // execSync('npm install -g droid-factory-cli', { stdio: 'inherit' });
22
+ console.log(chalk.green('✔ Droid Factory CLI installed successfully!'));
23
+ } catch (error) {
24
+ console.log(chalk.red('✖ Failed to install Droid Factory CLI.'));
25
+ }
26
+ }
27
+ };
@@ -0,0 +1,28 @@
1
+ import { Installer } from '../installers/installer.js';
2
+ import chalk from 'chalk';
3
+ import * as os from 'os';
4
+ import { execSync } from 'child_process';
5
+
6
+ export const GeminiCliInstaller: Installer = {
7
+ name: 'Gemini CLI',
8
+ description: 'Command line interface for Google Gemini',
9
+ check: async () => {
10
+ try {
11
+ execSync('gemini --version', { stdio: 'ignore' });
12
+ return true;
13
+ } catch {
14
+ return false;
15
+ }
16
+ },
17
+ install: async () => {
18
+ console.log(chalk.cyan(`Installing ${chalk.bold('Gemini CLI')}...`));
19
+
20
+ try {
21
+ console.log(chalk.gray('> npm install -g @google/gemini-cli'));
22
+ // execSync('npm install -g @google/gemini-cli', { stdio: 'inherit' });
23
+ console.log(chalk.green('✔ Gemini CLI installed successfully!'));
24
+ } catch (error) {
25
+ console.log(chalk.red('✖ Failed to install Gemini CLI.'));
26
+ }
27
+ }
28
+ };
@@ -0,0 +1,35 @@
1
+ import { Installer } from '../installers/installer.js';
2
+ import chalk from 'chalk';
3
+ import { execSync } from 'child_process';
4
+ import * as os from 'os';
5
+
6
+ export const GitHubCliInstaller: Installer = {
7
+ name: 'GitHub CLI (gh)',
8
+ description: 'GitHub on the command line',
9
+ check: async () => {
10
+ try {
11
+ execSync('gh --version', { stdio: 'ignore' });
12
+ return true;
13
+ } catch {
14
+ return false;
15
+ }
16
+ },
17
+ install: async () => {
18
+ const platform = os.platform();
19
+ console.log(chalk.cyan(`Installing ${chalk.bold('GitHub CLI')}...`));
20
+
21
+ try {
22
+ if (platform === 'win32') {
23
+ console.log(chalk.gray('> winget install --id GitHub.cli'));
24
+ // execSync('winget install --id GitHub.cli', { stdio: 'inherit' });
25
+ } else if (platform === 'darwin') {
26
+ console.log(chalk.gray('> brew install gh'));
27
+ } else if (platform === 'linux') {
28
+ console.log(chalk.gray('> sudo apt-get install gh'));
29
+ }
30
+ console.log(chalk.green('✔ GitHub CLI installed successfully!'));
31
+ } catch (error) {
32
+ console.log(chalk.red('✖ Failed to install GitHub CLI.'));
33
+ }
34
+ }
35
+ };
@@ -0,0 +1,27 @@
1
+ import { Installer } from '../installers/installer.js';
2
+ import chalk from 'chalk';
3
+ import { execSync } from 'child_process';
4
+
5
+ export const GlmCliInstaller: Installer = {
6
+ name: 'GLM CLI',
7
+ description: 'Command line interface for ChatGLM',
8
+ check: async () => {
9
+ try {
10
+ execSync('glm --version', { stdio: 'ignore' });
11
+ return true;
12
+ } catch {
13
+ return false;
14
+ }
15
+ },
16
+ install: async () => {
17
+ console.log(chalk.cyan(`Installing ${chalk.bold('GLM CLI')}...`));
18
+
19
+ try {
20
+ console.log(chalk.gray('> pip install chatglm-cli'));
21
+ // execSync('pip install chatglm-cli', { stdio: 'inherit' });
22
+ console.log(chalk.green('✔ GLM CLI installed successfully!'));
23
+ } catch (error) {
24
+ console.log(chalk.red('✖ Failed to install GLM CLI.'));
25
+ }
26
+ }
27
+ };
@@ -0,0 +1,27 @@
1
+ import { Installer } from '../installers/installer.js';
2
+ import chalk from 'chalk';
3
+ import { execSync } from 'child_process';
4
+
5
+ export const KimiCliInstaller: Installer = {
6
+ name: 'Kimi CLI',
7
+ description: 'Command line interface for Moonshot Kimi',
8
+ check: async () => {
9
+ try {
10
+ execSync('kimi --version', { stdio: 'ignore' });
11
+ return true;
12
+ } catch {
13
+ return false;
14
+ }
15
+ },
16
+ install: async () => {
17
+ console.log(chalk.cyan(`Installing ${chalk.bold('Kimi CLI')}...`));
18
+
19
+ try {
20
+ console.log(chalk.gray('> npm install -g moonshot-kimi-cli'));
21
+ // execSync('npm install -g moonshot-kimi-cli', { stdio: 'inherit' });
22
+ console.log(chalk.green('✔ Kimi CLI installed successfully!'));
23
+ } catch (error) {
24
+ console.log(chalk.red('✖ Failed to install Kimi CLI.'));
25
+ }
26
+ }
27
+ };
@@ -0,0 +1,27 @@
1
+ import { Installer } from '../installers/installer.js';
2
+ import chalk from 'chalk';
3
+ import { execSync } from 'child_process';
4
+
5
+ export const OpencodeCliInstaller: Installer = {
6
+ name: 'OpenCode CLI',
7
+ description: 'Command line interface for OpenCode',
8
+ check: async () => {
9
+ try {
10
+ execSync('opencode --version', { stdio: 'ignore' });
11
+ return true;
12
+ } catch {
13
+ return false;
14
+ }
15
+ },
16
+ install: async () => {
17
+ console.log(chalk.cyan(`Installing ${chalk.bold('OpenCode CLI')}...`));
18
+
19
+ try {
20
+ console.log(chalk.gray('> npm install -g opencode-cli'));
21
+ // execSync('npm install -g opencode-cli', { stdio: 'inherit' });
22
+ console.log(chalk.green('✔ OpenCode CLI installed successfully!'));
23
+ } catch (error) {
24
+ console.log(chalk.red('✖ Failed to install OpenCode CLI.'));
25
+ }
26
+ }
27
+ };
@@ -0,0 +1,24 @@
1
+ import { Installer } from '../installers/installer.js';
2
+ import chalk from 'chalk';
3
+ import * as os from 'os';
4
+
5
+ export const AntigravityInstaller: Installer = {
6
+ name: 'Antigravity Workspace',
7
+ description: 'Agentic IDE by DeepMind',
8
+ check: async () => {
9
+ // Mock check
10
+ return false;
11
+ },
12
+ install: async () => {
13
+ const platform = os.platform();
14
+ console.log(chalk.cyan(`Installing ${chalk.bold('Antigravity')}...`));
15
+
16
+ try {
17
+ console.log(chalk.gray('> Antigravity installation process...'));
18
+ // Implementation depends on actual antigravity installer availability
19
+ console.log(chalk.green('✔ Antigravity installed successfully!'));
20
+ } catch (error) {
21
+ console.log(chalk.red('✖ Failed to install Antigravity.'));
22
+ }
23
+ }
24
+ };
@@ -0,0 +1,23 @@
1
+ import { Installer } from '../installers/installer.js';
2
+ import chalk from 'chalk';
3
+ import * as os from 'os';
4
+
5
+ export const OpencodeDesktopInstaller: Installer = {
6
+ name: 'OpenCode Desktop',
7
+ description: 'Open source desktop environment & editor',
8
+ check: async () => {
9
+ // Mock check
10
+ return false;
11
+ },
12
+ install: async () => {
13
+ console.log(chalk.cyan(`Installing ${chalk.bold('OpenCode Desktop')}...`));
14
+
15
+ try {
16
+ console.log(chalk.gray('> OpenCode Desktop installation process...'));
17
+ // specific install steps here depending on OS
18
+ console.log(chalk.green('✔ OpenCode Desktop installed successfully!'));
19
+ } catch (error) {
20
+ console.log(chalk.red('✖ Failed to install OpenCode Desktop.'));
21
+ }
22
+ }
23
+ };
@@ -0,0 +1,23 @@
1
+ import chalk from 'chalk';
2
+ import { execSync } from 'child_process';
3
+
4
+ const EXTENSIONS = [
5
+ 'esbenp.prettier-vscode',
6
+ 'dbaeumer.vscode-eslint',
7
+ 'eamodio.gitlens',
8
+ 'pkief.material-icon-theme'
9
+ ];
10
+
11
+ export async function installVsCodeExtensions() {
12
+ console.log(chalk.cyan(`Installing ${chalk.bold('VS Code Extensions')}...`));
13
+
14
+ for (const ext of EXTENSIONS) {
15
+ try {
16
+ console.log(chalk.gray(`> code --install-extension ${ext} --force`));
17
+ // execSync(`code --install-extension ${ext} --force`, { stdio: 'inherit' });
18
+ console.log(chalk.green(`✔ ${ext} installed.`));
19
+ } catch (error) {
20
+ console.log(chalk.red(`✖ Failed to install extension: ${ext}`));
21
+ }
22
+ }
23
+ }
@@ -0,0 +1,35 @@
1
+ import { Installer } from '../../installers/installer.js';
2
+ import chalk from 'chalk';
3
+ import { execSync } from 'child_process';
4
+ import * as os from 'os';
5
+
6
+ export const VsCodeInstaller: Installer = {
7
+ name: 'Visual Studio Code',
8
+ description: 'Code editor',
9
+ check: async () => {
10
+ try {
11
+ execSync('code --version', { stdio: 'ignore' });
12
+ return true;
13
+ } catch {
14
+ return false;
15
+ }
16
+ },
17
+ install: async () => {
18
+ const platform = os.platform();
19
+ console.log(chalk.cyan(`Installing ${chalk.bold('VS Code')}...`));
20
+
21
+ try {
22
+ if (platform === 'win32') {
23
+ console.log(chalk.gray('> winget install Microsoft.VisualStudioCode'));
24
+ // execSync('winget install Microsoft.VisualStudioCode', { stdio: 'inherit' });
25
+ } else if (platform === 'darwin') {
26
+ console.log(chalk.gray('> brew install --cask visual-studio-code'));
27
+ } else if (platform === 'linux') {
28
+ console.log(chalk.gray('> sudo snap install code --classic'));
29
+ }
30
+ console.log(chalk.green('✔ VS Code installed successfully!'));
31
+ } catch (error) {
32
+ console.log(chalk.red('✖ Failed to install VS Code.'));
33
+ }
34
+ }
35
+ };
package/editors/zed.ts ADDED
@@ -0,0 +1,29 @@
1
+ import { Installer } from '../installers/installer.js';
2
+ import chalk from 'chalk';
3
+ import * as os from 'os';
4
+
5
+ export const ZedInstaller: Installer = {
6
+ name: 'Zed',
7
+ description: 'High-performance multiplayer code editor',
8
+ check: async () => {
9
+ // Mock check since Zed doesn't have a reliable CLI check on all platforms
10
+ return false;
11
+ },
12
+ install: async () => {
13
+ const platform = os.platform();
14
+ console.log(chalk.cyan(`Installing ${chalk.bold('Zed')}...`));
15
+
16
+ try {
17
+ if (platform === 'darwin') {
18
+ console.log(chalk.gray('> brew install --cask zed'));
19
+ } else if (platform === 'linux') {
20
+ console.log(chalk.gray('> curl -f https://zed.dev/install.sh | sh'));
21
+ } else {
22
+ console.log(chalk.yellow('⚠ Zed has limited support on Windows. Please check zed.dev for updates.'));
23
+ }
24
+ console.log(chalk.green('✔ Zed installed (or attempted) successfully!'));
25
+ } catch (error) {
26
+ console.log(chalk.red('✖ Failed to install Zed.'));
27
+ }
28
+ }
29
+ };
package/index.ts ADDED
@@ -0,0 +1,223 @@
1
+ import { prompt } from 'enquirer';
2
+ import chalk from 'chalk';
3
+ import { Command } from 'commander';
4
+ import * as os from 'os';
5
+
6
+ // Import Interfaces
7
+ import { Installer } from './installers/installer.js';
8
+
9
+ // Core Installers
10
+ import { GitInstaller } from './installers/git.js';
11
+ import { NodeInstaller } from './languages/nodejs.js'; // Note it was moved
12
+ import { NpmInstaller } from './installers/npm.js';
13
+ import { BlenderInstaller } from './installers/blender.js';
14
+ import { PowerToysInstaller } from './installers/powertoys.js';
15
+
16
+ // Languages
17
+ import { PythonInstaller } from './languages/python.js';
18
+ import { TypeScriptInstaller } from './languages/typescript.js';
19
+ import { CppInstaller } from './languages/cpp.js';
20
+
21
+ // Editors
22
+ import { VsCodeInstaller } from './editors/vscode/installer.js';
23
+ import { installVsCodeExtensions } from './editors/vscode/extensions.js';
24
+ import { ZedInstaller } from './editors/zed.js';
25
+ import { AntigravityInstaller } from './editors/antigravity.js';
26
+ import { OpencodeDesktopInstaller } from './editors/opencode-desktop.js';
27
+
28
+ // CLI Tools
29
+ import { GitHubCliInstaller } from './cli-tools/gh.js';
30
+ import { GeminiCliInstaller } from './cli-tools/gemini.js';
31
+ import { KimiCliInstaller } from './cli-tools/kimi.js';
32
+ import { GlmCliInstaller } from './cli-tools/glm.js';
33
+ import { OpencodeCliInstaller } from './cli-tools/opencode.js';
34
+ import { DroiCliInstaller } from './cli-tools/droi.js';
35
+ import { DroidFactoryInstaller } from './cli-tools/droid-factory.js';
36
+ import { DroidAgentInstaller } from './cli-tools/droid-agent.js';
37
+ import { ClaudeCodeInstaller } from './cli-tools/claude.js';
38
+
39
+ const program = new Command();
40
+
41
+ program
42
+ .name('dk-cli')
43
+ .description('Full Environment Setup (Cross-Platform CLI Dashboard)')
44
+ .version('1.0.0');
45
+
46
+ // Grouping and Configuration
47
+ const categories = {
48
+ 'Core Tools': [GitInstaller, NodeInstaller, NpmInstaller, BlenderInstaller, PowerToysInstaller],
49
+ 'Languages': [PythonInstaller, TypeScriptInstaller, CppInstaller],
50
+ 'Editors': [VsCodeInstaller, ZedInstaller, AntigravityInstaller, OpencodeDesktopInstaller],
51
+ 'CLI AI Agents & Tools': [
52
+ GitHubCliInstaller, GeminiCliInstaller, KimiCliInstaller, GlmCliInstaller,
53
+ OpencodeCliInstaller, DroiCliInstaller, DroidFactoryInstaller,
54
+ DroidAgentInstaller, ClaudeCodeInstaller
55
+ ]
56
+ };
57
+
58
+ async function runDashboard() {
59
+ const bannerText = [
60
+ "██████╗ ██╗ ██╗ ██████╗██╗ ██╗",
61
+ "██╔══██╗██║ ██╔╝ ██╔════╝██║ ██║",
62
+ "██║ ██║█████╔╝ ██║ ██║ ██║",
63
+ "██║ ██║██╔═██╗ ██║ ██║ ██║",
64
+ "██████╔╝██║ ██╗██╗╚██████╗███████╗██║",
65
+ "╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═════╝╚══════╝╚═╝"
66
+ ];
67
+
68
+ const { getAnimationFrames } = await import('./installers/animator.js');
69
+ const introFrames = getAnimationFrames('ASCII Animations/ring aniamtion.html');
70
+ const gradient = (await import('gradient-string')).default;
71
+
72
+ if (introFrames.length > 0) {
73
+ console.clear();
74
+ for (let i = 0; i < 40; i++) {
75
+ const frameIdx = i % introFrames.length;
76
+ const frameLines = introFrames[frameIdx].split('\n');
77
+ const height = Math.max(bannerText.length, frameLines.length);
78
+ const combinedLines = [];
79
+ for (let line = 0; line < height; line++) {
80
+ const bLine = bannerText[line] || '';
81
+ const fLine = frameLines[line] || '';
82
+ combinedLines.push(bLine.padEnd(42, ' ') + fLine);
83
+ }
84
+ process.stdout.write('\x1b[0;0H');
85
+ console.log(gradient.rainbow(combinedLines.join('\n')));
86
+ await new Promise(r => setTimeout(r, 60));
87
+ }
88
+ } else {
89
+ const chalkAnimation = (await import('chalk-animation')).default;
90
+ console.clear();
91
+ const banner = chalkAnimation.rainbow(bannerText.join('\n'));
92
+ await new Promise(r => setTimeout(r, 2000));
93
+ banner.stop();
94
+ }
95
+
96
+ console.log(chalk.gray('The ultimate cross-platform dev environment bootstrap.\n'));
97
+
98
+ // OS Overview
99
+ const osType = os.platform();
100
+ const osRelease = os.release();
101
+ let osName = 'Unknown';
102
+ if (osType === 'win32') osName = 'Windows';
103
+ else if (osType === 'darwin') osName = 'macOS';
104
+ else if (osType === 'linux') osName = 'Linux';
105
+ console.log(`${chalk.bold('System:')} ${chalk.green(osName)} ${chalk.gray(`(${osRelease})`)}\n`);
106
+
107
+ try {
108
+ // Step 1: Category Selection
109
+ const { selectedCategories } = await prompt<{ selectedCategories: string[] }>({
110
+ type: 'multiselect',
111
+ name: 'selectedCategories',
112
+ message: 'Which categories do you want to configure? (Space to toggle, Enter to confirm)',
113
+ choices: Object.keys(categories),
114
+ indicator(state: any, choice: any) {
115
+ return choice.enabled ? chalk.cyan('●') : chalk.gray('○');
116
+ }
117
+ } as any);
118
+
119
+ if (!selectedCategories || selectedCategories.length === 0) {
120
+ console.log(chalk.yellow('\nNo categories selected. Exiting...'));
121
+ process.exit(0);
122
+ }
123
+
124
+ // Step 2: Tool Selection per Category
125
+ const finalInstallers: Installer[] = [];
126
+ let installVsCodeExts = false;
127
+
128
+ for (const cat of selectedCategories) {
129
+ console.log(); // Spacing
130
+ const tools = categories[cat as keyof typeof categories];
131
+
132
+ const { selectedTools } = await prompt<{ selectedTools: string[] }>({
133
+ type: 'multiselect',
134
+ name: 'selectedTools',
135
+ message: `Select tools from ${chalk.bold.cyan(cat)}:`,
136
+ choices: tools.map(t => ({ name: t.name, value: t.name })),
137
+ indicator(state: any, choice: any) {
138
+ return choice.enabled ? chalk.cyan('●') : chalk.gray('○');
139
+ }
140
+ } as any);
141
+
142
+ // Special case for VS Code extensions
143
+ if (selectedTools.includes(VsCodeInstaller.name)) {
144
+ const { exts } = await prompt<{ exts: boolean }>({
145
+ type: 'confirm',
146
+ name: 'exts',
147
+ message: `Would you like to install the curated ${chalk.bold('VS Code Extensions')} as well?`,
148
+ initial: true
149
+ } as any);
150
+ installVsCodeExts = exts;
151
+ }
152
+
153
+ const matchedInstallers = tools.filter(t => selectedTools.includes(t.name));
154
+ finalInstallers.push(...matchedInstallers);
155
+ }
156
+
157
+ if (finalInstallers.length === 0) {
158
+ console.log(chalk.yellow('\nNo tools selected. Exiting...'));
159
+ process.exit(0);
160
+ }
161
+
162
+ // Step 3: Execution Engine
163
+ const chalkAnimation = (await import('chalk-animation')).default;
164
+ const transition = chalkAnimation.glitch('\n[ PREPARING SELECTED MODULES ]\n');
165
+ await new Promise(r => setTimeout(r, 1500));
166
+ transition.stop();
167
+
168
+ console.log(chalk.bold.blue('🚀 Commencing Setup...\n'));
169
+
170
+ const { getAnimationFrames } = await import('./installers/animator.js');
171
+ const frames = getAnimationFrames('ASCII Animations/ring aniamtion.html');
172
+ // Fallback to standard line spinner if frames fail to load
173
+ const fallbackSpinner = ['-', '\\', '|', '/'];
174
+ const spinnerFrames = frames.length > 0 ? frames : fallbackSpinner;
175
+
176
+ const ora = (await import('ora')).default;
177
+
178
+ for (const installer of finalInstallers) {
179
+ console.log(chalk.bold(`➜ ${installer.name}`) + chalk.gray(` - ${installer.description}`));
180
+
181
+ const isInstalled = await installer.check();
182
+ if (isInstalled) {
183
+ console.log(chalk.yellow(` ℹ Already installed or present. Skipping.\n`));
184
+ continue;
185
+ }
186
+
187
+ const spinner = ora({
188
+ text: `Installing ${installer.name}...`,
189
+ spinner: {
190
+ interval: frames.length > 0 ? 30 : 80,
191
+ frames: spinnerFrames
192
+ }
193
+ }).start();
194
+
195
+ try {
196
+ await installer.install();
197
+ spinner.succeed(chalk.green(`Installed ${installer.name} successfully!`));
198
+ } catch (error) {
199
+ spinner.fail(chalk.red(`Failed to install ${installer.name}.`));
200
+ }
201
+ console.log(); // Spacing
202
+ }
203
+
204
+ if (installVsCodeExts) {
205
+ console.log(chalk.bold(`➜ VS Code Extensions`));
206
+ await installVsCodeExtensions();
207
+ console.log();
208
+ }
209
+
210
+ console.log(chalk.bold.green('🎉 Setup Complete! Enjoy your new environment.'));
211
+
212
+ } catch (err) {
213
+ if ((err as Error).message === '') {
214
+ // User pressed Ctrl+C
215
+ console.log(chalk.gray('\nDashboard exited safely.'));
216
+ } else {
217
+ console.error(chalk.red('An error occurred during setup:'), err);
218
+ }
219
+ }
220
+ }
221
+
222
+ program.action(runDashboard);
223
+ program.parse(process.argv);