Companion Scripts
Overseer manages SSH tunnels, but real-world setups often involve more than just SSH. You might need to start a VPN before connecting, run a setup script when entering a context, or toggle services based on your location. This page covers patterns for using scripts alongside overseer.
Context-Driven Scripts
Using overseer's shell integration, you can run scripts that react to context changes.
Shell Precmd Approach
The simplest approach runs a script on every prompt, using the exported context:
# ~/.zshrc or ~/.bashrc
function _overseer_context_hook() {
source ~/.config/overseer/overseer.env 2>/dev/null || return
# Track context changes
if [[ "$OVERSEER_CONTEXT" != "$_LAST_OVERSEER_CONTEXT" ]]; then
_LAST_OVERSEER_CONTEXT="$OVERSEER_CONTEXT"
_on_context_change "$OVERSEER_CONTEXT"
fi
}
function _on_context_change() {
local context="$1"
case "$context" in
untrusted)
# Start local SOCKS proxy
if ! pgrep -x privoxy > /dev/null; then
privoxy ~/.config/privoxy/config 2>/dev/null &
fi
;;
trusted|corporate)
# Stop proxy if running
pkill -x privoxy 2>/dev/null
;;
esac
}
precmd_functions+=(_overseer_context_hook)File-Watching Approach
For actions that should happen immediately (not waiting for the next prompt), watch the context file:
#!/bin/bash
# ~/.local/bin/overseer-watcher.sh
# Run with: overseer-watcher.sh &
CONTEXT_FILE="$HOME/.config/overseer/context.txt"
LAST_CONTEXT=""
while true; do
if [[ -f "$CONTEXT_FILE" ]]; then
CONTEXT=$(cat "$CONTEXT_FILE")
if [[ "$CONTEXT" != "$LAST_CONTEXT" ]]; then
LAST_CONTEXT="$CONTEXT"
echo "Context changed to: $CONTEXT"
case "$CONTEXT" in
untrusted)
# Start VPN
~/.local/bin/vpn-connect.sh
;;
*)
# Stop VPN if running
~/.local/bin/vpn-disconnect.sh
;;
esac
fi
fi
sleep 2
doneVPN Companion Scripts
A common pattern is connecting a VPN when overseer enters certain contexts.
OpenConnect VPN
#!/bin/bash
# ~/.local/bin/vpn-connect.sh
VPN_HOST="vpn.example.com"
VPN_USER="david"
# Check if already connected
if pgrep -x openconnect > /dev/null; then
echo "VPN already connected"
exit 0
fi
# Get password from system keyring (macOS)
VPN_PASS=$(security find-generic-password -a "$VPN_USER" -s "vpn" -w 2>/dev/null)
if [[ -z "$VPN_PASS" ]]; then
echo "No VPN password found in keyring"
echo "Store it with: security add-generic-password -a '$VPN_USER' -s 'vpn' -w"
exit 1
fi
echo "$VPN_PASS" | sudo openconnect \
--user="$VPN_USER" \
--passwd-on-stdin \
--background \
"$VPN_HOST"WireGuard VPN
#!/bin/bash
# ~/.local/bin/wg-toggle.sh
INTERFACE="wg0"
case "$1" in
up)
if ! wg show "$INTERFACE" > /dev/null 2>&1; then
sudo wg-quick up "$INTERFACE"
fi
;;
down)
if wg show "$INTERFACE" > /dev/null 2>&1; then
sudo wg-quick down "$INTERFACE"
fi
;;
esacStartup Scripts
Combine overseer with your system startup:
# ~/.zshrc
# Start overseer daemon (silently if already running)
overseer start -q
# Source context environment
[[ -f ~/.config/overseer/overseer.env ]] && source ~/.config/overseer/overseer.envHelper Script: Active Gateway Check
This script checks if you need to use a jump host, useful in SSH config Match exec:
#!/bin/bash
# ~/.local/bin/need-gateway.sh
# Usage in ssh config: Match host *.internal exec "~/.local/bin/need-gateway.sh"
source ~/.config/overseer/overseer.env 2>/dev/null || exit 1
case "$OVERSEER_LOCATION" in
office|datacenter)
# On the local network, no gateway needed
exit 1
;;
*)
# Everywhere else, use the gateway
exit 0
;;
esacMatch host *.internal.example.com exec "~/.local/bin/need-gateway.sh"
ProxyJump gate.example.comWriting Your Own Scripts
When writing scripts that integrate with overseer:
Read from export files — Don't call
overseer statusin tight loops. Read the exported files instead — they're updated atomically on every state change.Handle missing files gracefully — The export files may not exist if overseer hasn't started yet:
CONTEXT=$(cat ~/.config/overseer/context.txt 2>/dev/null || echo "unknown")- Use the dotenv file for multiple variables — If you need more than one variable, source the dotenv file once rather than reading multiple files:
source ~/.config/overseer/overseer.env 2>/dev/null- Debounce reactions — If watching for file changes, add a small delay to avoid reacting to intermediate states during rapid network transitions.
