ReviewOS

also looking at this

stacks/buddy

feat(cli): restore the affordances the docs promised

#1402
Merged glennmichael123 wants to merge feat/restore-documented-affordances into main
6 files +150 -8
bin/cli.tsmodified+31-5
Changes to bin/cli.ts
@@ -289,10 +289,15 @@ interface CLIOptions {
289289 ignore?: string
290290 dryRun?: boolean
291291 respectLatest?: boolean
292 /** Which settings pages `open-settings` should open: repo, org or both. */
293 type?: string
292294}
293295
294296cli
295297 .command('setup', '🚀 Interactive setup for automated dependency updates (recommended)')
298 // `init` is what people type first, by convention from npm, git and cargo.
299 // Setup is the command that writes the config, so the alias is honest.
300 .alias('init')
296301 .option('--verbose, -v', 'Enable verbose logging')
297302 .option('--non-interactive', 'Run setup without prompts (use defaults)')
298303 .option('--preset <type>', 'Workflow preset: standard|high-frequency|security|minimal|testing', { default: 'standard' })
@@ -2633,10 +2638,19 @@ cli
26332638
26342639cli
26352640 .command('open-settings', 'Open GitHub repository and organization settings pages')
2641 .option('--type <scope>', 'Which settings to open: repo, org or both', { default: 'both' })
26362642 .option('--verbose, -v', 'Enable verbose logging')
26372643 .example('buddy open-settings')
26382644 .action(async (options: CLIOptions) => {
26392645 const logger = options.verbose ? Logger.verbose() : Logger.quiet()
2646
2647 // Validated before any work or output, so a typo fails immediately
2648 // rather than after the repository lookup has already printed.
2649 const scope = String(options?.type ?? 'both').toLowerCase()
2650 if (!['repo', 'org', 'both'].includes(scope)) {
2651 logger.error(`Unknown --type ${scope}. Expected repo, org or both.`)
2652 process.exit(1)
2653 }
26402654 const config = await resolveConfig(options.config)
26412655
26422656 try {
@@ -2708,13 +2722,16 @@ cli
27082722 }
27092723 }
27102724
2711 // Open repository settings
2712 await openUrl(repoUrl, 'repository settings')
2725 if (scope !== 'org')
2726 await openUrl(repoUrl, 'repository settings')
27132727
2714 // Also try to open organization settings (may fail if not an org)
2728 // Organisation settings 404 on a personal account, so they are opened
2729 // only when asked for, or as the tail of the default `both`.
27152730 setTimeout(async () => {
2716 logger.info('\n🏢 Attempting to open organization settings...')
2717 await openUrl(orgUrl, 'organization settings')
2731 if (scope !== 'repo') {
2732 logger.info('\n🏢 Attempting to open organization settings...')
2733 await openUrl(orgUrl, 'organization settings')
2734 }
27182735
27192736 logger.info('\n📋 Required Settings:')
27202737 logger.info(' 1. Under "Workflow permissions":')
@@ -3393,6 +3410,15 @@ cli.command('version', 'Show the version of Buddy').action(() => {
33933410 console.log(version)
33943411})
33953412
3413// `--help` is a flag, but `buddy help` is what a newcomer types. Registering
3414// it means the guess works rather than printing 'Command "help" not found'.
3415cli.command('help', 'Show this help text').action(() => {
3416 // Without this, outputHelp() renders the matched command — `buddy help`
3417 // itself — rather than the list of commands the reader is asking for.
3418 cli.unsetMatchedCommand()
3419 cli.outputHelp()
3420})
3421
33963422// Available on every command: each action reads `options.config` and passes it
33973423// to resolveConfig, which bypasses discovery when a path is given.
33983424cli.option('--config <path>', 'Path to a buddy config file')