Usar byox
Crear y compartir cursos
Un curso es un proyecto real dividido en etapas, cada una con su test. Puedes pedirle a tu asistente que lo escriba, o escribirlo tú con tu editor y Git. En los dos casos byox comprueba que se puede completar antes de publicarlo.
Crear, verificar e importar cursos ejecuta código en Docker, así que requiere una cuenta de administrador, o que la instancia use BYOX_AUTHORS=all. Ver Cuentas y permisos.
Con un asistente
La forma más rápida es pedírselo, con el MCP conectado:
Crea un curso de byox para construir un servidor HTTP desde cero en Go.
O con el comando /mcp__byox__crear_curso, que acepta el tema, el lenguaje y el número de etapas. El asistente sigue este flujo:
- Lee la guía de formato (
get_format_guide). - Investiga las fuentes reales de lo que va a construir: documentación, especificaciones, implementaciones.
- Escribe el curso (
write_course_files) y la solución de referencia a la par. - Valida el formato (
validate_course). - Lo verifica contra la solución (
verify_course) hasta que esté todo en verde. - Te pregunta si lo publica (
start_course).
A mano
Un curso también se puede escribir sin asistente:
byox new mi-curso --lang python # python, rust, go o node
Eso crea cursos/mi-curso a partir de una plantilla que ya funciona (dos etapas, tests y solución) y la clona. Edita los archivos y haz git push: cada push al repositorio fuente se verifica solo en tu Docker. byox check muestra los errores de formato y, por etapa, si el esqueleto falla y la solución pasa.
Pon origin: human en course.yaml para que la web lo muestre como hecho a mano.
Estructura de un curso
README.md la portada del curso
course.yaml metadatos, tramos y etapas
issues/NN-*.md el cuerpo de cada etapa (markdown)
files/** se copia tal cual a la raíz del repositorio del alumno
solution/** implementación de referencia; se aplica encima de files/ al verificar
course.yaml
title: build-your-own-redis
description: Un Redis de juguete en Go, del socket a la persistencia.
image: golang:1.25 # imagen donde corren los tests (necesita sh y git)
setup: go mod download # opcional: corre una vez antes de los tests
topics: [go, redes, protocolos]
origin: ai # "ai" si lo escribe un asistente, "human" si lo hace una persona
author: ana # opcional
milestones: # en el orden en que se muestran
- id: base
title: El servidor
description: Aceptar conexiones y hablar RESP.
issues: # ids 1..N, consecutivos y en orden
- id: 1
milestone: base
title: Un servidor TCP que responde PONG
labels: [fácil, redes]
deps: [] # ids que tienen que estar cerrados antes
body: issues/01-pong.md
test: go test ./pasos/p01/...
hints: # de lo más conceptual a lo más concreto
- "¿Qué paquete de la std escucha en un puerto TCP?"
- "`net.Listen` y un bucle con `Accept`."
- "Cada conexión en su propia goroutine; responde `+PONG\\r\\n`."
Campos
| Campo | Obligatorio | Qué es |
|---|---|---|
title, description |
Sí | Nombre y resumen del curso. |
image |
Sí | Imagen de Docker en la que corren los tests. Tiene que traer sh y git. |
setup |
No | Comando que se ejecuta una vez antes de los tests, por ejemplo para descargar dependencias. |
topics |
No | Etiquetas del curso. |
origin |
No | ai o human. La web distingue los cursos escritos por un asistente. |
milestones |
Sí | Los tramos, en el orden en que se muestran. |
issues[].id |
Sí | Número de la etapa: de 1 a N, sin huecos. Es el número del issue en Forgejo. |
issues[].deps |
Sí | Etapas que deben estar cerradas antes. Vacío si no depende de ninguna. |
issues[].test |
Sí | Script de sh que corre en la raíz del repositorio del alumno. Si sale con 0, la etapa pasa. |
issues[].hints |
No | Pistas, de la más conceptual a la más concreta. No se copian al repositorio del alumno. |
Reglas que valida validate_course
- Los ids van de 1 a N, en orden y sin huecos.
- Cada dependencia apunta a una etapa que existe y el grafo no tiene ciclos.
- Todas las etapas tienen
test. Si algo no se puede testear, hay que reformularlo hasta que se pueda. - Las etiquetas
bloqueadoydisponibleestán reservadas: las maneja el bot. files/no puede traer.course/ni.forgejo/.
Los tests
El comando test de una etapa corre dentro de la imagen del curso, en la raíz del repositorio del alumno. Dos propiedades importan mucho:
- Tiene que funcionar aunque las etapas posteriores no estén hechas. En lenguajes que compilan todo el paquete, un test del paso 5 que llama a una función que aún no existe rompería el paso 1. La solución habitual es un archivo de test por etapa: en Rust,
tests/paso_01.rsconcargo test --test paso_01(cada archivo detests/es un crate aparte); en Go, un paquete por paso (pasos/p01/); en Python o JavaScript, un archivo por paso (pytest tests/test_01.py). - Un test solo puede depender del código de su etapa y de sus dependencias. Si necesita algo de otra etapa, esa etapa va en
deps.
Los tests son visibles: están en el repositorio del alumno y está bien que los lea.
El cuerpo de cada etapa
El bot agrega al final cómo verificarla, las dependencias y cuántas pistas hay, así que no lo repitas. Una estructura que funciona:
## Objetivo
Qué vas a construir y por qué importa. Conéctalo con lo que ya sabe.
## Contrato
La firma o la interfaz exacta que el test espera.
## Reglas
- Restricciones que fuerzan el aprendizaje.
## Para descubrir
- Preguntas que llevan a la idea clave sin decírsela.
## Hecho cuando
- [ ] El test pasa.
## Para leer
- [Documentación oficial](https://…)
Verificación
verify_course (o byox check) corre .course/run.sh en la imagen del curso dos veces:
| Con | Resultado esperado |
|---|---|
Solo files/ (el esqueleto) |
Todos los tests fallan |
files/ más solution/ |
Todos los tests pasan |
Si un test pasa con el esqueleto, esa etapa se cerraría sola en el primer push, así que la verificación falla. El resultado queda como estado del commit, y start_course no publica un commit sin verificar. Cada vez que cambias el curso hay que volver a verificar.
Una solución real
Un curso con una API que no existe o un test que no compila es peor que no tener curso. Por eso:
- Fuentes reales. Antes de escribir un contrato, un test o una pista, contrástalo con la documentación oficial, la especificación o el código de una implementación real, en la versión que trae
image. - Solución completa.
solution/debe resolver el curso entero. Es la prueba de que se puede hacer, y el alumno no la ve. - Números medidos. Si una etapa menciona una salida, un tiempo o un conteo, sácalo de una corrida real.
- Cita. Cada etapa termina con «Para leer» y los enlaces que usaste.
La portada
El README.md es lo primero que ve el alumno al abrir su repositorio. byox lo usa como introducción y le agrega debajo el mapa del grafo, la lista de etapas por tramo y cómo se usa, así que eso no hace falta escribirlo. Una portada que funciona tiene un título con emoji, una frase que dice qué vas a construir, una demo con salida real, qué vas a aprender, los requisitos con el tiempo por tramo y los créditos de las fuentes.
Publicar para ti
start_course (o byox start, o el botón Empezar el curso de la web) crea tu repositorio del curso: issues, tramos, grafo de dependencias, etiquetas, pistas y workflows. Con reset: true borra el progreso y arranca de cero.
Compartir
export_course (o byox export <curso>, o el botón Compartir de la portada) produce un código byox1-… con el repositorio fuente completo comprimido, incluida la solución. Los cursos grandes conviene pasarlos como archivo: byox export <curso> -o curso.byox guarda el mismo código en un .byox.
Quien lo recibe lo importa pegándolo en Creados → Importar, con byox import o con import_course. Antes de confirmar ve una vista previa de lo que trae. Al importar se crea el repositorio fuente y se verifica en su Docker.
Los tests de un curso importado corren en tu Docker. Un código byox1-… de un desconocido puede ejecutar lo que quiera en tu máquina.
Actualizar un curso
Cuando cambias un curso ya publicado, vuelve a verificarlo. Quienes ya lo empezaron traen los cambios con upgrade_course (o el botón Actualizar cuando hay etapas nuevas), sin perder el progreso: se suman las etapas y tramos nuevos, se corrigen los textos y se actualizan los archivos que genera byox y los archivos del curso que el alumno no tocó. El código del alumno no se modifica nunca.
Diseño pedagógico
- Una etapa es una sesión de trabajo: entre 20 minutos y 2 horas.
- El grafo no tiene por qué ser una línea. Si dos cosas son independientes, que se puedan hacer en cualquier orden.
- Cada tramo termina con algo que funciona y se puede mostrar.
- Cierra el curso con etapas de bonus que no bloqueen a nadie.
- Las pistas guían, no resuelven: la última puede ser casi la solución, pero nunca el código entero.