icoa-cli 1.7.0 → 1.7.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.
@@ -1,6 +1,8 @@
1
1
  import chalk from 'chalk';
2
2
  import { execSync } from 'node:child_process';
3
3
  import { platform } from 'node:os';
4
+ // Target Python version for full compatibility
5
+ const PYTHON_TARGET = '3.12';
4
6
  // ══════════════════════════════════════════════════════════
5
7
  // 27 Python Libraries — ALL LOCKED VERSIONS
6
8
  // Tested on Python 3.12.x (recommended)
@@ -41,101 +43,103 @@ const PYTHON_LIBS = [
41
43
  { name: 'pyserial', check: 'python3 -c "import serial"', install: 'pyserial==3.5', category: 'Security Tools' },
42
44
  ];
43
45
  // ══════════════════════════════════════════════════════════
44
- // 82 System Tools — with brew/apt install commands
46
+ // 82 System Tools — brew (Mac) / apt (Ubuntu) / choco (Win)
45
47
  // ══════════════════════════════════════════════════════════
48
+ const W = process.platform === 'win32';
49
+ const CMD = (unix, win) => W ? (win || `where ${unix}`) : `which ${unix}`;
46
50
  const SYSTEM_TOOLS = [
47
51
  // Editors & Terminal (5)
48
- { name: 'vim', check: 'which vim', brew: 'vim', apt: 'vim', category: 'Editors & Terminal' },
49
- { name: 'nano', check: 'which nano', brew: 'nano', apt: 'nano', category: 'Editors & Terminal' },
50
- { name: 'tmux', check: 'which tmux', brew: 'tmux', apt: 'tmux', category: 'Editors & Terminal' },
51
- { name: 'screen', check: 'which screen', brew: 'screen', apt: 'screen', category: 'Editors & Terminal' },
52
- { name: 'less', check: 'which less', category: 'Editors & Terminal' },
52
+ { name: 'vim', check: CMD('vim'), brew: 'vim', apt: 'vim', choco: 'vim', category: 'Editors & Terminal' },
53
+ { name: 'nano', check: CMD('nano'), brew: 'nano', apt: 'nano', choco: 'nano', category: 'Editors & Terminal' },
54
+ { name: 'tmux', check: CMD('tmux'), brew: 'tmux', apt: 'tmux', category: 'Editors & Terminal' },
55
+ { name: 'screen', check: CMD('screen'), brew: 'screen', apt: 'screen', category: 'Editors & Terminal' },
56
+ { name: 'less', check: CMD('less'), category: 'Editors & Terminal' },
53
57
  // Compilers & Build (8)
54
- { name: 'gcc', check: 'which gcc', brew: 'gcc', apt: 'gcc', category: 'Compilers & Build' },
55
- { name: 'g++', check: 'which g++', brew: 'gcc', apt: 'g++', category: 'Compilers & Build' },
56
- { name: 'make', check: 'which make', brew: 'make', apt: 'make', category: 'Compilers & Build' },
57
- { name: 'nasm', check: 'which nasm', brew: 'nasm', apt: 'nasm', category: 'Compilers & Build' },
58
- { name: 'cmake', check: 'which cmake', brew: 'cmake', apt: 'cmake', category: 'Compilers & Build' },
59
- { name: 'as', check: 'which as', category: 'Compilers & Build' },
60
- { name: 'ld', check: 'which ld', category: 'Compilers & Build' },
61
- { name: 'pkg-config', check: 'which pkg-config', brew: 'pkg-config', apt: 'pkg-config', category: 'Compilers & Build' },
58
+ { name: 'gcc', check: CMD('gcc'), brew: 'gcc', apt: 'gcc', choco: 'mingw', category: 'Compilers & Build' },
59
+ { name: 'g++', check: CMD('g++'), brew: 'gcc', apt: 'g++', choco: 'mingw', category: 'Compilers & Build' },
60
+ { name: 'make', check: CMD('make'), brew: 'make', apt: 'make', choco: 'make', category: 'Compilers & Build' },
61
+ { name: 'nasm', check: CMD('nasm'), brew: 'nasm', apt: 'nasm', choco: 'nasm', category: 'Compilers & Build' },
62
+ { name: 'cmake', check: CMD('cmake'), brew: 'cmake', apt: 'cmake', choco: 'cmake', category: 'Compilers & Build' },
63
+ { name: 'as', check: CMD('as'), category: 'Compilers & Build' },
64
+ { name: 'ld', check: CMD('ld'), category: 'Compilers & Build' },
65
+ { name: 'pkg-config', check: CMD('pkg-config'), brew: 'pkg-config', apt: 'pkg-config', category: 'Compilers & Build' },
62
66
  // Python (3)
63
- { name: 'python3', check: 'python3 --version', brew: 'python@3.12', apt: 'python3', category: 'Python Runtime' },
64
- { name: 'pip3', check: 'pip3 --version', category: 'Python Runtime' },
65
- { name: 'python3-venv', check: 'python3 -c "import venv"', apt: 'python3-venv', category: 'Python Runtime' },
67
+ { name: 'python3', check: W ? 'python --version' : 'python3 --version', brew: 'python@3.12', apt: 'python3', choco: 'python312', category: 'Python Runtime' },
68
+ { name: 'pip3', check: W ? 'pip --version' : 'pip3 --version', category: 'Python Runtime' },
69
+ { name: 'python3-venv', check: W ? 'python -c "import venv"' : 'python3 -c "import venv"', apt: 'python3-venv', category: 'Python Runtime' },
66
70
  // Networking (12)
67
- { name: 'curl', check: 'which curl', brew: 'curl', apt: 'curl', category: 'Networking' },
68
- { name: 'wget', check: 'which wget', brew: 'wget', apt: 'wget', category: 'Networking' },
69
- { name: 'nc', check: 'which nc', brew: 'netcat', apt: 'netcat-openbsd', category: 'Networking' },
70
- { name: 'socat', check: 'which socat', brew: 'socat', apt: 'socat', category: 'Networking' },
71
- { name: 'nmap', check: 'which nmap', brew: 'nmap', apt: 'nmap', category: 'Networking' },
72
- { name: 'ssh', check: 'which ssh', apt: 'openssh-client', category: 'Networking' },
73
- { name: 'dig', check: 'which dig', brew: 'bind', apt: 'dnsutils', category: 'Networking' },
74
- { name: 'whois', check: 'which whois', brew: 'whois', apt: 'whois', category: 'Networking' },
75
- { name: 'ping', check: 'which ping', apt: 'iputils-ping', category: 'Networking' },
76
- { name: 'traceroute', check: 'which traceroute', brew: 'traceroute', apt: 'traceroute', category: 'Networking' },
77
- { name: 'tcpdump', check: 'which tcpdump', brew: 'tcpdump', apt: 'tcpdump', category: 'Networking' },
78
- { name: 'tshark', check: 'which tshark', brew: 'wireshark', apt: 'tshark', category: 'Networking' },
71
+ { name: 'curl', check: CMD('curl'), brew: 'curl', apt: 'curl', choco: 'curl', category: 'Networking' },
72
+ { name: 'wget', check: CMD('wget'), brew: 'wget', apt: 'wget', choco: 'wget', category: 'Networking' },
73
+ { name: 'nc', check: CMD('nc', 'where ncat'), brew: 'netcat', apt: 'netcat-openbsd', choco: 'nmap', category: 'Networking' },
74
+ { name: 'socat', check: CMD('socat'), brew: 'socat', apt: 'socat', category: 'Networking' },
75
+ { name: 'nmap', check: CMD('nmap'), brew: 'nmap', apt: 'nmap', choco: 'nmap', category: 'Networking' },
76
+ { name: 'ssh', check: CMD('ssh'), apt: 'openssh-client', category: 'Networking' },
77
+ { name: 'dig', check: CMD('dig'), brew: 'bind', apt: 'dnsutils', category: 'Networking' },
78
+ { name: 'whois', check: CMD('whois'), brew: 'whois', apt: 'whois', choco: 'whois', category: 'Networking' },
79
+ { name: 'ping', check: CMD('ping'), apt: 'iputils-ping', category: 'Networking' },
80
+ { name: 'traceroute', check: CMD('traceroute', 'where tracert'), brew: 'traceroute', apt: 'traceroute', category: 'Networking' },
81
+ { name: 'tcpdump', check: CMD('tcpdump'), brew: 'tcpdump', apt: 'tcpdump', category: 'Networking' },
82
+ { name: 'tshark', check: CMD('tshark'), brew: 'wireshark', apt: 'tshark', choco: 'wireshark', category: 'Networking' },
79
83
  // Debuggers & Tracing (5)
80
- { name: 'gdb', check: 'which gdb', brew: 'gdb', apt: 'gdb', category: 'Debuggers' },
81
- { name: 'ltrace', check: 'which ltrace', apt: 'ltrace', category: 'Debuggers' },
82
- { name: 'strace', check: 'which strace', apt: 'strace', category: 'Debuggers' },
83
- { name: 'objdump', check: 'which objdump', category: 'Debuggers' },
84
- { name: 'readelf', check: 'which readelf', category: 'Debuggers' },
84
+ { name: 'gdb', check: CMD('gdb'), brew: 'gdb', apt: 'gdb', choco: 'mingw', category: 'Debuggers' },
85
+ { name: 'ltrace', check: CMD('ltrace'), apt: 'ltrace', category: 'Debuggers' },
86
+ { name: 'strace', check: CMD('strace'), apt: 'strace', category: 'Debuggers' },
87
+ { name: 'objdump', check: CMD('objdump'), category: 'Debuggers' },
88
+ { name: 'readelf', check: CMD('readelf'), category: 'Debuggers' },
85
89
  // Reverse Engineering (4)
86
- { name: 'radare2', check: 'which r2', brew: 'radare2', apt: 'radare2', category: 'Reverse Engineering' },
87
- { name: 'rabin2', check: 'which rabin2', category: 'Reverse Engineering' },
88
- { name: 'upx', check: 'which upx', brew: 'upx', apt: 'upx', category: 'Reverse Engineering' },
89
- { name: 'strings', check: 'which strings', category: 'Reverse Engineering' },
90
+ { name: 'radare2', check: CMD('r2'), brew: 'radare2', apt: 'radare2', choco: 'radare2', category: 'Reverse Engineering' },
91
+ { name: 'rabin2', check: CMD('rabin2'), category: 'Reverse Engineering' },
92
+ { name: 'upx', check: CMD('upx'), brew: 'upx', apt: 'upx', choco: 'upx', category: 'Reverse Engineering' },
93
+ { name: 'strings', check: CMD('strings'), category: 'Reverse Engineering' },
90
94
  // Forensics (7)
91
- { name: 'binwalk', check: 'which binwalk', brew: 'binwalk', apt: 'binwalk', category: 'Forensics' },
92
- { name: 'foremost', check: 'which foremost', apt: 'foremost', category: 'Forensics' },
93
- { name: 'exiftool', check: 'which exiftool', brew: 'exiftool', apt: 'exiftool', category: 'Forensics' },
94
- { name: 'steghide', check: 'which steghide', apt: 'steghide', category: 'Forensics' },
95
- { name: 'file', check: 'which file', category: 'Forensics' },
96
- { name: 'xxd', check: 'which xxd', brew: 'vim', apt: 'xxd', category: 'Forensics' },
97
- { name: 'pdftotext', check: 'which pdftotext', brew: 'poppler', apt: 'poppler-utils', category: 'Forensics' },
95
+ { name: 'binwalk', check: CMD('binwalk'), brew: 'binwalk', apt: 'binwalk', category: 'Forensics' },
96
+ { name: 'foremost', check: CMD('foremost'), apt: 'foremost', category: 'Forensics' },
97
+ { name: 'exiftool', check: CMD('exiftool'), brew: 'exiftool', apt: 'exiftool', choco: 'exiftool', category: 'Forensics' },
98
+ { name: 'steghide', check: CMD('steghide'), apt: 'steghide', category: 'Forensics' },
99
+ { name: 'file', check: CMD('file'), category: 'Forensics' },
100
+ { name: 'xxd', check: CMD('xxd'), brew: 'vim', apt: 'xxd', category: 'Forensics' },
101
+ { name: 'pdftotext', check: CMD('pdftotext'), brew: 'poppler', apt: 'poppler-utils', category: 'Forensics' },
98
102
  // Crypto & Password (4)
99
- { name: 'john', check: 'which john', brew: 'john', apt: 'john', category: 'Crypto & Password' },
100
- { name: 'hashcat', check: 'which hashcat', brew: 'hashcat', apt: 'hashcat', category: 'Crypto & Password' },
101
- { name: 'openssl', check: 'which openssl', category: 'Crypto & Password' },
102
- { name: 'gpg', check: 'which gpg', brew: 'gnupg', apt: 'gpg', category: 'Crypto & Password' },
103
+ { name: 'john', check: CMD('john'), brew: 'john', apt: 'john', choco: 'john', category: 'Crypto & Password' },
104
+ { name: 'hashcat', check: CMD('hashcat'), brew: 'hashcat', apt: 'hashcat', choco: 'hashcat', category: 'Crypto & Password' },
105
+ { name: 'openssl', check: CMD('openssl'), category: 'Crypto & Password' },
106
+ { name: 'gpg', check: CMD('gpg'), brew: 'gnupg', apt: 'gpg', choco: 'gnupg', category: 'Crypto & Password' },
103
107
  // Data Processing (8)
104
- { name: 'jq', check: 'which jq', brew: 'jq', apt: 'jq', category: 'Data Processing' },
105
- { name: 'sqlite3', check: 'which sqlite3', brew: 'sqlite', apt: 'sqlite3', category: 'Data Processing' },
106
- { name: 'base64', check: 'which base64', category: 'Data Processing' },
107
- { name: 'hexdump', check: 'which hexdump', category: 'Data Processing' },
108
- { name: 'od', check: 'which od', category: 'Data Processing' },
109
- { name: 'sort', check: 'which sort', category: 'Data Processing' },
110
- { name: 'uniq', check: 'which uniq', category: 'Data Processing' },
111
- { name: 'wc', check: 'which wc', category: 'Data Processing' },
108
+ { name: 'jq', check: CMD('jq'), brew: 'jq', apt: 'jq', choco: 'jq', category: 'Data Processing' },
109
+ { name: 'sqlite3', check: CMD('sqlite3'), brew: 'sqlite', apt: 'sqlite3', choco: 'sqlite', category: 'Data Processing' },
110
+ { name: 'base64', check: CMD('base64'), category: 'Data Processing' },
111
+ { name: 'hexdump', check: CMD('hexdump'), category: 'Data Processing' },
112
+ { name: 'od', check: CMD('od'), category: 'Data Processing' },
113
+ { name: 'sort', check: CMD('sort'), category: 'Data Processing' },
114
+ { name: 'uniq', check: CMD('uniq'), category: 'Data Processing' },
115
+ { name: 'wc', check: CMD('wc'), category: 'Data Processing' },
112
116
  // Archive (6)
113
- { name: 'unzip', check: 'which unzip', brew: 'unzip', apt: 'unzip', category: 'Archive' },
114
- { name: 'zip', check: 'which zip', brew: 'zip', apt: 'zip', category: 'Archive' },
115
- { name: 'tar', check: 'which tar', category: 'Archive' },
116
- { name: 'gzip', check: 'which gzip', category: 'Archive' },
117
- { name: 'bzip2', check: 'which bzip2', category: 'Archive' },
118
- { name: 'xz', check: 'which xz', brew: 'xz', apt: 'xz-utils', category: 'Archive' },
117
+ { name: 'unzip', check: CMD('unzip'), brew: 'unzip', apt: 'unzip', category: 'Archive' },
118
+ { name: 'zip', check: CMD('zip'), brew: 'zip', apt: 'zip', category: 'Archive' },
119
+ { name: 'tar', check: CMD('tar'), category: 'Archive' },
120
+ { name: 'gzip', check: CMD('gzip'), category: 'Archive' },
121
+ { name: 'bzip2', check: CMD('bzip2'), category: 'Archive' },
122
+ { name: 'xz', check: CMD('xz'), brew: 'xz', apt: 'xz-utils', category: 'Archive' },
119
123
  // Core Unix (16)
120
- { name: 'cat', check: 'which cat', category: 'Core Unix' },
121
- { name: 'grep', check: 'which grep', category: 'Core Unix' },
122
- { name: 'sed', check: 'which sed', category: 'Core Unix' },
123
- { name: 'awk', check: 'which awk', category: 'Core Unix' },
124
- { name: 'find', check: 'which find', category: 'Core Unix' },
125
- { name: 'head', check: 'which head', category: 'Core Unix' },
126
- { name: 'tail', check: 'which tail', category: 'Core Unix' },
127
- { name: 'diff', check: 'which diff', category: 'Core Unix' },
128
- { name: 'patch', check: 'which patch', category: 'Core Unix' },
129
- { name: 'chmod', check: 'which chmod', category: 'Core Unix' },
130
- { name: 'chown', check: 'which chown', category: 'Core Unix' },
131
- { name: 'ln', check: 'which ln', category: 'Core Unix' },
132
- { name: 'cp', check: 'which cp', category: 'Core Unix' },
133
- { name: 'mv', check: 'which mv', category: 'Core Unix' },
134
- { name: 'mkdir', check: 'which mkdir', category: 'Core Unix' },
135
- { name: 'rm', check: 'which rm', category: 'Core Unix' },
124
+ { name: 'cat', check: CMD('cat'), category: 'Core Unix' },
125
+ { name: 'grep', check: CMD('grep'), category: 'Core Unix' },
126
+ { name: 'sed', check: CMD('sed'), category: 'Core Unix' },
127
+ { name: 'awk', check: CMD('awk'), category: 'Core Unix' },
128
+ { name: 'find', check: CMD('find'), category: 'Core Unix' },
129
+ { name: 'head', check: CMD('head'), category: 'Core Unix' },
130
+ { name: 'tail', check: CMD('tail'), category: 'Core Unix' },
131
+ { name: 'diff', check: CMD('diff'), category: 'Core Unix' },
132
+ { name: 'patch', check: CMD('patch'), category: 'Core Unix' },
133
+ { name: 'chmod', check: CMD('chmod'), category: 'Core Unix' },
134
+ { name: 'chown', check: CMD('chown'), category: 'Core Unix' },
135
+ { name: 'ln', check: CMD('ln'), category: 'Core Unix' },
136
+ { name: 'cp', check: CMD('cp'), category: 'Core Unix' },
137
+ { name: 'mv', check: CMD('mv'), category: 'Core Unix' },
138
+ { name: 'mkdir', check: CMD('mkdir'), category: 'Core Unix' },
139
+ { name: 'rm', check: CMD('rm'), category: 'Core Unix' },
136
140
  // Version Control & Container (2)
137
- { name: 'git', check: 'which git', brew: 'git', apt: 'git', category: 'Git & Docker' },
138
- { name: 'docker', check: 'which docker', brew: '--cask docker', category: 'Git & Docker' },
141
+ { name: 'git', check: CMD('git'), brew: 'git', apt: 'git', choco: 'git', category: 'Git & Docker' },
142
+ { name: 'docker', check: CMD('docker'), brew: '--cask docker', choco: 'docker-desktop', category: 'Git & Docker' },
139
143
  ];
