-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathinstall.sh
More file actions
executable file
·155 lines (138 loc) · 5.38 KB
/
Copy pathinstall.sh
File metadata and controls
executable file
·155 lines (138 loc) · 5.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/bin/bash
set -e
echo "=== dictate: push-to-talk voice input ==="
ARCH=$(uname -m)
# Detect distro
if [ -f /etc/os-release ]; then
. /etc/os-release
DISTRO="$ID"
else
DISTRO="unknown"
fi
echo "Detected: $DISTRO"
# Install system deps
case "$DISTRO" in
fedora)
echo "Installing system packages..."
sudo dnf install -y portaudio wl-clipboard
# wtype may not be available on all Fedora versions
sudo dnf install -y wtype 2>/dev/null || echo "wtype not available, clipboard-only mode"
;;
ubuntu|debian)
echo "Installing system packages..."
sudo apt-get update
sudo apt-get install -y libportaudio2 portaudio19-dev wl-clipboard wtype
;;
*)
echo "Unknown distro '$DISTRO'. Install manually: portaudio, wl-clipboard, wtype"
;;
esac
# Add user to input group (for evdev access without sudo)
if ! groups "$USER" | grep -q '\binput\b'; then
echo "Adding $USER to input group..."
sudo usermod -aG input "$USER"
echo "NOTE: Log out and back in for group change to take effect."
fi
# Create venv and install Python deps
VENV_DIR="$HOME/.local/share/dictate/venv"
echo "Creating venv at $VENV_DIR..."
if command -v uv &>/dev/null; then
PIP="uv pip"
uv venv "$VENV_DIR"
else
PIP="$VENV_DIR/bin/pip"
python3 -m venv "$VENV_DIR"
fi
# On aarch64 (Jetson): install pre-built ctranslate2 wheel
if [ "$ARCH" = "aarch64" ]; then
WHEEL_DIR="$HOME/.local/share/dictate/wheels"
WHEEL=$(ls "$WHEEL_DIR"/ctranslate2*.whl 2>/dev/null | head -1)
if [ -z "$WHEEL" ]; then
echo ""
echo "ERROR: No ctranslate2 wheel found in $WHEEL_DIR/"
echo " On aarch64 (Jetson), build it first: bash build-ctranslate2.sh"
exit 1
fi
echo "Installing pre-built ctranslate2 wheel: $(basename "$WHEEL")"
$PIP install --python "$VENV_DIR/bin/python" "$WHEEL"
fi
$PIP install --python "$VENV_DIR/bin/python" -r "$(dirname "$0")/requirements.txt"
# Install CUDA libs if NVIDIA GPU is present (x86_64 only — Jetson uses JetPack system CUDA)
if [ "$ARCH" != "aarch64" ] && command -v nvidia-smi &>/dev/null; then
echo "NVIDIA GPU detected, installing CUDA libraries..."
$PIP install --python "$VENV_DIR/bin/python" nvidia-cublas-cu12
fi
# Install launcher script
echo "Installing dictate to ~/.local/bin/"
mkdir -p ~/.local/bin
if [ "$ARCH" = "aarch64" ]; then
cat > ~/.local/bin/dictate <<LAUNCHER
#!/bin/bash
VENV="$VENV_DIR"
export LD_LIBRARY_PATH="/usr/local/cuda/lib64\${LD_LIBRARY_PATH:+:\$LD_LIBRARY_PATH}"
exec "\$VENV/bin/python" -u "$HOME/.local/share/dictate/dictate.py" "\$@"
LAUNCHER
else
NVIDIA_LIBS="$VENV_DIR/lib64/python*/site-packages/nvidia/cublas/lib"
cat > ~/.local/bin/dictate <<LAUNCHER
#!/bin/bash
VENV="$VENV_DIR"
for d in $NVIDIA_LIBS; do
[ -d "\$d" ] && export LD_LIBRARY_PATH="\$d\${LD_LIBRARY_PATH:+:\$LD_LIBRARY_PATH}"
done
exec "\$VENV/bin/python" -u "$HOME/.local/share/dictate/dictate.py" "\$@"
LAUNCHER
fi
chmod +x ~/.local/bin/dictate
# Copy the actual script and editor wrapper
cp "$(dirname "$0")/dictate" "$HOME/.local/share/dictate/dictate.py"
cp "$(dirname "$0")/dictate-editor" ~/.local/bin/dictate-editor
chmod +x ~/.local/bin/dictate-editor
# Install default config (don't overwrite existing)
mkdir -p ~/.config/dictate
if [ ! -f ~/.config/dictate/config.toml ]; then
cp "$(dirname "$0")/config.toml.example" ~/.config/dictate/config.toml
echo "Created config at ~/.config/dictate/config.toml"
fi
# Install global hints (don't overwrite existing)
mkdir -p ~/.config/dictate/hints.d
for f in "$(dirname "$0")"/hints.d/*; do
[ -f "$f" ] || continue
dst=~/.config/dictate/hints.d/"$(basename "$f")"
[ -f "$dst" ] || cp "$f" "$dst"
done
echo "Installed global hints to ~/.config/dictate/hints.d/"
# Install Claude Code integration
mkdir -p ~/.claude/commands
cp "$(dirname "$0")/dictate.claude-command" ~/.claude/commands/dictate.md
echo "Installed /dictate command for Claude Code."
# Install systemd services (optional, for background daemon + push-to-talk)
if [ -d /run/systemd/system ] && [ "$ARCH" != "aarch64" ]; then
echo ""
read -p "Install systemd services for background daemon + push-to-talk? [Y/n] " yn
yn="${yn:-y}"
if [[ "$yn" =~ ^[Yy] ]]; then
mkdir -p ~/.config/systemd/user
cp "$(dirname "$0")/dictate.service" ~/.config/systemd/user/dictate.service
cp "$(dirname "$0")/dictate-ptt.service" ~/.config/systemd/user/dictate-ptt.service
systemctl --user daemon-reload
systemctl --user enable --now dictate dictate-ptt
echo "Services installed and started."
# Install suspend/resume hook (signals daemon on wake)
if [ ! -f /usr/lib/systemd/system-sleep/dictate-resume ]; then
sudo cp "$(dirname "$0")/dictate-resume" /usr/lib/systemd/system-sleep/dictate-resume
sudo chmod +x /usr/lib/systemd/system-sleep/dictate-resume
echo "Installed suspend/resume hook."
fi
fi
fi
echo ""
echo "Done! Run: dictate"
echo " Hold Right Ctrl to record, release to transcribe."
echo " Ctrl+V to paste the transcribed text."
echo " Edit ~/.config/dictate/config.toml to customize."
echo ""
if grep -q "^input:.*\b$USER\b" /etc/group && ! id -nG 2>/dev/null | grep -qw input; then
echo "⚠ IMPORTANT: Log out and back in for input group membership to take effect."
echo " Without this, dictate cannot detect key presses."
fi