### Interactive Project Setup Wizard Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/guides/examples.mdx This example demonstrates a comprehensive project setup wizard using various Clack prompts like text, select, groupMultiselect, and confirm. It guides the user through project details, type selection, framework choice, feature selection, and final confirmation. Handles user cancellations gracefully. ```typescript import { text, select, confirm, groupMultiselect, isCancel } from '@clack/prompts'; async function setupProject() { // Get project details const name = await text({ message: 'Project name:', validate: (value) => { if (!value || value.length === 0) return 'Name is required'; if (!/^[a-z0-9-]+$/.test(value)) return 'Name can only contain lowercase letters, numbers, and hyphens'; return undefined; }, }); if (isCancel(name)) { console.log('Operation cancelled'); process.exit(0); } const type = await select({ message: 'Project type:', options: [ { value: 'web', label: 'Web Application', hint: 'Full-stack web application' }, { value: 'cli', label: 'CLI Tool', hint: 'Command-line interface tool' }, { value: 'api', label: 'API Server', hint: 'REST/GraphQL API server' }, ], }); if (isCancel(type)) { console.log('Operation cancelled'); process.exit(0); } // Get additional details based on project type let framework; if (type === 'web') { framework = await select({ message: 'Choose a framework:', options: [ { value: 'next', label: 'Next.js', hint: 'React framework for production' }, { value: 'nuxt', label: 'Nuxt', hint: 'Vue framework for production' }, { value: 'sveltekit', label: 'SvelteKit', hint: 'Svelte framework for production' }, ], }); if (isCancel(framework)) { console.log('Operation cancelled'); process.exit(0); } } // Select features const features = await groupMultiselect({ message: 'Select features:', options: { 'Development': [ { value: 'typescript', label: 'TypeScript', hint: 'Type safety' }, { value: 'eslint', label: 'ESLint', hint: 'Code linting' }, { value: 'prettier', label: 'Prettier', hint: 'Code formatting' }, ], 'Testing': [ { value: 'jest', label: 'Jest', hint: 'Unit testing' }, { value: 'cypress', label: 'Cypress', hint: 'E2E testing' }, ], 'Deployment': [ { value: 'docker', label: 'Docker', hint: 'Containerization' }, { value: 'ci', label: 'CI/CD', hint: 'Continuous integration' }, ], }, }); if (isCancel(features)) { console.log('Operation cancelled'); process.exit(0); } // Confirm setup const shouldProceed = await confirm({ message: `Create ${type} project "${name}"${framework ? ` with ${framework}` : ''}?`, }); if (isCancel(shouldProceed)) { console.log('Operation cancelled'); process.exit(0); } if (shouldProceed) { // Project creation logic here console.log('Creating project...'); } } ``` -------------------------------- ### Package Manager Completion Example: pnpm install Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/tab/index.mdx Demonstrates tab completions for the --reporter option in pnpm install, showing available reporter types. ```bash pnpm install --reporter= # Shows: append-only, default, ndjson, silent ``` -------------------------------- ### Install @clack/core with pnpm Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/core.mdx Install the core package using pnpm. ```bash pnpm add @clack/core ``` -------------------------------- ### Install @clack/core with Yarn Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/core.mdx Install the core package using Yarn. ```bash yarn add @clack/core ``` -------------------------------- ### Install @clack/core with npm Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/core.mdx Install the core package using npm. ```bash npm install @clack/core ``` -------------------------------- ### Install @clack/prompts with npm Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Install the @clack/prompts package using npm. ```bash npm install @clack/prompts ``` -------------------------------- ### Basic CLI Argument Parsing Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/args/getting-started.mdx Parse command-line arguments using the Args library. This example shows how to get started with minimal configuration. ```ts import { parse } from "@bomb.sh/args"; // my-cli build --bundle -rf --a value --b=value --c 1 const argv = process.argv.slice(2); const args = parse(argv); console.log(args); // { _: ['build'], bundle: true, r: true, f: true, a: "value", b: "value", c: 1 } ``` -------------------------------- ### Basic Clack CLI Example Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/basics/getting-started.mdx A simple example demonstrating text input, select menu, and confirmation prompts in Clack. ```typescript import { text, select, confirm, isCancel } from '@clack/prompts'; async function main() { // Get user's name const name = await text({ message: 'What is your name?', placeholder: 'John Doe', }) as string; // Get user's preferred framework const framework = await select({ message: 'Choose a framework:', options: [ { value: 'react', label: 'React' }, { value: 'vue', label: 'Vue' }, { value: 'svelte', label: 'Svelte' }, ], }); if (isCancel(framework)) { console.log('Operation cancelled'); process.exit(0); } // Confirm the selection const shouldProceed = await confirm({ message: `Create a ${framework} project for ${name}?`, }); if (shouldProceed) { console.log('Creating project...'); } } ``` -------------------------------- ### Install @clack/prompts with pnpm Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Install the @clack/prompts package using pnpm. ```bash pnpm add @clack/prompts ``` -------------------------------- ### Install @clack/prompts with Yarn Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Install the @clack/prompts package using Yarn. ```bash yarn add @clack/prompts ``` -------------------------------- ### Install Args with pnpm Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/args/getting-started.mdx Install the Args library using pnpm. This package manager is known for its efficiency. ```bash pnpm add @bomb.sh/args ``` -------------------------------- ### Install Args with npm Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/args/getting-started.mdx Install the Args library using npm. This is a common way to add the package to your project. ```bash npm install @bomb.sh/args ``` -------------------------------- ### Install Clack Prompts Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/basics/getting-started.mdx Install the Clack prompts package using npm, pnpm, or yarn. ```bash npm install @clack/prompts ``` ```bash pnpm add @clack/prompts ``` ```bash yarn add @clack/prompts ``` -------------------------------- ### Install Args with Yarn Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/args/getting-started.mdx Install the Args library using Yarn. Another popular package manager for Node.js projects. ```bash yarn add @bomb.sh/args ``` -------------------------------- ### Install Shell Autocompletions for Users Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/tab/index.mdx Provide instructions for users to set up autocompletions for your CLI tool, either temporarily or permanently. ```bash # One-time setup source <(my-cli complete zsh) # Permanent setup my-cli complete zsh > ~/.my-cli-completion.zsh echo 'source ~/.my-cli-completion.zsh' >> ~/.zshrc ``` -------------------------------- ### Install tab Package Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/tab/index.mdx Install the tab library using your preferred package manager. ```bash npm install @bomb.sh/tab # or pnpm add @bomb.sh/tab # or yarn add @bomb.sh/tab # or bun add @bomb.sh/tab ``` -------------------------------- ### Configuration Setup with Validation Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/guides/examples.mdx Sets up configuration prompts with input validation for port, host, mode, database type, database URL, and feature selection. Handles user cancellations gracefully. ```typescript import { text, select, groupMultiselect, isCancel } from '@clack/prompts'; interface Config { port: number; host: string; mode: 'development' | 'production'; features: string[]; database: { type: 'postgres' | 'mysql' | 'mongodb'; url: string; }; } async function setupConfig(): Promise { const port = await text({ message: 'Enter port number:', placeholder: '3000', validate: (value) => { if (!value) return 'Please enter a value'; const num = parseInt(value); if (isNaN(num)) return 'Please enter a valid number'; if (num < 1 || num > 65535) return 'Port must be between 1 and 65535'; return undefined; }, }); if (isCancel(port)) { console.log('Operation cancelled'); process.exit(0); return null; } const host = await text({ message: 'Enter host:', placeholder: 'localhost', validate: (value) => { if (!value) return 'Host is required'; if (!/^[a-zA-Z0-9.-]+$/.test(value)) return 'Invalid host format'; return undefined; }, }); if (isCancel(host)) { console.log('Operation cancelled'); process.exit(0); return null; } const mode = await select({ message: 'Select mode:', options: [ { value: 'development', label: 'Development', hint: 'For local development' }, { value: 'production', label: 'Production', hint: 'For production deployment' }, ], }); if (isCancel(mode)) { console.log('Operation cancelled'); process.exit(0); return null; } const database = await select({ message: 'Select database:', options: [ { value: 'postgres', label: 'PostgreSQL', hint: 'Advanced open source database' }, { value: 'mysql', label: 'MySQL', hint: 'Most popular open source database' }, { value: 'mongodb', label: 'MongoDB', hint: 'Document-oriented database' }, ], }); if (isCancel(database)) { console.log('Operation cancelled'); process.exit(0); return null; } const dbUrl = await text({ message: 'Enter database URL:', placeholder: `postgresql://user:pass@localhost:5432/db`, validate: (value) => { if (!value) return 'Database URL is required'; try { new URL(value); return undefined; } catch { return 'Invalid URL format'; } }, }); if (isCancel(dbUrl)) { console.log('Operation cancelled'); process.exit(0); return null; } const features = await groupMultiselect({ message: 'Select features:', options: { 'Security': [ { value: 'auth', label: 'Authentication', hint: 'User authentication' }, { value: 'cors', label: 'CORS', hint: 'Cross-origin resource sharing' }, ], 'Monitoring': [ { value: 'logging', label: 'Logging', hint: 'Application logging' }, { value: 'metrics', label: 'Metrics', hint: 'Performance metrics' }, ], 'Development': [ { value: 'swagger', label: 'Swagger', hint: 'API documentation' }, { value: 'debug', label: 'Debug', hint: 'Debugging tools' }, ], }, }); if (isCancel(features)) { console.log('Operation cancelled'); process.exit(0); return null; } return { port: Number(port), host, mode: mode as 'development' | 'production', features, database: { type: database as 'postgres' | 'mysql' | 'mongodb', url: dbUrl, }, }; } ``` -------------------------------- ### Clack Core Prompt Event Handling Example Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/core.mdx Demonstrates how to instantiate and interact with a Clack `Prompt` object, including subscribing to 'value', 'submit', and 'cancel' events. This example requires the `@clack/core` package. ```typescript // @errors: 2304 2314 2345 7006 2353 2459 // @noErrors import { Prompt } from '@clack/core'; // Example usage const p = new Prompt({ render: () => 'Enter your name:' }); // Handle value changes p.on('value', (value?: string) => { console.log('Value changed:', value); }); // Handle submission p.on('submit', (value?: string) => { console.log('Submitted:', value); }); // Handle cancellation p.on('cancel', () => { console.log('Operation cancelled'); }); ``` -------------------------------- ### Low-Level Text Prompt Example Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/basics/getting-started.mdx Demonstrates using the low-level TextPrompt primitive from @clack/core for custom prompt rendering. ```typescript import { TextPrompt, isCancel } from '@clack/core'; const p = new TextPrompt({ render() { return `What's your name?\n${this.value ?? ''}`; }, }); const name = await p.prompt(); if (isCancel(name)) { process.exit(0); } ``` -------------------------------- ### Disable Guide Lines Globally and Per-Prompt Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Demonstrates how to disable guide lines globally using `updateSettings` and per-prompt by passing `withGuide: false`. ```typescript import { text, updateSettings } from '@clack/prompts'; // Disable globally updateSettings({ withGuide: false }); // Or per-prompt const name = await text({ message: 'What is your name?', withGuide: false, // Disable guide lines for this prompt }); ``` -------------------------------- ### Package Manager Completion Example: yarn add Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/tab/index.mdx Illustrates tab completions for the --emoji option in yarn add, displaying boolean options. ```bash yarn add --emoji= # Shows: true, false ``` -------------------------------- ### Build an Interactive CLI Tool with Tasks Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/guides/examples.mdx This example shows how to create a full-featured interactive CLI tool. It uses select for main actions, text for input, confirm for user confirmation, and tasks with spinners to manage asynchronous operations. ```typescript import { text, select, confirm, tasks, spinner, isCancel } from '@clack/prompts'; async function cliTool() { while (true) { const action = await select({ message: 'What would you like to do?', options: [ { value: 'create', label: 'Create new item', hint: 'Create a new resource' }, { value: 'list', label: 'List items', hint: 'View all resources' }, { value: 'delete', label: 'Delete item', hint: 'Remove a resource' }, { value: 'update', label: 'Update item', hint: 'Modify a resource' }, { value: 'exit', label: 'Exit', hint: 'Close the application' }, ], }); if (isCancel(action)) { console.log('Operation cancelled'); process.exit(0); } if (action === 'exit') break; switch (action) { case 'create': { const name = await text({ message: 'Enter item name:', validate: (value) => { if (!value) return 'Name is required'; return undefined; }, }); if (isCancel(name)) { console.log('Operation cancelled'); break; } const spin = spinner(); spin.start('Creating item...'); await tasks([ { title: 'Validating input', task: async () => { // Validation logic return 'Input validated'; }, }, { title: 'Creating resource', task: async () => { // Creation logic return 'Resource created'; }, }, { title: 'Setting up permissions', task: async () => { // Permission setup return 'Permissions configured'; }, }, ]); spin.stop('Item created successfully'); break; } case 'list': { const spin = spinner(); spin.start('Fetching items...'); // Simulate API call await new Promise(resolve => setTimeout(resolve, 1000)); spin.stop('Items fetched successfully'); console.log('Listing items...'); break; } case 'delete': { const item = await text({ message: 'Enter item to delete:', validate: (value) => { if (!value) return 'Item name is required'; return undefined; }, }); if (isCancel(item)) { console.log('Operation cancelled'); break; } const shouldDelete = await confirm({ message: `Are you sure you want to delete ${item}?`, }); if (isCancel(shouldDelete)) { console.log('Operation cancelled'); break; } if (shouldDelete) { const spin = spinner(); spin.start('Deleting item...'); await tasks([ { title: 'Checking dependencies', task: async () => { // Check dependencies return 'Dependencies checked'; }, }, { title: 'Removing item', task: async () => { // Delete logic return 'Item removed'; }, }, { title: 'Cleaning up', task: async () => { // Cleanup logic return 'Cleanup completed'; }, }, ]); spin.stop('Item deleted successfully'); } break; } case 'update': { const item = await text({ message: 'Enter item to update:', validate: (value) => { if (!value) return 'Item name is required'; return undefined; }, }); if (isCancel(item)) { console.log('Operation cancelled'); break; } const spin = spinner(); spin.start('Updating item...'); await tasks([ { title: 'Fetching current state', task: async () => { // Fetch current state return 'Current state fetched'; }, }, { title: 'Applying updates', task: async () => { // Update logic return 'Updates applied'; }, }, { title: 'Verifying changes', task: async () => { // Verification logic return 'Changes verified'; }, }, ]); spin.stop('Item updated successfully'); break; } } } } ``` -------------------------------- ### Example Frontmatter for New Documentation Page Source: https://github.com/bombshell-dev/docs/blob/main/README.md Use this frontmatter structure when creating a new Markdown file for documentation pages. It includes essential metadata like title and description. ```markdown --- title: My New Page description: Description of my new page --- # My New Page Content goes here... ``` -------------------------------- ### Integrate Tab Completions with CAC CLI Framework Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/tab/index.mdx Set up tab completions for a CLI application built with the CAC framework. This example shows how to define custom completions for command options. ```typescript import cac from 'cac'; import tab from '@bomb.sh/tab/cac'; const cli = cac('my-cli'); // Define your CLI cli .command('dev', 'Start dev server') .option('--port ', 'Specify port') .option('--host ', 'Specify host'); // Initialize tab completions const completion = await tab(cli); // Add custom completions for option values const devCommand = completion.commands.get('dev'); const portOption = devCommand?.options.get('port'); if (portOption) { portOption.handler = (complete) => { complete('3000', 'Development port'); complete('8080', 'Production port'); }; } cli.parse(); ``` -------------------------------- ### Test CLI Autocompletions Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/tab/index.mdx Simulate a tab completion request in your terminal to verify the autocompletion setup. ```bash node my-cli.js complete -- dev --port= # Output: --port=3000 Development port # --port=8080 Production port ``` -------------------------------- ### Lazy Loading Prompts Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/guides/best-practices.mdx Load prompts only when they are needed to optimize application startup and resource usage. This example demonstrates lazy loading web-specific prompts based on user selection. ```typescript import { select, isCancel } from '@clack/prompts'; // Mock function for demonstration async function loadWebPrompts() { // This simulates loading web-specific prompts return { setupWebProject: async () => { // Implementation would go here return true; } }; } async function setupProject() { const projectType = await select({ message: 'Project type:', options: [ { value: 'web', label: 'Web Application' }, { value: 'cli', label: 'CLI Tool' }, ], }); if (isCancel(projectType)) { console.log('Operation cancelled'); process.exit(0); } // Only load web-specific prompts if needed if (projectType === 'web') { const { setupWebProject } = await loadWebPrompts(); await setupWebProject(); } } ``` -------------------------------- ### Extend Clack Prompt Class Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/core.mdx Extend the base `Prompt` class to create custom prompts. This example shows how to define a custom prompt with a specific rendering logic. ```typescript // @errors: 2339 import { Prompt } from '@clack/core'; // Example of extending the base Prompt class class CustomPrompt extends Prompt { constructor(options: { message: string }) { super({ ...options, render() { return `${options.message}\n${this.value ?? ''}`; } }); } } ``` -------------------------------- ### Integrate Tab Completions with Commander.js CLI Framework Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/tab/index.mdx Add tab completions to a CLI application built with Commander.js. This example shows how to provide custom suggestions for option values. ```typescript import { Command } from 'commander'; import tab from '@bomb.sh/tab/commander'; const program = new Command('my-cli'); program.version('1.0.0'); // Define commands program .command('serve') .description('Start the server') .option('-p, --port ', 'port to use', '3000') .option('-H, --host ', 'host to use', 'localhost') .action((options) => { console.log('Starting server...'); }); // Initialize tab completions const completion = tab(program); // Add custom completions const serveCommand = completion.commands.get('serve'); const portOption = serveCommand?.options.get('port'); if (portOption) { portOption.handler = (complete) => { complete('3000', 'Default port'); complete('8080', 'Alternative port'); }; } program.parse(); ``` -------------------------------- ### Note with Custom Line Formatting Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Customizes the display of each line within a note by providing a `format` function. This example prepends '→ ' to each line. ```typescript // @errors: 2345 7006 import { note } from '@clack/prompts'; note( 'Line 1\nLine 2\nLine 3', 'Formatted steps', { format: (line: string) => `→ ${line}` } ); ``` -------------------------------- ### Display Progress Bar for Downloads Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/guides/examples.mdx The `progress` prompt displays a progress bar for long-running operations. It can be started, advanced with messages, and stopped upon completion. ```typescript import { progress, intro, outro } from '@clack/prompts'; async function downloadFiles() { intro('File Downloader'); const files = ['package.json', 'README.md', 'src/index.ts', 'tsconfig.json', 'LICENSE']; const prog = progress({ style: 'heavy', max: files.length, size: 30, }); prog.start('Downloading files'); for (let i = 0; i < files.length; i++) { // Simulate download await new Promise(resolve => setTimeout(resolve, 500)); prog.advance(1, `Downloaded ${files[i]}`); } prog.stop('All files downloaded'); outro('Download complete!'); } ``` -------------------------------- ### Generate Package Manager Completion Scripts Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/tab/index.mdx Use npx to generate and install completion scripts for pnpm, npm, yarn, and bun for Zsh, Bash, Fish, and PowerShell shells. Follow the output instructions to source the generated scripts in your shell configuration files. ```bash npx @bomb.sh/tab pnpm zsh > ~/.pnpm-completion.zsh && echo 'source ~/.pnpm-completion.zsh' >> ~/.zshrc npx @bomb.sh/tab npm bash > ~/.npm-completion.bash && echo 'source ~/.npm-completion.bash' >> ~/.bashrc npx @bomb.sh/tab yarn fish > ~/.config/fish/completions/yarn.fish npx @bomb.sh/tab bun powershell > ~/.bun-completion.ps1 && echo '. ~/.bun-completion.ps1' >> $PROFILE ``` -------------------------------- ### Internationalizing Clack Prompts Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Shows how to update global messages and date-related settings for internationalization using `updateSettings`. This allows customization of prompt messages for different languages. The example also demonstrates using the `select` prompt with translated content and handling cancellation. ```typescript import { updateSettings, select, cancel } from '@clack/prompts'; // Update global messages updateSettings({ messages: { cancel: "Operación cancelada", error: "Se ha producido un error", }, date: { monthNames: [ "enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre", ], messages: { required: "Introduce una fecha válida", invalidMonth: "Solo hay 12 meses", invalidDay: (days, month) => `Solo hay ${days} días en ${month}`, afterMin: (min) => `La fecha debe ser el ${min.toISOString().slice(0, 10)} o posterior`, beforeMax: (max) => `La fecha debe ser el ${max.toISOString().slice(0, 10)} o anterior`, }, }, }); // Use the select prompt with translated content const framework = await select({ message: 'Selecciona un framework', options: [ { value: 'next', label: 'Next.js', hint: 'Framework de React' }, { value: 'astro', label: 'Astro', hint: 'Enfocado en contenido' }, { value: 'svelte', label: 'SvelteKit', hint: 'Framework de compilación' }, ] }); // If the user cancels, they'll see the translated message if (!framework) { cancel(); } ``` -------------------------------- ### Conditional Prompts Based on User Selection Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/guides/best-practices.mdx Use conditional logic to display prompts relevant to the user's previous selections. This example shows how to ask for database host and port only when the database type is not SQLite. ```typescript // @errors: 2339 import { text, select, isCancel } from '@clack/prompts'; interface DatabaseConfig { type: 'postgres' | 'mysql' | 'sqlite'; host?: string; port?: number; } async function setupDatabase() { const dbType = await select({ message: 'Select database type:', options: [ { value: 'postgres', label: 'PostgreSQL' }, { value: 'mysql', label: 'MySQL' }, { value: 'sqlite', label: 'SQLite' }, ], }); if (isCancel(dbType)) { console.log('Operation cancelled'); process.exit(0); } const config: DatabaseConfig = { type: dbType, }; // Only ask for host and port if not SQLite if (dbType !== 'sqlite') { const host = await text({ message: 'Database host:', defaultValue: 'localhost', }); if (isCancel(host)) { console.log('Operation cancelled'); process.exit(0); } const port = await text({ message: 'Database port:', defaultValue: dbType === 'postgres' ? '5432' : '3306', validate: (value) => { if (!value) return 'Please enter a value'; const num = parseInt(value); if (isNaN(num)) return 'Please enter a valid number'; if (num < 1 || num > 65535) return 'Port must be between 1 and 65535'; return undefined; }, }); if (isCancel(port)) { console.log('Operation cancelled'); process.exit(0); } config.host = host; config.port = parseInt(port); } return config; } ``` -------------------------------- ### Update and Access Global Settings in Clack Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/core.mdx Demonstrates how to update global settings for Clack prompts, including custom key aliases, disabling guide lines, and internationalization messages. It also shows how to access the current settings. ```typescript import { updateSettings, settings } from '@clack/core'; // Update global settings updateSettings({ // Custom key aliases for navigation aliases: { w: 'up', a: 'left', s: 'down', d: 'right', }, // Disable guide lines globally withGuide: false, // Custom messages for i18n messages: { cancel: 'Operación cancelada', error: 'Se produjo un error', }, }); // Access current settings console.log(settings.messages.cancel); ``` -------------------------------- ### Reusable Prompt Function for Port Input Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/guides/best-practices.mdx Encapsulate common prompt logic into reusable functions for cleaner and more maintainable code. This example creates a function to prompt for a port number with validation. ```typescript import { text, select, isCancel } from '@clack/prompts'; async function promptForPort(defaultPort: string) { const port = await text({ message: 'Enter port number:', defaultValue: defaultPort, validate: (value) => { if (!value) return 'Please enter a value'; const num = parseInt(value); if (isNaN(num)) return 'Please enter a valid number'; if (num < 1 || num > 65535) return 'Port must be between 1 and 65535'; return undefined; }, }); if (isCancel(port)) { console.log('Operation cancelled'); process.exit(0); } return parseInt(port); } // Use the reusable function const serverPort = await promptForPort('3000'); const dbPort = await promptForPort('5432'); ``` -------------------------------- ### Parse Completion Request Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/tab/index.mdx This command demonstrates how tab parses a completion request, typically called by the shell to provide suggestions. The `--port` flag is an example argument. ```bash # Parse completion request (called by shell) my-cli complete -- install --port="" ``` -------------------------------- ### Dynamic Autocomplete Options with Custom Ranking Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx This example demonstrates how to use a function for the `options` property to dynamically generate and rank choices based on user input. It disables the default filter to rely solely on the custom ranking logic. Ensure to import `AutocompletePrompt` and `Option` types for type safety. ```typescript import { autocomplete } from '@clack/prompts'; import type { AutocompletePrompt } from '@clack/core'; import type { Option } from '@clack/prompts'; const pool: Option[] = [ { value: 'next', label: 'Next.js', hint: 'React' }, { value: 'nuxt', label: 'Nuxt', hint: 'Vue' }, { value: 'nest', label: 'NestJS', hint: 'Node' }, ]; function rankByQuery(query: string, items: Option[]): Option[] { const q = query.trim().toLowerCase(); if (!q) return [...items]; return [...items] .filter((o) => { const t = `${o.label ?? ''} ${o.hint ?? ''} ${o.value}`.toLowerCase(); return t.includes(q); }) .sort((a, b) => { const la = (a.label ?? '').toLowerCase(); const lb = (b.label ?? '').toLowerCase(); const sa = la.startsWith(q) ? 0 : 1; const sb = lb.startsWith(q) ? 0 : 1; return sa - sb || la.localeCompare(lb); }); } const picked = await autocomplete({ message: 'Pick a framework', options(this: AutocompletePrompt>) { return rankByQuery(this.userInput, pool); }, filter: (_search, _option) => true, }); ``` -------------------------------- ### Basic Progress Bar with Styles Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Displays a progress bar for long-running operations. Supports 'light', 'heavy', and 'block' styles. Use `start`, `advance`, `message`, and `stop` methods to control the progress. ```typescript import { progress } from '@clack/prompts'; const prog = progress({ style: 'heavy', // 'light', 'heavy', or 'block' max: 100, // Maximum value (default: 100) size: 40, // Width of the progress bar (default: 40) }); prog.start('Processing files'); // Advance the progress bar prog.advance(10); // Advance by 10 steps prog.advance(25, 'Processing images...'); // Advance with a message update // Update just the message prog.message('Almost done...'); // Complete the progress prog.stop('All files processed'); ``` -------------------------------- ### Helpful Error Messages with Validation Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/guides/best-practices.mdx Provide clear and helpful error messages in the `validate` function of text prompts to guide users towards correct input. This example validates a server port number. ```typescript import { text } from '@clack/prompts'; const serverPort = await text({ message: 'Enter port number:', validate: (value) => { if (!value) return 'Please enter a value'; const num = parseInt(value); if (isNaN(num)) return 'Please enter a valid number'; if (num < 1 || num > 65535) return 'Port must be between 1 and 65535'; return undefined; }, }); ``` -------------------------------- ### Using Custom I/O Streams with Prompts Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Illustrates how to provide custom `Readable` input and `Writable` output streams to a prompt. ```typescript import { Writable, Readable } from 'node:stream'; import { text } from '@clack/prompts'; declare const customInput: Readable; declare const customOutput: Writable; const name = await text({ message: 'What is your name?', input: customInput, output: customOutput, }); ``` -------------------------------- ### Select Configuration File with Validation Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/guides/examples.mdx The `path` prompt allows users to navigate the file system with autocomplete. Includes validation to ensure the selected file has a `.json` or `.yaml` extension. ```typescript import { path, isCancel } from '@clack/prompts'; async function selectConfigFile() { const configPath = await path({ message: 'Select a configuration file:', root: process.cwd(), directory: false, validate: (value) => { if (!value?.endsWith('.json') && !value?.endsWith('.yaml')) { return 'Please select a .json or .yaml file'; } return undefined; }, }); if (isCancel(configPath)) { console.log('Operation cancelled'); process.exit(0); } console.log(`Selected config: ${configPath}`); } ``` -------------------------------- ### Clack Text Input with Validation Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/basics/getting-started.mdx Example of using the `text` prompt with a custom validation function to ensure age is a valid number between 0 and 120. ```typescript import { text } from '@clack/prompts'; // TypeScript will ensure the validation function returns the correct type const age = await text({ message: 'Enter your age:', validate: (value) => { if (!value) return 'Please enter a value'; const num = parseInt(value); if (isNaN(num)) return 'Please enter a valid number'; if (num < 0 || num > 120) return 'Age must be between 0 and 120'; return undefined; }, }); ``` -------------------------------- ### Using Clack Log Utilities Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Demonstrates how to use various log functions to display messages with different semantic meanings and styling. Import the log object from '@clack/prompts'. ```typescript import { log } from '@clack/prompts'; log.message('Entering directory "src"'); log.info('No files to update'); log.warn('Directory is empty, skipping'); log.warning('Directory is empty, skipping'); log.error('Permission denied on file src/secret.js'); log.success('Installation complete'); log.step('Check files'); ``` -------------------------------- ### Pick Release Date with Bounds Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/guides/examples.mdx Use the `date` prompt to select a date with a specified format and optional minimum/maximum date bounds. Handles user cancellation gracefully. ```typescript import { date, isCancel, cancel, outro } from '@clack/prompts'; async function pickReleaseDate() { const result = await date({ message: 'Pick a release date', format: 'YMD', minDate: new Date('2026-01-01'), maxDate: new Date('2026-12-31'), }); if (isCancel(result)) { cancel('Operation cancelled.'); process.exit(0); } outro(`Selected: ${result.toISOString().slice(0, 10)}`); } ``` -------------------------------- ### Confirmation Prompt Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx The `confirm` prompt is used to get a boolean (yes/no) answer from the user. It supports custom labels for 'yes' and 'no' and can be configured to have an initial selected value. ```typescript import { confirm } from '@clack/prompts'; const shouldProceed = await confirm({ message: 'Do you want to continue?', }); ``` -------------------------------- ### Import Core Components and Types Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/core.mdx Import prompt classes, layout helpers, utilities, and types from the @clack/core package for use in your CLI application. ```typescript import { // Prompt classes TextPrompt, SelectPrompt, ConfirmPrompt, PasswordPrompt, MultiSelectPrompt, GroupMultiSelectPrompt, SelectKeyPrompt, AutocompletePrompt, DatePrompt, // Layout helpers block, getColumns, getRows, wrapTextWithPrefix, // Utilities isCancel, updateSettings, settings, // Types type ClackSettings, type PromptOptions, type ConfirmOptions, type PasswordOptions, type MultiSelectOptions, type GroupMultiSelectOptions, type SelectKeyOptions, type AutocompleteOptions, type DateFormat, type DateOptions, type DateParts, } from '@clack/core'; ``` -------------------------------- ### Simple Select Prompt Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Use `select` for a single choice from a list of options. Persistent keyboard hints are shown by default. ```typescript import { select } from '@clack/prompts'; const framework = await select({ message: 'Pick a framework', options: [ { value: 'next', label: 'Next.js', hint: 'React framework' }, { value: 'astro', label: 'Astro', hint: 'Content-focused' }, { value: 'svelte', label: 'SvelteKit', hint: 'Compile-time framework' }, ], maxItems: 5, // Maximum number of items to display at once }); ``` -------------------------------- ### SelectKey Prompt for Key-Based Selection Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Use `selectKey` for prompts where users select options by pressing a specific key, useful for compact menus. It requires importing `isCancel` to handle user cancellation. ```typescript import { selectKey, isCancel } from '@clack/prompts'; const action = await selectKey({ message: 'What next?', options: [ { value: 'y', label: 'Continue' }, { value: 'n', label: 'Stop' }, { value: 's', label: 'Skip', hint: 'optional' }, ], caseSensitive: false, }); if (isCancel(action)) { process.exit(0); } ``` -------------------------------- ### Using `spinner` for Loading Indicators Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx The `spinner` function provides a visual loading indicator for long-running operations. It supports methods like `start`, `message`, `stop`, `cancel`, and `error` to indicate different states. ```typescript import { spinner } from '@clack/prompts'; const spin = spinner(); spin.start('Loading'); // Do something spin.message('Finishing'); // Do more things spin.stop('Done'); ``` -------------------------------- ### Selection Menu with Clack Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/guides/examples.mdx Demonstrates a selection menu prompt, allowing users to choose from a list of options. Use this when presenting predefined choices. ```typescript import { select, isCancel } from '@clack/prompts'; const framework = await select({ message: 'Choose a framework:', options: [ { value: 'react', label: 'React', hint: 'A JavaScript library for building user interfaces' }, { value: 'vue', label: 'Vue', hint: 'The Progressive JavaScript Framework' }, { value: 'svelte', label: 'Svelte', hint: 'Cybernetically enhanced web apps' }, ], }); if (isCancel(framework)) { console.log('Operation cancelled'); process.exit(0); } console.log(`You selected ${framework}`); ``` -------------------------------- ### Displaying an Introduction Message with `intro` Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx The `intro` function displays a title at the beginning of an interaction. It supports ANSI escape sequences for custom styling. ```typescript import { intro } from '@clack/prompts'; intro('Welcome to clack'); ``` -------------------------------- ### Basic Text Input with Clack Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/guides/examples.mdx Demonstrates a basic text input prompt. Use this for simple string collection from the user. ```typescript import { text, isCancel } from '@clack/prompts'; const name = await text({ message: "What is your name?", placeholder: "Jane Doe" }) ``` -------------------------------- ### Parse CLI Arguments with Configuration Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/args/api.mdx Parses raw CLI parameters using provided configuration options like defaults, aliases, and types. Use this for general argument parsing. ```ts import { parse } from "@bomb.sh/args" const args = parse(process.argv, { default: { a: 1, b: 2, c: "value" }, alias: { h: "help" }, boolean: ["foo", "bar"], string: ["baz", "qux"], array: ["input"], }); ``` -------------------------------- ### Basic Autocomplete Prompt Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Use this snippet to create a basic autocomplete prompt with a predefined list of options. It requires importing the `autocomplete` function from `@clack/prompts`. ```typescript import { autocomplete } from '@clack/prompts'; const framework = await autocomplete({ message: 'Search for a framework', options: [ { value: 'next', label: 'Next.js', hint: 'React framework' }, { value: 'astro', label: 'Astro', hint: 'Content-focused' }, { value: 'svelte', label: 'SvelteKit', hint: 'Compile-time framework' }, { value: 'remix', label: 'Remix', hint: 'Full stack framework' }, { value: 'nuxt', label: 'Nuxt', hint: 'Vue framework' }, ], placeholder: 'Type to search...', maxItems: 5, }); ``` -------------------------------- ### Stream Message and Info with File Read Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Demonstrates streaming a file's content as a message and then displaying asynchronous step-by-step information using generators. This is useful for showing the progress of operations involving file I/O or complex asynchronous tasks. ```typescript import { stream } from "@clack/prompts"; import * as fs from "node:fs"; await stream.message(fs.createReadStream('./banner.txt', { encoding: 'utf-8' })); await stream.info((async function*() { yield 'Open file...'; // Open file yield ' \x1b[32mOK\x1b[39m\n'; yield 'Parsing file...'; // Parse data yield ' \x1b[32mOK\x1b[39m'; return; })()); await stream.step([ 'Job1...', ' \x1b[32mdone\x1b[39m\n', 'Job2...', ' \x1b[32mdone\x1b[39m\n', 'Job3...', ' \x1b[32mdone\x1b[39m', ]); ``` -------------------------------- ### Path Selection Prompt Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Utilize the path prompt for file and directory selection, extending autocomplete functionality. Specify the message, root directory, and whether to filter for directories only. ```typescript import { path } from '@clack/prompts'; const selectedPath = await path({ message: 'Select a file:', root: process.cwd(), // Starting directory directory: false, // Set to true to only show directories }); ``` -------------------------------- ### Multiselect Prompt Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/packages/prompts.mdx Use `multiselect` to allow users to select multiple options from a list. Persistent keyboard hints are shown by default. ```typescript import { multiselect } from '@clack/prompts'; const framework = await multiselect({ message: 'Pick a framework', options: [ { value: { framework: 'Next', language: 'React' }, label: 'Next.js', hint: 'React framework' }, { value: { framework: null, language: 'Astro' }, label: 'Astro', hint: 'Content-focused' }, { value: { framework: 'Sveltekit', language: 'Svelte' }, label: 'SvelteKit', hint: 'Compile-time framework' }, ], maxItems: 5, // Maximum number of items to display at once }); ``` -------------------------------- ### Batch Operations with Promise.all Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/clack/guides/best-practices.mdx Use Promise.all for parallel execution when dealing with multiple prompts to improve performance. ```typescript import { text } from '@clack/prompts'; const [userName, userEmail, userAge] = await Promise.all([ text({ message: 'Name:' }), text({ message: 'Email:' }), text({ message: 'Age:' }), ]); ``` -------------------------------- ### Parse Options as Strings Source: https://github.com/bombshell-dev/docs/blob/main/src/content/docs/args/api.mdx Indicates that an option expects a string value. The argument following the option is treated as its value, or an empty string if none is available. Use this for options that require textual input. ```ts import { parse } from "@bomb.sh/args" const args = parse(process.argv, { string: ['get', 'user'], }); ```