bikeshed.coffee

Automation Should Be Like Iron Man, Not Ultron

Another way I’ve heard this put is “build mech suits, not robots.”

Iron Man’s exoskeleton takes the abilities that Tony Stark has and accentuates them. Tony is a smart, strong guy. He can calculate power and trajectory on his own. However, by having his exoskeleton do this for him, he can focus on other things. Of course, if he disagrees or wants to do something the program wasn’t coded to do, he can override the trajectory.

Ultron, on the other hand, was intended to be fully autonomous. It did everything and was, basically, so complex that when it had to be debugged the only choice was (spoiler alert!) to destroy it.

[... more]

Jun 5, 2025, 7:40 AM

hacking excerpts in astro

I wanted to do excerpts to give the main blog page more of a “feed” than a “post list” feeling. Surprisingly there wasn’t a straightforward / built-in way to do it in astro. The markdown => HTML conversion seems to happen as part of loading a post collection, and any downstream methods like render() just reuses that HTML.

When I looked around there were two bits of prior art:

  • The top google result renders the post body with an external library and then truncates the result. I didn’t love this because it seemed error-prone, e.g. it’s easy to truncate through the middle of a codeblock. Using

[... more]

Jun 4, 2025, 11:03 AM

finally setting this thing up

Jun 3, 2025, 12:00 AM

read field reports, ignore speculation

The easiest way to dodge the The Creative World’s Bullshit Industrial Complex in a hot field is to pay attention to case studies and field reports rather than breathless hype and over-generalized speculation.

Field reports are first or second hand accounts of concrete use cases and things actually happened. e.g. “here’s what I ran into when I built X,” “our team tried Y and here’s how it went,” etc.

Speculation may include a grain of reality (or not!) but is usually written by someone on the outside and followed up with baseless conjecture. e.g. “X built Y in 3 days and this is why AI is coming for all our jobs,” “the new oculus is so good soon we will all be living in the metaverse,” etc.

Jan 27, 2025, 12:00 AM

Real Intelligence:

Case of AI usage outside of the “usual” techno-sphere.

artificial intelligence (AI) was now handling some 40% of customer service inquiries and that that number had increased from just 10% in a few short months.

Someone else, listening in on the conversation, asked if his in-house customer service team, seeing this trend, feared for their jobs? But Kevin said no, that they loved the AI because it enabled them to spend more time solving the customer service inquiries that required depth of touch

[... more]

Jan 20, 2025, 12:00 AM

real learning is effortful

Real learning (the kind that sticks) requires active effort and engagement with the material: building a toy project, writing a critical essay, etc. Passive consumption (especially of short form media) should be treated as entertainment more than learning.

The rule of thirds applies here. The valence when e.g. reading the average Twitter post tends to be pretty flat. There are no “tough” sessions of scrolling the feed (or, conversely really “great” sessions), so how much growth is really taking place?

[... more]

Jan 7, 2025, 12:00 AM

rule of thirds

When you’re chasing a big goal, you’re supposed to feel good a third of the time, okay a third of the time, and crappy a third of the time… and if the ratio is roughly in that range, then you’re doing fine.

Source: Bravey, Alexi Pappas

This probably applies to sustainable growth / “productive discomfort” in general. Corollaries: If you’re consistently feeling good, say, >50% of the time, you’re not pushing hard enough to grow. If you’re feeling crappy >50% of the time, you’re pushing too hard to be productive.

[... more]

Jan 7, 2025, 12:00 AM

on shortification of “learning”

Learning is not supposed to be fun. It doesn’t have to be actively not fun either, but the primary feeling should be that of effort. It should look a lot less like that “10 minute full body” workout from your local digital media creator and a lot more like a serious session at the gym. You want the mental equivalent of sweating.

If you are consuming content: are you trying to be entertained or are you trying to learn? And if you are creating content: are you trying to entertain or are you trying to teach? You’ll go down a different path in each case. Attempts to seek the stuff in between actually clamp to zero.

[... more]

Jan 2, 2025, 12:00 AM

readwise + reader api notes

A few weeks back I switched from Raindrop to Readwise for my reading, highlights, and related notes. The main reason for switching was the Kindle integration, but part of my criteria is an API integration where I can automatically collect + archive the data into my personal cloud. It ended up being a bit of a learning curve, so below are notes for anyone who might be interested in doing the same:

The Readwise umbrella has two apps: Readwise and Reader. Readwise focuses on highlights + reviewing highlights, whereas Reader is a web bookmarking + highlighting tool that’s more akin to Raindrop. The APIs are separate, with their own docs + internal concepts:

[... more]

Dec 10, 2024, 12:00 AM

local secrets automation with 1pass

One of the annoying things about running the personal cloud is managing secrets (API keys, google creds, etc) for the bits that run locally on my laptop.

So far I’ve just been shuffling these creds around local-only env files tied to a couple of start scripts. It’s kind of a pain cause the files can’t be shared or committed to GitHub for obvious reasons so I have to walk on glass every time I touch them. And lord help if I accidentally delete one of the files or get them mixed up somehow.

Last week I finally got tired of the nonsense and automated it via 1Pass. Apparently they have a nifty

[... more]

Dec 3, 2024, 12:00 AM

extracting brave browsing history

As part of building my personal cloud, I wanted to back up my browser history. This is useful for info mining and search purposes, but also because Brave (or Chromium?) starts dropping data after 90 days. Who knew. The 90 day limit is hard-coded, so data loss is unavoidable without an export.

So first, the location. On Macs this is ~/Library/Application Support/BraveSoftware/Brave-Browser/[Default || Profile N]/History/brave_history.sqlite.

For chrome, the location is similar ~/Library/Application Support/BraveSoftware/Google/Chrome/[Default || Profile N]/History

[... more]

Nov 19, 2024, 12:00 AM

aspiration-first vs reality-first

Over the years I’ve noticed people seem to have two fundamental orientations towards goals: aspiration-first and reality-first.

Aspiration-first thinking starts with an external or motivational stance. For example: “I need to lose 20 lb before summer to fit into my beach clothes / reach a certain BMI / etc” Or in business: “We need $1MM ARR this year because that’s the benchmark for companies of our stage.” From there, achievement is throwing stuff against the wall till something hits the right trajectory.

[... more]

Oct 15, 2024, 12:00 AM

app-stores-cause-saasification

Yesterday I was editing a photo on my phone when I got hit with a prompt: $3.99/mo for premium features! It really feels like every software company and their mother wants to move to a subscription model these days. From a business standpoint, I get it: recurring revenue brings warm fuzzy feelings and is easier to sell to financiers. But as a customer it’s incredibly annoying when the pricing doesn’t match the value.

In this case, my thoughts ran through some usual tracks: Why should I pay a monthly fee for a photo editing app? They don’t have any server or maintenance costs. All the work is done on my phone, and the photos live on my storage. And it’s not like the software changes that often, only so many things you can do to a photo.

[... more]

Oct 8, 2024, 12:00 AM

growth is just upside risk

Lately we’ve been thinking about fundraising at work. We’ve built a good product and a business with gathering momentum and positive unit economics. Even without a raise we’re likely to be in the black in a reasonable amount of time – knock on wood – or as Silicon Valley likes to say, default alive.

The knee-jerk response for early stage SV-style startups is “of course you should raise, you can grow faster!” But another way to phrase “growth opportunity” is “upside risk,” and once you say “upside risk” the next natural thought is “downside risk.”

[... more]

Aug 6, 2024, 12:00 AM

zero-based

I first saw “zero-based budgeting” in some leisurely weekend reading on private equity firms (I know, party animal comin’ through). The idea is to start each annual budgeting process “from zero” and justify all expenses from scratch instead of anchoring on existing spend. “How much should we spend on X,” instead of “cut 5% off X this year”

This is a useful framework for other contexts:

  • Every day you stay at a job is a decision to take that job, knowing what you know that day.
  • Every day you hold an investment position is a decision to buy on that day’s price and fundamentals.

[... more]

May 24, 2024, 12:00 AM

How to Learn Better in the Digital Age

I see edutainment as preparation for learning: it’s a powerful explorative tool that can provide ideas and motivation to learn. And yet, it’s also not learning itself, in the same way as buying running shoes is not running. Within this framework, “mindless” browsing online can be transformed into scouting for learning opportunities.

The process takes a lot of time and effort, which means it’s not something I can afford to do with every piece of content I find online. Most of the time I trash the links I find, upon further review. Sometimes they end up in my learning wish list.

[... more]

Aug 21, 2023, 12:00 AM

full text search with sqlite

As a part work on an old project, I used sqlite native fts for an MVP full text search. The setup was interesting + ~mostly worked, so it deserves a quick walkthrough.

