Changelog

What's shipped

Curated for readability here; the full CHANGELOG.md in the repo is the source of truth and updates first.

Unreleased — heading toward v0.7.0

Three more plugins move into sandboxed frames, the app says what an action did in a notification, Debt payoff gains the controls people asked for, and the API gets a rate limit and a cap on concurrent CSV imports. The rate limit is on by default, so a script that calls the API in a loop may now get 429s. There are two new migrations, 034 and 035. Back up your database before upgrading, as for any release. Going back a version means running down twice, and that discards the new Debt payoff settings. See Upgrading.

Added

  • Debt payoff: leave a debt out of the plan. Each debt has an “In plan” switch, saved as soon as you change it. A debt that is switched off stays in your list, marked “Not in plan”, but is left out of the chart, the totals and the debt-free date, so one very large debt, a mortgage say, no longer flattens the rest. The headline says what it leaves out.
  • Debt payoff: an extra amount for one debt. Each debt can have its own monthly extra, paid on top of the shared extra. It stops when that debt is paid off instead of moving to another one.
  • Debt payoff: loans in deferment. A debt can have a repayment start date. Until then no minimum is due, the extra money skips it, and interest keeps adding to its balance. The page says what the loan will owe by then.
  • Debt payoff: promotional rates and deferred interest. A debt can have a promotional rate and the day it ends. With “interest is charged back” ticked, the plan pays the even amount that clears it in time, as far as your monthly payment allows, and says how much interest would be added if it falls short. This is an estimate; check your agreement.
  • Debt payoff: how interest is worked out, per debt. Monthly (as before), compounded daily, or simple daily interest. A debt that uses none of this gets exactly the plan it got before.
  • A limit on concurrent CSV imports. One person importing alone isn’t slowed. When several large files are committed at once, the extras wait for a turn without holding a database connection, for up to 30 seconds by default, and are then refused with a message that says nothing was imported. Sending the same file again imports it once. Measured on a small test machine, ten people importing 50,000 rows each used to make most other requests fail for about 40 seconds; with the limit, none did. See Concurrent imports.
  • For plugin authors: an experimental notification toast in @wickermoney/ui-kit (for the core app only for now), a rowDetail option on Table, a link icon, and two additive messages in the experimental isolated protocol. Nothing was removed. See Writing a plugin.
  • End-to-end tests. A first package of seven smoke specs that drives the built image through a throwaway compose stack. It isn’t part of the regular test run, and the compose stack it uses hasn’t been run under Docker yet.

Changed

  • The API has a per-user rate limit, on by default. Each signed-in user may make 600 requests a minute, 30 CSV import requests and 5 data exports. Someone using the app won’t meet it: a heavy session makes under a seventh of the general limit. A sync, a poller or a script that loops over the API may get 429 rate_limited. Raise API_RATE_LIMIT_MAX, or set API_RATE_LIMIT_ENABLED=false to turn the limit off. The counters are per API process. See API rate limit.
  • Upcoming, Forecast and Debt payoff run in sandboxed frames. Like Insights and Spending Trends since v0.6.0, they no longer share the app’s page or your session, and read through the app with only their own grants. They look and behave as before. Only Budgets and Import CSV still run in the app’s own page. The sandbox has the same known gaps and still hasn’t been independently reviewed. See How much a plugin is trusted.
  • Dashboard widgets in frames start when you scroll to them. A card that runs in a frame loads once it is within about 600 pixels of the window. Frames in the first screen load as before. Find in page and printing only see the cards that have started.
  • The app says what an action did in a notification. On Transactions, Recurring, Accounts, Categories and Settings, a result such as “Deleted ‘Coffee’ (-$4.50).” stays at the top of the page until you close it. There is no Undo, and nothing closes itself. See Notifications.
  • The Transactions recurring column is quieter. A matched row shows its recurring item as a pill with an Unmatch button. A new Link button on each row opens a list under it with the suggestion, the other items it could be, and the ones you dismissed.

Fixed

  • A hovered primary button keeps its colours. It used to turn light grey under its light text.
  • Phone layout: text buttons in the Transactions recurring column no longer overlap their neighbours.
  • Erase my data and a write in flight. A write that was open when the erase started could commit afterwards and leave a row. The erase now waits for open writes. A request that had already passed its session check can still leave one row, which the next erase removes.
  • pnpm dev and plugin frames. Widgets in frames failed to start in development, and pnpm dev failed on Windows with EPERM. Both are fixed; the dev server now serves the frame through the API.

Migrations

