Releases: estruyf/tideline
Release list
v1.13.0
Changed
-
Routing rules is a list you can read. The pane's whole model is that rules
are tried top down and the first match wins, and none of that was visible: no
numbers, no order to change, and a subtitle that said "No tests yet — nothing
will match" on a rule that had one. Every row now carries its number, the rule
in one line of words —name contains invoice, or download URL contains stripe.com— the folder it sends things to, and how many files that is right
now. Rows drag, because the order is the decision.The count is what the rule would actually get, not what its conditions
describe: a file a rule above it already claimed belongs to that rule, and a
list of overlapping rules all reporting the same file would be worse than no
count at all. Which is also how a rule that can never fire now says so —
Never fires — Invoices catches all 15 of these first, with a button that
moves it above the rule taking them. -
A rule is edited in a form, not in the list. The editor used to be spliced
into the same list as Add a rule, four lines apart and at the same indent.
It is now a form under the row it belongs to: the destination named as a
destination and spelled out as a path,~/Downloads/Invoices/ · exists, 41 items, so it is never a wide empty box called "Folder name". Below it, the
files the rule is matching right this second, each with the condition that
claimed it — which is how a pattern that catches too much gets noticed before
it files anything. -
Conditions are said in words. A condition is now a field, an operator and
what to look for — Name · contains · invoice — instead of a pattern you had
to know the star grammar to write. Nothing changed underneath:contains
still saves*invoice*, and matches pattern is there for anything the four
operators cannot say. Aa is a labelled Match case checkbox, since a
glyph that says nothing aloud said nothing on screen either. -
Catching up is per rule. It used to be one disabled button at the bottom
of the pane, as far from any rule as it could be. It is now on the rule, with
the number attached — 12 filed by date — catch up… — because that is the
rule the number belongs to. -
The settings panes are the theme's cards now, not the system's. Schedule,
Filing, Type folders, Clearing, Activity log and General were the last panes
built out ofForm { Section }, and a groupedSectioncannot be handed a
background — so while Overview, Reclaim space and Routing rules sat in
#202736, those six sat in whatever grey macOS drew, on the theme's own
ground. They are built out ofListPanelnow, like every other pane, with
SettingsToggleandSettingsFieldfor the rows so a switch and a popup
describe themselves the same way. Nothing moved and nothing was renamed; the
surfaces just belong to the app. -
Text fields are the theme's, everywhere in the window.
.roundedBorder
draws the system control background, which was one of the last surfaces the
palette never reached — every field sat in a grey the theme does not own, on
cards it does.themedField()is the recipe the Move out search box had
already built by hand, named so the next field does not have to build it
again: the pane colour recessed into the card, the theme's own hairline, and
the accent while it has the keyboard. Every field in Filing, Type folders,
Routing rules and Move out now uses it.
Added
-
A rule can need every condition to agree.
Catch a file when [any|all] of these is true.anyis what a rule has always meant and stays the default;
allsays "an invoice and from Stripe" in one rule instead of splitting
it into two that cannot express it either. A condition nobody filled in is
dropped before the question is asked, so a half-written row never switches a
rule off. Both engines implement it, andfixtures/sweep-cases.jsonholds the
cases. -
A rule can have a name of its own, separate from the folder it files into.
Two rules can legitimately share a folder — receipts from Stripe and receipts
from the bank — and a list showing both asReceiptscannot be reordered with
any confidence. A rule without one is still known by its folder.
Fixed
-
A rule's form no longer moves under you while you fill it in. Counting was
triggered by any change to the rules at all, so typing a rule's name walked
the root and every dated folder on a beat behind every letter, and the preview
list — and everything below it — took a fresh height each time. It now watches
what a count actually depends on: which rules are on, in what order, and what
each of them asks. Names are not part of that.Clicking into Rule name was enough on its own: taking focus writes the
field's value straight back, so a rule that had only ever been known by its
folder gained a title of the same words, which counted as a change to the
rules. It doesn't any more. The destination line still follows the folder
being typed — it asks about that one folder rather than riding along with the
count.
1.12.1
Added
-
A disk image beside the zip. The manual download is now
Tideline-<version>-macos-universal.dmg: a window with the app on the left,
the Applications folder on the right, and an arrow between them. Dragging it
across is the whole install, and there is no unpacking step to get wrong —
which also retires the oldest support question, the zip inside a zip that
comes off the Actions page instead of the release.It is also the first place there is room to say the thing a zip cannot:
Tideline runs in the menu bar and has no Dock icon. That is the first question
anybody has after installing it, and now it is answered before they ask.The zip stays, and stays the asset the in-app updater fetches. An update
should be a file the app can unpack on its own rather than a volume it has to
mount, so the two downloads exist for two different readers. Homebrew keeps
reading the zip as well.
1.12.0
Added
-
Routing rules: folders that claim a file by its name, or by where it came
from. A type folder asks what a file is, which settles a.dmgand
settles nothing about an invoice — an invoice is a PDF like every other PDF.
A routing rule is a folder and a list of conditions, and any one of them
matching is enough:name *invoice*, ordownloaded from *stripe*.The second one is the interesting half. macOS records the URL a download
arrived from and keeps it when the file is moved, so a rule can still
recognise something you renamed by hand, and a rule written today matches what
arrived last month. Windows keeps the same thing in theZone.Identifier
stream, so both apps read it. The whole URL is matched, not just the host, and
it is unescaped first — a receipt fromlogitech.comsays what it is only in
its path, and a Stripe invoice arrives from an S3 bucket that mentions neither.Rules are tried before the type folders, top down, first match wins.
OtherwiseDocumentswould swallow an invoice beforeInvoicesever saw it.
Like a type folder, a rule decides where a file goes and never when: it
still waits out the window set under Filing.Conditions ignore case unless you say otherwise, which the skip list does not.
A skip pattern names a file you can see in the folder; a rule is a hunt for a
word that could have been typed either way, and a rule that quietly stops
matching is not something anybody notices. -
Move out: finding things and taking them out of Downloads altogether. The
quarter's invoices into the accounts, a shoot onto an external drive. It never
runs on its own — you say what to look for, the app says what it found and
which condition found it, and only what you tick actually moves.It searches Downloads and every folder Tideline has filed, which is what
makes a rule retroactive: a search written today reaches the invoices already
sitting in2026-07-02/. Filing alone can never do that, because a sweep only
ever sees what is loose in the root.A destination is remembered as a bookmark rather than a path, so it survives
the folder above it being renamed, and it can carry a template —
{yyyy}/kwartaal {q}/in. The tokens fill in from each file's own date, so a
batch that straddles the end of a quarter lands in two folders, which is the
answer the accounting wanted.This is the one thing in the app that writes outside the folder it watches, so
a whole batch is recorded as one and Put Back returns it — each file to
the folder it came from, under the same collision rules as everything else. -
Catching up covers routing rules too. Catch Up… already pulled files out
of the dated folders when a type folder was switched on; it now does the same
for a rule you have just written. -
Move Out… in the menu bar, beside the Reclaim space reviews. Like them it
finds things and asks; unlike a sweep it never acts on its own.
Changed
-
Nothing in the window is smaller than 12pt. Explanatory text — the
sentence under a heading, the note beside a control — was two steps down from
body, at the size meant for a number in a column. A pane of it read as small
before it read as anything else. Sizes that were doing real work as small
text, tallies and per-row dates among them, came up with it, and the columns
cut to fit the old size were widened to match. -
Catch Up… stays on the pane you asked from. Asking from Routing rules
jumped the window to Type folders before opening the sheet. It acts on both
kinds of rule, so neither pane is more its home than the other.
v1.11.2
v1.11.1
This release needs macOS 14 or later. If you are on macOS 13, do not install it — stay on 1.7.0. Tideline's updater still does not check the version of macOS you are running, so it will offer you this update anyway, and the app will not open once it has swapped itself in.
A download named after a date now matches its own copies.
The day of the month was being counted as a copy
The duplicate review reads a trailing -14 as a copy count, which is right for report-14.pdf and wrong for notes-2026-02-14.pdf, where it is the day of the month. Reading the day as a count split the name down the middle: notes-2026-02-14.pdf reduced to notes-2026-02 while notes-2026-02-14 (1).pdf reduced to notes-2026-02-14. The original and its copies landed in different groups, so the one file that could have kept its plain name was the one left out of the group.
A name that ends in a date now keeps the whole date. Only the shapes a copy count could never take are read that way: the month and the day have to be real, so report-2026-14.pdf is still the fourteenth copy rather than the fourteenth month, and both have to be padded to two digits, because nothing that writes a copy pads its number — report-2024-1.pdf is the copy of report-2024.pdf it looks like.
A copy of a dated name still counts as one: notes-2026-02-14-1.pdf is copy one.
v1.11.0
This release needs macOS 14 or later. If you are on macOS 13, do not install it — stay on 1.7.0. Tideline's updater still does not check the version of macOS you are running, so it will offer you this update anyway, and the app will not open once it has swapped itself in.
The duplicate review keeps the copy it should, and every row in it opens in Finder.
It kept the wrong copy
A group could keep report (9).json while report (10).json sat below it, ticked for the Trash.
The sheet ordered a group by "date added" alone, down to the microsecond. Copies that arrived together — ten written in a row, a folder restored from a backup, a synced folder landing at once — are microseconds apart in whatever order the copying happened to walk them, which is usually alphabetical, and that is what puts (10) between (1) and (2). Sub-second order is a record of what moved the files, not of when they were downloaded.
Copies are now ordered by day, and within a day by the copy suffix, which is the downloader's own count: (10) exists only because (9) was already there, and a name with no suffix came before either. Days apart still separate first, so a file downloaded again today still beats the copy left over from January.
The list also comes out in the same order every time it is scanned, which it did not before — the old sort was not stable, so a group whose copies shared a timestamp could reshuffle between scans.
Opening a copy in Finder
The magnifier at the end of a row, and Show in Finder on a right-click, the same as the large-file review has had. The copies in a group are byte-for-byte the same, so this is never about which one to keep — it is about seeing what the thing actually is before agreeing that nine of them can go.
The type-folder fields name themselves
The folder name and extensions fields carried their example as their placeholder, which is also what VoiceOver read out — so the field for a folder's name announced itself as "Installers". They now have a label of their own, hidden because the row beside them already says it, and a placeholder that describes what to type rather than standing in for one particular answer.
Why there is no 1.10.0
This release was cut as 1.10.0 first. Publishing it with GitHub's immutable releases briefly switched on burned that tag: the setting keeps its record after it is turned off and the release is deleted, so v1.10.0 can never be created again. Nothing of it reached anyone. This is that release, renumbered.
1.9.0
This release needs macOS 14 or later. If you are on macOS 13, do not install it — stay on 1.7.0. Tideline's updater still does not check the version of macOS you are running, so it will offer you this update anyway, and the app will not open once it has swapped itself in.
Tideline asks before it does anything to your Downloads folder, and it can put everything it filed back where it found it.
Tideline asks before it does anything
A fresh install used to open with a macOS permission alert already on top of the window, and to be filing within seconds of that being answered — a system prompt before the app had introduced itself, and a folder rearranged before anyone had agreed that it should be.
It now opens on the window, and on the question. Allow Access… is what raises the macOS prompt, at a moment you chose and after the sheet has said what the permission is for and how far it reaches. Until it is pressed the folder is not read at all: not swept, not measured, not scanned. Granting it is still not starting — what it buys is the sheet being able to tell you what a first sweep would actually do to the folder as it stands right now: 143 items would move into 12 folders, 4 stay loose. Then the rule it would follow, and two buttons. Nothing is swept until Start Filing is pressed: not on launch, not when the folder changes, not on the daily timer. Not Yet leaves everything exactly where it is, and the question is on the Overview pane and in the menu bar for whenever you are ready.
An install that predates all this has been filing for weeks and is left alone — an update is no reason to stop and ask.
Put Everything Back
Filing was the one thing the app did that you could not undo with a single gesture: a year of downloads spread across a hundred folders is not something anyone drags back by hand. Filing › Putting it back lists everything Tideline ever filed, grouped by the folder it would come out of, all of it ticked — untick what you would rather leave filed, then put the rest back into the root. The folders it empties go to the Trash, type folders included: an empty Installers/ is not something your Downloads folder had before Tideline, so putting things back puts that back as well. The usual rules hold — a name already taken counts up to report-1.pdf, folders you made yourself are never opened, nothing is deleted, and preview mode previews it.
Filing switches off once a real restore finishes. The next sweep would move back exactly what was just taken out, and that is not an argument worth having with your own downloads folder. The switch in the header starts it again.
Tideline installs with Homebrew
brew install --cask estruyf/tap/tideline
It fetches the same signed and notarized build this page hands out and puts it in /Applications — the download, the unzip and the drag, done by the thing a lot of people already reach for first.
It knows the app updates itself, so brew upgrade does not reinstall over a copy Tideline may have already replaced; brew upgrade --greedy hands the job back to Homebrew for anyone who would rather it worked that way. It knows the app needs macOS 14, which the in-app updater does not, so nobody installs a bundle that will not launch. And brew uninstall --cask --zap tideline removes the same three files the Uninstall sheet names.
Opening the app shows the window again
Tideline decided whether a launch was a login item by looking for an XPC_SERVICE_NAME in its environment, on the theory that only launchd sets one. Launch Services sets one too, for every app it starts, so from the second launch onwards every double-click looked like a login launch and the app started into the menu bar with no window at all — the only way back in was the menu bar icon.
It now reads the flag the launch notification actually carries for this, so opening the app from Finder, the Dock or Launchpad puts the window on screen, while a login item still starts with no window and no Dock icon. Closing the window is unchanged: the app stays in the menu bar and keeps filing. Each launch says which it was in the log file, so a report of "no window appeared" has something to stand on.
A refused permission is no longer a dead end
macOS asks about a protected folder once and never again, so a prompt answered with Don't Allow — or dismissed by accident — left the app with no way to ask a second time, and the banner could only point at System Settings and suggest a restart. It now offers Choose Downloads Folder… as well: picking the folder yourself grants the same permission, on the spot, without a trip through System Settings or a relaunch. It doubles as the fix for a watched folder that has been moved or deleted, since whatever you choose becomes the folder Tideline watches.
The window says so too. Waving away the welcome sheet without granting the permission left a window that could not explain itself: the status card said Paused, the folder card said nothing was there, and no control anywhere would ask macOS. The banner across the top now covers that state as well as a refusal — a lock rather than a warning triangle, since not having asked is not a fault — and carries the one button that raises the prompt. The status card leads with it too: what is blocking filing outranks whether filing is switched on, so it reads Waiting for permission and its button asks rather than files.
The sheets are the same window now
Every review sheet — duplicates, large files, old folders, catching up, putting things back, the preview and the uninstall steps — was drawn on the system's own window grey while the window behind it was the app's near-black. The palette reached the accents inside them and nothing else, so a sheet read as a panel macOS had put on top of Tideline rather than a part of it. They now use the same surfaces the window does, and the accent goes across with them: every confirming button and every tick box in a review came up in the system blue, and they are the app's yellow now.
The Overview pane fills the window again, too — the card listing the folder stretches to the height it is given, so an empty folder reads as three cards rather than three cards adrift in a void.
Install: download Tideline-1.9.0-macos-universal.zip below, unzip it, and drag Tideline to /Applications — or brew install --cask estruyf/tap/tideline. The build is signed and notarized.
1.8.0
This release needs macOS 14 or later. If you are on macOS 13, do not install it — stay on 1.7.0. Tideline's updater does not yet check the version of macOS you are running, so it will offer you this update anyway, and the app will not open once it has swapped itself in.
The menu bar menu folds its reviews and its housekeeping into two submenus, and the version, the folder total and a waiting update now sit as badges on the rows they belong to.
The reviews live under Reclaim space
Review Duplicates…, Review Large Files… and Review Old Folders… sat in the menu as three flat rows, each asking to be read one at a time. They are now Duplicates, Large files and Old dated folders under Reclaim space — what the window has called them all along — with Review All in Tideline… at the foot, which is still the one that goes and looks.
The submenu quotes no figures. Opening a menu never starts a scan, so any count it showed would be as old as the last time the window was open, and a stale number is worse than no number.
Help & Updates, with a badge
Send Feedback… and Check for Updates… moved the same way, into Help & Updates, which now also carries Tideline on GitHub — nowhere in the menu bar before. The submenu wears a badge when a new version is waiting, so the news is visible without opening it.
The state row gained the window's own dot — green watching, yellow filing, red for no access — and Open Downloads Folder gained ⌘D.
Why macOS 14
The version, the folder size and the update count sit on the trailing edge of their rows as NSMenuItem.badge, which arrived in macOS 14. On 13 the same layout would have meant hand-drawn menu rows, which cost more than the one version is worth.
1.7.0
Tideline can tell you about a new version without the window being open, and Reclaim space no longer quotes a folder total it cannot stand behind.
A notification when a new version is out
The daily check already said so in the window and the menu bar, which is no use with the window shut. Notify me when a new version is out sits under Updates in General, next to the switch that decides whether the check happens at all, and it is on by default — an update nobody hears about is the same as no update.
It goes out once per version: a release sits there for weeks, and the same news every morning is not news. It is only ever a notice. Nothing is downloaded or installed by it, and it never raises a permission prompt of its own — finding an update is not a reason to ask — so it appears where you have already allowed Tideline to notify you.
The folder total says what it knows
Measuring the folder stops after 60,000 items and reports what it reached as a floor, while the three scans that add up to what could go are not bounded the same way. On a folder big enough to hit that cap, the amount that could be freed can come out larger than the total it is quoted against — 11,55 GB of more than 10,66 GB, which reads as a fault rather than as the two different measurements it is.
Past the cap the line now says how many items are in the way and offers Scan the folder in full, which walks every file — the same reading walk, only allowed to finish — and puts the real total in place of the floor. It is asked for rather than done every time because on a folder holding hundreds of thousands of items it is slow; once asked, it holds for the rest of the session, so the next sweep does not quietly measure the floor back.
v1.6.0
The window has been rebuilt around a sidebar, and everything that could give space back now sits on one pane.
Reclaim space
Duplicates, big files and old dated folders were spread over Filing and Clearing — which is where their settings belong, but not where the question belongs. All three answer "how much of this could go?", so they now share a pane, each showing what it found and the top few rows of it.
Could be freed, at the top, adds the three up. They overlap — a big file can sit inside a folder old enough to clear, and a duplicate copy can be both — so each byte is counted once, by the widest thing that would take it.
Big files and old dated folders are found by reading names, sizes and dates, so they now run when the window opens and the answer is already there when you arrive. Duplicates keep their button: matching copies means reading the candidates end to end, and that is not something to start behind your back.
Nothing about what moves, or where, or when has changed. The scans still only read, and everything you tick still goes to the Trash.
A sidebar instead of five tabs
Overview and Reclaim space at the top, the four rules that decide what happens — Schedule, Filing, Type folders, Clearing — grouped under a heading, then the activity log and the general settings. Five tabs had reached the point where Filing held four unrelated things at once.
The header shrank to a band: the app's name, what it does in a line, and the on/off switch. The foot of the sidebar says which folder all of this is about and what it is holding, whichever pane is open.
Overview shows the folder as it stands
It used to draw a sketch of a tidy Downloads folder — the right idea with the wrong contents, since it was the same picture whatever was actually in there. It is now the real listing: the type folders, the dated folders newest first, then whatever is still loose. What it marks as due comes from the same planner a sweep uses, so the panel and a sweep cannot disagree about a file.
Beside it, Waiting for you says how much could go and links straight into the review that deals with it.
A palette of its own
#ffd43b is the accent now, taken from the Demo Time theme along with the surfaces around it. Colour means something again rather than everything urgent being orange: the accent marks what the app put there and what it is about to touch, red is kept for faults, blue for a button that only navigates, green for running and watching. Every token has a light value and a dark one, so the window still follows the system appearance — what it no longer follows is the system accent colour.
Also
- Open Tideline (⌘O) now sits at the top of the menu bar actions and comes up on whichever pane you left. Settings… keeps ⌘, and earns the name by landing on Filing.
- Open at login moved to the status card on Overview. Filing only happens while Tideline is running, so the switch that decides that belongs next to the thing that shows it.
Install — download Tideline-1.6.0-macos-universal.zip below, unzip it, and drag Tideline.app into /Applications. An installed copy offers this on its own within a day; General › Updates › Check Now asks straight away.
Full Changelog: v1.5.0...v1.6.0