Repository navigation
Releases
v0.6.0
Added
-
retiretui-desktop, a second binary that opens the planner in a window: the
tuicommand's arguments and--lightfor a theme family's light variant,
Inconsolata embedded as its face, a grid of cells the shell lays itself out in
as it does in a terminal, the close button asking whatqasks over an
unsaved draft, and its log indesktop.log. The window shows the shell's
chrome in its own dress - the tabs as text over a baseline, the chosen one
underlined, switched by digit or click, a pill at the row's end switching
between today's and future dollars, the status, the key row two rows tall over
a hairline with its keys in from the edge as far as the tabs, a margin around
the body, each pane's frame inset from its neighbours with its title centred
on a two-row header and what it holds padded in from its line, a pane sized by
what it holds grown by the header so it keeps its rows, the sidebars, toasts,
the message drawer, the dialog and the pickers as sheets with a shadow - the
whole frame dimmed under whichever of them stands highest. No title says the
dollar basis; the switch does. Of the pages, it draws the Ledger: the years
under their headers, the flows, the money panes and the so-far table, each
scrolled on the wheel with a bar beside it, stepped by the keys, a row chosen
by a click and banded under the pointer. It draws the Plan tab's editing
domains the same way: each domain's table with its read-out beside it, a row
opened by a click and a column sorted by a click on its header, and the form
over it - its labels, headings and help, a text field typed into in a box
ringed while it holds the keyboard, a flag ticked by space or a click, a
slider moved by the arrows or a press on its track, a select as a box across
its row with its menu opened over the form and picked from by key or click,
and the buttons as boxes, the primary answer filled - scrolled with a bar as
the terminal's is. It draws what finds and makes a document: the file picker,
its path typed, completed and climbed as in the terminal, its listing scrolled
with the cursor and a row chosen by a double click; the new-plan form; and the
issues panel, scrolled with its cursor. It draws the Overview: a raised card
saying whether the money lasts, its mark on a disc of its colour, how surely
and what the plan rests on first, four more cards - what it ends with, the
least it holds after the last salary, what it spends and what it pays in tax,
each a figure at twice the size under its title and over a line of context -
the three lists, and the chart, picked by name from a pill in its pane's
header, with a row and a cell kept clear around the plot - its labels as text,
its key dotted in each band's colour, its plot through bevy's renderer, ruled
across at each quarter, each band filled deeper than its line under the lines,
the salary's end and zero ruled - read out under the pointer and opening the
Ledger on a click, as in the terminal. Every list the window scrolls shows the
terminal's bar beside it, and the pointer reaches every widget as in the
terminal: what lights up under it lights up, the wheel scrolls any list, and a
press in a text field places its caret and a drag selects. It draws the tools
and Compare: every table - the options a search ranks, the ladder, the people,
the expenses, the assumptions, the years, the proposals, the records, the tax
table and the compared plans - as the Ledger's, the help line under each page,
and the market tools' Ends With view as rows of bars. The window draws every
frame while a search runs and otherwise wakes for input and once a second, for
the file watch, focused or not. Known issue: under niri the window stays blank
while its height in pixels is fractional at the output's scale, as at a scale
of 1.6; fullscreen, or a height the scale divides, draws. -
Releases for Windows and macOS: every release archive holds the
retiretui
command and theretiretui-desktopwindow, the Linux tarballs beside a zip of
the two Windows executables, the window's with its icon, and a zip of a
universalRetireTui.appwith the command, ad-hoc signed. Neither is signed
by a publisher, so the README says what each platform asks on the first open.
Changed
- The app icon is a shell prompt: Inconsolata's dollar beside an amber block
cursor on the terminal's near-black, in the web app's manifest and on the
Windows executable. - A click anywhere in a pane hands it the keyboard: to the widget the click
landed in, or the pane's first. - Lists wrap at their ends and move on Left and Right too, but for a sidebar's
Right, which still goes into the page. A list that loses the keyboard draws no
cursor, and a menu closes when the keyboard leaves it. - The file picker climbs to the parent on
alt+up; left and right move the
caret in its path. - The terminal wears the embedded
githubtheme family by default,
github-lightorgithub-darkas the screen is. The terminal's own colours
are no longer a theme: the picker andretiretui themedo not list
terminal, and a settings file naming it is told so and wears the default. A
theme file states every colour as#rrggbb, and a role it leaves out takes
thegithubfamily's in its variant.
Removed
ctrl+cno longer copies the row under the cursor in any table.- A theme file can no longer name a colour by an ANSI name or palette index, nor
settransparent; one that does is reported as unreadable and the default
family is worn. - A form taller than the body scrolls on a wheel tick over any of its fields,
not only as the keyboard moves between them.
v0.5.0
Added
-
An expense's amount can change at triggers of its own, as
[[expenses.phases]]rows of afromtrigger and the amount from then on, so
a cost that changes with a move or with age is one expense rather than one per
period. The year a phase fires in is split by months where the trigger has
one;start,endandonkeep their whole-year meaning, andonexcludes
phases. The Expenses form offers a phase after the last one filled, the
read-out lists the filled ones alone, the table counts them, the Overview
marks an implausible phase amount, and the spending ceiling scales every phase
with its expense. -
A Spending Estimate tool proposes the plan's expenses from a bank's CSV, OFX
or QFX exports - the latest twelve months, a partial month counted by its
days, one proposal per expense with its categories beneath it. A category
lands in the expense named for it, else in one of its family, a new one, or a
bucket that also takes unnamed payees, as an optional[estimate]table leans
(existing only, new past a share of spending, or always new); the table also
names the bucket and assigns categories outright. Each expense shows its
amount now, proposed and the change and the payees behind it, each category
why it landed there and the transactions behind it; unnamed payees sit under
the bucket, refunds marked. Proposals can be edited and taken or written as a
scenario, in the terminal, the web app,retiretui estimateand
estimate_spendingover MCP. A payee can be named, merged with its variants
under one name, or ignored, as can a single record; ignored records are
counted nowhere and listed last, after the bucket. In the terminaliignores
andcmoves a payee to a category typed by its number, or to the bucket as
0, and ⏎ on a record offers these and sorting every payee containing its
words; the web gives each record the same menu. The terminal keeps these in
estimate/patterns.tomlin the config directory, whose rules can also test
the exact payee, a regex, the amount, the export and the date, the most
specific match winning over the bank's own category; a space at either end of
amatchmarks the edge of a word. A file that does not read is left out, and
said.retiretui estimate --category,--payee,--unnamedor--ignored,
andestimate_recordsover MCP, list those records, each with the rule, bank
category, transaction type or embedded entry that sorted it.--patternsis
read beside the config directory's file (--no-user-patternsleaves it out),
and MCP reads that file too, and exports and rules by path, each export named
by its path. -
A
self-employmentincome kind: net earnings that pay self-employment tax on
92.35% of net, Social Security's part up to what the wage base leaves over the
owner's wages, half of it deducted from ordinary income, and record that share
as covered earnings. It may becoveredby a workplace plan. -
A salary may state
pretax, what the employer takes out before tax - health
premiums, an FSA - which reaches neither cash, tax, the FICA base nor the
earnings record; the Ledger lists it where the year's money went, and the
year'spretaxreports it. A salary may saysocial_security = falsefor a
non-covered public job: no Social Security tax, Medicare's still, and nothing
recorded as covered earnings. The Income form offers both; the mid-career
couple example shows a pre-tax deduction. -
The Tax Tables page lists the year's payroll rates.
[payroll]in a tax table
carries them, the statutory rates where a table leaves it out. -
A
414kaccount takesby = "after-tax"contributions, as a 401(k) and a
403(b) do: a public pension's individual account can carry the member's
after-tax self-pay beside the employer's share. The money is kept as basis,
held to the plan's yearly cap after the other payers, and comes back untaxed
pro rata on every draw, through a rollover too.
Fixed
- The header's palette button is named with the "Ctrl K" it shows, as the
label-in-name rule asks.
Changed
- Breaking: every salary pays the employee's payroll tax out of cash -
Social Security to the year's wage base, Medicare on all wages, and the
Additional Medicare Tax on the household's wages over $200,000 or $250,000 -
so a salaried plan's working-year surplus falls by about 7.65% of each salary
below the base. It lands aspayrollin the year's taxes, inside their total,
and as a "Payroll" line in the Ledger's Tax pane. A payroll HSA contribution
comes off the FICA base and the earnings record; a 401(k) deferral does not. retiretui_engine:Expensegainsphases,ScaledExpenseeach phase's
amount at the ceiling, andspending_overlaytakes the plan it restates.
Taxesgainspayroll,YearRowpretaxandcovered- what each person's
earnings record gained in the year -Incomepretaxandsocial_security,
IncomeKindSelfEmployment, andTaxParamspayroll;tax::payrollis
new.- Breaking: building needs Rust 1.97.1.
retiretui_tuiis built on plurimus
0.9.0, plurimus_filepicker 0.3.0 and bevy 0.20, andretiretui_client's
bevyfeature onbevy_ecs0.20, so an app that embeds either moves with it.
v0.4.1
Changed
- The Overview's charts are keyed alike in the terminal and the web app. In the
terminal, Balances keys only the treatments the plan holds, taxable first and
at the bottom of the stack, then net worth, and lines are "Net worth",
"Income" and "Taxes". In the web app the market runs' bands are "10th to 90th"
and "25th to 75th" and their middle line "median". Compare's table of plans
leads each row with the same light stroke as the Overview's key.
Fixed
- In the web app a throw on the start screen, in a draft notice or in a group's
page chips is said in the page's place, the header, the navigation and the
footer still around it. It took them with it. Opening a plan or going to
another page tries again. - In the web app a page scrolled down stays there when a switch is turned, a row
is highlighted, or a form is opened or closed. It went back to the top.
v0.4.0
Added
-
An income may say that its amount is what it pays in its first year, with
cola_from = "start", and itscolathen runs from that year rather than
from the plan's start. A pension estimate or an annuity contract states a
benefit that way - a sum payable from a date, with a cost-of-living rate after
it - and until now a fixed-ratecolaalso compounded over the years before
the income began, so a pension of 20,000 at 2% starting five years into the
plan paid 22,082 in its first year and stayed that far ahead for life. With
cola_from = "start"it pays 20,000, then 20,400. The first year follows the
income'sstartoronwherever a scenario moves it, and an income already
being paid when the plan starts escalates from the plan's start as before.
cola_fromis"plan"unless stated, is left out of a saved file while it
is, and no plan that does not state it projects differently. A Social Security
income is refused it: a benefit is stated in today's dollars and takes its
cost-of-living adjustments whether or not it is claimed. Expenses, conversions
and contributions escalate from the plan's start as they did.- The Income form, in the terminal and in the web app, asks it as "Grows from"
beside Growth - "Plan start" or "Its first year" - and not of a Social
Security income. - The MCP server's schema reference says it under Escalation.
- The
public-pensionexample states Dana's pension this way, so it pays
42,000 in its first year rather than 45,462.
- The Income form, in the terminal and in the web app, asks it as "Grows from"
-
In the terminal planner, and the canvas page that shares its shell, what
stands over the page no longer vanishes on the frame it closes. A dialog, a
picker, an item's form and the file picker break up into the page beneath over
150 ms, and the Messages drawer and the Issues panel slide out through the
bottom of the body over 180 ms. The page is live again at once: the keyboard
and the pointer come back on the frame the overlay closes, the dim lifts with
them, and only what the overlay last drew lingers. Nothing leaves this way
whenmotionisreducedoroff, when an overlay is replaced by another of
its kind, or when one closes beneath another that still stands. Menus and
toasts are as they were. -
The terminal planner's keys can be rebound. A
[tui.keys]table in
config.toml, besidethemeandmotionin the user's config directory,
names a command as the palette lists it and states every key it answers to:[tui.keys] save = "ctrl-w" quit = ["q", "alt-q"] sort = [] ledger = "L"
- An entry replaces the command's keys whole, and an empty list leaves it with
none; the command is still run from the palette. The first key stated is the
one shown. - A key is spelled as the key row shows it:
ctrl-,alt-andshift-ahead
of a character or a name -esc,space,backspace,delete,insert,
home,end,pageup,pagedown,f1tof12- withtab,enter,
up,down,leftandrighttyped for the keys shown as⇥,⏎and
the arrows. A shifted character is written as itself,Gor?, and
shift-gis refused saying so. - A key another command holds by default is taken from it, which keeps its
others, and the shell says so once at launch: "[tui.keys] q now runs save,
not quit". A key two entries state goes to the command the palette lists
first, and the other entry is left out. A command particular to a page may
share a key with one of the shell's, as the defaults do, and runs in its
place while that page is shown. - The palette always keeps a key: an entry that empties it, or states the key
it holds, is left out. - An entry that names no command, or states anything that does not read as a
key, is left out whole, the command keeps its keys, and the shell says which
and why. - Everything that names a key names the one in force: the key row, the help
picker, the tab bar, a tool's help line. A command left with no key is not
hinted. A tab names its key only where one cell holds it, so a tab bound to
alt-1shows none. - The keys a form, a list or a dialog answers to by itself - ⏎, esc and ⇥
inside them, the arrows in a list - are not commands and are not rebound.
The canvas page reads the same table from the page's storage, which nothing
on the page writes.
- An entry replaces the command's keys whole, and an empty list leaves it with
-
The terminal planner wears themes of your own. A file in
themes/, beside
config.tomlin the user's config directory, is a theme named by its file
name -themes/dusk.tomlisdusk- written as the built-in ones are: a
family, avariantof"dark"or"light", and a colour for each role it
names, the rest left as the terminal's own, its tables unbanded unless it
namesstripe. It is chosen from the theme picker or by[tui.theme] name
like any other, and by its family where it states one, the variant following a
light or dark terminal.retiretui theme listnames every theme with its variant, its family and
where it comes from, andretiretui theme dump <name>prints one's file,
taking a name as[tui.theme] namedoes, to start another from:
retiretui theme dump nord > ~/.config/retiretui/themes/mine.toml.- A file named as a built-in theme takes its place,
listsaying so. A file
namedterminal.tomlis left out and said, sinceterminalis the
terminal's own colours. - The theme picker reads the directory again each time it opens, and puts what
is worn on afresh, so a theme being written shows without leaving the
planner. It marks a theme of the user'syours. - A file that does not read is said with its path and the reason, at launch
and as the picker opens. It is listed dimly asdoes not read, is not kept
when chosen, and stands for no family, so it hides no other theme. - The README has a Settings section: where
config.tomlis, what[tui]
holds, and how to start a theme.
-
A Spending Ceiling tool answers how much a plan could spend. It scales every
expense the household could cut alike and projects the plan whole at each
step, so tax, Medicare and every other interaction is priced in, and answers
twice: the most that lasts in the plan's own market, and the most that lasts
in a target share of its random markets, 90% unless another is set. A run
lasts as the Monte Carlo tool counts it: never short, and ending with at least
[market] leave_at_leastwhere the plan states one. Every candidate is walked
through the same markets, so the answers differ by spending alone. A plan that
falls short as it stands is answered with less than it spends.- An expense may say
essential = true: spending the household could not cut,
which the tool leaves as stated. A one-time expense is left either way. The
rest is the flexible spending it scales. The key is left out of a saved file
while false, and no plan projects differently for it. The Expenses form, in
the terminal and in the web app, ticks it as "Essential". - The search judges at most 16 plans for each answer, settles within $100 a
year of flexible spending, and stops at eight times what the plan spends,
which it says as "at least". It refuses a plan with no flexible spending,
and one that falls short even with none. retiretui optimize spending <plan>prints the plan as it stands and both
ceilings - the flexible spending, its change, the share of markets it lasts
in and the headline figures - over each expense now and at each ceiling.
--successsets the target as a fraction, and--writewrites the ceiling
at the target as a scenario that restates each scaled expense'samount. It
takes--nominal,--format json,--historyand--tax-diras the other
searches do.- The MCP server gains
optimize_spending, which replies both ceilings with
the scenario and stores it withwrite_to, and its schema reference
documentsessential. - The terminal planner has a Spending Ceiling page among its tools, between
Historical and Tax Tables: both ceilings under the plan's own row, the
highlighted one's expenses now and at the ceiling, and the target, edited in
a form and held for the session rather than saved with the plan. The cursor
starts on the ceiling at the target. It takes what the Overview has already
found rather than searching again.tor⏎takes the highlighted ceiling
into the plan after asking, as one step that undo takes back, andwwrites
it as a scenario and compares it; the commands aretake-spendingand
write-spending. Where the plan asks to leave nothing, the ceiling in its
own market says that it spends everything by the plan's end. - The web app has the same page, the highlighted ceiling kept in the address,
with a link from that note to Leave at least on the Market page. - The
mid-career-coupleexample marks its mortgage essential and
retired-coupleits Medicare premiums; both project as they did.
- An expense may say
-
A projected year says how much of its spending was essential and how much
flexible:expenses_essentialandexpenses_flexiblestand besideexpenses
in each year ofretiretui project --format jsonand of the MCP server's full
projection. What is neither was spent once.
Changed
- Breaking. No plan key is removed or renamed, and a plan written for 0.3.0
projects as it did. What breaks is the Rust API, and the workspace is 0.4.0:- The engine's
Incomegainscola_from, aColaAnchor, so a struct literal
of one written outside the engine must add it. - The client's
VocabularygainsColaAnchor, so amatchover it written
outside the client must cover it. - The engine's
Expensegainsessential, so a struct literal of one written
outside the engine must add it. - The engine's
YearRowgainsexpenses_essential,...
- The engine's
v0.3.0
Added
- A web app for phones and desktop browsers, at
https://kenianbei.github.io/retiretui/, published to GitHub Pages at the
site's root with each release: a page over the engine's JavaScript bindings,
the unpublishedretiretui_wasmcrate, and overretiretui_client, the crate
of what every interface shares, new with this release. It keeps its plans in
the browser's own storage and never sends them anywhere. The canvas page - the
terminal planner drawn in a browser, which 0.2.0 published at the root - is
beside it at/ratzilla/and keeps its plans apart from the app's: a plan
made in the 0.2.0 page is still there, and reaches the app by a download from
that page and an upload to the app.- Start. The Start page opens with a sentence on what RetireTui does. A
first plan is made from a few questions asked a step at a time - the
household, then each person - which read every answer back to be changed
before the plan is named, made and opened on the Overview; a blank age,
start of work or Social Security benefit reads as what the plan will
assume -Blank is 65while answered,65, the defaultread back - and the
answers survive a reload until the plan is made. The example plans and an
upload are offered beside them. The app reopens the plan last open, and
downloads the open plan; a plan that does not open is said on the Start page
by the file that failed, the line and why, with that file to download or
replace by an upload, and its text as written beneath, the failing line
marked. - Overview. It reads as the ledger's first page. It leads with how long
the money lasts, the share of a thousand random markets it survives - run
off the page's thread, and leading to the Monte Carlo tool - what it ends
with and what it pays in tax, in today's or future dollars and in the
terminal's words, as rows of a label and a figure on a phone; a plan that
runs short is noted above them with the year it first does and what it
leaves uncovered, leading to that year in the Ledger and to Expenses, and
how long the money lasts then reads the last year it covers. Beneath is what
to do in the year shown, in the dollars shown and said as the terminal says
it: today's by default, stepped by button or the arrow keys, or chosen with
a click on a chart, and leading to that year in the Ledger. Then what needs
attention - the worst historical start the plan does not survive and how
many fail, as the terminal says it, leading to the Historical tool on that
start; the years the plan pays Medicare's surcharges, contributions held
back, a benefit estimated without its earnings record, an amount too large
to be likely - and what could do better, each row leading to its year in the
Ledger, its item or its tool. Could do better gives each Roth owner's best
ladder, the household's best claims and the best withdrawal order against
the plan as it stands, each leading to its tool, a ladder's aimed at that
owner's account; what it finds is what the tools then show without searching
again. What to do, the milestones, what needs attention and what could do
better sit four across on a wide page, two on a narrower one. Beneath them,
all shown at once and two across on a wide page, the plan's balances by tax
treatment under its net worth, its net worth, its income against its taxes,
and its net worth through the random markets as percentile bands, each
salary's end marked and listed under its chart, each chart read as one image
with the Ledger as its table. - Ledger. It shows the plan year by year, the year column staying in view
as the table scrolls sideways, and the chosen year's flows through each
account - where each came from or went, with the year's warnings - and its
income and what it paid, beneath the table on a wide screen and above it on
a phone, where no page scrolls sideways but its tables. The year and the
dollars are in the page's address, kept between the Overview, the Ledger,
Compare and the tools and across a reload. - Plan pages. They edit the plan: each domain's items are a table sortable
by its columns, or rows with a Sort by on a phone, beside the highlighted
item read out in the form's words - a field left blank read as what it
stands for, muted, such asEarns nothingor6%, the default, and the
Market's fields under headings - and a domain there is one of is that
read-out alone. Edit, Add and Delete work one item at a time; the form is a
sheet, full screen on a phone, whose fields are entered by their kind -
picks from the schema's sets and the plan's own ids, a searched list for a
country or U.S. state, a slider beside a rate, a trigger as its kind and
sentence - and applying stores the whole item or says why not. Every applied
item or deletion is a step Undo and Redo walk, by button or Ctrl/Cmd+Z, and
Save or Ctrl/Cmd+S writes the plan back through the same validation as every
other surface; Save as… writes it under another name. A scenario opens
read-only. Unsaved edits are asked about before a form closes, another plan
opens, or the page is left, and a file changed in another tab under them is
reported rather than overwritten. A plan with issues counts them in the
header and lists each by the page, item and field it is about, each a link
to that field in its form, while the figures keep the last ones it had
without issues. A Social Security statement downloaded from ssa.gov is
imported onto a person from the People page as one step of history. - Roth Conversions. The tool searches every fillable bracket's conversion
ladder, ranks them under the plan as it stands, each saying what it ends
with against the plan, and shows the highlighted one's conversions year by
year beside them on a wide page, in either dollar basis, over the
constraints it searched under, read out and edited in a sheet; it searches
again whenever the plan or the constraints change, and takes the plan's one
Roth account as the destination where there is only one. The highlighted
ladder is taken into the plan after asking, as one step of history in place
of any ladder taken before, or written as a scenario beside the saved plan,
compared with it at once and offered to open. - SSA Benefits. The tool ranks every claim age for the household's
computed Social Security benefits under the plan as it stands, each against
the plan as a ladder is, beside each person's earnings record, how their
benefit is set and the benefit estimated at 62, full retirement age and 70,
with what can be done for the highlighted person: import a statement,
estimate a record from their salary, compute a stated benefit from their
record, clear the record or remove the benefit - the last two asked first -
each one step of history, or hold their claim as the plan states it while
the others are searched. The highlighted claims are taken into the plan
after asking or written as a scenario, as a ladder is; the claims
highlighted, the person and who is held are kept in the address. - Withdrawal Order. The tool ranks the orders the plan can withdraw in, by
the search said further down, under the plan as it stands, the highlighted
one taken into the plan after asking, as one step of history, or written as
a scenario and compared at once. The highlighted order is kept in the
address. - Monte Carlo and Historical. The tools run the plan through a thousand
random markets, or from every historical start year worst first, and say how
it fared in one sentence -Money lasts in 87% of 1,000 markets- in the
colour of its zone - as the Overview's figure is coloured - beside what the
runs were made under, each a link to the Market field it is edited at;
beneath the runs singled out, all shown at once, are the spread of net
worth - percentile bands in a neutral - under the highlighted run's line,
the share still funded, what the runs end with, and net worth by year at
each percentile (Monte Carlo only). The highlighted run opens in the Ledger,
replayed through its market and named by it - a random market's number, or
the year retired into - kept in the address through the year, the dollars
and edits, with a link back to the plan's own. - Compare. It sets the plan beside the plans chosen for it from the
workspace, the plan files the app keeps. It shows each plan's figures and
its success through random markets - each plan searched in a worker of its
own - or its differences from the one chosen as the baseline, what the
highlighted plan changes of the baseline, and one of eight metrics year by
year, charted beside its table. A plan alone is offered another from the
workspace, or, where there is none, an example written beside it and
compared at once. The plans compared, the baseline and the metric are kept
in the address, the plans compared carried by every link; opening a compared
plan puts it in the open plan's place with that plan joining the compared,
and opening any other plan leaves nothing compared. - Tax Tables. The tool reads out the tables the plan's projection applies
in the year shown - brackets, deductions, long-term gains, Social Security's
thresholds and benefit formula, the contribution limits, Medicare
surcharges, the RMD divisors and the state's income tax - in columns as many
as the page holds - for the plan's filing status and the state it lives in
that year, grown past the last published table at the plan's inflation, or
for any status or modeled state picked. - Plans and files. The header names the open plan, marked with a dot while
it has unsa...
- Start. The Start page opens with a sentence on what RetireTui does. A
v0.2.0: chore: release 0.2.0 (#13)
Added
- A form too tall for the terminal scrolls: its fields scroll above a help line
and buttons that stay put, the field holding the keyboard is kept in view, the
mouse wheel scrolls it, and a scrollbar on its right edge shows where it is. - An account's glide path is edited as up to six steps, each step offered once
the one before it is filled; a file's steps past the sixth are kept as they
are. - A mix's cash, and each glide step's, is shown beside its stocks and bonds as
what they leave, following them as they are edited and marked when they leave
less than none. - The Market form edits the stocks-cash and bonds-cash correlations.
- A new plan can start from one of the ten example plans, picked at the top of
the new-plan form and saved under the example's name. - The new-plan form asks when each person started working, and takes a retired
person's salary as what they last earned, so a retiree's Social Security is
computed from their career as a worker's is. A retiree who has not reached
their claim age claims at it. - On the Monte Carlo and Historical pages the cursor rests on "As planned", and
⏎ there shows the plan's own projection in the Ledger. - The planner runs in a browser page, published to GitHub Pages with each
release. Its workspace is kept in the browser's own storage and never leaves
it; the page reopens the plan last open, follows the browser's light or dark
preference, and Quit starts it over.uploadanddownload, in the page's
command palette, bring plans, scenarios and Social Security statements in -
asking before one replaces a file of the same name - and take the open
document's file back out as saved. Searches run on the page between frames, so
a large Monte Carlo run holds the page until it answers.
Changed
-
A form stands only as tall as the fields the item has a use for, and the
smallest terminal the planner takes no longer grows with its tallest form. -
The Roth Conversions tool converts into the plan's one Roth account without
asking, so its ladders are ranked on a first look. -
The Ledger's detail is as tall as the cursor year needs, up to half the page,
and Income & Tax leaves out what the year paid nothing on. -
The key row's words are shorter, so more of each page's keys fit at 128
columns, and a tool's write and take keys are shown only once there is
something to write or take. -
A table too narrow for its columns cuts a long header before any cell, and one
with room to spare uses all of it. A tool table's message wraps rather than
being cut off. -
The status bar cuts a long file name in the middle, keeping its end.
-
Every built-in theme colours the good and caution zones from its own palette,
and draws a text caret in its accent. The market runs table's title carries
the zone colour. -
Roth Conversions, SSA Benefits and Historical, opened on a plan the Overview
has already searched, show the Overview's answer at once rather than searching
the same plan again. -
The minimum versions of the engine's and the binary's dependencies are now the
versions they are built and checked against. -
Validation names the entry at fault in a list: a negative prior-year MAGI is
reported atmedicare.prior_magi[i]and a repeated withdrawal class at
plan.withdrawal_order[i], rather than at the whole list. -
An item open in a form while the plan changes underneath is followed to
wherever it now sits: applying no longer refuses because an undo or a reload
moved it. It is still refused when the item itself was changed or renamed. -
optimize conversionsand MCPsweep_conversion_bracketslist the brackets
best first - the least left unfunded, then the most left at the end - as the
Roth Conversions tool does, rather than by rate. -
The conversion source is optional: without
--fromon the CLI, orfromover
MCP, a ladder converts from every deferred account of the destination's owner,
as the Roth Conversions tool does when its source is left blank. Where that
owner holds none, the search says there is no deferred account to convert
from. -
The new-plan form numbers the ids it makes from a person's name, as new items
are numbered: Alice isalice-1, a second Alicealice-2, and their
retirement and workplace account follow asretire-alice-1and
alice-1-401k. -
MCP
project_planandtax_parametersdescribe their replies with full
output schemas - summary or full rows, and every tax table - and an issue in
any reply is described as the engine's own. Replies are unchanged. -
A computed Social Security benefit is priced at the claim's age in months, not
whole years: a claim on a date is priced from that date's month, and a claim
on an event or another income from the month of the date or age it rests on. A
claim at 62 starts in the first month 62 is held throughout, the month after
the birthday unless it falls on the 2nd, so most claims at 62 are 59 months
early rather than 60. A computed benefit claimed before the month 62 is
attained is refused. -
Every Social Security income's first year, typed or computed, is paid from the
month it starts, not only one started on its owner's age. -
Credits for delaying past full retirement age that are earned in the claim
year are paid from the next January, as SSA pays them, except for a claim
at 70. -
A benefit whose owner turned 62 before the plan starts is carried to the
plan's first year by the COLAs SSA published, truncated to the dime after
each, rather than at the plan's inflation. The tax tables carry every COLA
from 1975 to 2025. -
A person with no earnings record is taken to have worked from 22 until the
plan at the salary its first year pays them, so a computed benefit counts the
years before the plan; a stated record, even a partial one, is used as it
stands. The Overview says the benefit comes from an estimated career. -
An earnings statement row stating several years as one sum is spread evenly
over them rather than refused, and the import says which years it spread; MCP
import_earningssays so in a newnote. -
A tax parameter file for a year that leaves out a state takes that state from
the latest earlier year that has it, inflated, so a plan living there is no
longer refused. -
The engine is 0.2.0:
tax::social_security_benefittakes an age in months and
the COLAs to carry the benefit through,tax::claim_year_sharetakes the
first paid month,BenefitParamsgainscola,Statementgainsgrouped,
andStatementError::Groupedis gone.optimize::optimize_claimsand
optimize::sweep_bracketstake aProgressand answer aRunError, which
now live in asearchmodule and are still re-exported frommarket. -
A conversion sweep searches its brackets side by side on the machine's
threads, sooptimize conversionswithout--bracket, MCP
sweep_conversion_bracketsand the Roth Conversions tool answer in about half
the time. -
A claim or ladder search that a newer one replaces - an edit made while the
Overview, SSA Benefits or Roth Conversions page is searching - stops rather
than running to its end, and the SSA Benefits page works out each person's
estimates off the main thread. -
Turning back to an editing page whose plan has not changed keeps its table as
it was rather than rebuilding it, typing in a picker rewrites its rows rather
than making them anew, andtabfinds the page's panes without visiting every
row of its tables. -
The interactive planner is its own library crate,
retiretui_tui, which the
tuisubcommand and the browser page both run; the CLI and MCP take their
plan-file reading and the words their tables and actions are said in from it.
It reads and writes every plan file through aStore- the disk, or keys in a
browser's storage - and is built on plurimus 0.7.2 and plurimus_filepicker
0.1.1.
Fixed
- A computed Social Security benefit claimed before the plan starts is priced at
the age it was claimed at, not at the age its owner has reached in the plan's
first year. - Taking a searched Roth conversion ladder no longer removes a conversion of
your own whose id happens to start withopt-; only the optimizer's own
opt-<account>-<year>conversions are replaced. - After a reload fails, the planner and the Compare page watch the files the
plan now reads, so fixing a newly named base plan is picked up without
pressingr. - An issue against one place of a list in a form - one year's prior income -
marks and names that row alone, not every row of the list. - A list a form refuses keeps its amounts written as money once the keyboard
leaves them, rather than as bare digits. - A value an item has no use for, cleared by hand, leaves the form once the
keyboard leaves its row. - A trigger's kind menu lists its blank - the plan's start, say - first.
- The new-plan form refuses to write a plan that does not validate, as every
save does. - An issue against one step of a glide path marks that step's row in the form.
- A mix whose stocks are written as a whole number,
stocks = 1, no longer
gains a full share of cash when applied. - The Ledger's warnings state their amounts in the dollars on show, not always
in nominal dollars. - A click in a table whose pane has grown, after a terminal resize say, lands on
the row drawn under the pointer. - A person's claim held out of the claim search is no longer held for a person
of the same id in the next document opened.
v0.1.0
Added
Plans
- Plan files: a TOML description of a one- or two-person household - people,
accounts, income, expenses, contributions, transfers, conversions and events. - Accounts: 401(k), 403(b), 457(b), 414(k), traditional and Roth IRAs, HSA,
brokerage and cash, with cost basis, locks and a withdrawal order. - Triggers: anything starts or stops on a date, an age, or a named event or
income, with a year offset. - Escalation: each amount grows with inflation, stays flat in nominal dollars,
or grows at a rate of its own. - Contributions: fixed dollars, a share of salary, the legal maximum, or an
employer match, held to each year's IRS limits. - Residency: where the household lives over time; state income tax follows a
move. - Scenarios: a file naming a base plan and stating only what differs from it.
Scenarios can build on other scenarios. - Market assumptions: per-account stock, bond and cash mixes or glide paths, and
a[market]table of returns, volatility and inflation. - Social Security: a benefit stated as an amount, or computed from the person's
earnings record with SSA's formula. - Opt-in Medicare IRMAA surcharges, and MAGI cliffs such as ACA premium credits.
Engine
- Federal tax: brackets, capital gains, taxation of Social Security, RMDs,
early-withdrawal penalties and contribution limits, with 2026 tables built in. - State income tax for Oregon and the states without one.
- Year-by-year projection in nominal dollars, readable in today's dollars, with
tax-aware withdrawals. - Each projected year lists the actions taken: contributions, transfers, RMDs,
conversions, withdrawals and surplus saved. - Monte Carlo runs from the plan's assumptions or resampled history, and
historical runs from every start year since 1871. - Tax tables and market history can be replaced by files in the user config
directory.
Command line
validate,project(text or JSON),actions(one year's to-dos) and
compare(plans side by side).optimize conversions: finds the Roth conversion ladder that fills a tax
bracket, optionally under an IRMAA tier or MAGI cap.optimize claims: ranks Social Security claim ages for the household.- Both optimizers can write their result as a scenario.
monte-carloandhistorical: how often the plan's money lasts, with
percentile runs.import-earnings: records the earnings from anssa.govstatement on a
person.mcp: the same tools for AI agents over the Model Context Protocol, limited
to one directory, with a plan schema reference.
Interactive planner
retiretui tui: a keyboard- and mouse-driven planner for a plan, a scenario
or a directory.- Overview: whether the money lasts, milestones, warnings, the year's to-dos,
balance charts and suggested improvements. - Ledger: every year's totals, and each account's flows, income and taxes for
the selected year. - Compare: the open plan beside other plans, with their differences and charts
by year. - Tools: the conversion and claim-age searches, Monte Carlo and historical runs.
A result can be applied to the plan or saved as a scenario. - Editing: a page per plan section and a form per item, validated on apply, with
undo and redo. - A new-plan form that builds a starting plan from a few answers.
- A file picker for opening and saving; open files reload when they change on
disk. - A command palette, key hints, a message log, themes and reduced motion.
Project
- Example plans in
examples/. - Crates on crates.io and prebuilt binaries for x86_64 and aarch64 Linux.