steamscope.sh: Universal Steam Launcher for Linux

🎮 Why this matters Running games via Steam on Linux often feels like “dancing with a tambourine”: different engines need different flags, AMD and NVIDIA require different environment variables, and tools like Gamescope and MangoHud must be manually inserted into launch commands. Solution: steamscope.sh - a wrapper script that: ✅ Auto-detects GPU (AMD/NVIDIA) and applies appropriate optimizations ✅ Supports engine-specific flags: Source, Unreal, Unity ✅ Integrates Gamescope, Gamemode, MangoHud, FSR in one command ✅ Works as %command% in Steam launch options ✅ Doesn’t break standard launch - everything is optional 💡 The script doesn’t replace Proton or Steam - it makes their work predictable and configurable. ...

07 Apr 2026 · 5 min · 993 words · Potato Energy Team, ponfertato

Heltec V4: Your Own Network Without Internet. Part 1: Why Bother?

Imagine: you’re hiking, at a dacha, in an area with poor signal - or you just want to communicate without carriers, clouds, and surveillance. Solution: decentralized LoRa network - low-power radio with range up to several kilometers. 💡 This isn’t an internet replacement. It’s “internet for emergencies, privacy, and experiments”. Who this series is for: ✅ Friends and relatives who want to understand “why do I need this” ✅ Beginners in radio/electronics (no soldering required!) ✅ Anyone who values privacy and infrastructure independence 📡 LoRa and mesh networks (in simple terms) LoRa (Long Range) Parameter Value Range 1–10 km urban, 50+ km line-of-sight Power ~100 mA transmit, ~10 mA idle Speed 0.3–50 kbps (text, coordinates, small data only) Frequency 433 MHz (RU), 868 MHz (EU), 915 MHz (US) Simple analogy: ...

07 Apr 2026 · 5 min · 943 words · Potato Energy Team, ponfertato

HyperOS: Remove Chrome from Second Space

The Problem After switching to HyperOS (POCO, Xiaomi), links from apps (Telegram, WhatsApp, etc.) open in the cloned Chrome account instead of the main one - even when the main Chrome is set as default browser. Symptoms: Click link → Chrome opens in second space Default browser settings show main Chrome Resetting settings doesn’t help Cause: HyperOS prioritizes cloned apps when handling intents, ignoring user preference. 💡 Issue reproduces on MIUI 14 / HyperOS 1.0+ with “Dual Apps” / “Second Space” enabled. ...

20 Mar 2026 · 3 min · 573 words · Potato Energy Team, ponfertato

Obtainium: App Updates from Source

Obtainium is an Android update manager that downloads apps directly from developer repositories (GitHub, GitLab, Codeberg, F-Droid), bypassing third-party stores. Why you need it: Get updates faster than Google Play / F-Droid Avoid trackers and ads from third-party stores Control which versions are installed (stable, beta, pre-release) Automate updates without manual confirmation 💡 Obtainium doesn’t host apps - it only points where to download them. You always know the source. ...

20 Mar 2026 · 4 min · 692 words · Potato Energy Team, ponfertato

Shizuku: Android System Access Without Root

Shizuku is a service that gives apps access to Android system APIs without root. It works via ADB (Android Debug Bridge), using shell privileges. Why you need it: Install apps without confirmation (Obtainium, SAI) Freeze/unfreeze apps (Ice Box, Hail) Manage permissions (AppOps, Permission Pilot) Change system settings (DarQ, Naptime) Remove system apps (Canta, AppManager) 💡 Shizuku doesn’t grant full root - only limited access to system functions. Safer than root, but more powerful than a regular app. ...

20 Mar 2026 · 4 min · 712 words · Potato Energy Team, ponfertato

Docker WSL: Disk Cleanup & Optimization

Docker Desktop on Windows uses WSL2 with dynamic VHDX files. They grow when adding images/containers but don’t shrink automatically when deleting them. Result: C: drive fills up, even though docker system df shows free space. 💡 Solution: manual VHDX optimization via PowerShell + Docker utility. 📦 Cleanup script Create file # File: $HOME\Scripts\docker-clear-wsl.ps1 $script = @' $LOCAL = "$env:LOCALAPPDATA\Docker\wsl" $VHD1 = Join-Path $LOCAL "disk\docker_data.vhdx" $VHD2 = Join-Path $LOCAL "main\ext4.vhdx" # 1. Docker cleanup docker system prune -f # 2. Reclaim space via official tool docker run --rm --privileged --pid=host docker/desktop-reclaim-space docker rmi docker/desktop-reclaim-space -f # 3. Stop Docker Desktop Get-Process -Name "Docker Desktop","com.docker.backend","com.docker.build" ` -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue # 4. Shutdown WSL wsl --shutdown # 5. Optimize VHDX files (compact) if (Test-Path $VHD1) { Optimize-VHD -Path $VHD1 -Mode Full } if (Test-Path $VHD2) { Optimize-VHD -Path $VHD2 -Mode Full } # 6. Restart Docker Desktop Start-Sleep -Seconds 2 Start-Process -FilePath "$env:ProgramFiles\Docker\Docker\Docker Desktop.exe" ` -ErrorAction SilentlyContinue '@ $script | Out-File -FilePath "$HOME\Scripts\docker-clear-wsl.ps1" -Encoding UTF8 Run # As Administrator (required for Optimize-VHD) powershell.exe -ExecutionPolicy Bypass -File "$HOME\Scripts\docker-clear-wsl.ps1" 🔍 How it works Step Command What it does 1 docker system prune -f Removes stopped containers, unused images, build cache 2 docker/desktop-reclaim-space Official Docker tool to reclaim space in WSL2 3 Stop-Process Gracefully stops Docker Desktop (otherwise VHDX is locked) 4 wsl --shutdown Fully shuts down WSL, freeing files for optimization 5 Optimize-VHD -Mode Full Compacts VHDX files, returning space to host 6 Start-Process Restarts Docker Desktop Why this way: ...

17 Mar 2026 · 3 min · 614 words · Potato Energy Team, ponfertato

GitHub CLI: Bulk Delete Old Issues

Long-running projects accumulate outdated issues: bugs for old versions, features that are no longer relevant, test tickets. Manual deletion is slow and tedious. This script automatically finds and deletes (or marks) old issues by specified labels. 💡 Script uses dry-run by default - shows what would be deleted, without actual deletion. 📦 Script: delete-issues.sh Full code #!/bin/bash # Delete old GitHub Issues by labels and date # Usage: ./delete-issues.sh [--execute] set -euo pipefail # === CONFIG === REPO="owner/repo" # Repository in owner/repo format LABELS='label1,label2,label3' # Labels to filter (comma-separated) CUTOFF="2025-12-31T23:59:59Z" # Delete issues created BEFORE this date DRY_RUN=true # true = preview only, false = actually delete # Parse arguments if [[ "${1:-}" == "--execute" ]]; then DRY_RUN=false echo "⚠️ Mode: ACTUAL DELETION" else echo "ℹ️ Mode: DRY RUN (nothing will be deleted)" fi echo "🔍 Searching issues in $REPO with labels: $LABELS, created before $CUTOFF" echo "---" # Fetch and filter issues gh issue list --repo "$REPO" --state all --limit 1000 \ --json number,title,createdAt,labels,url | \ jq -r --arg labels "$LABELS" --arg cutoff "$CUTOFF" ' ($labels | split(",")) as $label_array | .[] | select(.createdAt < $cutoff) | select(.labels | map(.name) | any(. as $l | $label_array | index($l))) | "\(.number)|\(.title)|\(.url)" ' | \ while IFS='|' read -r number title url; do if [[ "$DRY_RUN" == "true" ]]; then echo "[DRY RUN] ##$number - $title" echo " $url" else echo "🗑 Deleting ##$number - $title" gh issue delete "$REPO" "$number" --yes sleep 1 # Small pause to avoid rate limits fi done echo "---" echo "✅ Done" Install dependencies # GitHub CLI # Windows (winget): winget install GitHub.cli # Linux (Ubuntu/Debian): sudo apt install gh # macOS (Homebrew): brew install gh # Authenticate gh auth login # jq (JSON processor) # Windows (winget): winget install jq.jq # Linux: sudo apt install jq # macOS: brew install jq Run # Make script executable chmod +x delete-issues.sh # DRY RUN (safe mode - preview only) ./delete-issues.sh # ACTUAL DELETION (add --execute flag) ./delete-issues.sh --execute 🔍 How it works Step-by-step breakdown Step Command What it does 1 gh issue list --json ... Fetches issues as JSON with fields: number, title, date, labels, URL 2 jq -r ... Filters: date < cutoff AND has at least one of specified labels 3 while read ... Processes each matching issue 4 gh issue delete Deletes issue (only if DRY_RUN=false) jq filter logic ($labels | split(",")) as $label_array | # Split label string into array .[] | # For each issue select(.createdAt < $cutoff) | # Only if created before cutoff select( .labels | map(.name) | # Get list of label names any(. as $l | $label_array | index($l)) # Check if any matches our labels ) | "\(.number)|\(.title)|\(.url)" # Format output Why this way: ...

17 Mar 2026 · 5 min · 880 words · Potato Energy Team, ponfertato