- Ruby 45.2%
- Python 33.5%
- Shell 14.7%
- Go 6.6%
| keepass2gopass | ||
| media | ||
| w3mcookies | ||
| battery_alert | ||
| blu | ||
| borgtest | ||
| chaos | ||
| chksum | ||
| cmd | ||
| con | ||
| dither | ||
| kao | ||
| LICENSE | ||
| light | ||
| manc | ||
| qemu_create_vm | ||
| qemu_snapshots_deleter | ||
| qemu_start_vm | ||
| radio | ||
| README.md | ||
| record | ||
| remain | ||
| rssfind | ||
| send | ||
| vidtogif | ||
| vol | ||
| vpn | ||
| web | ||
| workhours | ||
pebbles
Little scripts to improve my CLI life, written in Ruby (stdlib only), Bash, and a few other languages. I use evilwm as my main window manager and some of these scripts aim to add features usually found on full-blown DEs: volume and brightness control, easily enabling / disabling network interfaces, recording screencasts and so on.
Why Ruby for the most part? I stumbled on this post showcasing the language's strengths to replace Bash scripting and it inspired me to rewrite some of my scripts. I ended up rewriting more than anticipated and had a great time. I still don't know if I'd use Ruby for large projects, but this is an elegant language to avoid Bash's pitfalls: no redundant import statements to fully use the stdlib, arguments and environment variables are readily available, parsing flags is easily done by combining optparse and ostruct, and regexes are much more intuitive compared to Python.
Want to parse the output of a command? Use backticks. Want to simply run a command and return to your script once done? Use system().
Nearly all these scripts check for required tools before running, so they shouldn't go awry and leave a mess. Still, make sure to read them before running them.
QEMU scripts
I started using QEMU instead of VirtualBox a few years ago, mainly for performance reasons. My use is pretty straightforward so I don't want to rely on front-ends such as virsh. With a little bit of scripting, using it alone is quite nice.
qemu_create_vm
qemu_create_vm will create a qcow2 empty image of a specified size (default: 50 GiB) and run it with an image of your choice through the -cdrom flag. Upon exiting the first run with your ISO, it will immediately create a snapshot to preserve your fresh install.
Example use:
Usage: qemu_create_vm [options]
-v, --vm-path PATH Where to create the VM file (VM filename will be derived from image filename).
-s, --size SIZE_GB Size of the VM to create in GiB (default: 50 GiB).
-i, --img-path PATH Path of the image file to install on VM.
# create a 30 GiB qcow2 image in ~/qemu and run it with Fedora's ISO:
qemu_create_vm -v ~/qemu -s 30 -i Fedora-Workstation-Live-x86_64-40-1.14.iso
qemu_start_vm
qemu_start_vm launches a selected VM with decent settings for my usecase. It allocates all host's cores and 8 GB RAM by default and forwards 8080 and 8081 ports with SSH for web proxying. Port 22 is redirected to port 2222 to access the VM through SSH, leaving display disabled and QEMU daemonized.
If -d / --desktop flag is used, all aforementioned ports are not forwarded or redirected and VM is started with GTK display instead.
Regardless how the VM is started, a snapshot is always created before launch, tagged with a random hex string of 8 characters. You might want to edit out -k fr option before use, as it enforces a french keyboard layout.
Example use:
Usage: qemu_start_vm [options]
-c, --cores NUM_CORES Max cores allocated to VM (default: all).
-m, --ram NUM_RAM Max RAM allocated to VM (default: 8 GB).
-v, --vm-path PATH Path of the VM file to start.
-d, --desktop Start VM with gtk display (default: no display, SSH only).
qemu_start_vm -m 4 -c 4 -v ~/qemu/fedora_x64.qcow2 --desktop
qemu_snapshots_deleter
qemu_snapshots_deleter loops over all snapshots of a selected VM and use a simple Y/N prompt to either keep a snapshot or delete it. Because snapshots are automatically created with qemu_start_vm before each launch, they can quickly pile up. This script helps pruning them out efficiently without sacrificing this safeguard.
vol and light
vol relies on pactl to decrease/increase volume by 5% increments on default sink until CTRL-C is hit. Use j/k to change volume in a vim-like way.
light does the same thing for brightness, using brightnessctl in 10% increments.
web
web aims to create a pleasant viewing experience for the w3m text-based browser by using tmux panes, in the same fashion goyo provides a distraction-free writing experience in Vim.
It runs the following tmux sequence in a new terminal window:
- Create three equal horizontal panes in new window.
- Resize left and right panes evenly to give center pane a width of ~88 columns.
- Set
PS1=''in all panes to hide prompt. - Set tmux's pane borders to background color to fully hide them.
- If arguments are found, search them on mojeek in
w3m. - If argument matches the pattern of a URL, directly go to specified site.
- If no arguments are found, go to mojeek's homepage.
I use it on a daily basis with newsboat and it's been really worth it.
Example use:
web ruby append list # will search those terms on mojeek.
web https://ovelny.sh/ # go directly to specified site.
web # just go to mojeek's homepage.
manc
Same idea as web, but for manpages: open them centered with the same process described above.
Example use:
manc nmap # will open nmap's manpage in new tmux window, centered.
record
record is a bash script that only uses ffmpeg and ffprobe to record your screen with X11. It does the following:
- Start a 5 seconds countdown before recording, so you can alt-tab where you need to
- Record your screen with
x11grabsetting at 60 FPS, withultrafastpreset to avoid glitches and latency in video output. Video is stored in~/Videos/screencasts - Wait for SIGINT and once CTRL-C is pressed, copy video and remove its last 3 seconds to edit out the alt-tabbing + SIGINT you just did
The final mp4 video uses libx264 and yuv240p to make it shareable via signal desktop, which has been a pain with many other video formats in my case.
This is a very simple script, but it covers nearly all of my screen recording needs. Just run record to use it.
vidtogif
vidtogif uses ffmpeg to convert a video to a gif. Video is not deleted and the gif is saved in the same location with the same base name. It uses palettegen and paletteuse to keep a similar color profile, prompting the user to rescale the gif or not. Gif is rendered at 30 FPS with infinite loop enabled.
Example use:
vidtogif ~/Videos/my_video.mp4
radio
radio is a simple dictionary / hash of all radio playlists I enjoy listening to. When called without arguments, the script will parse all domains from dictionary and build a list of selectable streams. Using radio <stream>, such as radio groove_salad will start playing the stream with mpv in background.
battery_alert
battery_alert is a small acpi wrapper that sends an alert to all pts devices if the last remaining battery has less than 25% power left. It probably won't work if extra non-laptop batteries are detected, such as a wireless mouse, a headset, etc.
I use it with a cronjob, arbitrarily set to run every 8 minutes.
rssfind
RSS is in this strange place, where most people don't care about it for their blogs and sites anymore and yet it's almost always present by default, thanks to frameworks and static site generators. As a result, it can be a bit of a pain to manually guess and find the RSS endpoint of a site you want to follow. rssfind loops over a short list of common RSS endpoints, start a thread for each one of them and outputs all pages that return a 200 status code.
Example use:
rssfind https://ovelny.sh/
RSS feed found: https://ovelny.sh/atom
RSS feed found: https://ovelny.sh/atom.xml
All done.
workhours
workhours is a small companion for the time-tracking tool zeit. It simply parses zeit's output to return the sum of all worked hours in a given month.
Example use:
Usage: workhours [options]
-m, --month MONTH Month to sum up work hours for (example: november).
-y, --year YEAR Year of month to sum up work hours for (default: current year).
workhours -m july
total hours worked in july 2024: 58:32h
chksum
chksum calculates SHA1, SHA256 and MD5 sums of a given file and check if any of those hashes matches the one currently in your clipboard (requires xclip). Checking against all 3 hash functions is inefficient, but let's face it: most of the time, the extra delay is reasonable and this tradeoff for convenience is okay. No more downloading checksum files for a quick check-up.
Example use:
chksum Fedora-Workstation-Live-x86_64-40-1.14.iso
con
con is a wrapper around nmcli to quickly list / enable / disable network interfaces. I plan to expand it in the future to handle more wifi features as well.
Example use:
Usage: con [options]
-u, --up Enable a connection.
-c, --connect Connect to wifi.
-d, --down Disable a connection.
-k, --kill Kill (delete) a connection.
-l, --list List all connections.
-s, --status List status of all devices.
con -u # select a connection to enable by ID list.
con -d # select a connection to disable by ID list.
blu
Terrible (and I mean terrible) wrapper around bluetoothctl that covers 90% of my use case: connecting and trusting a device, removing a device, or listing devices. Also features a weird bug with bluetoothctl devices output that has been awfully filtered.
It works and it's much more practical than raw bluetoothctl commands, but don't expect much from it.
Usage: blu [options]
-c, --connect Pair, connect and trust a bluetooth device.
-d, --disconnect Remove a bluetooth device.
-l, --list List available bluetooth devices.
blu -u # select a device to pair, connect and trust by ID list.
con -d # select a device to remove by ID list.
send
send is a wrapper for wormhole that generates a transfer code with Ruby and copy it to clipboard with xclip. This is just for convenience, so I don't have to manually copy generated codes when transferring files between VMs.
Example use:
send ~/Downloads/script.ps1 # just paste clipboard's content on receiving machine
mullswitch
Using mullvad VPN, or any VPN for that matter, gets more and more tedious every year. I hit captchas regularly and have to switch relays frequently just to avoid being slowed down by Cloudflare. This script takes a country prefix as first argument and parses mullvad CLI tool's output to randomly pick and switch to a corresponding relay.
Example use:
mullswitch de # pick and switch to a random relay in Germany
cmd
cmd is a tool to parse command templates from my wiki, chaos. I use <brackets> to denote settings like target IP and other parameters in commands as those characters are rarely (if ever) found in Bash or Powershell.
cmd loops over all opening and closing bracket parameters from a copied command in clipboard (with xclip), and prompt the user to replace each field with the actual parameter. The completed command is then copied to clipboard, ready for use.
Why? Because it's tedious to keep track of all commands and their nonstandard idiosyncrasies during CTFs (looking at you, long flag arguments with a single dash). If I can avoid wasting that time, I'll take it.
chaos
chaos is a small fzf wrapper to search my cybersecurity wiki on the command-line. When called, it will concatenate all my markdown files and pipe that blob to fzf. If a title is selected, the related file will be opened with less, using the title as a search term for quick focus. If any other line is selected, chaos will grep and output 12 surrounding lines above and below it for quick context and copy the line to clipboard, as i often select commands that way.
It's not possible to use this script without having access to my site's static builder repo, but sharing it might still be useful.
Using both chaos and cmd in conjunction has been really useful so far.
w3mcookies
w3mcookies is a small and crude golang snippet that converts ungoogled-chromium cookies for w3m. It's very basic and all the leg work is accomplished by the kooky library.
It's not limited to chromium, but needs to be edited at line 13 to provide the path of your browser's cookies. To build the binary, run go build inside the w3mcookies directory.
Example use:
# Fetch all cookies that contain "github" in their
# Domain attribute, and output to ~/.w3m/cookie:
w3mcookies github > ~/.w3m/cookie
keepass2gopass
keepass2gopass exports and convert keepass entries to ~/.password-store entries for gopass. It assumes the following:
- Your password store is located in
~/.password-storeand has been already initialized. - Your keepass entries are not nested in directories but directly at the top-level.
gpgandgopassare installed on your Linux system.
If those requirements are met, running keepass2gopass <kdbx file path> will delete all *.gpg files in ~/.password-store before renewing the directory with your keepass entries. This program is hardcoded to run with 16 threads.
I use keepass on all my devices, but syncing the entries to gopass is very convenient to fetch credentials directly from the CLI. And I got tired of relying on pykeepass for this.
kao
List kaomojis I like with their keywords if ran without arguments, or copy one of them to clipboard by passing said keyword as first argument of the script.
remain
Bash script for khal CLI calendar that parses all events for the next 10 years, selects those that begin with "deadline:", and outputs how many days are left for each one of them.
borgtest
Automatically test your borgmatic backups. This script will select your most recent backups in all repositories, pick 5 small random files (max 50M) for each directory backed up, restore them in /tmp and output the first few bytes to check if they seem okay.
I switched back to restic since then, but this might still be useful.
