Guía Completa de Construcción de CLI
En este artículo, voy a abordar una guía completa sobre cómo construir una CLI (Command Line Interface) profesional, que sea fácil de usar y, principalmente, fácil de integrar por otras aplicaciones. Si nunca has construido una CLI antes, no te preocupes — vamos a empezar desde cero.
¿Qué es una CLI?
CLI significa Command Line Interface (Interfaz de
Línea de Comandos). Es ese programa que utilizas escribiendo comandos en
la terminal, como git, npm,
docker, pip, entre otros. A diferencia de los
programas con interfaz gráfica (GUI), las CLIs se controlan por texto,
lo que las hace extremadamente potentes, automatizables y fáciles de
integrar con otros sistemas.
Entendiendo el ARGV
Antes que nada, necesitas entender qué es el argv. La
respuesta es simple: argv es un array de strings que contiene
los argumentos pasados al programa. Todo lo que se escribió en
la terminal se separa por espacios y se transforma en este array.
argv[0]→ nombre del programa (o del runtime + script)argv[1]→ primer argumentoargv[2]→ segundo argumento- Y así sucesivamente…
Cómo funciona argv en diferentes lenguajes
En lenguajes interpretados (como Python), el
argv[0] es el nombre de tu script, y los argumentos
comienzan a partir de argv[1].
En lenguajes compilados (como C, C++, Go, Rust), el
argv[0] es el nombre del ejecutable compilado.
Ejemplo en Python
import sys
print(sys.argv)Ejecuta:
python3 script.py arg1 arg2 arg3Salida:
['script.py', 'arg1', 'arg2', 'arg3']
Ejemplo en C
#include <stdio.h>
int main(int argc, char *argv[]) {
for (int i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}Compila y ejecuta:
gcc programa.c -o programa
./programa arg1 arg2 arg3Salida:
argv[0] = ./programa
argv[1] = arg1
argv[2] = arg2
argv[3] = arg3
Construyendo tu propia CLI
Para construir una CLI sólida y profesional, sigue los siguientes pasos:
1. Define las Actions (Acciones)
El primer argumento (después del nombre del programa) debe ser la action, es decir, la acción que el usuario desea ejecutar.
mi_programa <action> [flags y argumentos]Usemos git como ejemplo. Tiene varias actions como
commit, pull, push,
rebase, etc. Mira el siguiente comando:
git commit -m "mensaje del commit"En este ejemplo: - commit → es la
action - -m → es una flag
- "mensaje del commit" → es el valor de la
flag
Consejo para principiantes: Piensa en la action como una función, y en las flags como los parámetros de esa función.
Cómo implementar actions
La forma más sencilla de implementar actions es usar una estructura condicional para verificar el primer argumento:
Ejemplo en Python:
import sys
def action_hello():
print("¡Hola! ¡Bienvenido a mi CLI!")
def action_version():
print("mi_programa v1.0.0")
if len(sys.argv) < 2:
print("Uso: mi_programa <action>")
print("Usa 'mi_programa help' para ver las acciones disponibles.")
sys.exit(1)
action = sys.argv[1]
if action == "hello":
action_hello()
elif action == "version":
action_version()
else:
print(f"Acción desconocida: {action}")
print("Usa 'mi_programa help' para ver las acciones disponibles.")2. Define las Flags
Ahora que has separado cada acción posible de tu CLI, debes definir las flags que cada action puede recibir. Las flags modifican el comportamiento de una action.
Existen dos tipos de flags:
Boolean Flags (flags sin valor)
Son flags que no reciben valor — solo indican que algo debe ser
activado. Generalmente comienzan con --.
git push --forceAquí, --force es una flag booleana que indica que el
push debe ser forzado.
Value Flags (flags con valor)
Son flags que reciben un valor inmediatamente después. Pueden usar
- (forma corta) o -- (forma larga).
git commit -m "mensaje del commit"
git commit --message "mensaje del commit"Aquí, -m (o --message) es una flag que
recibe el mensaje como valor.
Cómo implementar flags
Ejemplo en Python:
import sys
def parse_flags(args):
"""Analiza los argumentos y retorna un diccionario de flags."""
flags = {}
i = 0
while i < len(args):
if args[i].startswith("--"):
flag_name = args[i][2:] # Elimina el prefijo --
# Verifica si es una boolean flag o una value flag
if i + 1 < len(args) and not args[i + 1].startswith("-"):
flags[flag_name] = args[i + 1]
i += 2
else:
flags[flag_name] = True
i += 1
elif args[i].startswith("-"):
flag_name = args[i][1:] # Elimina el prefijo -
if i + 1 < len(args) and not args[i + 1].startswith("-"):
flags[flag_name] = args[i + 1]
i += 2
else:
flags[flag_name] = True
i += 1
else:
i += 1
return flags
# Ejemplo de uso:
# mi_programa commit -m "mensaje" --force
action = sys.argv[1]
flags = parse_flags(sys.argv[2:])
print(f"Action: {action}")
print(f"Flags: {flags}")3. Define un Help (Ayuda)
Todo programa de línea de comandos necesita una
acción help. Debe listar todas las acciones y flags
disponibles, con una descripción clara de cada una.
mi_programa helpEjemplo de salida:
mi_programa - Una herramienta increíble para gestionar tareas
Uso: mi_programa <action> [flags]
Acciones disponibles:
help Muestra este mensaje de ayuda
version Muestra la versión del programa
add Añade una nueva tarea
--title <texto> Título de la tarea (obligatorio)
--priority <n> Prioridad de 1 a 5 (por defecto: 3)
list Lista todas las tareas
--filter <status> Filtra por estado (pendiente, completada)
--limit <n> Limita el número de resultados
done Marca una tarea como completada
--id <id> ID de la tarea (obligatorio)
Ejemplos:
mi_programa add --title "Comprar café" --priority 1
mi_programa list --filter pendiente
mi_programa done --id 42
Consejo: Siempre incluye ejemplos prácticos en la ayuda. Esto ayuda mucho a los principiantes.
4. Define un Version (Versión)
Crea una action llamada version que muestre la versión
actual de tu CLI. Esto es esencial para debugging y para que los
usuarios sepan qué versión están usando.
mi_programa versionEjemplo de salida:
mi_programa v1.0.0
Consejo: Sigue el estándar Semantic Versioning (SemVer) para numerar tus versiones:
MAJOR.MINOR.PATCH(ej:1.2.3).
5. Define Stored Configs (Configuraciones Almacenadas)
A menudo es conveniente que tu CLI almacene configuraciones del
usuario para que no necesite escribirlas cada vez. Esto es muy común —
piensa en git config o en npm config.
Ejemplo:
mi_programa config-user --username "Mateus" --email "mateus@gmail.com" --password "contraseña"Una vez configurado, en las siguientes acciones puedes solicitar solo la flag identificadora:
mi_programa set-profile-picture --username "Mateus" --picture foto.png¿Dónde almacenar las configuraciones?
Es muy recomendable que guardes todos los datos en
una sola ubicación, preferiblemente en una carpeta oculta en el
home del usuario (los directorios que comienzan con
. son ocultos en Linux/macOS).
Ejemplo: las configuraciones podrían guardarse en el archivo
~/.mi_programa/config.json:
{
"username": "Mateus",
"email": "mateus@gmail.com",
"password": "test"
}Formas comunes de almacenamiento: - JSON → simple y ampliamente soportado - SQLite → ideal para datos más complejos o relacionales - TOML/YAML → bueno para archivos de configuración legibles - Archivos de texto → para datos muy simples
6. Tratamiento de Errores
Una CLI profesional debe tratar los errores de forma clara y amigable. Nunca dejes que el programa “se rompa” con un error incomprensible.
Buenas prácticas:
import sys
if len(sys.argv) < 2:
print("Error: ninguna acción proporcionada.")
print("Uso: mi_programa <action> [flags]")
print("Usa 'mi_programa help' para más información.")
sys.exit(1)Consejos para buenos errores: - Di qué salió mal - Di por qué salió mal (si es posible) - Sugiere cómo solucionarlo
Ejemplo:
Error: la flag --title es obligatoria para la acción 'add'.
Uso: mi_programa add --title "Mi tarea"
7. Códigos de Salida (Exit Codes)
Los programas de línea de comandos comunican el éxito o el fracaso a través de códigos de salida. Esto es fundamental para que otros programas y scripts puedan saber si tu CLI se ejecutó correctamente.
- Código
0→ éxito - Código
1o superior → error
import sys
# Éxito
sys.exit(0)
# Error genérico
sys.exit(1)Esto permite que otros programas usen tu CLI así:
mi_programa add --title "Tarea" && echo "¡Éxito!" || echo "¡Falló!"8. Salida Estructurada (Output para Otras Aplicaciones)
Si tu CLI puede ser utilizada por otros programas (¡y debería serlo!), considera ofrecer salida en formatos estructurados como JSON.
mi_programa list --output jsonSalida normal (para humanos):
ID | Título | Estado
1 | Comprar café | pendiente
2 | Estudiar CLI | completada
Salida JSON (para programas):
[
{"id": 1, "titulo": "Comprar café", "status": "pendiente"},
{"id": 2, "titulo": "Estudiar CLI", "status": "completada"}
]Esto hace que tu CLI sea fácilmente integrable con otros sistemas, scripts y pipelines.
Consejos Extras
Nunca mezcles convenciones de nomenclatura. Si una action se llama
set-profile-picture(separando por-), usa el mismo patrón en todas las actions. Esto facilita la legibilidad y la intuición de uso.Si la información es sensible, encriptala. Nunca almacenes contraseñas en texto plano. Usa alguna forma de encriptación y requiere la contraseña de desencriptación como argumento o configuración almacenada.
Añade colores al output. Los colores hacen que la salida sea mucho más legible. Por ejemplo, errores en rojo, éxito en verde, advertencias en amarillo. En la mayoría de los lenguajes existen bibliotecas para esto (como
coloramaen Python ochalken Node.js).Soporta auto-completado. Si es posible, permite que el usuario configure auto-completado en el shell (Bash, Zsh, Fish). Esto mejora drásticamente la experiencia de uso.
Escribe una buena documentación. Además de la
ayudaintegrada, considera mantener un README o una página de documentación con ejemplos detallados.Prueba tu CLI. Escribe tests automatizados para cada action y para combinaciones de flags. Esto evita regresiones y garantiza que todo funcione como se espera.
Conclusión
Construir una CLI profesional va más allá de solo leer argumentos de la terminal. Implica pensar en la experiencia del usuario, en la consistencia de los comandos, en el tratamiento de errores y en la integrabilidad con otros sistemas. Siguiendo los pasos de esta guía, tendrás una base sólida para crear CLIs que sean agradables de usar y fáciles de mantener.
Recuerda: una buena CLI es aquella que el usuario puede usar sin necesidad de consultar la documentación en todo momento. Invierte en buenos mensajes de ayuda, nombres de acciones intuitivos y mensajes de error claros.
