free-coding-models 0.3.37 → 0.3.40

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.
Files changed (58) hide show
  1. package/CHANGELOG.md +10 -1794
  2. package/README.md +4 -1
  3. package/bin/free-coding-models.js +8 -0
  4. package/package.json +13 -3
  5. package/src/app.js +3 -0
  6. package/src/cli-help.js +2 -0
  7. package/src/command-palette.js +3 -0
  8. package/src/endpoint-installer.js +1 -1
  9. package/src/tool-bootstrap.js +34 -0
  10. package/src/tool-launchers.js +137 -1
  11. package/src/tool-metadata.js +9 -0
  12. package/src/utils.js +10 -0
  13. package/web/app.legacy.js +900 -0
  14. package/web/index.html +20 -0
  15. package/web/server.js +382 -0
  16. package/web/src/App.jsx +150 -0
  17. package/web/src/components/analytics/AnalyticsView.jsx +109 -0
  18. package/web/src/components/analytics/AnalyticsView.module.css +186 -0
  19. package/web/src/components/atoms/Sparkline.jsx +44 -0
  20. package/web/src/components/atoms/StabilityCell.jsx +18 -0
  21. package/web/src/components/atoms/StabilityCell.module.css +8 -0
  22. package/web/src/components/atoms/StatusDot.jsx +10 -0
  23. package/web/src/components/atoms/StatusDot.module.css +17 -0
  24. package/web/src/components/atoms/TierBadge.jsx +10 -0
  25. package/web/src/components/atoms/TierBadge.module.css +18 -0
  26. package/web/src/components/atoms/Toast.jsx +25 -0
  27. package/web/src/components/atoms/Toast.module.css +35 -0
  28. package/web/src/components/atoms/ToastContainer.jsx +16 -0
  29. package/web/src/components/atoms/ToastContainer.module.css +10 -0
  30. package/web/src/components/atoms/VerdictBadge.jsx +13 -0
  31. package/web/src/components/atoms/VerdictBadge.module.css +19 -0
  32. package/web/src/components/dashboard/DetailPanel.jsx +131 -0
  33. package/web/src/components/dashboard/DetailPanel.module.css +99 -0
  34. package/web/src/components/dashboard/ExportModal.jsx +79 -0
  35. package/web/src/components/dashboard/ExportModal.module.css +99 -0
  36. package/web/src/components/dashboard/FilterBar.jsx +73 -0
  37. package/web/src/components/dashboard/FilterBar.module.css +43 -0
  38. package/web/src/components/dashboard/ModelTable.jsx +86 -0
  39. package/web/src/components/dashboard/ModelTable.module.css +46 -0
  40. package/web/src/components/dashboard/StatsBar.jsx +40 -0
  41. package/web/src/components/dashboard/StatsBar.module.css +28 -0
  42. package/web/src/components/layout/Footer.jsx +19 -0
  43. package/web/src/components/layout/Footer.module.css +10 -0
  44. package/web/src/components/layout/Header.jsx +38 -0
  45. package/web/src/components/layout/Header.module.css +73 -0
  46. package/web/src/components/layout/Sidebar.jsx +41 -0
  47. package/web/src/components/layout/Sidebar.module.css +76 -0
  48. package/web/src/components/settings/SettingsView.jsx +264 -0
  49. package/web/src/components/settings/SettingsView.module.css +377 -0
  50. package/web/src/global.css +199 -0
  51. package/web/src/hooks/useFilter.js +83 -0
  52. package/web/src/hooks/useSSE.js +49 -0
  53. package/web/src/hooks/useTheme.js +27 -0
  54. package/web/src/main.jsx +15 -0
  55. package/web/src/utils/download.js +15 -0
  56. package/web/src/utils/format.js +42 -0
  57. package/web/src/utils/ranks.js +37 -0
  58. package/web/styles.legacy.css +963 -0
package/README.md CHANGED
@@ -14,7 +14,7 @@
14
14
 
15
15
  <p align="center">
16
16
  <strong>Find the fastest free coding model in seconds</strong><br>