Two new migrations, so an upgrade runs two more steps. Going back is down twice.

  • 034 adds an “In plan” switch and an extra amount to each debt. Every existing debt stays in the plan with no extra.
  • 035 adds the repayment start date, the promotional rate and its options, and the interest option to each debt, each with a default that keeps today’s behaviour. Its down, like 034’s, discards what you set in the new columns.

v0.6.1 — owner confirmation and a table that fits

2026-10-23

A small patch on v0.6.0. An owner is asked to confirm before a third-party plugin is switched on, the Transactions table fits narrower windows, the browser console and DevTools stop warning about the plugin frame, and one more row-level security policy gets the per-statement user lookup. There is one new migration, 033, which changes no access. Back up your database before upgrading, as for any release. See Upgrading.

Added

  • Switching on a third-party plugin asks first. In Settings, an owner now sees a confirmation before a plugin that is not bundled goes on. It names the origin the plugin loads from and the tables it is granted, and repeats that it runs in a sandboxed frame, has no server-side code and can send what it reads to another server through the sandbox’s known gaps. Bundled plugins and switching a plugin off do not ask. The question is in the Settings page only: a request sent straight to the API does not ask.
  • An additive API change in a patch release. The owner plugin list (GET /api/v1/plugins/registry) now returns origin and tables on each plugin. Nothing else in the response changed. See the API reference.

Changed

  • The Transactions table fits the room it has. From the phone layout up, the date never wraps, the Edit and Delete buttons are always in view, and neither the table nor the page scrolls sideways. With less room, each row becomes three lines with the buttons in a column beside them. Every column is still there, in the same order.

Fixed

  • No more Origin-Agent-Cluster warnings in the browser console. Chromium logged one for each plugin frame on a dashboard. The API no longer sends the header, and nothing about the frame’s sandbox changes.
  • No more “blocks the use of eval” issues for the plugin frame. Chrome DevTools listed a Content Security Policy violation for the frame on every dashboard. The zod library probes for eval support, the policy refuses it and zod falls back, so nothing broke. The frame now turns the probe off. The policy and the sandbox are unchanged, and the frame still refuses eval.

Migrations

  • 033 rewrites any policy that still calls the tenant lookup once per row so it runs once per statement. It returns the same rows and locks nothing where there is nothing to rewrite. Going back a version is one down, which changes nothing in your data.

v0.6.0 — plugin isolation and owner tooling

2026-10-16

Plugin isolation, owner tooling and a performance and accessibility sweep. Insights and Spending Trends now run in sandboxed frames, the data export asks for your password again, owners can change roles and erase data from Settings, and a debt payoff plugin joins the bundled set. Back up your database before upgrading. This release has four migrations. Going back a version means running down four times, and that deletes the new debt payoff tables and their data. See Upgrading.

Breaking

  • The data export asks for your password. Downloading it from Settings now opens a password dialog. If you call the API directly, GET /settings/export needs a one-use ticket from the new POST /settings/export-ticket (good for two minutes) in an x-wickermoney-export-ticket header; without it, the answer is 403. See the API reference.
  • Plugin authors: @wickermoney/plugin-sdk no longer exports its manifest schemas (pluginManifestSchema and the four smaller ones). To validate a manifest, call parseManifest(input), which returns the manifest or a readable error. See Plugin authoring.
  • CSV import, if you call the API directly: the analyze response is now paged, with a smaller shape. Anything reading it from a script needs a look. The app itself is already updated. See the API reference.

