Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ jobs:
- name: Check navigation shortcuts
run: ./scripts/check-navigation-shortcuts.sh

- name: Check installer symlink safety
run: ./scripts/check-install-symlinks.sh

- name: Validate TOML configs
shell: bash
run: |
Expand Down
19 changes: 3 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,23 +95,11 @@ dotfiles/

## Boundary con Cortex

Este repo sigue siendo standalone: `install.sh` no requiere tener el repo `cortex` disponible y estos dotfiles deben poder instalarse por sí solos. El bootstrap carga primero `~/.config/cortex-dotfiles/shell/cortex-dotfiles.zsh` y, si existe, carga al final `~/.cortex/shell/cortex.zsh`, que pertenece a Cortex. Ambos fragments son opcionales y un error en uno no impide intentar cargar el otro. Cortex conserva el ownership de sus variables core; este repo solo define variables bajo el namespace `CORTEX_DOTFILES_*`.
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á.

Algunos artefactos viven acá temporalmente porque nacieron junto al setup personal, pero conceptualmente son propios del producto Cortex y no deberían tener a `cortex-dotfiles` como source of truth permanente:
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.

- `opencode/themes/` — themes Cortex para OpenCode.
- `claude/themes/` — themes Cortex para Claude Code.
- `claude/statusline.sh` — statusline orientada a superficies Cortex.
- `docs/agent-state-v1.md` — contrato `cortex.agent_state.v1`.
- `scripts/check-agent-state.sh` — smoke check del contrato agent-state.
- `zsh/scripts/agent-state.sh` — bridge local para reportar estado de agentes.
- `zsh/scripts/postcompact-hook.sh` y `zsh/scripts/memsave-nudge.sh` — hooks ligados al workflow Cortex.

La migración se coordina en tres repos independientes: `cortex` define ownership de los artefactos product-owned, `cortex-dotfiles` conserva instalación/adaptación local, y `cortex-dots` sigue siendo un snapshot OSS-safe de dotfiles sin depender de `cortex`.

No borrar ni cambiar estos artefactos acá hasta que `cortex` tenga reemplazos validados y se decida qué queda como adaptación local.