17
- <sub>Ping 238 models across 25 AI Free providers in real-time </sub><br><sub> Install Free API endpoints to your favorite AI coding tool: <br>📦 OpenCode, 🦞 OpenClaw, 💘 Crush, 🪿 Goose, 🛠 Aider, 🐉 Qwen Code, 🤲 OpenHands, ⚡ Amp, π Pi, 🦘 Rovo or ♊ Gemini in one keystroke</sub>
17
+ <sub>Ping 238 models across 25 AI Free providers in real-time </sub><br><sub> Install Free API endpoints to your favorite AI coding tool: <br>📦 OpenCode, 🦞 OpenClaw, 💘 Crush, 🪿 Goose, 🛠 Aider, 🐉 Qwen Code, 🤲 OpenHands, ⚡ Amp, 🔮 Hermes, ▶️ Continue, 🧠 Cline, π Pi, 🦘 Rovo or ♊ Gemini in one keystroke</sub>
18
18
  </p>
19
19
 
20
20
 
@@ -182,6 +182,9 @@ free-coding-models --openclaw --origin groq
182
182
  | `--qwen` | 🐉 Qwen Code |
183
183
  | `--openhands` | 🤲 OpenHands |
184
184
  | `--amp` | ⚡ Amp |
185
+ | `--hermes` | 🔮 Hermes |
186
+ | `--continue` | ▶️ Continue CLI |
187
+ | `--cline` | 🧠 Cline |
185
188
  | `--pi` | π Pi |
186
189
  | `--rovo` | 🦘 Rovo Dev CLI |
187
190
  | `--gemini` | ♊ Gemini CLI |
@@ -46,6 +46,14 @@ async function main() {
46
46
  process.exit(1);
47
47
  }
48
48
 
49
+ // 📖 --web mode: launch the web dashboard instead of the TUI
50
+ if (cliArgs.webMode) {
51
+ const { startWebServer } = await import('../web/server.js')
52
+ const port = parseInt(process.env.FCM_PORT || '3333', 10)
53
+ await startWebServer(port, { open: true })
54
+ return
55
+ }
56
+
49
57
  // 📖 Load JSON config
50
58
  const config = loadConfig();
51
59
  ensureTelemetryConfig(config);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "free-coding-models",
3
- "version": "0.3.37",
3
+ "version": "0.3.40",
4
4
  "description": "Find the fastest coding LLM models in seconds — ping free models from multiple providers, pick the best one for OpenCode, Cursor, or any AI coding assistant.",