Added

  • Debt payoff plugin. List your loans and cards, pick snowball or avalanche, add an extra monthly amount, and see the date you’ll be debt free and the interest it saves against paying only the minimums. A dashboard widget shows the date and the next debt in line. See Debt payoff.
  • Owners can change roles in Settings → People. Promote a member to a second owner, or step an owner down. The last owner can’t be demoted. No more SQL. See Owners and members.
  • A danger zone in Settings. “Erase my data” deletes everything you own across the app and every plugin, and keeps your login so you can sign straight back in to an empty account. For an owner, “Erase this entire instance” empties every account and starts the instance over. Each asks for your password and a typed phrase, and offers the data export first. See Erasing your data.
  • Database and import settings. DB_POOL_MAX, DB_STATEMENT_TIMEOUT and DB_LONG_STATEMENT_TIMEOUT tune the connection pool and how long a query may run, and IMPORT_MAX_ROWS raises the CSV import row limit from a fixed 50,000 to a default of 100,000. There is also a note on running behind PgBouncer. See Configuration.
  • Plugins can run in a sandboxed frame. Insights and Spending Trends now do: they can’t reach your session, cookies or the page, and they get data only through the app, with a short-lived token that carries just the plugin’s grants. The other five bundled plugins still run in the app’s own page. A test suite that attacks the sandbox runs on every pull request. The sandbox has known gaps (in Chromium it doesn’t stop prerender or WebRTC requests, so a plugin you can grant your transactions to could send them out), and it is experimental and not yet independently reviewed. See Plugins.
  • An operator can add a third-party UI plugin by hand. Set PLUGIN_REMOTE_ORIGINS and put a manifest with an integrity pin in PLUGIN_MANIFEST_DIR; it starts switched off and runs only in a frame, with no server code. Both settings are empty by default, and there is no install flow or catalog. See Adding a third-party plugin.
  • Plugin SDK: a stable @wickermoney/plugin-sdk/date entry point for the calendar helpers, an experimental /isolated entry point for plugins that run in a frame, and an optional integrity pin on the manifest. A manifest that declares network:outbound, schedule:daily or notify is now refused, since the app implements none of them.
  • Smaller API additions: ?fields=basic on the account list, accountName on upcoming recurring items, and truncated flags on recurring matching.

Changed

  • The server compresses its own responses (brotli or gzip). If you run a reverse proxy that also compresses, turn that off for this upstream. See Configuration.
  • Faster pages. Core pages load when you first visit them, the Transactions page re-renders less, and Budgets and recurring matching read the ledger fewer times. Sorting the ledger by merchant or amount is backed by new indexes; on a very large ledger, building them can briefly block writes during the upgrade.
  • Plainer trust wording. The docs, SECURITY.md and the changelog now say what the sandbox protects and what it doesn’t. See Plugins.
  • Frames cost a little. Each sandboxed widget adds roughly 6 to 9 MiB and 150 ms after the first.
  • The image has no :next tag. A release candidate is published under its version tag only. :latest is stable releases only, as before.

Fixed

  • Keyboard and screen reader fixes: focus stays inside the setup wizard and the phone navigation drawer, chart marks are exposed to assistive technology, the forecast’s day readout is announced, table headers have scopes, the account menu is a plain disclosure, and the plugin switch announces “Saving…”. Charts gain a “Show as table” view. These haven’t been checked with a screen reader yet.
  • Light-mode green has more contrast for positive amounts.

v0.5.0 — a sturdier plugin platform

2026-10-10

Plugin platform hardening, plus account allowances. The theme is getting the plugin foundations right before more plugins are built on them: one shared contract for plugin server code, labelled stability for the plugin SDK, fewer duplicate requests, a way to name the instance’s owner up front, and plainer wording about what a plugin is trusted to do. There is no breaking change for plugin authors. Back up your database before upgrading. Both of this release’s database changes can be undone, so going back to 0.4.2 doesn’t need the backup, but it’s still the safe habit.

Added

  • Name your owner. Set BOOTSTRAP_OWNER_EMAIL and only the account registered with that address becomes the instance’s owner, even if someone else signed up first. Left unset, nothing changes: the first account is the owner. Email addresses aren’t verified, so register your own account promptly, then close registration. See Owners and members.
  • Account allowances. Say “$150 a month goes into this checking account to spend on whatever” and see how much of it is left. Everything that leaves the account counts, except transfers, income and the categories you choose (holiday gifts, say, which keep a budget window of their own). What you didn’t spend rolls into next month, and an overspend carries forward. See Budget account allowances.
  • One server contract for plugins. @wickermoney/plugin-sdk/server holds the types and helpers a plugin’s server code is built on, in one place instead of a copy in each plugin. Nothing already published changed.
  • Stability labels for the plugin SDK. Each entry point is now marked stable or experimental, so plugin authors know what can change under them. Only the recurring-items date maths is experimental, and nothing was removed from it. Two calendar helpers, addDays and addMonths, are now exported from it, replacing the copies the app carried. See Stability tiers.

Changed

  • Add and edit forms open in a dialog. On Accounts, Categories and Recurring, “Add account”, “Add category”, “Add rule” and “Add recurring item” are buttons in the page header, so the tables get the full width. They open in the same dialog Transactions uses: a side drawer on a computer, a full-screen sheet on a phone.
  • The dashboard asks once. Widgets that need the same numbers now share one request instead of each making their own, with no change to any plugin.
  • Recurring matches load faster. The Transactions page reads the data behind its recurring-item matches once instead of twice, with the same results.
  • Plainer security wording. The docs now say directly that a plugin’s screens run fully trusted inside the app, and that the database role limiting a bundled plugin’s queries is a guardrail against honest mistakes, not a sandbox. That is why installing third-party plugins isn’t supported yet. Nothing about how plugins behave changed.
  • A startup warning. A new instance with open registration and no BOOTSTRAP_OWNER_EMAIL logs a reminder that the first person to register becomes its owner.

Fixed

  • The search box, date pickers and buttons on the Transactions filter row now line up.

v0.4.2 — made for phones

2026-10-06

Wicker Money now works on a phone, with tidier lists everywhere and a round of accessibility fixes. No database changes, so upgrading is a pull and a restart, and going back to 0.4.1 is just running the old image.

Check your passwords first. From this release, an instance whose AUTH_SECRET or app database password is still a placeholder such as change-me or CHANGE_ME refuses to start, because a known secret lets anyone forge a sign-in. If you generated real values, as the quickstart says to, nothing changes. If not, the self-hosting docs have the two-minute fix.

Added

  • A menu for small screens. On a phone the sidebar becomes a drawer you open from a menu button.
  • Cards instead of wide tables. Transactions, Accounts, Recurring and Categories show one card per row on a phone, so nothing scrolls sideways.
  • Collapsible Categories and Rules. Parent categories open and close, with a count of what’s inside, and rules are grouped by category. A parent opens by itself when you add something under it.
  • Icon buttons for row actions. Edit, delete, archive and the rest are small labelled icons that stay on one line.
  • Skip to content, and a title for every page. Keyboard and screen reader users get a skip link and a browser tab title that says which page they’re on, and focus moves to the page after you navigate.

Changed

  • The budget breakdown on the dashboard fills one column to the card’s height before starting a second, instead of leaving a blank card.
  • Charts on Insights and Spending trends are drawn at the width they’re shown at, so their labels are readable on a phone.
  • The warning colour is darker in light mode so it’s easier to read.

Fixed

  • Matching a payment to a recurring item no longer misses recent transactions on a long history.
  • The Transactions page loads faster when everything on the page is already matched.
  • Hovering a bar on the Spending trends chart no longer redraws the whole chart.

v0.4.1 — two new starter categories

2026-10-05

Two more categories in the starter set. No database changes, so upgrading is a pull and a restart, and going back to 0.4.0 is just running the old image.

Added

  • Memberships. A new category under Subscriptions, for the store and shopping memberships that don’t fit streaming or software: Costco, Amazon Prime and the like. It’s in everyone’s starter set.
  • Domains / web hosting. A new category under Technology, added when you tick the setup question about smart home, networking, gaming or web hosting (the question now mentions hosting).

Already set up? These aren’t added to an existing account on their own. Open Categories → Run setup again and finish the wizard: it adds only what’s missing and leaves every category you already have as it is.

v0.4.0 — plugins you can turn on and off

2026-10-04

Pick the plugins your instance runs, match payments straight from your transactions, and see form mistakes right where you made them. Back up your database before upgrading. Both of this release’s database changes can be undone, so going back to 0.3.0 doesn’t need the backup, but it’s still the safe habit.

If more than one person signed up on your instance before this release, read this: from now on only the first account is the instance’s owner, and everyone who signs up later is a member. Existing accounts keep the role they had, and before this release that was always owner. The self-hosting docs show how to check and change it.

Added

  • Turn plugins on and off. Settings → Plugins lists every plugin, what it adds, and whether it’s on. The instance’s owner can switch any of them on or off, and the change shows up straight away, no reload. Turning a plugin off deletes nothing: turn it back on and everything is where you left it. Plugins that do similar jobs, such as two ways of budgeting, can run side by side.
  • Owners and members. The first account is the owner, the only one who can change which plugins are on. Everyone else uses the app as normal, with their own data.
  • Match from the Transactions page. A Recurring column shows which recurring item each transaction paid, suggests one to confirm with a click, or lets you pick another.
  • “Not this.” Dismiss a suggested match you know is wrong and it won’t come back. Changed your mind? Undo.
  • Errors where you’ll see them. Every form now checks what it can before sending, and shows each problem under the field it’s about, in plain sentences, instead of in a message at the top of the page.

Changed

  • The Transactions pager shows “Page 3 of 25” once it knows the total.
  • Building from source needs a newer Node.js (22.22.2 or 24.15 and up). The container image is unaffected.

Fixed

  • “Only uncategorized” no longer lists transfers between your own accounts, which can’t take a category, so an empty list now means everything is filed.
  • Dark mode no longer flashes white on every page load.

v0.3.0 — did it land?

