Journalist/developer. Storytelling developer @ USA Today Network. Builder of @HomicideWatch. Sinophile for fun. Past: @frontlinepbs @WBUR, @NPR, @NewsHour.
2208 stories
·
45 followers

A Software Library with No Code

1 Share

All You Need is Specs?

Today I’m releasing whenwords, a relative time formatting library that contains no code.

whenwords provides five functions that convert between timestamps and human-readable strings, like turning a UNIX timestamp into “3 hours ago”.

There are many libraries that perform similar functions. But none of them are language agnostic.

whenwords supports Ruby, Python, Rust, Elixir, Swift, PHP, and Bash. I’m sure it works in other languages, too. Those are just the languages I’ve tried and tested.

(I even implemented it as Excel formulas. Though that one requires a bit of work to install.)

But like I said: the whenwords library contains no code. Instead, whenwords contains specs and tests, specifically:

  • SPEC.md: A detailed description of how the library should behave and how it should be implemented.
  • tests.yaml: A list of language-agnostic test cases, defined as input/output pairs, that any implementation must pass.
  • INSTALL.md: Instructions for building whenwords, for you, the human.

The installation instructions are comically simple, just a prompt to paste into Claude, Codex, Cursor, whatever. It’s short enough to print here in its entirety:

Implement the whenwords library in [LANGUAGE].

1. Read SPEC.md for complete behavior specification
2. Parse tests.yaml and generate a test file
3. Implement all five functions: timeago, duration, parse_duration, 
   human_date, date_range
4. Run tests until all pass
5. Place implementation in [LOCATION]

All tests.yaml test cases must pass. See SPEC.md "Testing" section 
for test generation examples.

Pick your language, pick your location, copy, paste, and go.


Okay. This is silly. But the more I play with it, the more questions and thoughts I have.

Recent advancements in coding agents are stunning. Opus 4.5 coupled with Claude Code isn’t perfect, but its ability to implement tightly specified code is uncanny. Models and their harnesses crossed a threshold in Q4, and everyone I know using Opus 4.5 has felt it. There wasn’t a single language where Claude couldn’t implement whenwords in one shot. These capabilities are raising all sorts of questions, especially: “What does software engineering look like when coding is free?”

I’ve chewed on this question a bit, but this “software library without code” is a tangible thought experiment that helped firm up a few questions and thoughts. Specifically:

Do we still need 3rd party code libraries?

There are many utility libraries that aim to perform similar functions, but exist as language-specific implementations. Do we need them all? Or do we need one, tightly defined set of rules which we implement on demand, according to the specific conventions of a given language and project? For libraries that are simple utilities (as opposed to complex frameworks), I think the answer might be, “Yes.”

Now, whenwords is (purposely) a very simple utility. It’s five functions, doesn’t require many dependencies, and depends on a well-defined standard (Unix time). It’s not an expensive operation, a poor implementation probably won’t be a bottleneck, and the written spec is only ~500 lines.

But there’s no reason we couldn’t get more complex. Well defined standards (like those you’d need to implement a browser) can help you tackle complex bits of software relatively quickly. The question is: when does this model make sense and when doesn’t it?

Today, I see 5 reasons why you’d want libraries with code:

1. When Performance Matters

Let’s run with that browser example. There are well-defined, large specs for how to interpret HTML, JS, and CSS. One could push these further and deliver a spec-only browser.

But performance is going to be an issue. I want to open hundreds of tabs and not spring memory leaks. I want rendering to be quick, optimized to within an inch of what’s possible. I want a large group of users going out and encountering strange websites, buggy javascript, bad imports, and more. I want people finding these issues, fixing them, and memorializing them as code.

2. When Testing is Complicated

But Drew, you say, if we find performance issues in the spec-only browser we can just update the spec. That’s true, but testing updates gets complicated fast.

Let’s say you notice whenwords has a bug in its Elixir implementation. To fix the whenwords spec, you add a line to the SPEC.md file to prevent the Elixir bug. You submit a PR request and I’m able to verify it helps Claude build a working Elixir implementation.

But did the change screw up the other variants? Does whenwords still work for Ruby, Python, Bash, and Excel? Does it work for all of them when building with Claude and Codex? What about Qwen? Do we end up with a CI/CD pipeline that builds and tests our spec against 4 coding agents and 20 languages? Or do we just say, “Screw it,” and tell users they’re responsible for whatever code produced?

This isn’t a huge deal for a library with the scope of whenwords, but for anything moderately complex, the amount of surface area we’d want to test grows quickly. whenwords has 125 tests. For comparison, SQLite has 51,445 tests. I’m not building on a spec-only implementation of a database.

3. When You Need to Provide Support & Bug Fixes

Chasing down bugs is harder with spec-only libraries because failures are inconsistent.

Let’s imagine a future where we’re shipping enterprise software as a Claude Skill, or some other similar prepared context that lets agents implement our software for our customers, depending on their environment. This is basically our “software library with no code” taken to an extreme. While there may be benefits here, there are also perils.

Replicating bugs is nearly impossible. If the customer gets stuck on an issue with their own generated codebase, how do we have a hope of finding the problem? Do we just iterate on our spec and add plenty of tests, toss it over to them, and ask them to rebuild the whole thing? Probably not. The models remain probabilistic and as our specs grow the likelihood of our implementations being significantly different grows.

4. When Updates Matter

A library I like is LiteLLM, an AI gateway that provides one interface to call many LLMs across multiple platforms. They add new models quickly, push updates to address connection issues with different platforms, and are generally very responsive.

Other foundational libraries (like nginx, Rails, Postgres) push essential security updates. These are dependencies I wish to maintain. Spec-only libraries, on the other hand, likely work best for implement-and-forget utilities and functions. When continual fixes, support, and security aren’t needed or aren’t valued.

5. When Community & Interoperability Matter

Running through all the points above is community. Lots of users mean more bugs are spotted. More contributors mean more bugs are fixed. Comprehensive testing means PRs are accepted faster. A big community increases the odds someone is available to help. Community support means code is kept up-to-date.

When you want these things, you want community. The code we rely on is not just an instantiation of a spec (a tightly defined set of concepts, aims, and requirements), but the product of people and culture that crystallize around a goal. It’s the magic of open source; why it works and why I love it.

For the job whenwords performs, we don’t need to belong to a club. But for foundations, the things we want to build on, the community is essential because it delivers the points above. Sure, there may be instances of spec-only libraries created and maintained by a vibrant community. But I imagine there will continually be a reference implementation that codifies and ties the spec to the ground.


But the above isn’t fully baked. Our models will get better, our agents more capable. And I’m sure the list above is not exhaustive. I’d enjoy hearing your thoughts on this one, do reach out.


Read the whole story
chrisamico
6 hours ago
reply
Boston, MA
Share this story
Delete

Useful patterns for building HTML tools

1 Share

I've started using the term HTML tools to refer to HTML applications that I've been building which combine HTML, JavaScript, and CSS in a single file and use them to provide useful functionality. I have built over 150 of these in the past two years, almost all of them written by LLMs. This article presents a collection of useful patterns I've discovered along the way.

First, some examples to show the kind of thing I'm talking about:

  • svg-render renders SVG code to downloadable JPEGs or PNGs
  • pypi-changelog lets you generate (and copy to clipboard) diffs between different PyPI package releases.
  • bluesky-thread provides a nested view of a discussion thread on Bluesky.
screenshot of svg-render screenshot of pypi-changelog screenshot of bluesky-thread

These are some of my recent favorites. I have dozens more like this that I use on a regular basis.

You can explore my collection on tools.simonwillison.net - the by month view is useful for browsing the entire collection.

If you want to see the code and prompts, almost all of the examples in this post include a link in their footer to "view source" on GitHub. The GitHub commits usually contain either the prompt itself or a link to the transcript used to create the tool.

The anatomy of an HTML tool

