exhale

module
v0.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 12, 2026 License: AGPL-3.0

README

Exhale

Breathe out. Your subscriptions are handled.

Exhale reminds you before every renewal and lets you fix it from the reminder itself:
mark it paid, move the date, change the card, cancel. In Telegram, Slack or your browser.
It runs on your own computer, so your data stays with you.

Download · Website · Docs · Changelog

Latest release CI

Free and open source · English and Spanish

The reminder is the app

Most tools tell you Netflix renews in three days and leave the rest to you. Exhale's reminder is where you deal with it. This is a real one, in Telegram:

🔔 Spotify Family renews in 3 days
   💶 €17.99 · Sun, 8 Nov 2026
   💳 Revolut ••0937

   [ ✅ Already paid ]      [ 📅 Change date ]
   [ 💳 Payment method ]    [ ✏️ Amount ]
   [ ⏭ Skip this one ]      [ ❌ Cancel subscription ]
   [ 💤 Remind me tomorrow ] [ 💤 In 3 days ]

One tap and the message updates in place, with an undo. The web updates at the same moment.

Why people switch to Exhale

🔔 Reminders you can answer Already paid, a new date (this charge or from now on), another amount or card, skip, cancel, undo. One tap in the message, and it updates in place.
⏳ The dates that cost money Free trials before they charge, the last day to cancel, renewals that need you (domains, licences), fixed-term contracts and price rises announced ahead.
🔍 Find the ones you forgot Import a bank export (CSV) or a PDF statement and Exhale finds the charges that repeat, with no AI needed. Later statements show what was paid, what changed price and what never arrived.
📱 The whole app in a chat message A pinned Telegram or Slack message is Exhale itself: spend, upcoming charges, every subscription, an add wizard, payment methods and settings. It redraws when anything changes. Send the bot a statement to import it.
🩺 A check-up of facts, not tips The same service paid twice, prices that went up this year, trials about to charge, a card about to expire and everything that depends on it.
💻 Awake when it matters An icon in the menu bar (or the tray) with your next charges. Keep a laptop awake for an hour or a night, even with the lid closed, never down to an empty battery. What was due while it slept goes out when it wakes.
📲 On your phone, no app store Install the web as an app and get push notifications with a button that works from the notification. Or reminders by email, ntfy and webhook.
📆 Billing days as banks charge them Day 31 in short months, "the third Wednesday", weekends moved to a business day. Counted from the first charge, so dates never drift.
💶 Every currency, exact Totals in your currency at ECB rates, what each subscription has really cost you, and how much to set aside each month for the yearly bills.
👥 Shared, not mixed A partner or flatmates get their own account and reminders. Split a subscription and see who owes whom. Private ones stay private.
🤖 Ask it anything Plain language in chat, or Claude, ChatGPT and local models over MCP. Every change shows a preview first and can be undone.
📥 Bring everything with you Import from Wallos or a spreadsheet. Export it all as JSON, CSV or ZIP, or follow your charges in your calendar.
🔒 Yours, on your computer One program, one data folder, a backup every day, and each new version installed with one click. No cloud, no telemetry, no account with us, no paid tier.

Download

macOS 12+ Exhale.dmg, Apple silicon and Intel
Windows 10/11 Exhale-Setup.exe, or a .zip for x64 and ARM64
Linux .deb, .rpm or .tar.gz, x86-64, ARM64 and ARM 32-bit (Raspberry Pi)
Server or NAS Docker image, ghcr.io/akamachinecode/exhale

Or from a terminal:

curl -fsSL https://akamachinecode.github.io/exhale/install.sh | sh -s -- --service   # Linux, as a systemd service
docker run -d --name exhale --restart unless-stopped \
  -p 8484:8484 -v exhale-data:/data ghcr.io/akamachinecode/exhale                   # anywhere with Docker

