@ornexus/neocortex 4.0.1

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.

Potentially problematic release.


This version of @ornexus/neocortex might be problematic. Click here for more details.

Files changed (121) hide show
  1. package/LICENSE +56 -0
  2. package/README.md +32 -0
  3. package/install.js +486 -0
  4. package/install.ps1 +1790 -0
  5. package/install.sh +1587 -0
  6. package/package.json +104 -0
  7. package/packages/client/dist/adapters/adapter-registry.d.ts +61 -0
  8. package/packages/client/dist/adapters/adapter-registry.js +106 -0
  9. package/packages/client/dist/adapters/antigravity-adapter.d.ts +18 -0
  10. package/packages/client/dist/adapters/antigravity-adapter.js +77 -0
  11. package/packages/client/dist/adapters/claude-code-adapter.d.ts +19 -0
  12. package/packages/client/dist/adapters/claude-code-adapter.js +79 -0
  13. package/packages/client/dist/adapters/codex-adapter.d.ts +19 -0
  14. package/packages/client/dist/adapters/codex-adapter.js +80 -0
  15. package/packages/client/dist/adapters/cursor-adapter.d.ts +19 -0
  16. package/packages/client/dist/adapters/cursor-adapter.js +115 -0
  17. package/packages/client/dist/adapters/gemini-adapter.d.ts +18 -0
  18. package/packages/client/dist/adapters/gemini-adapter.js +71 -0
  19. package/packages/client/dist/adapters/index.d.ts +19 -0
  20. package/packages/client/dist/adapters/index.js +21 -0
  21. package/packages/client/dist/adapters/platform-detector.d.ts +46 -0
  22. package/packages/client/dist/adapters/platform-detector.js +106 -0
  23. package/packages/client/dist/adapters/target-adapter.d.ts +70 -0
  24. package/packages/client/dist/adapters/target-adapter.js +12 -0
  25. package/packages/client/dist/adapters/vscode-adapter.d.ts +19 -0
  26. package/packages/client/dist/adapters/vscode-adapter.js +72 -0
  27. package/packages/client/dist/agent/refresh-stubs.d.ts +65 -0
  28. package/packages/client/dist/agent/refresh-stubs.js +234 -0
  29. package/packages/client/dist/agent/update-agent-yaml.d.ts +26 -0
  30. package/packages/client/dist/agent/update-agent-yaml.js +102 -0
  31. package/packages/client/dist/agent/update-description.d.ts +45 -0
  32. package/packages/client/dist/agent/update-description.js +251 -0
  33. package/packages/client/dist/cache/crypto-utils.d.ts +30 -0
  34. package/packages/client/dist/cache/crypto-utils.js +76 -0
  35. package/packages/client/dist/cache/encrypted-cache.d.ts +30 -0
  36. package/packages/client/dist/cache/encrypted-cache.js +94 -0
  37. package/packages/client/dist/cache/in-memory-asset-cache.d.ts +59 -0
  38. package/packages/client/dist/cache/in-memory-asset-cache.js +70 -0
  39. package/packages/client/dist/cache/index.d.ts +13 -0
  40. package/packages/client/dist/cache/index.js +13 -0
  41. package/packages/client/dist/cli.d.ts +14 -0
  42. package/packages/client/dist/cli.js +194 -0
  43. package/packages/client/dist/commands/activate.d.ts +55 -0
  44. package/packages/client/dist/commands/activate.js +390 -0
  45. package/packages/client/dist/commands/cache-status.d.ts +39 -0
  46. package/packages/client/dist/commands/cache-status.js +112 -0
  47. package/packages/client/dist/commands/invoke.d.ts +70 -0
  48. package/packages/client/dist/commands/invoke.js +490 -0
  49. package/packages/client/dist/config/resolver-selection.d.ts +40 -0
  50. package/packages/client/dist/config/resolver-selection.js +278 -0
  51. package/packages/client/dist/config/secure-config.d.ts +78 -0
  52. package/packages/client/dist/config/secure-config.js +269 -0
  53. package/packages/client/dist/constants.d.ts +25 -0
  54. package/packages/client/dist/constants.js +25 -0
  55. package/packages/client/dist/context/context-collector.d.ts +28 -0
  56. package/packages/client/dist/context/context-collector.js +222 -0
  57. package/packages/client/dist/context/context-sanitizer.d.ts +28 -0
  58. package/packages/client/dist/context/context-sanitizer.js +145 -0
  59. package/packages/client/dist/index.d.ts +55 -0
  60. package/packages/client/dist/index.js +38 -0
  61. package/packages/client/dist/license/index.d.ts +5 -0
  62. package/packages/client/dist/license/index.js +5 -0
  63. package/packages/client/dist/license/license-client.d.ts +79 -0
  64. package/packages/client/dist/license/license-client.js +257 -0
  65. package/packages/client/dist/machine/fingerprint.d.ts +34 -0
  66. package/packages/client/dist/machine/fingerprint.js +160 -0
  67. package/packages/client/dist/machine/index.d.ts +5 -0
  68. package/packages/client/dist/machine/index.js +5 -0
  69. package/packages/client/dist/resilience/circuit-breaker.d.ts +70 -0
  70. package/packages/client/dist/resilience/circuit-breaker.js +170 -0
  71. package/packages/client/dist/resilience/degradation-manager.d.ts +67 -0
  72. package/packages/client/dist/resilience/degradation-manager.js +164 -0
  73. package/packages/client/dist/resilience/freshness-indicator.d.ts +59 -0
  74. package/packages/client/dist/resilience/freshness-indicator.js +100 -0
  75. package/packages/client/dist/resilience/index.d.ts +8 -0
  76. package/packages/client/dist/resilience/index.js +8 -0
  77. package/packages/client/dist/resilience/recovery-detector.d.ts +59 -0
  78. package/packages/client/dist/resilience/recovery-detector.js +74 -0
  79. package/packages/client/dist/resolvers/asset-resolver.d.ts +79 -0
  80. package/packages/client/dist/resolvers/asset-resolver.js +13 -0
  81. package/packages/client/dist/resolvers/local-resolver.d.ts +26 -0
  82. package/packages/client/dist/resolvers/local-resolver.js +218 -0
  83. package/packages/client/dist/resolvers/remote-resolver.d.ts +91 -0
  84. package/packages/client/dist/resolvers/remote-resolver.js +282 -0
  85. package/packages/client/dist/telemetry/index.d.ts +5 -0
  86. package/packages/client/dist/telemetry/index.js +5 -0
  87. package/packages/client/dist/telemetry/offline-queue.d.ts +57 -0
  88. package/packages/client/dist/telemetry/offline-queue.js +131 -0
  89. package/packages/client/dist/tier/index.d.ts +5 -0
  90. package/packages/client/dist/tier/index.js +5 -0
  91. package/packages/client/dist/tier/tier-aware-client.d.ts +97 -0
  92. package/packages/client/dist/tier/tier-aware-client.js +260 -0
  93. package/packages/client/dist/types/index.d.ts +140 -0
  94. package/packages/client/dist/types/index.js +38 -0
  95. package/postinstall.js +272 -0
  96. package/targets-stubs/antigravity/README.md +36 -0
  97. package/targets-stubs/antigravity/gemini.md +22 -0
  98. package/targets-stubs/antigravity/install-antigravity.sh +44 -0
  99. package/targets-stubs/antigravity/mcp-config.json +9 -0
  100. package/targets-stubs/antigravity/skill/SKILL.md +67 -0
  101. package/targets-stubs/claude-code/README.md +20 -0
  102. package/targets-stubs/claude-code/neocortex.agent.yaml +24 -0
  103. package/targets-stubs/claude-code/neocortex.md +125 -0
  104. package/targets-stubs/codex/README.md +32 -0
  105. package/targets-stubs/codex/agents.md +61 -0
  106. package/targets-stubs/codex/config-mcp.toml +6 -0
  107. package/targets-stubs/codex/install-codex.sh +61 -0
  108. package/targets-stubs/cursor/README.md +33 -0
  109. package/targets-stubs/cursor/agent.md +94 -0
  110. package/targets-stubs/cursor/install-cursor.sh +35 -0
  111. package/targets-stubs/cursor/mcp.json +11 -0
  112. package/targets-stubs/gemini-cli/README.md +34 -0
  113. package/targets-stubs/gemini-cli/agent.md +101 -0
  114. package/targets-stubs/gemini-cli/gemini.md +16 -0
  115. package/targets-stubs/gemini-cli/install-gemini.sh +56 -0
  116. package/targets-stubs/gemini-cli/settings-mcp.json +11 -0
  117. package/targets-stubs/vscode/README.md +34 -0
  118. package/targets-stubs/vscode/agent.md +102 -0
  119. package/targets-stubs/vscode/copilot-instructions.md +16 -0
  120. package/targets-stubs/vscode/install-vscode.sh +42 -0
  121. package/targets-stubs/vscode/mcp.json +13 -0
package/LICENSE ADDED
@@ -0,0 +1,56 @@
1
+ Business Source License 1.1
2
+
3
+ Parameters
4
+
5
+ Licensor: OrNexus AI
6
+ Licensed Work: @ornexus/neocortex v3.8.0 and later versions
7
+ Additional Use Grant: You may use the Licensed Work for personal development,
8
+ evaluation, and non-commercial projects without a
9
+ commercial license.
10
+ Change Date: Four (4) years from the date of each release of the
11
+ Licensed Work.
12
+ Change License: Apache License, Version 2.0
13
+
14
+ For the full text of the Business Source License 1.1, see:
15
+ https://mariadb.com/bsl11/
16
+
17
+ Notice
18
+
19
+ The Licensed Work is (c) 2024-2026 OrNexus AI.
20
+
21
+ -----------------------------------------------------------------------------
22
+
23
+ IMPORTANT: The full BSL-1.1 legal text must be inserted here before
24
+ publication. The canonical template is available at:
25
+
26
+ https://mariadb.com/bsl11/
27
+
28
+ Reference implementations:
29
+ - HashiCorp (Terraform): https://github.com/hashicorp/terraform/blob/main/LICENSE
30
+ - CockroachDB: https://github.com/cockroachdb/cockroach/blob/master/licenses/BSL.txt
31
+ - Sentry: https://github.com/getsentry/sentry/blob/master/LICENSE.md
32
+
33
+ TODO: Replace this placeholder with the complete BSL-1.1 text with the
34
+ parameters above filled in. Have legal counsel review before publishing.
35
+
36
+ -----------------------------------------------------------------------------
37
+
38
+ What you CAN do:
39
+
40
+ - Use Neocortex for personal projects and learning
41
+ - Use Neocortex for evaluation and testing purposes
42
+ - Use Neocortex for non-commercial open source projects
43
+ - Contribute to the Neocortex project
44
+ - Fork and modify for personal use
45
+
46
+ What you CANNOT do without a commercial license:
47
+
48
+ - Use Neocortex in production environments that generate revenue
49
+ - Redistribute Neocortex as part of a commercial product
50
+ - Offer Neocortex as a hosted service to third parties
51
+ - Extract, copy, or redistribute the proprietary prompts, workflows,
52
+ skills, or agent definitions
53
+
54
+ For commercial licensing inquiries:
55
+ Email: licensing@ornexus.com
56
+ Web: https://ornexus.com/licensing
package/README.md ADDED
@@ -0,0 +1,32 @@
1
+ # Neocortex
2
+
3
+ **AI-powered development orchestrator. From idea to pull request.**
4
+
5
+ Neocortex automates the full software development lifecycle -- architecture planning, implementation, code review, and deployment -- across 6 AI platforms including Claude Code, Cursor, Gemini CLI, Codex, VS Code, and Antigravity.
6
+
7
+ ## Get Started
8
+
9
+ Visit **[neocortex.sh](https://neocortex.sh)** to create your account, install, and activate.
10
+
11
+ ```bash
12
+ npm install -g @ornexus/neocortex
13
+ ```
14
+
15
+ After installing, activate your license and start building:
16
+
17
+ ```
18
+ neocortex activate YOUR-LICENSE-KEY
19
+ ```
20
+
21
+ Full documentation, pricing, and support available at [neocortex.sh](https://neocortex.sh).
22
+
23
+ ## License
24
+
25
+ Business Source License 1.1 (BSL-1.1). See [LICENSE](./LICENSE) for details.
26
+
27
+ Personal and development use is free. Commercial production use requires a license.
28
+ Contact: licensing@ornexus.com
29
+
30
+ ---
31
+
32
+ Built by [OrNexus Team](https://neocortex.sh)
package/install.js ADDED
@@ -0,0 +1,486 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Neocortex - Cross-Platform Multi-Target Installer
5
+ * Interactive platform selection with @clack/prompts + OS detection + shell dispatch
6
+ */
7
+
8
+ const { spawn } = require('child_process');
9
+ const path = require('path');
10
+ const os = require('os');
11
+ const fs = require('fs');
12
+ const {
13
+ intro, outro, multiselect, confirm, spinner, cancel, isCancel, note, log
14
+ } = require('@clack/prompts');
15
+ const color = require('picocolors');
16
+
17
+ const SCRIPT_DIR = __dirname;
18
+ const args = process.argv.slice(2);
19
+
20
+ // Read version from package.json
21
+ const pkg = JSON.parse(fs.readFileSync(path.join(SCRIPT_DIR, 'package.json'), 'utf8'));
22
+ const VERSION = pkg.version;
23
+
24
+ // ═══════════════════════════════════════════════════════════════════
25
+ // PLATFORM DEFINITIONS
26
+ // ═══════════════════════════════════════════════════════════════════
27
+
28
+ const PLATFORMS = [
29
+ { name: 'Claude Code CLI', key: 'claude-code', tier: 1, default: true, detect: 'claude', label: 'Tier 1 - Full Pipeline' },
30
+ { name: 'Cursor IDE', key: 'cursor', tier: 2, default: false, detect: 'cursor', label: 'Tier 2 - CLI Pipeline' },
31
+ { name: 'VS Code / GitHub Copilot', key: 'vscode', tier: 3, default: false, detect: 'code', label: 'Tier 3 - Agent-Directed' },
32
+ { name: 'Gemini CLI', key: 'gemini-cli', tier: 2, default: false, detect: 'gemini', label: 'Tier 2 - CLI Pipeline' },
33
+ { name: 'OpenAI Codex CLI', key: 'codex', tier: 2, default: false, detect: 'codex', label: 'Tier 2 - CLI Pipeline' },
34
+ { name: 'Google Antigravity', key: 'antigravity', tier: 3, default: false, detect: 'agy', label: 'Tier 3 - Agent-Directed', experimental: true },
35
+ ];
36
+
37
+ // ═══════════════════════════════════════════════════════════════════
38
+ // PLATFORM DETECTION
39
+ // ═══════════════════════════════════════════════════════════════════
40
+
41
+ function detectPlatform(command) {
42
+ const { execSync } = require('child_process');
43
+ try {
44
+ // Platform-aware detection: `where.exe` on Windows, `which` on Unix
45
+ // `which` does not exist natively on Windows (Epic 63 - Story 63.4)
46
+ if (process.platform === 'win32') {
47
+ // Epic 67 - Story 67.4: Use where.exe /Q (quiet mode) to suppress
48
+ // localized error messages (e.g., "INFO: ..." in non-EN locales).
49
+ // /Q returns only exit code without any stdout/stderr output.
50
+ execSync(`where.exe /Q ${command}`, { stdio: 'pipe' });
51
+ } else {
52
+ execSync(`which ${command} 2>/dev/null`, { stdio: 'pipe' });
53
+ }
54
+ return true;
55
+ } catch {
56
+ return false;
57
+ }
58
+ }
59
+
60
+ function detectInstalledPlatforms() {
61
+ const detected = {};
62
+ for (const p of PLATFORMS) {
63
+ detected[p.key] = detectPlatform(p.detect);
64
+ }
65
+ return detected;
66
+ }
67
+
68
+ // ═══════════════════════════════════════════════════════════════════
69
+ // ARGUMENT HANDLING
70
+ // ═══════════════════════════════════════════════════════════════════
71
+
72
+ function parseTargetsArg() {
73
+ for (const arg of args) {
74
+ if (arg.startsWith('--targets=')) {
75
+ return arg.replace('--targets=', '').split(',').map(t => t.trim()).filter(Boolean);
76
+ }
77
+ }
78
+ return null;
79
+ }
80
+
81
+ function isAutoYes() {
82
+ return args.includes('-y') || args.includes('--yes') || args.includes('-Yes');
83
+ }
84
+
85
+ function isVersion() {
86
+ return args.includes('-v') || args.includes('--version') || args.includes('-V');
87
+ }
88
+
89
+ function isHelp() {
90
+ return args.includes('-h') || args.includes('--help') || args.includes('-Help');
91
+ }
92
+
93
+ function isDebug() {
94
+ return args.includes('-d') || args.includes('--debug') || args.includes('-Debug');
95
+ }
96
+
97
+ /**
98
+ * Declarative flag mapping: Unix CLI flags -> PowerShell parameters.
99
+ * To add a new flag, just add an entry here. No switch/case to update.
100
+ */
101
+ const FLAG_MAP_WIN32 = {
102
+ // Auto-confirm mode
103
+ '-y': '-Yes',
104
+ '--yes': '-Yes',
105
+ // Debug output
106
+ '-d': '-Debug',
107
+ '--debug': '-Debug',
108
+ // Skip project directory creation
109
+ '-s': '-SkipProject',
110
+ '--skip-project': '-SkipProject',
111
+ // Force project directory creation
112
+ '--create-project': '-CreateProject',
113
+ // Suppress non-essential output
114
+ '-q': '-Quiet',
115
+ '--quiet': '-Quiet',
116
+ // Suppress ASCII banner
117
+ '--no-banner': '-NoBanner',
118
+ // Show help text
119
+ '-h': '-Help',
120
+ '--help': '-Help',
121
+ // Remove legacy artifacts from ~/.claude/
122
+ '--cleanup-legacy': '-CleanupLegacy',
123
+ // --local removed (Epic 50): thin-client mandatory, zero IP on client
124
+ // Server URL override
125
+ // --server-url=<url> is passed through as-is (handled by shell scripts)
126
+ };
127
+
128
+ function mapArgs(platform, originalArgs) {
129
+ const filtered = originalArgs.filter(a => !a.startsWith('--targets='));
130
+ if (platform === 'win32') {
131
+ return filtered.map(arg => FLAG_MAP_WIN32[arg] || arg);
132
+ }
133
+ return filtered;
134
+ }
135
+
136
+ // ═══════════════════════════════════════════════════════════════════
137
+ // SCRIPT EXECUTION
138
+ // ═══════════════════════════════════════════════════════════════════
139
+
140
+ function checkScript(scriptPath) {
141
+ if (!fs.existsSync(scriptPath)) {
142
+ log.error(`Script nao encontrado: ${scriptPath}`);
143
+ process.exit(1);
144
+ }
145
+ }
146
+
147
+ function runWindows(selectedTargets) {
148
+ const scriptPath = path.join(SCRIPT_DIR, 'install.ps1');
149
+ checkScript(scriptPath);
150
+
151
+ const mappedArgs = mapArgs('win32', args);
152
+ if (selectedTargets) {
153
+ mappedArgs.push('-Targets', selectedTargets.join(','));
154
+ }
155
+
156
+ const shells = ['pwsh', 'powershell'];
157
+
158
+ function tryShell(index) {
159
+ if (index >= shells.length) {
160
+ log.error('PowerShell nao encontrado.');
161
+ log.info('Instale o PowerShell Core: https://aka.ms/powershell');
162
+ process.exit(1);
163
+ }
164
+
165
+ const shell = shells[index];
166
+ const psArgs = ['-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', scriptPath, ...mappedArgs];
167
+
168
+ const child = spawn(shell, psArgs, { stdio: 'inherit', shell: false });
169
+
170
+ child.on('error', (err) => {
171
+ if (err.code === 'ENOENT') tryShell(index + 1);
172
+ else {
173
+ log.error(`Falha ao executar ${shell}: ${err.message}`);
174
+ process.exit(1);
175
+ }
176
+ });
177
+
178
+ child.on('exit', (code) => process.exit(code || 0));
179
+ }
180
+
181
+ tryShell(0);
182
+ }
183
+
184
+ function runUnix(selectedTargets) {
185
+ const scriptPath = path.join(SCRIPT_DIR, 'install.sh');
186
+ checkScript(scriptPath);
187
+
188
+ try { fs.chmodSync(scriptPath, '755'); } catch { }
189
+
190
+ const filteredArgs = mapArgs('unix', args);
191
+ if (selectedTargets) {
192
+ filteredArgs.push(`--targets=${selectedTargets.join(',')}`);
193
+ }
194
+
195
+ const child = spawn('bash', [scriptPath, ...filteredArgs], { stdio: 'inherit', shell: false });
196
+
197
+ child.on('error', (err) => {
198
+ if (err.code === 'ENOENT') {
199
+ const shChild = spawn('sh', [scriptPath, ...filteredArgs], { stdio: 'inherit', shell: false });
200
+ shChild.on('error', (e) => { log.error(`Shell nao encontrado: ${e.message}`); process.exit(1); });
201
+ shChild.on('exit', (code) => process.exit(code || 0));
202
+ } else {
203
+ log.error(`Falha ao executar instalador: ${err.message}`);
204
+ process.exit(1);
205
+ }
206
+ });
207
+
208
+ child.on('exit', (code) => process.exit(code || 0));
209
+ }
210
+
211
+ // ═══════════════════════════════════════════════════════════════════
212
+ // HELP
213
+ // ═══════════════════════════════════════════════════════════════════
214
+
215
+ function showHelp() {
216
+ console.log('');
217
+ console.log(color.bold(` Neocortex Installer v${VERSION}`));
218
+ console.log(color.dim(' Development Orchestrator'));
219
+ console.log('');
220
+ console.log(` ${color.dim('Uso:')} npx @ornexus/neocortex ${color.dim('[opcoes]')}`);
221
+ console.log(` npx @ornexus/neocortex activate ${color.dim('<KEY>')}`);
222
+ console.log('');
223
+ console.log(color.dim(' Comandos:'));
224
+ console.log(` ${color.cyan('activate <KEY>')} Ativar licenca (repara config se necessario)`);
225
+ console.log(` ${color.cyan('invoke --args <args>')} Invocar o server (thin-client)`);
226
+ console.log('');
227
+ console.log(color.dim(' Opcoes:'));
228
+ console.log(` ${color.cyan('-y, --yes')} Modo automatico (Claude Code only)`);
229
+ console.log(` ${color.cyan('--targets=<lista>')} Plataformas separadas por virgula`);
230
+ console.log(` ${color.cyan('--create-project')} Instalar estrutura no projeto`);
231
+ console.log(` ${color.cyan('-s, --skip-project')} Nao perguntar sobre projeto`);
232
+ console.log(` ${color.cyan('-q, --quiet')} Modo silencioso`);
233
+ console.log(` ${color.cyan('--cleanup-legacy')} Remover artefatos legados de ~/.claude/`);
234
+ console.log(` ${color.dim('--local')} ${color.dim('(Removido) Thin-client obrigatorio')}`);
235
+ console.log(` ${color.cyan('--server-url=<url>')} URL do server Neocortex`);
236
+ console.log(` ${color.cyan('-d, --debug')} Modo debug`);
237
+ console.log(` ${color.cyan('-v, --version')} Mostra a versao instalada`);
238
+ console.log(` ${color.cyan('-h, --help')} Mostra esta ajuda`);
239
+ console.log('');
240
+ console.log(color.dim(' Plataformas:'));
241
+ for (const p of PLATFORMS) {
242
+ const tag = p.experimental ? color.red(' [experimental]') : '';
243
+ console.log(` ${color.cyan(p.key.padEnd(20))} ${p.name} ${color.dim(`(${p.label})`)}${tag}`);
244
+ }
245
+ console.log('');
246
+ console.log(color.dim(' Exemplos:'));
247
+ console.log(` npx @ornexus/neocortex ${color.dim('# Selecao interativa')}`);
248
+ console.log(` npx @ornexus/neocortex --yes ${color.dim('# Claude Code (auto)')}`);
249
+ console.log(` npx @ornexus/neocortex --targets=claude-code,cursor`);
250
+ console.log('');
251
+ process.exit(0);
252
+ }
253
+
254
+ // ═══════════════════════════════════════════════════════════════════
255
+ // INTERACTIVE WIZARD
256
+ // ═══════════════════════════════════════════════════════════════════
257
+
258
+ async function interactiveWizard() {
259
+ // Detect installed platforms
260
+ const s = spinner();
261
+ s.start('Detectando plataformas instaladas...');
262
+ const detected = detectInstalledPlatforms();
263
+ const detectedNames = PLATFORMS.filter(p => detected[p.key]).map(p => p.name);
264
+ s.stop(
265
+ detectedNames.length > 0
266
+ ? `${detectedNames.length} plataforma(s) detectada(s): ${color.dim(detectedNames.join(', '))}`
267
+ : 'Nenhuma plataforma detectada automaticamente'
268
+ );
269
+
270
+ // Platform selection
271
+ const options = PLATFORMS.map(p => {
272
+ const hints = [];
273
+ if (detected[p.key]) hints.push('detectado');
274
+ if (p.experimental) hints.push('experimental');
275
+ hints.push(p.label);
276
+
277
+ return {
278
+ value: p.key,
279
+ label: p.name,
280
+ hint: hints.join(' | '),
281
+ };
282
+ });
283
+
284
+ const selectedPlatforms = await multiselect({
285
+ message: 'Selecione as plataformas de destino:',
286
+ options,
287
+ initialValues: PLATFORMS.filter(p => p.default).map(p => p.key),
288
+ required: true,
289
+ });
290
+
291
+ if (isCancel(selectedPlatforms)) {
292
+ cancel('Instalacao cancelada.');
293
+ process.exit(0);
294
+ }
295
+
296
+ // Show selection summary
297
+ const selectedNames = selectedPlatforms.map(key => {
298
+ const p = PLATFORMS.find(pl => pl.key === key);
299
+ return p.name;
300
+ });
301
+ log.info(`Plataformas: ${color.bold(selectedNames.join(', '))}`);
302
+
303
+ // Ask about project-level installation
304
+ let createProject = false;
305
+ if (!args.includes('-s') && !args.includes('--skip-project')) {
306
+ const projectInstall = await confirm({
307
+ message: 'Instalar estrutura completa no diretorio atual do projeto?',
308
+ initialValue: false,
309
+ });
310
+
311
+ if (isCancel(projectInstall)) {
312
+ cancel('Instalacao cancelada.');
313
+ process.exit(0);
314
+ }
315
+
316
+ createProject = projectInstall;
317
+ }
318
+
319
+ return { selectedPlatforms, createProject };
320
+ }
321
+
322
+ // ═══════════════════════════════════════════════════════════════════
323
+ // ASCII BANNER
324
+ // ═══════════════════════════════════════════════════════════════════
325
+
326
+ function showAsciiBanner() {
327
+ const c = '\x1b[36m'; // cyan
328
+ const b = '\x1b[1m'; // bold
329
+ const d = '\x1b[2m'; // dim
330
+ const r = '\x1b[0m'; // reset
331
+
332
+ console.log('');
333
+ console.log(`${c} #######${r}`);
334
+ console.log(`${c} ### ########${r}`);
335
+ console.log(`${c} ######### #####${r}`);
336
+ console.log(`${c} ## ############## ${b}N E O C O R T E X${r}`);
337
+ console.log(`${c} ## ### ###### ## ${b}v${VERSION}${r}`);
338
+ console.log(`${c} ## ### ### ##${r}`);
339
+ console.log(`${c} ## ###### ### ## ${d}OrNexus Team${r}`);
340
+ console.log(`${c} ############### ##${r}`);
341
+ console.log(`${c} ##### ########${r}`);
342
+ console.log(`${c} ######## ##${r}`);
343
+ console.log(`${c} #######${r}`);
344
+ console.log('');
345
+ }
346
+
347
+ // ═══════════════════════════════════════════════════════════════════
348
+ // MAIN
349
+ // ═══════════════════════════════════════════════════════════════════
350
+
351
+ async function main() {
352
+ const platform = os.platform();
353
+
354
+ // ── Subcommand delegation (Epic 70 - Story 70.01) ─────────────────
355
+ // Delegate known subcommands to neocortex-client binary.
356
+ // This ensures `neocortex activate KEY` reaches the activate handler
357
+ // instead of running the installation wizard.
358
+ const DELEGATED_COMMANDS = new Set(['activate', 'invoke', 'cache-status']);
359
+ const firstArg = args[0]?.toLowerCase();
360
+ if (firstArg && DELEGATED_COMMANDS.has(firstArg)) {
361
+ // Resolve neocortex-client: prefer sibling in same bin directory (npm shim),
362
+ // fallback to direct path to dist/cli.js within the package.
363
+ const clientBinDirect = path.join(SCRIPT_DIR, 'packages', 'client', 'dist', 'cli.js');
364
+ const child = spawn(process.execPath, [clientBinDirect, ...args], {
365
+ stdio: 'inherit',
366
+ env: process.env,
367
+ });
368
+ child.on('error', (err) => {
369
+ console.error(`Failed to delegate to neocortex-client: ${err.message}`);
370
+ process.exit(1);
371
+ });
372
+ child.on('exit', (code) => process.exit(code ?? 1));
373
+ return; // Do not continue with install wizard
374
+ }
375
+
376
+ // Version flag -- print just the version number and exit (for scripting)
377
+ if (isVersion()) {
378
+ console.log(VERSION);
379
+ return;
380
+ }
381
+
382
+ // Debug info
383
+ if (isDebug()) {
384
+ console.log(color.dim(` [debug] Platform: ${platform} | Node: ${process.version} | Dir: ${SCRIPT_DIR}`));
385
+ console.log(color.dim(` [debug] Args: ${args.join(' ') || '(none)'}`));
386
+ console.log('');
387
+ }
388
+
389
+ // Help
390
+ if (isHelp()) {
391
+ showHelp();
392
+ return;
393
+ }
394
+
395
+ // Determine selected targets
396
+ let selectedTargets = null;
397
+ let createProject = false;
398
+
399
+ // Priority 1: --targets= argument
400
+ const targetsArg = parseTargetsArg();
401
+ if (targetsArg) {
402
+ const validKeys = PLATFORMS.map(p => p.key);
403
+ const invalid = targetsArg.filter(t => !validKeys.includes(t));
404
+ if (invalid.length > 0) {
405
+ console.log('');
406
+ log.error(`Plataformas invalidas: ${color.bold(invalid.join(', '))}`);
407
+ log.info(`Validas: ${validKeys.join(', ')}`);
408
+ process.exit(1);
409
+ }
410
+ selectedTargets = targetsArg;
411
+
412
+ // In non-interactive mode with explicit targets, still check for project flag
413
+ if (args.includes('--create-project')) createProject = true;
414
+ }
415
+ // Priority 2: --yes flag = Claude Code only (backward compat)
416
+ else if (isAutoYes()) {
417
+ selectedTargets = ['claude-code'];
418
+ createProject = true;
419
+ }
420
+ // Priority 3: Interactive selection (if TTY)
421
+ else if (process.stdin.isTTY && process.stdout.isTTY) {
422
+ showAsciiBanner();
423
+ intro(color.bgWhite(color.black(` Neocortex v${VERSION} `)));
424
+
425
+ const result = await interactiveWizard();
426
+ selectedTargets = result.selectedPlatforms;
427
+ createProject = result.createProject;
428
+
429
+ if (selectedTargets.length === 0) {
430
+ cancel('Nenhuma plataforma selecionada.');
431
+ process.exit(0);
432
+ }
433
+ }
434
+ // Priority 4: Non-interactive, no flags = Claude Code only
435
+ else {
436
+ selectedTargets = ['claude-code'];
437
+ }
438
+
439
+ // ── Thin-Client Mode (Epic 50) ─────────────────────────────────
440
+ // ALL installations are thin-client. Zero IP on client, always.
441
+ const configPath = path.join(os.homedir(), '.neocortex', 'config.json');
442
+ const hasConfig = fs.existsSync(configPath);
443
+
444
+ if (!hasConfig) {
445
+ // Not activated yet - show activation instructions
446
+ log.info('');
447
+ log.info(color.cyan('Thin-Client Mode'));
448
+ log.info(color.dim('All content is served by the Neocortex remote server.'));
449
+ log.info('');
450
+ log.info(color.yellow('To activate your license:'));
451
+ log.info(color.bold(' neocortex activate NX-PRO-xxx'));
452
+ log.info('');
453
+ } else {
454
+ try {
455
+ // Strip UTF-8 BOM if present (PowerShell 5.1 writes BOM via Out-File -Encoding utf8)
456
+ // Defense in depth: handles configs written by old PS 5.1 installers (Epic 63 - Story 63.1)
457
+ const cfg = JSON.parse(fs.readFileSync(configPath, 'utf-8').replace(/^\uFEFF/, ''));
458
+ if (cfg.mode === 'remote') {
459
+ log.info(color.dim(`Remote mode active (server: ${cfg.serverUrl || 'default'})`));
460
+ }
461
+ } catch { /* ignore corrupted config */ }
462
+ }
463
+
464
+ // Dispatch to platform-specific installer
465
+ if (createProject) {
466
+ args.push('--create-project');
467
+ } else if (!args.includes('-s') && !args.includes('--skip-project')) {
468
+ args.push('--skip-project');
469
+ }
470
+
471
+ // Suppress shell banner when JS wizard already showed it (avoid duplicate)
472
+ if (process.stdin.isTTY && process.stdout.isTTY && !args.includes('-q') && !args.includes('--quiet')) {
473
+ args.push('--no-banner');
474
+ }
475
+
476
+ if (platform === 'win32') {
477
+ runWindows(selectedTargets);
478
+ } else {
479
+ runUnix(selectedTargets);
480
+ }
481
+ }
482
+
483
+ main().catch(err => {
484
+ log.error(err.message);
485
+ process.exit(1);
486
+ });