·14 min de lectura

Una terminal en serio en Windows 11

Dos scripts convierten un Windows 11 recién instalado en una terminal de trabajo de verdad: WSL con Debian, Alacritty, zsh con un prompt útil, búsqueda en el historial y herdr para sesiones, paneles y una barra lateral de archivos que siguen vivos al cerrar la ventana.

La mayoría de las personas conoce la línea de comandos a través de la ventana que Windows abre por defecto: escriben un comando que encontraron en internet y la cierran en cuanto funciona. Para un comando suelto, eso basta. Para trabajar, no: no hay un historial en el que valga la pena buscar, no se ve en qué carpeta ni en qué rama se está, y todo desaparece al cerrar la ventana.

Esta guía instala la terminal que uso a diario, adaptada a Windows 11. Dos scripts hacen el trabajo, y cada pieza que instalan está explicada, para que más adelante pueda ajustarla en lugar de tratarla como una caja negra.

Qué va a tener al final

PiezaQué hace por usted
WSL 2 + DebianUn Linux real dentro de Windows. Las herramientas de casi cualquier tutorial funcionan aquí sin cambios
AlacrittyLa ventana de la terminal. Rápida, sencilla y configurada desde un solo archivo de texto
zsh + Oh My PoshEl shell, con un prompt que muestra la carpeta, la rama de git y qué cambió
AutosugerenciasPropone el resto de un comando a partir de su historial mientras escribe
fzfBúsqueda aproximada en el historial de comandos, en archivos y en carpetas
herdrPestañas, paneles divididos, una barra lateral de archivos y git, y sesiones que sobreviven a la ventana

Términos que va a encontrar

TérminoSignificado
TerminalLa ventana donde se escriben los comandos. En esta guía, Alacritty
ShellEl programa dentro de la terminal que lee y ejecuta esos comandos. Aquí, zsh
WSLWindows Subsystem for Linux: la forma en que Microsoft ejecuta Linux junto a Windows
DistribuciónUna versión empaquetada de Linux. Esta guía usa Debian
PromptLa línea que espera el siguiente comando. Puede mostrar contexto útil
AliasUn nombre corto para un comando largo, como gs para git status
PanelUn shell dentro de una ventana dividida. herdr puede mostrar varios lado a lado
SesiónSu conjunto de pestañas y paneles. herdr lo mantiene en marcha al cerrar la ventana
RepositorioUna carpeta de proyecto controlada por git, con todo su historial de cambios

1. El lado de Windows

bootstrap.ps1 instala WSL 2 con Debian, Alacritty y la fuente FiraCode Nerd Font, que trae los iconos que usan el prompt y la barra lateral. También limita la memoria que puede tomar WSL: por defecto puede reservar la mitad de la RAM del equipo y tarda en devolverla.

Abra PowerShell como administrador (clic derecho en el botón Inicio y luego Terminal (Administrador)), descargue el script y ejecútelo:

PowerShell
cd $env:USERPROFILE\Downloads
Invoke-RestMethod https://geekendzone.com/scripts/terminal/bootstrap.ps1 -OutFile bootstrap.ps1
Set-ExecutionPolicy -Scope Process Bypass -Force
.\bootstrap.ps1

Si el script indica que WSL se acaba de instalar, reinicie Windows antes de continuar. Se puede ejecutar de nuevo sin riesgo: cada paso omite lo que ya está instalado.

El script completo
PowerShell
#Requires -Version 5.1
# bootstrap.ps1: the Windows half of a serious terminal.
# Installs WSL 2 with Debian, Alacritty and the FiraCode Nerd Font, and caps WSL's memory.
# Run it in PowerShell opened as Administrator:
#   Set-ExecutionPolicy -Scope Process Bypass -Force
#   .\bootstrap.ps1
# Safe to re-run: every step skips what is already there.
$ErrorActionPreference = 'Stop'
function Say($msg) { Write-Host "==> $msg" -ForegroundColor Cyan }

$admin = ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()
         ).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $admin) { Write-Warning 'Open PowerShell with "Run as administrator" and try again.'; exit 1 }

# --- 1. WSL 2 + Debian -------------------------------------------------------------
Say 'WSL (updating)'
wsl.exe --update | Out-Host
$distros = (wsl.exe --list --quiet 2>$null) -replace "`0", '' | Where-Object { $_ -match '\S' }
$needsReboot = $false
if (-not ($distros -match '^Debian')) {
    Say 'Debian'
    wsl.exe --install -d Debian --no-launch | Out-Host
    $needsReboot = $true
}
wsl.exe --set-default-version 2 | Out-Null