These are the characteristics I have found to be most productive in building tools of this nature:

  1. A single file: inline JavaScript and CSS in a single HTML file means the least hassle in hosting or distributing them, and crucially means you can copy and paste them out of an LLM response.
  2. Avoid React, or anything with a build step. The problem with React is that JSX requires a build step, which makes everything massively less convenient. I prompt "no react" and skip that whole rabbit hole entirely.
  3. Load dependencies from a CDN. The fewer dependencies the better, but if there's a well known library that helps solve a problem I'm happy to load it from CDNjs or jsdelivr or similar.
  4. Keep them small. A few hundred lines means the maintainability of the code doesn't matter too much: any good LLM can read them and understand what they're doing, and rewriting them from scratch with help from an LLM takes just a few minutes.

The end result is a few hundred lines of code that can be cleanly copied and pasted into a GitHub repository.

Prototype with Artifacts or Canvas

The easiest way to build one of these tools is to start in ChatGPT or Claude or Gemini. All three have features where they can write a simple HTML+JavaScript application and show it to you directly.

Claude calls this "Artifacts", ChatGPT and Gemini both call it "Canvas". Claude has the feature enabled by default, ChatGPT and Gemini may require you to toggle it on in their "tools" menus.

Try this prompt in Gemini or ChatGPT:

Build a canvas that lets me paste in JSON and converts it to YAML. No React.

Or this prompt in Claude:

Build an artifact that lets me paste in JSON and converts it to YAML. No React.

I always add "No React" to these prompts, because otherwise they tend to build with React, resulting in a file that is harder to copy and paste out of the LLM and use elsewhere. I find that attempts which use React take longer to display (since they need to run a build step) and are more likely to contain crashing bugs for some reason, especially in ChatGPT.

All three tools have "share" links that provide a URL to the finished application. Examples:

Switch to a coding agent for more complex projects

Coding agents such as Claude Code and Codex CLI have the advantage that they can test the code themselves while they work on it using tools like Playwright. I often upgrade to one of those when I'm working on something more complicated, like my Bluesky thread viewer tool shown above.

I also frequently use asynchronous coding agents like Claude Code for web to make changes to existing tools. I shared a video about that in Building a tool to copy-paste share terminal sessions using Claude Code for web.

Claude Code for web and Codex Cloud run directly against my simonw/tools repo, which means they can publish or upgrade tools via Pull Requests (here are dozens of examples) without me needing to copy and paste anything myself.

Load dependencies from CDNs

Any time I use an additional JavaScript library as part of my tool I like to load it from a CDN.

The three major LLM platforms support specific CDNs as part of their Artifacts or Canvas features, so often if you tell them "Use PDF.js" or similar they'll be able to compose a URL to a CDN that's on their allow-list.

Sometimes you'll need to go and look up the URL on cdnjs or jsDelivr and paste it into the chat.

CDNs like these have been around for long enough that I've grown to trust them, especially for URLs that include the package version.

The alternative to CDNs is to use npm and have a build step for your projects. I find this reduces my productivity at hacking on individual tools and makes it harder to self-host them.

Host them somewhere else

I don't like leaving my HTML tools hosted by the LLM platforms themselves for a couple of reasons. First, LLM platforms tend to run the tools inside a tight sandbox with a lot of restrictions. They're often unable to load data or images from external URLs, and sometimes even features like linking out to other sites are disabled.

The end-user experience often isn't great either. They show warning messages to new users, often take additional time to load and delight in showing promotions for the platform that was used to create the tool.

They're also not as reliable as other forms of static hosting. If ChatGPT or Claude are having an outage I'd like to still be able to access the tools I've created in the past.

Being able to easily self-host is the main reason I like insisting on "no React" and using CDNs for dependencies - the absence of a build step makes hosting tools elsewhere a simple case of copying and pasting them out to some other provider.

My preferred provider here is GitHub Pages because I can paste a block of HTML into a file on github.com and have it hosted on a permanent URL a few seconds later. Most of my tools end up in my simonw/tools repository which is configured to serve static files at tools.simonwillison.net.

Take advantage of copy and paste

One of the most useful input/output mechanisms for HTML tools comes in the form of copy and paste.

I frequently build tools that accept pasted content, transform it in some way and let the user copy it back to their clipboard to paste somewhere else.

Copy and paste on mobile phones is fiddly, so I frequently include "Copy to clipboard" buttons that populate the clipboard with a single touch.

Most operating system clipboards can carry multiple formats of the same copied data. That's why you can paste content from a word processor in a way that preserves formatting, but if you paste the same thing into a text editor you'll get the content with formatting stripped.

These rich copy operations are available in JavaScript paste events as well, which opens up all sorts of opportunities for HTML tools.

  • hacker-news-thread-export lets you paste in a URL to a Hacker News thread and gives you a copyable condensed version of the entire thread, suitable for pasting into an LLM to get a useful summary.
  • paste-rich-text lets you copy from a page and paste to get the HTML - particularly useful on mobile where view-source isn't available.
  • alt-text-extractor lets you paste in images and then copy out their alt text.
screenshot of hacker-news-thread-export screenshot of paste-rich-text screenshot of alt-text-extractor

Build debugging tools

The key to building interesting HTML tools is understanding what's possible. Building custom debugging tools is a great way to explore these options.

clipboard-viewer is one of my most useful. You can paste anything into it (text, rich text, images, files) and it will loop through and show you every type of paste data that's available on the clipboard.

Clipboard Format Viewer. Paste anywhere on the page (Ctrl+V or Cmd+V). This shows text/rtf with a bunch of weird code, text/plain with some pasted HTML diff and a Clipboard Event Information panel that says Event type: paste, Formats available: text/rtf, text/plain, 0 files reported and 2 clipboard items reported.

This was key to building many of my other tools, because it showed me the invisible data that I could use to bootstrap other interesting pieces of functionality.

More debugging examples:

  • keyboard-debug shows the keys (and KeyCode values) currently being held down.
  • cors-fetch reveals if a URL can be accessed via CORS.
  • exif displays EXIF data for a selected photo.
screenshot of keyboard-debug screenshot of cors-fetch screenshot of exif

Persist state in the URL

HTML tools may not have access to server-side databases for storage but it turns out you can store a lot of state directly in the URL.

I like this for tools I may want to bookmark or share with other people.

  • icon-editor is a custom 24x24 icon editor I built to help hack on icons for the GitHub Universe badge. It persists your in-progress icon design in the URL so you can easily bookmark and share it.

Use localStorage for secrets or larger state

The localStorage browser API lets HTML tools store data persistently on the user's device, without exposing that data to the server.

I use this for larger pieces of state that don't fit comfortably in a URL, or for secrets like API keys which I really don't want anywhere near my server - even static hosts might have server logs that are outside of my influence.

  • word-counter is a simple tool I built to help me write to specific word counts, for things like conference abstract submissions. It uses localStorage to save as you type, so your work isn't lost if you accidentally close the tab.
  • render-markdown uses the same trick - I sometimes use this one to craft blog posts and I don't want to lose them.
  • haiku is one of a number of LLM demos I've built that request an API key from the user (via the prompt() function) and then store that in localStorage. This one uses Claude Haiku to write haikus about what it can see through the user's webcam.
screenshot of word-counter screenshot of render-markdown screenshot of haiku

Collect CORS-enabled APIs

CORS stands for Cross-origin resource sharing. It's a relatively low-level detail which controls if JavaScript running on one site is able to fetch data from APIs hosted on other domains.

APIs that provide open CORS headers are a goldmine for HTML tools. It's worth building a collection of these over time.

Here are some I like:

  • iNaturalist for fetching sightings of animals, including URLs to photos
  • PyPI for fetching details of Python packages
  • GitHub because anything in a public repository in GitHub has a CORS-enabled anonymous API for fetching that content from the raw.githubusercontent.com domain, which is behind a caching CDN so you don't need to worry too much about rate limits or feel guilty about adding load to their infrastructure.
  • Bluesky for all sorts of operations
  • Mastodon has generous CORS policies too, as used by applications like phanpy.social

GitHub Gists are a personal favorite here, because they let you build apps that can persist state to a permanent Gist through making a cross-origin API call.

  • species-observation-map uses iNaturalist to show a map of recent sightings of a particular species.
  • zip-wheel-explorer fetches a .whl file for a Python package from PyPI, unzips it (in browser memory) and lets you navigate the files.
  • github-issue-to-markdown fetches issue details and comments from the GitHub API (including expanding any permanent code links) and turns them into copyable Markdown.
  • terminal-to-html can optionally save the user's converted terminal session to a Gist.
  • bluesky-quote-finder displays quotes of a specified Bluesky post, which can then be sorted by likes or by time.