Seguimiento: [cortex-dotfiles #31](https://github.com/barbatdev/cortex-dotfiles/issues/31), [cortex #1038](https://github.com/barbatdev/cortex/issues/1038), [cortex-dots #14](https://github.com/barbatdev/cortex-dots/issues/14).
La coordinación vigente del contrato shell se sigue en [cortex #1259](https://github.com/barbatdev/cortex/issues/1259). Las migraciones de artefactos actualmente versionados en este repo se tratan por separado en [cortex-dotfiles #31](https://github.com/barbatdev/cortex-dotfiles/issues/31).

## Especificaciones

Expand Down Expand Up @@ -150,7 +138,6 @@ Editá `local/env.zsh` (gitignored) para configurar:
- `PERSONAL_PROJECTS_DIR` — repos locales, por defecto `$WORKSPACE_DIR/local`
- `TOOLS_DIR` y `WORKTREES_DIR` — herramientas locales y worktrees
- `CORTEX_DOTFILES_DIR` — repo fuente de dotfiles, por defecto `$BARBATDEV_DIR/cortex/cortex-dotfiles`
- `CORTEX_DOTFILES_SHELL_ENTRYPOINT` — override del entrypoint propio, por defecto `~/.config/cortex-dotfiles/shell/cortex-dotfiles.zsh`
- `CORTEX_DOTFILES_MULTIPLEXER` — fallback standalone para helpers, por defecto `cmux`; `CORTEX_MULTIPLEXER` de Cortex tiene precedencia
- `OPENCODE_DEFAULT_FLAGS` — flags por defecto para `oc`
- `INNIT_DIR` y overrides `INNIT_*_DIR` — raíz y subdirectorios `apis`, `mobile`, `webs` y `pcsoft`
Expand Down
59 changes: 10 additions & 49 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DRY_RUN=false
PLATFORM="$(uname -s)"

# shellcheck source=scripts/install-helpers.sh
source "$DOTFILES/scripts/install-helpers.sh"

if [[ "${1:-}" == "--dry-run" ]]; then
DRY_RUN=true
fi
Expand Down Expand Up @@ -209,7 +212,6 @@ PY
check_symlink_target "$DOTFILES/bun/bunfig.toml" "$HOME/.bunfig.toml"
check_symlink_target "$DOTFILES/uv/uv.toml" "$HOME/.config/uv/uv.toml"
check_symlink_target "$DOTFILES/starship/starship.toml" "$HOME/.config/starship.toml"
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"
Expand Down Expand Up @@ -426,43 +428,12 @@ fi
echo ""
echo "💾 Haciendo backup de configs existentes..."

backup_if_exists() {
local src="$1"
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"
echo " → Backup: $backup"
fi
fi
}

backup_karabiner_if_exists() {
local src="$HOME/.config/karabiner/karabiner.json"
if [[ -e "$src" || -L "$src" ]]; then
local backup="${src}.bak_${TIMESTAMP}"
if [[ "$DRY_RUN" == true ]]; then
echo " → Would backup $src to $backup"
else
if [[ -L "$src" ]]; then
cp -P "$src" "$backup"
else
cp "$src" "$backup"
fi
echo " → Backup: $backup"
fi
fi
}

backup_if_exists "$HOME/.zshrc"
backup_if_exists "$HOME/.config/cortex-dotfiles/shell/cortex-dotfiles.zsh"
backup_if_exists "$HOME/.npmrc"
backup_if_exists "$HOME/.bunfig.toml"
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"
Expand All @@ -478,34 +449,19 @@ if [[ "$PLATFORM" == "Darwin" ]]; then
backup_if_exists "$HOME/.yabairc"
backup_if_exists "$HOME/.config/skhd/skhdrc"
backup_if_exists "$HOME/.skhdrc"
backup_karabiner_if_exists
backup_if_exists "$HOME/.config/karabiner/karabiner.json"
fi

# --- Crear symlinks ---
echo ""
echo "🔗 Creando symlinks..."

create_symlink() {
local src="$1"
local dst="$2"
if [[ "$DRY_RUN" == true ]]; then
echo " → Would symlink $dst → $src"
else
mkdir -p "$(dirname "$dst")"
# -n evita que ln dereferencie un symlink-a-directorio existente y cree
# un link adentro (caso ghostty/shaders → loop shaders/shaders)
ln -sfn "$src" "$dst"
echo " ✓ $dst → $src"
fi
}

create_symlink "$DOTFILES/zsh/zshrc" "$HOME/.zshrc"
create_symlink "$DOTFILES/zsh/cortex-dotfiles.zsh" "$HOME/.config/cortex-dotfiles/shell/cortex-dotfiles.zsh"
create_symlink "$DOTFILES/npm/npmrc" "$HOME/.npmrc"
create_symlink "$DOTFILES/bun/bunfig.toml" "$HOME/.bunfig.toml"
create_symlink "$DOTFILES/uv/uv.toml" "$HOME/.config/uv/uv.toml"
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"
Expand Down Expand Up @@ -628,10 +584,15 @@ if [[ ! -f "$DOTFILES/local/env.zsh" ]]; then
if [[ "$DRY_RUN" == true ]]; then
echo "📝 Would create local/env.zsh from local/env.zsh.example"
else
cp "$DOTFILES/local/env.zsh.example" "$DOTFILES/local/env.zsh"
install -m 600 "$DOTFILES/local/env.zsh.example" "$DOTFILES/local/env.zsh"
echo "📝 Creado local/env.zsh desde el ejemplo — editalo con tus paths"
fi
else
if [[ "$DRY_RUN" == true ]]; then
echo " → Would set local/env.zsh permissions to 600"
else
chmod 600 "$DOTFILES/local/env.zsh"
fi
echo "✓ local/env.zsh ya existe"
fi

Expand Down
1 change: 0 additions & 1 deletion local/env.zsh.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

# Configuración propia de cortex-dotfiles.
# export CORTEX_DOTFILES_DIR="$BARBATDEV_DIR/cortex/cortex-dotfiles"
# export CORTEX_DOTFILES_SHELL_ENTRYPOINT="$HOME/.config/cortex-dotfiles/shell/cortex-dotfiles.zsh"

# Proyectos personales
# export PERSONAL_PROJECTS_DIR="${WORKSPACE_DIR:-$HOME/dev}/local"
Expand Down
31 changes: 21 additions & 10 deletions scripts/check-cortex-shell-integration.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@ repo_root="$(cd "$(dirname "$0")/.." && pwd)"
tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT

dotfiles_fragment="$tmp_dir/cortex-dotfiles.zsh"
cortex_fragment="$tmp_dir/cortex.zsh"
home_dir="$tmp_dir/home"
dotfiles_fragment="$home_dir/.config/cortex-dotfiles/shell/cortex-dotfiles.zsh"
cortex_fragment="$home_dir/.cortex/shell/cortex.zsh"
mkdir -p "$(dirname "$dotfiles_fragment")" "$(dirname "$cortex_fragment")"
printf '%s\n' '_SHELL_LOAD_ORDER+=(dotfiles)' > "$dotfiles_fragment"
printf '%s\n' '_SHELL_LOAD_ORDER+=(cortex)' > "$cortex_fragment"
printf '%s\n' '_UNTRUSTED_ENTRYPOINT_LOADED=1' > "$tmp_dir/untrusted.zsh"

env \
CORTEX_DOTFILES_SHELL_ENTRYPOINT="$dotfiles_fragment" \
HOME="$home_dir" \
CORTEX_DOTFILES_SHELL_ENTRYPOINT="$tmp_dir/untrusted.zsh" \
CORTEX_SHELL_INTEGRATION="$cortex_fragment" \
zsh -f -c '
_SHELL_LOAD_ORDER=()
source "$1"
[[ "${(j/:/)_SHELL_LOAD_ORDER}" == "dotfiles:cortex" ]]
(( ! ${+_UNTRUSTED_ENTRYPOINT_LOADED} ))
(( ! ${+_CORTEX_DOTFILES_SHELL_PATH} ))
(( ! ${+_CORTEX_SHELL_PATH} ))
' _ "$repo_root/zsh/zshrc"

home_dir="$tmp_dir/home"
mkdir -p "$home_dir/.config/cortex-dotfiles/shell" "$home_dir/.cortex/shell"
cp "$dotfiles_fragment" "$home_dir/.config/cortex-dotfiles/shell/cortex-dotfiles.zsh"
cp "$cortex_fragment" "$home_dir/.cortex/shell/cortex.zsh"

env -u CORTEX_HOME -u CORTEX_ROOT -u CORTEX_DOTFILES_SHELL_ENTRYPOINT \
-u CORTEX_SHELL_INTEGRATION HOME="$home_dir" zsh -f -c '
_SHELL_LOAD_ORDER=()
Expand All @@ -39,7 +39,7 @@ env HOME="$tmp_dir/missing-home" zsh -f -c 'source "$1"' _ "$repo_root/zsh/zshrc

printf '%s\n' 'return 1' > "$dotfiles_fragment"
env \
CORTEX_DOTFILES_SHELL_ENTRYPOINT="$dotfiles_fragment" \
HOME="$home_dir" \
CORTEX_SHELL_INTEGRATION="$cortex_fragment" \
zsh -f -c '
_SHELL_LOAD_ORDER=()
Expand All @@ -51,10 +51,21 @@ grep -Fq "zsh: no se pudo cargar cortex-dotfiles: $dotfiles_fragment" "$tmp_dir/

printf '%s\n' 'if [[' > "$dotfiles_fragment"
env \
CORTEX_DOTFILES_SHELL_ENTRYPOINT="$dotfiles_fragment" \
HOME="$home_dir" \
CORTEX_SHELL_INTEGRATION="$cortex_fragment" \
zsh -f -c '
_SHELL_LOAD_ORDER=()
source "$1" 2>/dev/null
[[ "${(j/:/)_SHELL_LOAD_ORDER}" == "cortex" ]]
' _ "$repo_root/zsh/zshrc"

rm -f "$dotfiles_fragment"
ln -s "$repo_root/zsh/cortex-dotfiles.zsh" "$dotfiles_fragment"
env HOME="$home_dir" CORTEX_SHELL_INTEGRATION="$tmp_dir/missing-cortex.zsh" zsh -f -c '
setopt ERR_EXIT
source "$1" >/dev/null
source "$1" >/dev/null
for expected in "$HOME/.local/bin" "$HOME/.opencode/bin" "$HOME/.bun/bin" "/opt/homebrew/opt/bc/bin"; do
(( ${path[(I)$expected]} == ${path[(i)$expected]} ))
done
' _ "$repo_root/zsh/zshrc"
57 changes: 57 additions & 0 deletions scripts/check-install-symlinks.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#!/bin/bash
set -euo pipefail

repo_root="$(cd "$(dirname "$0")/.." && pwd)"
tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT

TIMESTAMP=test
DRY_RUN=false
# shellcheck source=scripts/install-helpers.sh
source "$repo_root/scripts/install-helpers.sh"

new_target="$tmp_dir/new-target"
printf '%s\n' new > "$new_target"

regular="$tmp_dir/regular"
printf '%s\n' original > "$regular"
backup_if_exists "$regular" >/dev/null
[[ "$(<"$regular.bak_test")" == original ]]
create_symlink "$new_target" "$regular" >/dev/null
[[ "$(readlink "$regular")" == "$new_target" ]]

old_target="$tmp_dir/old-target"
printf '%s\n' old > "$old_target"
link="$tmp_dir/link"
ln -s "$old_target" "$link"
backup_if_exists "$link" >/dev/null
[[ -L "$link.bak_test" ]]
[[ "$(readlink "$link.bak_test")" == "$old_target" ]]
create_symlink "$new_target" "$link" >/dev/null

directory="$tmp_dir/directory"
mkdir -p "$directory"
printf '%s\n' marker > "$directory/marker"
backup_if_exists "$directory" >/dev/null
[[ -f "$directory.bak_test/marker" ]]
create_symlink "$new_target" "$directory" >/dev/null
[[ -L "$directory" ]]
[[ ! -e "$directory/new-target" ]]

blocked="$tmp_dir/blocked"
printf '%s\n' keep > "$blocked"
if create_symlink "$new_target" "$blocked" >/dev/null 2>&1; then
echo "create_symlink accepted an unbacked destination" >&2
exit 1
fi
[[ "$(<"$blocked")" == keep ]]

collision="$tmp_dir/collision"
printf '%s\n' original > "$collision"
printf '%s\n' existing > "$collision.bak_test"
if backup_if_exists "$collision" >/dev/null 2>&1; then
echo "backup_if_exists accepted an existing backup path" >&2
exit 1
fi
[[ "$(<"$collision")" == original ]]
[[ "$(<"$collision.bak_test")" == existing ]]
35 changes: 35 additions & 0 deletions scripts/install-helpers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/bin/bash

backup_if_exists() {
local src="$1"
if [[ -e "$src" || -L "$src" ]]; then
local backup="${src}.bak_${TIMESTAMP}"
if [[ "$DRY_RUN" == true ]]; then
echo " → Would backup $src to $backup"
else
if [[ -e "$backup" || -L "$backup" ]]; then
echo " ✗ Backup existente: $backup" >&2
return 1
fi
mv "$src" "$backup"
echo " → Backup: $backup"
fi
fi
}

create_symlink() {
local src="$1"
local dst="$2"
if [[ "$DRY_RUN" == true ]]; then
echo " → Would symlink $dst → $src"
else
mkdir -p "$(dirname "$dst")"
if [[ -e "$dst" || -L "$dst" ]]; then
echo " ✗ Destino existente sin backup: $dst" >&2
return 1
fi
ln -s "$src" "$dst"
[[ -L "$dst" && "$(readlink "$dst")" == "$src" ]] || return 1
echo " ✓ $dst → $src"
fi
}
15 changes: 10 additions & 5 deletions zsh/cortex-dotfiles.zsh
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@ fi
#endregion

#region PATH
export PATH="$HOME/.local/bin:$PATH"
[[ -d "/Applications/cmux.app/Contents/Resources/bin" ]] && export PATH="/Applications/cmux.app/Contents/Resources/bin:$PATH"
_cortex_dotfiles_path_prepend() {
[[ ":$PATH:" == *":$1:"* ]] || export PATH="$1:$PATH"
}

_cortex_dotfiles_path_prepend "$HOME/.local/bin"
[[ -d "/Applications/cmux.app/Contents/Resources/bin" ]] && _cortex_dotfiles_path_prepend "/Applications/cmux.app/Contents/Resources/bin"
#endregion

#region Zsh Options
Expand Down Expand Up @@ -348,12 +352,13 @@ _welcome
#endregion

# opencode
export PATH=$HOME/.opencode/bin:$PATH
_cortex_dotfiles_path_prepend "$HOME/.opencode/bin"

# bun
export BUN_INSTALL="$HOME/.bun"
export PATH="$BUN_INSTALL/bin:$PATH"
_cortex_dotfiles_path_prepend "$BUN_INSTALL/bin"

# bun completions
[ -s "$BUN_INSTALL/_bun" ] && source "$BUN_INSTALL/_bun"
export PATH="/opt/homebrew/opt/bc/bin:$PATH"
_cortex_dotfiles_path_prepend "/opt/homebrew/opt/bc/bin"
unfunction _cortex_dotfiles_path_prepend
10 changes: 5 additions & 5 deletions zsh/zshrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@

_cortex_dotfiles_source_optional() {
local label="$1"
local path="$2"
local fragment_path="$2"

[[ -r "$path" ]] || return 0
if ! source "$path"; then
print -u2 -- "zsh: no se pudo cargar $label: $path"
[[ -r "$fragment_path" ]] || return 0
if ! source "$fragment_path"; then
print -u2 -- "zsh: no se pudo cargar $label: $fragment_path"
fi
return 0
}

_CORTEX_DOTFILES_SHELL_PATH="${CORTEX_DOTFILES_SHELL_ENTRYPOINT:-$HOME/.config/cortex-dotfiles/shell/cortex-dotfiles.zsh}"
_CORTEX_DOTFILES_SHELL_PATH="$HOME/.config/cortex-dotfiles/shell/cortex-dotfiles.zsh"
_CORTEX_SHELL_PATH="${CORTEX_SHELL_INTEGRATION:-${CORTEX_HOME:-$HOME/.cortex}/shell/cortex.zsh}"

_cortex_dotfiles_source_optional "cortex-dotfiles" "$_CORTEX_DOTFILES_SHELL_PATH"
Expand Down
Loading