2026-10-03

Tell Wicker Money when a paycheck or bill actually posts, and it stops counting it as still to come. Plus budgets that cover a stretch of time instead of a single month. Back up your database before upgrading: going back to 0.2.1 means restoring that backup. Needs PostgreSQL 15 or later; 16 was already the minimum.

Added

  • Did these land? Match a transaction to the recurring item it paid, and Until payday and the forecast stop counting it twice. A paycheck that lands a day early is no longer counted again on payday. The Recurring page suggests likely matches; nothing is matched until you click.
  • One-off changes. Skip one month’s bill, move one paycheck to another day, or change one occurrence’s amount, without touching the rest of the series. Each item’s History shows its recent and coming dates and what paid each one.
  • Late payments. Once you’ve matched an item, a payment that hasn’t shown up within a week of its date is flagged late and still counted, so a delayed paycheck doesn’t make your outlook look better than it is. Items you never match work exactly as before.
  • Budget windows. One amount for one category across a date range, spent down to zero, like holiday gifts from October 1 to December 25. You see “spent so far of funded” for the whole window, and bunched-up spending is expected, so it never gets flagged as at risk.
  • For plugin authors: one shared, exact money module in the SDK.

Changed

  • A budget amount with more than four decimal places is now refused instead of quietly cut short.

v0.2.1 — the forecast

2026-10-02

See where an account is heading, not just where it is. No database changes, so upgrading from 0.2.0 is a pull and a restart. Afterwards, open Settings → Time zone.

Added

  • Forecast. A new page that projects one account’s balance day by day from your recurring items: 30, 60 or 90 days, 6 months, or to the end of the year. It shows zero and your cushion as lines, names the first day the balance would dip below either, and lists what moves the line. Bills on payday are drawn before the paycheck, so a tight day shows as the dip it is. It covers your recurring items, not everyday spending, and says so.
  • Your time zone. Set it under Settings, so “today” turns over at your midnight, not UTC’s. New accounts pick up your browser’s time zone when you sign up.

Fixed

  • The Recurring page and Until payday no longer roll over to tomorrow in the evening once your time zone is set.

v0.2.0 — recurring items and Until payday

2026-10-02

Tell Wicker Money what you expect to come in and go out, and it tells you whether you’ll make it to payday. Back up your database before upgrading: this release reshapes how recurring items are stored, and going back to 0.1.0 means restoring that backup.

Added

  • Recurring items. A Recurring page for your paychecks, bills, card and loan payments, and transfers between your own accounts. Each one shows when it’s next due, in plain words (“Every 2 weeks”), and the page totals what comes in, what goes out and what’s left each month. A paycheck split across two accounts is one item, not two.
  • Until payday. A dashboard widget that answers “will I make it?”: how much is safe to spend before your next paycheck, each checking account’s lowest point before then, and a warning naming any account that would drop below the cushion you set for it. One account’s extra money is never quietly counted against another account’s shortfall, because your bank doesn’t do that either.
  • Choose what counts as spendable. Pick which accounts count toward “safe to spend”, and set each account’s cushion (its buffer), on the Accounts page.
  • Deleting or merging an account now tells you which recurring items it affects, and what will happen to each, before anything changes.

Fixed

  • Plugins showed dates a day early for anyone west of UTC.

Known limitation

  • “Today” followed UTC, so in the evening in the Americas the Recurring page and the widget had already moved on to tomorrow. Fixed in 0.2.1.

v0.1.0 — the first release

2026-09-28

The first tagged release: everything you need to run Wicker Money on your own server, import your history and see where your money goes. Curated from the repo’s own CHANGELOG.md.

Added

  • Ready to self-host. A step-by-step quickstart, a published container image (amd64 and arm64) that serves the whole app on a single port, and a light, dark or system theme.
  • Import and categorization. CSV import with saved column mapping per source, an explicit date format with a live parse preview, duplicate detection and batch undo. A categories page with rules — previewed before a rule touches anything — and triage on the Transactions page.
  • The shell and the first plugins. Sign-in, navigation and a dashboard fed entirely by plugins. Each plugin gets its own database role, limited to the tables it says it needs.
  • Accounts and the ledger. Accounts, categories, category rules, transactions and splits, with every user’s data kept apart by the database itself. Account balances are worked out from your transactions, never stored separately.
  • A budgets plugin with per-category budgets, and leftover money that can roll over line by line.
  • The plugin SDK and UI kit, published to npm, for anyone building a plugin.

Security

  • Closed a hole where one user’s transaction could have been attached to another user’s account.