screenshot of species-observation-map screenshot of zip-wheel-explorer screenshot of github-issue-to-markdown screenshot of terminal-to-html screenshot of bluesky-quote-finder

LLMs can be called directly via CORS

All three of OpenAI, Anthropic and Gemini offer JSON APIs that can be accessed via CORS directly from HTML tools.

Unfortunately you still need an API key, and if you bake that key into your visible HTML anyone can steal it and use to rack up charges on your account.

I use the localStorage secrets pattern to store API keys for these services. This sucks from a user experience perspective - telling users to go and create an API key and paste it into a tool is a lot of friction - but it does work.

Some examples:

screenshot of haiku screenshot of openai-audio-output screenshot of gemini-bbox

Don't be afraid of opening files

You don't need to upload a file to a server in order to make use of the <input type="file"> element. JavaScript can access the content of that file directly, which opens up a wealth of opportunities for useful functionality.

Some examples:

  • ocr is the first tool I built for my collection, described in Running OCR against PDFs and images directly in your browser. It uses PDF.js and Tesseract.js to allow users to open a PDF in their browser which it then converts to an image-per-page and runs through OCR.
  • social-media-cropper lets you open (or paste in) an existing image and then crop it to common dimensions needed for different social media platforms - 2:1 for Twitter and LinkedIn, 1.4:1 for Substack etc.
  • ffmpeg-crop lets you open and preview a video file in your browser, drag a crop box within it and then copy out the ffmpeg command needed to produce a cropped copy on your own machine.
screenshot of ocr screenshot of social-media-cropper screenshot of ffmpeg-crop

You can offer downloadable files too

An HTML tool can generate a file for download without needing help from a server.

The JavaScript library ecosystem has a huge range of packages for generating files in all kinds of useful formats.

screenshot of svg-render screenshot of social-media-cropper screenshot of open-sauce-2025

Pyodide can run Python code in the browser

Pyodide is a distribution of Python that's compiled to WebAssembly and designed to run directly in browsers. It's an engineering marvel and one of the most underrated corners of the Python world.

It also cleanly loads from a CDN, which means there's no reason not to use it in HTML tools!

Even better, the Pyodide project includes micropip - a mechanism that can load extra pure-Python packages from PyPI via CORS.

screenshot of pyodide-bar-chart screenshot of numpy-pyodide-lab screenshot of apsw-query

WebAssembly opens more possibilities

Pyodide is possible thanks to WebAssembly. WebAssembly means that a vast collection of software originally written in other languages can now be loaded in HTML tools as well.

Squoosh.app was the first example I saw that convinced me of the power of this pattern - it makes several best-in-class image compression libraries available directly in the browser.

I've used WebAssembly for a few of my own tools:

screenshot of ocr screenshot of sloccount screenshot of micropython

Remix your previous tools

The biggest advantage of having a single public collection of 100+ tools is that it's easy for my LLM assistants to recombine them in interesting ways.

Sometimes I'll copy and paste a previous tool into the context, but when I'm working with a coding agent I can reference them by name - or tell the agent to search for relevant examples before it starts work.

The source code of any working tool doubles as clear documentation of how something can be done, including patterns for using editing libraries. An LLM with one or two existing tools in their context is much more likely to produce working code.

I built pypi-changelog by telling Claude Code:

Look at the pypi package explorer tool

And then, after it had found and read the source code for zip-wheel-explorer:

Build a new tool pypi-changelog.html which uses the PyPI API to get the wheel URLs of all available versions of a package, then it displays them in a list where each pair has a "Show changes" clickable in between them - clicking on that fetches the full contents of the wheels and displays a nicely rendered diff representing the difference between the two, as close to a standard diff format as you can get with JS libraries from CDNs, and when that is displayed there is a "Copy" button which copies that diff to the clipboard

Here's the full transcript.

See Running OCR against PDFs and images directly in your browser for another detailed example of remixing tools to create something new.

Record the prompt and transcript

I like keeping (and publishing) records of everything I do with LLMs, to help me grow my skills at using them over time.

For HTML tools I built by chatting with an LLM platform directly I use the "share" feature for those platforms.

For Claude Code or Codex CLI or other coding agents I copy and paste the full transcript from the terminal into my terminal-to-html tool and share that using a Gist.

In either case I include links to those transcripts in the commit message when I save the finished tool to my repository. You can see those in my tools.simonwillison.net colophon.

Go forth and build

I've had so much fun exploring the capabilities of LLMs in this way over the past year and a half, and building tools in this way has been invaluable in helping me understand both the potential for building tools with HTML and the capabilities of the LLMs that I'm building them with.

If you're interested in starting your own collection I highly recommend it! All you need to get started is a free GitHub repository with GitHub Pages enabled (Settings -> Pages -> Source -> Deploy from a branch -> main) and you can start copying in .html pages generated in whatever manner you like.

Bonus transcript: Here's how I used Claude Code and shot-scraper to add the screenshots to this post.

You are only seeing the long-form articles from my blog. Subscribe to /atom/everything/ to get all of my posts, or take a look at my other subscription options.

Read the whole story
chrisamico
4 days ago
reply
Boston, MA
Share this story
Delete

All the Claude (Code) Things

1 Share

Of nearly all of the potential uses for Large Language Models, perhaps the best and most defensible is using them to write code. During the recently-completed fall semester, I co-taught a Computer Science class with Bill Pugh that explored some good ways to do that. We used a lot of Claude Code for that class, and it quickly has become my favorite coding model. And then, in the middle of November, the folks at Anthropic released Claude Code on the Web and gave paid users free credits to use it. I got $250 worth, and I had a lot of ideas.

I didn’t use all of the $250 in credits, but I made it to about $25. I had Claude Code revive a few very old (10+ years) projects, make significant progress on some long-stalled codebases and put the finishing touches on complex problems. There were the now-familiar moments when the model got caught in unproductive loops, as well as over-engineered approaches to simpler tasks. But on the whole, a couple of weeks of Claude Code on the web proved very useful. Here’s some of what I had Claude Code do.

Simple Apps

One of the sweet spots for coding models are simple HTML/CSS/JS applications - often deployed on GitHub Pages - based on some data you’ve got in a repository. I have a lot of data sitting around in repositories, so I had Claude Code make some apps, because not everyone wants to look at a CSV file.

  • Maryland Women’s Basketball Data. I’ve been collecting and storing JSON files with game-level information from women’s college basketball for a few years now. But few people want to look at JSON files in a browser, so this was a great candidate for a simple web app. This one took a number of attempts at refinement, and I needed to get specific with Claude Code about some of the things I wanted, especially the details of each game. But I also asked for an assist network analysis without providing any other instructions, and what I got is pretty great. It updates every day via GitHub Actions.
  • Post Ping. I’ve been collecting SMS alerts from the Washington Post since March 2024, and here is the entirety of my instructions: “Create a slightly whimsical webpage that presents the alert data in several ways: a quick look at the alerts from the previous 24 hours, a searchable filter on title, another on target topic. Have a line chart showing the trend of alerts and title the page “Post Ping”. Use JS CSS HTML.” I think we can all agree that the font is perhaps too “whimsical”, but Claude Code did everything I asked for and produced a site I actually look at.
  • Frederick County Fire & Rescue Incidents. Working with a Maryland newspaper,I wrote a scraper to track emergency response incidents and provide them as an RSS feed reporters could subscribe to. That wasn’t really effective, but this simple searchable and browsable database that Claude Code built was more useful.
  • UMPD Logs. A former student, Rachel Marconi, originally built this app for my news apps class, and I had Claude add some visual upgrades and some topline summary data with minimal effort.
  • Hattiesburg (Miss.) Public Notices. For a presentation at a conference on local news hosted at Southern Miss, I had Claude Code build an app that allows users to comb through public notices from the Hattiesburg American, using an LLM to provide a newsworthiness value to each announcement.
  • WV Football Game Viewer. For a 2023 Mountain State Spotlight story on transfers in West Virginia high school football, I scraped game scores to measure blowouts. Claude Code took that data and made a simple website of it.

