diff --git a/CLAUDE.md b/CLAUDE.md index 8958c95..b2b2d87 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -41,7 +41,7 @@ dotfiles/ └── install.sh # Instalador ``` -**Flujo de carga del zshrc:** Las secciones están separadas por `#region`/`#endregion`. El orden importa: Brew → PATH → Zsh options → Editor → Env vars → Aliases → Source scripts → Local overrides → Starship → Welcome. +**Flujo de carga del zshrc:** Las secciones están separadas por `#region`/`#endregion`. El orden importa: Brew → PATH → Mise → Zsh options → Editor → Env vars → Aliases → Source scripts → Local overrides → Starship → Welcome. **`local/env.zsh`** está gitignored y contiene paths personales, tokens y overrides de variables de entorno (`SCREENSHOTS_DIR`, `WORKSPACE_DIR`, `WORK_PROJECTS_DIR`). Se genera desde `env.zsh.example` en la primera instalación. diff --git a/README.md b/README.md index c53f98e..2ed590f 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ GitHub Actions ejecuta un smoke check mínimo en pull requests y pushes a `main` - **Terminal**: [Ghostty](https://ghostty.org/) y Alacritty - **Shell**: Zsh nativo de macOS -- **Prompt**: [Starship](https://starship.rs/) — tema Gruvbox Dark +- **Prompt**: [Starship](https://starship.rs/) — paleta Cortex warm slate - **Multiplexor**: tmux + helpers de sesión - **Barra macOS**: [SketchyBar](https://github.com/FelixKratz/SketchyBar) con tema Gruvbox - **Window manager macOS**: [yabai](https://github.com/koekeishiya/yabai) + [skhd](https://github.com/koekeishiya/skhd) opcional y gradual @@ -127,6 +127,7 @@ Seguimiento: [cortex-dotfiles #31](https://github.com/barbatdev/cortex-dotfiles/ | `ccclip ` | 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 | +| `hremote`, `hremote-stop`, `hremote-restart` | Attach/restart seguro de sesiones Herdr remotas nombradas | | `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 | @@ -156,6 +157,8 @@ Usá `hremote` desde tu terminal local en macOS. No hagas `ssh` primero y despu - Para pegar una imagen del clipboard local en la terminal remota, usá `Ctrl+V` por defecto (no `Cmd+V`). - `herdr --remote` puentea ese pegado copiando la imagen a un archivo temporal remoto y pegando el path resultante en la shell remota. +- Si Herdr dice `remote herdr server must restart before this bridge can attach`, corré `hremote-stop ` y después `hremote `. +- `hremote-stop` usa `herdr session stop ` en el host remoto: detiene solo esa sesión nombrada, no el server default. - 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. diff --git a/docs/herdr-workflow.md b/docs/herdr-workflow.md index 45b28af..56f5c6b 100644 --- a/docs/herdr-workflow.md +++ b/docs/herdr-workflow.md @@ -82,9 +82,13 @@ The default Herdr prefix is `Ctrl+B`. See [keymaps](keymaps.md) for the practica | Reattach role session | `hfocus [path]`, `hside [path]`, `hscratch [path]` | | Reattach explicit session | `herdr --session ` or `herdr session attach ` | | Reattach remote session | `hremote [session]` | +| Stop stale remote session | `hremote-stop [session]` | +| Stop and reattach remote session | `hremote-restart [session]` | Before detaching long-running work, name important panes and run `whereami` if the shell context is ambiguous. +If remote attach reports `remote herdr server must restart before this bridge can attach`, stop only the named remote session with `hremote-stop ` and then reattach. This maps to `herdr session stop ` on the remote host; it does not stop the remote default server. + ## Related Docs - [Keymaps](keymaps.md) diff --git a/herdr/config.toml b/herdr/config.toml index 06c622c..1edd878 100644 --- a/herdr/config.toml +++ b/herdr/config.toml @@ -6,12 +6,16 @@ sidebar_width = 32 sidebar_min_width = 24 sidebar_max_width = 42 agent_panel_sort = "priority" +hide_tab_bar_when_single_tab = true show_agent_labels_on_pane_borders = true prompt_new_tab_name = true pane_borders = true pane_gaps = true accent = "#F97316" +[ui.sound] +enabled = false + [terminal] new_cwd = "follow" @@ -19,10 +23,10 @@ new_cwd = "follow" resume_agents_on_restore = true [remote] -manage_ssh_config = false +manage_ssh_config = true [theme] -name = "cortex" +name = "terminal" auto_switch = false [theme.custom] diff --git a/install.sh b/install.sh index 4b57896..47ce5df 100755 --- a/install.sh +++ b/install.sh @@ -161,7 +161,6 @@ PY check_command herdr warn check_command mosh warn check_command tmux warn - check_command herdr warn check_command lazygit warn check_command sketchybar warn check_command yabai warn @@ -215,7 +214,6 @@ PY check_symlink_target "$DOTFILES/herdr/config.toml" "$HOME/.config/herdr/config.toml" check_symlink_target "$DOTFILES/ghostty/config" "$HOME/.config/ghostty/config" check_symlink_target "$DOTFILES/ghostty/shaders" "$HOME/.config/ghostty/shaders" - check_symlink_target "$DOTFILES/herdr/config.toml" "$HOME/.config/herdr/config.toml" check_symlink_target "$DOTFILES/opencode/tui.json" "$HOME/.config/opencode/tui.json" check_symlink_target "$DOTFILES/opencode/themes" "$HOME/.config/opencode/themes" check_symlink_target "$DOTFILES/tmux/tmux.conf" "$HOME/.tmux.conf" @@ -413,12 +411,12 @@ echo "💾 Haciendo backup de configs existentes..." backup_if_exists() { local src="$1" - if [[ -e "$src" && ! -L "$src" ]]; then + if [[ -e "$src" || -L "$src" ]]; then local backup="${src}.bak_${TIMESTAMP}" if [[ "$DRY_RUN" == true ]]; then echo " → Would backup $src to $backup" else - cp -R "$src" "$backup" + mv "$src" "$backup" echo " → Backup: $backup" fi fi @@ -448,7 +446,6 @@ backup_if_exists "$HOME/.config/uv/uv.toml" backup_if_exists "$HOME/.config/starship.toml" backup_if_exists "$HOME/.config/herdr/config.toml" backup_if_exists "$HOME/.config/ghostty/config" -backup_if_exists "$HOME/.config/herdr/config.toml" backup_if_exists "$HOME/.config/opencode/tui.json" backup_if_exists "$HOME/.config/opencode/themes" backup_if_exists "$HOME/.tmux.conf" @@ -491,7 +488,6 @@ create_symlink "$DOTFILES/starship/starship.toml" "$HOME/.config/starship.toml" create_symlink "$DOTFILES/herdr/config.toml" "$HOME/.config/herdr/config.toml" create_symlink "$DOTFILES/ghostty/config" "$HOME/.config/ghostty/config" create_symlink "$DOTFILES/ghostty/shaders" "$HOME/.config/ghostty/shaders" -create_symlink "$DOTFILES/herdr/config.toml" "$HOME/.config/herdr/config.toml" create_symlink "$DOTFILES/opencode/tui.json" "$HOME/.config/opencode/tui.json" create_symlink "$DOTFILES/opencode/themes" "$HOME/.config/opencode/themes" create_symlink "$DOTFILES/tmux/tmux.conf" "$HOME/.tmux.conf" diff --git a/starship/starship.toml b/starship/starship.toml index 6bfa982..1409a59 100644 --- a/starship/starship.toml +++ b/starship/starship.toml @@ -17,16 +17,16 @@ $line_break$character""" # Módulos alineados a la derecha right_format = """$cmd_duration$time""" -palette = 'innit_tech_slate' +palette = 'cortex_warm_slate' -[palettes.innit_tech_slate] +[palettes.cortex_warm_slate] color_fg0 = '#F6F8FA' color_bg1 = '#1C2128' color_bg3 = '#2D333B' color_blue = '#0054ff' color_aqua = '#58A6FF' color_green = '#3FB950' -color_orange = '#0054ff' +color_orange = '#F97316' color_purple = '#8B5CF6' color_red = '#F85149' color_yellow = '#D29922' @@ -159,7 +159,7 @@ disabled = false [character] disabled = false -success_symbol = '[󰼀](fg:color_fg0) ' +success_symbol = '[󰼀](fg:color_orange) ' error_symbol = '[󰼀](fg:color_red) ' vimcmd_symbol = '[󰼀](fg:color_fg0) ' vimcmd_replace_one_symbol = '[󰼀](fg:color_purple) ' diff --git a/zsh/scripts/herdr-helpers.zsh b/zsh/scripts/herdr-helpers.zsh index 9c8a6ba..408cb43 100644 --- a/zsh/scripts/herdr-helpers.zsh +++ b/zsh/scripts/herdr-helpers.zsh @@ -64,7 +64,24 @@ _herdr_open_session_for_path() { fi session="$(_herdr_session_name_with_suffix "$resolved" "$suffix")" - CORTEX_MULTIPLEXER=herdr herdr --session "$session" + (cd "$resolved" && CORTEX_MULTIPLEXER=herdr herdr --session "$session") +} + +_herdr_validate_remote_args() { + local target="$1" + local session="$2" + + if [[ "$target" == -* ]]; then + echo "Target SSH inválido: $target" + echo "Usá un host o alias SSH, no opciones de ssh." + return 1 + fi + + if [[ "$session" == -* || "$session" == *[^A-Za-z0-9_.-]* ]]; then + echo "Nombre de sesión inválido: $session" + echo "Usá solo letras, números, punto, guion o underscore." + return 1 + fi } _herdr_workspace_id_by_label() { @@ -146,9 +163,28 @@ hscratch() { hremote() { local target="${1:?Uso: hremote [session]}" local session="${2:-main}" + _herdr_validate_remote_args "$target" "$session" || return CORTEX_MULTIPLEXER=herdr CORTEX_SSH_TARGET="$target" herdr --remote "$target" --session "$session" } +# Parar una sesión Herdr remota nombrada cuando el bridge pide restart. +# Uso: hremote-stop [session] +hremote-stop() { + local target="${1:?Uso: hremote-stop [session]}" + local session="${2:-main}" + _herdr_validate_remote_args "$target" "$session" || return + + ssh -t "$target" "PATH=\"\$HOME/.local/bin:\$HOME/.cargo/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:\$PATH\"; herdr session stop '$session'" +} + +# Parar y re-attachar una sesión Herdr remota nombrada. +# Uso: hremote-restart [session] +hremote-restart() { + local target="${1:?Uso: hremote-restart [session]}" + local session="${2:-main}" + hremote-stop "$target" "$session" && hremote "$target" "$session" +} + # Renombrar el pane actual de Herdr con un label humano o uno derivado de repo/branch. hname() { local label="${1:-$(_herdr_workspace_name_for_path "$PWD")}" diff --git a/zsh/scripts/ssh-helpers.zsh b/zsh/scripts/ssh-helpers.zsh index c7d2dd7..fa13662 100644 --- a/zsh/scripts/ssh-helpers.zsh +++ b/zsh/scripts/ssh-helpers.zsh @@ -4,11 +4,7 @@ _remote_herdr_command_for_path() { local remote_path="$1" local shell_path - if [[ "$remote_path" == "$HOME/"* ]]; then - shell_path="~/${remote_path#$HOME/}" - else - shell_path="${(q)remote_path}" - fi + shell_path="${(q)remote_path}" printf 'cd %s && exec ${SHELL:-zsh}' "$shell_path" } diff --git a/zsh/zshrc b/zsh/zshrc index af43219..0f17baf 100644 --- a/zsh/zshrc +++ b/zsh/zshrc @@ -18,6 +18,16 @@ fi export PATH="$HOME/.local/bin:$PATH" #endregion +#region Mise +if [[ -x "$HOME/.local/bin/mise" ]]; then + eval "$("$HOME/.local/bin/mise" activate zsh)" +elif [[ -x "/opt/homebrew/bin/mise" ]]; then + eval "$(/opt/homebrew/bin/mise activate zsh)" +elif [[ -x "/usr/local/bin/mise" ]]; then + eval "$(/usr/local/bin/mise activate zsh)" +fi +#endregion + #region Zsh Options # Historia HISTFILE="$HOME/.zsh_history" @@ -326,6 +336,11 @@ help-profile() { echo " ${C}ccd [sub] ${R}Navegar al Claude workspace" echo " ${C}ccclip ${R}Copiar código al clipboard" + echo "\n${T}Herdr remoto${R}" + echo " ${C}hremote [s] ${R}Attach a sesión remota" + echo " ${C}hremote-stop [s] ${R}Parar una sesión remota nombrada" + echo " ${C}hremote-restart [s] ${R}Parar y re-attachar sesión remota" + echo "\n${T}Tmux — sesiones${R}" echo " ${C}tcc ${R}Abrir Claude Code + lazygit (layout automático)" echo " ${C}tdev ${R}Sesión con nombre del directorio actual"