shell es un shell manager para macOS: crea VMs Linux con Lima
y te permite saltar entre el host y varios entornos manteniendo los mismos
archivos del host, pero aplicando configuración global distinta en cada uno.
Es el modelo de un devcontainer, con una diferencia: cada shell tiene su propio home y su propio perfil (dotfiles), mientras que el directorio del host que elijas se montan dentro de todas las VMs de forma escritura.
host (macOS) shell A (Ubuntu) shell B (Ubuntu)
~/Workspaces/project ──► ~/Workspace (mismo dir, en vivo)
~/.zshrc (macOS) ~/.zshrc (A) ~/.zshrc (B) (distintos por shell)
node@18, python@3.11 node@20, rust
shell create <name> --workspace ~/dir [--image ubuntu] [--cpus 8] [--memory 8GiB]
[--disk 40GiB]
shell enter <name> # abre una sesión interactiva (SSH) en la VM
shell remove <name> # borra perfil + VM + dotfiles
shell list [name] # estado de todos los shells, o detalle de uno
shell start|stop <name> # ciclo de vida de la VM--workspace es obligatorio al crear un shell. La carpeta del host aparece
dentro del guest en ~/Workspace (el nombre que tenga en el host da igual).
Al crear, la VM se descarga y se provisiona una sola vez (arranca, instala y se
apaga); después shell start <name> solo la enciende.
El sistema son engranajes aislados unidos por puertos y adaptadores,
con una única composición explícita en el binario shell.
crates/
├── kernel/ # engranaje: dominio + casos de uso + puertos
├── host/ # utilidad: layout de rutas + fs
├── text/ # utilidad: plantillas
├── store/ # adaptador: ProfileStore (SQLite · sqlx)
├── lima/ # adaptador: VmProvider + VmShell + BrowserBridge (limactl, ssh)
├── environment/ # adaptador: ShellEnvironment (dotfiles/env)
├── provision/ # adaptador: Provisioner (bootstrap del sistema)
└── app/ # binario: composición + CLI
templates/ # plantillas de texto (lima.yaml, env.sh, apply.sh, bootstrap.sh)
kernelno conoce Lima, SQLite, el filesystem ni la terminal: solo su dominio, sus casos de uso y los puertosProfileStore,VmProvider,VmShell,ShellEnvironment,ProvisioneryBrowserBridge.- Los adaptadores implementan esos puertos; el único lugar que los conoce a
todos es
crates/app. - Configuración en SQLite (
~/.local/share/shell/shell.db), no en TOML. - Los dotfiles sí son archivos reales (
~/.local/share/shell/shells/<name>/home/), materializados al home del guest en cadaenter. - El guest solo ve la carpeta montada, en
~/Workspace; el home del host no se monta (se desactiva el mount por defecto de Lima) yenterarranca ahí. - El mount usa virtiofs con
mountInotifydesactivado: la opciónmountInotifyde Lima rompemkdir/chmodconcurrentes sobre el share (EACCES intermitente) y hace fallarnpm install. Ver lima#2450. Como contrapartida, losinotifydel guest no ven cambios hechos en el host. - El bootstrap instala neovim y el entorno del guest exporta
EDITOR=nvim. - El shell de login del guest es zsh: se instala como paquete y cada
enterlo fija conchsh. Comolimactl shellusa eluser.shellde Lima (no/etc/passwd),enterle pasa--shellcon el shell de login del guest. - Al entrar,
shelllevanta un puente de navegador: un shimxdg-openen el guest reenvía las URLs al navegador del host por un túnel SSH inverso que vive mientras dure la sesión, asígh auth loginy compañía abren el navegador de macOS. - El terminfo del terminal del host se copia al guest en cada
enter(infocmpen el host →ticen el guest), para que la edición de línea yclearfuncionen con terminales como kitty o alacritty. - Las plantillas de texto viven en
templates/(raíz del repo); el binario las copia a~/.local/share/shell/templates/al arrancar y renderiza desde ahí (ruta de origen configurable conSHELL_TEMPLATES). limactlse localiza porPATHy, si falta, en ubicaciones típicas de Homebrew.
| Área | Crate |
|---|---|
| CLI | clap |
| Persistencia | sqlx (SQLite) |
| Modelo/serialización | serde, serde_json |
| Errores tipados | thiserror |
| Runtime async | tokio |
| Prompts | dialoguer |
| Tablas | comfy-table |
| Logs | tracing, tracing-subscriber |
~/.local/share/shell/shell.db # configuración (SQLite)
~/.local/share/shell/lima/ # LIMA_HOME aislado (VMs de `shell`)
~/.local/share/shell/templates/ # plantillas copiadas del repo `templates/`
~/.local/share/shell/machines/<name>.yaml # lima.yaml generado por shell
~/.local/share/shell/shells/<name>/home/ # tus dotfiles por shell (editables)
- macOS con Apple Silicon (driver
vz) y Lima:brew install lima. - El primer
shell createdescarga la imagen base (~600 MB), puede tardar.
cargo fmt
cargo clippy --all-targets -- -D warnings
cargo test
cargo build --release # binario en target/release/shellPruebas: reglas puras y casos de uso con adaptadores falsos (kernel) y
regresión del parseo de limactl (NDJSON y array) en lima.
Primera versión funcional: create / enter / remove / list / start /
stop. Pendiente/ideas: sincronización en vivo de dotfiles, port-forwarding,
snapshots de shells, y TUI.