5
5
  "keywords": [
6
6
  "nvidia",
@@ -41,6 +41,7 @@
41
41
  "files": [
42
42
  "bin/",
43
43
  "src/",
44
+ "web/",
44
45
  "sources.js",
45
46
  "patch-openclaw.js",
46
47
  "patch-openclaw-models.js",
@@ -51,16 +52,25 @@
51
52
  "scripts": {
52
53
  "start": "node bin/free-coding-models.js",
53
54
  "test": "node --test test/test.js",
55
+ "dev:web": "node scripts/dev-web.mjs",
56
+ "build:web": "vite build",
57
+ "preview:web": "vite preview",
54
58
  "test:fcm": "node scripts/testfcm-runner.mjs",
55
59
  "test:fcm:mock": "node scripts/testfcm-runner.mjs --tool crush --tool-bin-dir test/fixtures/mock-bin"
56
60
  },
57
61
  "dependencies": {
58
- "chalk": "^5.4.1"
62
+ "chalk": "^5.6.2"
59
63
  },
64
+ "packageManager": "pnpm@10.24.0",
60
65
  "engines": {
61
66
  "node": ">=18.0.0"
62
67
  },
63
68
  "devDependencies": {
64
- "@mariozechner/terminalcp": "^1.3.3"
69
+ "@vitejs/plugin-react": "^6.0.1",
70
+ "agent-tui": "^1.0.1",
71
+ "react": "^19.2.4",
72
+ "react-dom": "^19.2.4",
73
+ "vite": "^8.0.5",
74
+ "vite-plus": "^0.1.16"
65
75
  }
66
76
  }
package/src/app.js CHANGED
@@ -233,6 +233,9 @@ export async function runApp(cliArgs, config) {
233
233
  qwen: cliArgs.qwenMode,
234
234
  openhands: cliArgs.openHandsMode,
235
235
  amp: cliArgs.ampMode,
236
+ hermes: cliArgs.hermesMode,
237
+ 'continue': cliArgs.continueMode,
238
+ cline: cliArgs.clineMode,
236
239
  pi: cliArgs.piMode,
237
240
  rovo: cliArgs.rovoMode,
238
241
  gemini: cliArgs.geminiMode,
package/src/cli-help.js CHANGED
@@ -36,12 +36,14 @@ const ANALYSIS_FLAGS = [
36
36
  ]
37
37
 
38
38
  const CONFIG_FLAGS = [
39
+ { flag: '--web', description: 'Launch the web dashboard in your browser' },
39
40
  { flag: '--no-telemetry', description: 'Disable anonymous telemetry for this run' },
40
41
  { flag: '--help, -h', description: 'Print this help and exit' },
41
42
  ]
42
43
 
43
44
  const EXAMPLES = [
44
45
  'free-coding-models --help',
46
+ 'free-coding-models --web',
45
47
  'free-coding-models --openclaw --tier S',
46
48
  "free-coding-models --json | jq '.[0]'",
47
49
  ]
@@ -28,6 +28,9 @@ const TOOL_MODE_DESCRIPTIONS = {
28
28
  qwen: 'Launch Qwen Code using the selected provider model.',
29
29
  openhands: 'Launch OpenHands with the selected model endpoint.',
30
30
  amp: 'Launch Amp with this model as active target.',
31
+ hermes: 'Launch Hermes Agent with the selected model.',
32
+ 'continue': 'Launch Continue CLI with the selected model.',
33
+ cline: 'Launch Cline CLI with the selected model.',
31
34
  rovo: 'Rovo Dev CLI model (launch with Rovo tool only).',
32
35
  gemini: 'Gemini CLI model (launch with Gemini tool only).',
33
36
  }
@@ -52,7 +52,7 @@ import { getToolMeta } from './tool-metadata.js'
52
52
  const DIRECT_INSTALL_UNSUPPORTED_PROVIDERS = new Set(['replicate', 'zai', 'rovo', 'gemini', 'opencode-zen'])
53
53
  // 📖 Install Endpoints only lists tools whose persisted config shape is actually supported here.
54
54
  // 📖 Claude Code, Codex, and Gemini stay out while their dedicated bridges are being rebuilt.
55
- const INSTALL_TARGET_MODES = ['opencode', 'opencode-desktop', 'openclaw', 'crush', 'goose', 'pi', 'aider', 'qwen', 'openhands', 'amp']
55
+ const INSTALL_TARGET_MODES = ['opencode', 'opencode-desktop', 'openclaw', 'crush', 'goose', 'pi', 'aider', 'qwen', 'openhands', 'amp', 'hermes', 'continue', 'cline']
56
56
 
57
57
  function getDefaultPaths() {
58
58
  const home = homedir()
@@ -228,6 +228,40 @@ export const TOOL_BOOTSTRAP_METADATA = {
228
228
  },
229
229
  },
230
230
  },
231
+ 'continue': {
232
+ binary: 'cn',
233
+ docsUrl: 'https://docs.continue.dev/cli/overview',
234
+ install: {
235
+ default: {
236
+ shellCommand: 'npm install -g @continuedev/cli',
237
+ summary: 'Install Continue CLI globally via npm.',
238
+ },
239
+ },
240
+ },
241
+ cline: {
242
+ binary: 'cline',
243
+ docsUrl: 'https://docs.cline.bot/cline-cli/overview',
244
+ install: {
245
+ default: {
246
+ shellCommand: 'npm install -g cline',
247
+ summary: 'Install Cline CLI globally via npm.',
248
+ },
249
+ },
250
+ },
251
+ hermes: {
252
+ binary: 'hermes',
253
+ docsUrl: 'https://github.com/NousResearch/hermes-agent',
254
+ install: {
255
+ default: {
256
+ shellCommand: 'curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash',
257
+ summary: 'Install Hermes Agent via the official Nous Research installer.',
258
+ note: 'Hermes requires Python 3.11+ and git. The installer handles everything else automatically.',
259
+ },
260
+ },
261
+ installUnsupported: {
262
+ win32: 'Hermes Agent does not support native Windows. Use WSL2 instead.',
263
+ },
264
+ },
231
265
  gemini: {
232
266
  binary: 'gemini',
233
267
  docsUrl: 'https://github.com/google-gemini/gemini-cli',
@@ -17,6 +17,9 @@
17
17
  * 📖 Crush: writes crush.json with provider config + models.large/small defaults
18
18
  * 📖 Pi: uses --provider/--model CLI flags for guaranteed auto-selection
19
19
  * 📖 Aider: writes ~/.aider.conf.yml + passes --model flag
20
+ * 📖 Hermes: uses `hermes config set` CLI commands + `hermes gateway restart` before launching `hermes chat`
21
+ * 📖 Continue: writes ~/.continue/config.yaml with provider: openai + apiBase
22
+ * 📖 Cline: writes ~/.cline/globalState.json with openai-compatible provider config
20
23
  *
21
24
  * @functions
22
25
  * → `resolveLauncherModelId` — choose the provider-specific id for a launch
@@ -36,7 +39,7 @@ import chalk from 'chalk'
36
39
  import { existsSync, mkdirSync, readFileSync, writeFileSync, copyFileSync } from 'fs'
37
40
  import { homedir } from 'os'
38
41
  import { dirname, join } from 'path'
39
- import { spawn } from 'child_process'
42
+ import { spawn, spawnSync } from 'child_process'
40
43
  import { sources } from '../sources.js'
41
44
  import { PROVIDER_COLOR } from './render-table.js'
42
45
  import { getApiKey } from './config.js'
@@ -73,6 +76,9 @@ function getDefaultToolPaths(homeDir = homedir()) {
73
76
  piModelsPath: join(homeDir, '.pi', 'agent', 'models.json'),
74
77
  piSettingsPath: join(homeDir, '.pi', 'agent', 'settings.json'),
75
78
  openHandsEnvPath: join(homeDir, '.fcm-openhands-env'),
79
+ hermesConfigPath: join(homeDir, '.hermes', 'config.yaml'),
80
+ continueConfigPath: join(homeDir, '.continue', 'config.yaml'),
81
+ clineConfigPath: join(homeDir, '.cline', 'globalState.json'),
76
82
  }
77
83
  }
78
84
 
@@ -401,6 +407,80 @@ function writeRovoConfig(model, configPath = join(homedir(), '.rovodev', 'config
401
407
  return { filePath: configPath, backupPath }
402
408
  }
403
409
 
410
+ // 📖 writeContinueConfig — write ~/.continue/config.yaml with the selected model.
411
+ // 📖 Continue CLI uses YAML config with `provider: openai` for OpenAI-compatible endpoints.
412
+ function writeContinueConfig(model, apiKey, baseUrl, paths = getDefaultToolPaths()) {
413
+ const filePath = paths.continueConfigPath
414
+ const backupPath = backupIfExists(filePath)
415
+ // 📖 Write a minimal config.yaml that Continue CLI can parse directly
416
+ const content = [
417
+ '# 📖 Managed by free-coding-models',
418
+ 'name: FCM Config',
419
+ 'version: 0.0.1',
420
+ 'schema: v1',
421
+ 'models:',
422
+ ' - name: ' + (model.label || model.modelId),
423
+ ' provider: openai',
424
+ ' model: ' + model.modelId,
425
+ ...(baseUrl ? [' apiBase: ' + baseUrl] : []),
426
+ ...(apiKey ? [' apiKey: ' + apiKey] : []),
427
+ ' roles:',
428
+ ' - chat',
429
+ ' - edit',
430
+ ' - apply',
431
+ '',
432
+ ].join('\n')
433
+ ensureDir(filePath)
434
+ writeFileSync(filePath, content)
435
+ return { filePath, backupPath }
436
+ }
437
+
438
+ // 📖 writeClineConfig — write ~/.cline/globalState.json with the selected model.
439
+ // 📖 Cline CLI stores provider config in globalState.json under apiConfiguration.
440
+ function writeClineConfig(model, apiKey, baseUrl, paths = getDefaultToolPaths()) {
441
+ const filePath = paths.clineConfigPath
442
+ const backupPath = backupIfExists(filePath)
443
+ const config = readJson(filePath, {})
444
+ // 📖 Set the API provider to "openai-compatible" and configure the endpoint
445
+ config.apiConfiguration = {
446
+ ...(config.apiConfiguration || {}),
447
+ apiProvider: 'openai-compatible',
448
+ openAiCompatibleApiModelId: model.modelId,
449
+ ...(baseUrl ? { openAiCompatibleApiBaseUrl: baseUrl } : {}),
450
+ ...(apiKey ? { openAiCompatibleApiKey: apiKey } : {}),
451
+ }
452
+ writeJson(filePath, config)
453
+ return { filePath, backupPath }
454
+ }
455
+
456
+ // 📖 writeHermesConfig — configure Hermes Agent via its own `hermes config set` CLI.
457
+ // 📖 This avoids YAML parsing and uses Hermes's native config management.
458
+ // 📖 Sets model name, base_url (OpenAI-compatible endpoint), and api_key.
459
+ function writeHermesConfig(model, apiKey, baseUrl, paths = getDefaultToolPaths()) {
460
+ const configPath = paths.hermesConfigPath
461
+ const backupPath = backupIfExists(configPath)
462
+ const hermesBin = resolveToolBinaryPath('hermes') || 'hermes'
463
+
464
+ // 📖 Use `hermes config set` for each field — robust and dependency-free
465
+ spawnSync(hermesBin, ['config', 'set', 'model', model.modelId], { stdio: 'ignore' })
466
+ spawnSync(hermesBin, ['config', 'set', 'model.provider', 'custom'], { stdio: 'ignore' })
467
+ if (baseUrl) {
468
+ spawnSync(hermesBin, ['config', 'set', 'model.base_url', baseUrl], { stdio: 'ignore' })
469
+ }
470
+ if (apiKey) {
471
+ spawnSync(hermesBin, ['config', 'set', 'model.api_key', apiKey], { stdio: 'ignore' })
472
+ }
473
+
474
+ return { filePath: configPath, backupPath }
475
+ }
476
+
477
+ // 📖 restartHermesGateway — restart the Hermes messaging gateway after config changes.
478
+ // 📖 Non-blocking: if gateway is not running, this is a no-op.
479
+ function restartHermesGateway() {
480
+ const hermesBin = resolveToolBinaryPath('hermes') || 'hermes'
481
+ spawnSync(hermesBin, ['gateway', 'restart'], { stdio: 'ignore', timeout: 10000 })
482
+ }
483
+
404
484
  /**
405
485
  * 📖 buildGeminiEnv - Build environment variables for Gemini CLI
406
486
  *
@@ -597,6 +677,45 @@ export function prepareExternalToolLaunch(mode, model, config, options = {}) {
597
677
  }
598
678
  }
599
679
 
680
+ if (mode === 'hermes') {
681
+ const result = writeHermesConfig(model, apiKey, baseUrl, paths)
682
+ return {
683
+ command: 'hermes',
684
+ args: ['chat'],
685
+ env,
686
+ apiKey,
687
+ baseUrl,
688
+ meta,
689
+ configArtifacts: [{ path: result.filePath, backupPath: result.backupPath, label: 'config' }],
690
+ }
691
+ }
692
+
693
+ if (mode === 'continue') {
694
+ const result = writeContinueConfig(model, apiKey, baseUrl, paths)
695
+ return {
696
+ command: 'cn',
697
+ args: [],
698
+ env,
699
+ apiKey,
700
+ baseUrl,
701
+ meta,
702
+ configArtifacts: [{ path: result.filePath, backupPath: result.backupPath, label: 'config' }],
703
+ }
704
+ }
705
+
706
+ if (mode === 'cline') {
707
+ const result = writeClineConfig(model, apiKey, baseUrl, paths)
708
+ return {
709
+ command: 'cline',
710
+ args: [],
711
+ env,
712
+ apiKey,
713
+ baseUrl,
714
+ meta,
715
+ configArtifacts: [{ path: result.filePath, backupPath: result.backupPath, label: 'config' }],
716
+ }
717
+ }
718
+
600
719
  if (mode === 'rovo') {
601
720
  const result = writeRovoConfig(model, join(homedir(), '.rovodev', 'config.yml'), paths)
602
721
  console.log(chalk.dim(` 📖 Rovo Dev CLI configured with model: ${model.modelId}`))
@@ -679,6 +798,23 @@ export async function startExternalTool(mode, model, config) {
679
798
  return spawnCommand(resolveLaunchCommand(mode, launchPlan.command), launchPlan.args, launchPlan.env)
680
799
  }
681
800
 
801
+ if (mode === 'hermes') {
802
+ // 📖 Restart the Hermes gateway so the new model config takes effect immediately
803
+ restartHermesGateway()
804
+ console.log(chalk.dim(` 📖 Hermes Agent configured with model: ${model.modelId}`))
805
+ return spawnCommand(resolveLaunchCommand(mode, launchPlan.command), launchPlan.args, launchPlan.env)
806
+ }
807
+
808
+ if (mode === 'continue') {
809
+ console.log(chalk.dim(` 📖 Continue CLI configured with model: ${model.modelId}`))
810
+ return spawnCommand(resolveLaunchCommand(mode, launchPlan.command), launchPlan.args, launchPlan.env)
811
+ }
812
+
813
+ if (mode === 'cline') {
814
+ console.log(chalk.dim(` 📖 Cline configured with model: ${model.modelId}`))
815
+ return spawnCommand(resolveLaunchCommand(mode, launchPlan.command), launchPlan.args, launchPlan.env)
816
+ }
817
+
682
818
  if (mode === 'rovo') {
683
819
  console.log(chalk.dim(` 📖 Launching Rovo Dev CLI in interactive mode...`))
684
820
  return spawnCommand(resolveLaunchCommand(mode, launchPlan.command), launchPlan.args, launchPlan.env)
@@ -36,6 +36,9 @@ export const TOOL_METADATA = {
36
36
  qwen: { label: 'Qwen Code', emoji: '🐉', flag: '--qwen', color: [255, 213, 128] },
37
37
  openhands: { label: 'OpenHands', emoji: '🤲', flag: '--openhands', color: [228, 191, 239] },
38
38
  amp: { label: 'Amp', emoji: '⚡', flag: '--amp', color: [255, 232, 98] },
39
+ hermes: { label: 'Hermes', emoji: '🔮', flag: '--hermes', color: [200, 160, 255] },
40
+ 'continue': { label: 'Continue CLI', emoji: '▶️', flag: '--continue', color: [255, 100, 100] },
41
+ cline: { label: 'Cline', emoji: '🧠', flag: '--cline', color: [100, 220, 180] },
39
42
  rovo: { label: 'Rovo Dev CLI', emoji: '🦘', flag: '--rovo', color: [148, 163, 184], cliOnly: true },
40
43
  gemini: { label: 'Gemini CLI', emoji: '♊', flag: '--gemini', color: [66, 165, 245], cliOnly: true },
41
44
  }
@@ -53,6 +56,9 @@ export const COMPAT_COLUMN_SLOTS = [
53
56
  { emoji: '🐉', toolKeys: ['qwen'], color: [255, 213, 128] },
54
57
  { emoji: '🤲', toolKeys: ['openhands'], color: [228, 191, 239] },
55
58
  { emoji: '⚡', toolKeys: ['amp'], color: [255, 232, 98] },
59
+ { emoji: '🔮', toolKeys: ['hermes'], color: [200, 160, 255] },
60
+ { emoji: '▶️', toolKeys: ['continue'], color: [255, 100, 100] },
61
+ { emoji: '🧠', toolKeys: ['cline'], color: [100, 220, 180] },
56
62
  { emoji: '🦘', toolKeys: ['rovo'], color: [148, 163, 184] },
57
63
  { emoji: '♊', toolKeys: ['gemini'], color: [66, 165, 245] },
58
64
  ]
@@ -68,6 +74,9 @@ export const TOOL_MODE_ORDER = [
68
74
  'qwen',
69
75
  'openhands',
70
76
  'amp',
77
+ 'hermes',
78
+ 'continue',
79
+ 'cline',
71
80
  'rovo',
72
81
  'gemini',
73
82
  ]
package/src/utils.js CHANGED
@@ -455,12 +455,18 @@ export function parseArgs(argv) {
455
455
  const ampMode = flags.includes('--amp')
456
456
  const piMode = flags.includes('--pi')
457
457
  const rovoMode = flags.includes('--rovo')
458
+ const hermesMode = flags.includes('--hermes')
459
+ const continueMode = flags.includes('--continue')
460
+ const clineMode = flags.includes('--cline')
458
461
  const geminiMode = flags.includes('--gemini')
459
462
  const noTelemetry = flags.includes('--no-telemetry')
460
463
  const jsonMode = flags.includes('--json')
461
464
  const helpMode = flags.includes('--help') || flags.includes('-h')
462
465
  const premiumMode = flags.includes('--premium')
463
466
 
467
+ // 📖 --web / --gui / web subcommand — launch the web dashboard instead of the TUI
468
+ const webMode = flags.includes('--web') || flags.includes('--gui') || args[0] === 'web'
469
+
464
470
  // New boolean flags
465
471
  const sortDesc = flags.includes('--desc')
466
472
  const sortAscFlag = flags.includes('--asc')
@@ -492,6 +498,9 @@ export function parseArgs(argv) {
492
498
  openHandsMode,
493
499
  ampMode,
494
500
  piMode,
501
+ hermesMode,
502
+ continueMode,
503
+ clineMode,
495
504
  rovoMode,
496
505
  geminiMode,
497
506
  noTelemetry,
@@ -505,6 +514,7 @@ export function parseArgs(argv) {
505
514
  hideUnconfigured,
506
515
  showUnconfigured,
507
516
  premiumMode,
517
+ webMode,
508
518
  // 📖 Profile system removed - API keys now persist permanently across all sessions
509
519
  recommendMode,
510
520
  }