Update rofi tmcodex launcher
This commit is contained in:
@@ -1,20 +1,44 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env zsh
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
# Pick a directory via rofi, then start Codex in a tmux session rooted there.
|
# Pick a directory via rofi, then start tmcodex there.
|
||||||
# Remembers previously used directories in:
|
# Candidate dirs come from previous tmcodex launches and Codex session metadata.
|
||||||
|
# tmcodex launch history is stored in:
|
||||||
# ${XDG_STATE_HOME:-~/.local/state}/rofi-tmcodex/dirs
|
# ${XDG_STATE_HOME:-~/.local/state}/rofi-tmcodex/dirs
|
||||||
|
|
||||||
state_dir="${XDG_STATE_HOME:-$HOME/.local/state}/rofi-tmcodex"
|
state_dir="${XDG_STATE_HOME:-$HOME/.local/state}/rofi-tmcodex"
|
||||||
history_file="$state_dir/dirs"
|
history_file="$state_dir/dirs"
|
||||||
|
codex_home="${CODEX_HOME:-$HOME/.codex}"
|
||||||
|
terminal="${TMCODEX_TERMINAL:-${TERMINAL:-ghostty}}"
|
||||||
|
debug_log="$state_dir/debug.log"
|
||||||
mkdir -p "$state_dir"
|
mkdir -p "$state_dir"
|
||||||
touch "$history_file"
|
touch "$history_file"
|
||||||
|
|
||||||
emit_candidates() {
|
debug() {
|
||||||
# 1) Previously-used dirs (most recent first).
|
[[ -n "${TMCODEX_ROFI_DEBUG:-}" ]] || return 0
|
||||||
cat "$history_file" 2>/dev/null || true
|
printf '%s %s\n' "$(date -Is)" "$*" >>"$debug_log" 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
# 2) A few common roots.
|
emit_candidates() {
|
||||||
|
local root gitdir
|
||||||
|
|
||||||
|
# 1) Explicit tmcodex history, most recent first.
|
||||||
|
cat -- "$history_file" 2>/dev/null || true
|
||||||
|
|
||||||
|
# 2) Codex session directories, newest sessions first.
|
||||||
|
if command -v jq >/dev/null 2>&1; then
|
||||||
|
for root in "$codex_home/sessions" "$codex_home/archived_sessions"; do
|
||||||
|
[[ -d "$root" ]] || continue
|
||||||
|
find "$root" -type f -name '*.jsonl' -printf '%T@ %p\n' 2>/dev/null \
|
||||||
|
| sort -rn \
|
||||||
|
| awk 'NR <= 1000 { sub(/^[^ ]+ /, ""); print }' \
|
||||||
|
| while IFS= read -r session_file; do
|
||||||
|
jq -r 'first(select(.type == "session_meta") | .payload.cwd? // empty)' "$session_file" 2>/dev/null
|
||||||
|
done
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 3) A few common roots.
|
||||||
for d in \
|
for d in \
|
||||||
"$HOME/dotfiles" \
|
"$HOME/dotfiles" \
|
||||||
"$HOME/dotfiles/nixos" \
|
"$HOME/dotfiles/nixos" \
|
||||||
@@ -25,9 +49,8 @@ emit_candidates() {
|
|||||||
[[ -d "$d" ]] && printf '%s\n' "$d"
|
[[ -d "$d" ]] && printf '%s\n' "$d"
|
||||||
done
|
done
|
||||||
|
|
||||||
# 3) Shallow git repo discovery under a few likely roots.
|
# 4) Shallow git repo discovery under a few likely roots.
|
||||||
if command -v fd >/dev/null 2>&1; then
|
if command -v fd >/dev/null 2>&1; then
|
||||||
local root gitdir
|
|
||||||
for root in "$HOME/Projects" "$HOME/dotfiles" "$HOME/config" "$HOME/org"; do
|
for root in "$HOME/Projects" "$HOME/dotfiles" "$HOME/config" "$HOME/org"; do
|
||||||
[[ -d "$root" ]] || continue
|
[[ -d "$root" ]] || continue
|
||||||
# Find ".git" directories; print their parent (repo root).
|
# Find ".git" directories; print their parent (repo root).
|
||||||
@@ -43,9 +66,23 @@ dedup() {
|
|||||||
awk 'NF && !seen[$0]++'
|
awk 'NF && !seen[$0]++'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
existing_dirs() {
|
||||||
|
local dir
|
||||||
|
while IFS= read -r dir; do
|
||||||
|
[[ -d "$dir" ]] && printf '%s\n' "$dir"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
if [[ "${1:-}" == "--print-candidates" ]]; then
|
||||||
|
emit_candidates | dedup | existing_dirs
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
debug "script=$0 codex_home=$codex_home history_file=$history_file terminal=$terminal"
|
||||||
selected_dir="$(
|
selected_dir="$(
|
||||||
emit_candidates | dedup | rofi -dmenu -i -p 'tmcodex dir'
|
emit_candidates | dedup | existing_dirs | rofi -dmenu -i -p 'tmcodex dir' || true
|
||||||
)"
|
)"
|
||||||
|
debug "selected_dir=$selected_dir"
|
||||||
|
|
||||||
[[ -n "${selected_dir}" ]] || exit 0
|
[[ -n "${selected_dir}" ]] || exit 0
|
||||||
|
|
||||||
@@ -61,7 +98,9 @@ if command -v realpath >/dev/null 2>&1; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ! -d "$selected_dir" ]]; then
|
if [[ ! -d "$selected_dir" ]]; then
|
||||||
# Fail quietly; rofi launchers generally shouldn't spam terminals.
|
if command -v notify-send >/dev/null 2>&1; then
|
||||||
|
notify-send "tmcodex launcher" "Directory not found: $selected_dir"
|
||||||
|
fi
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -70,19 +109,15 @@ tmp="$(mktemp)"
|
|||||||
{
|
{
|
||||||
printf '%s\n' "$selected_dir"
|
printf '%s\n' "$selected_dir"
|
||||||
cat "$history_file"
|
cat "$history_file"
|
||||||
} | dedup | head -n 200 >"$tmp"
|
} | awk 'NF && !seen[$0]++ && count++ < 200' >"$tmp"
|
||||||
mv -f "$tmp" "$history_file"
|
mv -f "$tmp" "$history_file"
|
||||||
|
|
||||||
# rofi launches typically have no controlling terminal. Start the agent detached
|
terminal_argv=(${(z)terminal})
|
||||||
# inside tmux (tmux allocates a pty for the window). You can attach later.
|
if (( ${#terminal_argv[@]} == 0 )); then
|
||||||
base="$(basename -- "$selected_dir")"
|
if command -v notify-send >/dev/null 2>&1; then
|
||||||
ck="$(printf '%s' "$selected_dir" | cksum | awk '{print $1}')"
|
notify-send "tmcodex launcher" "Terminal command is empty"
|
||||||
session="codex-${base}-${ck}"
|
fi
|
||||||
# tmux is picky; keep session name simple.
|
exit 1
|
||||||
session="$(printf '%s' "$session" | tr -cs 'A-Za-z0-9_-' '-' | sed 's/^-//;s/-$//')"
|
|
||||||
|
|
||||||
if tmux has-session -t "$session" 2>/dev/null; then
|
|
||||||
exec tmux new-window -t "$session" -c "$selected_dir" codex --dangerously-bypass-approvals-and-sandbox
|
|
||||||
else
|
|
||||||
exec tmux new-session -d -s "$session" -c "$selected_dir" codex --dangerously-bypass-approvals-and-sandbox
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
("${terminal_argv[@]}" -e zsh -lc 'cd -- "$1" && exec tmcodex' zsh "$selected_dir" >/dev/null 2>&1 &!)
|
||||||
|
|||||||
Reference in New Issue
Block a user