householdplan
Generate a written household financial plan: policies by domain, an action register, an assumptions table where every value carries a rationale and a revisit trigger, and the scaffolding to keep the plan current after it is written.
A household plan records what you do when something happens, so the decision gets made once, in advance, rather than under pressure. Most plans go stale because nothing forces the assumptions to be revisited and nothing records why a number was chosen. This tool generates both parts: the document, and the review structure around it.
Thirty-one policy rules across eleven domains, two dependencies, no language model, and no network access. The same inputs always produce the same document, because policy text comes from a YAML corpus rather than from generated prose.
Educational. Not legal, tax, or investment advice.
Install
pip install householdplan
Python 3.11+. Two dependencies (pydantic, pyyaml). No network access, no telemetry, no
language model: policy text comes from a YAML corpus, so the same inputs always produce the
same document.
Use
householdplan draft examples/couple.yaml -o plan.md # the plan document
householdplan validate plan.md # structural checks
householdplan scaffold -o planrepo/ # appendices + review template
householdplan export-rules -o rules.json # the corpus, for other runtimes
Use as a library
Everything public is importable from the package root, so internal layout can change without breaking you:
from householdplan import PlanHousehold, PlanSpec, build_document, load_rules, render_markdown
spec = PlanSpec(
household=PlanHousehold(couple=True, taxable=True),
effective_date="2026-03-01",
values={"savings-rate.rate": 20, "reserve-floor.months": 6},
)
document = build_document(spec, load_rules())
markdown = render_markdown(document)
load_rules() caches the parsed corpus, and the rules it returns are frozen, so calling it
per request is cheap and no caller can rewrite policy text for another.
Storing a plan
PlanSpec() is valid with no arguments, which is right for a draft being filled in and
wrong for a payload coming back from storage: a read that fails and returns an empty mapping
would otherwise produce a complete-looking document instead of an error. Load stored specs
through from_stored, which refuses anything untagged:
payload = spec.for_storage() # stamps schema_version
restored = PlanSpec.from_stored(payload)
PlanSpec.from_stored({}) # ValueError: no schema_version
PlanSpec.from_stored(None) # TypeError: not a mapping
This is a backstop rather than a substitute for a storage layer that raises on its own read failures.
What it generates
draft emits a seven-section document:
- Why we manage money this way
- Goals, in priority order
- Policies, grouped by domain
- Action register
- Assumptions
- Review and change policy
- Appendices to write next
scaffold emits the layer that keeps it alive: eleven numbered appendix skeletons (00
Summary through 10 References) with their table headers in place, a quarterly review
template whose sections map one-to-one onto those appendices, and a review log.
Policy domains
Cash flow, liquidity, debt, investing, taxes, equity compensation, insurance, goals, retirement, estate and handoff, governance.
Each rule declares which households it applies to, so a solo household without equity compensation never sees rules written for a couple with vesting stock. A rule you switch off is recorded as a deliberate omission rather than dropped silently, which keeps a later review from relitigating a decision that was already made.
Rules are data
The corpus lives in YAML, one file per domain:
- id: reserve-floor
domain: Liquidity
label: Cash reserve floor and what happens if it breaks
relevant: always
default_on: true
inputs:
- {key: months, label: Reserve floor, kind: num, suffix: months of essential spending}
assumption_keys: [months]
variants:
- when: always
text: "{We} hold at least {n:months} months of essential spending in {t:accounts}.
If reserves fall below that floor, optional taxable investing pauses until
the floor is restored."
relevant and when are boolean expressions over six household flags (couple,
dependents, both_retirement_plans, equity_comp, taxable, near_retirement)
combined with and, or, not, and parentheses. A recursive-descent parser handles them,
so a corpus file cannot execute anything and an unknown flag name fails at load.
Because the corpus is data rather than code, export-rules emits it as JSON for other
runtimes to render, and a single edit to a policy sentence reaches every consumer.
Validation
validate runs ten structural checks: every enabled rule's inputs are bound, every
assumption has a rationale and a revisit trigger, every action has an owner and a due date,
goals are uniquely ranked, the disclaimer is present, no individualized securities advice, no
overstated certainty, every number in the prose traces to a bound input, an effective date is
set, and switched-off domains are recorded rather than dropped.
Scope
This generates a policy document from inputs you supply. It does not run projections, pick investments, or give individualized advice. Numbers you put in come back out with their rationale attached; it does no arithmetic of its own.
Related
The plan document pairs with projection tools rather than replacing them. A projection tells
you whether the numbers work; this records what you will do when they stop working.
planner-lab consumes this package as an optional
extra and can build a plan straight from a typed case file, so the policy figures and the
memo figures come from the same source.
License
MIT
#personal-finance #financial-planning #investment-policy-statement #household-budget
#retirement-planning #financial-independence #document-generation #markdown
#python #pydantic #deterministic #no-llm #open-source-finance #money-management
#financial-literacy
Metadata
Release files for householdplan 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| householdplan-0.2.1.tar.gz | 103.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| householdplan-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 150.9 kB
Release files / householdplan-0.2.1.tar.gz
| Download URL | householdplan-0.2.1.tar.gz |
|---|---|
| Size | 103.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ae89144b7568c956d5ff822dc5c5bbd82495ee6665c5efb3e81fcdfe3401f4a2
|
|
BLAKE2b-256 checksum How to use checksums |
56086ed16d1150d46cdf671ea7ce9cb9c3ea9fcb8de9a06e799b009322a4830d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.
Transparency logRelease files / householdplan-0.2.1-py3-none-any.whl
| Download URL | householdplan-0.2.1-py3-none-any.whl |
|---|---|
| Size | 47.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ddf54c83f7e9a66b88d4ce6f8755d5cb089a84d9d263c9787371746ca6254f1d
|
|
BLAKE2b-256 checksum How to use checksums |
906ca1e439a4ad531295586b1bd7fa1e8b90844ccc56e73bafdc01c08eff380c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 9, 2026.
Transparency log