#!/usr/bin/env bash # claudedo bootstrap — does the system setup pip can't. idempotent: re-running is # safe and won't duplicate the shell-rc cc kit. run from the repo root. set -euo pipefail REPO_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ASOUNDRC="$HOME/.asoundrc" MARKER_BEGIN="# >>> claudedo cc kit >>>" MARKER_END="# <<< claudedo cc kit <<<" say() { printf '\n\033[1;36m==> %s\033[0m\n' "$*"; } warn() { printf '\033[1;33m!! %s\033[0m\n' "$*" >&2; } die() { printf '\033[1;31mxx %s\033[0m\n' "$*" >&2; exit 1; } # 1. windows-side checks (cannot automate — check and instruct) ----------------- say "checking WSLg audio bridge" if [ ! -e /mnt/wslg/PulseServer ]; then die "WSLg PulseServer missing (/mnt/wslg/PulseServer). claudedo needs WSLg audio. update WSL ('wsl --update' in Windows) or install WSL from the Microsoft Store, then restart WSL ('wsl --shutdown') and re-run this script." fi echo " /mnt/wslg/PulseServer present" cat <<'EOF' MANUAL WINDOWS STEP (this script cannot do it for you): Windows Settings -> Privacy & security -> Microphone -> enable "Let desktop apps access your microphone". Without this, the mic is silent inside WSL. Do it now if you haven't. EOF # 2. WSL audio deps (apt) ------------------------------------------------------- say "installing WSL audio dependencies (apt)" sudo apt-get update sudo apt-get install -y libportaudio2 libasound2t64 libasound2-plugins \ alsa-utils pulseaudio-utils # 3. ALSA -> Pulse routing ------------------------------------------------------ say "configuring ALSA -> Pulse routing (~/.asoundrc)" if [ -f "$ASOUNDRC" ] && grep -q "type pulse" "$ASOUNDRC"; then echo " ~/.asoundrc already routes to pulse" else { echo "pcm.!default { type pulse }" echo "ctl.!default { type pulse }" } >> "$ASOUNDRC" echo " wrote pulse default to ~/.asoundrc" fi if [ -z "${PULSE_SERVER:-}" ] && [ -e /mnt/wslg/PulseServer ]; then export PULSE_SERVER="unix:/mnt/wslg/PulseServer" echo " exported PULSE_SERVER=$PULSE_SERVER (WSLg usually sets this already)" fi # 4. verify audio (fail loudly with guidance) ----------------------------------- say "verifying audio path" if pactl info >/dev/null 2>&1; then DEFAULT_SRC="$(pactl info | sed -n 's/^Default Source: //p')" echo " Default Source: ${DEFAULT_SRC:-}" if ! pactl list sources short 2>/dev/null | grep -q RDPSource; then warn "RDPSource not listed by pactl — mic may not be bridged. check Windows mic permission." fi else warn "pactl info failed — pulseaudio-utils installed but no server reachable yet." fi TESTWAV="/tmp/claudedo_test.wav" if arecord -D default -f S16_LE -c 1 -r 16000 -d 2 "$TESTWAV" >/dev/null 2>&1 && [ -s "$TESTWAV" ]; then echo " arecord captured 2s -> $TESTWAV ($(stat -c%s "$TESTWAV") bytes)" else warn "arecord could not capture. fix-chain: apt deps above + ~/.asoundrc + Windows mic permission. debug anytime with: claudedo test-audio" fi # 5. python install + model prime ----------------------------------------------- say "installing the claudedo python package" PIP="${PIP:-pip3}" "$PIP" install -e "$REPO_DIR" say "priming the faster-whisper model (so first run isn't slow)" MODEL="$(sed -n 's/^model *= *"\(.*\)".*/\1/p' "$REPO_DIR/config.toml" | head -1)" MODEL="${MODEL:-small}" python3 - "$MODEL" <<'PY' || warn "model prime failed — first run will download it" import sys from faster_whisper import WhisperModel WhisperModel(sys.argv[1], device="cpu", compute_type="int8") print(" primed faster-whisper model:", sys.argv[1]) PY # 6. cc kit as a sourced file + rc wiring (idempotent) -------------------------- say "installing the cc kit (~/.config/claudedo/cc.sh)" CONF_DIR="$HOME/.config/claudedo" mkdir -p "$CONF_DIR" install -m 0644 "$REPO_DIR/shell/cc.sh" "$CONF_DIR/cc.sh" echo " wrote $CONF_DIR/cc.sh" # wire EVERY rc that exists (the user may have both zsh and bash). wired_any=0 for RC in "$HOME/.zshrc" "$HOME/.bashrc"; do [ -f "$RC" ] || continue wired_any=1 if grep -qF "$MARKER_BEGIN" "$RC"; then echo " cc kit marker already in $RC (not duplicating)" continue fi cp "$RC" "$RC.claudedo.bak" echo " backed up $RC -> $RC.claudedo.bak" cat >> "$RC" <<'CCKIT' # >>> claudedo cc kit >>> [ -f ~/.config/claudedo/cc.sh ] && source ~/.config/claudedo/cc.sh # <<< claudedo cc kit <<< CCKIT echo " wired source-line block into $RC (open a new shell or 'source $RC')" done [ "$wired_any" = 1 ] || warn "no ~/.zshrc or ~/.bashrc found — add the marker block from README.md manually." # warn about any OLD loose cc defs outside our markers (do not auto-delete). for RC in "$HOME/.zshrc" "$HOME/.bashrc"; do [ -f "$RC" ] || continue loose="$(grep -nE '^[[:space:]]*(cc|ccr|ccl|cck|cckl|_cc_name)[[:space:]]*\(\)' "$RC" \ | grep -v 'claudedo' || true)" if [ -n "$loose" ]; then warn "old cc-function defs found in $RC (outside the claudedo markers):" echo "$loose" | sed 's/^/ /' echo " review and remove them by hand — the new sourced kit overrides them, but" echo " they are dead code. a backup is at $RC.claudedo.bak" fi done # 7. tmux settings for reliable send-keys (idempotent ~/.tmux.conf append) ------- say "configuring tmux for reliable send-keys (~/.tmux.conf)" TMUX_CONF="$HOME/.tmux.conf" TMUX_MARKER="# >>> claudedo tmux >>>" touch "$TMUX_CONF" if grep -qF "$TMUX_MARKER" "$TMUX_CONF"; then echo " claudedo tmux block already present (not duplicating)" else cat >> "$TMUX_CONF" <<'TMUXCONF' # >>> claudedo tmux >>> # settings for reliable keystroke injection + notifications (do not edit inside the # markers; re-run install.sh to refresh). escape-time 0 stops injected Escape from # being misread; allow-passthrough + extended-keys let notifications and modified # keys (Shift+Enter) reach the claude pane; the larger history-limit keeps scrollback. set -g escape-time 0 set -g history-limit 50000 set -g allow-passthrough on set -s extended-keys on set -as terminal-features 'xterm*:extkeys' # <<< claudedo tmux <<< TMUXCONF echo " appended claudedo tmux settings to $TMUX_CONF (reload: tmux source-file ~/.tmux.conf)" fi say "done. next: 'claudedo test-audio' then 'claudedo start'"