Développement d'Interface en Ligne de Commande

VérifiéSûr

Fournit une expertise dans la création d'interfaces en ligne de commande : analyse d'arguments, sous-commandes, invites interactives et motifs de conception CLI. Aide à créer des outils CLI, des utilitaires ou des applications terminal interactives. Couvre les meilleures pratiques en Go, Python, Node.js, Rust, etc.

Spar Skills Guide Bot
DeveloppementIntermédiaire
02/06/2026
Claude CodeCursorWindsurfCopilotCodex
#cli#command-line#argument-parsing#interactive-prompts#best-practices

Recommandé pour

Synthèse automatique

Ce skill fournit des directives complètes pour le développement d'interfaces en ligne de commande (CLI), incluant l'analyse d'arguments, les sous-commandes, les invites interactives et les bonnes pratiques.

Points forts

  • Couverture de multiples langages de programmation (Go, Python, Node.js, Rust) et leurs bibliothèques CLI respectives.
  • Inclusion de concepts avancés comme les sous-commandes, les menus de sélection et les barres de progression.
  • Exemples de code concrets et modèles de développement.
  • Accent sur l'expérience utilisateur (aide, messages d'erreur, auto-complétion).

Limites

  • Ne détaille pas la distribution ou le packaging des outils CLI.
  • Suppose une familiarité avec au moins un des langages listés.
  • Les nuances spécifiques aux plates-formes ne sont pas exhaustivement traitées.
Quand l'utiliser

Utilisez ce skill lorsque vous devez créer un nouvel outil en ligne de commande structuré avec analyse d'arguments, sous-commandes et fonctionnalités interactives.

Quand l'éviter

Évitez ce skill si vous avez besoin d'un script simple avec des arguments minimaux ; une approche rapide sans framework lourd est alors préférable.

Analyse de sécurité

Sûr
Score qualité92/100

This skill is purely an instructional guide on CLI development with code examples. It contains no executable commands, no destructive operations, no data exfiltration, and no obfuscation.

Aucun point d'attention détecté

Comment cette analyse est faite

Exemples

Go CLI with Cobra for to-do management
Write a Go CLI tool using Cobra that manages to-do items with add, list, and delete subcommands.
Python CLI with Click for file reading
Create a Python CLI using Click that accepts a filename and optional verbosity flag, and echoes the file content.
Interactive prompts in Node.js CLI
Explain how to implement interactive prompts and selection menus in a Node.js CLI with Commander.

name: cli description: Expert command-line interface development including argument parsing, subcommands, interactive prompts, and CLI best practices

User Input

$ARGUMENTS

You MUST consider the user input before proceeding (if not empty).

Outline

You are a Command Line Interface (CLI) expert specializing in argument parsing, subcommands, interactive prompts, and CLI best practices. Use this skill when the user needs help with:

  • Creating command-line tools and utilities
  • Implementing argument parsing and validation
  • Building interactive CLI applications
  • Designing CLI help systems and documentation
  • CLI testing and distribution
  • Cross-platform CLI development

CLI Libraries and Frameworks

1. Go CLI Libraries

  • Cobra: Powerful CLI framework for Go applications
  • urfave/cli: Simple, fast, and fun CLI applications
  • flag: Standard library flag package
  • pflag: POSIX-compliant flag package
  • kingpin: Deprioritized but still useful

2. Python CLI Libraries

  • Click: Composable command interface creation
  • argparse: Standard library argument parser
  • docopt: Command-line interface descriptions
  • typer: Modern CLI library with type hints
  • fire: Automatic CLI generation

3. Node.js CLI Libraries

  • Commander.js: Complete solution for Node.js command-line programs
  • yargs: Command-line argument parser
  • oclif: CLI framework for Node.js
  • meow: Helper for CLI apps
  • minimist: Argument parser

4. Rust CLI Libraries

  • clap: Command Line Argument Parser
  • structopt: Derive-based argument parser (deprecated, use clap)
  • argh: Fast and simple argument parser
  • lexopt: Minimalist argument parser

Core CLI Concepts

1. Argument Parsing

  • Positional arguments: Required arguments in specific positions
  • Optional flags: Optional parameters with single/double dashes
  • Subcommands: Nested command structures
  • Environment variables: Configuration via environment
  • Config files: Persistent configuration storage
  • Validation: Type checking and value validation

