6: The Command Palette - transcript
Liam: The QUILL Cast, episode six. I'm Liam, and today, one keystroke is worth the whole episode. Control shift P. The command palette.
Jessica: I'm Jessica. Last episode, Liam and I walked Notebooks and Versions: the project container that holds your documents, the named snapshots you can come back to, the entries panel, the tree navigators, and the four "go to in Notebook" commands on the Navigate menu. The honest moment in that episode was the rename: older QUILL documentation called these Workspace Snapshots; the current code calls them Versions, and the data class has been renamed to Notebook Snapshot. If you ever read old notes, that is the word to look for.
Liam: The honest framing for today. We are going to spend this entire episode on one feature, and we are going to verify it against the code, not the marketing. The feature is a searchable popup, a small dialog about seven hundred pixels wide and five hundred tall, that lists every command QUILL knows. Type into it, the list filters as you type, arrow to what you want, press enter, the command runs. Escape closes it with zero side effects. It sounds almost too simple, and that is the point. The reason we are giving it a full episode is that this one feature changes how you use the rest of QUILL. Once it becomes a habit, you stop memorising menu paths and start asking questions.
Jessica: Quick series check. This is episode six of fifty-four. After this, we have episodes seven through twelve on everyday editor skills, then deep dives, then AI, then the long tail. But for the next thirty minutes, the only command that matters is the one that lists every other command.
Liam: Here is the part to do right now, before any theory. Pause the audio. Open QUILL. Press control shift P. A dialog will appear in the middle of the window, titled "Command Palette," with a single search box at the top, a small status line underneath, and a list below that. Type the word save. Watch the list narrow. Type it again, type save a, type save as. Notice the speed. Press escape. Press control shift P again, type the word compare. Notice what is there. Press escape one more time. Press play when you are ready. We will be right here.
Jessica: Welcome back. If the dialog opened, you have the palette. If it did not, the most common reason is that another modal dialog owns the window, for example an unsaved-changes prompt or an export progress dialog. Close whatever is open and try again. The palette is reachable any time the main frame is, and the keybinding lives in the default keymap, profile underscore default dot json, under the command id app dot command underscore palette. The literal binding is control shift P. The status bar also says so, on first launch: "Ready. Tip: press control shift P for Command Palette." That tip is gated by a setting, announcement underscore startup underscore tips underscore enabled, so if you have turned startup tips off, you will not see it, but the key still works.
Liam: What you just did is the whole feature, but we are going to go underneath it, because the design is what makes the feature safe. The dialog is implemented in quill slash ui slash palette dot py, in a class called CommandPaletteDialog. It is a wx Dialog with default style and a resize border. The size is seven hundred by five hundred. The accessibility name on the dialog itself is "Command Palette, type to search, enter to run, escape to close," which means a screen reader announces all of that as soon as it opens. The search box is a wx SearchCtrl with a process-enter style, so the enter key does not insert a newline, it confirms the selection. There is a small cancel button inside the search control, and pressing it clears the query in one shot. The results list is a wx ListBox, with the accessible name "Command results, use arrows to navigate, enter to run."
Jessica: Underneath the list, there is a status line. The status line is the second thing the feature does well, and it is the part screen reader users tend to notice first. Every time the result list changes, the palette writes a one-line summary to the status label, and it also calls the announce function if one was supplied. The summary is in the form "N command(s), M available. Top match: X. Down slash Up to navigate, enter to run." The reason that line matters is that it tells you three things at once. How many results matched. How many of them are actually runnable in your current context. And the name of the first result, which is the one enter will run. You never have to guess what the default action is.
Liam: The list itself has a precise shape. Each row is the command's title, then a space, then its current keybinding in square brackets, if it has one. So "Save [control S]," "Save As [control shift S]," "Compare With [no keybinding]." If a command has no binding, the brackets are simply absent. That is the third feature of the palette in one detail: it is a shortcut tutor. You use a command through the palette, you keep seeing the key next to it, you internalise the key, and one day you just press the key. The palette teaches you the keyboard by using the keyboard, which is the only way most of us actually learn.
Jessica: Now the matching. The default mode, with no prefix at the start of the query, scores each command by how well the query matches the title or the id. Exact match on the full title is the highest score, one thousand. A title that starts with the query scores nine hundred. A title that contains the query as a substring scores seven hundred. The same logic is repeated against the command id, with slightly lower numbers. If none of those match, the ranker falls back to a subsequence check, which is the most permissive of all: as long as the characters of the query appear in the title in order, even with gaps, the command is in the result list, with a score that decreases as the gap grows. The score is then tie-broken by how many times you have used the command through the palette, then by when you last used it, then by the alphabetical order of the title. So the top of the list is, in order, the best text match, the most-used command, the most-recent command, and finally the alphabet.
Liam: What that means in practice. The matching is forgiving. Fragments work. Order matters, but gaps are allowed. You do not have to start the word. You do not have to know the precise spelling. You can type the first three letters of each word in a long command name, and as long as the letters appear in the title in the right order, you will find it. For users on a screen reader, this matters more than it sounds: arrow navigation through results is one keystroke per result, and the top result is announced as the title and binding, so the smaller the result set, the less arrowing you do. A good query gets you to the right command in two or three arrows, and the only skill required is a habit of typing fragments.
Jessica: There are four prefix markers that change how the search is interpreted. The first is greater than. Typing greater than and then a phrase strips the prefix and searches the way we just described. It is also the default, so you do not actually need to type it. The second is colon. Colon switches the search into id mode, which scores the query against the command id instead of the title. That is the one you reach for when you know the id, for example app dot command underscore palette, but you would be surprised how often the title is the more memorable one. The third is question mark. Question mark switches into bound mode, which only returns commands that have a keybinding at all, and then runs the normal scoring against their titles. That is the right prefix if you are hunting for "what command does control shift G do" and you want to narrow fast. The fourth is tilde. Tilde switches into recent mode, which is the same scoring but in a context that biases towards commands you have used recently. We will come back to tilde when we talk about repeat. The two siblings that the palette knows about, control shift P for commands, and control shift grave then G for Go to Anything, accept all four prefixes.
Liam: A second dialog lives next to the command palette, and it is worth a paragraph. Go to Anything, command id navigate dot go underscore to underscore anything, binding control shift grave then G, opens a slightly taller dialog, seven hundred by five hundred and twenty. The title is "Go to Anything." It accepts the same four prefix markers the command palette does, plus a fifth: hash. Hash restricts the result list to outline headings from the current document. The result list shows both commands and headings at once, with a kind label and the title, so arrow through and hear "heading: Introduction" or "command: Save [control S]." Headings are gathered by a small helper, underscore collect underscore outline underscore headings, that walks the editor's text, looks for lines beginning with one to six hash characters, and records the heading text and the line number. Select a heading, press enter, and the editor jumps to that line. It is the same mental model as the palette, with one extra kind of thing to find.
Jessica: Honest moment. We have been talking as if every command in the registry is in the palette. It is not, and there is a feature manager in the middle. When the palette is constructed, the constructor asks the FeatureManager which features are visible in the current profile, then drops every command whose feature is not visible. So if you have turned a whole family of commands off in Preferences, the palette reflects that. You will not see them. The visible list is also sorted alphabetically by title in the registry's list method, and the ranker reorders them by score afterwards, but the underlying list that the ranker sees is the filtered one. That is the correct behaviour: the palette should show you the QUILL you have configured, not the full catalogue. We mention it because the inverse is also true, if you cannot find a command you are sure exists, the first place to look is the feature gating.
Liam: Now the secret second function we hinted at, and it is the one we want you to leave the episode thinking about. The palette is a discovery tool. Idle ten minutes with the palette open, type a letter, watch the list, and you will meet commands you did not know existed. The list contains every registered command, including every Notebook and Version command from last episode, every spell check command, every compare command, every AI command, every accessibility command. The ChapterForge design notes that the palette borrows from describe this as "the map of the whole territory, searchable," and that is the right way to think about it. If you have ever wondered "can QUILL do X," the answer is the palette, every time.
Jessica: Compare documents is a good example, because it has a couple of interesting properties. There is no default keybinding for compare in the default keymap, profile underscore default dot json. We checked, and the bindings file has no entry under tools dot compare underscore documents or any of the similar ids we could find. So if you have ever wondered "how do I compare two documents," the answer is the palette. Open it, type compare, the result list will narrow to compare-related commands. The top match depends on what the ranker finds. Run the one you want. That is the loop: wonder, open the palette, type, run. No menu hunting.
Liam: Spell check is the other example worth a beat. The default keymap has bindings for the full family: tools dot spell underscore check underscore dialog is F seven, tools dot next underscore misspelling is control F seven, tools dot previous underscore misspelling is control shift F seven, tools dot misspelling underscore list is alt shift L, tools dot thesaurus is shift F seven. So spell check has a complete keyboard story. The palette is for the moments when you do not remember which F-key is which, or when you want to skim a new feature, not commit it to muscle memory yet. The palette and the keymap are not competitors, they are layers, and the right time to use each is a question we will answer for you in a moment.
Jessica: A code-honest correction, because we want to keep earning the trust we built in earlier episodes. The docstring at the top of the palette file describes unavailable commands as being shown with a dash prefix, "minus space title." That description comes from the ChapterForge design the palette borrows from. The current code does not do that. What the code does is two things. First, the constructor filters the candidate list to commands whose feature is visible, so most unavailable commands are never in the list to begin with. Second, for the rare case where a command is in the filtered list but is still not available, the palette announces the title with a trailing "(unavailable)" in the per-item announcement, and the status line says "X is not available in the current context." If you press enter on an unavailable command, the palette refuses to run it and tells you why. So the behaviour is the spirit of the docstring, but the visual presentation is different. We are not going to pretend the comment is right when the code is what runs. The code is what runs.
Liam: A second code-honest correction, this one against the previous version of this episode. The earlier short script said "F one answers what is this." That is wrong. The default keymap has F one unbound. The actual keybinding for context help, which is "what is this thing and what does it do," is help dot context underscore help, bound to control shift grave then shift H. So if you are hunting for the "what is this" feature, it is control shift grave, then shift H, not F one. We flag this because the kind of drift where a key name in a podcast transcript disagrees with the keymap is exactly the kind of thing a screen reader user will catch immediately, and a sighted user will not catch until they press the key and nothing happens. We would rather be the ones to fix it.
Jessica: Now the part that is not obvious from the code, the double-press trick. Press control shift P, pick a command, run it. Press control shift P again immediately, within four hundred milliseconds by default, and the palette does not open. It re-runs the last palette command. The mechanism is a small dispatcher, MultiPressDispatcher, that counts consecutive presses of the same key within a window. The window is set from the setting multi underscore press underscore window underscore ms, defaulting to four hundred milliseconds. If a second press lands inside the window, count is two, the timer is cancelled, and the main frame's open underscore palette method runs underscore run underscore last underscore palette underscore command. The last run command id is stored on the main frame in underscore last underscore palette underscore command underscore id, updated every time the palette runs a command. If the second press lands outside the window, count is one, the palette opens normally, and the timer fires after the window expires to do nothing.
Liam: What the double-press lets you do, in practice, is turn the palette into a one-key macro. Pick the command once. Run it as many times as you want, with the second press as a repeat. The classic case is "next misspelling," control F seven, but you do not actually press control F seven, you press control shift P, type the first few letters, press enter, and then every subsequent press of control shift P within four hundred milliseconds walks the editor to the next misspelling. The same trick works for next region, F six, and for any other command that has a clear "do it again" interpretation. The code marks a small set of commands, like toggle commands, as informational, so a second press on those does not toggle back and forth, it announces "showing what you just said" instead of doing the action again. That is a thoughtful design choice, and we will revisit it in a later episode.
Jessica: A second way the palette is smart. The ranker uses palette usage data, stored at palette usage dot json inside the QUILL app data directory. Every time a command is run from the palette, the ranker records a small entry: the command id, an incremented count, and the current epoch timestamp. The entry is written through the atomic JSON helper, so a crash during the write does not corrupt the file. The next time you open the palette, the ranker reads the file and uses the counts and timestamps as tie-breakers. So the more you use a command, the higher it floats in the result list, even if the text match is not perfect. That is the same idea as the search engine in your email client, but local, in a single file, in your data directory.
Liam: A short tour of the data, because you may want to look at it. The file is plain JSON, with a top-level object whose keys are command ids. Each value is an object with two fields, count and last underscore used underscore epoch. Count is an integer that grows on every palette use, last underscore used underscore epoch is an integer that holds the unix timestamp of the most recent use. There is no automatic decay, so a command you used once five years ago will still count, but the recent-epoch tie-breaker will still rank recent commands above old ones. The file is safe to delete if you want a fresh start, and the next palette use will recreate it.
Jessica: The one thing we want to be careful about. Usage is recorded only for commands run from the palette, not for commands run from a keybinding or a menu. That is the right scope, because the ranker is feeding the palette, not the rest of the app. If you never use a command via the palette, its count stays at zero, and the ranker treats it like every other new command, scored on text match alone. So the path of "use the palette to learn a keybinding, then use the keybinding" is exactly what the ranker expects. The path of "always use the palette, never learn the keys" is also fine, and the ranker will reward you for it.
Liam: Let's talk about what the palette is not. It is not a search engine for the file system. It does not find files, it finds commands. Files are reached through File, Open, or through the recent files in the File menu, or through the spell check style navigators. It is not a documentation reader. F one, or rather control shift grave then shift H, is the documentation reader, because it opens a context-sensitive help panel for whatever is currently under the cursor. The palette answers "what can I do," the context help answers "what is this." Use them together, and QUILL is a self-documenting application, the manual woven into the surface you are working on.
Jessica: It is also not a settings editor. Settings live in Preferences, control comma. The palette will run the Preferences command, and the command opens the dialog, but the palette itself is not the dialog. We mention this because the temptation is to think of the palette as "the place where everything happens." It is the place where every command starts, not the place where every command finishes. Some commands open a dialog, some commands run a transformation, some commands ask a question. The palette is the door; the door does not tell you what is on the other side.
Liam: A short list of the kind of things you can do through the palette, just to set the scale. New, Open, Save, Save As, Close, Print, and on it goes through the file menu. Undo, Redo, Cut, Copy, Paste, Find, Replace, Find Next, Find All Matches, Search in Files, Replace in Files. Go to Line, Go to Page, Next Region, Previous Region, Outline Navigator, Match Bracket, Next Structure, Previous Structure, Heading Organizer, Go to Anything. Word Count, Spell Check Dialog, Next Misspelling, Previous Misspelling, Misspelling List, Thesaurus, Read Aloud Start Pause, Read Aloud Stop, Dictation Toggle, Voice Command, Voice Conversation, Voice Wakeword. Table Studio, CSV Studio, Voice Status, Describe Image, Document Intake Report. Continue Writing, Run Agent, Ask Quill Chat, Ask Quill Conversation, Run Agent Foo, Run Agent Bar, and so on. Context Help, Spoken Echo, Announce Contrast, Document Summary, Key Cheatsheet, Why Unavailable. Bold, Italic, Heading One through Six, Indent, Outdent, Toggle Line Comment, Toggle Block Comment, List Manager. Insert Snippet, Manage Snippets, Expand Abbreviation, Manage Abbreviations, Toggle Abbreviation Expansion. Insert Special Character, Number Lines, Trim Blank Lines, Keep Unique Lines, Magic Paste. Every one of these is in the palette. The list is genuinely long, and the only way to know what is there is to open the palette and read.
Jessica: The natural learning loop. Use a command through the palette a few times, keep noticing the key listed next to it, and one day you just press the key instead. Nobody sits down and studies a shortcut chart; the palette teaches you in passing. The flip side is also true. If you find yourself using a command ten times a day through the palette, that is the right signal to assign it a binding, and the keymap editor, which is the topic of episode nine, is how you do that. The palette and the keymap are not in tension. They are two ways to spell the same word, and you switch between them as the moment requires.
Liam: A short bridge before the closing habit, because the next idea only really lands if you have used the palette for a week. The pieces we have named are the binding, the matching, the prefixes, the unavailable-commands behaviour, the double-press repeat, the usage history, and the relationship to the keymap. None of them are difficult. All of them become obvious the first time you actually do them. So the habit is the curriculum, not a paragraph.
Liam: Here is the habit to build, concretely. For one week, ban yourself from the menu bar for anything you already know the name of. Want spell check, palette. Want to compare, palette. Want to go to a line, palette. Want to switch language, palette. The menu bar stays great for browsing and learning, the palette becomes your expressway for doing. By the end of the week, the commands you reach for the most will have settled into the top of your result list, and you will feel the ranker helping. We are not promising you will never use the menu bar again. We are promising that after one week, the menu bar will feel slower than it did before, and you will know which commands you actually want on the keyboard.
Jessica: We will leave you with the broader arc. Episode seven is the one that makes this whole family feel safe. It is about what QUILL says, the announcement system, the verbosity profiles, the Quiet and Meeting modes, and the Why did QUILL say that command. The reason it pairs with the palette is that the palette is the door, and the announcement system is the voice on the other side. Once you have the door and you can shape the voice, the rest of QUILL stops being a surface you have to learn and starts being a surface you can ask.
Liam: I'm Liam.
Jessica: I'm Jessica. Control shift P. That is the whole episode.