Command-Line Utilities & Scrapers

Building pipelines for data is a big part of my work (and teaching), and mostly that has meant writing single Python scripts do do the work of obtaining and transforming data. This set of Claude Code work led to more robust and predictable CLI tools.

  • Testudo. I picked up the original code for this project, which scrapes Maryland’s Schedule of Classes site, from Ed Summers. It was good code, but it also had some constraints: users could only scrape all of the classes for a given term, producing JSON files and a single CSV file with the combined data. Using Claude Code, I added a bunch of features, including optional scraping for syllabi. Plus tests and better documentation. It is a much better-organized and more reliable piece of software now.
  • python-statement. Years ago, I extracted a Ruby gem that scraped press releases from the congressional news app I worked on at The New York Times. It was super useful but became a pain to maintain, and I haven’t written much Ruby in the past five years. So I had Claude Code port it to Python, where I hope to keep it going with some student help. Translating code from one language to another is very much in an LLM’s wheelhouse, although it was interesting and somewhat disappointing that given hundreds of methods, Claude literally gave up, coming up with lines such as “# … and more methods here”. These coding assistants really are like disinterested interns some times, but I would not have done this myself.
  • College Sports Rosters. For a few years I’ve maintained scrapers to extract player information from official collegiate roster sites for women’s basketball and volleyball. I based the latter code on the former, but that involved a lot of work and maintenance was an issue, making expanding to other sports an unappealing prospect. Claude Code changed that, not only producing very serviceable code for men’s and women’s soccer, lacrosse and women’s field hockey, but also creating common utilities shared across repositories. And it cleaned up and reorganized the original women’s basketball scraper code, making it much easier to work with.
  • Foreign Gifts to U.S. Officials. I first built this repo to show off the ability of LLMs to parse weirdly-structured PDFs, and my code was kind of a mess. Claude Code polished it up and reorganized the files, adding a CLI and a way to visualize the data. Improving or extending existing codebases is a pretty solid use case for these coding assistants.

Resurrected Apps

I’ll do a follow-up post on this category, because it is the most ambitious use case I could imagine: taking a code base that is large, old and unmaintained and bringing it back to life. I pointed Claude Code at several of these, including official Senate disbursements (one of the white whales of the open government movement), a Django app to download and parse IRS campaign finance filings and even Fumblerooski, the first Django app I ever made. Oh, and a still-private repo containing the codebase of Capitol Words, a former Sunlight Foundation joint that ProPublica briefly took over and tried to resurrect.

Why a separate post on these? Because unlike the other projects mentioned above, these are substantial and complicated codebases. I’ll need some time to dig into them and assess the changes. I’m sure some of them will be incomplete or screwed up in some way - I didn’t give many instructions aside from “update the code so it runs now” and tried to simplify things where I could. The results - as with most things generated by AI - sound impressive, but the devil’s in the details.

The Takeaway

Properly guided by users who know what they are doing, these coding assistants can be super useful. They certain can make quick work of what my friend and colleague Matt Waite calls the “throwaway news app”, a simple HTML/JS/CSS site that can make data and information accessible. That alone is a huge benefit, if newsrooms are smart about how they do it. The way I employed Claude Code during that mid-November stretch wasn’t ideal; a deadline often means things get left behind or neglected. But since then, I’ve made good use of Claude Code and a few other assistants, especially in writing tests, documentation and helping me draft plans for upgrades. Although these tools are designed for coding, you can throw other tasks at them, which sometimes is an improvement over a chat interface since they can use tools to help them understand and operate on files. I often use Claude Code to help me understand an unfamiliar code base, for example.

The other lesson I’ve learned is that these models write code quickly, and that’s often not a great thing. But you can slow them down, both through direct instruction and via what I call “constitutional” documents like Claude.md that contain basic operational principles: do X this way, wait for confirmation before doing Y, etc. The “magic” of these assistants is that they seem like they can drive the bus. But you’re the one who should be behind the wheel.

Read the whole story
chrisamico
4 days ago
reply
Boston, MA
Share this story
Delete

How musicals use motifs to tell stories

1 Share

to this line from the musical Wicked.

Or click anywhere to begin

This same melody repeats three times during the show, each at a pivotal moment for the main character, Elphaba.

🎧 Click play and see if you can hear how the melody is the same in each clip.

A chart with time on the x-axis depicting the occurence of the “unlimited” motif in wicked.

This sort of thing happens in lots of art forms, from film scores to standup sets. Depending on the medium, you might call it a theme or a callback. In music, the word motif describes a short, distinctive musical idea that recurs in a salient way.

Here are all of the motifs in Wicked.

A chart with time on the x-axis depicting the occurence of 6 total motifs in wicked.

Musicals put motifs on display in a unique way.

Music is always telling a story, but here that is quite literal. This is especially true in musicals like Les Misérables or Hamilton where the entire story is told through song, with little to no dialogue. These musicals rely on motifs to create structure and meaning, to help tell the story.

A chart with time on the x-axis depicting the occurence of 47 total motifs in lesmis.

Musicals like these are an excellent ground for observing the power and function of motifs – what exactly are they doing for the stories they are a part of? Let’s break that down, using examples from these sung-through musicals, but with patterns you’ll also spot across film, TV, and beyond.

Common Threads

Composers have been using repetition for forever. Think Beethoven’s Symphony No. 5, where repeats and reappears throughout the piece.

In the 19th century, German composers started formalizing the idea of attaching a motif to a person, place, or idea within a story (these are called leitmotifs). Think , where different instruments and melodies represent different animals in the woods. Or the theme in , which captures the idea of Carl and Ellie’s shared life together.

So a motif doesn’t just exist, it represents something.

This creates a musical storytelling shortcut: when the audience hears a motif, that something is evoked. The audience can feel this information even if they can’t consciously perceive how it’s being delivered.

Carl and Ellie from Pixar’s Up, waving out at the crowd as they get married

In the first four minutes of Pixar’s Up, a melodic motif carries the emotional weight of the story, all without any dialogue.

This technique has been embraced in many mediums — from opera to video game music to modern musical theater.

Let’s look at some examples of story and emotional information being conveyed through musical motifs.

Representing a character

One of the most straightforward uses of a motif is to represent a character in the story. These motifs can help cue the audience that a character is present, like or someone from the in Avatar the Last Airbender. A change in the motif’s instrumentation or tone can signal a change in that character.

A chart with time on the x-axis depicting the occurence of 4 character motifs in lesmis.

In Hamilton, there are often literal introductions of characters to a consistent melody or rhythm.

A chart with time on the x-axis depicting the occurence of 5 character motifs in hamilton.

Representing an idea

More often, motifs are a marker for something more abstract – love, heartbreak, adventure – and not always owned by a specific character. Like this Star Wars theme that embodies the concept of , calling in ideas around destiny, hope, the struggle between good and evil.

A chart with time on the x-axis depicting the occurence of 4 idea motifs in lesmis.

Creating emotional layers

Why does that scene from Up make everyone cry? It establishes a simple melodic that comes to represent Carl & Ellie’s adventure together. But the real emotional weight comes from the fact that we hear it both in moments of joy and in moments of loss and heartbreak, each appearance carrying the previous memories with it. We feel the weight of the past layered onto the present moment, which makes it hit even harder.

The following motifs repeat, but with drastically different emotions across the show.

A chart with time on the x-axis depicting the occurence of 4 motifs with emotional changes in lesmis.
A chart with time on the x-axis depicting the occurence of 2 motifs with emotional changes in hamilton.

Weaving everything together

Both Les Misérables and Hamilton have a song at the end of the first act where many of the motifs introduced so far all come together. The audience is reminded of everything we’ve learned and seen so far, and the most important threads of the story collide and are woven together.

A chart with time on the x-axis depicting the occurence of 6 motifs from one day more in lesmis.
A chart with time on the x-axis depicting the occurence of 12 motifs from non-stop in hamilton.

There’s something else hidden within that “Unlimited” motif from Wicked. It’s actually the same notes as “Somewhere Over The Rainbow”, a nod to the musical’s original source material.

A piano diagram showing that the first four notes of the Unlimited theme and Somewhere Over The Rainbow are the same.

From Wicked

From The Wizard of Oz

