Will ChenWill Chen
← Writingsystem design

The Raycast command stack

For five months I asked which tasks deserved automating. Asking which prompts deserved a keyboard shortcut produced a working stack in a month.

Will ChenWill Chen8 min

Motivation

For five months I had been asking which of my tasks deserved to be automated. In August 2024 I started asking which of my prompts deserved a keyboard shortcut, and within a few days I had something I actually used every hour.

The two questions look similar and they are not. Deciding that a task deserves automation requires you to know, in advance, that the task is worth the evening it will cost, and that judgment needs evidence you do not have until after you have built the thing. Deciding that a prompt deserves a hotkey costs about four minutes. If the answer turns out to be no, you have lost four minutes.

Script commands

Raycast is a launcher, the box that appears over everything when you hit a key combination. Most people use it to open applications. It also runs script commands, which are ordinary programs on your machine that the launcher will execute by name, pass arguments to, and render the output of straight back into the same box.

That combination is what made it interesting. I could write a Python script that built a prompt, called a model through LangChain, and returned text, and then reach it from anywhere on the machine without switching windows, without opening a browser tab, and without losing whatever I was in the middle of. The thing I wrote down at the time was that I had finally found a way to call these scripts from a desktop application and have the results immediately visible on screen, and that I could execute language models at the speed of thought.

I did not write the first dozen prompts. I took them from Fabric, Daniel Miessler's collection, the ones like extract-wisdom and analyze-prose, on the grounds that I knew those patterns were useful and I was not using them. Then I added some of my own, mostly small cognitive utilities aimed at a specific moment in knowledge work, including one whose entire job was finding the exact word for something I could only describe.

Interaction instead of automation

The reframe did something to my model of what AI was for, and it took a few weeks to see it.

Building automations puts the model somewhere you are not. It runs on a schedule or a trigger, it produces output into a system, and the design goal is that you stop being involved. Building hotkeys puts the model exactly where you already are, in the middle of a sentence you are writing or a problem you are stuck on, and the design goal is that being involved gets better.

I wrote it out as a numbered set of remarks in the middle of one night that August, and two of them still hold. The first is that I did not think automation was the way out, but interactivity, because I was getting far more value from enhancing what I could do than from having a model do things instead of me, and that automation should serve to make life better rather than easier, which are not the same thing. The second was a complaint about the field: language model flows were centered on making the agent useful, on output and actions, rather than on making the interaction between the model and a person better, and that nobody was solving the second problem.

The shift had actually started a few weeks earlier. In mid-July, writing the retrospective on the automation challenge, I had already put it as a preference for human augmentation over automation, on the grounds that overeager automations are fragile and the flexible part of the system is the person. August is when I had a tool that made the preference practical.

Admission criteria

The test I still apply came out of thinking about one app rather than out of theory, which is probably why it survived.

I had adopted Mochi, a spaced repetition tool, and wrote down three reasons it worked: it had an API, so I could push things into it from a script; it had genuinely good interfaces on desktop, web and phone; and it separated notes from flashcards, which meant I could keep a page of material and a drill of that material as different objects. That last one is the reason I moved off Anki, which merges the two, so a fact you want to keep and a fact you want to be quizzed on have to be the same object. Anki's engine is the one everyone else's is measured against and the separation is a design choice rather than an oversight, but it is the wrong choice for what I was doing, which was writing a page and then deciding afterwards which parts of it deserved drilling. About two hours later I noticed those reasons were not about Mochi at all, and I wrote them out as general criteria for anything joining the stack:

"1. there's an app I can use, that is convenient -- the more accessible, the better. this is the human interface 2. there's an API -- the AI flows need to be able to manage resources / processes on it -- this facilitates the experience of it 3. it must be tied to a behavior or goal that I'm trying to accomplish -- it should be related to self-programming or self-improvement. usage of the app should be directly linked somehow with the human getting better."

Three sentences written about one flashcard app turned out to be the admission test for everything after it, and each clause does separate work.

There has to be an app I can use, and the more accessible the better. This is the human interface. If the only way to reach the thing is through my own scripts, then the day my scripts break I lose the data and the habit with it.

There has to be an API, so the AI flows can manage resources and processes on it. This is what makes it participate rather than sit beside everything else.

It has to be tied to a behavior or goal I am actually trying to accomplish. Using the app has to be linked to me getting better at something, or the whole arrangement is a toy that generates work.

Each clause is load-bearing and the failure modes are distinct. Drop the first and you have built something only you can operate. Drop the second and you have a nice app that your system cannot reach. Drop the third and you have a very sophisticated way of doing nothing.

Spaced repetition as a primitive

Spaced repetition is where the test earned itself, so it is worth walking through what the criteria actually caught.

Spaced repetition is an old and well-supported idea: review something just before you would have forgotten it, and the interval between reviews can grow, so a small daily budget maintains a large amount of material. The algorithm has never been the hard part. The hard part is that somebody has to turn what they read into cards, one at a time, and almost nobody sustains that, which is why the technique has a reputation for being excellent and for being abandoned.

What I built was a script that took a piece of text and produced the cards. It broke the material into bite-sized pieces in increasing order of difficulty using the Feynman method, wrote quizzes aimed at mastery, and created notes in Mochi with cloze deletions and annotations along with the flashcards. It sat behind a keyboard shortcut with several siblings. When I decided I should know something, I pushed it into the pipeline and stopped thinking about it, because the scheduling algorithm then decided what I saw and when.

The reason this felt like an upgrade rather than a convenience is that it changed what kind of thing learning was. Before, learning was a block of time I had to defend on a calendar. After, it was a queue I fed, and the review happened in the fifteen minutes a day I spent in an app that told me what to look at.

Mochi's killer feature is its scheduling engine, and that engine became accessible to me because a model could do the data entry it required. Which generalises, and the generalisation is the actual idea. The question I asked next was which other algorithms have been sitting there, good and unused, because the preprocessing they demanded was more work than anyone would do by hand. Spaced repetition became a primitive in my stack, and the interesting part was that I could not think of a reason it would be the only one.

Friction as the design variable

By the end of the month I had the constraint that has governed everything I have built since, and I flagged it in my own notes as important while writing it.

The friction has to be so low that the tool effectively becomes an extension of yourself. AI human augmentation cannot just be convenient tools.

That is a threshold claim rather than a preference, and it is worth being precise about the difference. A convenient tool is one you choose to use, and choosing has a cost that gets paid every single time, so a tool that is merely convenient competes with doing nothing and frequently loses. Below some level of friction the choosing stops happening. The command fires because you thought of it, and by the time you would have weighed whether to bother, the output is already on the screen.

Capability was never the binding constraint that month. The models could do all of it in a browser tab. What the browser tab could not do was disappear.

Portability

The stack had one property I could not fix, which is that none of it was shareable.

Every one of those commands was a Python file on my machine, pointed at my API keys, wired to my data, and shaped around habits I had spent months studying in myself. I wrote at the time that almost nobody would ever get to this, not because the ideas were hard but because the friction of discovering what is valuable is enormous, and it had taken me continuous adaptation and deliberate attention to find things that fit into my routine without demanding that I change it.

Which is a strange position to end a good month in. The thing I had built was working, and the part that made it work was the part that could not travel.