140
144
  function isInstalled(check) {
141
145
  try {
@@ -186,7 +190,11 @@ export function registerEnvCommand(program) {
186
190
  }
187
191
  function showStatus() {
188
192
  console.log();
193
+ const os = platform();
194
+ const osName = os === 'darwin' ? 'macOS' : os === 'linux' ? 'Linux' : 'Windows';
195
+ const pm = os === 'darwin' ? 'brew' : os === 'linux' ? 'apt' : 'choco';
189
196
  console.log(chalk.bold.white(' ICOA Competition Environment (109 commands)'));
197
+ console.log(chalk.gray(` Platform: ${osName} | Package Manager: ${pm} | Python: ${PYTHON_TARGET}.x`));
190
198
  console.log(chalk.gray(' ─────────────────────────────────────────────'));
191
199
  // Python version check
192
200
  const pyVer = getPythonMajorMinor();
@@ -255,42 +263,76 @@ async function installAll() {
255
263
  console.log();
256
264
  const os = platform();
257
265
  const pipFlag = os === 'darwin' || os === 'linux' ? '--break-system-packages' : '';
258
- // Python version warning
266
+ // Python version check — install 3.12 if needed
259
267
  const pyVer = getPythonMajorMinor();
260
- if (pyVer && pyVer !== '3.12') {
261
- console.log(chalk.yellow(` Note: Python ${pyVer} detected. Python 3.12.x recommended.`));
268
+ if (pyVer !== '3.12') {
269
+ console.log(chalk.yellow(` Python ${pyVer || 'not found'} installing Python 3.12...`));
270
+ try {
271
+ if (os === 'darwin') {
272
+ execSync('brew install python@3.12', { stdio: 'inherit' });
273
+ // Link python3.12 as default python3
274
+ try {
275
+ execSync('brew link --overwrite python@3.12', { stdio: 'ignore' });
276
+ }
277
+ catch { /* ok */ }
278
+ console.log(chalk.green(' ✓ Python 3.12 installed'));
279
+ console.log(chalk.gray(' Use: /opt/homebrew/opt/python@3.12/bin/python3.12'));
280
+ console.log(chalk.gray(' Or: brew link --overwrite python@3.12'));
281
+ }
282
+ else if (os === 'linux') {
283
+ execSync('sudo apt-get update && sudo apt-get install -y python3.12 python3.12-venv python3.12-dev', { stdio: 'inherit' });
284
+ console.log(chalk.green(' ✓ Python 3.12 installed'));
285
+ console.log(chalk.gray(' Set default: sudo update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 1'));
286
+ }
287
+ else {
288
+ execSync('choco install -y python312', { stdio: 'inherit' });
289
+ console.log(chalk.green(' ✓ Python 3.12 installed'));
290
+ }
291
+ }
292
+ catch {
293
+ console.log(chalk.red(' ✗ Failed to install Python 3.12'));
294
+ console.log(chalk.gray(` Manual install: ${os === 'darwin' ? 'brew install python@3.12' : os === 'linux' ? 'sudo apt install python3.12' : 'choco install python312'}`));
295
+ }
262
296
  console.log();
263
297
  }
264
- // Install system tools via brew (macOS) or apt (Linux)
265
- if (os === 'darwin' || os === 'linux') {
266
- const missingSystem = [];
267
- for (const tool of SYSTEM_TOOLS) {
268
- if (!isInstalled(tool.check)) {
269
- const pkg = os === 'darwin' ? tool.brew : tool.apt;
270
- if (pkg)
271
- missingSystem.push(tool);
272
- }
298
+ else {
299
+ console.log(chalk.green(` ✓ Python 3.12 (${getVersion('python3')})`));
300
+ console.log();
301
+ }
302
+ // Install system tools via brew (macOS) / apt (Linux) / choco (Windows)
303
+ const missingSystem = [];
304
+ for (const tool of SYSTEM_TOOLS) {
305
+ if (!isInstalled(tool.check)) {
306
+ const pkg = os === 'darwin' ? tool.brew : os === 'linux' ? tool.apt : tool.choco;
307
+ if (pkg)
308
+ missingSystem.push(tool);
273
309
  }
274
- if (missingSystem.length > 0) {
275
- const pm = os === 'darwin' ? 'brew' : 'sudo apt-get';
276
- console.log(chalk.bold.white(` System Tools (${missingSystem.length} missing)`));
277
- console.log(chalk.gray(' ─────────────────────────────────────────────'));
278
- for (const tool of missingSystem) {
279
- const pkg = os === 'darwin' ? tool.brew : tool.apt;
280
- process.stdout.write(chalk.gray(` ⏳ ${tool.name}...`));
281
- try {
282
- const cmd = os === 'darwin' ? `brew install ${pkg}` : `sudo apt-get install -y ${pkg}`;
283
- execSync(cmd, { stdio: 'ignore' });
284
- process.stdout.write('\r');
285
- console.log(chalk.green(` ${tool.name}`));
286
- }
287
- catch {
288
- process.stdout.write('\r');
289
- console.log(chalk.red(` ✗ ${tool.name}`) + chalk.gray(` (${pm} install ${os === 'darwin' ? tool.brew : tool.apt})`));
290
- }
310
+ }
311
+ if (missingSystem.length > 0) {
312
+ const pmName = os === 'darwin' ? 'brew' : os === 'linux' ? 'apt' : 'choco';
313
+ console.log(chalk.bold.white(` System Tools via ${pmName} (${missingSystem.length} missing)`));
314
+ console.log(chalk.gray(' ─────────────────────────────────────────────'));
315
+ for (const tool of missingSystem) {
316
+ const pkg = os === 'darwin' ? tool.brew : os === 'linux' ? tool.apt : tool.choco;
317
+ process.stdout.write(chalk.gray(` ⏳ ${tool.name}...`));
318
+ try {
319
+ let cmd;
320
+ if (os === 'darwin')
321
+ cmd = `brew install ${pkg}`;
322
+ else if (os === 'linux')
323
+ cmd = `sudo apt-get install -y ${pkg}`;
324
+ else
325
+ cmd = `choco install -y ${pkg}`;
326
+ execSync(cmd, { stdio: 'ignore' });
327
+ process.stdout.write('\r');
328
+ console.log(chalk.green(` ✓ ${tool.name}`));
329
+ }
330
+ catch {
331
+ process.stdout.write('\r');
332
+ console.log(chalk.red(` ✗ ${tool.name}`) + chalk.gray(` (${pmName} install ${pkg})`));
291
333
  }
292
- console.log();
293
334
  }
335
+ console.log();
294
336
  }
295
337
  // Install Python libraries
296
338
  let pipInstalled = 0;
package/dist/index.js CHANGED
@@ -36,7 +36,7 @@ ${LINE}
36
36
  ${chalk.white('Sydney, Australia')} ${chalk.gray('Jun 27 - Jul 2, 2026')}
37
37
  ${chalk.cyan.underline('https://icoa2026.au')}
38
38
 
39
- ${chalk.gray('CLI-Native Competition Terminal v1.7.0')}
39
+ ${chalk.gray('CLI-Native Competition Terminal v1.7.2')}
40
40
 
41
41
  ${LINE}
42
42
  `;
package/dist/repl.js CHANGED
@@ -6,7 +6,7 @@ import { isActivated, activateToken, isFreeCommand, isDeviceMatch, recordExit, r
6
6
  import { resetTerminalTheme } from './lib/theme.js';
7
7
  import { ensureSandbox, runInSandbox, isDockerAvailable } from './lib/sandbox.js';
8
8
  const INTERCEPT = '__REPL_NO_EXIT__';
9
- const VERSION = '1.7.0';
9
+ const VERSION = '1.7.2';
10
10
  export async function startRepl(program, resumeMode) {
11
11
  const config = getConfig();
12
12
  const connected = isConnected();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "icoa-cli",
3
- "version": "1.7.0",
3
+ "version": "1.7.2",
4
4
  "description": "ICOA CLI — The world's first CLI-native CTF competition terminal",
5
5
  "type": "module",
6
6
  "bin": {