Across generations, these pieces speak to each other — the threads connect. From the subtle to the more overt, connections like these shape how we feel and what sticks with us.

Most of us don’t consciously notice this force at work in the moment. Luckily, we don’t have to understand it to feel it.

Explore all the motifs we found in Hamilton, Les Misérables, and Wicked.

hamilton playbill program A chart with time on the x-axis depicting the occurence of 35 motifs in hamilton.

🤷‍♂️ how does a

Sung by Aaron Burr, narrating and introducing a new part of the story.

💰 alexander hamilton

The main guy!

🤩 just you wait

Hamilton proving himself is a big theme throughout the musical.

🎩 aaron burr sir

An exchange, usually between Burr and Hamilton.

🤫 talk less

A piece of advice Burr gives Hamilton (which he ignores), that demonstrates the difference between them.

🏀 my shot

One of Hamilton's main motifs.

💭 i imagine death

Hamilton contemplating his mortality and legacy.

🍻 raise a glass

Like the motif in Les Misérables, this theme captures the camaraderie and idealism of young revolutionaries.

📜 angelica

Each Schyuler sister gets their own name motif.

🕯️ eliza

Each Schyuler sister gets their own name motif.

👩‍👧‍👦 schuyler sisters

This one comes back very subtly in Act 2.

😎 summer in the city

“Someone in a rush” changes to “someone under stress” later on.

👀 look around

This motif repeats lyrically in “Non-Stop” and melodically in “Schuyler Defeated.”

🇬🇧 you'll be back

These 3 songs, all sung by King George, are basically identical and musically distinct from the rest of the show.

😍 helpless

Eliza sings this motif as she falls head over heels for Hamilton.

⏳ flashback

“Satisfied” is a flashback of “Helpless,” and this motif helps place us in time as we experience the same events from a different angle.

💞 my sister

Angelica demonstrating her sisterly love for Eliza.

👍🏽 satisfied

This motif was borrowed from a letter from Angelica to Hamilton, where she writes: “You are happy my dear friend to find consolation in ‘words and thoughts.’ I cannot be so easily satisfied.”

💀 doesn't discriminate

Burr contemplating two forces that are beyond his control, love and death.

🛑 wait for it

Burr's main motif, representing his cautious, measured approach to life.

9️⃣ counting

This count is usually used in the context of a duel, but also in “Take a Break” for Phillip's piano lesson (some sad foreshadowing).

📏 duel rules

These two songs are basically identical.

🔫 aim no higher

The final rule, which recurs for each of the three duels in the show.

🥺 that would be enough

One of Eliza's main motifs, representing her love and devotion to Hamilton and their family.

🥺 that would be enough B

The second section of Eliza’s motif.

👨‍✈️ asking me to lead

Washington's motif representing duty and leadership.

🗺️ history has its eyes

One of the core messages of the show, this motif represents the weight of legacy.

🤍 who tells your story

These are the final words we hear in the show.

⏰ running out of time

This motif is sung by other people about Hamilton and his relentless sense of urgency.

😇 phillip rap

Phillip performs this rap for his parents as a 9-year old, and then again to himself when he's grown up, and feeling nervous before a duel.

📝 room where it happens

Burr feels left out, even though his passiveness has put him there.

😏 on your side

Hamilton seems to be Washington’s favorite, and Burr, Jefferson, and Madison jealously sing about it.

⚖️ equal opposite

One of Jefferson’s only motifs!

✌🏽 say goodbye

Washington’s goodbye echoes in Hamilton’s final words.

💔 quiet uptown

Hamilton calls back to the previous song about grieving the loss of his son while everyone around him in “The Election of 1800” is focused on politics.

Notes

This piece focuses on melodic motifs that are sung, leaving out those occurring just in the orchestra (which are plentiful, just harder to capture reliably). I drew the line there because these are the easiest to hear and recognize. To qualify, a motif must recur at least twice across multiple songs. Each chart shows one instance of each motif per song, though many reappear several times within a single song.

To detect the motifs, I listened to these musicals a bunch of times, and noted occurrences by hand, while consulting some outside sources.

Hear a motif that we missed? Reach out at michelle@pudding.cool.

Read the whole story
chrisamico
4 days ago
reply
Boston, MA
Share this story
Delete

Researchers Are Hunting America for Hidden Datacenters

1 Share

Advertisement

The nonprofit research group Epoch AI is tracking the physical imprint of the technology that’s changing the world.

Researchers Are Hunting America for Hidden Datacenters Google Earth image highlighted by Epoch AI.
Read the whole story
chrisamico
8 days ago
reply
Boston, MA
Share this story
Delete

The Double Life of Thomas Goldstein, a Supreme Court Lawyer

1 Share
Credit...Jonno Rattman for The New York Times

Thomas Goldstein was a superstar in the legal world. He was also a secret high-stakes gambler, whose wild 10-year run may now land him in prison.

Credit...Jonno Rattman for The New York Times

The high point of Thomas Goldstein’s career as a Supreme Court advocate took place a few minutes after 10 on the morning of Oct. 7, 2020. Goldstein had just begun his argument before the justices on behalf of Google in an immensely complicated, but highly significant, copyright dispute with Oracle. The controversy arose when Google, in developing its Android operating system for smartphones, used about 11,500 lines of computer code from Oracle’s Java SE, a platform that allows developers to write programs that can run on various devices. In a lower court, Oracle won a judgment that Google’s use of the code violated Oracle’s copyright. Google was facing $9 billion in damages.

Before Goldstein appeared in front of the court, he had focused on one main point in his written brief: Oracle’s platform was simply not copyrightable, so Google could not have committed infringement. But after hearing the first few questions from the justices, Goldstein made a sharp pivot — and took a big gamble. Even if Oracle possessed a valid copyright in Java SE, he argued, Google had made “fair use” of the platform, which was a distinctly subsidiary point in his brief. “Fair use” of copyrighted material is not infringement.

Goldstein’s shift was so dramatic that even the justices took note of it. “Mr. Goldstein,” Justice Neil M. Gorsuch said, “if I understand the conversation so far, you are moving past, rather rapidly, the primary argument in your brief that the code just simply isn’t copyrightable. And I think that’s probably a wise move.”

It was. The following April, the Supreme Court gave Google a smashing victory, entirely along the lines that Goldstein had raised on the fly at the oral argument. In a 6-to-2 majority opinion, Justice Stephen G. Breyer said that Google’s copying of the lines of software amounted to fair use, and thus the court overturned Oracle’s victory. Google wouldn’t have to pay a cent.

For Goldstein, the decision was the latest chapter in an extraordinary story of professional ascent. The Supreme Court bar is a priesthood within a priesthood, an especially rarefied corner of the legal profession where almost all the leading performers share the same credentials: graduation from an elite law school, clerkship for a Supreme Court justice and service in the Office of the Solicitor General, which represents the federal government before the court. Goldstein did none of these things, but he still rose to the very top. At age 50, he had already argued more than 40 cases before the justices and co-founded SCOTUSblog.com, an authoritative guide to the work of the court. Thanks to a high-profile victory for a blue-chip client like Google, he could look forward to years of similarly important, and lucrative, assignments.

It hasn’t worked out that way. Just a couple of years after his victory in Google v. Oracle, Goldstein stunned the world of Supreme Court advocates and insiders by announcing that he would no longer represent clients before the justices. In public, he attributed the decision to the rightward drift of the court, but that explanation contained only a sliver of the truth. In fact, over the previous decade-plus, Goldstein had been leading a secret life of ultra-high-stakes gambling and “sugar daddy” relationships with multiple young women — a life so sheltered from those around him that no one knew the full extent of it, least of all his wife.

When it came to light, his life unraveled. His friends have largely abandoned him. His marriage of three decades is ending. He is nearly bankrupt. Most pressing of all, Goldstein is staring down a 22-count federal indictment on tax-fraud charges and a trial that is scheduled to begin in January. If convicted on the most serious charges, he will almost certainly face prison time.

Contemplating his future from his home office in Washington, Goldstein is frequently reminded of his current predicament. His bail conditions limit him to just two electronic devices — a phone and a desktop computer, where a message pops up every five minutes to inform him that the federal authorities are monitoring his activity. Goldstein sought to sell the house, valued at about $3 million, to pay his lawyers and expert witnesses, but prosecutors barred the sale; they plan to seize it, as the fruit of his crimes, if he is convicted.

