Skip to content

Instantly share code, notes, and snippets.

@Cdaprod
Last active September 22, 2025 17:18
Show Gist options
  • Save Cdaprod/cb8ee6eaded70a7df6d808093c9df2a3 to your computer and use it in GitHub Desktop.
Save Cdaprod/cb8ee6eaded70a7df6d808093c9df2a3 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
# Autostart tiler: Chromium (LEFT -> $URL) + terminal (RIGHT -> tmux attach to "recent" + optional follow-up)
# - If a tmux session exists, attach to the most-recent one by default.
# - Optionally inject a FOLLOWUP_CMD into that tmux session as a new window or split.
# - Falls back to plain shell if no tmux sessions exist.
# - Preserves your original tiling logic.
set -euo pipefail
# ---------------- config ----------------
URL="https:app.cdaprod.dev/login"
TERM_TITLE="DeskAuto Tmux"
MAX_TRIES=60
# ── tmux attach policy ────────────────────────────────────────────────────────
# TMUX_SESSION:
# "recent" → attach to most recently used session (auto-detected)
# "<name>" → attach to this named session if it exists, else fallback to shell
TMUX_SESSION="recent"
# FOLLOW-UP behavior (runs *inside* tmux if we attach, otherwise in the same shell):
# "tmux:new-window" → create a new tmux window running FOLLOWUP_CMD
# "tmux:split-h" → split horizontally and run FOLLOWUP_CMD
# "tmux:split-v" → split vertically and run FOLLOWUP_CMD
# "shell:sequential" → run AFTER initial command in the same shell
# "off" → do nothing extra
FOLLOWUP_MODE="tmux:new-window"
# Your follow-up command (examples):
FOLLOWUP_CMD="ssh [email protected] 'z that && sleep 10 && dcl -f'"
# FOLLOWUP_CMD="ssh [email protected] 'journalctl -fu capture-daemon'"
# FOLLOWUP_CMD="echo 'No follow-up set'; sleep 1"
# -----------------------------------------------------------------------------
# --- auto-detach when launched from a TTY (manual run) ---
if [ -t 1 ] && [ "${DESKAUTO_FORKED:-0}" != "1" ]; then
exec setsid -f env DESKAUTO_FORKED=1 "$0" "$@" > /tmp/desk-autostart.log 2>&1
fi
need() { command -v "$1" >/dev/null 2>&1 || { echo "Missing: $1" >&2; exit 1; }; }
for b in xdotool wmctrl xrandr xwininfo xprop; do need "$b"; done
export DISPLAY="${DISPLAY:-:0}"
# ---- pick browser ----
CHROMIUM_BIN="$(command -v chromium-browser || true)"; [ -z "$CHROMIUM_BIN" ] && CHROMIUM_BIN="$(command -v chromium || true)"
[ -n "$CHROMIUM_BIN" ] || { echo "Chromium not found"; exit 1; }
# ---- pick terminal ----
TERM_BIN="$(command -v lxterminal || true)"
if [ -z "$TERM_BIN" ]; then TERM_BIN="$(command -v xfce4-terminal || true)"; fi
[ -n "$TERM_BIN" ] || { echo "No terminal found (need lxterminal or xfce4-terminal)"; exit 1; }
# ---- helpers ----
find_win() { xdotool search --onlyvisible --name "$1" 2>/dev/null | head -n1 || true; }
recent_tmux_session() {
# Returns the most recently attached tmux session name, or empty if none.
tmux ls -F '#{session_last_attached} #{session_name}' 2>/dev/null \
| sort -nr \
| awk 'NR==1{print $2}'
}
resolve_tmux_target() {
local target="${1:-recent}"
if [ "$target" = "recent" ]; then
recent_tmux_session || true
else
echo "$target"
fi
}
tmux_has_session() {
local name="$1"
[ -n "$name" ] || return 1
tmux has-session -t "$name" 2>/dev/null
}
# ---- (re)use existing windows if they already exist ----
CHROM_WIN="$(find_win 'Chromium' || true)"
if [ -z "$CHROM_WIN" ]; then
"$CHROMIUM_BIN" --new-window "$URL" --no-first-run --no-default-browser-check \
--window-size=640,480 --window-position=10,10 >/dev/null 2>&1 &
CHROM_PID=$!
else
CHROM_PID=""
fi
# ── Compose the terminal command ------------------------------------------------
# INITIAL: attach to tmux "recent" (or named). If no tmux, fall back to login shell.
generate_terminal_exec() {
local target session attach_cmd run_follow=""
session="$(resolve_tmux_target "$TMUX_SESSION")"
if tmux_has_session "$session"; then
attach_cmd="tmux attach -t \"$session\""
case "$FOLLOWUP_MODE" in
tmux:new-window)
run_follow="tmux new-window -t \"$session\" -n 'AutoCmd' bash -lc $(printf "%q" "$FOLLOWUP_CMD")"
;;
tmux:split-h)
run_follow="tmux split-window -t \"$session\" -h bash -lc $(printf "%q" "$FOLLOWUP_CMD")"
;;
tmux:split-v)
run_follow="tmux split-window -t \"$session\" -v bash -lc $(printf "%q" "$FOLLOWUP_CMD")"
;;
shell:sequential)
# Will run after attach *only when attach fails* (otherwise attach takes control);
# not very useful for tmux, so warn into log and skip.
run_follow="echo '[desk-autostart] FOLLOWUP_MODE shell:sequential is ignored when attaching to tmux'; true"
;;
off|*)
run_follow=""
;;
esac
if [ -n "$run_follow" ]; then
# Pre-seed the follow-up inside tmux *before* attaching, so it's visible after attach
echo "bash -lc \"$run_follow; $attach_cmd || exec bash -l\""
else
echo "bash -lc \"$attach_cmd || exec bash -l\""
fi
else
# No tmux session available → plain shell path
if [ "$FOLLOWUP_MODE" = "shell:sequential" ]; then
echo "bash -lc \"$FOLLOWUP_CMD; exec bash -l\""
else
echo "bash -lc \"exec bash -l\""
fi
fi
}
TERM_CMD="$(generate_terminal_exec)"
# Launch terminal
if [[ "$TERM_BIN" =~ xfce4-terminal$ ]]; then
"$TERM_BIN" --title "$TERM_TITLE" -e "$TERM_CMD" >/dev/null 2>&1 &
else
lxterminal -T "$TERM_TITLE" -e "$TERM_CMD" >/dev/null 2>&1 &
fi
TERM_PID=$!
# ---- wait helpers ----
wait_for_pid_win() {
local pid="$1" label="$2" tries=200
[ -z "$pid" ] && return 0
for _ in $(seq 1 $tries); do
for w in $(xdotool search --onlyvisible --pid "$pid" 2>/dev/null || true); do
xwininfo -id "$w" >/dev/null 2>&1 && echo "$w" && return 0
done
sleep 0.07
done
echo "Timed out waiting for $label (pid=$pid)" >&2
return 1
}
# resolve window IDs
[ -z "$CHROM_WIN" ] && CHROM_WIN="$(wait_for_pid_win "$CHROM_PID" Chromium || true)"
[ -z "$CHROM_WIN" ] && CHROM_WIN="$(find_win 'Chromium' || true)"
TERM_WIN="$(wait_for_pid_win "$TERM_PID" Terminal || true)"
[ -z "$TERM_WIN" ] && TERM_WIN="$(find_win "$TERM_TITLE" || true)"
[ -n "${CHROM_WIN:-}" ] && [ -n "${TERM_WIN:-}" ] || { echo "Could not resolve window IDs"; exit 0; }
# ---- compute WORKAREA (excludes panels) ----
read -r WA_X WA_Y WA_W WA_H < <(xprop -root _NET_WORKAREA | awk -F'= ' '{print $2}' | tr ',' ' ' | awk '{print $1,$2,$3,$4}')
if [ -z "${WA_W:-}" ] || [ -z "${WA_H:-}" ]; then
read -r _ _ WA_W WA_H < <(xrandr --query | awk '/ connected primary /{print "0 0 "$3}' | sed 's/[x+]/ /g' | head -n1)
WA_X=0; WA_Y=0
fi
L_X=$WA_X; L_Y=$WA_Y; L_W=$(( WA_W / 2 )); L_H=$WA_H
R_X=$(( WA_X+L_W )); R_Y=$WA_Y; R_W=$(( WA_W - L_W )); R_H=$WA_H
# ---- normalize & enforce geometry (bounded retries) ----
normalize() { wmctrl -ir "$1" -b remove,fullscreen,maximized_vert,maximized_horz,hidden,shaded,below || true; }
normalize "$CHROM_WIN"; normalize "$TERM_WIN"; sleep 0.1
apply() {
local wid="$1" x="$2" y="$3" w="$4" h="$5"
wmctrl -ir "$wid" -e 0,"$x","$y","$w","$h" 2>/dev/null || true
}
ok_after() {
local wid="$1" w="$2" h="$3"
read -r _ _ AW AH < <(xwininfo -id "$wid" | awk '/Width:/ {w=$2} /Height:/ {h=$2} END {print 0,0,w,h}')
[ -n "${AW:-}" ] && [ -n "${AH:-}" ] && [ "$AW" -ge $((w-2)) ] && [ "$AH" -ge $((h-2)) ]
}
wmctrl -ir "$CHROM_WIN" -b add,above || true
wmctrl -ir "$TERM_WIN" -b add,above || true
for _ in $(seq 1 "$MAX_TRIES"); do
apply "$CHROM_WIN" "$L_X" "$L_Y" "$L_W" "$L_H"
apply "$TERM_WIN" "$R_X" "$R_Y" "$R_W" "$R_H"
ok_after "$CHROM_WIN" "$L_W" "$L_H" && ok_after "$TERM_WIN" "$R_W" "$R_H" && break
sleep 0.05
done
wmctrl -ir "$CHROM_WIN" -b remove,above || true
wmctrl -ir "$TERM_WIN" -b remove,above || true
wmctrl -ia "$TERM_WIN" || true
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment