2025-05-04 08:00:00
I can't live near friends right now, but I can synthesize some propinquity.
iOS's Find My enables friends/family to track my location in real-time. As somebody who hates notifications and SMS, this tech is godsend. My wife knows which coffee shop I'm at, my friends know exactly how much traffic I'm stuck in, etc.
I sacrifice my own privacy for convenience, but I never expect others to do the same. All my friends/family should feel entitled to privacy. There is no shame in unrequited location sharing.
Unlike read receipts, I do not expect the social norms on location-tracking to change any time soon. Most of the benefits of live location are conferred to the sharer rather than the receiver.
I don't want to bother people whenever I fly from SEA to SFO/LAX/etc. I want friends to know when I land, and I want friends to join my festivities.
You cannot count on others to check your location, nor to be available for your flights/fancies. Deeper relationships demand effort/planning/coordination. This isn't a replacement for real plans -- it's a backup for happy accidents.
Luckily, Find My can also notify them when you're near their 'hood.
This tech becomes extra valuable as you accumulate friends across Earth. You'll find that it's the biggest small world after all, filled with familiar faces in far-away places.
Don't leave serendipity to chance.
2025-05-02 08:00:00
Read my full sad-money mouth emoji proposal and/or submit your own idea.
2025-04-28 08:00:00
2025-04-09 08:00:00
I learned essential etiquette from LimeWire.
When freebooting on the web, people participate in a sort of distributed iterated prisoner's dilemma. Everybody shares bandwidth; everybody risks prosecution.
These conditions naturally create "seeders" and "leechers" -- those who create surplus, and those who exploit that surplus.
You also attract scammers and (angelic) archivists.
Networks are characterized by their incentives. The seeder/leecher distribution is largely determined by risk/reward (e.g. payoff matrices).
One investigation showed that of 123 randomly selected downloaded files, 37 contained malware – about 30%.
-- via Wikipedia
Within a network, individuals exercise discretion; the sum of rational decisions determine the fate of the network. Sometimes these equilibria tend toward tragic commons.
But humans can act irrationally. Some scoundrels pay dearly to reap revenge. Some Good Samaritans sacrifice their lives for others. Game theory only works when people play the game.
Trust lubricates networks; nodes can skip verification to contribute more surplus. You don't need proof-of-work in a high-trust society.
TLS costs more than TCP.
One such verification shortcut is etiquette. When individuals follow certain norms/conventions, they're signaling a willingness to participate a high-trust game.
Pedigree is another shortcut.
I went to see Mrs. B (Rose Blumkin), carrying a 11/4-page purchase proposal for NFM that I had drafted…. Mrs. B accepted my offer without changing a word, and we completed the deal without the involvement of investment bankers or lawyers (an experience that can only be described as heavenly).
-- Warren Buffet, Berkshire Hathaway 2013 Annual Report
My ideal world runs on handshake deals, but unverified agreements invite exploitation. When a pot grows too large, people defect.
Ray Kroc allegedly forsook his handshake deal with the titular McDonald family.
Prior to April 2004, the free version of LimeWire was distributed with a bundled program called LimeShop (a variant of TopMoxie), which was spyware. Among other things, LimeShop monitored online purchases in order to redirect sales commissions to Lime Wire LLC. Uninstallation of LimeWire would not remove LimeShop. These objections were addressed in 2004 with the removal of all bundled software in LimeWire 3.9.4.
-- via Wikipedia
As wolves don sheep's clothing, etiquette evolves new signals. The meta changes. "Networking" events fill with leechers; seeders start secret high-trust clubs.
Reputation is the evergreen shortcut. It is hard to earn, harder to keep, and nearly impossible to salvage.
Reputable BitTorrent archives remain. Consider donating to archive.org, scihub, Anna's Archive, and LibGen.
To earn reputation, (1) act predictably and (2) maximize your seed/leech ratio.
Most real-world games are iterated. Predictable actors are more valuable than unpredictable ones.
Optimizing seed/leech ratio is a wicked problem. Nobody can define what seeding/leeching means for you, nor whether you're succeeding, nor whether it leverages your unique life experience.
Open-source software culture is exemplary. Where can you make the most impact in OSS? Contributing to an existing project or starting a new one? To serve the status-quo or betray it? Solving a few big problems or lots of small problems? Individual contribution or management or governance? DPS, support, or tank?
When seeding your network, you learn how the system really works. By continued good-faith effort, you discover friction and opportunity.
I experienced this phenomenon on this blog. By sharing others' essays online (e.g. HN), I honed a sense of valuable/viral content. By consistently contributing such surplus, I've learned to anticipate specific wants/needs of the network. It's wholesome fun -- promoting friends' blogs and tickling the imagination of the masses.
Like money, you can apply leverage to reputation. By staking time/resources/connections on people, you extend your reputation like a line-of-credit. Each time this cycle succeeds, surplus can be reinvested in your local network.
As surplus grows, people become more tempted to defect. Beware greed; embrace "enough". Prune disreputable acquaintances. Adhere to your principles; continue to pursue others' wants/needs. Establish trustworthy neighbors and help them flourish.
It's difficult to identify/articulate "core" issues, and most polite folks will not advertise their troubles. People appreciate an opening for sincere dialogue: "What are you looking for right now?", "How can I help?", "Need any money for that?", and so on.
Lately, I've been working hard to (1) find "dream" jobs for friends, (2) find capital for friends' startups, and (3) find startups for my friends' funds. It costs me nothing to dramatically improve the lives of my loved ones. Ask friends what they want; go make it happen.
Extend trust; tragic commons are not inevitable. Don't let the leechers win. Flood this world with abundance.
2025-03-28 08:00:00
Loyal bytes toil in memory, on disk, across wires, etc. They crunch our numbers; we cast them to the garbage collector. Et tu, brutus computus.
And so I've been thinking about "compassionate" compilation. How can we learn to love our languages again? How can we reduce our energy footprint? How can we tame the chaos monkeys? How can we reignite the joy of simple software? How can we share our abundance as if recycling air?
Modern web computing looks vaguely like this:
This is barely a map of the happy path. It skips error states, compiler internals, OS, CI, package management, containers, garbage collection, CPU caches, etc. How many allocations--
Nope. It's too much for my sad synapses. I cannot pretend to comprehend the journey that my data take to load a single web app.
Computers are crafted at the nanometer scale; they are the pinnacle of human precision. But software squanders this power. Our precision engines evoke frustration, bugs, and inconsistency -- "did you try turning it off and on again?". Codebases devolve into chimeras of LEGO, Lincoln Logs, cement, popsicle sticks, duct tape -- software cannot succeed like this.
But to wrest LEGO and Lincoln Logs from y'all would be folly. I cannot coerce an entire industry to converge on compatible standards. No, no -- please keep your familiar tools/toys.
Here's my proposal: we choose one "good enough" data layout, and we squeeze it for as much mileage as it can bear. Such a format must encode most popular formats, respect bandwidth, support single-pass execution, allocate sparingly, afford sublinear lookup (for lists/dicts), and remain simple to understand/implement. Good news: our computing forefathers already solved these problems -- we just need to cram them into a single convenient package.
tl;dr flat scraps = bootleg MsgPack + bootleg IPFS + bootleg XSD + bootleg FORTH
Integers, floats, strings, bytes, arrays, maps, variants, types -- any serialization format that encodes these data will do. CBOR and MsgPack are reasonable starting points.
Flat scraps are still in the discovery phase! Meanwhile, check out Max Bernstein's elegant ~100 LOC scrapscript serializer.
Most popular markup/config/data formats (JSON, YAML, XML, CSS, HTML, CSV, Dockerfile, etc.) can be efficiently encoded as CBOR/MsgPack (sketched here as scrapscript types):
()
; csv :
list text
; css :
list css-rule
; css-rule :
| #style { selector : text, declarations : list decl }
| #at { name : text, prelude : text, block : maybe (list decl) }
; css-decl :
{ property : text, value : text, important : bool }
; html :
xml
; xml :
| #text text
| #float float
| #bool bool
| #object (list xml)
| #doctype { name : text, attrs : dict text xml }
| #tag { name : text, attrs : dict text xml, body : xml }
; yaml :
json
; json :
| #null
| #bool bool
| #int int
| #float float
| #text text
| #list (list json)
| #dict (dict text json)
; dockerfile :
{ base : (pair text text)
, instructions : list (
| #from (pair text text)
| #run text
| #copy (pair (list text) text)
| #workdir text
| #env (list (pair text text))
| #expose (list int)
| #volume (list text)
| #user text
| #entrypoint (list text)
| #cmd (list text)
| #comment text
)
}
CSS parsers should live in editors, not browsers. You can still write as much CSS as you want -- just don't send it around as CSS text. Text is floppy. It's hard to cache, hard to compress, hard to parse, hard to validate, etc. Send data structures instead.
By shoving all these data structures into the same serialization format, all software can reap the rewards of common infrastructure: shared compression, shared schema validation, shared optimizations, shared versioning, etc.
Scrapscript (and flat scraps) extend "sharing" further. You can replace any "scrap" of data with its cryptographic hash to reference it and reuse it. For example, we could serialize HTML pages like this:
<html>
<html title="meta" href="scrap://$e9a23cbc455158951716b440c3d165e0"/>
<body>
<html title="header" href="scrap://$099fb995346f31c749f6e40db0f395e3"/>
<main>
<p>hello world</p>
</main>
<html title="footer" href="scrap://$d7eb6b340a11a367a1bec55e4a421d949214759f"/>
</body>
</html>
Suddenly, without any syntax changes, every format acquires the powers of git at the semantic level. Replace any chunk of JSON/CSV/etc with its hash and it can hit a cache on the other side of the wire.
It gets better. We can use scrap maps to name (and version) arbitrary hashes:
<html>
<html href="scrap://taylortown/example/meta"/>
<body>
<html href="scrap://taylortown/example/header"/>
<main>
<p>hello world</p>
</main>
<html href="scrap://taylortown/example/footer"/>
</body>
</html>
But wait -- it gets even better.
Flat scraps have a type system. Imagine succinct JSON Schema, friendly XSD, serializable Haskell, etc. You can reuse all the exact same tools for maximum strictness:
package-json
; package-json :
{ name : text
, version : text
, description : maybe text
, main : maybe text
, types : maybe text
, scripts : dict text text
, repository : maybe { type : maybe text, url : text, directory : maybe text }
, keywords : list text
, author : maybe { name : text, email : maybe text, url : maybe text }
, license : maybe text
, bugs : maybe { url : maybe text, email : maybe text }
, homepage : maybe text
, dependencies : dict text text
, devdependencies : dict text text
, peerdependencies : dict text text
, optionaldependencies : dict text text
, engines : maybe { node : maybe text, npm : maybe text }
, private : maybe bool
, publishconfig : maybe { registry : maybe text, access : maybe text }
, workspaces : maybe (list text)
}
You needn't f*ck around nor find out. You can infer/enforce types at runtime or compile time. You can ensure that all configs and messages are truly compatible.
You may enjoy my talk from UNSOUND '24.
But that's just static data. You can also efficiently encode arbitrary programs this way. Code can be data, too.
By extending CBOR/MsgPack with executable data, we unlock new superpowers: dynamic configs, templating engines, RPCs, client-side codegen, hot reload, Smalltalk-esque images, etc.
Behold the reigning champion of simple computing: FORTH. Stack languages are the simplest means of practical memory/compute. Uxn is exemplary.
Why not WASM? LLVM IR? In short, they're not simple enough for my tastes. I think humans write more code than we can responsibly maintain. In my experience, bloat is the nastiest unsolved problem in software; slow/buggy software is holding us back.
Most people consider reverse-polish notation an eye blight, but computers kinda prefer it over prefix and infix notations.
We might be able to get the best of all worlds by embedding "performance hint" operators: explicit allocations, SIMD, etc.
{ add1 = n -> n + 1 }
-- flat scrap (bytes):
-- { "add1" = expr[var(n) var(n) 1 op(+) op(->)] }
Here's my compromise: flat scraps use RPN; scrapscript reflects them as an infix notation.
While I've been off exploring flat scraps, Max (and friends) have been turning scrapscript into a real high-level programming language with a world-class compiler!
This is the vision I'm working toward with flat scraps:
It looks stupid, because yes -- it's stupid.
Computing can be simpler.
2025-03-17 08:00:00
There are no shortcuts. You cannot build a successful company in five weeks.
But for optimists (and lunatics), five weeks is plenty to start a company.
You probably have a dayjob. Exceed your employer's expectations. Don't accept paychecks you don't deserve. Work on your startup mornings (not evenings) and weekends. Save your PTO until the third week, and then start taking off Mondays/Tuesdays (not Thursdays/Fridays) if needed. If you can no longer maintain stellar quality at work, it's time to move on.
Founders must adopt an investor mindset. If you want to create value, learn how to assess opportunity, how to leverage assets, and how to hedge risk.
It's okay to fundraise and it's okay to bootstrap. Either way, don't let ego rule you. Capital can be a tool like any other.
Investors don't choose startups, they choose founders. They want to multiply their money, and they want you to do it. But you can't just "pivot" a lousy personality. Nobody wants to bet on a billion-dollar idea that's chained to a fool.
If you are worth investment, then invest in yourself.
Good businesses create non-zero-sum wealth. If you sell that wealth for dollars, you can create more wealth to sell.
Outside of theft and burglary, the only way to make money is to convince other people to give you their money.
The main thing is to keep the main thing the main thing.
Create wealth and sell it to customers. You will not succeed if you cannot (1) create wealth, (2) find customers, and (3) sell that wealth.
Don't lose focus. Share your wealth.
Put everything together. Construct an engine that predictably transforms money into wealth, and then wealth into more money.
This is just the beginning. The rules are simple, but the game is grueling:
If you succeed, share that abundance with others. Remember where you're going, remember where you came from, and choose who you're becoming.