Invoice for my first Mac (2004)
Thanks to a bug in Apple Mail, my Gmail archive likes to revert to sort by ascending date every now and then. Today, I scanned through some of those early emails and stumbled upon this incredible artifact: the e-mail invoice from Apple.com for my first Mac. It was a build-to-order 12" iBook G4 in July 2004.
Besides being set in such carefully-coifed monospace plaintext, the invoice provides an almost hilarious level of detail and verbiage by today's standards. Also, it never gets old to marvel at how much computers have depreciated over time. A whopping $1,362.00 for a mid-tier build of Apple's smallest, cheapest laptop in 2004. That's $2,317.82 in 2025 dollars after inflation. Today, the cheapest laptop Apple.com will sell you is the M4 MacBook Air (in an unusually recommendable configuration), starting at $999.
Big thanks to my dad Fred for spoiling me with a second computer literally one year into college (for which he bought me a Dell in June of 2003), because I was so insistent on switching to the Mac. (I sure was an entitled piece of shit.) I really wish I'd managed to hold onto that thing—a lot of fond memories, looking back.
The full invoice follows:
Apple Computer, Inc. INVOICE RECEIPT
Please remit to:
FOR YOUR RECORDS ONLY
Customer Number Invoice Number
900007 9212467049
Reference Date 07/14/04
Amount Due .00
Please Reference Apple's Invoice Number on Your Remittance
Sold To: Ship To:
Fred Searls Justin Searls
REDACTED REDACTED
TRENTON MI 48183 GRAND RAPIDS MI 49504
USA USA
________________________________________________________________________________
Customer Number Customer P.O. Number Sales Order Number
900007 7346758400 7010461968
Invoice Number Invoice Date Terms
9212467049 07/14/04 Credit Card
________________________________________________________________________________
Item Product Product Total Total Unit Extended
Number Description Ordered Shipped Price Price
________________________________________________________________________________
002 Z0A704KVH IBOOK 12.1/1.GHZ/768/60G/COMB 1 1 1,362.00 1,362.00
Original ordered material was Z0A7
SerialNo.: ( UV42906LR73 )
The unit above contains the following options:
Memory 065-5001 768MB DDR266
Hard Drive 065-5004 60GB ULTRA ATA DRIVE
Optical Drive 065-5006 COMBO DRIVE
Airport 065-5009 Airport Extreme Card
BlueTooth 065-5011 Internal BlueTooth Module
Custom SW I 065-4683 Not Applicable
Keyboard/Mac OS Language 065-5012 Keyboard/Mac OS
________________________________________________________________________________
Subtotal 1,362.00
Tax 81.72
Shipping Charges
TOTAL USD 1,443.72
DO NOT PAY
________________________________________________________________________________
Questions? Call (800) 676-2775 Mon-Fri 8am-9pm, Sat-Sun 9am-6pm CT
________________________________________________________________________________
Salesperson Contact Entry Date Ship Date Routing Waybill Number
BD 07/11/04 07/13/04 FEDERAL EX658584351832
________________________________________________________________________________
Shipped From:
F/G Distribution Center
Elk Grove, Ca 95758
Web Order Number: W8731448
Billed To: Credit Card
________________________________________________________________________________
After Remitting Payment Retain This Portion Of Invoice For Your Records.
Please See Below For Terms And Conditions Pertaining To This Order.
________________________________________________________________________________
Apple Computer, Inc.
________________________________________________________________________________
TERMS & CONDITIONS OF SALE
ORDER STATUS For order status information, you may visit
http://www.apple.com/OrderStatus or navigate to http://store.apple.com/ and click
the "Your Account" button to view the status of your order.
U.S. SALES ONLY The Apple Store sells and ships products only within the
continental United States, Alaska, and Hawaii. No shipments can be outside the
United States. You may not export any products purchased at the Apple Store.
SALES TO END USERS ONLY The Apple Store sells and ships products to end user
customers only.
RETURN & REFUND POLICY If you are not satisfied with your Apple purchase of a
pre-built product, please call 1-800-676-2775 for a Return Material Authorization
(RMA) request within 10 business days of the receipt of the product. If the item
is returned unopened in the original box, we will exchange it or offer you a
refund based on your original method of payment. The product must be returned to
the Apple warehouse within 10 business days of the issuance of the RMA. All
products must be packed in the original, unmarked packaging including any
accessories, manuals, documentation and registration that shipped with the
product. A 10% open box fee will be assessed on any opened hardware or accessory.
If you purchased your order using an Apple Instant Loan or an Apple Business
Lease, you may be asked to provide a major credit card (Visa, MasterCard,
American Express, or Discover) for Apple to assess the 10% open box restocking
fee.
Please note that Apple does not permit the return of or offer refunds for the
following products:
1. Product that is custom configured to your specifications
2. Opened memory
3. Opened software
4. Electronic software downloads
NOTE: Apple recommends that you (1) use a carrier that offers shipment tracking
for all returns and (2) either insure your package for safe return to Apple or
declare the full value of the shipment so that you are completely protected if
the shipment is lost or damaged in transit. If you choose not to (1) use a
carrier that offers tracking and (2) insure or declare the full value of the
product, you will be responsible for any loss or damage to the product during
shipping. Please note that the United States Postal Service (USPS) offers limited
tracking capabilities and that there is a 30-calendar-day waiting period before
the USPS will initiate a trace.
DEFECTIVE ITEMS If you discover what you believe is a product defect for any
Apple-branded product, please contact Apple Care Technical Support at
1-800-APL-CARE (275-2273). Such a defect, if any, is covered under the terms of
your product's warranty. Please refer to the warranty information and other
supporting documentation that came with your product. (See Product Warranty
section below for specific information about Apple's product warranties.)
If you discover what you believe is a product defect for any third-party product,
please contact the manufacturer directly for information regarding the
manufacturer's warranty.
PROOF OF PURCHASE This receipt is your proof of purchase from Apple.
CUSTOM-CONFIGURED PRODUCT We are pleased to offer product that is
custom-configured to your specifications, and we encourage you to review your
order carefully. Since the product is built to your specifications, the order
cannot be changed, modified, or canceled once your order is in production.
SUPPORT PRODUCTS Support products (such as the AppleCare Protection Plan) are
subject to the terms and conditions that accompany those products. By requesting
services under those products or completing and returning to Apple any
accompanying enrollment forms, you agree to the terms and conditions that apply
to those products. Those terms and conditions take precedence over any
inconsistent provisions in these Terms & Conditions of Sale.
SALES TAX Apple Store purchases will include sales tax based on the ship-to
location and the sales tax rate in effect at the time of shipping. If you phone
in your order, the Apple Store sales representative will provide the final dollar
total of your order including tax and any applicable shipping charges at the time
you place your order. If the sales tax rate for the state to which your order is
being shipped changes before the product is shipped, the new tax rate in effect
at the time of shipment will apply. The proof of purchase that Apple mails to you
will include any applicable sales tax.
PRICES The Apple Store endeavors to offer you competitive prices on current
Apple products and selected refurbished and clearance products Your total order
price will include the price of the product (on the day of shipping) plus any
applicable sales tax and shipping charges. Apple reserves the right to change
prices for products displayed at the Apple Store at any time.
Should Apple reduce its price on any shipped product within 10 calendar days of
shipment, you may contact Apple Sales Support at 1-800-676-2775 to request a
refund or credit of the difference between the price you were charged and the
current selling price. To receive the refund or credit you must contact Apple
within 14 business days of shipment.
PRODUCT AVAILABILITY Given the popularity of some products, Apple may restrict
the number of such items that you may purchase. Any product limit restrictions
will be posted on the Apple Store web site. This information is subject to
change.
PRODUCT WARRANTY The sole warranty for Apple-branded product shall be Apple's
standard Limited Warranty as set forth in the documentation that accompanies each
Apple product.
Non-Apple-branded/Third-party products are sold "AS IS" by the Apple Store, but
may be accompanied by their manufacturers' standard warranties. "AS IS" products
are sold by Apple as is, where is, and with all faults, and without express or
implied warranties from Apple. If you have questions about any manufacturers'
warranties that accompany such products, please call 1-800-APL-CARE (275-2273)..
OTHER TERMS AND CONDITIONS
- Apple is not responsible for typographical errors.
- Apple reserves the right to change the terms and conditions of sale at the
Apple Store at any time.
- Title and risk of loss to all products will pass to you on delivery.
- All sales at the Apple Store are governed by California law, without giving
effect to California's conflict of law provisions.
- No Apple employee or agent has the authority to vary any of the Apple Store's
policies or the terms and conditions governing any sale.
- Additional terms and conditions may apply to Education customers purchasing for
personal use. Please refer to the Education Individual sales policies located at:
http://store.apple.com/Catalog/US/Images/salespoliciesEdIndividual.html
02-CONS-05-09-03
TLDR is the best test runner for Claude Code
A couple years ago, Aaron and I had an idea for a satirical test runner that enforced fast feedback by giving up on running your tests after 1.8 seconds. It's called TLDR.
I kept pulling on the thread until TLDR could stand as a viable non-satirical test runner and a legitimate Minitest alternative. Its 1.0 release sported a robust CLI, configurable (and disable-able) timeouts, and a compatibility mode that makes TLDR a drop-in replacement for Minitest in most projects.
Anyway, as I got started working with Claude Code and learned about how hooks work, I realized that a test runner with a built-in concept of a timeout was suddenly a very appealing proposition. To make TLDR a great companion to agentic workflows, I put some work into a new release this weekend that allows you to do this:
tldr --timeout 0.1 --exit-0-on-timeout --exit-2-on-failure
The above command does several interesting things:
- Runs as many tests in random order and in parallel as it can in 100ms
- If some tests don't run inside 100ms, TLDR will exit cleanly (normally a timeout fails with exit code 3)
- If a test fails, the command fails with status code 2 (normally, failures exit code 1)
These three flags add up to a really interesting combination when you configure them as a Claude Code hook:
- A short timeout means you can add TLDR to run as an after-write hook for Claude Code without slowing you or Claude down very much
- By exiting with code 0 on a timeout, Claude Code will happily proceed so long as no tests fail. Because Claude Code tends to edit a lot of files relatively quickly, the hook will trigger many randomized test runs as Claude works—uncovering any broken tests reasonably quickly
- By exiting code 2 on test failures, Claude will—according to the docs—block Claude from proceeding until the tests are fixed
Here's an example Claude Code configuration you can drop into any project that uses TLDR. My .claude/settings.json
file on todo_or_die looks like this:
{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|MultiEdit|Write",
"hooks": [
{
"type": "command",
"command": "bundle exec tldr --timeout 0.1 --exit-0-on-timeout --exit-2-on-failure"
}
]
}
]
}
}
If you maintain a linter or a test runner, you might want to consider exposing configuration for timeouts and exit codes in a similar way. I suspect demand for hook-aware CLI tools will become commonplace soon.
Video of this episode is up on YouTube:
Welcome to the first episode of 🔥Hotfix🔥! Breaking Change's first show-within-a-show, wherein I let somebody else talk for once. Each episode will show up as a patch release in the Breaking Change feed and feature guests with Hot takes about a relevant issue and a clear fix in mind for what we can do about it.
That first guest is a long-time collaborator and top 5 all-time colleague of mine named Dave Mosher, who's here to drop some truth bombs labeled "agentic coding" on the unsuspecting populace.
My secret mission on each of these is to lean into the show's E-for-explicit tag and try to get the guest to say something that could get them fired. I failed this time, but in fairness to me, Dave is Canadian.
We'd love to get your feedback to podcast@searls.co — I'll read it all and flag relevant questions and comments for the next Breaking Change.
You can follow Dave Mosher online at:
A handful of things we mentioned:
Notify your iPhone or Watch when Claude Code finishes
I taught Claude Code a new trick this weekend and thought others might appreciate it.
I have a very bad habit of staring at my computer screen while waiting for it to do stuff. My go-to solution for this is to make the computer do stuff faster, but there's no getting around it: Claude Code insists on taking an excruciating four or five minutes to accomplish a full day's work. Out of the box, claude
rings the terminal bell when it stops out of focus, and that's good enough if you've got other stuff to do on your Mac. But because Claude is so capable running autonomously (that is, if you're brave enough to --dangerously-skip-permissions
), that I wanted to be able to walk away from my Mac while it cooked.
This led me to cobble together this solution that will ping my iPhone and Apple Watch with a push notification whenever Claude needs my attention or runs out of work to do. Be warned: it requires paying for the Pro tier of an app called Pushcut, but anyone willing to pay $200/month for Claude Code can hopefully spare $2 more.
Here's how you can set this up for yourself:
- Install Pushcut to your iPhone and whatever other supported Apple devices you want to be notified on
- Create a new notification in the Notifications tab. I named mine "terminal". The title and text don't matter, because we'll be setting custom parameters each time when we POST to the HTTP webhook
- Copy your webhook secret from Pushcut's Account tab
- Set that webhook secret to an environment variable named
PUSHCUT_WEBHOOK_SECRET
in your~/.profile
or whatever - Save the shell script below
- Use this settings.json to configure Claude Code hooks
Of course, now I have a handy notify_pushcut
executable I can call from any tool to get my attention, not just Claude Code. The script is fairly clever—it won't notify you while your terminal is focused and the display is awake. You'll only get buzzed if the display is asleep or you're in some other app. And if it's ever too much and you want to disable the behavior, just set a NOTIFY_PUSHCUT_SILENT
variable.
The script
I put this file in ~/bin/notify_pushcut
and made it executable with chmod +x ~/bin/notify_pushcut
:
#!/usr/bin/env bash
set -e
# Doesn't source ~/.profile so load env vars ourselves
source ~/icloud-drive/dotfiles/.env
if [ -n "$NOTIFY_PUSHCUT_SILENT" ]; then
exit 0
fi
# Check if argument is provided
if [ $# -eq 0 ]; then
echo "Usage: $0 TITLE [DESCRIPTION]"
exit 1
fi
# Check if PUSHCUT_WEBHOOK_SECRET is set
if [ -z "$PUSHCUT_WEBHOOK_SECRET" ]; then
echo "Error: PUSHCUT_WEBHOOK_SECRET environment variable is not set"
exit 1
fi
# Function to check if Terminal is focused
is_terminal_focused() {
local frontmost_app=$(osascript -e 'tell application "System Events" to get name of first application process whose frontmost is true' 2>/dev/null)
# List of terminal applications to check
local terminal_apps=("Terminal" "iTerm2" "iTerm" "Alacritty" "kitty" "Warp" "Hyper" "WezTerm")
# Check if frontmost app is in the array
for app in "${terminal_apps[@]}"; do
if [[ "$frontmost_app" == "$app" ]]; then
return 0
fi
done
return 1
}
# Function to check if display is sleeping
is_display_sleeping() {
# Check if system is preventing display sleep (which means display is likely on)
local assertions=$(pmset -g assertions 2>/dev/null)
# If we can't get assertions, assume display is awake
if [ -z "$assertions" ]; then
return 1
fi
# Check if UserIsActive is 0 (user not active) and no prevent sleep assertions
if echo "$assertions" | grep -q "UserIsActive.*0" && \
! echo "$assertions" | grep -q "PreventUserIdleDisplaySleep.*1" && \
! echo "$assertions" | grep -q "Prevent sleep while display is on"; then
return 0 # Display is likely sleeping
fi
return 1 # Display is awake
}
# Set title and text
TITLE="$1"
TEXT="${2:-$1}" # If text is not provided, use title as text
# Only send notification if Terminal is NOT focused OR display is sleeping
if ! is_terminal_focused || is_display_sleeping; then
# Send notification to Pushcut - using printf to handle quotes properly
curl -s -X POST "https://api.pushcut.io/$PUSHCUT_WEBHOOK_SECRET/notifications/terminal" \
-H 'Content-Type: application/json' \
-d "$(printf '{"title":"%s","text":"%s"}' "${TITLE//\"/\\\"}" "${TEXT//\"/\\\"}")"
exit 0
fi
Claude hooks configuration
You can configure Claude hooks in ~/.claude/settings.json
:
{
"hooks": {
"Notification": [
{
"hooks": [
{
"type": "command",
"command": "/bin/bash -c 'json=$(cat); message=$(echo \"$json\" | grep -o '\"message\"[[:space:]]*:[[:space:]]*\"[^\"]*\"' | sed 's/.*: *\"\\(.*\\)\"/\\1/'); $HOME/bin/notify_pushcut \"Claude Code\" \"${message:-Notification}\"'"
}
]
}
],
"Stop": [
{
"hooks": [
{
"type": "command",
"command": "$HOME/bin/notify_pushcut \"Claude Code Finished\" \"Claude has completed your task\""
}
]
}
]
}
}

If my blog post about Full-breadth Developers has you the tiniest bit curious about how to get started with coding with AI, read this: addyo.substack.com/p/the-ai-native-software-engineer
Full-breadth Developers
The software industry is at an inflection point unlike anything in its brief history. Generative AI is all anyone can talk about. It has rendered entire product categories obsolete and upended the job market. With any economic change of this magnitude, there are bound to be winners and losers. So far, it sure looks like full-breadth developers—people with both technical and product capabilities—stand to gain as clear winners.
What makes me so sure? Because over the past few months, the engineers I know with a lick of product or business sense have been absolutely scorching through backlogs at a dizzying pace. It may not map to any particular splashy innovation or announcement, but everyone agrees generative coding tools crossed a significant capability threshold recently. It's what led me to write this. In just two days, I've completed two months worth of work on Posse Party.
I did it by providing an exacting vision for the app, by maintaining stringent technical standards, and by letting Claude Code do the rest. If you're able to cram critical thinking, good taste, and strong technical chops into a single brain, these tools hold the potential to unlock incredible productivity. But I don't see how it could scale to multiple people. If you were to split me into two separate humans—Product Justin and Programmer Justin—and ask them to work the same backlog, it would have taken weeks instead of days. The communication cost would simply be too high.
We can't all be winners
When I step back and look around, however, most of the companies and workers I see are currently on track to wind up as losers when all is said and done.
In recent decades, businesses have not only failed to cultivate full-breadth developers, they've trained a generation into believing product and engineering roles should be strictly segregated. To suggest a single person might drive both product design and technical execution would sound absurd to many people. Even for companies who realize inter-disciplinary developers are the new key to success, their outmoded job descriptions and salary bands are failing to recruit and retain them.
There is an urgency to this moment. Up until a few months ago, the best developers played the violin. Today, they play the orchestra.
Google screwed up
I've been obsessed with this issue my entire career, so pardon me if I betray any feelings of schadenfreude as I recount the following story.
I managed to pass a phone screen with Google in 2007 before graduating college. This earned me an all-expense paid trip for an in-person interview at the vaunted Googleplex. I went on to experience complete ego collapse as I utterly flunked their interview process. Among many deeply embarrassing memories of the trip was a group session with a Big Deal Engineer who was introduced as the inventor of BigTable. (Jeff Dean, probably? Unsure.) At some point he said, "one of the great things about Google is that engineering is one career path and product is its own totally separate career path."
I had just paid a premium to study computer science at a liberal arts school and had the audacity to want to use those non-technical skills, so I bristled at this comment. And, being constitutionally unable to keep my mouth shut, I raised my hand to ask, "but what if I play a hybrid class? What if I think it's critical for everyone to engage with both technology and product?"
The dude looked me dead in the eyes and told me I wasn't cut out for Google.
The recruiter broke a long awkward silence by walking us to the cafeteria for lunch. She suggested I try the ice cream sandwiches. I had lost my appetite for some reason.
In the years since, an increasing number of companies around the world have adopted Silicon Valley's trademark dual-ladder career system. Tech people sit over here. Idea guys go over there.
What separates people
Back to winners and losers.
Some have discarded everything they know in favor of an "AI first" workflow. Others decry generative AI as a fleeting boondoggle like crypto. It's caused me to broach the topic with trepidation—as if I were asking someone their politics. I've spent the last few months noodling over why it's so hard to guess how a programmer will feel about AI, because people's reactions seem to cut across roles and skill levels. What factors predict whether someone is an overzealous AI booster or a radicalized AI skeptic?
Then I was reminded of that day at Google. And I realized that developers I know who've embraced AI tend to be more creative, more results-oriented, and have good product taste. Meanwhile, AI dissenters are more likely to code for the sake of coding, expect to be handed crystal-clear requirements, or otherwise want the job to conform to a routine 9-to-5 grind. The former group feels unchained by these tools, whereas the latter group just as often feels threatened by them.
When I take stock of who is thriving and who is struggling right now, a person's willingness to play both sides of the ball has been the best predictor for success.
Role | Engineer | Product | Full-breadth |
---|---|---|---|
Junior | ❌ | ❌ | ✅ |
Senior | ❌ | ❌ | ✅ |
Breaking down the patterns that keep repeating as I talk to people about AI:
-
Junior engineers, as is often remarked, don't have a prayer of sufficiently evaluating the quality of an LLM's work. When the AI hallucinates or makes mistakes, novice programmers are more likely to learn the wrong thing than to spot the error. This would be less of a risk if they had the permission to decelerate to a snail's pace in order to learn everything as they go, but in this climate nobody has the patience. I've heard from a number of senior engineers that the overnight surge in junior developer productivity (as in "lines of code") has brought organization-wide productivity (as in "working software") to a halt—consumed with review and remediation of low-quality AI slop. This is but one factor contributing to the sense that lowering hiring standards was a mistake, so it's no wonder that juniors have been first on the chopping block
-
Senior engineers who earnestly adopt AI tools have no problem learning how to coax LLMs into generating "good enough" code at a much faster pace than they could ever write themselves. So, if they're adopting AI, what's the problem? The issue is that the productivity boon is becoming so great that companies won't need as many senior engineers as they once did. Agents work relentlessly, and tooling is converging on a vision of senior engineers as cattle ranchers, steering entire herds of AI agents. How is a highly-compensated programmer supposed to compete with a stable of agents that can produce an order of magnitude more code at an acceptable level of quality for a fraction of the price?
-
Junior product people are, in my experience, largely unable to translate amorphous real-world problems into well-considered software solutions. And communicating those solutions with the necessary precision to bring those solutions to life? Unlikely. Still, many are having success with app creation platforms that provide the necessary primitives and guardrails. But those tools always have a low capability ceiling (just as with any low-code/no-code platform). Regardless, is this even a role worth hiring? If I wanted mediocre product direction, I'd ask ChatGPT
-
Senior product people are among the most excited I've seen about coding agents—and why shouldn't they be? They're finally free of the tyranny of nerds telling them everything is impossible. And they're building stuff! Reddit is lousy with posts showing off half-baked apps built in half a day. Unfortunately, without routinely inspecting the underlying code, anything larger than a toy app is doomed to collapse under its own weight. The fact LLMs are so agreeable and unwilling to push back often collides with the blue-sky optimism of product people, which can result in each party leading the other in circles of irrational exuberance. Things may change in the future, but for now there's no way to build great software without also understanding how it works
Hybrid-class operators, meanwhile, seem to be having a great time regardless of their skill level or years experience. And that's because what differentiates full-stack developers is less about capability than about mindset. They're results-oriented: they may enjoy coding, but they like getting shit done even more. They're methodical: when they encounter a problem, they experiment and iterate until they arrive at a solution. The best among them are visionaries: they don't wait to be told what to work on, they identify opportunities others don't see, and they dream up software no one else has imagined.
Many are worried the market's rejection of junior developers portends a future in which today's senior engineers age out and there's no one left to replace them. I am less concerned, because less experienced full-breadth developers are navigating this environment extraordinarily well. Not only because they excitedly embraced the latest AI tools, but also because they exhibit the discipline to move slowly, understand, and critically assess the code these tools generate. The truth is computer science majors, apprenticeship programs, and code schools—today, all dead or dying—were never very effective at turning out competent software engineers. Claude Pro may not only be the best educational resource under $20, it may be the best way to learn how to code that's ever existed.
There is still hope
Maybe you've read this far and the message hasn't resonated. Maybe it's triggered fears or worries you've had about AI. Maybe I've put you on the defensive and you think I'm full of shit right now. In any case, whether your organization isn't designed for this new era or you don't yet identify as a full-breadth developer, this section is for you.
Leaders: go hire a good agency
While my goal here is to coin a silly phrase to help us better communicate about the transformation happening around us, we've actually had a word for full-breadth developers all along: consultant.
And not because consultants are geniuses or something. It's because, as I learned when I interviewed at Google, if a full-breadth developer wants to do their best work, they need to exist outside the organization and work on contract. So it's no surprise that some of my favorite full-breadth consultants are among AI's most ambitious adopters. Not because AI is what's trending, but because our disposition is perfectly suited to get the most out of these new tools. We're witnessing their potential to improve how the world builds software firsthand.
When founding our consultancy Test Double in 2011, Todd Kaufman and I told anyone who would listen that our differentiator—our whole thing—was that we were business consultants who could write software. Technology is just a means to an end, and that end (at least if you expect to be paid) is to generate business value. Even as we started winning contracts with VC-backed companies who seemed to have an infinite money spigot, we would never break ground until we understood how our work was going to make or save our clients money. And whenever the numbers didn't add up, we'd push back until the return on investment for hiring Test Double was clear.
So if you're a leader at a company who has been caught unprepared for this new era of software development, my best advice is to hire an agency of full-breadth developers to work alongside your engineers. Use those experiences to encourage your best people to start thinking like they do. Observe them at work and prepare to blow up your job descriptions, interview processes, and career paths. If you want your business to thrive in what is quickly becoming a far more competitive landscape, you may be best off hitting reset on your human organization and starting over. Get smaller, stay flatter, and only add structure after the dust settles and repeatable patterns emerge.
Developers: congrats on your new job
A lot of developers are feeling scared and hopeless about the changes being wrought by all this. Yes, AI is being used as an excuse by executives to lay people off and pad their margins. Yes, how foundation models were trained was unethical and probably also illegal. Yes, hustle bros are running around making bullshit claims. Yes, almost every party involved has a reason to make exaggerated claims about AI.
All of that can be true, and it still doesn't matter. Your job as you knew it is gone.
If you want to keep getting paid, you may have been told to, "move up the value chain." If that sounds ambiguous and unclear, I'll put it more plainly: figure out how your employer makes money and position your ass directly in-between the corporate bank account and your customers' credit card information. The longer the sentence needed to explain how your job makes money for your employer, the further down the value chain you are and the more worried you should be. There's no sugar-coating it: you're probably going to have to push yourself way outside your comfort zone.
Get serious about learning and using these new tools. You will, like me, recoil at first. You will find, if you haven't already, that all these fancy AI tools are really bad at replacing you. That they fuck up constantly. Your new job starts by figuring out how to harness their capabilities anyway. You will gradually learn how to extract something that approximates how you would have done it yourself. Once you get over that hump, the job becomes figuring out how to scale it up. Three weeks ago I was a Cursor skeptic. Today, I'm utterly exhausted working with Claude Code, because I can't write new requirements fast enough to keep up with parallel workers across multiple worktrees.
As for making yourself more valuable to your employer, I'm not telling you to demand a new job overnight. But if you look to your job description as a shield to protect you from work you don't want to do… stop. Make it the new minimum baseline of expectations you place on yourself. Go out of your way to surprise and delight others by taking on as much as you and your AI supercomputer can handle. Do so in the direction of however the business makes its money. Sit down and try to calculate the return on investment of your individual efforts, and don't slow down until that number far exceeds the fully-loaded cost you represent to your employer.
Start living these values in how you show up at work. Nobody is going to appreciate it if you rudely push back on every feature request with, "oh yeah? How's it going to make us money?" But your manager will appreciate your asking how you can make a bigger impact. And they probably wouldn't be mad if you were to document and celebrate the ROI wins you notch along the way. Listen to what the company's leadership identifies as the most pressing challenges facing the business and don't be afraid to volunteer to be part of the solution.
All of this would have been good career advice ten years ago. It's not rocket science, it's just deeply uncomfortable for a lot of people.
Good game, programmers
Part of me is already mourning the end of the previous era. Some topics I spent years blogging, speaking, and building tools around are no longer relevant. Others that I've been harping on for years—obsessively-structured code organization and ruthlessly-consistent design patterns—are suddenly more valuable than ever. I'm still sorting out what's worth holding onto and what I should put back on the shelf.
As a person, I really hate change. I wish things could just settle down and stand still for a while. Alas.
If this post elicited strong feelings, please e-mail me and I will respond. If you find my perspective on this stuff useful, you might enjoy my podcast, Breaking Change. 💜

Everything we learn about Shizuoka just makes us more excited that we chose it as the place to get a condo. Turns out, it's a huge soccer town! Bonus: Fuji-adjacent stadium 🗻⚽️ youtube.com/watch?v=txanTKRQXmI
A handy script for launching editors
Today, I want to share with you a handy edit
script I use to launch my editor countless times each day. It can:
edit posse_party
– will launch my editor with project~/code/searls/posse_party
edit -e vim rails/rails
– will change to the~/code/rails/rails
directory and runvim
edit testdouble/mo[TAB]
– will auto-complete toedit testdouble/mocktail
edit emoruby
– will, if not found locally, clone and open searls/emoruby
This script relies on following the convention of organizing working copies of projects in a GitHub <org>/<repo>
format (under ~/code
by default). I can override this and a few other things with environment variables:
CODE_DIR
- defaults to"$HOME/code"
DEFAULT_ORG
- defaults to"searls"
DEFAULT_EDITOR
- defaults tocursor
(for the moment)
I've been organizing my code like this for 15 years, but over the last year I've found myself bouncing between various AI tools so often that I finally bit the bullet to write a custom meta-launcher.
If you want something like this, you can do it yourself:
- Add the edit executable to a directory on your
PATH
- Make sure
edit
is executable withchmod +x edit
- Download the edit.bash bash completions and put them somewhere
- In .profile or
.bashrc
or whatever, runsource path/to/edit.bash
The rest of this post is basically a longer-form documentation of the script that you're welcome to peruse in lieu of a proper README.
How to subscribe to email newsletters via RSS
I have exactly one inbox for reading blogs and following news, and it's expressly not my e-mail client—it's my feed reader. (Looking for a recommendation? Here are some instructions on setting up NetNewsWire; for once, the best app is also the free and open source one.)
Anyway, with the rise of Substack and the trend for writers to eschew traditional web publishing in favor of e-mail newsletters, more and more publishers want to tangle their content up in your e-mail. Newsletters work because people will see them (so long as they ever check their e-mail…), whereas routinely visiting a web site requires a level of discipline that social media trained out of most people a decade ago.
But, if you're like me, and you want to reserve your e-mail for bidirectional communication with humans and prefer to read news at the time and pace of your choosing, did you know you can convert just about any e-mail newsletter into an RSS feed and follow that instead?
Many of us nerds have known about this for a while, and while various services have tried to monetize the same feature, it's hard to beat Kill the Newsletter: it doesn't require an account to set up and it's totally free.
How to convert an e-mail newsletter into a feed
Suppose you're signed up to the present author's free monthly newsletter, Searls of Wisdom, and you want to start reading it in a feed reader. (Also suppose that I do not already publish an RSS feed alternative, which I do).
Here's what you can do:
-
Visit Kill the Newsletter and enter the human-readable title you want for the newsletter. In this case you might type Searls of Wisdom and and click
Create Feed
. -
This yields two generated strings: an e-mail address and a feed URL
-
Copy the e-mail address (e.g.
1234@kill-the-newsletter.com
) and subscribe to the newsletter via the publisher's web site, just as you would if you were giving them your real e-mail address -
Copy the URL (e.g.
https://kill-the-newsletter.com/feeds/1234.xml
) and subscribe to it in your feed reader, as if it was any normal RSS/Atom feed -
Confirm it's working by checking the feed in your RSS reader. Because this approach simply recasts e-mails into RSS entries, the first thing you see will probably be a welcome message or a confirmation link you'll need to click to verify your subscription
-
Once it's working, if you'd previously subscribed to the newsletter with your personal e-mail address, unsubscribe from it and check it in your feed reader instead
That's it! Subscribing to a newsletter with a bogus-looking address so that a bogus-looking feeds starts spitting out articles is a little counter-intuitive, I admit, but I have faith in you.
(And remember, you don't need to do this for my newsletter, which already offers a feed you can just follow without the extra steps.)
Why is Kill the Newsletter free? How can any of this be sustainable? Nobody knows! Isn't the Internet cool?
Video of this episode is up on YouTube:
I have returned to the nation of freedom and tariffs and all my shit has stopped working! Which shit? Why? What did I buy now? Listen and find out.
Remember, listeners who write in to podcast@searls.co will be spared on judgment day.
Website stuff follows: