feat(installer): add hypr-lens/hl wrappers and satty integration

Complete the satty annotation feature on the install side:
- Install hypr-lens + hl wrapper scripts (detach on launch, sync for IPC)
  and remove them on uninstall
- Add satty as an optional dependency and bundle defaults/satty.toml into
  the config dir (never touches ~/.config/satty)
- Update README/MANUAL to use the hypr-lens/hl commands instead of raw
  'qs --path ...'
- Add dev-update.sh helper for syncing scripts + shell.qml integration
This commit is contained in:
DJ committed 2026-06-06 14:43:15 -04:00
1 parent 1e01b0ab5c
commit 470bab70ec
4 files changed
+139 -13

No files matched your search

+7 -5
View File
@@ -235,19 +235,21 @@ Control hypr-lens programmatically via quickshell IPC:
```bash
# Region screenshot
qs --path ~/.config/quickshell/hypr-lens ipc call region screenshot
hypr-lens ipc call region screenshot
# Image search
qs --path ~/.config/quickshell/hypr-lens ipc call region search
hypr-lens ipc call region search
# OCR
qs --path ~/.config/quickshell/hypr-lens ipc call region ocr
hypr-lens ipc call region ocr
# Recording
qs --path ~/.config/quickshell/hypr-lens ipc call region record
qs --path ~/.config/quickshell/hypr-lens ipc call region recordWithSound
hypr-lens ipc call region record
hypr-lens ipc call region recordWithSound
```
> **Tip:** You can also use the short alias `hl` instead of `hypr-lens`.
**Note:** hypr-lens must be running for IPC commands to work.
## Customizing Keybinds
+5 -3
View File
@@ -163,12 +163,14 @@ killall quickshell; quickshell &
Add to your Hyprland startup (e.g., `execs.conf`):
```bash
exec-once = qs --path ~/.config/quickshell/hypr-lens &
exec-once = hypr-lens
```
To start immediately:
```bash
qs --path ~/.config/quickshell/hypr-lens &
hypr-lens &
# or use the short alias:
hl &
```
</details>
@@ -230,7 +232,7 @@ qs ipc call region record
qs ipc call region recordWithSound
```
> For standalone mode, use: `qs --path ~/.config/quickshell/hypr-lens ipc call ...`
> For standalone mode, use: `hypr-lens ipc call ...` (or `hl ipc call ...`)
See [MANUAL.md](MANUAL.md#ipc-commands) for detailed IPC documentation.
Executable
+42
View File
@@ -0,0 +1,42 @@
#!/bin/bash
# Quick dev update - syncs scripts + ensures shell.qml integration
set -eu
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SCRIPTS_DEST="$HOME/.local/share/hypr-lens/scripts"
SHELL_QML="$HOME/.config/quickshell/shell.qml"
# Sync scripts
echo "Syncing scripts..."
rsync -av --delete "$SCRIPT_DIR/scripts/" "$SCRIPTS_DEST/"
chmod +x "$SCRIPTS_DEST/videos/record.sh"
chmod +x "$SCRIPTS_DEST/images/find-regions-venv.sh"
chmod +x "$SCRIPTS_DEST/images/find_regions.py"
# Shell.qml integration (one-time)
if [[ -f "$SHELL_QML" ]] && ! grep -q "RegionSelector" "$SHELL_QML"; then
echo "Integrating into shell.qml..."
# Find last import line
last_import=$(grep -n "^import" "$SHELL_QML" | tail -1 | cut -d: -f1)
# Find closing brace of Scope
closing_brace=$(grep -n "^}" "$SHELL_QML" | tail -1 | cut -d: -f1)
if [[ -n "$last_import" && -n "$closing_brace" ]]; then
# Insert import after last import
sed -i "${last_import}a import \"./hypr-lens/modules/regionSelector\"" "$SHELL_QML"
# Insert RegionSelector before closing brace (line number shifted by 1 due to previous insert)
closing_brace=$((closing_brace + 1))
sed -i "${closing_brace}i\\ RegionSelector {}" "$SHELL_QML"
echo "✓ Shell integration added"
else
echo "⚠ Could not find insertion points - integrate manually"
fi
else
echo "✓ Shell already integrated"
fi
echo "Done! Restart quickshell: killall quickshell; quickshell &"
+85 -5
View File
@@ -33,7 +33,7 @@ Generated (you copy manually):
Requirements:
Required: quickshell, grim, slurp, wl-copy, hyprctl, notify-send, jq
Optional: tesseract, swappy, wf-recorder, hyprpicker, python3, opencv, matugen
Optional: tesseract, satty, swappy, wf-recorder, hyprpicker, python3, opencv, matugen
EOF
exit 0
}
@@ -75,6 +75,8 @@ QML_INSTALL_DIR="$HOME/.config/quickshell/hypr-lens"
SCRIPTS_INSTALL_DIR="$HOME/.local/share/hypr-lens/scripts"
VENV_DIR="$HOME/.local/share/hypr-lens/venv"
CONFIG_DIR="$HOME/.config/hypr-lens"
WRAPPER_PATH="$HOME/.local/bin/hypr-lens"
WRAPPER_ALIAS="$HOME/.local/bin/hl"
# ==============================================================================
# Helper Functions
@@ -194,6 +196,7 @@ declare -A CMD_TO_PKG=(
["magick"]="imagemagick"
# Optional
["tesseract"]="tesseract"
["satty"]="satty"
["swappy"]="swappy"
["wf-recorder"]="wf-recorder"
["hyprpicker"]="hyprpicker"
@@ -365,6 +368,54 @@ install_scripts() {
success "Scripts installed"
}
install_wrapper_script() {
info "Installing wrapper scripts"
if dry_run_preview \
"Would create: $WRAPPER_PATH" \
"Would create: $WRAPPER_ALIAS (symlink)"; then
return
fi
# Check for existing hypr-lens command
if command -v hypr-lens &>/dev/null; then
local existing=$(command -v hypr-lens)
if [[ "$existing" != "$WRAPPER_PATH" ]]; then
warn "hypr-lens command already exists at: $existing"
if ! ask "Overwrite with new wrapper?"; then
info "Skipping wrapper installation"
return 0
fi
fi
fi
# Create directory if needed
mkdir -p "$(dirname "$WRAPPER_PATH")"
# Create main wrapper script
cat > "$WRAPPER_PATH" << 'EOF'
#!/bin/sh
# hypr-lens wrapper - auto-detaches for launch, sync for IPC
QS_PATH="$HOME/.config/quickshell/hypr-lens"
# IPC calls need synchronous execution for output
if [ "$1" = "ipc" ]; then
exec qs -p "$QS_PATH" "$@"
fi
# Launch mode: detach from terminal
# setsid creates new session, nohup ignores hangup, &>/dev/null silences output
setsid -f qs -p "$QS_PATH" "$@" &>/dev/null
EOF
chmod +x "$WRAPPER_PATH"
# Create short alias (symlink to main wrapper)
ln -sf "$WRAPPER_PATH" "$WRAPPER_ALIAS"
success "Wrappers installed: hypr-lens, hl"
}
setup_python_venv() {
if ! command -v python3 &>/dev/null; then
warn "Python3 not found, skipping venv setup"
@@ -403,7 +454,8 @@ install_config() {
if dry_run_preview \
"Would create: $CONFIG_DIR" \
"Would copy: $SCRIPT_DIR/defaults/config.json → $CONFIG_DIR/config.json" \
"Would copy: $SCRIPT_DIR/defaults/CONFIG_README.md → $CONFIG_DIR/CONFIG_README.md"; then
"Would copy: $SCRIPT_DIR/defaults/CONFIG_README.md → $CONFIG_DIR/CONFIG_README.md" \
"Would copy: $SCRIPT_DIR/defaults/satty.toml → $CONFIG_DIR/satty.toml"; then
return
fi
@@ -437,6 +489,20 @@ install_config() {
success "Default config installed"
fi
success "Config README installed"
# Bundled satty annotation config (passed to satty via -c; never touches ~/.config/satty)
if [[ -f "$CONFIG_DIR/satty.toml" ]]; then
warn "satty config already exists at $CONFIG_DIR/satty.toml"
if ask "Overwrite with defaults?"; then
cp "$SCRIPT_DIR/defaults/satty.toml" "$CONFIG_DIR/satty.toml"
success "satty config overwritten"
else
success "Keeping existing satty config"
fi
else
cp "$SCRIPT_DIR/defaults/satty.toml" "$CONFIG_DIR/satty.toml"
success "satty config installed"
fi
}
generate_keybinds_example() {
@@ -600,6 +666,7 @@ uninstall() {
echo "Components to remove:"
echo " - QML modules: $QML_INSTALL_DIR"
echo " - Scripts: $SCRIPTS_INSTALL_DIR"
echo " - Wrappers: $WRAPPER_PATH, $WRAPPER_ALIAS"
echo ""
echo "Optional (will ask):"
echo " - Python venv: $VENV_DIR"
@@ -615,6 +682,10 @@ uninstall() {
remove_if_exists "$QML_INSTALL_DIR" "QML modules"
remove_if_exists "$SCRIPTS_INSTALL_DIR" "scripts"
# Remove wrapper scripts
[[ -f "$WRAPPER_PATH" ]] && rm -f "$WRAPPER_PATH" && success "Removed: $WRAPPER_PATH"
[[ -L "$WRAPPER_ALIAS" ]] && rm -f "$WRAPPER_ALIAS" && success "Removed: $WRAPPER_ALIAS"
# Optional removals
remove_if_exists "$VENV_DIR" "Python venv" --prompt "Remove Python venv ($VENV_DIR)?"
remove_if_exists "$CONFIG_DIR" "config" --prompt "Remove config ($CONFIG_DIR)?"
@@ -670,10 +741,11 @@ show_next_steps() {
echo " killall quickshell; quickshell &"
else
echo -e "1. ${BOLD}Start hypr-lens (for this session):${NC}"
echo " qs --path ~/.config/quickshell/hypr-lens &"
echo " hypr-lens &"
echo " # or use the short alias: hl &"
echo ""
echo -e "2. ${BOLD}Add startup to your execs.conf:${NC}"
echo " exec-once = qs --path ~/.config/quickshell/hypr-lens &"
echo " exec-once = hypr-lens"
fi
# Determine next step number based on what was shown above
@@ -869,7 +941,7 @@ install() {
info "Checking dependencies..."
check_and_install "required" quickshell grim slurp wl-copy jq notify-send magick
check_and_install "optional" tesseract swappy wf-recorder hyprpicker python3 matugen
check_and_install "optional" tesseract satty swappy wf-recorder hyprpicker python3 matugen
success "Required dependencies found"
echo ""
@@ -889,6 +961,7 @@ install() {
# Install components
install_qml_modules
install_scripts
install_wrapper_script
update_directories_paths
install_config
@@ -960,6 +1033,13 @@ update() {
success "Scripts updated"
fi
# Install/update wrapper scripts
if [[ -f "$WRAPPER_PATH" ]]; then
success "Wrapper scripts already installed"
else
install_wrapper_script
fi
# Update Directories.qml paths (always needed)
update_directories_paths