2. Interactive Elements

  • Prompts: User input with validation
  • Confirmations: Yes/no confirmations
  • Selection menus: Choose from predefined options
  • Progress bars: Show operation progress
  • Spinners: Indicate ongoing work

3. User Experience

  • Help systems: Auto-generated help text
  • Error messages: Clear, actionable error reporting
  • Auto-completion: Tab completion for commands
  • Colors and formatting: Readable output formatting
  • Consistency: Follow CLI conventions

CLI Development Patterns

Go with Cobra Example

package main

import (
    "fmt"
    "os"
    "github.com/spf13/cobra"
    "github.com/spf13/viper"
)

var rootCmd = &cobra.Command{
    Use:   "myapp [command]",
    Short: "My application does awesome things",
    Long: `My application is a CLI tool that demonstrates 
best practices for command-line interface development.`,
}

var configCmd = &cobra.Command{
    Use:   "config [key] [value]",
    Short: "Get or set configuration values",
    Long:  `Get or set configuration values. If only key is provided,
gets the value. If both key and value are provided, sets the value.`,
    Args:  cobra.MinimumNArgs(1),
    Run:   runConfig,
}

var (
    configFile string
    verbose    bool
    output     string
)

func init() {
    cobra.OnInitialize(initConfig)
    
    rootCmd.PersistentFlags().StringVarP(&configFile, "config", "c", "", "config file (default is $HOME/.myapp.yaml)")
    rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output")
    rootCmd.PersistentFlags().StringVarP(&output, "output", "o", "json", "output format (json|yaml|text)")
    
    rootCmd.AddCommand(configCmd)
}

func initConfig() {
    if configFile != "" {
        viper.SetConfigFile(configFile)
    } else {
        home, err := os.UserHomeDir()
        if err != nil {
            fmt.Println(err)
            os.Exit(1)
        }
        
        viper.AddConfigPath(home)
        viper.SetConfigType("yaml")
        viper.SetConfigName(".myapp")
    }
    
    viper.AutomaticEnv()
    
    if err := viper.ReadInConfig(); err == nil {
        fmt.Println("Using config file:", viper.ConfigFileUsed())
    }
}

func runConfig(cmd *cobra.Command, args []string) {
    switch len(args) {
    case 1:
        // Get value
        value := viper.GetString(args[0])
        if value == "" {
            fmt.Printf("Config key '%s' not found\n", args[0])
            os.Exit(1)
        }
        fmt.Printf("%s: %s\n", args[0], value)
    case 2:
        // Set value
        viper.Set(args[0], args[1])
        fmt.Printf("Set %s = %s\n", args[0], args[1])
    default:
        fmt.Println("Usage: myapp config [key] [value]")
        os.Exit(1)
    }
}

func main() {
    if err := rootCmd.Execute(); err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
}

Python with Click Example

#!/usr/bin/env python3
import click
import json
import sys
from pathlib import Path

@click.group()
@click.option('--config', '-c', type=click.Path(), help='Configuration file path')
@click.option('--verbose', '-v', is_flag=True, help='Enable verbose output')
@click.pass_context
def cli(ctx, config, verbose):
    """My application does awesome things."""
    ctx.ensure_object(dict)
    ctx.obj['config'] = config
    ctx.obj['verbose'] = verbose

@cli.command()
@click.argument('filename', type=click.Path(exists=True))
@click.option('--format', '-f', 
              type=click.Choice(['json', 'yaml', 'text']), 
              default='text', 
              help='Output format')
@click.pass_context
def process(ctx, filename, format):
    """Process a file and output results."""
    verbose = ctx.obj.get('verbose', False)
    
    if verbose:
        click.echo(f"Processing file: {filename}")
    
    try:
        with open(filename, 'r') as f:
            content = f.read()
        
        # Process the content
        result = process_content(content)
        
        # Output in requested format
        if format == 'json':
            click.echo(json.dumps(result, indent=2))
        elif format == 'yaml':
            import yaml
            click.echo(yaml.dump(result))
        else:
            click.echo(str(result))
            
    except Exception as e:
        click.echo(f"Error: {e}", err=True)
        sys.exit(1)

@cli.command()
@click.argument('key')
@click.argument('value', required=False)
@click.pass_context
def config(ctx, key, value):
    """Get or set configuration values."""
    config_file = ctx.obj.get('config') or get_default_config_path()
    
    if value:
        set_config_value(config_file, key, value)
        click.echo(f"Set {key} = {value}")
    else:
        value = get_config_value(config_file, key)
        if value:
            click.echo(f"{key} = {value}")
        else:
            click.echo(f"Config key '{key}' not found")
            sys.exit(1)

def process_content(content):
    """Example content processing function."""
    lines = content.split('\n')
    return {
        'lines': len(lines),
        'chars': len(content),
        'words': len(content.split())
    }

if __name__ == '__main__':
    cli()

Rust with Clap Example

use clap::{Parser, Subcommand};
use serde::{Deserialize, Serialize};
use std::fs;
use std::io;

#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Cli {
    #[arg(short, long, default_value = "config.yaml")]
    config: String,
    
    #[arg(short, long, action = clap::ArgAction::Count)]
    verbose: u8,
    
    #[command(subcommand)]
    command: Commands,
}

#[derive(Subcommand)]
enum Commands {
    Process(ProcessCommand),
    Config(ConfigCommand),
}

#[derive(Parser)]
struct ProcessCommand {
    /// Input file to process
    #[arg(value_name = "FILE")]
    file: String,
    
    /// Output format
    #[arg(short, long, default_value = "text")]
    format: String,
}

#[derive(Parser)]
struct ConfigCommand {
    /// Configuration key to get/set
    key: String,
    
    /// Configuration value to set
    value: Option<String>,
}

fn main() {
    let cli = Cli::parse();
    
    match cli.command {
        Commands::Process(cmd) => process_file(cmd, &cli),
        Commands::Config(cmd) => handle_config(cmd, &cli),
    }
}

fn process_file(cmd: ProcessCommand, cli: &Cli) {
    if cli.verbose > 0 {
        println!("Processing file: {}", cmd.file);
    }
    
    match fs::read_to_string(&cmd.file) {
        Ok(content) => {
            let result = analyze_content(&content);
            
            match cmd.format.as_str() {
                "json" => println!("{}", serde_json::to_string_pretty(&result).unwrap()),
                "yaml" => println!("{}", serde_yaml::to_string(&result).unwrap()),
                _ => println!("{:?}", result),
            }
        }
        Err(e) => {
            eprintln!("Error reading file: {}", e);
            std::process::exit(1);
        }
    }
}

fn handle_config(cmd: ConfigCommand, cli: &Cli) {
    match cmd.value {
        Some(value) => set_config_value(&cli.config, &cmd.key, &value),
        None => {
            match get_config_value(&cli.config, &cmd.key) {
                Some(value) => println!("{} = {}", cmd.key, value),
                None => {
                    eprintln!("Config key '{}' not found", cmd.key);
                    std::process::exit(1);
                }
            }
        }
    }
}

#[derive(Serialize, Deserialize)]
struct ContentAnalysis {
    lines: usize,
    chars: usize,
    words: usize,
}

fn analyze_content(content: &str) -> ContentAnalysis {
    ContentAnalysis {
        lines: content.lines().count(),
        chars: content.chars().count(),
        words: content.split_whitespace().count(),
    }
}

Interactive CLI Patterns

Confirmation Prompts (Python with Click)

import click

@click.command()
def deploy():
    """Deploy the application."""
    
    if not click.confirm('This will deploy to production. Continue?'):
        click.echo('Deployment cancelled.')
        return
    
    with click.progressbar(length=100, label='Deploying') as bar:
        for i in range(100):
            time.sleep(0.1)
            bar.update(1)
    
    click.echo('Deployment complete!')

@click.command()
@click.option('--force', is_flag=True, help='Skip confirmation')
def delete(force):
    """Delete resources."""
    
    if not force:
        if not click.confirm('This will delete all resources. Continue?'):
            click.echo('Deletion cancelled.')
            return
    
    # Perform deletion
    click.echo('Resources deleted.')

Interactive Selection (Node.js with Inquirer)

const inquirer = require('inquirer');
const program = require('commander');

program
    .version('1.0.0')
    .command('setup')
    .description('Interactive setup wizard')
    .action(async () => {
        const answers = await inquirer.prompt([
            {
                type: 'input',
                name: 'name',
                message: 'What is your project name?',
                validate: input => input.length > 0 || 'Project name is required'
            },
            {
                type: 'list',
                name: 'template',
                message: 'Choose a template:',
                choices: ['basic', 'advanced', 'minimal']
            },
            {
                type: 'checkbox',
                name: 'features',
                message: 'Select features:',
                choices: ['database', 'auth', 'logging', 'testing']
            }
        ]);
        
        console.log('Setup complete with:', answers);
        // Continue setup...
    });

program.parse(process.argv);

CLI Testing Patterns

Go CLI Testing

package main

import (
    "bytes"
    "os"
    "strings"
    "testing"
    "github.com/spf13/cobra"
)

func TestRootCommand(t *testing.T) {
    tests := []struct {
        name     string
        args     []string
        expected string
        error    bool
    }{
        {
            name:     "help flag",
            args:     []string{"--help"},
            expected: "myapp does awesome things",
            error:    false,
        },
        {
            name:     "invalid command",
            args:     []string{"invalid"},
            expected: "",
            error:    true,
        },
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            // Capture output
            buf := new(bytes.Buffer)
            rootCmd.SetOut(buf)
            rootCmd.SetErr(buf)
            
            // Set arguments
            rootCmd.SetArgs(tt.args)
            
            // Execute command
            err := rootCmd.Execute()
            
            output := buf.String()
            
            if tt.error && err == nil {
                t.Errorf("expected error but got none")
            }
            if !tt.error && err != nil {
                t.Errorf("unexpected error: %v", err)
            }
            if !strings.Contains(output, tt.expected) {
                t.Errorf("expected output to contain %q, got %q", tt.expected, output)
            }
        })
    }
}

Python CLI Testing

import pytest
from click.testing import CliRunner
from myapp import cli

def test_process_command(tmp_path):
    """Test the process command."""
    runner = CliRunner()
    
    # Create test file
    test_file = tmp_path / "test.txt"
    test_file.write_text("test content\n")
    
    # Run command
    result = runner.invoke(cli.process, [str(test_file)])
    
    assert result.exit_code == 0
    assert "lines: 1" in result.output
    assert "chars: 12" in result.output

def test_config_command():
    """Test the config command."""
    runner = CliRunner()
    
    # Test getting value
    result = runner.invoke(cli.config, ['test.key'])
    assert result.exit_code == 0
    
    # Test setting value
    result = runner.invoke(cli.config, ['test.key', 'test.value'])
    assert result.exit_code == 0
    assert "Set test.key = test.value" in result.output

CLI Best Practices

1. Command Design

  • Use descriptive command names (verbs are good)
  • Follow Unix conventions (short options, long options)
  • Provide help text and examples
  • Support configuration files and environment variables
  • Handle errors gracefully

2. Output Formatting

  • Support multiple output formats (JSON, YAML, plain text)
  • Use colors sparingly and respect NO_COLOR environment
  • Provide progress indicators for long operations
  • Format numbers with appropriate units

3. User Experience

  • Implement auto-completion where possible
  • Provide clear error messages with suggestions
  • Use confirmation prompts for destructive operations
  • Support verbose and quiet modes

4. Distribution

  • Create single-binary executables where possible
  • Provide installation instructions
  • Include man pages or help documentation
  • Consider packaging for different platforms

When to Use This Skill

Use this skill when you need to:

  • Build command-line tools and utilities
  • Create CLI interfaces for existing applications
  • Design interactive command-line applications
  • Implement argument parsing and validation
  • Add help systems and documentation to CLI tools
  • Test CLI applications
  • Package and distribute CLI tools

Always prioritize:

  • Clear, intuitive command structures
  • Comprehensive error handling
  • Cross-platform compatibility
  • Rich user experience when appropriate
  • Comprehensive testing coverage

Du fichier au premier essai

Le téléchargement contient exactement le contenu affiché sur cette fiche. Cette copie peut différer de la dernière version du dépôt source.

Consulter la source et ses fichiers annexes

Ce téléchargement contient uniquement SKILL.md. Les scripts, références, modèles et dépendances éventuels ne sont pas inclus. Récupérez les fichiers nécessaires depuis la source en conservant leur arborescence avant de poursuivre.

1. Télécharger le fichier

Télécharger SKILL.md

Depuis la racine d’un projet de test, enregistrez le fichier sous .skill-downloads/command-line-interface-development-mm8o5123/SKILL.md, ou utilisez la commande suivante. Ce dossier sert à examiner la skill avant son installation.

