rune
Script runner para monorepos de JavaScript y TypeScript, escrito en Rust. Los comandos viven en un único config tipado en la raíz y cada paquete los llama por nombre.
- rust
- typescript
- monorepo
- cli
- tooling
rune saca todos los comandos de un monorepo de los bloques scripts y los pone en un único rune.config.ts tipado, en la raíz. Los paquetes dejan de cargar strings de comandos y llaman a los scripts por nombre.
En un workspace de veinte paquetes, el mismo vitest run --coverage --reporter=dot termina copiado en veinte package.json, desincronizándose un flag a la vez. Defínelo una vez; referéncialo en todos lados.
El config
// rune.config.ts
import { defineConfig } from '@gio-labs/rune';
export default defineConfig({
scripts: {
build: {
command: 'tsc --build',
description: 'Compila todos los paquetes',
},
test: {
command: 'vitest run',
env: { NODE_ENV: 'test' },
dependsOn: ['build'],
},
dev: { parallel: ['dev:api', 'dev:web'] },
'dev:api': { command: 'tsx watch src/server.ts', cwd: 'packages/api' },
'dev:web': { command: 'vite', cwd: 'packages/web' },
},
});{ "scripts": { "test": "rune run test" } }Por qué funciona así
- El config es TypeScript real, pero nunca carga Node. Los tipos se eliminan y el archivo corre en un motor de JavaScript embebido, así una corrida en caliente queda por debajo de 5 ms. Un config que tuviera que resolver
node_modulescostaría lo mismo que los scripts que describe.rune.platform,rune.envyrune.isCIreemplazan aprocess, y los imports relativos siguen funcionando. - Los comandos por plataforma se declaran, no se ramifican.
command: { default: 'xdg-open …', win32: 'start …', darwin: 'open …' }. - El proceso hijo recibe la terminal real, rune sale con el código del hijo y sus propios diagnósticos van a stderr — así stdout le pertenece al script.
- Los argumentos sobreviven a Windows. Casi toda herramienta en
node_modules/.bines un batch file que vuelve a leer sus argumentos, así que rune escapa para ambos lectores cuando un comando resuelve a.cmdo.bat. - Un binario nativo por plataforma, resuelto por dependencias opcionales — nada se compila al instalar y no corre ningún postinstall. Los builds de Linux son estáticos y se prueban en un contenedor musl y en uno glibc antes de publicarse.
Rune es un registro de scripts y un runner, no un grafo de tareas: sin caché, sin orden topológico. Turbo y Nx se apoyan encima y siguen encargándose de esa parte — agrega rune.config.ts a sus inputs declarados, porque los strings de comandos que ellos hashean ya no cambian.
Las guías y la referencia completa del CLI están en rune.gio-labs.com.