WYGIWYH deletes by default, and its quick start ends mid-sentence
A simple but powerful self-hosted finance tracker
At a glance
- What is it?
- A self-hosted finance tracker on Django, Postgres and a Vite front end, published under AGPL and deployed by hand-pasting two files into an editor. The design is a spending rule rather than a budget, and the data-retention default is the opposite of what a ledger wants.
- Who is it for?
- Adopt it if your money situation is simple and you want the ledger to enforce one rule rather than to help you plan a budget, because that opinionated stance is the entire product and everything else in the repository serves it. Multi-currency accounts, custom currencies for points and rewards, rules that rewrite transactions, and a dollar-cost averaging tracker cover the cases the author says his spreadsheet could not.
- Can I use it commercially?
- Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
- Is it still maintained?
- Yes. The repository last received commits 2 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 1, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The product is one spending rule, and budgeting is explicitly out of scope
WYGIWYH expands to What You Get Is What You Have, pronounced wiggy-wih, and it describes itself as opinionated by design. The opinion is one sentence: use what you earn this month for this month, and track any savings but treat them as untouchable for future months. That is a rule, not a plan, and the second of the author's five requirements says the tool must not be a budgeting app because he dislikes budgeting constraints. The other four are multi-currency support, web app usability with mobile support as a nice-to-have, an automation-ready API, and custom transaction rules for things like credit card billing cycles. The origin story is a spreadsheet that worked for years and then broke under multiple currencies, multiple accounts and investments, after several commercial apps failed the same list.
The demo disables exactly the features that would justify running it yourself
A public instance is offered at a demo subdomain, with the credentials printed in the README: the e-mail [email protected] and the password wygiwyhdemo. Two conditions come with it. Anything you add is wiped within twenty-four hours or less, and most automation features are disabled, specifically the API, the rules engine, automatic exchange rates and import and export. That list is the problem. Custom transaction rules, the automation API, multi-currency handling and spreadsheet round-tripping are the four reasons in the author's own requirements list, and a visitor to the demo cannot exercise any of them. The demo also runs on somebody else's subdomain rather than the project's own domain, so it reads as a courtesy instance rather than a product surface.
Deleted transactions are gone unless you turn on soft delete, and then they last a year
The environment example is where the real design decisions show. Two variables govern deletion. ENABLE_SOFT_DELETE is false, with the comment that you enable it if you want to keep deleted transactions in the database. KEEP_DELETED_TRANSACTIONS_FOR is 365, described as the number of days after which a soft-deleted transaction is truly deleted, with an instruction to set it to 0 to keep all. So the default for a finance application is that a deletion is a deletion, and the safer mode still carries a one-year horizon that eventually purges rows with no further prompt. That is a defensible choice for a personal tracker and a wrong default for anything you intend to treat as a record.
The environment file will create your admin account from a plaintext password
Three settings in the example environment deserve attention before you paste it in. The first pair is commented out and described as a way to automatically create an admin account using those credentials on startup, with an instruction to remove them after your first successful login. That is convenient and it means a plaintext administrator password sitting in a file on disk, and the safety depends on you following the cleanup step. The database block sets SQL_USER to wygiwyh with the password left as a placeholder to be filled, and points SQL_HOST at the database name variable, which means the host only resolves inside Compose and not on a bare machine. Third, the port pair is split: the app listens on an internal port defaulting to 8000 while the published port defaults to 9005.
Setup means pasting two files into an editor, and the last line stops mid-word
The whole install path is one command block:
# Create a folder for WYGIWYH (optional)
$ mkdir WYGIWYH
# Go into the folder
$ cd WYGIWYH
$ touch docker-compose.yml
$ nano docker-compose.yml
# Paste the contents of https://github.com/eitchtee/WYGIWYH/blob/main/docker-compose.prod.yml and edit according to your needs
# Fill the .env file with your configurations
$ touch .env
$ nano .env # or any other editor you want to use
# Paste the contents of https://github.com/eitchtee/WYGIWYH/blob/main/.env.example and edit accordingly
# Run the app
$ docker compose up -d
# Create the first admin account. This isn't required if you set tThere are no copy commands, only two touch and nano pairs with instructions to paste the repository's own production compose file and environment example. The block then breaks off partway through the sentence about the first admin account, so the step that creates that account from the command line is not shown. For running locally the README is clearer: remove the URL variable, set HTTPS_ENABLED to false, keep the default host list, and open the published port in a browser.
Two deployment paths with different database obligations
The Compose route brings its own database, which is why the environment file can point the application host at the database service name. The second route is a community template: a contributor has published an Unraid template in his own repository, and the application is also on the Unraid Store. That path hands you a specific obligation, because you have to provision your own Postgres at version 15 or newer, and the first account is created by opening the container console from the Unraid interface and running the Django createsuperuser management command. Two smaller notes from the same section. The host list in the documentation table shows only localhost and the IPv4 loopback, while the shipped environment example also includes the IPv6 loopback, so the documented default and the real default are not the same string. And the local instructions warn you to add a machine address without a scheme when you are not on localhost.
Debug toolbar and user impersonation are production dependencies, not dev extras
The Python manifest lists 31 dependencies, and two of them belong in a development extra rather than a finance application's runtime: the Django debug toolbar, pinned exactly, and a package that lets an administrator sign in as another user, also pinned exactly. The pinning is mixed by design and by accident, with 11 dependencies on exact versions, 19 on compatible-release constraints and one on a bare minimum. Beyond those, the stack shows the shape of the product: a Postgres-backed task queue with a single worker by default, connection pooling, query caching, a browsable REST API with OpenAPI schema generation, a progressive web app, a Vite build with a Jinja component library, spreadsheet import for both old and new Excel formats, static file serving straight from the app server, and a market data library for the dollar-cost averaging tracker. The MCP integration appears only in the environment file.
The MCP server is configured in the environment file, and main can break without warning
The navigation bar at the top of the README advertises eight sections, including one for the MCP server, one for translation and one for caveats. The visible text runs out while the environment variable table is still printing, so the only place MCP is described anywhere in what is there is the environment example: a block of commented variables for an OAuth client named WYGIWYH MCP, with an identifier, a secret, redirect URIs, and a note that uncommenting them auto-creates or updates the client used by remote MCP integrations after migrations complete. So the agent-facing surface is real and provisioned by configuration rather than by the first-run wizard. The other thing the environment file exposes is a personal access token setting for how often a token's last-used timestamp is rewritten, in seconds.
Editorial conclusion
Adopt it if your money situation is simple and you want the ledger to enforce one rule rather than to help you plan a budget, because that opinionated stance is the entire product and everything else in the repository serves it. Multi-currency accounts, custom currencies for points and rewards, rules that rewrite transactions, and a dollar-cost averaging tracker cover the cases the author says his spreadsheet could not. Three things to fix on your own instance before you trust it with a year of data. Soft delete is off, so a deleted transaction is gone, and turning it on only buys you 365 days before permanent removal unless you set the retention to zero. The environment file offers to create your admin account from plaintext variables. And the demo cannot show you the automation, because the API, rules, exchange rates and import and export are exactly what it disables. Check what AGPL-3.0 requires of your deployment before you modify it and serve it to anyone.
Frequently asked questions
What is WYGIWYH?
A self-hosted finance tracker, short for What You Get Is What You Have, built on Django with Postgres. Its central rule is that you spend what you earned this month and savings are tracked but treated as untouchable for later months.
How do I run WYGIWYH myself?
With Docker and docker-compose: create a folder, paste the contents of docker-compose.prod.yml into a compose file, paste the contents of .env.example into a .env file, then run docker compose up -d. An Unraid template also exists and requires you to supply your own Postgres 15 or newer.
What does the WYGIWYH demo instance let me try?
A shared instance with the e-mail [email protected] and the password wygiwyhdemo, where anything you add is wiped within twenty-four hours, and the API, rules, automatic exchange rates and import and export are all disabled.
Does WYGIWYH keep transactions after I delete them?
Not by default. Soft delete is off, and when you enable it, transactions deleted for more than 365 days are permanently removed unless you set the retention value to 0 to keep everything.
What does WYGIWYH integrate with?
It exposes a REST API, spreadsheet import and export, automatic exchange rates, and an MCP server for agent integrations. The MCP OAuth client can be created automatically after migrations complete, configured through variables in the environment file.
What license is WYGIWYH under?
AGPL-3.0, with the LICENSE file at the repository root.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/eitchtee-wygiwyh)