fix(shell): keep Cursor on agent and Grok on grok
Grok's installer prepends ~/.grok/bin and steals ~/.local/bin/agent. easyzsh already shims `grok`; claim `agent` for Cursor and drop the vendor bin from PATH so a later Grok upgrade cannot shadow it.
This commit is contained in:
@@ -27,6 +27,21 @@ if [[ -d "$ZSH_ALWAYS_ON_DIR" ]]; then
|
||||
. "$f"
|
||||
done
|
||||
fi
|
||||
|
||||
# Cursor owns `agent` when installed. Grok is only ~/.local/bin/grok.
|
||||
# Grok's installer also writes ~/.local/bin/agent and may prepend ~/.grok/bin.
|
||||
_easyzsh_agent=
|
||||
[[ -L $HOME/.local/bin/agent ]] && _easyzsh_agent=$(readlink $HOME/.local/bin/agent)
|
||||
if [[ -x $HOME/.local/bin/cursor-agent ]]; then
|
||||
if [[ ! -e $HOME/.local/bin/agent || $_easyzsh_agent == *'/.grok/'* ]]; then
|
||||
ln -sfn $HOME/.local/bin/cursor-agent $HOME/.local/bin/agent
|
||||
fi
|
||||
elif [[ -L $HOME/.local/bin/agent && $_easyzsh_agent == *'/.grok/'* ]]; then
|
||||
rm -f $HOME/.local/bin/agent
|
||||
fi
|
||||
unset _easyzsh_agent
|
||||
path=(${path:#$HOME/.grok/bin})
|
||||
|
||||
if [[ -f "$ZSH_ALWAYS_ON_DIR/local.zsh" ]]; then
|
||||
# shellcheck disable=SC1090
|
||||
. "$ZSH_ALWAYS_ON_DIR/local.zsh"
|
||||
|
||||
@@ -148,3 +148,9 @@ alias j="z"
|
||||
if (( $+functions[k] )); then
|
||||
alias k="k -h"
|
||||
fi
|
||||
|
||||
# Grok CLI may prepend ~/.grok/bin (its `agent` shadows Cursor).
|
||||
path=(${path:#$HOME/.grok/bin})
|
||||
if [[ -x $HOME/.local/bin/cursor-agent ]]; then
|
||||
alias agent=$HOME/.local/bin/cursor-agent
|
||||
fi
|
||||
|
||||
@@ -39,13 +39,17 @@ From a git checkout (shell stubs only):
|
||||
| `~/.config/zsh/*.zsh` | Always-on tool fragments (e.g. `fnm.zsh`) | Left alone (via `patch.sh`) |
|
||||
| `~/.config/zsh/local.zsh` | Machine-local overrides (every zsh, including agents) | **Never overwritten** |
|
||||
| `~/.config/zshrc/*.zsh` | Personal/tool overlays before oh-my-zsh (interactive) | Left alone |
|
||||
| `~/.local/bin/` | User tools + shims (e.g. `grok` → `~/.grok/bin/grok`) | Left alone |
|
||||
| `~/.local/bin/` | User tools + shims (`grok` → Grok CLI; `agent` → Cursor when installed) | Left alone except those two shims |
|
||||
|
||||
Core deploy does not manage `~/.zprofile`. The pyenv add-on appends one login
|
||||
hook so macOS `path_helper` cannot outrank pyenv shims. Put other machine hooks
|
||||
in `local.zsh`.
|
||||
|
||||
Do **not** put `~/.grok/bin` on PATH wholesale.
|
||||
Do **not** put `~/.grok/bin` on PATH. That tree ships an `agent` that shadows
|
||||
Cursor. Grok is the `grok` command (`~/.local/bin/grok`). Cursor is `agent`
|
||||
and `cursor-agent`. Deploy and `.zshenv` retarget a Grok-stolen
|
||||
`~/.local/bin/agent`; `.zshrc` drops `~/.grok/bin` again if a Grok upgrade
|
||||
prepends it.
|
||||
|
||||
```bash
|
||||
# ~/.config/zsh/local.zsh
|
||||
|
||||
@@ -154,11 +154,27 @@ install -m 644 "${ROOT}/.zshrc" "${TARGET_HOME}/.zshrc"
|
||||
"${ZSH_CFG}/local.zsh.example" \
|
||||
"${TARGET_HOME}/.config/zshenv.local"
|
||||
|
||||
# Ensure intentional grok shim when the binary tree exists.
|
||||
# Grok is `grok`. Cursor owns `agent` when its CLI is present.
|
||||
if [[ -e "${TARGET_HOME}/.grok/bin/grok" ]]; then
|
||||
ln -sfn "${TARGET_HOME}/.grok/bin/grok" "${TARGET_HOME}/.local/bin/grok"
|
||||
echo "Ensured ~/.local/bin/grok -> ~/.grok/bin/grok"
|
||||
fi
|
||||
|
||||
agent_link="${TARGET_HOME}/.local/bin/agent"
|
||||
cursor_agent="${TARGET_HOME}/.local/bin/cursor-agent"
|
||||
agent_target=""
|
||||
if [[ -L "$agent_link" ]]; then
|
||||
agent_target=$(readlink "$agent_link")
|
||||
fi
|
||||
if [[ -x "$cursor_agent" ]]; then
|
||||
if [[ ! -e "$agent_link" || "$agent_target" == *'/.grok/'* ]]; then
|
||||
ln -sfn "$cursor_agent" "$agent_link"
|
||||
echo "Ensured ~/.local/bin/agent -> cursor-agent"
|
||||
fi
|
||||
elif [[ -L "$agent_link" && "$agent_target" == *'/.grok/'* ]]; then
|
||||
rm -f "$agent_link"
|
||||
echo "Removed ~/.local/bin/agent (was Grok; Cursor is not installed)"
|
||||
fi
|
||||
|
||||
echo "Deploy complete."
|
||||
echo "Verify: env -i HOME=\"$TARGET_HOME\" PATH=/usr/bin:/bin zsh -c '. ~/.zshenv; command -v grok'"
|
||||
echo "Verify: env -i HOME=\"$TARGET_HOME\" PATH=/usr/bin:/bin zsh -c '. ~/.zshenv; command -v grok; command -v agent'"
|
||||
|
||||
+32
-2
@@ -113,6 +113,12 @@ fi
|
||||
grep -Fq 'brew shellenv' "$ROOT/.zshenv" || fail "Homebrew is not initialized in .zshenv"
|
||||
grep -Fq '/usr/local/bin/brew' "$ROOT/.zshenv" || fail "Intel Homebrew path is missing from .zshenv"
|
||||
grep -Fq '$HOME/.local/bin' "$ROOT/.zshenv" || fail "~/.local/bin is not added in .zshenv"
|
||||
grep -Fq '${path:#$HOME/.grok/bin}' "$ROOT/.zshenv" || fail ".zshenv does not drop ~/.grok/bin"
|
||||
grep -Fq '${path:#$HOME/.grok/bin}' "$ROOT/.zshrc" || fail ".zshrc does not drop ~/.grok/bin"
|
||||
grep -Fq 'alias agent=$HOME/.local/bin/cursor-agent' "$ROOT/.zshrc" || fail ".zshrc does not alias agent to Cursor"
|
||||
if grep -Eq '^[[:space:]]*(export[[:space:]]+)?PATH=.*\.grok/bin' "$ROOT/.zshenv" "$ROOT/.zshrc"; then
|
||||
fail "easyzsh stubs must not prepend ~/.grok/bin"
|
||||
fi
|
||||
grep -Fq 'local.zsh' "$ROOT/.zshenv" || fail "local.zsh is not sourced from .zshenv"
|
||||
grep -Fq 'ZSH_ALWAYS_ON_DIR' "$ROOT/.zshenv" || fail "always-on ~/.config/zsh/*.zsh glob is missing from .zshenv"
|
||||
grep -Fq 'zsh/fnm' "$ROOT/install_fnm.sh" || fail "install_fnm.sh does not patch always-on zsh/fnm"
|
||||
@@ -130,19 +136,43 @@ fi
|
||||
# deploy.sh installs stubs and preserves local.zsh; removes obsolete tree
|
||||
deploy_home="$TEMP_DIR/deploy-home"
|
||||
mkdir -p "$deploy_home/.config/zsh/env" "$deploy_home/.local/bin" "$deploy_home/.grok/bin"
|
||||
printf '%s\n' 'machine-only' >"$deploy_home/.config/zsh/local.zsh"
|
||||
printf '%s\n' '# machine-only' >"$deploy_home/.config/zsh/local.zsh"
|
||||
printf '%s\n' 'stale' >"$deploy_home/.config/zsh/env/00-path.zsh"
|
||||
printf '%s\n' '#!/bin/sh' 'echo grok-ok' >"$deploy_home/.grok/bin/grok"
|
||||
chmod +x "$deploy_home/.grok/bin/grok"
|
||||
HOME="$deploy_home" bash "$ROOT/deploy.sh" --home "$deploy_home"
|
||||
[[ -f "$deploy_home/.zshenv" ]] || fail "deploy.sh did not install .zshenv"
|
||||
[[ -f "$deploy_home/.zshrc" ]] || fail "deploy.sh did not install .zshrc"
|
||||
grep -Fxq 'machine-only' "$deploy_home/.config/zsh/local.zsh" ||
|
||||
grep -Fxq '# machine-only' "$deploy_home/.config/zsh/local.zsh" ||
|
||||
fail "deploy.sh overwrote local.zsh"
|
||||
[[ ! -e "$deploy_home/.config/zsh/env" ]] || fail "deploy.sh left obsolete env/ tree"
|
||||
[[ ! -e "$deploy_home/.config/zsh/local.zsh.example" ]] || fail "deploy.sh left local.zsh.example in home"
|
||||
[[ -L "$deploy_home/.local/bin/grok" ]] || fail "deploy.sh did not create grok shim"
|
||||
|
||||
# Grok's `agent` must not keep the name when Cursor is absent.
|
||||
printf '%s\n' '#!/bin/sh' 'echo grok-agent' >"$deploy_home/.grok/bin/agent"
|
||||
chmod +x "$deploy_home/.grok/bin/agent"
|
||||
ln -sfn "$deploy_home/.grok/bin/agent" "$deploy_home/.local/bin/agent"
|
||||
HOME="$deploy_home" bash "$ROOT/deploy.sh" --home "$deploy_home" >/dev/null
|
||||
[[ ! -e "$deploy_home/.local/bin/agent" ]] || fail "deploy.sh left Grok bound to agent without Cursor"
|
||||
|
||||
# Cursor takes `agent`; Grok stays on `grok`.
|
||||
printf '%s\n' '#!/bin/sh' 'echo cursor-agent' >"$deploy_home/.local/bin/cursor-agent"
|
||||
chmod +x "$deploy_home/.local/bin/cursor-agent"
|
||||
ln -sfn "$deploy_home/.grok/bin/agent" "$deploy_home/.local/bin/agent"
|
||||
HOME="$deploy_home" bash "$ROOT/deploy.sh" --home "$deploy_home" >/dev/null
|
||||
[[ "$(readlink "$deploy_home/.local/bin/agent")" == "$deploy_home/.local/bin/cursor-agent" ]] ||
|
||||
fail "deploy.sh did not point agent at cursor-agent"
|
||||
[[ "$(readlink "$deploy_home/.local/bin/grok")" == "$deploy_home/.grok/bin/grok" ]] ||
|
||||
fail "deploy.sh did not keep the grok shim"
|
||||
|
||||
# .zshenv repairs a Grok-stolen agent without deploy.
|
||||
ln -sfn "$deploy_home/.grok/bin/agent" "$deploy_home/.local/bin/agent"
|
||||
HOME="$deploy_home" PATH=/usr/bin:/bin zsh -c '. ~/.zshenv' ||
|
||||
fail ".zshenv failed while repairing agent"
|
||||
[[ "$(readlink "$deploy_home/.local/bin/agent")" == "$deploy_home/.local/bin/cursor-agent" ]] ||
|
||||
fail ".zshenv did not retarget a Grok-stolen agent"
|
||||
|
||||
# Non-interactive zsh must resolve ~/.local/bin without sourcing .zshrc.
|
||||
local_bin_home="$TEMP_DIR/local-bin-home"
|
||||
mkdir -p "$local_bin_home/.local/bin"
|
||||
|
||||
Reference in New Issue
Block a user