Every release has cosign-signed checksums and build provenance. The install guide covers first-launch prompts, verifying downloads, HTTPS and remote access, backups and single sign-on.

Quick start

  1. Open Exhale. It opens in its own window and starts by itself with your computer. On a server, open http://<server>:8484 and enter the one-time setup code from the log (docker logs exhale).
  2. Create your account. The home page walks you through the rest. Making your own Telegram bot takes a minute and is guided.
  3. Add your subscriptions. By hand, from Wallos or a spreadsheet, or from your bank statement. Reminders start the same day.

No public address needed: Exhale talks to Telegram and Slack with outgoing connections only, so it works behind a home router. An always-on machine (a home server, a Raspberry Pi, a VPS) never misses a reminder.

Questions before installing

Does my computer have to be on?

Reminders go out while Exhale is running. On a laptop, Exhale can keep it awake for a while, even with the lid closed, from its menu bar icon or Settings → This computer, and anything due while it slept is sent when it wakes. A home server or a Raspberry Pi that never sleeps is ideal.

Where is my data?

In one folder on your computer, backed up every day. Nothing is sent anywhere unless you set up a channel such as Telegram.

Can I use it on my phone?

Yes. Reminders reach your phone through Telegram or Slack, or as push notifications once you install the web as an app (it needs HTTPS). Exhale itself runs on a computer.

Is it really free?

Yes. Exhale is free software under the AGPL-3.0, with no paid tier, no account with us and no telemetry.

I use Wallos. Can I move over?

Yes. Import your Wallos database and review every subscription before it is saved.

Learn more

The documentation site has every guide, with search, the REST API reference and llms.txt for language models. A few places to start:

Status

Exhale is young (v0.x) and used every day by its author. Expect rough edges and tell us about them in Issues; read the changelog before upgrading.

Contributing

Contributions are welcome, from a translation (two JSON files) to a new feature. Read CONTRIBUTING.md and AGENTS.md, the map of the code for people and coding agents. Every technical decision is recorded as an ADR.

git clone https://github.com/akamachinecode/exhale && cd exhale
mise install        # Go, Node, pnpm and the other tools
mise run build      # builds the web UI into the binary: bin/exhale
./bin/exhale serve  # http://127.0.0.1:8484
mise run test       # Go tests with the race detector

Report vulnerabilities as described in SECURITY.md.

Licence

AGPL-3.0-or-later. Free to use, change and share.

Directories

