I love those kinds of programs! I create aliases and small shell functions all the time in this style. One of my favorites is a puts function that basically evals in Ruby what I type. I often use it to do maths and date calculations. I know you can do this in shell, but I do so much Ruby that it is like a second language (third, after English?) for me.
function puts() {
ruby -r date -e "puts($*)"
}
$ puts Date.today + 10 # What day is ten days from now?
2022-03-19
$ puts "10 ** 3 / 9.0"
111.11111111111111
I just open devtools in the browser, or maybe aa node repl instead, to each their own :)
One of my first utilities that I wrote was a dice, we wanted to play GURPS but didn’t have dice so I wrote one quickly. Back in the nineties there were no cellphones. I’ve written such things before and after but this one i always remember.
NB: I’m not the author, though the excellent @jvns is!
I’ve written numerous tiny scripts and programs to mold my desktop workflow to my wants, one of my favorites a series of scripts that lets me search though files (filtering with rofi/dmenu) in predetermined locations in my homedir, and then pipes the file name to a custom plumber script (written in fennel) that uses file name and mime type to determine a program to open the file, it’s incredibly fast for finding random files! The script also has a few regexen for opening urls, it’s nice for things like opening youtube links directly in mpv.
Another one is a screenshotting script that combines slurp (choosing windows/rectangles on screen), grim (wayland screenshotting), and uploading directly to an image pastebin for really fast screenshot sharing.
In a similar spirit, I often end up writing many small elisp functions for individual projects to reduce the friction of the development cycle. I’m currently taking an undergraduate operating systems course, and I have a function that lets me quickly choose a user program to boot up the OS under qemu with gdb, of course taking advantage of emacs’ gdb mode. I love how easy emacs makes it to write tiny bits of software to support and integrate my workflows!
Bind it to a paste-like hotkey (e.g. cmd-ctrl-v). Now you can grab text on slideshows by screenshotting it and pasting it as actual text! (well, it will just transform your pasteboard data, but it’s pretty close)
During the early pandemic, I started learning Go. One of the first programs I wrote uses the bitly API to shorten a URL from the clipboard or the command line. I use this all the time when writing emails in mutt. In fact, I use it so often, that I wrote a small wrapper to make it easier to call from within vim.
I really enjoy writing this kind of small programs as well. Some time ago I wrote a program that sits in the windows system tray and lets me switch the main display by just right-clicking and selecting the right display, because most games don’t support choosing the output display and I wanted to play videogames on my TV, which is just an external monitor with a very long (6m!) HDMI cable.
I also do it at work whenever I have to transform data or automate some boring stuff. Recently we had to use this script given to us by the client that used a library that was also provided to us by the client, and we used Rust so we had to write bindings to all the functions. We still had to use the script fairly frequently because it did some stuff that we didn’t need to do in our project and so we didn’t write bindings for those functions, and the script was annoying to use because it would take a while to execute and it would ask you for some input halfway through, so with the power of Ruby and popen3 I wrote a script that ran that script capturing stdin and then wrote the parameters you passed via command line in the right order to that process’s stdin. Oh, and it also ran “make” before doing all that to ensure it was using the latest version of the library.
My most used tool fits the same niche, but I realized that I didn’t actually care about watching files so I simplifed it.
It is basically a small wrapper around entr that watches a single static path. Then I have a matching hook in my editor that touches that path whenever I save. I call the command w and I use it for basically everything I do. My most use command it probably w cargo test and my next 3 most used command are probably also the script.
The name w did cone from watch, but it was nice to avoid having to bother actually telling it which files to watch and just make it run-on-save (or whatever else I want to touch that file).
I wrote many such programs, but here’s an old one I just remembered that made me smile: in 2007 I needed to time subtitles on Linux. Typical software like Aegisub didn’t work well enough yet, so I just used markers in Audacity and wrote a small Perl script to convert .aup files to .ass (Advanced SubStation Alpha) format…
I’ve been working on an omnifocus clone that I just have running in Heroku for my own usage, it’s a clunky program but it’s also nice cuz I’m not having to really do as much product design.
One thing that’s frustrating for me recently (especially with web stuff) is I have to choose between “nice to code in” or “easy to deploy/make accessible”. I really wish the Django deployment story was nicer (and like… single-file Django projects were doable), cuz I’m super familiar with it but the “easy” solution (Heroku) is pretty costly
More modern alternatives to Heroku like fly.io or render.com have generous free plans which include databases / storage if you are inclined to use those.
Here’s my list of tiny programs https://adi.onl/projects.html, the log analyzers are soon the be updated. There’s a set of plain text linters in there, percent encoding on the CLI, TAP testing for the CLI, a generic shell preprocessor, my static site generator, Void Linux installation script and my dotfiles if that counts. :P
With the spikes of gasoline prices, I have developed a tiny program that find the station with best gasoline prices close to my position. This might become a public website in the future
I have mostly automated my mailing list: I save the links in Raindrop, save to Notion, write a bit of text, and send through Buttondown. It’s still work in progress, but it works nicely.
To fronting vaccine booking for my parents, I wrote a script that check if the vaccine was open for their age group.
When I moved to my new house, there was some technical problems to activate my ADSL (the telecom company need to dig into the street and it was planned, but not scheduled). Then I wrote a scraper that every 2 hours check on the website if my address was available for a new ADSL line.
My wife is working on property management. For law enforcement, at the end of the month, they need to send details about guests to police. It’s a tedious activity to make by hand because you need to fill up a form for every guest. So, my wife has prepared a form in Airtable that the guests must fill up with all the information needed; then I wrote a Lambda function that at the end of the month, get the data from Airtable, generate a file in the format for bulk upload and send it to my wife via email. I saved her hours.
I am in Italy and the government authority daily release a CSV with the prices of fuel. They are not real time updated, but this is enough for my scope.
When the second COVID vaccine doses opened up, all of the slots were full. It turned out that the website’s backend had an API, so I wrote a script to poll the API every 60 seconds or so and watch for cancellations and notify me so that I could get an earlier appointment.
This didn’t turn out to be necessary (more appointments opened up pretty soon anyway and there were enough for everyone), but it was fun.
I did that too (there was no obvious API in my case - I wrote some java that checked the site using selenium every 5 minutes until it stopped saying “no appointments are available” and then sent myself a text that I should go try to complete the enrollment). I suspect there were a lot of software engineers writing this sort of thing in March of 2021.
I had a school project to generate crosswords. It was pretty fun (except the part where I had to write it in Java). I used simulated annealing to try and fit the crosswords into the smallest space possible. That also allowed for loops (but occasionally it created isolated crosswords).
I wrote t, a tiny wrapper around tmux that just opens a new, named tmux session with one, two, or three panes (defaults to three) and optionally runs a different command in each one. If the session by that name is already running, it just opens it.
Now, most of my aliases for “bring up project X” run something like:
t projectname 'vim -S project.vim' 'yarn start' 'some helper cmd'
I had a silly one that was really just part of an otherwise already amusing evening.
We were doing a dinner party, where each person could only order three things for each course, from a list. (This included cutlery.) It was all in Italian, and anyone who knew any, had to have their order selected by someone else.
I didn’t want to give anything away via the ordering of entries, so ideally, the menu would be random, and not even the same for each person. A bit of Perl later, and I had generated PostScript to send to the laser printer, creating one randomized menu per person.
A bunch of these have ended up in my Bash history: sort multi-line chunks of text, refresh browser window every N seconds, a bunch of batch processing stuff, and just any old complex command I can never remember, like how to use find, tar, etc.
I’ve got a number of simple sites / projects where full-blown CI/CD is overkill, and just copying files from staging to production is a lot more efficient for deployment. I setup a few basic scripts to make this a little easier. I create a .project file in the project root that has info for the remote path to the project, and then I have a couple of tiny scripts that read the .project file and can sync files in different ways:
rollout.sh[1] - Rsyncs a particular file (or path) to the remote server.
pullin.sh[2] - Rsyncs files from remote to the local path (I should probably combine this with rollout, but I’ve never been bothered enough to do it.)
pvimdiff[3] - Vimdiff, except it compares the local file with the same file on the remote server
Nice, when I was to pick a nickname, I wrote a script which finds letter combinations with the least amount of search results in Bing. And yeah, I also ended up not using it.
I love those kinds of programs! I create aliases and small shell functions all the time in this style. One of my favorites is a
puts
function that basically evals in Ruby what I type. I often use it to do maths and date calculations. I know you can do this in shell, but I do so much Ruby that it is like a second language (third, after English?) for me.Very cool ! I always do this by opening a Python shell, but never thought about making a shortcut: thanks :D
I just open devtools in the browser, or maybe aa node repl instead, to each their own :)
One of my first utilities that I wrote was a dice, we wanted to play GURPS but didn’t have dice so I wrote one quickly. Back in the nineties there were no cellphones. I’ve written such things before and after but this one i always remember.
Why did you call it
puts
?To follow the name of Ruby’s method to print to output. You can even see me calling it in the code
puts($*)
.Also, it not only evals the code, but prints its result.
I have a similar one:
but since I haven’t found anything as good as php’s strtotime(), it remains the only script that forces me to install php :( Source here: https://github.com/chelmertz/dotfiles/blob/master/bin/datedate
A coworker of mine created something like this in Rust:
Note that GNU date can do this built-in:
This has made my Friday.
Maybe https://github.com/hroptatyr/dateutils do the same job without PHP?
My aliases
Favorite one is
cdtemp
, great for quickly testing out stuff.NB: I’m not the author, though the excellent @jvns is!
I’ve written numerous tiny scripts and programs to mold my desktop workflow to my wants, one of my favorites a series of scripts that lets me search though files (filtering with rofi/dmenu) in predetermined locations in my homedir, and then pipes the file name to a custom plumber script (written in fennel) that uses file name and mime type to determine a program to open the file, it’s incredibly fast for finding random files! The script also has a few regexen for opening urls, it’s nice for things like opening youtube links directly in
mpv
.Another one is a screenshotting script that combines
slurp
(choosing windows/rectangles on screen),grim
(wayland screenshotting), and uploading directly to an image pastebin for really fast screenshot sharing.In a similar spirit, I often end up writing many small elisp functions for individual projects to reduce the friction of the development cycle. I’m currently taking an undergraduate operating systems course, and I have a function that lets me quickly choose a user program to boot up the OS under qemu with
gdb
, of course taking advantage of emacs’ gdb mode. I love how easy emacs makes it to write tiny bits of software to support and integrate my workflows!That sounds a bit like “godothecorrectthing” (https://github.com/andrewchambers/godothecorrectthing), which acts on the clipboard’s content.
Love this!
The single most useful tiny program I’ve written gives you OCR powers on Mac OS, with countless applications:
Bind it to a paste-like hotkey (e.g. cmd-ctrl-v). Now you can grab text on slideshows by screenshotting it and pasting it as actual text! (well, it will just transform your pasteboard data, but it’s pretty close)
Dependencies: pngpaste, textcleaner, tesseract
One old and one recent tiny favorite:
One of the first programs I ever wrote is a tiny perl script that grabs a haiku at random from a list of haikus and prints the poem to the terminal. It is a terrible program: I used a bunch of obscure perl built-in variables—most of which I can’t even remember anymore—and it’s way more complicated than it needs to be. But I love what it gives me: I smile every time I type
haiku
into a terminal and read a poem. (The translations are from Robert Haas’s The Essential Haiku: Versions of Bashō, Buson, and Issa. I’m not qualified to say that these are good translations, but I enjoy them very much.)During the early pandemic, I started learning Go. One of the first programs I wrote uses the bitly API to shorten a URL from the clipboard or the command line. I use this all the time when writing emails in mutt. In fact, I use it so often, that I wrote a small wrapper to make it easier to call from within vim.
I really enjoy writing this kind of small programs as well. Some time ago I wrote a program that sits in the windows system tray and lets me switch the main display by just right-clicking and selecting the right display, because most games don’t support choosing the output display and I wanted to play videogames on my TV, which is just an external monitor with a very long (6m!) HDMI cable.
I also do it at work whenever I have to transform data or automate some boring stuff. Recently we had to use this script given to us by the client that used a library that was also provided to us by the client, and we used Rust so we had to write bindings to all the functions. We still had to use the script fairly frequently because it did some stuff that we didn’t need to do in our project and so we didn’t write bindings for those functions, and the script was annoying to use because it would take a while to execute and it would ask you for some input halfway through, so with the power of Ruby and popen3 I wrote a script that ran that script capturing stdin and then wrote the parameters you passed via command line in the right order to that process’s stdin. Oh, and it also ran “make” before doing all that to ensure it was using the latest version of the library.
Probably the most useful program I’ve written in this style was a polling file system watcher which I use almost every day.
I know that entr exists, but it doesn’t exist on Windows at the moment, so this Janet program works quite well for me.
My most used tool fits the same niche, but I realized that I didn’t actually care about watching files so I simplifed it.
It is basically a small wrapper around entr that watches a single static path. Then I have a matching hook in my editor that touches that path whenever I save. I call the command
w
and I use it for basically everything I do. My most use command it probablyw cargo test
and my next 3 most used command are probably also the script.The name
w
did cone from watch, but it was nice to avoid having to bother actually telling it which files to watch and just make it run-on-save (or whatever else I want to touch that file).Disabling retweets is amazing. Your feed turns from echo chamber to mostly original content.
Yes, there are also a few more tricks to reduce spam, but I think mostly manual.
I wrote many such programs, but here’s an old one I just remembered that made me smile: in 2007 I needed to time subtitles on Linux. Typical software like Aegisub didn’t work well enough yet, so I just used markers in Audacity and wrote a small Perl script to convert .aup files to .ass (Advanced SubStation Alpha) format…
I love these tiny personal programs.
I’ve been working on an omnifocus clone that I just have running in Heroku for my own usage, it’s a clunky program but it’s also nice cuz I’m not having to really do as much product design.
One thing that’s frustrating for me recently (especially with web stuff) is I have to choose between “nice to code in” or “easy to deploy/make accessible”. I really wish the Django deployment story was nicer (and like… single-file Django projects were doable), cuz I’m super familiar with it but the “easy” solution (Heroku) is pretty costly
Have you looked at Caprover? I’ve used it to consolidate some apps onto a single VPS.
@rtpg see also https://dokku.com/, which claims to be heroku compatible (but it’s all hosted on one box you rent).
More modern alternatives to Heroku like fly.io or render.com have generous free plans which include databases / storage if you are inclined to use those.
Here’s my list of tiny programs https://adi.onl/projects.html, the log analyzers are soon the be updated. There’s a set of plain text linters in there, percent encoding on the CLI, TAP testing for the CLI, a generic shell preprocessor, my static site generator, Void Linux installation script and my dotfiles if that counts. :P
With the spikes of gasoline prices, I have developed a tiny program that find the station with best gasoline prices close to my position. This might become a public website in the future
I have mostly automated my mailing list: I save the links in Raindrop, save to Notion, write a bit of text, and send through Buttondown. It’s still work in progress, but it works nicely.
To fronting vaccine booking for my parents, I wrote a script that check if the vaccine was open for their age group.
When I moved to my new house, there was some technical problems to activate my ADSL (the telecom company need to dig into the street and it was planned, but not scheduled). Then I wrote a scraper that every 2 hours check on the website if my address was available for a new ADSL line.
My wife is working on property management. For law enforcement, at the end of the month, they need to send details about guests to police. It’s a tedious activity to make by hand because you need to fill up a form for every guest. So, my wife has prepared a form in Airtable that the guests must fill up with all the information needed; then I wrote a Lambda function that at the end of the month, get the data from Airtable, generate a file in the format for bulk upload and send it to my wife via email. I saved her hours.
Oooh as someone that lives in California, I love that first one. Where do you scrape the data from?
I am in Italy and the government authority daily release a CSV with the prices of fuel. They are not real time updated, but this is enough for my scope.
I did that too (there was no obvious API in my case - I wrote some java that checked the site using selenium every 5 minutes until it stopped saying “no appointments are available” and then sent myself a text that I should go try to complete the enrollment). I suspect there were a lot of software engineers writing this sort of thing in March of 2021.
I had a school project to generate crosswords. It was pretty fun (except the part where I had to write it in Java). I used simulated annealing to try and fit the crosswords into the smallest space possible. That also allowed for loops (but occasionally it created isolated crosswords).
A nice tool for this is anydice.
I wrote
t
, a tiny wrapper aroundtmux
that just opens a new, named tmux session with one, two, or three panes (defaults to three) and optionally runs a different command in each one. If the session by that name is already running, it just opens it.Now, most of my aliases for “bring up project X” run something like:
I had a silly one that was really just part of an otherwise already amusing evening. We were doing a dinner party, where each person could only order three things for each course, from a list. (This included cutlery.) It was all in Italian, and anyone who knew any, had to have their order selected by someone else.
I didn’t want to give anything away via the ordering of entries, so ideally, the menu would be random, and not even the same for each person. A bit of Perl later, and I had generated PostScript to send to the laser printer, creating one randomized menu per person.
tiny is my favorite kind of programming, i like making cli tools and websites that really do one thing pretty good:
nows
: remove all whitespace from piped in input: https://github.com/nkcmr/nowsprettylist
: take new-line delimited input and make it into pretty comma delimited lists with quite a few options: https://github.com/nkcmr/prettylistage
encryption tool: https://age-online.com/A bunch of these have ended up in my Bash history: sort multi-line chunks of text, refresh browser window every N seconds, a bunch of batch processing stuff, and just any old complex command I can never remember, like how to use
find
,tar
, etc.I’ve got a number of simple sites / projects where full-blown CI/CD is overkill, and just copying files from staging to production is a lot more efficient for deployment. I setup a few basic scripts to make this a little easier. I create a .project file in the project root that has info for the remote path to the project, and then I have a couple of tiny scripts that read the .project file and can sync files in different ways:
rollout.sh[1] - Rsyncs a particular file (or path) to the remote server.
pullin.sh[2] - Rsyncs files from remote to the local path (I should probably combine this with rollout, but I’ve never been bothered enough to do it.)
pvimdiff[3] - Vimdiff, except it compares the local file with the same file on the remote server
[1] https://github.com/lftl/dotfiles/blob/master/bin/rollout.sh [2] https://github.com/lftl/dotfiles/blob/master/bin/pullin.sh [3] https://github.com/lftl/dotfiles/blob/master/bin/pvimdiff
Nice, when I was to pick a nickname, I wrote a script which finds letter combinations with the least amount of search results in Bing. And yeah, I also ended up not using it.
https://github.com/boris-marinov/obscure-names
These are nifty.