index.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. #!/usr/bin/env bun
  2. import { doctor, parseDoctorArgs } from './doctor';
  3. import { install } from './install';
  4. import { getGeneratedPresetNames, isGeneratedPresetName } from './providers';
  5. import type {
  6. BackgroundSubagentsArg,
  7. BooleanArg,
  8. CompanionArg,
  9. InstallArgs,
  10. } from './types';
  11. export function parseArgs(args: string[]): InstallArgs {
  12. const result: InstallArgs = {
  13. tui: true,
  14. skills: 'yes',
  15. companion: 'ask',
  16. };
  17. for (const arg of args) {
  18. if (arg === '--no-tui') {
  19. result.tui = false;
  20. } else if (arg.startsWith('--skills=')) {
  21. result.skills = arg.split('=')[1] as BooleanArg;
  22. } else if (arg.startsWith('--companion=')) {
  23. const mode = arg.split('=')[1] as CompanionArg;
  24. if (!['ask', 'yes', 'no'].includes(mode)) {
  25. console.error('Unsupported --companion value: use ask, yes, or no');
  26. process.exit(1);
  27. }
  28. result.companion = mode;
  29. } else if (arg.startsWith('--preset=')) {
  30. const preset = arg.split('=')[1];
  31. if (!isGeneratedPresetName(preset)) {
  32. console.error(
  33. `Unsupported preset: ${preset}. Available presets: ${getGeneratedPresetNames().join(', ')}`,
  34. );
  35. process.exit(1);
  36. }
  37. result.preset = preset;
  38. } else if (arg.startsWith('--background-subagents=')) {
  39. const mode = arg.split('=')[1] as BackgroundSubagentsArg;
  40. if (!['ask', 'yes', 'no'].includes(mode)) {
  41. console.error(
  42. 'Unsupported --background-subagents value: use ask, yes, or no',
  43. );
  44. process.exit(1);
  45. }
  46. result.backgroundSubagents = mode;
  47. } else if (arg.startsWith('--background-subagents-target=')) {
  48. result.backgroundSubagentsTarget = arg.split('=')[1];
  49. } else if (arg === '--dry-run') {
  50. result.dryRun = true;
  51. } else if (arg === '--reset') {
  52. result.reset = true;
  53. } else if (arg === '-h' || arg === '--help') {
  54. printHelp();
  55. process.exit(0);
  56. }
  57. }
  58. result.backgroundSubagents ??= 'ask';
  59. return result;
  60. }
  61. function printHelp(): void {
  62. console.log(`
  63. oh-my-opencode-slim installer
  64. Usage:
  65. bunx oh-my-opencode-slim install [OPTIONS]
  66. bunx oh-my-opencode-slim doctor [OPTIONS]
  67. Options:
  68. --skills=yes|no Install bundled skills (default: yes)
  69. --companion=ask|yes|no Install desktop companion binary and enable config
  70. (default: ask; prompt defaults to no)
  71. --preset=<name> Active generated config preset (default: openai)
  72. --background-subagents=ask|yes|no
  73. Persist required OpenCode background subagent env
  74. (default: ask; prompt defaults to yes)
  75. --background-subagents-target=<path>
  76. Shell startup file to update
  77. --no-tui Non-interactive mode
  78. --dry-run Simulate install without writing files
  79. --reset Force overwrite of existing configuration
  80. -h, --help Show this help message
  81. Doctor options:
  82. --json Print diagnostics as JSON
  83. Available presets: ${getGeneratedPresetNames().join(', ')}
  84. The installer generates OpenAI and OpenCode Go presets by default.
  85. OpenAI is active unless --preset selects another generated preset.
  86. For the full config reference, see docs/configuration.md.
  87. Examples:
  88. bunx oh-my-opencode-slim install
  89. bunx oh-my-opencode-slim install --no-tui --skills=yes
  90. bunx oh-my-opencode-slim install --background-subagents=yes
  91. bunx oh-my-opencode-slim install --preset=opencode-go
  92. bunx oh-my-opencode-slim install --reset
  93. bunx oh-my-opencode-slim doctor
  94. `);
  95. }
  96. async function main(): Promise<void> {
  97. const args = process.argv.slice(2);
  98. if (args.length === 0 || args[0] === 'install') {
  99. const hasSubcommand = args[0] === 'install';
  100. const installArgs = parseArgs(args.slice(hasSubcommand ? 1 : 0));
  101. const exitCode = await install(installArgs);
  102. process.exit(exitCode);
  103. } else if (args[0] === 'doctor') {
  104. const doctorArgs = parseDoctorArgs(args.slice(1));
  105. const exitCode = await doctor(doctorArgs);
  106. process.exit(exitCode);
  107. } else if (args[0] === '-h' || args[0] === '--help') {
  108. printHelp();
  109. process.exit(0);
  110. } else {
  111. console.error(`Unknown command: ${args[0]}`);
  112. console.error('Run with --help for usage information');
  113. process.exit(1);
  114. }
  115. }
  116. if (import.meta.main) {
  117. main().catch((err) => {
  118. console.error('Fatal error:', err);
  119. process.exit(1);
  120. });
  121. }