index + trigger setup

For the this walkthrough, let’s say I have a table bookmarks with a title and a description field. First step is setting up the index:

create virtual table
  fts_bookmarks
using fts5(
  title,
  description,
  content=bookmarks,
  content_rowid=id
);

The content option tells sqlite that this is an external content table

[... more]

Jan 30, 2023, 12:00 AM

tomorrow and tomorrow and tomorrow

Just finished reading Tomorrow, and Tomorrow, and Tomorrow this past week and it’s the best fiction I’ve read in recent memory. Certainly the best realistic-ish fiction I’ve read in years. Whether it’s the close demographic match (Asian immigrant, grew up with the internet, spent a lot of childhood in virtual game worlds…), the fresh variation of style and framing devices, or quippy lines like “To return to the city of one’s birth always felt like retreat,” this one just hit.

It’s not perfect book by any means. But chances are if you’re on this blog and still reading for whatever reason, you’ll probably like it too. In the meantime guess I’m gonna read AJ Fikry just in time for the movie.

[... more]

Oct 9, 2022, 12:00 AM

zsh startup slowness

For a while now I’ve felt like my zsh has been starting up more and more slowly. It’s one of those small annoyances that builds up over time, especially if you pop a lot of shells via e.g. tmux and have to wait more than “One Mississippi” to do anything. This week I finally got annoyed enough to do something about it.

before

Step one is to figure out exactly how slow and why. First I timed the init:

$ time zsh -i -c exit
0.71s user 0.58s system 52% cpu 2.479 total`

… Two and a half seconds?? Ouch.

[... more]

Aug 7, 2022, 12:00 AM

Roam Research impressions

Roam Research is the darling of the latest wave of knowledge management / note-taking apps. I’ve been using it for about two months now. tl;dr - Roam delivers on its promise of networked thought and the features around bidirectional linking are extremely well-executed. However it does still have non-trivial downsides, for example the mobile experience. So I’m not a card-carrying member of the #roamcult just yet but I will continue to use it, at least over the short-to-mid term.

😄

  • The affordances for bidirectional linking are super slick. A link can be created at any time by enclosing it in double brackets, e.g.

[... more]

Dec 10, 2020, 12:00 AM

:label in elixir's IO.inspect

IO.inspect is great for println debugging, and generally “does the right thing” with just about any input you throw at it. Up until recently, I would use it in a way that looked something like this:

IO.puts("debugging pw validation (length)")
validated =
  credential
  |> cast(attrs, [:password])
  |> validate_required([:password])
  |> validate_length(:password, min: 15, max: 1000)
  |> IO.inspect()
  |> validate_complexity(:password)
  |> hash_password()

… which is mostly fine, but the extra IO.puts

[... more]

Dec 5, 2020, 12:00 AM

the compiler is your friend

One sentiment I see from people coming from dynamically typed languages (python, ruby) or even Java and C is a general dismissiveness about static typing and compilers. At best, the sentiment is “Oh, well it makes sure my input is an Int, or a Float, or a Bool… That’s cool I guess, but I can do that with TDD”. At worst, static typing is seen as something to fight against — shackles that limit our creativity and bar us from what we really want to do and the beautiful programs that we could write if only the type-checker got out of our way.

[... more]

May 20, 2016, 12:00 AM

vim % expansion

% (Current File Name)

Another vim tip this week! This time, it’s about ‘%’, which expands to ‘current file name’. This is especially useful in projects with java/scala style directory setups, where your source is approximately 1.5 million folders away from the project root, but you kind of want to hang around project root for things like ant/sbt/etc to work. % makes this easier to work with files in the deeply nested folders while doing this.

Taking a contrived example, instead of doing something like this to

[... more]

Jan 24, 2015, 12:00 AM

thread macro

Let’s talk about clojure for a bit. Or lisps in general, I guess. A lot of the “kinda joking except not really” quips that commonly float around on the internet are about the parentheses, as in how there are so many of them. For example, if you want to take a number x and add one, multiply by two, then add 3, the code might naively look something like this:

(+ (* (+ x 1) 2) 3)

Or perhaps like this:

(+ 3 (* 2 (+ 1 x)))

Look at the parens! Especially the consecutive 3 closing ones in the second variation. For a sufficiently long chain of functions, it can get pretty unreadable—especially with multiple arguments and whatnot.

[... more]

Jan 24, 2015, 12:00 AM