Outside the front door, his two Bentleys, among other family vehicles, are gone, replaced by a Honda. But Goldstein is uncowed. “I have never, ever believed that I did anything wrong,” he told me. For his defense at trial, he’s planning the same kind of bold, all-in strategy that he used at the Supreme Court, this time with his own freedom on the line.

Goldstein’s fall has been as precipitous as his rise was meteoric. An indifferent student at the University of North Carolina, he survived academically by relying on the class notes of his girlfriend since freshman year, Amy Howe, who would later become his wife. He was admitted to the law school at American University only because a distant relative, who happened to be an adjunct professor there, went to bat for him with the admissions office.

During law school, though, something clicked, and Goldstein excelled. While he was a student, he developed a particular fascination with the Supreme Court, and he was hired as a summer intern by Nina Totenberg, the longtime Supreme Court reporter for National Public Radio. (As a law student at Georgetown, Howe also interned for her.) The couple, who married in 1994, became like family to Totenberg, and their first child, born in 2001, is named Nina in her honor.

Thanks in part to Totenberg’s recommendations, Goldstein started working for the celebrated lawyers David Boies and Laurence Tribe on the cases that became Bush v. Gore. I was covering the contested aftermath of the 2000 presidential election when I first met Goldstein. He was just 30, and he already displayed the premature aging — the wispy comb-over, the indoor pallor — of the prototypical Washington nerd. Still, his dweeby look deceived. Most young lawyers in the bag-carrying stage of their careers kept a cautious distance from reporters like me, but Goldstein was an opinionated schmoozer who gave off the unmistakable vibe of someone destined for big things. He’d mastered the inside game — “No one knew more about the Supreme Court than he did,” Boies told me recently — but he also thirsted to play in the broader culture, including the media and the internet, at a time when many other lawyers were first signing up for email.

Image

Thomas Goldstein represented Epic Games, makers of the popular Fortnite video game, in an antitrust case brought against Apple in the Court of Appeals for the Ninth Circuit, in San Francisco, in 2022.Credit...Jeff Chiu/Associated Press

As a young lawyer at the large firm Jones Day, Goldstein had an original insight. He could use the primitive computer tools then available to uncover so-called split circuits — cases in which circuit courts had decided the same question of law differently. Then — and here was Goldstein’s real innovation — he would call the lawyers on the losing side and offer his law firm’s services to file appeals to the Supreme Court. At the time, prospecting for clients was seen as somehow vulgar, sort of like advertising, and thus beneath the dignity of advocates who appeared before the justices. As Chief Justice John G. Roberts Jr. put it, back when he was still a private lawyer with an active Supreme Court practice: “If I’m going to have heart-bypass surgery, I wouldn’t go to the surgeon who calls me up.”

Goldstein ignored such etiquette with his cold calls — and they worked. “So I go and get five of these cases, and the first four are granted: bang, bang, bang, bang,” he told me. When Jones Day wouldn’t let him argue the cases he’d found — at that point he had never argued a case in any court — Goldstein left and started his own firm, where he was able to rustle his own split-circuit clients. Soon, Amy joined him in what would become Goldstein & Howe. In the years that followed, many Supreme Court practitioners, indeed most lawyers, began recruiting clients in a similar way.

By his early 30s, Goldstein had established himself as a successful, and prosperous, Supreme Court advocate, an adjunct professor at Stanford and Harvard law schools and, through his blog, a leading public commentator on the justices. On the day that the court upheld the Affordable Care Act, in 2012, as many as a million people would follow along as his site live-blogged the outcome.

In the early 2000s, ESPN began broadcasting poker, a game Goldstein had never played. “I loved watching,” he told me. “I think of it as a pretty intellectual thing. Actually, I like it because what poker is, fundamentally, is management of luck and management of risk.”

Goldstein quickly graduated from games around the kitchen table with jars of quarters to tables of high-rollers in Washington and New York. “I would play in home games where you could win and lose $100,000,” he told me.

Goldstein’s style of play reflected his swaggering, risk-friendly approach to litigation. “Very often lawyers, or people in general, want to make every conceivable argument, and you get in the situation where, by making every point, you essentially make no points,” he told me. “I’m a big believer that you have to figure out what your winning argument is. It is a poker thing, and that is being willing to say: This is not working. And if I just sit here and hedge my bets and argue both, I’m not going to accomplish anything.” As Bill Perkins, an Austin, Texas-based hedge fund manager, put it: “Tom is extremely wild and crazy, like a lunatic at the poker table. He’s fearless, an overbluffing kind of a player, what we call a chip bully. He tried to run people over at the table. You want controlled aggression, and he had unbridled aggression.” For better or worse, in poker and elsewhere, Goldstein believed in going all-in.

The first major turning point in Goldstein’s poker career came in 2008, when he put up the $10,000 fee to enter the World Series of Poker, a multiday extravaganza in Las Vegas. On the first night, after the tournament had ended for the day, Goldstein sat down at a table at the Bellagio. “I end up playing without looking at my cards,” Goldstein said. That, to put it mildly, was an unconventional strategy. He bet wildly and recklessly, but his opponents were flummoxed by his blind aggression. Goldstein told me he ultimately played that way for 18 hours and won some $400,000.

That night was also significant because it’s when Goldstein met Dan Bilzerian. An heir to a family fortune, Bilzerian became famous for his extravagant and louche lifestyle as a professional poker player in Las Vegas, and later for being a social media influencer whose posts often featured guns and women in bikinis. Bilzerian recalled Goldstein’s antics that night: “People were all watching the game and talking about what a [expletive] maniac he was.”

Goldstein appeared to regard Bilzerian with admiration; he contributed a passage to “The Setup,” Bilzerian’s 2021 memoir, calling him a “weed-smoking, gun-toting, multiple-girl-banging dude. … I’m lucky enough to say that he’s one of my best friends.” The nerd became a player, in more ways than one. Goldstein started wearing chunky silver jewelry and, like Bilzerian, sporting a thick, full beard. “Dan wanted to do all kinds of bets,” Goldstein told me, “He wanted to do a TV show where it was him and me doing all kinds of crazy things around the world.”

The TV show never came to fruition, but the pair did make one famous nonpoker bet. Goldstein had bought a Ferrari, which cost about $300,000. “I was jealous,” Bilzerian later recalled, “so I did what most jealous people do. I talked [expletive].” Specifically, Bilzerian boasted that his souped-up 1965 Shelby Cobra could beat the Ferrari in a race. One thing led to another, and they agreed to a quarter-mile showdown at a drag-racing track in Las Vegas. According to Bilzerian’s memoir, the original wager was $100,000, but the night before the race, Goldstein raised the stakes to $300,000 with poker chips from the Bellagio. The battle took place on March 9, 2011. Goldstein pushed his Ferrari to 121 miles per hour; but Bilzerian cranked his Cobra up to 133, and won handily.

Image

Screenshot of the drag race Goldstein had with Dan Bilzerian to settle a $300,000 wager.Credit...Screenshot from YouTube

During a photo shoot for Hustler magazine, Bilzerian threw a naked porn actress named Janice Griffith off a roof in Los Angeles into a swimming pool. She broke her foot, and her lawyer threatened to sue Bilzerian. Goldstein’s legal response on his friend’s behalf went viral in both the Supreme Court and poker worlds. “She was under contract to Hustler and agreed with Hustler’s request that she be photographed while being thrown off the roof,” he wrote. “I always thought that this kind of thing was Photoshopped instead. Perhaps Hustler’s editorial standards would not permit it. Perhaps she insists on doing all her own stunts. I really do not know. In all events, she agreed. Very few people I know would make that choice. But there it is.” He continued: “Like your client, the facts of the claim won’t, quite, fly.” TMZ obtained a video of the pool incident, which has nearly five million views on YouTube. (In later years, Bilzerian became notorious for his antisemitic views and conspiracy theorizing.)