# --- 2. Memory cap -------------------------------------------------------------------
# WSL takes up to half the RAM by default and is slow to give it back.
$wslconfig = Join-Path $env:USERPROFILE '.wslconfig'
if (-not (Test-Path $wslconfig)) {
    Say 'WSL memory cap (8 GB)'
    "[wsl2]`nmemory=8GB`n`n[experimental]`nautoMemoryReclaim=gradual`n" |
        Set-Content -Path $wslconfig -Encoding ASCII
}

# --- 3. Alacritty --------------------------------------------------------------------
$have = winget list --id Alacritty.Alacritty --exact --accept-source-agreements 2>$null | Select-String 'Alacritty'
if (-not $have) {
    Say 'Alacritty'
    winget install --id Alacritty.Alacritty --exact --silent `
        --accept-package-agreements --accept-source-agreements | Out-Host
}

# --- 4. FiraCode Nerd Font (the icons in the prompt and the sidebar) ---------------------
$fontName = 'FiraCode Nerd Font Mono'
$fontKey  = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts'
$haveFont = Get-ItemProperty -Path $fontKey | Get-Member -MemberType NoteProperty |
            Where-Object { $_.Name -like "$fontName*" }
if (-not $haveFont) {
    Say $fontName
    $zip = Join-Path $env:TEMP 'FiraCode-NF.zip'
    $dir = Join-Path $env:TEMP 'FiraCode-NF'
    Invoke-WebRequest -UseBasicParsing -OutFile $zip `
        -Uri 'https://github.com/ryanoasis/nerd-fonts/releases/latest/download/FiraCode.zip'
    Expand-Archive -Path $zip -DestinationPath $dir -Force
    foreach ($style in 'Regular', 'Bold') {
        $file = "FiraCodeNerdFontMono-$style.ttf"
        Copy-Item (Join-Path $dir $file) (Join-Path $env:WINDIR "Fonts\$file") -Force
        $label = if ($style -eq 'Regular') { $fontName } else { "$fontName $style" }
        Set-ItemProperty -Path $fontKey -Name "$label (TrueType)" -Value $file
    }
    Remove-Item $zip, $dir -Recurse -Force
}

Say 'Windows side done.'
if ($needsReboot) { Write-Host '  Restart Windows now: WSL was just installed.' -ForegroundColor Yellow }
Write-Host '  Next: open "Debian" from the Start menu, create your Linux user, and run terminal-setup.sh.'

¿Por qué Debian y no Ubuntu? Ambos ejecutan todas las herramientas de esta guía. La imagen de Debian para WSL arranca menos servicios en segundo plano, así que consume menos memoria en una laptop que además tiene que mover Windows.

2. Cree su usuario de Linux

Abra Debian desde el menú Inicio. La primera vez le pedirá un nombre de usuario y una contraseña. Esta cuenta es distinta de su cuenta de Windows. Anote la contraseña: Linux la pide cada vez que un comando necesita permisos de administrador (sudo).

3. El lado de Linux

En esa misma ventana de Debian, descargue el segundo script y ejecútelo:

bash
sudo apt-get update && sudo apt-get install -y curl
curl -fsSLO https://geekendzone.com/scripts/terminal/terminal-setup.sh
bash terminal-setup.sh

Instala zsh y sus complementos, Oh My Posh, fzf y herdr, escribe un ~/.zshrc comentado, deja zsh como shell predeterminado y, como Alacritty ya está instalado, escribe su configuración del lado de Windows. Igual que el primero, se puede ejecutar de nuevo sin riesgo.

El script completo
bash
#!/usr/bin/env bash
# terminal-setup.sh: a serious terminal inside WSL (Debian or Ubuntu).
# zsh + Oh My Posh + autosuggestions + syntax highlighting + fzf + herdr (with its
# sidebar), and, if Alacritty is installed on Windows, its config.
# Safe to re-run: every step skips what is already there.
set -euo pipefail

log() { printf '\033[1;34m==>\033[0m %s\n' "$*"; }
BIN="$HOME/.local/bin"
mkdir -p "$BIN"
export PATH="$BIN:$PATH"

# --- 1. Base packages ---------------------------------------------------------
log "Base packages"
sudo apt-get update -qq
sudo apt-get install -y -qq zsh git curl ca-certificates fzf unzip tree >/dev/null

# --- 2. Oh My Posh (the prompt) -----------------------------------------------
if ! command -v oh-my-posh >/dev/null; then
  log "Oh My Posh"
  curl -fsSL https://ohmyposh.dev/install.sh | bash -s -- -d "$BIN" >/dev/null
fi
mkdir -p "$HOME/.config/ohmyposh"
[ -f "$HOME/.config/ohmyposh/atomic.omp.json" ] || curl -fsSL -o "$HOME/.config/ohmyposh/atomic.omp.json" \
  https://raw.githubusercontent.com/JanDeDobbeleer/oh-my-posh/main/themes/atomic.omp.json

# --- 3. zsh plugins -----------------------------------------------------------
for p in zsh-autosuggestions zsh-syntax-highlighting; do
  [ -d "$HOME/.zsh/plugins/$p" ] || {
    log "$p"
    git clone -q --depth 1 "https://github.com/zsh-users/$p" "$HOME/.zsh/plugins/$p"
  }
done

# --- 4. herdr (sessions, tabs and panes that survive closing the window) ------
if ! command -v herdr >/dev/null; then
  log "herdr"
  curl -fsSL https://herdr.dev/install.sh | sh >/dev/null
fi
if ! herdr plugin list 2>/dev/null | grep -q 'herdr-sidebar'; then
  log "herdr sidebar plugin"
  # Pin the latest release: a bare install tracks the main branch
  tag=$(curl -fsSLI -o /dev/null -w '%{url_effective}' https://github.com/alexarthurs/herdr-sidebar/releases/latest)
  herdr plugin install alexarthurs/herdr-sidebar/plugins/herdr-sidebar --ref "${tag##*/}" --yes >/dev/null 2>&1
fi
cfg="$HOME/.config/herdr/config.toml"
mkdir -p "$(dirname "$cfg")"
grep -q 'herdr-sidebar.open-sidebar' "$cfg" 2>/dev/null || cat >> "$cfg" <<'EOF'

# Sidebar: Ctrl+B then f toggles it, d opens source control, Shift+F finds a file.
[[keys.command]]
key = "prefix+f"
type = "plugin_action"
command = "herdr-sidebar.open-sidebar"
description = "sidebar: toggle"

[[keys.command]]
key = "prefix+d"
type = "plugin_action"
command = "herdr-sidebar.show-git"
description = "sidebar: source control"

[[keys.command]]
key = "prefix+shift+f"
type = "plugin_action"
command = "herdr-sidebar.quick-open"
description = "sidebar: quick open file"
EOF

# --- 5. ~/.zshrc ----------------------------------------------------------------
marker="# terminal-setup.sh"
if ! grep -qF "$marker" "$HOME/.zshrc" 2>/dev/null; then
  [ -f "$HOME/.zshrc" ] && mv "$HOME/.zshrc" "$HOME/.zshrc.bak-$(date +%Y%m%d-%H%M%S)"
  log "~/.zshrc"
  cat > "$HOME/.zshrc" <<'EOF'
# terminal-setup.sh: edit freely; machine-specific lines go in ~/.zshrc.local
export PATH="$HOME/.local/bin:$PATH"
export EDITOR=nano

# History: large, shared between panes, no duplicates
HISTFILE=~/.zsh_history HISTSIZE=10000 SAVEHIST=10000
setopt SHARE_HISTORY HIST_IGNORE_ALL_DUPS HIST_REDUCE_BLANKS

# Completion menu you can move through with the arrow keys
autoload -Uz compinit && compinit
zstyle ':completion:*' menu select

# Prompt, suggestions from history, and fuzzy search (Ctrl+R, Ctrl+T, Alt+C)
eval "$(oh-my-posh init zsh --config ~/.config/ohmyposh/atomic.omp.json)"
source ~/.zsh/plugins/zsh-autosuggestions/zsh-autosuggestions.zsh
eval "$(fzf --zsh)"

# Navigation and listing
alias ..="cd .." ...="cd ../.."
alias ll="ls -lah --color=auto" la="ls -A --color=auto"
mkcd() { mkdir -p "$1" && cd "$1"; }

# Safer defaults: ask before overwriting or deleting
alias cp="cp -iv" mv="mv -iv" rm="rm -Iv"

# Git
alias gs="git status" ga="git add ." gc="git commit -m" gp="git push"
alias gl="git log --oneline --graph --decorate -15" gd="git diff"

# Packages and maintenance
alias pkgi="sudo apt install" pkgs="apt search" pkgr="sudo apt remove"
alias zconf='${EDITOR} ~/.zshrc' zreload='source ~/.zshrc'
update() {
  echo "==> apt";  sudo apt update && sudo apt upgrade -y
  echo "==> oh-my-posh"; oh-my-posh upgrade
  echo "==> herdr"; herdr update
  local p; for p in ~/.zsh/plugins/*/; do
    echo "==> $(basename "$p")"; git -C "$p" pull --ff-only -q
  done
}

[ -f ~/.zshrc.local ] && source ~/.zshrc.local
# Must be last: it wraps every widget defined above
source ~/.zsh/plugins/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh
EOF
fi

# --- 6. zsh as the login shell ------------------------------------------------
if [ "$(getent passwd "$USER" | cut -d: -f7)" != "$(command -v zsh)" ]; then
  log "zsh as your login shell"
  sudo chsh -s "$(command -v zsh)" "$USER"
fi

# --- 7. Alacritty on Windows: open this distro straight into herdr -------------
if grep -qi microsoft /proc/version 2>/dev/null && [ -x "/mnt/c/Program Files/Alacritty/alacritty.exe" ]; then
  appdata=$(wslpath "$(cmd.exe /c 'echo %APPDATA%' 2>/dev/null | tr -d '\r')")
  dst="$appdata/alacritty/alacritty.toml"
  if [ ! -f "$dst" ]; then
    log "Alacritty config ($dst)"
    mkdir -p "$(dirname "$dst")"
    cat > "$dst" <<EOF
[terminal.shell]
program = "wsl.exe"
args = ["-d", "$WSL_DISTRO_NAME", "--cd", "~", "-e", "sh", "-lc", 'export SHELL=$(command -v zsh); exec "\$HOME/.local/bin/herdr"']

[env]
TERM = "xterm-256color"

[font]
size = 12.0
normal = { family = "FiraCode Nerd Font Mono", style = "Regular" }

[scrolling]
history = 10000

[colors.primary]
background = "#000000"
foreground = "#c0caf5"

[colors.normal]
black = "#15161e"
red = "#f7768e"
green = "#9ece6a"
yellow = "#e0af68"
blue = "#7aa2f7"
magenta = "#bb9af7"
cyan = "#7dcfff"
white = "#a9b1d6"

[colors.bright]
black = "#414868"
red = "#f7768e"
green = "#9ece6a"
yellow = "#e0af68"
blue = "#7aa2f7"
magenta = "#bb9af7"
cyan = "#7dcfff"
white = "#c0caf5"

[mouse]
bindings = [{ mouse = "Right", action = "Paste" }]
EOF
  fi
fi

log "Done. Open Alacritty (or run: exec zsh)."

Cuando termine, cierre la ventana de Debian y abra Alacritty desde el menú Inicio. A partir de ahora, esa es su terminal.

4. Alacritty: una ventana que entra directo a Linux

Alacritty no agrega pestañas, menús ni pantallas de ajustes. Todo vive en un archivo de texto, %APPDATA%\alacritty\alacritty.toml, y la parte más importante es el primer bloque:

toml
[terminal.shell]
program = "wsl.exe"
args = ["-d", "Debian", "--cd", "~", "-e", "sh", "-lc", 'export SHELL=/usr/bin/zsh; exec "$HOME/.local/bin/herdr"']

Cada vez que se abre la ventana, arranca Debian en su carpeta personal y ejecuta herdr, que abre zsh dentro de sus paneles. SHELL se define al entrar porque herdr lo usa para elegir el shell de los paneles nuevos. El resto del archivo fija la fuente, los colores (Tokyo Night sobre negro puro) y el pegado con clic derecho.

5. El shell: contexto antes de escribir

El prompt muestra la carpeta, la rama y los cambios pendientes antes de ejecutar nada.
El prompt hace la primera revisión. main ≢ ?1 ~1 se lee así: rama main, todavía sin copia remota, un archivo nuevo y uno modificado. gs solo lo confirma.

El prompt es Oh My Posh con el tema atomic. Muestra la carpeta actual, la rama de git, cuántos archivos cambiaron y cuánto tardó el último comando. La mayoría de los errores en una terminal vienen de ejecutar un comando en la carpeta o en la rama equivocada; el prompt mantiene ambas a la vista.

Un comando escrito a medias, con el resto sugerido en gris.
Basta con escribir git l. El texto gris es el último comando del historial que coincide. La flecha derecha lo acepta.

Las autosugerencias completan un comando a partir de su propio historial mientras escribe. Pulse la flecha derecha para aceptar la sugerencia, o siga escribiendo para ignorarla.

La búsqueda de fzf filtrando el historial por las letras apt.
Ctrl+R busca en todo lo que ha ejecutado. Las letras no tienen que estar juntas: apt también coincide repartida en graph … decorate.

fzf agrega tres búsquedas:

TeclasBusca
Ctrl+REn el historial de comandos
Ctrl+TArchivos bajo la carpeta actual, y los inserta en la línea de comandos
Alt+CCarpetas bajo la carpeta actual, y entra en la que elija

Los alias acortan los comandos más usados. El ~/.zshrc que escribe el script incluye estos:

AliasEjecuta
llls -lah: todos los archivos, con tamaños y fechas
gs / gdgit status / git diff
glLos últimos 15 commits en forma de gráfico
ga, gc "mensaje", gpPreparar todo, hacer commit, subir
mkcd nombreCrear una carpeta y entrar en ella
zconf / zreloadEditar ~/.zshrc / recargarlo
updateActualizar el sistema y todas las herramientas de esta guía

Además, cp, mv y rm preguntan antes de sobrescribir o borrar. El resaltado de sintaxis colorea el comando mientras lo escribe, así que un error de tipeo aparece en rojo antes de pulsar Enter.

6. herdr: sesiones, paneles y barra lateral

herdr funciona entre Alacritty y el shell. Cerrar la ventana no termina su trabajo: las pestañas, los paneles y los programas en ejecución siguen vivos, y la próxima ventana de Alacritty se vuelve a conectar a ellos, siempre que WSL siga en marcha.

Tres columnas: la barra lateral de archivos, el historial de git en un panel y el árbol del proyecto en otro.
Una ventana, un proyecto. La barra lateral marca la carpeta reports porque tiene cambios sin commit; los dos paneles son shells independientes en la misma carpeta.

Todas las teclas de herdr empiezan con Ctrl+B. Púlselo, suéltelo y luego pulse la siguiente tecla:

Después de Ctrl+BHace
cPestaña nueva
vDivide el panel actual en dos
xCierra el panel actual
h / lPasa al panel de la izquierda / derecha
wCambia de espacio de trabajo (uno por proyecto)
fMuestra u oculta la barra lateral
dAbre la vista de control de versiones de la barra lateral
Shift+FBusca un archivo por nombre
?Todas las teclas y ajustes

El ratón también funciona: un clic en un panel lo activa, arrastrar un borde cambia su tamaño y el clic derecho abre menús.

Para agentes, plugins, automatización y herdr como servicio, consulte la Guía práctica de herdr.

La vista de control de versiones de la barra lateral con dos archivos cambiados y un cuadro para el commit.
Git sin salir de la terminal. M es un archivo modificado y U uno sin seguimiento. Escriba un mensaje y pulse Enter para hacer el commit; las secciones de abajo guardan el gráfico, las ramas y los stashes.

7. Mantenerla al día

Ejecute update una vez por semana. Actualiza los paquetes de Debian, Oh My Posh, herdr y los complementos de zsh, uno tras otro, y muestra cada paso para que vea qué cambió.

Siguientes pasos

  • Su propia configuración. Todo lo personal va en ~/.zshrc (o en ~/.zshrc.local) y en el archivo de Alacritty. Cambie una cosa a la vez y ejecute zreload.
  • Agentes de IA para programar. Claude Code, Gemini CLI y herramientas similares funcionan justo en este tipo de terminal. herdr muestra en cada pestaña si su agente está trabajando o esperando una respuesta, lo que hace manejable tener dos o tres a la vez.
  • La versión completa. La configuración que uso en todos mis equipos, con más alias, un gestor de archivos, una línea de estado para Claude Code y un update más completo, está en mi repositorio de dotfiles.

// share