Configuración local extraida de cortex: terminal, shell, prompt, helpers de AI CLI y herramientas de desarrollo para macOS.
GitHub Actions ejecuta un smoke check mínimo en pull requests y pushes a main: sintaxis Zsh/Fish/Bash, el harness aislado de Fish, JSON con jq, TOML con python3/tomllib, y ./install.sh --check cuando el instalador lo soporte.
- Terminal: Ghostty y Alacritty
- Shell: Zsh nativo de macOS + profile Fish core opt-in (W2)
- Prompt: Starship — tema Gruvbox Dark
- Multiplexor: tmux + helpers de sesión
- Barra macOS: SketchyBar con tema Gruvbox
- Window manager macOS: yabai + skhd opcional y gradual
- Keyboard remaps macOS: Karabiner-Elements con profile
cortex - Editor terminal: Neovim basado en LazyVim/Gentleman.Dots con overlay RefactorIA
- Ls: eza
- AI CLI UX: Claude Code statusline, OpenCode helpers y cmux local/remoto
- Workflow docs: cmux workflow, Herdr workflow y keymaps prácticos
- Supply-chain guardrails: defaults globales para
uv,npm,pnpmybun - Fuente: FiraCode Nerd Font + variante custom RefactorIA
mkdir -p ~/.cortex
git clone <repo-url> ~/.cortex/cortex-dotfiles
cd ~/.cortex/cortex-dotfiles
bash install.shPara auditar el entorno sin instalar paquetes ni modificar archivos:
bash install.sh --checkPara previsualizar lo que haría la instalación sin mutar archivos, instalar paquetes, arrancar servicios ni crear local/env.zsh:
bash install.sh --dry-runEl instalador macOS:
- Instala dependencias via Homebrew (cmux, starship, tmux, lazygit, neovim, eza, sketchybar, yabai, skhd, Karabiner-Elements, FiraCode Nerd Font)
- Hace backup de configs existentes con timestamp
- Crea symlinks de los dotfiles y guardrails globales (
.npmrc,pnpm/rc,.bunfig.toml,uv.toml) - Intenta seleccionar el profile
cortexde Karabiner sikarabiner_cliestá disponible - Intenta arrancar/recargar
sketchybar,yabaiyskhdsin cortar la instalación si macOS requiere permisos - Crea
local/env.zshdesde el template
W1 agrega solamente una base de Flake y Home Manager al repositorio. No instala Nix, no genera flake.lock, no activa Home Manager y no cambia ningún archivo del host.
bash scripts/nix-preflight.sh
bash scripts/test-nix-preflight.sh
bash -n scripts/nix-preflight.sh scripts/test-nix-preflight.shEl preflight es de solo lectura y sin red: usa --offline y --no-write-lock-file. En una máquina sin Nix termina con estado no cero de forma esperada, pero no cambia el host. Su contrato de readiness exige macOS arm64 o x86_64, un usuario y HOME válidos, Nix disponible y los inputs bloqueados ya disponibles localmente. Una configuración Fish existente es una advertencia, no un bloqueo: W1 no la administra.
| Área | Owner en W1 |
|---|---|
/opt/homebrew/bin/fish |
Homebrew actual |
| Symlinks, servicios y fuentes actuales | install.sh |
| Zsh y Ghostty | Configuración actual, sin cambios |
~/.config/fish/conf.d/99-local.fish |
Host; reservado para secretos/estado privado futuro, no creado ni gestionado por Nix |
flake.nix y nix/home.nix |
Base inactiva de Home Manager |
El bootstrap queda explícitamente diferido a un work unit revisado. Después de instalar Nix por fuera de este repositorio, ese trabajo podrá generar el lock con:
nix --extra-experimental-features 'nix-command flakes' flake lockEse comando resuelve inputs y modifica flake.lock; por eso no es parte de W1. También quedan diferidos cualquier home-manager switch, nix run ... switch, instalación de paquetes, cambio de shell, chsh, servicios o extensiones Fish fuera del core W2.
La configuración pura de W1 es homeConfigurations.jbarbat: declara username = "jbarbat", homeDirectory = "/Users/jbarbat" y system = "aarch64-darwin" de forma explícita y revisable. Una futura activación debe seleccionar ese target sin derivar valores de la máquina en tiempo de evaluación.
Para volver atrás de W1 basta quitar flake.nix, nix/, scripts/nix-preflight.sh, scripts/test-nix-preflight.sh y esta sección. No hay estado de host que revertir porque W1 no activó nada.
W2 agrega un profile Fish inerte y opt-in: no cambia el login shell, no activa Home Manager, no toca starship.toml ni crea 99-local.fish.
- Copiá
fish/conf.d/99-local.fish.examplea~/.config/fish/conf.d/99-local.fishsi necesitás paths o editor locales. - Mantené ese archivo fuera de Git: carga después de los defaults rastreados.
- Probá el profile en una sesión Fish; Zsh permanece sin cambios.
| Área | Owner en W2 |
|---|---|
fish/conf.d/10-core.fish y fish/functions/*.fish |
Fuentes rastreadas de Fish |
~/.config/fish/conf.d/99-local.fish |
Host; override privado no gestionado |
| Home Manager | Mapea cada fuente Fish explícitamente; no gestiona el directorio completo, historial ni variables Fish |
| Starship | Inicialización solo interactiva y cuando el comando existe; su TOML sigue fuera de este profile |
El core incluye defaults de entorno, selección de editor, aliases Git/navegación y dev, barbat, innit con sus destinos relacionados (innit-apis, innit-mobile, innit-webs, innit-pcsoft), además de la navegación simple con cowork, personal, tools, worktrees y work. La creación, gestión y protecciones de Git worktrees siguen diferidas para W3+, junto con Git/SSH identities, PCSoft, tmux, screenshots, Herdr y helpers de agentes.
Para validar sin tocar configuración real:
/opt/homebrew/bin/fish fish/tests/w2-core.fishLa evaluación Nix permanece diferida: esta unidad no genera flake.lock ni ejecuta activación.
W3 suma helpers Fish opt-in para identidades Git, protección de archivos PCSoft y worktrees; no crea ~/.ssh/config, no clona durante la configuración y no modifica la identidad global de Git.
- Copiá
fish/conf.d/99-local.fish.examplea tu99-local.fishprivado y definí las cuatro variablesGIT_*_NAMEyGIT_*_EMAIL. - En un repositorio, usá
git-workdevogit-personaldev; si falta un valor privado, el helper falla antes de cambiar la configuración local o el remote. - Usá
clone-workdevoclone-personaldevsolo cuando quieras clonar: enrutan la URL mediantegithub-workdevogithub-personaldev.
| Área | Interfaz rastreada | Estado privado del host |
|---|---|---|
| Identidades Git | git-workdev, git-personaldev, git-whoami, clone-* y aliases SSH github-workdev / github-personaldev |
nombre, email, claves y ~/.ssh/config |
| PCSoft | is-pcsoft-forbidden, is-pcsoft-editable, edit |
IDE Windows y estado del proyecto |
| Worktrees | wtadd, wtlist, wtremove; wtadd bloquea repos PCSoft antes de mutar |
directorios de worktree y procesos locales |
edit rechaza extensiones PCSoft prohibidas y pide confirmación para las editables. wtremove elimina solamente el worktree nombrado: verificá wtlist antes de usarlo. Home Manager mapea cada función explícitamente; no administra el directorio completo, claves, remotes, historial ni variables privadas.
Para validar sin tocar identidades reales ni la red:
/opt/homebrew/bin/fish fish/tests/w3-helpers.fishW4b agrega ss, last, ssd e imgclip sin capturar la pantalla ni leer el clipboard durante la carga. SCREENSHOTS_DIR usa el override solo si apunta a un directorio existente; si no, conserva el fallback de macOS: ~/Screenshots cuando existe y luego ~/Desktop. Home Manager mapea cada función explícitamente y no administra el directorio, screenshots ni clipboard del host.
Para validar con HOME, PATH y comandos macOS falsos aislados:
/opt/homebrew/bin/fish fish/tests/w4b-screenshots.fishADVERTENCIA: por elección explícita del owner, cc ejecuta Claude Code con --dangerously-skip-permissions y oc/ocb ejecutan OpenCode con --auto; estos shortcuts intencionalmente omiten o autoaprueban permisos. W6 agrega cc, oc, ocb, ccx, ccd y ccclip como helpers Fish opt-in en el directorio validado; ccx entrega el contexto por stdin y ccclip escribe al clipboard solo al invocarse. No incluye ccb.
| Área | Owner en W6 |
|---|---|
| Helpers y soporte privado | fish/functions/{_cortex_resolve_target,_cortex_run_agent,cc,oc,ocb,ccx,ccd,ccclip}.fish |
| Home Manager | Mapea cada una de esas funciones de forma explícita; no administra binarios de agentes, clipboard, worktrees, estado, historial ni configuración de proveedores |
Para validar con agentes y clipboard falsos aislados:
/opt/homebrew/bin/fish fish/tests/w6-agent-helpers.fishdotfiles/
├── claude/ # Claude Code statusline
├── docs/ # Referencias operativas y keymaps
├── ghostty/ # Config Ghostty, muxy legado y shaders
├── fonts/ # Fuente RefactorIA y script de regeneración
├── npm/ # Global npm defaults (~/.npmrc)
├── pnpm/ # Global pnpm defaults (~/Library/Preferences/pnpm/rc)
├── bun/ # Global bun defaults (~/.bunfig.toml)
├── uv/ # Global uv defaults (~/.config/uv/uv.toml)
├── zsh/
│ ├── zshrc # Bootstrap: dotfiles primero, Cortex al final (~/.zshrc)
│ ├── cortex-dotfiles.zsh # Entrypoint propio del profile de dotfiles
│ └── scripts/
│ ├── claude-helpers.zsh # Integración Claude Code
│ ├── cmux-sidebar-refresh.sh # Metadata Cortex para cmux
│ ├── ssh-helpers.zsh # cmux SSH y SSH convencional
│ ├── git-helpers.zsh # Identidades Git y clone helpers
│ ├── tmux-helpers.zsh # Helpers tmux
│ ├── worktree-helpers.zsh # Helpers git worktree
│ ├── screenshots.zsh # Manejo de screenshots macOS
│ └── pcsoft-helpers.zsh # Protección archivos PCSoft
├── tmux/ # Config tmux
├── lazygit/ # Config lazygit
├── karabiner/ # Config Karabiner-Elements (~/.config/karabiner/karabiner.json)
├── nvim/ # Notas de configuración Neovim RefactorIA
├── sketchybar/ # Barra macOS y plugins
├── yabai/ # Window manager macOS opcional
├── skhd/ # Hotkeys macOS para yabai
├── starship/
│ └── starship.toml # Prompt (~/.config/starship.toml)
├── local/
│ └── env.zsh.example # Template de config local (gitignored)
└── install.sh
Nota migración cmux: el path legacy
~/Library/Application Support/com.cmuxterm.app/config.ghosttyya no está gestionado por estos dotfiles. Si todavía existe en tu máquina, podés borrarlo manualmente sin afectar la configuración actual.
Este repo sigue siendo standalone: install.sh no requiere tener Cortex instalado. Administra el entrypoint fijo ~/.config/cortex-dotfiles/shell/cortex-dotfiles.zsh, sus archivos enlazados y las variables CORTEX_DOTFILES_* documentadas acá.
El bootstrap carga dotfiles primero y después intenta cargar ~/.cortex/shell/cortex.zsh. Esa segunda ruta y las variables core que exponga pertenecen a Cortex; este repo solo las consume. Ambos fragments son opcionales y un error en uno no impide intentar cargar el otro.
La coordinación vigente del contrato shell se sigue en cortex #1259. Las migraciones de artefactos actualmente versionados en este repo se tratan por separado en cortex-dotfiles #31.
- Cortex Agent State v1: contrato
cortex.agent_state.v1para normalizar estados de agentes hacia Herdr, statuslines, SketchyBar y notificaciones.
| Comando | Descripción |
|---|---|
gs, ga, gc, gp, gl |
Git shortcuts |
dev, barbat, cowork, personal, tools, worktrees |
Navegación rápida en ~/dev |
work, innit, innit-apis, innit-mobile, innit-webs, innit-pcsoft |
Navegación rápida de trabajo |
dotfiles |
Navegación rápida al repo de dotfiles |
cc [path] |
Abrir Claude Code |
oc [path] |
Abrir OpenCode |
ccclip <files> |
Copiar código al clipboard |
tcc, tdev, ta, tn, tl, tk |
Helpers tmux (tcc abre Claude Code en tmux) |
wtadd, wtlist, wtremove |
Helpers de git worktrees |
sshx, sshc, sshx-doctor |
cmux SSH persistente, SSH convencional y diagnóstico |
cortex.agent_state.v1, agent-state |
Reportar/listar estado local de agentes Cortex y, dentro de Herdr, actualizar el pane actual |
ss [n] |
Listar últimos screenshots |
last [-c|-o] |
Último screenshot |
ll, la, lt |
Listar archivos (eza) |
ep |
Editar este profile |
reload |
Recargar zsh |
refactoria |
Mostrar el logo RefactorIA en Braille Unicode |
help-profile |
Ver todos los comandos |
Editá local/env.zsh (gitignored) para configurar:
SCREENSHOTS_DIR— directorio de screenshotsWORKSPACE_DIR— directorio raíz de tus proyectosBARBATDEV_DIR— repos de barbatdev, por defecto$WORKSPACE_DIR/barbatdevWORK_PROJECTS_DIR— repos de trabajo, por defecto$WORKSPACE_DIR/innit-sasPERSONAL_PROJECTS_DIR— repos locales, por defecto$WORKSPACE_DIR/localTOOLS_DIRyWORKTREES_DIR— herramientas locales y worktreesCORTEX_DOTFILES_DIR— repo fuente de dotfiles, por defecto$BARBATDEV_DIR/cortex/cortex-dotfilesCORTEX_DOTFILES_MULTIPLEXER— fallback standalone para helpers, por defectocmux;CORTEX_MULTIPLEXERde Cortex tiene precedenciaOPENCODE_DEFAULT_FLAGS— flags por defecto paraocINNIT_DIRy overridesINNIT_*_DIR— raíz y subdirectoriosapis,mobile,websypcsoft- Aliases y paths personales
Referencia completa: Herdr workflow. Atajos prácticos: keymaps.
El profile Fish también expone h, hs, hl, hhere, hmain, hrole, hnew, hfocus, hside, hscratch, hname, whereami, sshc, sshx y sshx-doctor; Home Manager mapea cada función de forma explícita.
Usá hremote desde tu terminal local en macOS. No hagas ssh primero y después intentes levantar herdr dentro de esa sesión remota.
- Para pegar una imagen del clipboard local en la terminal remota, usá
Ctrl+Vpor defecto (noCmd+V). herdr --remotepuentea ese pegado copiando la imagen a un archivo temporal remoto y pegando el path resultante en la shell remota.- Una sesión SSH normal no puede leer el clipboard del escritorio local de macOS, así que ese flujo depende de Herdr corriendo del lado local.
- Para archivos que no sean imágenes del clipboard, puede seguir haciendo falta un fallback separado de transferencia.
La config macOS enlaza sketchybar/ en ~/.config/sketchybar. El diseño es sobrio, notch-safe y usa la paleta dark/green de InnIT.
Layout activo:
| Pantalla | Uso | Layout |
|---|---|---|
Mac Retina (display=1) |
apps generales: Discord, WhatsApp, Mail, Postman, Zen Browser | app activa + network, volumen, calendario, hora, batería |
ViewSonic vertical (display=2) |
auxiliar/random, Ghostty/Herdr y Claude de formato vertical | brand + panel/spaces + app activa; derecha: RAM + CPU + hora |
LG Ultrawide (display=3) |
mixto: Ghostty/Herdr, Claude, ChatGPT, Obsidian | brand + panel/spaces + app activa; derecha: RAM + CPU + hora |
4K derecho (display=4) |
Ghostty/Herdr exclusivo | brand + panel/spaces + app activa; derecha: RAM + CPU + hora |
El centro queda libre para evitar el notch y reducir ruido visual.
Interacciones:
| Item | Acción |
|---|---|
| Glyph RefactorIA | abre ~/dev |
| Spaces | enfocan el space si yabai está corriendo |
| Volumen | mute/unmute |
| Batería | abre Battery Settings |
| Fecha/hora | abre Calendar |
La barra asume Mac con notch y varios monitores: el centro queda libre y evita widgets de contexto remoto (git, issue/PR, SDD, brains, timer), porque el trabajo operativo corre en Herdr remoto.
El layout cambia automáticamente al recargar SketchyBar: con un solo display, el Retina mantiene los indicadores de estado útiles; con varios displays, el Retina queda liviano y el layout completo se mueve al externo disponible.
Si macOS deja monitores externos como Online aunque estén desconectados, se puede forzar perfil con:
~/.config/sketchybar/sketchybar-profile.sh portable
~/.config/sketchybar/sketchybar-profile.sh office
~/.config/sketchybar/sketchybar-profile.sh autoLa separación global de ventanas queda desactivada en yabai (top_padding=0, bottom_padding=0, left_padding=0, right_padding=0, window_gap=0) para evitar márgenes persistentes después de reiniciar.
El instalador intenta activarla automáticamente. Si macOS bloquea el servicio o querés hacerlo manualmente:
brew services start sketchybarPara recargar cambios manualmente:
sketchybar --reloadAtajos resumidos junto al resto del stack: keymaps.
La config incluida es gradual y no usa scripting addition: no requiere desactivar SIP. Sirve para acostumbrarse al tiling y navegación por teclado sin cambiar partes sensibles de macOS.
El instalador crea symlinks en ambas rutas de configuración: ~/.config/yabai/yabairc y ~/.yabairc para yabai, ~/.config/skhd/skhdrc y ~/.skhdrc para skhd. Se mantienen las rutas legacy porque los launch services de yabai/skhd leen esas ubicaciones por defecto.
Decisiones:
| Tema | Decisión |
|---|---|
| Leader | Option + Command |
| Scripting addition | No se usa |
| Raycast | Evitar shortcuts con Option + Command para reducir colisiones |
| Apps flotantes | System Settings, Calculator, Activity Monitor y diálogos de Finder |
| SketchyBar | Los spaces de la barra usan yabai si está disponible |
El instalador intenta arrancar o recargar estos servicios automáticamente después de enlazar la configuración. Activación manual de fallback:
yabai --start-service
skhd --start-servicePara detenerlos:
yabai --stop-service
skhd --stop-serviceSi macOS bloquea los servicios, habilitá permisos en:
System Settings → Privacy & Security → Accessibility
Binarios a permitir:
/opt/homebrew/bin/yabai
/opt/homebrew/bin/skhd
Atajos principales (option + command):
| Atajo | Acción |
|---|---|
Option + Command + Left/Down/Up/Right |
Focus izquierda/abajo/arriba/derecha |
Option + Command + Shift + Left/Down/Up/Right |
Mover ventana en el layout |
Option + Command + 1..9 |
Ir al space |
Option + Command + Shift + 1..9 |
Mover ventana al space y seguirla |
Option + Command + f |
Flotar/desflotar ventana |
Option + Command + b |
Balancear layout |
Option + Command + r |
Resetear gap a cero + balance + recargar SketchyBar |
Option + Command + / |
Mostrar ayuda de atajos |
Option + Command + Shift + r |
Recargar yabai/skhd/sketchybar |
Notas de uso:
Optiones la tecla que macOS también llamaAlt.- El bloque
devde SketchyBar también abre la ayuda de atajos con click. - Algunos comandos no hacen nada si no hay una ventana gestionada por
yabaio si no existe una ventana vecina en esa dirección. - Si Raycast usa el mismo shortcut, deshabilitá ese hotkey en Raycast o cambialo para dejar
Option + Commandaskhd. - Para recargar cambios manualmente:
skhd --reload && yabai --restart-service && sketchybar --reload.
La config enlaza karabiner/karabiner.json en ~/.config/karabiner/karabiner.json y define un profile default llamado cortex.
Remap incluido:
| Tecla | Acción |
|---|---|
Caps Lock tap |
Escape |
Caps Lock hold |
Left Control |
Right Command |
Delete backward |
El instalador instala karabiner-elements via Homebrew cask si no encuentra karabiner_cli ni la app, hace backup del JSON existente y crea el symlink. Si karabiner_cli está disponible, intenta seleccionar el profile cortex como best-effort.
macOS puede requerir permisos en:
System Settings → Privacy & Security → Input Monitoring
System Settings → Privacy & Security → Accessibility
Después de instalar o cambiar permisos, puede hacer falta abrir o reiniciar Karabiner-Elements para que cargue la config versionada.
El prompt usa una variante local de FiraCode Nerd Font Mono con el glyph de la barba de RefactorIA en el Private Use Area.
| Dato | Valor |
|---|---|
| Family | FiraCode Nerd Font Mono Beard |
| Archivo instalado | ~/Library/Fonts/FiraCodeNerdFontMonoBeard-Reg.ttf |
| Codepoint | U+F0F00 |
| Glyph test | python3 -c 'print("\U000F0F00")' |
La config de Starship usa este glyph PUA directamente. Si la terminal no tiene seleccionada FiraCode Nerd Font Mono Beard, el prompt puede mostrar un cuadrado/tofu en lugar de la barba. En macOS, install.sh instala la fuente y deja configurado Ghostty con esa family.
Para regenerar la fuente:
mkdir -p ~/Downloads/refactoria/build
magick ~/Downloads/refactoria/RefactorIA.png -threshold 50% -negate ~/Downloads/refactoria/build/refactoria.bmp
potrace ~/Downloads/refactoria/build/refactoria.bmp -s -o ~/Downloads/refactoria/build/refactoria.svg
fontforge -script fonts/patch_beard.py \
--font ~/Library/Fonts/FiraCodeNerdFontMono-Regular.ttf \
--svg ~/Downloads/refactoria/build/refactoria.svg \
--output-dir ~/Downloads/refactoria/build
cp ~/Downloads/refactoria/build/FiraCodeNerdFontMonoBeard-Reg.ttf ~/Library/Fonts/One-liner para renderizar el glyph con Pillow:
python3 - <<'PY'
from PIL import Image, ImageDraw, ImageFont
font = ImageFont.truetype('~/Library/Fonts/FiraCodeNerdFontMonoBeard-Reg.ttf', 64)
img = Image.new('RGB', (128, 128), 'black')
draw = ImageDraw.Draw(img)
draw.text((32, 24), '\U000F0F00', font=font, fill='white')
img.save('/tmp/refactoria-glyph.png')
PYEl comando refactoria imprime una versión Braille Unicode del logo. Es intencionalmente bajo demanda para no meter ruido visual en cada shell nueva.
refactoriaUso recomendado:
- screenshots o demos donde conviene una marca visual sin depender de imágenes
- intros manuales antes de grabar o compartir una terminal
- banners puntuales en scripts propios, siempre que no tapen output útil
No usarlo como banner automático del shell por defecto. En sesiones de trabajo largas, el prompt con el glyph ya cumple la función de marca permanente con menos ruido.
El setup instala estas protecciones globales para reducir riesgo de supply-chain:
~/.npmrcmin-release-age=7ignore-scripts=true
~/Library/Preferences/pnpm/rcminimum-release-age=10080(7 días en minutos)strict-dep-builds=trueblock-exotic-subdeps=truetrust-policy=no-downgrade
~/.bunfig.tomlminimumReleaseAge = 604800
~/.config/uv/uv.tomlexclude-newer = "7 days"
Además, la política operativa recomendada es:
- evitar upgrades accidentales o implícitos de dependencias
- preferir versiones pinneadas y lockfiles cuando el proyecto lo justifique
- evitar
latesty ejecuciones runtime no revisadas salvo necesidad explícita - hacer upgrades de dependencias en cambios/PRs dedicados, no mezclados con features