That Goldstein had law clients in the poker world helped him explain to his wife his increasingly long absences from Washington. (He also represented the website Poker Stars, which was headquartered on the Isle of Man.) Goldstein told me that over the years he had actively misled his wife and friends about how much he was gambling. But once he started playing in public tournaments like the World Series of Poker, the size of the stakes unnerved those who cared about him. “I’ve been on his case about this for years and years, as was his wife,” Nina Totenberg told me recently. “He just lied to us about it. In 2010, he promised her he wasn’t going to gamble anymore.” (Amy Howe, Goldstein’s wife, declined to comment. To be clear, the Amy Howe who is the chief executive of FanDuel, the sports gambling company, is a different person.)

Most litigators have to engage in time-consuming tasks like reviewing documents, taking depositions and negotiating with adversaries. But the core of Goldstein’s work was writing briefs (which could be done remotely) and then parachuting back into the capital for oral arguments. And throughout his career, Goldstein’s forays didn’t hurt his law practice — or his skills in court. A few weeks after the drag race, on April 26, 2011, Goldstein represented a company that challenged, on First Amendment grounds, a Vermont law that restricted pharmacies from selling various data. His argument, delivered with conversational ease, was a tour de force. He directed the justices to page numbers in the briefs and court record as if he were their peer. Later, by a 6-to-3 vote in the case, Sorrell v. IMS Health, the court agreed with Goldstein that the law was unconstitutional. Thanks to victories like this one, Goldstein had secured his place as an elite Supreme Court practitioner, at the same time that he was disappearing, for ever longer periods, into the poker world.

Goldstein quickly realized that even with his successful law practice, he didn’t have the cash to compete. “The idea was to be able to play very, very, very deep and not be out of money,” Goldstein told me. He took out a $10 million line of credit from Stewart Resnick, a California billionaire who owns the parent company of Pom juice, a former client of Goldstein’s. (Resnick declined to comment.)

In 2014, Goldstein met a Malaysian businessman who would bring his poker career to the next level. The businessman, Paul Phua, has been called the “world’s biggest bookie” because he owned one of the leading sports betting sites in Asia. He was also an inveterate gambler who traveled the world looking for high-stakes poker games. On July 9 that year, the F.B.I. raided Phua’s villa at Caesars Palace in Las Vegas, which went for tens of thousands of dollars a night, as part of an investigation into $400 million in illegal wagers on the 2014 FIFA World Cup. Through connections in the poker world, Phua hired Goldstein as his defense lawyer. Goldstein learned that the F.B.I. had gained access to Phua’s villa by posing as cable TV technicians. Goldstein convinced the court that the ruse made the search illegal, and the case against Phua fell apart. A great friendship between the two men was born, and Phua introduced Goldstein to the kind of poker that made his contests with Bilzerian look penny-ante by comparison.

With Phua, Goldstein no longer flew commercial. They took Phua’s jet to Hong Kong and Manila, and Goldstein increasingly operated in hushed private suites or homes. Two types of poker predominated as Goldstein moved his action into Phua’s world: In “ring games,” six to 10 players compete against one another; “heads-up games” are one on one, with just a dealer.

After getting the loan from Resnick, Goldstein promptly lost $9 million playing ring games. “Playing ring poker against a bunch of people requires enormous discipline, enormous patience, and those are just not things in poker that I have,” Goldstein said. “If you’re playing against eight people, just mathematically, the odds that somebody has a hand that’s better than yours are quite high. If you’re playing against one person, you don’t have to be nearly as patient. What’s rewarded is being very aggressive. So heads-up, in essence, is built for me.” Goldstein started taking on investors in his heads-up contests, who would share in his wins and losses.

In heads-up games, most of Goldstein’s opponents were billionaires with an expensive hobby. With just three men in the room, the games didn’t feature a lot of conversation. “You can imagine people who are just super, super focused,” he told me. “They’re not chatting. There’s me, there’s the dealer, there’s them and, you know, somewhere between two and 20 hours of pretty stone silence, except for the bets.” In Manila, Goldstein played poker with a gambler known as Tango and won $13.4 million. He also won $9.96 million from a gambler known as Chairman. From 2016 to 2018, Goldstein was out of the country for almost a full year. (He generally told his wife he was on business trips for Phua.)

Image

Goldstein at the Triton Super High Roller Series in Montenegro, in 2018. The buy-in for the event was $1 million.Credit...Danny Maxwell, via PokerNews

At the end of 2016, Goldstein played a California businessman named Alec Gores in Beverly Hills and won $26.435 million — the biggest score of his life. (Earlier that year, Goldstein also won $200,000 in a game that included the actor Kevin Hart.) During this run he won a total of about $50 million, and even though he had sold roughly 75 percent of his stakes to investors, he still personally cleared about $12 million. Flush with his success against Gores, Goldstein sat down to a heads-up match with a real estate magnate named Bob Safai — and this time he didn’t spread the risk by taking on backers. “I just have convinced myself, because I won $50 million in heads-up poker, that I am a savant at heads-up poker,” Goldstein told me. He promptly lost $14 million to Safai, all out of his own pocket. (Phua, Tango and the Chairman could not be reached; Gores, Hart and Safai declined to comment.)

I asked Goldstein how he could stand the stress of playing for such gargantuan stakes. “I have both the benefit and the great disadvantage of not placing particular value on the money,” he said. “So that means that I can play at very large stakes and not get psyched out about it, but it also means that I will take too many risks with too much money. So it’s a blessing and a curse. It does not bother me. It doesn’t cause my heart rate to go up. I mean, I can think of $26 million like $26,000, really, genuinely.”

Around this time, at least when he was on the road, Goldstein also began to adopt the kind of decadent lifestyle he saw in the jet-set poker world. This included contacting women on a website called Seeking Arrangement, which existed to foster “sugar dating” — that is, to connect wealthy men to young women. According to the indictment, “between 2016 and 2022, Goldstein was involved in, or pursued, intimate personal relationships with at least a dozen women, transferring hundreds of thousands of dollars to them from his financial accounts or joint bank accounts he set up with the women, and paying for travel and other expenses for many of them.” Goldstein’s wife remained in the dark. “Amy had no idea about any aspect of this — the poker, the women, anything,” he told me. “I just had this entirely separate life.”

In November 2020, criminal investigators from the Internal Revenue Service and the Justice Department showed up unannounced at Goldstein’s office to serve grand-jury subpoenas. Goldstein supplied the information demanded, but for long stretches afterward he heard nothing; he was neither charged with a crime nor cleared of potential wrongdoing.

The investigation arose at a time of increasing disquiet for Goldstein, as the rightward political drift of the Supreme Court led to more judgments in favor of corporate defendants. Goldstein, who often represented plaintiffs, felt that his cases were becoming uphill, if not futile, battles. And he still owed millions to Stewart Resnick, who had extended the $10 million line of credit.

In addition, Goldstein became more estranged from his life in Washington as he pursued relationships with women he met online. At one point, he rented a house in California where three of the women lived together, and carried on relationships with each of them.

Goldstein hit on what seemed like a solution to his money problems: the perfect opponent. After he started playing poker for seven- and eight-figure stakes, he began seeking out a particular Southern businessman who was an especially profligate player. If Goldstein could line up heads-up games against him, perhaps he could clear his debts and start making real money. But Goldstein had a hard time setting up a game with him. (Goldstein told me about his dealings with the businessman on the condition that I not use his name. The businessman did not respond to a request for comment.)

Finally, Goldstein found his way to the Southern businessman through a game at the Beverly Hills home of Alec Gores, which included, among others, Leonardo DiCaprio and an old-school gambler known as Big Al DeCarolis. (Al Pacino came by to watch, but he didn’t play.) DeCarolis then invited Goldstein to a poker game in Costa Rica where the Southerner would be playing.

The Southerner had a reputation as an inveterate womanizer, so Goldstein thought he would impress him by showing that he was a kindred spirit. Goldstein brought four of his girlfriends with him to Costa Rica. “He found this to be the most interesting thing in the world,” Goldstein recalled. “That was on purpose.” Starting in Costa Rica, Goldstein and the businessman struck up a friendship as well as a poker rivalry, and Goldstein began flying to play against him, usually successfully. Goldstein traveled back and forth so often that he rented an apartment in the city where the man lived.

