This website is the personal knowledge base of @jakintosh. It is a collection of thinking, writing, work, and reflection. The goal is to communicate both knowledge and process, and so every page is composed of both a garden and a stream.
The Garden is the manicured, pruned, and always evolving "living document" for a given topic or project. The garden captures the current state of my knowledge, and is the primary content at the top of each page.
The Stream contains a reverse chronological action log that shows what has happened to get the garden to its current state. The stream captures the historical process of knowledge on the site, and can be found at the bottom of every page.
Recently Updated Pages
- [2024-02-18] /woodworking
- [2024-01-07] /architecture
- [2024-01-03] /architecture-ching
- [2023-12-28] /bicycle-manifesto-tracy
- [2023-12-27] /urban-science-bettencourt
- [2023-12-05] /death-and-life-jacobs
- [2023-12-01] /december-adventure
- [2023-11-24] /order-without-design-bertaud
- [2023-11-24] /zoning
- [2023-11-16] /hare
Introduction to Architecture
Francis D.K. Ching & James F. Eckler | Wiley (2012)
Sam Tracy | PM Press (2013)
Introduction to Urban Science
Luis M. A. Bettencourt | MIT Press (2021)
The Death and Life of Great American Cities
Jane Jacobs | Random House (1961)
Order Without Design
Alain Bertaud | MIT Press (2018)
Recent Stream Updates
February 18, 2024
For the past nearly two weeks of my wood shop time, I've been working on an end grain cutting board to replace an aging IKEA cutting board at home. End grain cutting boards are very popular in "pop-woodworking", playing the role of a common project for beginner woodworkers. Knowing this, I jumped into making one thinking it would be an afternoon project. I was wrong.
The main issue is that the strain of woodworking that end grain cutting boards are popular with is the type of suburban dad whose favorite part of being a "DIY guy" is buying power tools. Making an end grain cutting board requires a ton of boring (yet tedious) glue ups, and flattening end grain. In fact, this is the whole process: a mass repetition of cutting boring strips of wood, those tedius glue ups, and then figuring out how to get it flat.
No part of the process was challening or interesting, and the standard way that most people achieve each step is through a heavy application of power tools. It wasn't until I had my final glued cutting board that I realized that I had no idea how to flatten end grain. When I looked it up, I found out that the standard process was either to run it through a planer even though everyone knows it's very dangerous, or to set up this nightmare of a router jig to effectively "CNC" the board flat.
Neither of those options were appealing to me, so I spent a week trying to restore an old hand plane I had in my studio hoping that would help me out. It didn't. I gave up and took the router jig path. While this did end up giving me a flat surface, it also completely chewed it up, collapsing the end grain and tearing out a bunch of divots. I now had a flat surface, but had no idea how to make it smooth. After again pursuing several more human-powered options, I ended up taking a low grit heavy duty handheld belt sander and grinding away until it looked presentable.
In the end, at least I've got a halfway decent looking cutting board. There are still final finishing steps I'd like to take, but overall I look at what I ended up with as a project full of compromises. There's plety of places where I could have "done it right" but didn't, because I hated working on it so much that I just wanted it to be over so that I can get to a different project that was more fulfilling. (I'll post a picture once it's done and oiled.)
The most valuable part of this project was that it gave me so much time to think about what I would rather be doing that it helped crystalize the aspects of woodworking that I love and hate. I love planning and designing furniture, and cutting precise joinery by hand. I hate glue, power tools, and sanding. Tomorrow I'm going to scour ebay for some used japanese hand planes.
January 7, 2024
/stream /reading /colophon
Spent some time building out "Now Reading" functionality using /collect. Essentially, every "page" that describes a book now has a handful of other @value objects on it for metadata like title/author/publisher, and I wrote a few @scope objects that render a book summary using those values. I also tagged those pages with additional @group tags "books" and "in-progress", so I can make a @list with @query objects to @include all of the "in-progress" items and then @filter those for "books". Then I @reverse that list and pass it to the different renderers, and now I can see all of the books that are in progress just by adding some metadata to those books' garden pages.
The recent months have been very busy and unstructured, and have led to a minor case of burnout. A lot of time was spent on a large housing policy change in my city, though it didn't end up nearly as effective as I'd hoped. Many friends, who are fellow advocates and activists, are also running for city council. In the midst of all of this, I (and my partner) finally caught COVID in early December after avoiding it for almost 4 years.
Given all of this, I entered the new year feeling like I had just completed a hard reset. I'm settling into it without any real resolutions, but with a few general directions to move in. Part of what defined the last year for me was a constant urgency that wreaked havoc on my attention, pulling me in a hundred different directions. There's still real work to be done, but I need to do that work in a way that is more sustainable and enjoyable for me.
The first direction is to be moving towards doing fewer "categories" of things. I don't know exactly how this will manifest yet, but I'm a little burnt out on things like organizing roles and low-level computer /programming. I'm also missing other types of work, like /woodworking.
This leads me to my second direction, which is a bit more specific: I want to explore what it might mean to be an "architect". As I've struggled with the intersection of my interests, my nature, and the problems and needs of the world, it feels to me like architecture (in a broad sense) may be the field where I can make the biggest difference. I'm a holistic thinker with aesthetic, design, and engineering sensibilities, a trained game desginer and "coder", and I have a deep understanding of housing policy and urban development. I think that low-impact or /degrowth lifestyles can be enabled, encouraged, and enshrined in creative architecture, and humanity also needs a lot of reponsibly designed and sourced buildings as it continues to shrink its footprint through the energy and urbanization transitions.
The third direction is towards documentation. I built this website last year with the goal of sharing a lot of the things I've learned, both concrete and abstract, but have not made the space to actually get things out of my head and into documentation. Not doing this has been one of the biggest things eating away at me, and I'd like to be more intentional about carving out time for this.
So that's where I'm at. Do less, document more, and explore architecture as an intersection of my skills and interests and the needs of the planet and my neighbors.
December 6, 2023
/stream /programming /december-adventure
Today's work was thinking work. Part of my goal of putting the /coalescent computer on pause was to start framing coalescent data within existing computing systems instead of a blank slate, and so I wanted this project to reflect that. Today I was thinking about how I would manage the different "resources" (accounts, entries, reports) in a coalescent way, and I think I came up with a plan to achieve that.
Each "agent" (user/node pair) will have its own event log, and each log can only be edited by its owner. A log is just a text file where each line describes some (CRUD) event on a resource. The logs can freely be synced with other agents, and each agent can keep track of how long it thinks each log is so that they know when there are new events to process in a given log. If my state tells me that
agent1.log is 40 lines long, but my local copy is now 42 lines long, that means two events have come in for that log since the last time I processed events.
Effectively, this means the CLI will have some commands that write to the local agent's event log, an event log resolver that generates and modifies resources based on all of the event logs as a single logical unit, and then report generating commands that work from the local resources. There can be a little bit of state on an agent that helps it track and cache what it's already computed, but it can also at any point just re-run through all of the event logs again to rebuild the current state. Playing back events means it will also be possible to catch instances where new events are trying to write to "closed" books.
This sounds complicated when writing it all down, but I think with a little more planning it should be possible for this to be implemented pretty quickly (minus syncing, which will just be done with rsync).
December 5, 2023
/stream /programming /hare /december-adventure
Another short December Adventure session today, but I implemented some functionality for creating and listing accounts within a project. For now, this is done by adding files to an 'accounts' directory inside the project, and having each account file be the stringified version of an
account struct. I should probably put together some kind of de/serializing functions that make it easier to re-ingest the text file back into program data later on, and also clean up the way I'm creating "resources" since I'll need to do a lot more of that. Honestly, if I have more than a few minutes to work on this tomorrow I should take a step back and do a bit more planning now that I have all of this infrastructure working.
December 4, 2023
/stream /programming /hare /december-adventure
I only had about twenty minutes for my December Adventure today, but managed to implement the
books list command using the config work from yesterday. I also refactored those config functions to work as a general key-value store, which made it very easy to then also implement
books set project to set the active project. Overall, the work I did yesterday made it so that implementing these other commands was pretty straightforward. I need to come back to this a bit later and think through the error handling a bit better, because for now it just unwraps all the errors with
$ ./books list
$ ./books set project home
December 3, 2023
/stream /programming /hare /december-adventure
Had a pretty packed day, but found a few moments to tinker. Spent most of today's time starting to learn about the
os modules of the standard library. Wrote a few functions for reading and writing files, and now the CLI for
books lets you set a directory where it looks for your projects by default. Trying to lean on the filesystem to do all of the work in this project, so this "setting" is just a file
$XDG_CONFIG_HOME/books/root that contains the path.
$ ./books set root ~/books
$ cat ~/.config/books/root
December 2, 2023
/stream /programming /hare /december-adventure
Today's work on the December Adventure was more fleshing out of the command tree as I was thinking about the different types of resources that need to be created and managed. Things like accounts, journal entries, and so on. Fleshing out the tree has been a good test of my cli module, and is also a good way to think through the use of the program as a set of resources being managed.
I also needed to figure out a way to have the user set an active project and let the program know where to find project directories, and this led me to learn about the XDG Base Directory Specification, which is what defines the ~/.local, ~/.config, and ~/.cache directories, and what types of files should go in each. I learned something new, and also figured out how I should handle the default storage of configuration and state data for this program.
December 1, 2023
/stream /programming /hare /december-adventure
I've been cutting my teeth on /hare for a few weeks now, and yesterday I finally got my "learning project" (a CLI argument parsing module) finished. So today, I started work on a CLI double-entry bookkeeping program which I think is going to be my December Adventure for 2023.
Today's work was fleshing out a command tree using my new argument parsing module, and then learning about how the Hare compiler uses multiple source files. I can now compile a binary that executes a few placeholder subcommands.
November 24, 2023
/stream /reading /order-without-design-bertaud
Through my work on /livable city advocacy in my home city, I've met a lot of people with different lenses on how to look at some of the core issues. One of those people has been one of the most analytical and data driven policy thinkers I've ever met, and while at first the approach came across as cold to me, over the course of a year it became harder and harder for me to deny how well informed his thoughts were and how clearly his approach reflected the reality I was seeing in urban policy every day. The book he would frequently bring up as a primary influence to him was "Order Without Design: How Markets Shape Cities".
As someone who is both highly critical of the economic structure of Capitalism, but simultaneously holding a worldview centered on holarchy and emergent complex systems, there is a deep tension around the notion of "markets". Markets are not strictly tied to Capitalism, but markets are integral to its broader philosohpy. At the same time, markets are the same shape as one of the key information channels in an emergent and distributed complex system. As I solidified my distrust in The Market(tm) and began to cautiously embrace lower-case "m" markets as a social communication channel, I began to finally read this book.
The first chapter begins by outlining the author's experience as an urban planner starting in the 60s, his first experiences that showed him the cracks in traditional planning logic, and his first meaningful encounter with an urban economist that gave him deeper insight as to what actually caused those cracks in planning logic. It immediately touched on concrete examples of issues around /zoning and land prices, which is something we are dealing with right now, and I think that I'll come out of this book with a much more grounded understanding of urban economies and planning policy.
November 17, 2023
/stream /repair /bicycle /fixie
The intention for the /fixie was always that it would be deeply refurbished and modifed over the winter. After a few months of riding it around and getting a feel for it, it was finally time to take the first step of a full disassembly, followed by a cleaning and a paint job.
When I bought the bike, it already had a pretty poorly applied two-tone spray-paint job, so I had always intended to sand it down and repaint it properly. I removed everything except the headset and bottom bracket, masked those off, and painted the bike a "British Racing Green" using
Since it's already mid-November here in Vermont, I was racing against the clock to get the bike painted before the temperature got too cold for the paint to be effective. I wish I had taken a bit more time to be more detailed in my sanding work and take the painting process slowly, but it was looking like I only had one last chance for the weather to cooperate the day I painted. Overall, it came out nicely, with only a few minor patches where previous paint/rust spots had not been fully smoothed out.
November 14, 2023
/stream /technology /programming /hare
Over the past few days, I've been starting to get acquainted with the Hare programming language. Someone on Merveilles mentioned something about it, and after looking it up something really clicked about it for me. I'd been really starting to sour a bit on Rust, especially the complexity of the ecosystem, and was thinking that I should start to learn 'C'. So finding the Hare language, which is an opinionated 'C' replacement whose opinions heavily match my own, has been a joy.
From what I can tell so far, the core idea behind Hare is that "Understandability of the Toolchain" should be the highest goal. You can bootstrap the compiler with gcc in about 30 seconds, with about 30k lines of source code. That's faster than building most simple Rust binaries with an empty cache. In terms of language features, it is focused on proven ideas implemented well, and consistency over syntactic sugar. As an example of its philosophy, its implementation of tagged unions turn a very basic type system into something that punches way above its weight class in terms of capabilities and program correctness. It makes a big leap from something like C towards something like Rust, but with an order of magnitude less complexity.
So far, the only things close to a "dealbreaker" is the limited editor integrations, like in-editor compiler warnings, and autocomplete/autoformatting. Perhaps I can try my hand at an LSP implementation...
November 11, 2023
/stream /technology /imac-2013
Acquired another new computer today, a 21.5" /iMac (2013). I'm writing this update from that computer, having moved over all of my tools and configuration. I'm not sure it's really a useful skill to be able to configure an old mac as a personal linux machine, but I'm getting pretty good at it. I appreciate the smaller footprint and lower power consumption than the 27" /iMac (2020) that it replaces. All of my transition towards linux as my daily driver operating system has occured on laptops so far, so this is the first time bringing my work to my desk on a (slightly) bigger screen.
It's nice to finally have a linux desktop, though I'm bummed that my layout on my split keyboard does not translate at all from macOS to Linux. There are way too many hot-key changes, and so many programs implicitly rely on the QWERTY layout, that my custom configuration and ColemakDH layout were painful, and I've temporarily reverted back to a standard-issue Apple keyboard. I'll have to slowly redesign and (readjust to) the layout as I continue using my environment at a desktop setting.
November 8, 2023
/stream /technology /permacomputing /repair /macbook-2007
Disassembled the /MacBook (2007) today to give a proper internal dusting and a fresh application of thermal paste. Even after all the work done on the /MacBook Pro (2006), I still find myself using the /MacBook (2007) as my daily driver now, because it's smaller, lighter, and the plastic doesn't burn my legs as much as the metal case on the Pro. However, I've noticed that the CPU still seems to get quite hot, and I figured the 16 year old thermal paste wasn't helping much.
After the application, I noticed that peak thermals were much lower: ~68C as opposed to the ~80C I was seeing before when doing something like compiling a rust binary. The stable idle temperature during a work session hasn't changed much (~58C), but it takes much longer to reach that temperature (about 20 minutes of working), and temperature recovery back to baseline after a spike is also noticably better.
Hopefully this preventative maintenance extends the life of this computer even further than it was on track to go.
October 25, 2023
A few days ago, I finally took a stab at a multi-machine "dotfiles" system. To get a feel for the challenges presented by a highly portable software environment, I've been jumping around between three different laptops, /MacBook (2007), /MacBook Pro (2006), and /MacBook Pro (2015). Keeping all of the distinct physical environments in sync as a single logical environment has been a huge, manual pain. The machines had slightly different configuration needs, so it took me a while to sit down and think about a solution. The approach I decided on was this: a "dotfiles" repo that holds the common configuration without any sensitive data (like user or server names in aliases), and then each machine assigns values to the secret environment variables, sources the common config root, and then adds any machine specific config in its local
One of the interesting parts that took some thinking was how to handle my shell script "micro apps", like my journaling utility. I used to just throw all the journal shell scripts in
~/bin and then define aliases to those scripts in
.zshrc file, but with this new setup it ended up coupling machine configuration with "app" installation. Instead, I created a new repo just for the "journal app", which is composed of its original scripts and a new
api.sh script, which exports a necessary environment variable and defines the aliases to its functional scripts. So now, on each computer that I want to "install" the journal on, I just clone the journal repo and then source the
api.sh code from my local .zshrc.
All said and done, a local .zshrc file now looks roughly something like this on all of my different machines:
export SYNCUSER=## omitted ##
export SYNCSERVER=## omitted ##
export SYNCDIR=## omitted ##
October 22, 2023
As per usual, the past six weeks have been incredibly busy. A large chunk of September was dedicated to organizing a downtown block party for World Car Free Day, which was a big success. I built some diy street barricades to help close the street, and we had a ton of neighbors turn out to celebrate.
Much of my time also continues to be dominated by the same /livable cities advocacy group, as we have become the primary group leading the grassroots conversation around policy changes needed to alleviate our city's housing crisis. With a comprehensive residential zoning overhaul in the works right now, there's not much time for other things.
I had some quiet time on a train recently, which I used to begin chipping away at a bare-minimum operating system for the coalescent computer, which I've nicknamed "lesceOS". It's been a good exercise to push the co assembler and toolchain a bit further, and get more practice writing my own language.
The art co-op is continuing to find its footing, and has not disappeared yet. We're starting to find some ways to bring in money to pay for rent, and I'm also learning about some of the types of situations that work better with delegated decision makers, vs needing consensus from 10 people.
/stream /tactical-urbanism /woodworking /diy-pallet-barricades
Wrote out the bulk of what I learned from building street barricades out of reclaimed pallets last month, in an effort to get it in writing before I forget. Still need to revisit later to add images, and perhaps some 3D illustrations/animations for maximum impact.
October 21, 2023
/stream /linux /games
With October in full swing, I've been in the mood to replay Space Funeral, a bizarre and spooky RPG Maker 2003 game by thecatamites with one of the best soundtracks in anything, ever. It's an old school windows EXE, and so I figured it would be a prime candidate to be run via Wine on Arch Linux. To make a long story short, I got it working. I imagine you can follow these instructions to get this game (and other similar RPG Maker games) working for yourself.
First, we need to make the lib32 packages available in pacman by enabling the multilib repo. We do this by uncommenting the
[multilib] section near the bottom of
Include = /etc/pacman.d/mirrorlist
Then we can install Wine and the other necessary components:
sudo pacman -S wine \
This installs Wine along with the 32bit dependencies for OpenGL and audio playback, and then configures Wine into win32 mode. I use X + DWM for my graphical environment, and Pipewire/Wireplumber for audio. From here, in my environment, the game ran without issue on the /MacBook Pro (2006).
If you don't want to keep all the junk you have to install once done playing the game (it's a bit much), you can remove it all like so:
sudo pacman -Rns wine \
rm -rf ~/.wine
October 6, 2023
Last Fall I discovered that our in-window air conditioning unit was about a half an inch taller than its product page claimed, because it didn't fit under the bed frame that I built specifically for that purpose. This year, in order to make sure we could fit the AC under the bed, I built some leg risers for the bed that match the design.
I used the same construction technique as the legs themselves: I cut a bunch of 1" x 1" strips, glued them up into 3" x 1" boards, and then glued those boards together to create a 3" x 3" post. Instead of 15" long posts like the original legs, these were cut into four 1" tall "pucks" that the legs would sit on.
In order to keep the legs from sliding off the pucks, I also made some 4" x 1" boards and the resawed and planed those into something closer to 3.5" x 0.5". Those were then cut down to 1.5" tall and "wrapped" around the puck, creating a lip for the legs to slide into. I added a simple chamfer both to remove sharp edges and for aesthetics, and then sanded them and finished with hemp oil.
September 25, 2023
/stream /bicycle /repair /rad-runner
Last night I went to install a front rack on the /RadRunner Plus and had to reroute my front brake cable. By taking it out, it loosened a frayed part of the cable which then got jammed inside the cable housing, rendering the brake useless. I had never replaced a brake cable before, but a quick search told me it should be pretty straightforward. Today I was able to get a replacement cable from a local bike shop for $3 and swap it out in about 5 minutes.
The special notes were that brake cables are pretty standardized but are different than shifting cables, and that you have to match the "head" of the new brake cable with the one used in the brake lever. I was able to remove (and replace) my cable from the brake lever without tools by just aligning the slots in the barrel adjusters and pulling the cable through. I reused the existing rigid cable housing, and threaded the new cable through it. I was also able to re-use the cable-end cap from the old brake cable by sliding it off with needle-nose pliers, and then crimping it back onto the new cable. Finally, I used those same pliers to cut the new cable to length.
September 15, 2023
/stream /technology /permacomputing /repair /macbook-pro-2006
After coming to the conclusion that GRUB2 was the only way to boot, my only remaining option to get the GPU working on /MacBook Pro (2006) was to go through the process of extracting the firmware from a BIOS boot, and then patching the radeon kernel module to manually load that firmware from a file. I tried for a long time to make a BIOS-bootable USB drive of an old Ubuntu 10 live CD, but the computer refused to boot from it. From what others had written online, it seemed like booting from a DVD was the easiest path forward, so I hunted down a blank DVD and burned that 32bit Ubuntu 10 image to it.
Unfortunately, when trying to boot from the DVD I came to the conclusion that the DVD drive was broken. My /MacBook (2007) easily booted from the DVD, but the /MacBook Pro (2006) did not. My solution: open up both machines, hook up the working drive from the MacBook to the MacBook Pro, boot into Ubuntu and extract the firmware, and put everything back together. To make a long story short: it worked, miraculously. After a long morning of open-heart surgery, I still had two working laptops and a "vbios.bin" file that would be the key to a working GPU.
I spent a little time after the firmware extraction looking into patching the kernel, but didn't make it too far.
September 8, 2023
/stream /technology /permacomputing /repair /macbook-pro-2006
After a bit of a break, I came back to the project of getting the /MacBook Pro (2006) GPU functional in arch linux again. With the time away, I'd had more time to think about what the problem was, and to come up with new approaches. Essentially, I understood that the GPU driver needed to be able to see the GPU firmware, which was only exposed during certain boot conditions. I came to the conclusion that if I could boot directly into an EFISTUB that the firmware would be visible, and so I made it my goal to try and do that.
Unfortunately, the main problem with this machine is that it has two oddities with its EFI: it uses 32bit EFI hardware to boot into a 64bit CPU, and it is also an Apple-specific EFI 1.10 implementation and not a modern UEFI standard implementation. I think I ended up believing that there have been advances in both the linux kernel and also things like systemd-boot that would have overcome the 32bit -> 64bit mismatch, but I kept running into boot errors anyway. My final takeaway is that it was the custom EFI 1.10 implementation that was breaking the boot process due to missing hooks. If you're reading this in the future, I don't think that this machine will ever get any better boot options due to its proprietary and opaque EFI 1.10 implementation, unless someone takes the time to reverse-engineer Apple's implementation.
This means that I'm left relying on GRUB2 and its EFI Handover Protocol method of booting "mixed-mode" on this particular hardware. I also discovered that newer versions of GRUB2 (starting at r566 I believe) have issues with this boot mode, so I ended up pinning grub to an older version (2.04) in pacman and now booting works every time. By adding "reboot=pci" to the kernel parameters, rebooting also works every time, and the laptop never has any strange boot issues. All that's left now is to figure out how to get the GPU firmware loaded manually.
September 5, 2023
The summer has been incredibly busy. My /livable city advocacy group has had a lot of both engagement and disengagement, with city initiatives asking for our input and members being generally unavailable due to summer holidays. It continues to be a difficult line to walk as a volunteer based organization, where nobody is getting paid but success requires people to keep showing up.
Over the course of August, my partner and I stumbled into an opportunity to take over a large commercial space in the center of our Downtown as part of a collective of artists. There is huge potential for the space to be a much needed non-commercial hub of arts and activism, but organizing a bunch of strangers into creating a financially solvent space in such a short time frame is also a difficult task. We're hoping to establish a legal Co-op, and we'll see how it plays out.
Progress on the /coalescent computer moves in small bursts, though my time is increasingly dedicated to scheduling meetings and running agendas for volunteer and activist groups. It's hard to get a concrete feeling of forward movement, but it does generally feel like things are happening. I'd be lying if I didn't mention how frequently I wonder if I shouldn't move out to the country and focus my time on /farming, land stewardship, writing about /philosophy, and /programming, but that feels like giving up and running away.
Finally, we are not in imminent financial danger, but our lack of household income is becoming increasingly difficult to ignore. I have been hoping to serendipitously find a way to generate a bare minimum of income while working on all of these projects towards a better world, but it doesn't seem to be happening. It's frustrating to feel like I need to pause one or more of my many important initiatives so that I can extract money from the economy, but sooner or later something is going to have to give.
I'll try to post smaller and more frequent updates in the future.
September 3, 2023
/stream /collapse /complex-systems
Spent a big chunk of time today writing out my thoughts on /collapse, descent, and contingency, spurred by a couple of posts I saw floating around Merveilles today. While there's a lot written out here now, I'm thinking about how I can better explain some of the intuitions I've developed around the nature of life and complex systems. I have so many long posts written out and unpublished on my philosophical explorations into metaphysics, abstractions, /complex systems, and so on, and I should really get them out into the world in some form.
September 2, 2023
/stream /colophon /programming /linux
After spending a few hours this week trying to build a CLI that replaces my
jnl shell-alias tool and allowed it to publish my website, I spent a few more hours today really thinking about the difference between a shell script and a program binary, and if I wasn't creating unecessary complications. This project of porting a shell script to a Rust binary taught me a lot of things about the nature of the shell as a computing environment, and pushed me to try to keep these tools as shell scripts for now.
I ultimately don't feel like the scripts I have now are the best version of this tool, but I also don't think that the compiled binary I was building was any better... and it was going to take an order of magnitude longer. I'm going to sit in the discomfort of these unfinished tools for a while as I continue to shape the /coalescent computer environment, and at least enjoy the fact that it's much faster to add entries to my website logs now.