Commande pour macOS/Linux ou WSL : un shell POSIX et curl sont nécessaires. Sous Windows sans WSL, utilisez le bouton de téléchargement et créez le dossier manuellement.

mkdir -p '.skill-downloads/command-line-interface-development-mm8o5123' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/command-line-interface-development-mm8o5123/download' --output '.skill-downloads/command-line-interface-development-mm8o5123/SKILL.md.part' && mv '.skill-downloads/command-line-interface-development-mm8o5123/SKILL.md.part' '.skill-downloads/command-line-interface-development-mm8o5123/SKILL.md'

2. Vérifier les prérequis

Lisez SKILL.md avant de l’utiliser. Si le fichier cite des scripts ou services externes, examinez-les et préparez les accès nécessaires dans votre environnement de test.

Aucune section de prérequis reconnue dans ce fichier. Cela ne signifie pas qu’il est autonome : les bibliothèques, outils et accès peuvent être cités ailleurs dans le contenu ou dans le dépôt source.

Les plateformes de la fiche sont des indications du catalogue. Les chemins ci-dessous suivent la documentation des outils ; ils ne prouvent pas que cette skill y a été exécutée. Aucune version minimale de ces outils n’est attestée pour cette fiche.

3. Charger la skill

Après vérification, copiez le dossier complet dans le projet avec l’une des commandes ci-dessous, puis ouvrez une nouvelle session de l’outil. La commande s’arrête si un dossier du même nom existe déjà : comparez les fichiers avant de le remplacer.

Claude Code
test -f '.skill-downloads/command-line-interface-development-mm8o5123/SKILL.md' && test -s '.skill-downloads/command-line-interface-development-mm8o5123/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/cli' && cp -R '.skill-downloads/command-line-interface-development-mm8o5123' '.claude/skills/cli'

Cursor
test -f '.skill-downloads/command-line-interface-development-mm8o5123/SKILL.md' && test -s '.skill-downloads/command-line-interface-development-mm8o5123/SKILL.md' && mkdir -p '.cursor/skills' && test ! -e '.cursor/skills/cli' && cp -R '.skill-downloads/command-line-interface-development-mm8o5123' '.cursor/skills/cli'

Codex
test -f '.skill-downloads/command-line-interface-development-mm8o5123/SKILL.md' && test -s '.skill-downloads/command-line-interface-development-mm8o5123/SKILL.md' && mkdir -p '.agents/skills' && test ! -e '.agents/skills/cli' && cp -R '.skill-downloads/command-line-interface-development-mm8o5123' '.agents/skills/cli'

OpenSkills

OpenSkills doit déjà être installé. La procédure locale install/read est contrôlée avec OpenSkills 1.5.0, qui exige Node.js ≥ 20.6.0. Aucun slug du catalogue n’est résolu automatiquement.

Installation officielle d’OpenSkills
openskills install './.skill-downloads/command-line-interface-development-mm8o5123'

openskills read 'command-line-interface-development-mm8o5123'

La lecture doit afficher le contenu du fichier installé et son dossier de base. Elle ne lance ni la skill ni ses dépendances.

Pour un agent qui lit AGENTS.md, synchronisez ensuite l’index. Cette commande modifie AGENTS.md : relisez le diff avant de l’utiliser.

openskills sync

Mode manuel ou autre outil : joignez SKILL.md à une conversation, ou ouvrez-le dans un agent capable de lire les fichiers. Ajoutez les ressources annexes nécessaires. Il n’existe pas de dossier universel reconnu par tous les outils.

4. Faire un premier essai

Utilisez une entrée courte et fictive : un endpoint d’API, un petit document ou un brief d’interface. Dans une nouvelle conversation, joignez le fichier ou donnez son chemin à l’agent, puis adaptez cette demande :

Lis .skill-downloads/command-line-interface-development-mm8o5123/SKILL.md et applique ses instructions à cet exemple : [décrire une entrée de test]. Indique les fichiers, dépendances ou accès qui manquent. Produis le résultat demandé par la skill sans inventer de données ni exécuter de script non examiné.

Résultat attendu : une sortie correspondant aux instructions de la skill, ou une liste précise des prérequis manquants. Une simple confirmation de lecture ne valide pas le premier usage. Si une ressource externe est indisponible, ce parcours reste à tester.

Skills similaires