Goldstein’s poker rivalry with the Southerner was one reason for his announcement, in March 2023, that he would give up his law practice. In public, Goldstein portrayed his decision as a kind of protest against the conservatism of the Supreme Court. “There’s very little that an advocate for the little guy can hope to accomplish anymore,” he told Bloomberg Law. Goldstein’s frustration with the justices was real, but he told me that the main reason he ultimately abandoned the law was because he was finally playing heads-up games against the Southern businessman. “I was beating him,” Goldstein said. “And that was just a way more interesting life.” Goldstein won roughly $50 million from the Southerner, netting $15 million for himself after paying off his investors.

Then suddenly, Goldstein got the worst break of his life. The tax investigation, which had drifted inconclusively for years, was taken over by a federal prosecutor named Stanley Okula. Through decades of service in New York and Washington, Okula had earned a reputation as a bulldog whose aggressive tactics had twice been criticized by judges. The prosecution team issued 300-plus subpoenas and interviewed dozens of people.

The formal charges were handed down on Jan. 16, 2025, four days before the end of the Biden administration, and it was a thunderclap in the legal world. Goldstein’s friends knew that he played poker, but they had no idea that he was playing for such high stakes. The 50-page indictment laid bare Goldstein’s double life and included 22 counts, which carried the possibility of dozens of years in prison. The legal press was ablaze with the story — one prominent podcast posted an “emergency episode!” — and the reactions included both schadenfreude (“Tom Goldstein Should’ve Stuck With High-Stakes Go Fish”) and sympathy, especially for Howe.

Image

Goldstein says: “I think of it as a pretty intellectual thing. Actually, I like it because what poker is, fundamentally, is management of luck and management of risk.”Credit...Jonno Rattman for The New York Times

The core of the government’s case is that Goldstein used funds from his law firm to pay several million dollars in personal expenses, including some poker debts, thus reducing his taxable income. Goldstein acknowledges that this did happen on occasion, but he said the payments were errors by his office manager or his accountant. To make that case, he showed me a 2014 email that he sent to his office manager in response to a question about taxes: “We always play completely by the rules,” it read.

There were several years in which Goldstein asked for a delay in paying his taxes, saying that he did not have the money when his returns were due. The government believes the delays were unjustified, given that Goldstein was making large payments to the women in his life around the same time. Goldstein asserts that his bank records will prove his point. “Millions of people file and then pay late, as I did,” he told me.

The criminal charges asserted that Goldstein briefly hired four of the women he met on his travels but that they did no work for the firm; thus, according to the government, the payments to them were personal expenditures by Goldstein laundered, tax-free, through his firm. As a government brief in his case put it, he met “Woman-1, then a recent college graduate, on a dating website for individuals seeking to receive or provide financial support as part of an intimate personal relationship. He paid her $500 for their first meeting, and they began an intimate personal relationship.” (These four women are different from the three who shared the house in California.)

But Goldstein established — and the government conceded — that three of the four women did some work for the firm. (The fourth immediately went on medical leave.) In a recent ruling, Judge Lydia Kay Griggsby prohibited the government from arguing at trial that the four women were sham employees. The payments to the women were very small, just a few thousand dollars in total, so the tax issues were almost trivial. “Those charges have nothing to do with taxes,” Goldstein told me, “They just put in those charges to dirty me up, to make the jury dislike me.” The judge said she would carefully monitor the government’s evidence, especially about Goldstein’s extramarital affairs, to make sure it was not unduly prejudicial.

The most difficult counts for Goldstein to defend relate to applications that he and Howe filled out for mortgages. In those bank forms, Goldstein understated his debts, especially the multiple millions of dollars that he still owed to Resnick for his line of credit. Knowingly misstating your financial condition on a mortgage application can be bank fraud. Goldstein told me that he omitted that information because he wanted to keep that debt secret from Howe, as he had kept her in the dark about most of his poker activity. Because Goldstein appears to have little defense to the bank-fraud counts, those charges would seem to be ripe for a plea bargain, which is how most federal prosecutions end. But Goldstein told me that the government’s plea offer involves a prison sentence of roughly five years, and he will not plead to anything that includes a prison sentence.

One day when Goldstein and I were talking in his office in Washington, he rose from the chair in front of his computer and invited me to take his place. “Go ahead,” he said. “Look at anything you like.” He offered to show me his tax returns, bank records that Goldstein and his law firm had turned over pursuant to subpoenas, thousands of emails and texts to and from his poker opponents and all of his lawyers’ pleas to the Justice Department. I didn’t take full advantage of Goldstein’s characteristically dramatic gesture, but he made his point. He had nothing to fear because, he insisted, the evidence showed he was innocent.

Goldstein’s bail conditions prohibit him from playing poker, so his lifetime win-loss record has been frozen for the past year. He’s won upward of $88 million in heads-up contests, a vast majority of which went to his investors. Most of Goldstein’s losses came in ring games, which he financed himself. He told me that overall he was a net loser, with a deficit of between $10 million and $15 million.

Most of his acquaintances have kept their distance from him since he was indicted, either because they’re barred from contact as a bail condition or out of loyalty to Howe, whom they regard as a wronged party. Still, when I spoke with Goldstein’s friends, I was struck by their enduring affection for him and their genuine distress at his current plight. To a person, they described him as “generous” and “loyal.” As one friend put it: “When I came out of the government and wanted to start a Supreme Court practice — that is, to become a competitor to Tommy — no one was more helpful and enthusiastic than he was.” They also all think he’s addicted to gambling.

I asked Goldstein whether he thought he had a problem. “Definitely not,” he said. “Because, for example, I haven’t played in quite a while; I feel no desire to. I was very happy not gambling. I have no interest in other forms of gambling.” He pointed out that it might help with his legal troubles if he could claim that he was in the grip of an addiction, but that just wasn’t the case. At his wife’s insistence, after his indictment, he attended a few meetings of Gamblers Anonymous, but he quickly deemed it unnecessary.

As the months have passed since he closed his law firm, Goldstein has moved ever further from the staid routines of a Washington lawyer. He told me that he escapes to New York on many weekends to join a new group of friends who share his interest in shibari, a form of Japanese rope bondage that can involve suspending people in the air. “I have spent the last year becoming, weirdly, very good at that,” he said, with the same pride he talks about the cases he argued in front of the Supreme Court. “Now I’m asked to do performances around the country.”

Goldstein’s plans for the future start with being acquitted. At his January trial, in Greenbelt, Md., Goldstein will be defended by Jonathan Kravis, a well-known white-collar defense lawyer in Washington, but there’s no question about who will be calling the shots. “The way that I’m having Kravis argue this is that I’m going to make him stand up and say, Look, when the government files a 22-count indictment and several counts have different alternative theories, at least one of two things is happening,” Goldstein told me. “One is, you are dealing with a horrible person who absolutely doesn’t give a damn about the law and should be convicted of all these things and should spend the rest of their life in jail. Or something has gone very wrong, and somebody is out to get somebody. And you’re going to decide which of those two is true here, because this is going to come down to: Am I a good guy or a bad guy?”

Goldstein still speaks knowledgeably about the Supreme Court, but he recognizes, perhaps with justification, that his current troubles foreclose a return to his prior life. He insists, almost believably, that he’s content to abandon his law practice — and that poker represents the route to his salvation, not just the cause of his downfall. In this version of his life, the Southern businessman remains a talisman of a bright future that only he can see. Playing him, Goldstein told me, “is a way I can make a quarter-billion dollars for the rest of my life.”

Jeffrey Toobin is a former assistant U.S. attorney who writes about the intersection of law and politics. He is the author of “The Nine: Inside the Secret World of the Supreme Court,” “The Pardon: The Politics of Presidential Mercy” and other books.

Related Content

Advertisement

SKIP ADVERTISEMENT

Ends soon:
Gift subscriptions to New York Times Games are on sale.Games gift subscriptions are on sale.

The New York Times Games

The New York Times Games

The New York Times Games

Give the gift they’ll enjoy all year. Give the gift they’ll enjoy all year —
unlimited access to everything we offer.

Games gift subscriptions. $50 $40/year.

Games gift subscriptions.
$50 $40/year.

The New York Times Games

Read the whole story
chrisamico
8 days ago
reply
Boston, MA
Share this story
Delete
Next Page of Stories