Path Synopsis
cmd
exhale command
Command exhale is the Exhale server and CLI.
Command exhale is the Exhale server and CLI.
internal
actions
Package actions (piece ⑥) decides what every reminder says and which buttons it carries, and runs the multi-step flows behind those buttons.
Package actions (piece ⑥) decides what every reminder says and which buttons it carries, and runs the multi-step flows behind those buttons.
agents
Package agents (piece ⑰) makes Exhale agent-ready: an MCP server that exposes every use case as a tool, the household briefing as a resource, and ready-made prompts (ADR 0018).
Package agents (piece ⑰) makes Exhale agent-ready: an MCP server that exposes every use case as a tool, the household briefing as a resource, and ready-made prompts (ADR 0018).
app
Package app (piece ⑦) holds every business operation of Exhale.
Package app (piece ⑦) holds every business operation of Exhale.
assistant
Package assistant is the model Exhale itself uses (ADR 0018, part B): plain language in chat and in the web, and reading statements and screenshots into the import review list.
Package assistant is the model Exhale itself uses (ADR 0018, part B): plain language in chat and in the web, and reading statements and screenshots into the import review list.
auth
Package auth resolves who is calling: API tokens for scripts and AI agents, one-time codes for linking chat accounts, and web accounts and sessions (ADR 0006).
Package auth resolves who is calling: API tokens for scripts and AI agents, one-time codes for linking chat accounts, and web accounts and sessions (ADR 0006).
awake
Package awake keeps the computer Exhale runs on from going to sleep, so that reminders go out on time and chat buttons keep answering (ADR 0028).
Package awake keeps the computer Exhale runs on from going to sleep, so that reminders go out on time and chat buttons keep answering (ADR 0028).
backup
Package backup copies the SQLite database safely: a consistent snapshot with VACUUM INTO (copying the file of a live database can corrupt the copy), a rolling set of automatic snapshots while the server runs, and a restore that never overwrites data (ADR 0009, ADR 0020).
Package backup copies the SQLite database safely: a consistent snapshot with VACUUM INTO (copying the file of a live database can corrupt the copy), a rolling set of automatic snapshots while the server runs, and a restore that never overwrites data (ADR 0009, ADR 0020).
bus
Package bus (piece ⑫) fans out domain events in memory: the web receives them over SSE, chat adapters re-edit messages already sent, and the scheduler re-plans reminders.
Package bus (piece ⑫) fans out domain events in memory: the web receives them over SSE, chat adapters re-edit messages already sent, and the scheduler re-plans reminders.
channels/email
Package email sends reminders by email over SMTP (ADR 0007).
Package email sends reminders by email over SMTP (ADR 0007).
channels/email/smtptest
Package smtptest is an in-process SMTP server for tests.
Package smtptest is an in-process SMTP server for tests.
channels/fake
Package fake is a text channel for tests: it renders messages as plain text so conversation scripts can be compared with golden files.
Package fake is a text channel for tests: it renders messages as plain text so conversation scripts can be compared with golden files.
channels/notifiers
Package notifiers runs the notify-only channels (email, ntfy, webhooks, Web Push): it owns their instance settings and hands the channels to the action layer.
Package notifiers runs the notify-only channels (email, ntfy, webhooks, Web Push): it owns their instance settings and hands the channels to the action layer.
channels/notify
Package notify is what the notify-only channels (email, ntfy, webhooks) share: turning a channel-agnostic actions.Message into plain text and HTML, and the link back to the web.
Package notify is what the notify-only channels (email, ntfy, webhooks) share: turning a channel-agnostic actions.Message into plain text and HTML, and the link back to the web.
channels/ntfy
Package ntfy sends reminders as push notifications through ntfy (https://ntfy.sh or a self-hosted server).
Package ntfy sends reminders as push notifications through ntfy (https://ntfy.sh or a self-hosted server).
channels/slack
Package slack (piece ③) connects Exhale to a Slack workspace over Socket Mode: a WebSocket the app opens outward, so no public URL or open port is needed (ADR 0001, 0007).
Package slack (piece ③) connects Exhale to a Slack workspace over Socket Mode: a WebSocket the app opens outward, so no public URL or open port is needed (ADR 0001, 0007).
channels/telegram
Package telegram (piece ②) connects Exhale to a Telegram bot over long polling: an outbound connection, so no public URL or open port is needed (ADR 0001, 0007).
Package telegram (piece ②) connects Exhale to a Telegram bot over long polling: an outbound connection, so no public URL or open port is needed (ADR 0001, 0007).
channels/webhook
Package webhook sends each reminder as one HTTP POST with a JSON body to an address the member chooses.
Package webhook sends each reminder as one HTTP POST with a JSON body to an address the member chooses.
channels/webpush
Package webpush sends reminders as Web Push notifications to the browsers and installed apps (PWA) where a member turned them on (ADR 0026).
Package webpush sends reminders as Web Push notifications to the browsers and installed apps (PWA) where a member turned them on (ADR 0026).
channels/webpush/pushtest
Package pushtest is a fake Web Push service and a fake browser for tests.
Package pushtest is a fake Web Push service and a fake browser for tests.
desktop
Package desktop is Exhale installed as a desktop app (ADR 0029, 0030, 0032).
Package desktop is Exhale installed as a desktop app (ADR 0029, 0030, 0032).
domain
Package domain (piece ⑧) holds the entities and business rules of Exhale.
Package domain (piece ⑧) holds the entities and business rules of Exhale.
engine
Package engine is the billing time engine (piece ⑨): civil dates and billing-style recurrence.
Package engine is the billing time engine (piece ⑨): civil dates and billing-style recurrence.
fx
Package fx (piece ⑤) downloads the European Central Bank's daily reference rates: free, no API key, about 30 currencies (ADR 0008).
Package fx (piece ⑤) downloads the European Central Bank's daily reference rates: free, no API key, about 30 currencies (ADR 0008).
httpapi
Package httpapi (piece ①) serves the REST API (huma, OpenAPI 3.1), live events (SSE), the MCP endpoint, health checks and the embedded web UI.
Package httpapi (piece ①) serves the REST API (huma, OpenAPI 3.1), live events (SSE), the MCP endpoint, health checks and the embedded web UI.
i18n
Package i18n holds the languages Exhale speaks and the translations of what chat and the service say (ADR 0023).
Package i18n holds the languages Exhale speaks and the translations of what chat and the service say (ADR 0023).
importer
Package importer turns files from other tools into Exhale import items: a Wallos database or export, a spreadsheet saved as CSV, or Exhale's own export.
Package importer turns files from other tools into Exhale import items: a Wallos database or export, a spreadsheet saved as CSV, or Exhale's own export.
merchant
Package merchant reduces the description a bank writes for a payment to the words that identify who was paid, so "NETFLIX.COM 866-579-7172 CA", "Netflix.com Amsterdam" and a subscription called "Netflix" compare equal.
Package merchant reduces the description a bank writes for a payment to the words that identify who was paid, so "NETFLIX.COM 866-579-7172 CA", "Netflix.com Amsterdam" and a subscription called "Netflix" compare equal.
money
Package money (piece ⑩) represents exact amounts of money in a currency.
Package money (piece ⑩) represents exact amounts of money in a currency.
netguard
Package netguard keeps HTTP requests to addresses chosen by users (webhook URLs, ntfy servers) away from the server's own machine and network.
Package netguard keeps HTTP requests to addresses chosen by users (webhook URLs, ntfy servers) away from the server's own machine and network.
oauth
Package oauth is Exhale's own OAuth 2.1 authorization server, the part of the MCP authorization spec that lets a cloud assistant (Claude.ai, ChatGPT, Grok) connect to a person's Exhale by its URL (ADR 0018 milestone 3, ADR 0024).
Package oauth is Exhale's own OAuth 2.1 authorization server, the part of the MCP authorization spec that lets a cloud assistant (Claude.ai, ChatGPT, Grok) connect to a person's Exhale by its URL (ADR 0018 milestone 3, ADR 0024).
platform
Package platform (piece ⑮) holds process-level concerns: data directory, logging and supervision of long-running services.
Package platform (piece ⑮) holds process-level concerns: data directory, logging and supervision of long-running services.
scheduler
Package scheduler (piece ⑪) is Exhale's clock.
Package scheduler (piece ⑪) is Exhale's clock.
store
Package store (pieces ⑬ and ⑭) owns the SQLite database: opening it with safe pragmas, running migrations after an automatic backup, and mapping rows to domain types.
Package store (pieces ⑬ and ⑭) owns the SQLite database: opening it with safe pragmas, running migrations after an automatic backup, and mapping rows to domain types.
testutil
Package testutil holds shared test helpers.
Package testutil holds shared test helpers.
toolschema
Package toolschema turns a use case of the op catalog into the JSON Schema of a model tool.
Package toolschema turns a use case of the op catalog into the JSON Schema of a model tool.
update
Package update keeps Exhale up to date from its GitHub releases (ADR 0033).
Package update keeps Exhale up to date from its GitHub releases (ADR 0033).
Package web embeds the compiled web UI (built with Vite into web/dist).
Package web embeds the compiled web UI (built with Vite into web/dist).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL