Skip to content

Instantly share code, notes, and snippets.

@vorbei
Last active March 28, 2026 19:36
Show Gist options
  • Select an option

  • Save vorbei/6992998cac2485104d430b59952b1a09 to your computer and use it in GitHub Desktop.

Select an option

Save vorbei/6992998cac2485104d430b59952b1a09 to your computer and use it in GitHub Desktop.
Zed terminal shell selector with arrow-key menu

zed-shell

Interactive shell selector for Zed terminal tabs. Opens an arrow-key menu on each new terminal.

Install

brew install lazygit yazi
brew install --cask font-jetbrains-mono-nerd-font  # for yazi icons

mkdir -p ~/.local/bin
# download zed-shell and zed-menu.py from this gist into ~/.local/bin/
chmod +x ~/.local/bin/zed-shell ~/.local/bin/zed-menu.py

Add to Zed settings.json:

"terminal": {
  "shell": { "program": "/Users/YOUR_USERNAME/.local/bin/zed-shell" },
  "font_family": "JetBrainsMono Nerd Font"
}

Controls

↑ ↓ navigate · Enter select · q / Ctrl+C cancel

#!/usr/bin/env python3
import sys, os, tty, termios
ESC = '\x1b'
RESET = f'{ESC}[0m'
ORANGE = f'{ESC}[1;38;5;202m'
GRAY = f'{ESC}[38;5;245m'
CLEAR = f'{ESC}[2J{ESC}[H'
def draw(tty_out, title, items, cur):
out = CLEAR
out += f'\r\n {GRAY}{title}{RESET}\r\n\r\n'
for i, item in enumerate(items):
if i == cur:
out += f' {ORANGE}❯ {item}{RESET}\r\n'
else:
out += f' {GRAY}{item}{RESET}\r\n'
tty_out.write(out.encode())
tty_out.flush()
def menu(tty_in, tty_out, title, items):
cur = 0
fd = tty_in.fileno()
old = termios.tcgetattr(fd)
tty.setraw(fd)
try:
draw(tty_out, title, items, cur)
while True:
ch = os.read(fd, 1)
if ch == b'\x1b':
rest = os.read(fd, 2)
ch += rest
if ch in (b'\r', b'\n'):
return cur
elif ch in (b'\x03', b'q'):
return -1
elif ch == b'\x1b[A' and cur > 0:
cur -= 1
draw(tty_out, title, items, cur)
elif ch == b'\x1b[B' and cur < len(items) - 1:
cur += 1
draw(tty_out, title, items, cur)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old)
tty_out.write(CLEAR.encode())
tty_out.flush()
MAIN_ITEMS = [
"claude AI coding assistant",
"zsh Standard shell",
"uv + zsh zsh with uv project env",
"python Python REPL (uv)",
"lazygit Git TUI",
"yazi File manager TUI",
]
CLAUDE_ITEMS = [
"new Start a new session",
"continue Resume most recent session",
"resume Pick a previous session",
]
try:
tty_in = open('/dev/tty', 'rb', buffering=0)
tty_out = open('/dev/tty', 'wb', buffering=0)
except OSError:
print("zsh")
sys.exit(0)
choice = menu(tty_in, tty_out, "Open in...", MAIN_ITEMS)
if choice == 0:
mode = menu(tty_in, tty_out, "Claude session...", CLAUDE_ITEMS)
results = ["claude", "claude --continue", "claude --resume"]
print(results[mode] if 0 <= mode < len(results) else "zsh")
elif choice == 1:
print("zsh")
elif choice == 2:
print("uv+zsh")
elif choice == 3:
print("python")
elif choice == 4:
print("lazygit")
elif choice == 5:
print("yazi")
else:
print("zsh")
#!/bin/zsh
export PATH="/opt/homebrew/bin:/usr/local/bin:$PATH"
[[ -t 1 ]] || exec zsh -l
CHOICE=$(python3 "$(dirname $0)/zed-menu.py")
case "$CHOICE" in
claude) claude ;;
"claude --continue") claude --continue ;;
"claude --resume") claude --resume ;;
"uv+zsh")
if [[ -f ".venv/bin/activate" ]]; then
exec zsh -l -c 'source .venv/bin/activate && exec zsh'
elif command -v uv &>/dev/null && [[ -f "pyproject.toml" ]]; then
exec uv run zsh
else
exec zsh -l
fi
;;
python)
if command -v uv &>/dev/null && [[ -f "pyproject.toml" ]]; then
exec uv run python
else
exec python3
fi
;;
lazygit) exec lazygit ;;
yazi) exec yazi ;;
*) exec zsh -l ;;
esac
# Re-show menu after claude exits
exec "$0"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment