Releases: beatzball/swoop
Release list
v0.10.1
Every view matches the way the root does: a few letters in order are enough.
Added
- Every view matches the way the root does. Inside a view, a word's
letters need only be in a row in order:akeyfinds API key in
Settings, as it does at the root. Words still match in any order, in the
title, the subtitle, or a setting's hidden words. The best rows come
first: a word as typed ahead of one with letters in between, the start
of a word ahead of its middle, a title ahead of a subtitle, a short
reach ahead of a long one. Settings, its choices and Extensions, Tasks
and Done, Notes, Snippets, Emoji, Stats, the action menu, and a
keyword's rows (Links, Window) all filter this way. A note's text and a
clipboard entry match a word only as typed. In Tasks and Reminders the
groups and the days keep their order, and the best match leads among
tasks due the same day. A row made from the text (Add task, New note,
Use what you typed) still shows, where it was. swoop-matchfor extensions. A view in shell prints its rows and
pipes them throughswoop-match <query>, and gets the same matching and
order as the bundled views. Agroupheader with no matching row is
left out. Reminders uses it, so it finds a reminder by its list's name
too.
v0.10.0
Tasks in groups, headers the cursor skips, and a Settings filter that takes words in any order.
Added
- Tasks in groups. The open tasks sit under headers by when they are
due: Past due, Today, Tomorrow, This week, This month, Later,
Unscheduled. A header shows only when it has a task, and typing filters
inside the view. Reminders gets the same headers. - Done is its own view. A ticked task leaves the list. Done, the last
row, opens the done tasks, the most recently done first;Back to open
or Esc comes back. The file format is the same. - Week starts on. A new setting,
week = mondayorsunday, says
where This week ends. Monday is the default. - A
grouprow kind for extensions. A row of kindgroupis a
header: Enter on it does nothing. - Settings filters by words. The text in the bar is split on spaces,
and a row shows when every word is in its title or in the value beside
it, in any order:key apifinds API key, andnvimfinds Editor when
that is the editor.aifinds the API URL and API key rows too.
Extensions and each setting's choices filter the same way. - The cursor skips a header. A view opens on its first row that is
not a header, Up and Down step over one, and typing, a tick and Esc
all leave the cursor on a row you can act on. A click on a header does
nothing. A header's title now starts at the left edge, dimmed, with the
icons of its rows lined up under it. Every extension that prints a
grouprow gets this.
Fixed
- Enter after typing in a view takes the first row. The cursor used
to keep its row number while you typed, so from a row further down,
Enter on a new task could tick another one. - The API key can be typed in Settings. In the API key pane, text in
the bar hid every row, so there was nothing to press Enter on. The row
that takes what you typed now shows, once the text is 8 characters or
more.
v0.9.2
The site deploys itself, and a cut gets to the tap in half the time.
Changed
- The site knows its version. https://swoop.sh/version.json carries
the version and the build time, and a cut redeploys the site, so the
live docs always name the release they describe. - Faster cuts. CI keeps the frame's Swift build between runs and tags
a release the moment its merge lands; the checks on a pull request are
now required before a merge.
v0.9.1
The owl: on the site, in the menu bar, and the site on the supernova recipe.
Changed
- The owl in the menu bar. The frame's menu bar item shows swoop's
owl as a one-colour mark that takes the bar's colour, light or dark,
instead of a stock bird symbol. - The owl is the logo. The site's header, hero, touch icon and favicon
carry it, cut from the drawing with the background removed; the hero
shows it mirrored and large, larger still on a phone. - The site at swoop.sh is rebuilt on litro's supernova recipe: a new
landing page with the install command to copy, the keys worth knowing,
and what swoop is built on. The docs pages and their addresses are the
same.
v0.9.0
Keywords that scope the bar, a docs site, a Snippets pane, and a
launcher that never drops a key.
Added
- Keywords: an extension's keyword and a space ask only that
extension.def apopens Define withaptyped,win lshows only the
window rows forl. An extension declares its keyword in akeyword
file beside it; the bundled ones aredef,calc,clip,files,
ai,links,emoji,snip,win,notes,tasks,rem,stats
andsettings. - A docs site, at https://swoop.sh: install, trying it in a terminal,
Ask AI, every extension that ships, and Settings, from the README's own
words. The README links to it at the top. - Writing an Extension, a page of the site that builds one extension
from nothing: a shell script that lists, previews and runs, then opens a
pane, then offers ctrl-k actions, then toggles and opens an editor, each
step tried in the launcher.
Changed
-
Ask AI loose ends. With no model picked, ollama runs the model named
byollama = <model>in the settings file, or else the newest one
pulled, and the line under the dots says which;ai = ollamawith no
model does the same. On Linux the Copy rows say when neitherwl-copy
norxclipis installed. On Windows a worker that has stopped is seen
as stopped, instead of dots until the five minute limit. -
A New note with nothing typed is named by the date and time,
2026-09-28 21:15as its heading and2026-09-28-21-15.mdas its
file, instead ofuntitled. The New note row says the name it will
get. -
New note comes back on the note it made, with the bar empty, so a
second Enter does not make a second note. For extensions: a run of a
terminalrow may write a row id to the file named by$SWOOP_LAND,
and the launcher comes back on that row with the bar cleared.
Fixed
-
Snippets: Edit on ctrl-k, and the placeholders explained. Edit
opens the snippet's file in your editor. The how-to that the Snippets
and New snippet rows preview, and the README, say what each of
{date},{time},{clipboard},{uuid}and{cursor}becomes. -
A Snippets row, always. Once a snippet existed,
snippetsmatched
nothing: each snippet is a row named after itself. Now a Snippets row
opens a pane, New snippet first, then every snippet, filtered as you
type; snippets stay at the root too. -
Snippets with none yet: Enter makes the first one. The row used to
post the how-to and close the launcher. Now it writes the Signature
example and opens it in your editor, in the panel; quit, and it is a
row. ctrl-k on any snippet hasNew snippet, a file named by the date
and time, opened the same way. -
The Settings titles sit in one column. Editor, Open the config
folder, the Settings row at the root, and every choice had no icon,
and the skin tone row's hand was two cells wide, so those titles were
a cell off from the rest. -
Keys typed while a list reloads are kept. Two quick Enters on a
checklist tick two tasks, and letters typed right after Esc all reach
the bar. Before, the launcher ignored keys until the new list had
landed, so the second Enter and the first letters were lost. -
Accessibility survives a rebuild. A checkout install makes
swoop-dev, a self-signed code-signing certificate in the login
keychain (one macOS password prompt, the first time), andmake shell-macsigns the frame with it asdev.swoop.shell. Before, every
build was signed ad-hoc, a new program to macOS, and window rows and
pastes were refused although the switch still showed on. The permission
messages now say what to do then: remove swoop-shell-mac with the minus
button and add it again. Releases are not signed yet, so after an
upgrade that step is still needed once.
v0.8.0
What a launcher has: quicklinks, emoji, snippets, window management,
notes, tasks and reminders, all in the panel, with an editor inside it,
a paste that lands where you were typing, and a switch for each.
Added
- Edit inside the panel. Enter on a note, or on
New note, opens it
in your editor right in the panel, and quitting brings the list back
with the preview redrawn; ctrl-kOpen in appkeeps the old way. The
editor is a new Settings row,editor = nvimin the config, else
$EDITOR, elsenano. Tasks gets ctrl-kEdit the list, Search Files
gets ctrl-kEditon a text file. Extensions can use it too: a row of
kindterminalgets the whole terminal and the launcher stays open. - Notes. Type
notes, Enter: markdown files in
~/.local/share/swoop/notes/, newest change first, searched by title
and text, previewed rendered. Enter opens the file;New notemakes
one from what you typed; ctrl-k copies, reveals, or deletes to
deleted/. - Tasks. Type
tasks, Enter: a checklist in
~/.local/share/swoop/tasks.md. Typed text adds a task, and
today,tomorrow, a weekday or a date at its end is the due date.
Enter ticks a task and the list stays open; ctrl-k undoes, deletes,
copies. On a Mac,remindersis the same view over Apple Reminders. - Snippets. Named text as rows at the root, one markdown file each in
~/.config/swoop/snippets/: name, an optionalkeyword:line, text.
Enter pastes into the app in front with{date},{time},
{clipboard}and{uuid}filled, and leaves the caret at{cursor};
it copies where emoji copies.swoop-snippets importreads a JSON
export (name, text, keyword); ctrl-k copies or deletes. - Emoji and symbols. Type
emoji, Enter, then a name or keyword:
every emoji and flag, and a few hundred symbols. Enter pastes into the
app in front, or copies without Accessibility, in a plain terminal,
and on Linux; ctrl-k copies or picks one of six skin tones, and the
default tone is a setting. The most recently used lead the view. - Window management. Rows that move and size the window you were in:
halves, thirds, quarters, maximize, almost maximize, reasonable size,
center, next and previous display. macOS, through the Accessibility
API; the first run without the permission opens the settings pane. - Quicklinks. Named links as rows at the root, from
~/.config/swoop/quicklinks.tsv: name, link, app to open it with. A
link holding{argument}is a pane: Enter, type, Enter opens the link
with the text in it, encoded. Google, DuckDuckGo, Wikipedia, YouTube,
and GitHub ship until the file exists.swoop-links addand
swoop-links import(a JSON export) write the file; ctrl-k copies
the link or deletes it. - Apps on Linux. swoop lists the applications in
.desktopfiles, in
XDG order, so a copy in~/.local/share/applicationsoverrides or hides
the system's. Enter launches withgio launch, or runs the Exec line
when gio is missing; the menu shows the folder and copies the path. The
preview shows the name, the command, the comment, and the file. - Start, stop, restart.
swoop start|stop|restart|statusworks the
same from Homebrew, the curl installer, or a checkout; the bird menu
has Restart and Quit; and after an upgrade the frame restarts itself
once the panel is hidden. - Turn extensions on and off. Settings, Extensions lists every
extension, bundled and your own; Enter turns one off, and it leaves the
root, Tab and ctrl-k until you turn it back on. It is one line in the
config,off = reminders, tasks, which you can also write by hand.
Settings itself stays on.
Changed
- Emoji and snippets paste from the frame. The frame hides its panel,
then presses cmd+V itself, and only into a text field (or an app that
shows no focus, like a terminal); on a button or the desktop the text
is copied and a notification says so. No more osascript keystroke or
fixed wait, and the Accessibility prompt now names swoop-shell-mac. - Lighter tools. The twelve tools together are 30 MB stripped, from
35. swoop-settings no longer carries an HTTP stack for one request to
LM Studio on localhost; the Kitty placeholder table and a small width
function replace a Charm package that brought four modules along for
two constants and one measurement.
Fixed
- The Reminders pane is no longer empty. It opens at once, from a
cache or with aLoading reminders…row, and fills itself when the
list arrives. The list is read through EventKit in a fraction of a
second, not in 40 through Apple Events.
v0.7.0
Settings inside the launcher, Ask AI with any model, and the list that
learns what you use.
Added
- Used recently, and Stats. The root list starts with the five things
opened most recently, marked. Every open is one line in
~/.local/state/swoop/usage.jsonl; aStatsrow shows what you open
most, how often, when last, and a fortnight by day. A setting turns the
group off; ctrl-k in Stats clears the log. - Start Screensaver, a row beside Sleep and Lock Screen.
- ctrl-k on New conversation changes the model. The same list as
Settings, Enter picks one and returns to the pane; the New row says
which model will answer. - Ask AI with any model. Presets under AI model in Settings:
claude,
codex, eachollamamodel, each model LM Studio has loaded, and
openai:<model>for OpenAI or any server with that API (OpenRouter,
Groq, vLLM) with the address under API URL and the key under API key.
Two transports: a command with the conversation on stdin, or a small
HTTP client in the OpenAI chat shape, streamed, with a model's thinking
shown as "thinking" under the dots rather than in the answer. Web
search, when on, reaches claude, codex and OpenAI; the line under the
dots says when the model you picked cannot search. - Settings, inside the launcher. Type
settings, or cmd+, in the
frame: one row per setting, Enter to change it. The hotkey, the preview
width, the AI model (claude, or ollama with any model you have), web
search on or off, the transcript renderer, and a door to the config
folder. Every value is one line in~/.config/swoop/config. The frame
watches that file, so a new hotkey works within a second. - A Homebrew tap.
Changed
- Web search is off by default. claude may search and fetch only when
the Web search setting is on. Turn it on in Settings, orweb = onin
the config file.brew install beatzball/tap/swoop, and on a Mac
brew services start swoopruns the frame at login. The formula is
written byscripts/tap-formulafrom a release's checksums, and the
release workflow pushes it to the tap when it has a token for it.
Fixed
- ollama answers are clean.
ollama runwrapped words with cursor
moves even through a pipe, and a thinking model's reasoning came out
as the answer. The ollama line now runs with--nowordwrap,
--hidethinkingand--think=false, escape codes are stripped from
what any command prints, and with web search on and an ollama model
the line under the dots says the model cannot search.
v0.6.1
The renderer as a command, and the watcher put to rest.
Fixed
- The launcher never starts a watcher launchd owns. On a Mac with
the agent installed,swoop-clipd startnow does nothing: launchd
brings its watcher back itself, and one started by the launcher in the
second before it did held the lock from then on. The installer also
waits for launchd's watcher to hold the lock before it starts the
frame.
Added
swoop-md. The transcript's markdown renderer as a command:
markdown on stdin, styled text on stdout,-wfor the width. For
anything else that wants markdown in a terminal.render =in the settings file. Any command can draw the AI
transcript instead of the built-in renderer:render = glow -s dark.
The answer goes to its stdin, its stdout is the pane.
v0.6.0
The frame grows up: a movable divider, a resizable panel, a bird in the
menu bar. And tests for the wiring.
Added
- The divider moves. cmd+[ and cmd+] in the frame, alt+left and
alt+right in a terminal, give the preview or the list 5% more, and the
width is remembered in~/.config/swoop/config, the launcher's own
settings file: onekey = valueper line. - The panel resizes. Drag any edge of the frame; the size is kept in
shell-mac.jsonbeside the font size, and can be typed there too. - A handle on the edge. Bring the mouse near an edge of the panel
and a short bar appears there, a small mark near a corner: the edges
drag. Nothing shows anywhere else. - A bird in the menu bar. Open swoop, Settings, Quit. The one visible
sign the frame is running. - Two end-to-end tests.
scripts/launcher-testdrives the launcher
through a pseudo-terminal: filter, a view and back, the action menu,
Ask AI with a fake model, the divider keys, Enter on a row.
scripts/launchd-testruns the installer's launchd steps against a
fake launchctl and checks the order that keeps a stray watcher from
winning.make e2eandmake test; CI runs both.
Changed
- swoop-ai is half the size. The AI transcript is rendered by
swoop's own markdown renderer on goldmark, in place of glamour, which
brought a code highlighter for every language along: 17.6 MB to
9.3 MB, and 6.4 MB in the release tarball, which is now built with
symbols stripped, as every tool in it is.
Fixed
- The launcher opens on Linux. The app lister answered "not
implemented" as an error there, andbin/swoopstopped before fzf
started. It now answers with no apps, and the extensions' rows show.
Found by the new launcher test on its first Linux run. make installunloads before it kills. A frame killed while its
launchd service was still loaded came back within a second, ran swoop,
and started a clipboard watcher outside launchd, which launchd's own
then gave way to. The installer now unloads both services, waits for
launchd to forget them, then stops what is left, then starts.
v0.5.0
Ask AI: a conversation pane on Tab, fed by whatever command you name.
Fixed
make installleaves one clipboard watcher, launchd's. A watcher
still letting go of its lock made launchd's new one give up, and the
frame's own swoop then started one outside launchd that won forever.
The installer now waits for the old frame and watcher to be gone before
it starts anything.make installstarts the frame the first time. launchd's bootout
returns before the old service is gone, and a bootstrap in that window
was refused, so the frame came up only on a second run. The installer
now waits for the old service to go and tries again if refused.
Fixed
- An answer that never comes says so. A command that ended with
nothing on stdout looked like one still thinking. It is now a red line
under the prompt with the reason: the command's last words on stderr,
or that it printed nothing. While waiting, the dots carry the seconds
and the last thing the command said, which for the defaultclaude -p
is the tool it is using. A worker that dies is reported, not waited
for; five minutes is the most an answer may take.
Changed
- App rows show only the name. The folder is in the preview.
- The preview is wider, 58% of the window, and ctrl-u and ctrl-d
scroll it half a page. - The AI transcript is rendered. Answers are markdown, drawn by
glamour: headings, lists, code, tables. The defaultclaude -pmay now
search and fetch the web, so a question about the weather gets an
answer instead of a refusal.
Added
- Ask AI. Press Tab from anywhere: a pane with your conversations on
the left and the transcript on the right. Enter sends what is in the bar;
dots show under your prompt until the model starts, then the answer
streams in, and each later prompt appends below. ctrl-k on a
conversation offers Copy last answer, Copy conversation, and Delete. Esc
brings the launcher back with the text you had before Tab. The model is
whatever command you name in~/.config/swoop/ai; without that file,
claude -porollama run. The launchd agents now carry the installing
shell's PATH, so the frame finds the same tools your terminal does.