You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Most banking apps tell you what already happened. Horizon tells you what happens next.
One glance, about two seconds: current balance, future balance, and what caused the change.
Horizon lives in the menu bar as a gauge ring and your live balance. Click it and the
whole product is one popover. Every screenshot below is the real app, running against
Investec's shared sandbox account rather than anyone's own money.
The balance, at a glance
The number you actually came for sits at the top, with a one word read on it:
comfortable, getting tight, or low buffer. That word is not decoration, it comes from your
projected minimum balance compared to your monthly commitments.
The three rings are the whole month compressed:
Buffer is how much of today's balance survives to the lowest point of the forecast.
36% means the dip takes roughly two thirds of it.
Payday counts down to the next income Horizon detected, and fills as the pay cycle
progresses.
Spent is this month against what a normal month looks like for you. It turns red
past 90%, which is the useful moment to know.
This month switches between the month total and a per day average, so "R19 360 spent"
becomes "R968 a day versus a typical R579". The daily view is usually the one that
explains the month.
Two things banks routinely blur, spelled out here instead:
Money spent but not posted. Card purchases sit as an authorisation for days, and
some merchants only claim theirs in a weekly batch. Investec leaves these out of the
transactions feed unless asked, so Horizon asks, and counts them. The headline is what
is really yours once everything in flight lands, not what has merely cleared.
Credit that is not your money. On an account with a facility the headline is what
you actually hold, which can be negative, with a line underneath saying how far into the
facility you are and how much is still spendable. The forecast measures its buffer
against the bottom of the facility rather than against zero.
Below it, the forecast curve and where it lands in 30 days.
Where the balance is heading
The ladder is the forecast in four numbers. Today, a week out, a fortnight, a month. If it
only tells you one thing, it is whether the line goes up or down.
Financial outlook names the lowest point and the date it happens, because a month end
balance can look healthy while the third week quietly goes to nothing. The projected
minimum is the number that actually decides whether a purchase is safe.
What if? re runs the whole forecast with one thing changed and redraws the curve, with
the original left behind as a dashed ghost line so you can see the difference rather than
being told it. Spending R3 000 today, a salary landing three days late, cutting back 30%.
The comparison tracks the projected minimum, not the end balance. A late salary leaves
the 30 day endpoint identical while making the dip much worse, so comparing endpoints
would tell you it costs nothing, which is wrong.
The question mark opens the full arithmetic behind the number.
Every month, then every day
A cube per month, showing what moved across it. The figure is signed, because a month
is a change and not a balance: green gained, red used.
Hover one and the line above answers the question you actually had, which is what you were
left with when the month ended. There is no historical balance endpoint, so that number is
reconstructed by winding the transaction feed back off today's figure.
Months that are not finished cannot be reported as fact, so they carry a tilde and the
hover splits the two halves apart: what has gone so far, and what is still expected. Months
older than the transaction feed say so rather than quietly repeating the oldest balance
Horizon happens to know.
Press a month and it opens into a cube per day.
Red is money out, green is money in.
Filled dots already happened. Hollow dots are expected, so the rest of the month
is visibly a prediction rather than a fact.
Today is ringed in your accent colour.
Hover a day for what it used or gained. Press one and it opens below with the total and
every line item, tagged where something is still pending or only expected.
This is the view that answers "why was last week so expensive" faster than a list of
transactions ever does.
Make it yours
Background follows the system, or you can pin it to light or dark.
Accent colour has six options. This is applied to the whole interface, including the
forecast curve and the gauges.
Auto refresh picks how often Horizon pulls from Investec, from 5 to 60 minutes. There
is also a refresh button in the header for right now.
Lock when closed puts Touch ID, or your login password, in front of the window. The
menu bar opens on a single click, so this is what stops someone reading your balance off an
unlocked laptop. It asks as the window opens and locks again as it closes, and it keeps the
balance out of the menu bar too, since guarding the window while printing the number above
it would protect nothing.
Balance includes credit is for accounts that report one figure with the overdraft
already counted in. Tell Horizon the size of the facility and it subtracts it, leaving what
is actually yours, and the forecast then measures how close you are to the bottom of the
facility instead of to zero.
Account shows which account is connected, whether it is your own or the shared
sandbox, and how many transactions the forecast was built from.
Disconnecting wipes the credentials out of the Keychain and returns the app to onboarding.
Connecting, and locking it down
Two ways in: the shared Investec sandbox to try it out, or your own account with
keys from Investec Online, then Manage, then Investec Developer. Horizon ships with no
credentials of any kind, so the sandbox route points you at Investec's documentation and
asks you to paste their published test keys yourself.
There is no production or sandbox switch to get wrong. Your keys are treated as production,
and if Investec rejects them there Horizon retries the sandbox host automatically.
Restrict the key to your IP is the step worth doing. Investec can limit an API key to
specific addresses, so a leaked key is useless from anywhere else. Horizon looks up the
public address this Mac appears as, gives you a copy button, and walks through where the
setting lives. It also warns you about the catch: a changing address, a hotspot or a VPN
will lock you out until the allowlist is updated.
When a connection fails, Horizon explains it instead of showing a status code. A 403 leads
with the allowlist as the likely cause and offers your IP right there in the error.
Find recurring payments and income. A merchant only counts once it has fired three
or more times on a steady interval (5 to 45 days). Regularity is scored, so a debit
order sails through while noisy card spending at the same shop fails the test and is
ignored. Without this, buying coffee often makes coffee a "subscription".
Estimate everyday spending as the average non recurring outflow over 60 days.
Lay the recurring events onto a calendar across the next 30 days.
Add the estimated daily spend on top.
Walk day by day to get a projected balance for every day.
Find the lowest point, the number that actually matters.
Surface the assumptions and any risks.
Scenarios re run the same pipeline with the event list nudged, so a scenario is always
explainable in the same terms as the base forecast.
Which Investec data it uses
Investec Private Banking API, read only:
GET /za/pb/v1/accounts
GET /za/pb/v1/accounts/{id}/balance
GET /za/pb/v1/accounts/{id}/transactions
OAuth2 client credentials (Basic auth plus x-api-key, scope=accounts). Sandbox serves
the token and the data from openapisandbox.investec.com; production serves both from
openapi.investec.com. Mixing the two is the classic way to get an auth failure that looks
like an empty account.
Horizon never calls a payment or transfer endpoint. Being native, it talks to Investec
directly, so there is no proxy and no browser in the path.
What it assumes, and where it can be wrong
Recurring payments continue at their detected amount and cadence.
Everyday spending resembles the last 60 days on average.
The next salary lands on its detected cadence. Horizon predicts by interval rather than
by calendar day, so a payday can drift a day or two.
One account is forecast at a time.
Forecasts are projections, not guarantees. The interface says projected and expected, never
"you will have".
Security
Keys live in the macOS Keychain. Never in the app bundle, never on disk in the clear,
never in this repo.
Read only. Horizon has no code path that moves money.
IP allowlisting is offered during setup so the key only works from your device.
The only request to anything other than Investec is the public IP lookup on the allowlist
screen, which sends no account data.
Build it yourself
Requires macOS 14 or later and the Swift toolchain (Xcode or the Command Line Tools).
git clone https://github.com/Nevvyboi/Horizon.git
cd Horizon
./scripts/bundle.sh
open build/Horizon.app
scripts/bundle.sh builds a release binary with Swift Package Manager and wraps it in a
proper .app. It is an agent app, so it lives only in the menu bar with no Dock icon and
no entry in the app switcher.
Note that the build is ad hoc signed. macOS ties Keychain access to the code signature, so
each rebuild will ask for Keychain permission again. A real signing identity removes that.
How it is put together
Sources/Horizon/
HorizonApp.swift MenuBarExtra entry point
AppState.swift loading, refreshing, scenario building, error reporting
InvestecClient.swift OAuth2 and the read only endpoints
ForecastEngine.swift recurring detection and the projection
Keychain.swift credential storage
Unlock.swift Touch ID and the locked window
PublicIP.swift the address to allowlist
Models.swift the shared shapes, including the balance arithmetic
Money.swift rand and date formatting
Theme.swift accent themes, appearance and stored settings
GaugeMark.swift the mark, drawn rather than shipped as artwork
Components.swift gauges, the forecast chart, shared rows
RootView.swift the balance screen and the screen switch
FutureView.swift the forecast, scenarios and the timeline
ActivityCalendar.swift the month and day cubes
SettingsView.swift settings
OnboardingView.swift connecting an account
What it will not do
Move money. No payments, transfers or trades. Read only, always.
Give financial advice. Scenarios are calculations, not recommendations.