Tu propia herramienta de terminal: tareas
Vas a construir una CLI: un programa que se usa escribiendo órdenes en la terminal y que trabaja con tus ficheros — ordena descargas, renombra fotos, limpia temporales, resume documentos — mediante acciones que defines tú en un fichero acciones.json. Combina lo que sabe hacer el sistema operativo con lo que sabe hacer la IA, y se instala con una sola orden en Linux, Windows y macOS.
Y la construyes de otra manera: desde este proyecto trabajas de forma agéntica con OpenCode, un agente de programación open source conectado a los modelos de IA locales del centro. Tú decides qué se hace y apruebas cada cambio; el agente lee tu repo, propone y edita. El chat queda para consultas.
Por qué importa: los desarrolladores viven en la terminal. Git, los gestores de paquetes, los servidores, la integración continua y los propios agentes de IA son CLI. Quien sabe usarlas automatiza; quien sabe construirlas crea herramientas que usan otros.
Qué es una CLI
CLI (Command Line Interface, interfaz de línea de órdenes) es un programa que se controla escribiendo texto: tecleas una orden, pulsas Intro, el programa hace su trabajo, escribe un resultado y termina. Sin ventanas, sin botones. Lo contrario es una GUI (Graphical User Interface): ventanas, menús y ratón.
Gana la GUI (ventanas y ratón)
- Explorar algo que no conoces: ves las opciones en pantalla.
- Tareas visuales: retocar una foto, maquetar, editar vídeo a mano.
- Usuarios que no quieren aprender órdenes.
Gana la CLI (texto y teclado)
- Automatizar y repetir: la misma orden hoy, mañana y 300 veces.
- Encadenar herramientas con tuberías (|): la salida de una es la entrada de otra.
- Servidores sin pantalla: el 90 % de Internet se administra por SSH.
- Scripts, tareas programadas (cron) e integración continua (CI): nadie hace clic ahí.
- Dejar rastro: una orden se copia, se documenta y se repite exacta.
Terminal, shell y CLI: no es lo mismo
Terminal
La aplicación que muestra texto y recoge lo que tecleas: Terminal de Linux o macOS, Windows Terminal, la terminal integrada de VS Code.
Shell
El programa que lee tu orden y la lanza: bash (Linux), zsh (macOS), PowerShell (Windows). Cada una tiene su sintaxis: por eso hay órdenes que cambian de un sistema a otro.
CLI
La herramienta que la shell ejecuta: git, curl, uv… y, dentro de dos semanas, tareas. Funciona igual desde cualquier shell.
Resumen: abres una terminal, dentro corre una shell, y en ella escribes órdenes que lanzan CLI.
Anatomía de una orden
Esta es una orden real de tu futura herramienta. Separada en piezas se entiende todo lo demás:
Se lee como una frase: «herramienta, haz esto, con esto, aquí, de esta manera».
Y estas son las otras piezas que tiene cualquier CLI seria (y tendrá la tuya):
Ayuda (--help)
Toda CLI decente se explica sola. Es lo primero que pruebas con una herramienta nueva y lo primero que se evalúa en la tuya.
tareas --helptareas ejecutar --helpArgumentos vs opciones
Argumento: dato posicional, normalmente obligatorio (QUÉ). Opción: empieza por - o --, tiene nombre y suele ser opcional (CÓMO). Un flag es una opción sí/no.
tareas listar ~/Descargas # argumentotareas listar ~/Descargas --json # + opción (flag)tareas --config otro.json acciones # opción con valorstdin, stdout y stderr
Tres canales: entrada estándar, salida estándar (resultados) y salida de error (avisos y fallos). Separarlos permite redirigir solo lo útil.
tareas listar > lista.txt # stdout a un ficherotareas validar 2> errores.txt # stderr a otrotareas listar --json | jq length # tubería: stdout entra en jqCódigos de salida
Al acabar, el programa devuelve un número: 0 = todo bien, distinto de 0 = algo falló. Los scripts y la CI deciden con él. En tu CLI: 0 bien · 1 fallo al ejecutar · 2 error de uso · 3 configuración inválida.
tareas validarecho $? # bash/zsh → 0, 1, 2 o 3echo $LASTEXITCODE # PowerShellVariables de entorno
Valores que el sistema le pasa al programa sin escribirlos en la orden: rutas, idioma, claves de API (nunca en el código).
export TAREAS_MODELO=llama3 # bash/zsh$env:TAREAS_MODELO = "llama3" # PowerShellFichero de configuración
Lo que cambia poco y no quieres teclear cada vez. En tu proyecto, las acciones viven en acciones.json, no en el código.
tareas acciones # usa ./acciones.jsontareas --config ~/mis.json accionesFormato de salida
Para personas: tablas y colores. Para máquinas: --json (estable, sin colores). Una buena CLI ofrece las dos.
tareas listar ~/Descargas # tabla bonitatareas listar ~/Descargas --json # para otro programaInteractiva vs no interactiva
Antes de borrar, pregunta (¿Seguro? [s/N]). Pero en un script nadie responde: --si confirma sin preguntar. Y --simular enseña qué haría sin tocar nada.
tareas ejecutar limpiar-temporales --simulartareas ejecutar limpiar-temporales # preguntatareas ejecutar limpiar-temporales --si # no preguntaLas CLI que usa el mundo
Muchas de las herramientas más potentes de la informática no tienen ventanas. Algunas que verás (o usarás) este curso:
Código y versiones
Control de versiones: la máquina del tiempo de tu código.
GitHub desde la terminal: repos, issues, PR y releases.
Agente de código open source que vive en la terminal: lee tu repo, ejecuta órdenes (con tu permiso) y propone cambios. Primos: Claude Code, Codex CLI, Gemini CLI.
Red y descargas
Habla HTTP: descarga ficheros, prueba APIs, instala herramientas.
Descarga vídeo y audio de cientos de webs (respeta derechos y licencias).
Copias y copias de seguridad incrementales, en local o por red.
Multimedia y documentos
La navaja suiza del vídeo y el audio: convertir, recortar, extraer.
Convierte, redimensiona y retoca imágenes por lotes.
Convierte documentos entre formatos: Markdown, Word, PDF, HTML.
Buscar y filtrar
Busca texto en miles de ficheros en milisegundos.
Buscador difuso interactivo: elige de una lista tecleando.
Lee, filtra y transforma JSON en la terminal.
Sistema y entornos
Ejecuta aplicaciones en contenedores aislados y reproducibles.
Gestores de paquetes: instalan librerías y herramientas.
Monitor de procesos, CPU y memoria en la terminal.
Ayuda e IA
Ejemplos prácticos de cualquier orden, sin leer el manual entero.
Descarga y ejecuta modelos de IA en tu propio equipo.
orden --help, tldr orden o man orden. Y si tu herramienta no se explica así de bien, aún no está terminada.Ideas de acciones para tu herramienta
De menos a más difícil. Empieza por arriba; las de IA llegan en la semana 3. Tus acciones tienen que resolver un problema tuyo: mira tu carpeta de descargas y piensa qué te gustaría no volver a hacer a mano.
- 1Renombrarsistema●●●●●●
Fotos con su fecha (2026-10-26_001.jpg), quitar espacios y tildes de nombres, numerar entregas.
- 2Ordenarsistema●●●●●●
Descargas por tipo (PDF, imágenes, comprimidos, instaladores) o apuntes por asignatura según el nombre.
- 3Limpiar y detectarsistema●●●●●●
Temporales con más de 30 días, duplicados por hash (mismo contenido, distinto nombre), informe de espacio en disco por carpeta.
- 4Resumir con IAIA●●●●●●
Resumir PDFs o textos largos, generar el README de una carpeta de proyecto, convertir apuntes desordenados en Markdown limpio.
- 5Renombrar por contenido con IAIA●●●●●●
La IA lee el principio de cada documento y propone un nombre que diga lo que es (con --simular primero).
- 6Acciones encadenadassistema + IA●●●●●●
Ordenar → quitar duplicados → resumir lo nuevo → informe final. Una orden, varios pasos.
Cómo se desarrolla una CLI de verdad
Las herramientas profesionales no salen de un prompt gigante. Salen de este ciclo, paso a paso, con un commit al acabar cada uno. Es el que seguirás:
- 01
Spec de 10 líneas
Para quién es, qué problema resuelve, qué órdenes tendrá, qué NO hará. Si no cabe en 10 líneas, aún no sabes qué quieres.
docs/spec.md - 02
Interfaz
Las órdenes y opciones exactas, como las teclearía alguien. Se diseña antes que el código: es el contrato con quien la usa.
tareas --help - 03
Núcleo (motor)
La lógica que hace el trabajo, separada de la interfaz: el motor no sabe nada de Typer ni de colores. Así se prueba y se reutiliza.
motor.py - 04
Errores y casos feos
Carpeta que no existe, JSON mal escrito, fichero abierto, sin permisos, sin red, nombre con tildes. Mensajes claros, nunca un traceback.
errores.py - 05
Pruebas
pytest comprueba que cada acción hace lo que dice en una carpeta temporal. Si cambias algo y se rompe, te enteras antes que tu usuario.
tests/ - 06
Empaquetado e instalación
pyproject.toml con su entry point: tu programa se convierte en un comando que se instala con una orden.
uv tool install - 07
Release
Versión etiquetada (v1.0.0), notas de cambios y README con instalación probada en otro sistema.
git tag v1.0.0 - Y vuelta a empezar. Cada acción nueva repasa el ciclo en pequeño: spec → interfaz → motor → casos feos → prueba → commit.
acciones.json (decides qué hace), el agente (OpenCode) implementa con tu permiso, y tú auditas: lees el código, pruebas casos feos y haces commits pequeños con mensajes que cuentan el proceso. Guarda tus prompts clave en docs/prompts.md. Lo que no sabes explicar, no lo entregas.Cómo vas a trabajar: con un agente
Hasta ahora le pedías código a un chat y lo copiabas. Desde este proyecto, el código lo escribe un agente dentro de tu repo, y tú diriges. Se usará todo el curso, en presencial y en semipresencial; este proyecto es la introducción.
Chat
Preguntas, responde con texto y tú copias. No ve tu repo ni ejecuta nada: si se equivoca, no se entera. Sigue valiendo para dudas y explicaciones.
Agente (OpenCode)
Lee tus ficheros, propone un plan, edita y lanza órdenes —cada cambio te lo pide primero— y comprueba el resultado. Más potencia, más responsabilidad: tú apruebas y tú auditas.
El flujo de cada sesión (siempre el mismo)
- 1Tú decides
Escribes la intención: la spec, tu acciones.json o el criterio de aceptación de la tarea.
- 2Plan
Agente plan (Tab): «explícame cómo lo harías y qué ficheros tocarías». Lees el plan y lo corriges.
- 3Build aprobando diffs
Agente build (Tab): «hazlo». Lees cada diff y cada orden antes de aceptarla.
- 4Auditas
Lees el código y pruebas con --simular en ~/pruebas-tareas, con casos feos. ¿Mal? /undo o le explicas el fallo.
- 5Commit tuyo
git add + git commit los haces tú, pequeños y con un mensaje que cuente el paso. El prompt clave, a docs/prompts.md.
- 6Sesión nueva
/new para cada tarea y /compact si la conversación se alarga: contexto limpio, menos errores.
Qué configuras en tu repo
La conexión con los modelos del centro va en tu configuración global (con variables de entorno: la clave nunca acaba en un fichero que subas a git). En el repo van las reglas del juego para el agente:
| Fichero | Cuándo | Para qué |
|---|---|---|
| opencode.json | Semana 1 | Permisos: qué puede hacer solo (leer, git status), qué te pregunta (editar, casi todas las órdenes) y qué nunca (git push, rm, leer .env). |
| AGENTS.md | Semana 1 | Lo genera /init y lo editas tú: stack, órdenes del proyecto y normas (pathlib, utf-8, nada de commits ni push). |
| .opencode/skills/acciones-json/SKILL.md | Semana 2 | Skill: las reglas de tu acciones.json, que el agente carga cuando toca acciones. |
| .opencode/commands/nueva-accion.md | Semana 2 | Comando /nueva-accion: añadir una acción siempre con los mismos pasos. |
| .opencode/agents/revisor.md | Semana 2 | Subagente revisor de solo lectura: @revisor busca errores y casos feos antes de cada commit. |
En clase usamos OpenCode 1.18.35 (claves en singular: permission, agent…). Si un tutorial habla de permissions o agents en plural, es OpenCode 2 y su configuración no es compatible.
Tecnologías para hacer una CLI
Casi cualquier lenguaje sirve. Cada uno paga un precio distinto:
| Opción | A favor | En contra | CLI famosas hechas así |
|---|---|---|---|
| Python · Typer / Click / argparseLa del curso | Legible, librerías para todo (ficheros, PDF, IA), multiplataforma, rapidísimo de escribir. argparse viene de serie; Typer genera ayuda y autocompletado desde los tipos. | Necesita Python instalado (uv lo resuelve); arranque algo más lento; no da un único ejecutable de serie. | aws-cli, yt-dlp, httpie, pip, Ansible |
| Node.js · commander / oclif | Ecosistema npm enorme; ideal si ya trabajas en JavaScript; buena integración con herramientas web. | Necesita Node; node_modules pesados; asincronía que complica scripts sencillos. | npm, Vercel CLI, Heroku CLI, Angular CLI |
| Go · cobra | Un único binario sin dependencias, compila para cualquier sistema, arranque instantáneo. | Más verboso; tipado y compilación que ralentizan el primer prototipo. | kubectl, gh, docker, hugo |
| Rust · clap | Velocidad máxima y seguridad de memoria; binarios únicos; clap es excelente. | Curva de aprendizaje dura; compilaciones lentas. | ripgrep, fd, bat, uv |
| Scripts Bash / PowerShell | Ya están instalados; perfectos para pegar 5 órdenes existentes. | Frágiles al crecer, difíciles de probar y no multiplataforma (Bash ≠ PowerShell). | instaladores, nvm, scripts de despliegue |
Por qué Python 3 + Typer + uv
Puedes leer y auditar lo que escribe el agente aunque estés empezando.
El mismo código funciona en Linux, Windows y macOS si sigues cuatro reglas.
Python es el lenguaje en el que más código ha visto cualquier modelo: menos inventos.
uv instala Python, dependencias y tu herramienta como comando global.
A partir de los tipos de tus funciones genera --help, validación de argumentos y autocompletado.
Tablas, colores y barras de progreso que funcionan también en Windows Terminal.
Un «hola mundo» con Typer. Fíjate: no escribes nada sobre la ayuda ni sobre cómo leer los argumentos. Typer lo deduce de nombre: str, veces: int = 1 y gritar: bool = False.
import typerapp = typer.Typer(help="Tu primera CLI con Typer.")@app.command()def hola(nombre: str, veces: int = 1, gritar: bool = False): """Saluda a NOMBRE tantas VECES como pidas.""" for _ in range(veces): texto = f"Hola, {nombre}" print(texto.upper() if gritar else texto)if __name__ == "__main__": app()uv run --with typer hola.py Ana --veces 2 --gritar# HOLA, ANA# HOLA, ANAuv run --with typer hola.py --help Usage: hola.py [OPTIONS] {nombre} Saluda a NOMBRE tantas VECES como pidas.╭─ Arguments ──────────────────────────────────────────────────────────╮│ * nombre <str> [required] │╰──────────────────────────────────────────────────────────────────────╯╭─ Options ────────────────────────────────────────────────────────────╮│ --veces <int> [default: 1] ││ --gritar --no-gritar [default: no-gritar] ││ --install-completion Install completion for ││ the current shell. ││ --show-completion Show completion for ││ the current shell, to ││ copy it or customize ││ the installation. ││ --help Show this message and ││ exit. │╰──────────────────────────────────────────────────────────────────────╯Argumento obligatorio, opciones con valor por defecto, un flag con su contrario y autocompletado para tu shell. Gratis.
Multiplataforma: Linux primero, pero en todas partes
En el aula trabajas en Linux. Pero tu herramienta la instalará gente con Windows y macOS (y si eres de semipresencial, tu propio equipo puede ser cualquiera de los tres). Python lo pone fácil si respetas seis reglas:
Rutas con pathlib, nunca concatenando
Windows usa \ y Linux /. Path elige el separador correcto por ti.
La ~ hay que expandirla
~ lo entiende la shell, no Python. Sin expanduser() busca una carpeta llamada «~».
Codificación explícita
En Windows la codificación por defecto puede no ser UTF-8: las tildes y la ñ se rompen.
Nada de shell=True ni os.system
mv no existe en PowerShell clásico, un nombre con espacios lo rompe y abre la puerta a inyecciones.
Saltos de línea normalizados
Windows usa CRLF y Linux LF. Sin esto, git marca cambios fantasma en todas las líneas.
Colores con Rich
Los códigos ANSI a mano salen como basura en algunas consolas. Rich detecta lo que soporta cada una.
Y en la semana 4, GitHub Actions ejecutará tus pruebas en Ubuntu, Windows y macOS a la vez en cada git push: si algo solo funciona en tu equipo, te enterarás.
Equivalencias bash ↔ PowerShell
PowerShell tiene alias con los nombres de Linux (ls, cp, mv…), pero las opciones no siempre coinciden. Entre paréntesis, el nombre «de verdad» del cmdlet.
| Quiero… | bash / zsh (Linux, macOS) | PowerShell (Windows) |
|---|---|---|
| Listar ficheros | ls -la | Get-ChildItem (o ls) |
| Cambiar de carpeta | cd ~/Proyectos | cd ~\Proyectos |
| ¿Dónde estoy? | pwd | pwd (Get-Location) |
| Crear carpeta | mkdir -p pruebas/a | mkdir pruebas\a (New-Item -ItemType Directory) |
| Copiar | cp origen destino | cp origen destino (Copy-Item) |
| Mover / renombrar | mv viejo nuevo | mv viejo nuevo (Move-Item) |
| Borrar | rm fichero · rm -r carpeta | rm fichero · rm -r carpeta (Remove-Item) |
| Ver un fichero | cat acciones.json | cat acciones.json (Get-Content) |
| ¿Dónde está un comando? | which tareas | Get-Command tareas · where.exe tareas |
| Leer una variable | echo $HOME | echo $env:USERPROFILE |
| Código de salida | echo $? | echo $LASTEXITCODE |
Instalarla para que sea útil
Un script que solo funciona con python src/tareas/cli.py desde su carpeta es un ejercicio. Una herramienta se teclea por su nombre desde cualquier carpeta. ¿Cómo lo consigue git?
El PATH
Cuando escribes tareas, la shell busca un ejecutable con ese nombre en una lista de carpetas: la variable de entorno PATH. Un comando está «instalado» cuando hay un ejecutable suyo en alguna de ellas.
echo $PATH # bash/zsh$env:Path # PowerShellwhich tareas # ¿cuál se ejecuta? (Get-Command en Windows)El entry point
En pyproject.toml declaras qué función se ejecuta al teclear el comando. Al instalar, uv crea el ejecutable tareas en una carpeta del PATH (~/.local/bin en Linux y macOS).
[project.scripts]tareas = "tareas.cli:app" # comando = "módulo:objeto"Modo editable: cada cambio que guardas se nota al momento, sin reinstalar.
cd cli-tareasuv tool install --editable .tareas --helpDirectamente desde tu repo público de GitHub. Con uv o, si no lo tiene, con pipx.
uv tool install git+https://github.com/TU-USUARIO/cli-tareas# o bienpipx install git+https://github.com/TU-USUARIO/cli-tareasUna buena herramienta se va igual de limpia que llegó. Su configuración de usuario (si la hay) se borra aparte.
uv tool uninstall tareasuv tool list # comprobar que ya no está| Dónde vive cada cosa | Linux / macOS | Windows |
|---|---|---|
| El comando instalado | ~/.local/bin/tareas | %USERPROFILE%\.local\bin\tareas.exe |
| acciones.json (por defecto) | ./acciones.json, en la carpeta donde lanzas la orden, o la que indiques con --config | |
| Config de usuario (avance) | ~/.config/tareas/ | %APPDATA%\tareas\ |
La ruta de config de usuario no se escribe a mano: la librería platformdirs devuelve la correcta en cada sistema.
- Pide a un compañero (mejor con otro sistema operativo) que siga solo tu README, sin ayuda tuya.
- Instala con la orden de
uv tool install git+…y pruebatareas --helpytareas versiondesde otra carpeta. - Crea una carpeta de pruebas con ficheros de ejemplo y lanza cada acción con
--simulary luego de verdad. - Prueba un nombre con tildes y espacios (
Apuntes de Física.pdf) y una ruta con~. - Rompe a propósito el
acciones.json:tareas validardebe decir qué falla y salir con código 3. - Desinstala y comprueba que
tareasya no existe. Todo lo que haya fallado, al README o a un issue.
El proyecto: qué tiene que hacer tu CLI
El comando de ejemplo se llama tareas y el repo cli-tareas (público en GitHub). Puedes elegir otro nombre, pero estas son las órdenes de referencia:
| Orden | Qué hace |
|---|---|
| tareas --help | Ayuda general con todas las órdenes (la genera Typer). |
| tareas version | Muestra la versión instalada (0.1.0 al empezar). |
| tareas listar [CARPETA] | Tabla con nombre, tipo, tamaño y fecha de cada fichero. Por defecto, la carpeta actual. |
| tareas acciones | Lista las acciones definidas en acciones.json con su descripción. |
| tareas validar | Comprueba acciones.json y dice exactamente qué campo falla (código 3 si es inválido). |
| tareas ejecutar NOMBRE [CARPETA] --simular | Muestra qué haría la acción sin tocar nada. |
| tareas ejecutar NOMBRE [CARPETA] --si | La ejecuta sin preguntar (para scripts). |
| tareas --config RUTA … | Opción global: otro fichero de acciones (por defecto ./acciones.json). |
Códigos de salida: 0 bien · 1 fallo al ejecutar · 2 error de uso (lo pone Typer) · 3 configuración inválida.
acciones.json: el corazón del proyecto
Las acciones no se escriben en el código: se describen en este fichero y el motor las interpreta. Este es el esquema de referencia; tú lo adaptas a tus acciones y lo documentas en tu README.
{ "version": 1, "acciones": [ { "nombre": "ordenar-descargas", "descripcion": "Mueve los PDF y documentos de Descargas a Documentos/PDF", "tipo": "mover", "origen": "~/Descargas", "filtro": { "extensiones": [".pdf", ".docx"] }, "destino": "~/Documentos/PDF" }, { "nombre": "renombrar-fotos", "descripcion": "Renombra fotos con su fecha: 2026-10-26_001.jpg", "tipo": "renombrar", "filtro": { "extensiones": [".jpg", ".jpeg", ".png"] }, "plantilla": "{fecha:%Y-%m-%d}_{n:03}{ext}" }, { "nombre": "limpiar-temporales", "descripcion": "Borra .tmp con más de 30 días", "tipo": "borrar", "filtro": { "patron": ".*\\.tmp$", "mas_antiguo_que_dias": 30 }, "confirmar": true } ]}- version
- Versión del esquema del fichero. Si algún día cambias el formato, sabrás leer los antiguos.
- acciones
- Lista de acciones. Añadir una nueva no exige tocar el código: ese es el objetivo.
- nombre
- Identificador que se teclea: tareas ejecutar ordenar-descargas. Minúsculas y guiones, único.
- descripcion
- Lo que verá quien ejecute tareas acciones. Una frase que diga qué hace.
- tipo
- Qué clase de acción es: mover, renombrar, copiar, borrar… (y en la semana 3, las de IA). Cada tipo es una clase en acciones.py.
- origen / destino
- Carpetas sobre las que trabaja. Admiten ~ (se expande con expanduser). Si no hay origen, se usa la CARPETA de la orden.
- filtro
- Qué ficheros le afectan: extensiones, patron (expresión regular sobre el nombre), mas_antiguo_que_dias…
- plantilla
- Para renombrar: {fecha:%Y-%m-%d} es la fecha del fichero, {n:03} un contador a 3 cifras y {ext} la extensión original.
- confirmar
- true en acciones destructivas: pregunta antes de actuar salvo que pases --si.
Estructura del repositorio
Cada fichero tiene un único trabajo. La regla de oro: cli.py habla con la persona, motor.py y acciones.py hacen el trabajo, config.py desconfía del JSON.
cli-tareas/├── pyproject.toml # [project.scripts] tareas = "tareas.cli:app"├── README.md├── .gitignore # .venv/, __pycache__/, .env, *.egg-info, dist/├── .gitattributes # * text=auto├── acciones.json # TUS acciones (lo escribes tú)├── docs/adr/0001-configuracion-externa.md├── src/tareas/│ ├── __init__.py # __version__ = "0.1.0"│ ├── __main__.py # permite: python -m tareas│ ├── cli.py # interfaz Typer: órdenes, opciones, salida│ ├── config.py # leer y VALIDAR acciones.json│ ├── motor.py # clase Motor: ejecuta una Accion sobre una carpeta│ ├── acciones.py # clases Accion (mover, renombrar, copiar, borrar…)│ └── errores.py # TareasError, ConfigError, AccionNoValida└── tests/ # semana 4La capa de IA
Acciones de tipo IA (resumir, generar README, renombrar por contenido) que llaman a un modelo — los mismos del centro con los que trabaja OpenCode, o el que configures. La clave va en un .env ignorado por git desde el primer commit, con un .env.example documentado.
Modo sin red
Si no hay red o falta la clave, tu CLI no revienta con un traceback: lo explica en una línea y sigue ofreciendo todas las acciones que no necesitan IA.
.gitignore con .env antes del primer commit; nunca claves en el repo ni en el chat; acciones destructivas siempre con --simular primero y confirmación; y prueba siempre en ~/pruebas-tareas, nunca en tus ficheros reales hasta que funcione.Planificación: las dos primeras semanas
Sesión 1 · Arranque: la terminal y tu primera orden
Objetivo: Perderle el miedo a la terminal y tener un comando tareas que existe de verdad.
- Moverte por carpetas, crear, copiar y borrar en tu terminal (bash o PowerShell).
- Instalar uv y Python 3.12; crear el proyecto con uv init --package y añadir Typer.
- Escribir tu spec de 10 líneas y el .gitignore (con .env) ANTES del primer commit.
- Primeras órdenes: --help, version y listar con tabla Rich.
- Instalarla con uv tool install --editable . y lanzarla desde cualquier carpeta.
- Instalar OpenCode 1.18.35 y conectarlo a los modelos del centro.
- uv init y .gitignore a mano y primer commit ANTES de abrir OpenCode (/undo necesita git).
- opencode.json de permisos en la raíz del repo.
- /init → AGENTS.md, que revisas y editas tú.
- plan → build para crear cli.py (version + listar), aprobando cada diff; /undo cuando algo sale mal.
Sesión 2 · Acciones predefinidas: acciones.json y el motor
Objetivo: Que tu herramienta haga cosas útiles definidas en un fichero que escribes tú.
- Diseñar tu acciones.json con al menos 3 acciones propias (no las del ejemplo).
- config.py que valida el JSON y dice qué campo falla; errores.py con tus excepciones.
- Clases Accion y Motor separadas de la interfaz; órdenes acciones, validar y ejecutar.
- --simular siempre primero y confirmación antes de borrar; todo en ~/pruebas-tareas.
- ADR 0001: por qué configuración externa y no acciones escritas en el código.
- Tu acciones.json lo escribes tú, sin IA.
- Skill del proyecto acciones-json con las reglas del esquema (compruébala con /skills).
- Comando personalizado /nueva-accion para añadir acciones siempre igual.
- Subagente revisor de solo lectura (@revisor) y /review antes de cada commit.
Cómo se organiza cada grupo
- Es tu segundo proyecto: línea individual de 4 h/semana en el aula, en paralelo a la startup en grupo (las otras 4 h).
- Equipos del aula con Linux: la terminal es bash desde el primer minuto.
- Herramientas: terminal y OpenCode conectado a los modelos de IA locales del centro, en paralelo a la startup. El chat, solo para consultas.
- Cada sesión acaba con commit y push: lo que no está en GitHub no existe.
- Quincena 3 = estas dos semanas (26 oct → 6 nov).
- Comprobación de proceso el 6 nov: 3 acciones propias funcionando + ADR + commits reales.
- Quincena 4 (9 → 20 nov): IA, pruebas, release y entrega el 20 nov.
- Trabajas con OpenCode también en casa, por ejemplo en la terminal integrada de VS Code, conectado a los modelos del centro. El chat de Copilot de Microsoft 365 queda solo para consultas.
- La terminal y cómo conectarte desde casa a los modelos del centro se explican en la tutoría colectiva de arranque, de presencia obligatoria (fecha en el aula virtual).
- Tu equipo puede ser Windows, Linux o macOS: la sección multiplataforma es para ti.
OpenCode: MCP (servidor context7 para documentación de librerías, activado solo cuando hace falta). Tu CLI: capa IA que llama a los mismos modelos del centro desde Python, .env y modo sin red.
Pruebas que escribe el agente y auditas tú (pytest + GitHub Actions), opencode run no interactivo en scripts, README, release v1.0 y día de instalación cruzada.
Cómo se evalúa
Primero, la puerta de entrada: si falla cualquiera de estos mínimos, el proyecto no se evalúa (aunque el resto esté genial).
- Se instala siguiendo el README y la orden de ayuda (--help) funciona.
- Al menos 3 acciones propias definidas en el fichero de configuración (acciones.json) funcionan.
- Ninguna clave ni secreto en el repositorio ni en su historial.
- Historial git real: mínimo 10 commits con mensajes que cuentan el proceso.
Después, 7 criterios con su peso. Esto es lo que hay que hacer para el Excelente en cada uno:
| Criterio | Peso | Nivel Excelente |
|---|---|---|
Acciones predefinidas funcionando Lo que tu herramienta hace de verdad con tus ficheros. | 20 % | 5 o más acciones propias útiles, combinables, con salida clara y sin efectos sorpresa (simulación previa o confirmación antes de borrar o sobrescribir). |
Configuración externa (acciones.json) Las acciones viven en un fichero que escribes tú, no dentro del código. | 15 % | Además: añadir una acción no exige tocar el código y hay un ADR que justifica por qué configuración externa y no código. |
Capa IA, secretos y modo sin red IA donde aporta, sin filtrar claves y sin depender de ella para todo. | 15 % | Al menos 2 acciones con IA útiles; ninguna clave en el historial; si no hay red, la CLI lo explica y sigue con las acciones sin IA. |
Robustez: excepciones y entradas feas Qué pasa cuando el usuario se equivoca o el disco no es como esperabas. | 15 % | Excepciones propias (ConfigError, AccionNoValida…) con mensajes humanos; ningún traceback ante errores previsibles; aserciones en desarrollo. |
Diseño en clases y módulos Cómo está organizado el código por dentro. | 10 % | Responsabilidades separadas (interfaz, motor, acciones, proveedor IA), visibilidad cuidada y métodos estáticos con sentido (p. ej., fábricas desde la configuración). |
Pruebas y calidad Cómo demuestras que funciona y que sigue funcionando. | 15 % | Pruebas que cubren el camino feliz y 3 casos feos, ejecutadas en GitHub Actions y auditadas por el alumno (sabe explicar cada aserción). |
Instalación, documentación y proceso Que otra persona la instale y la use sin preguntarte nada. | 10 % | Se instala con una orden siguiendo el README; release v1.0 etiquetada con changelog; historial con ramas y PR legibles. |
La rúbrica completa, con los cuatro niveles (Insuficiente, En desarrollo, Competente, Excelente) de cada criterio, está en el campus del aula. Léela antes de empezar, no después de entregar.
