myMeans
myMeans maintains ledger-cli books from bank data.
It can import legacy CSV statements or stage read-only Plaid changes through a local journal, then categorize entries and generate reports without giving a remote provider write access to financial accounts.
Its separate means-plan surface also projects explicit, fictional or private cashflow and debt assumptions without reading or mutating a Ledger.
Version 1.0 is the first stable release: the bank-sync safety model, deterministic planning surfaces, and scenario-lab interfaces are exercised and documented.
Install
myMeans requires Python 3.13 or newer and the ledger executable.
Install ledger-cli through your operating system, verify it first, then install myMeans from PyPI:
ledger --version
uv tool install my-means
means-bank --help
pipx install my-means is equivalent.
For library use, add it to a Python project with uv add my-means.
The optional LLM classifier uses Anthropic's SDK and is kept out of the base accounting install:
uv tool install 'my-means[llms]'
Choose an ingestion path
| Path | Use it when | Mutation boundary |
|---|---|---|
| Plaid bank sync | Accounts are linked and supported by Plaid | fetch updates the private journal; only an explicit reviewed apply replaces the generated sidecar |
| CSV import | A provider is unsupported or exports are the source of record | ingest converts statement files into the configured manual ledger workflow |
The two paths can coexist. Keep unsupported institutions explicit instead of silently treating them as synchronized.
Read-only Plaid workflow
Point every command at one configured means directory:
export MY_MEANS=/path/to/your/means-directory
means-bank --directory "$MY_MEANS" status --json
The normal cycle is deliberately staged:
# 1. Fetch through your secret-injection wrapper; credentials never belong in argv.
pass-cli run --env-file /path/to/bank-sync.env.pp -- \
means-bank --directory "$MY_MEANS" fetch --json
# 2. Inspect provider accounts by opaque ID and bind each one once.
means-bank --directory "$MY_MEANS" accounts --json
means-bank --directory "$MY_MEANS" bind \
--account account-opaque-example \
--ledger-account funds:owner:checking
# 3. Create an immutable preview; this does not replace the live sidecar.
means-bank --directory "$MY_MEANS" plan --json
# 4. After reviewing preview_path, apply that exact plan ID explicitly.
means-bank --directory "$MY_MEANS" apply --plan plan-opaque-example --json
apply performs no network calls.
It rejects stale source or ledger hashes, unresolved bindings, ambiguous transfers, overlapping manual entries, invalid Ledger output, and unknown crash-recovery state.
Running the same unchanged cycle again is a no-op.
Initial Hosted Link setup and Proton Pass token storage are documented in the bank-sync CLI guide. The architecture and recovery invariants live in the bank-sync overview.
Categorize new entries
The deterministic path is interactive and local:
categorize --directory "$MY_MEANS" --auto
--auto accepts only unambiguous historical matches; the remaining entries stay interactive.
For new memo patterns, suggest asks an economical hosted model to propose reusable templates.yaml entries.
The only required secret is the standard environment variable read by the Anthropic SDK:
export ANTHROPIC_API_KEY=your-api-key
export MEANS_LLM_MODEL=claude-haiku-4-5-20251001 # optional; this is the default
# Preview the response without changing templates.yaml.
suggest --directory "$MY_MEANS" --dry-run
# Run again and explicitly confirm before merging the proposed YAML.
suggest --directory "$MY_MEANS"
--model overrides MEANS_LLM_MODEL for one run.
The default is Claude Haiku 4.5, Anthropic's economical current model for high-volume work; model selection remains configurable because provider availability and pricing change.
Privacy boundary:
suggestsends uncategorized memo strings, the existing templates, and the account structure to Anthropic. It never sends API keys through the prompt or telemetry.--dry-runprevents a local file write, but it still makes the remote model request.
The model can only propose templates. A proposal is rejected unless every account path exists, every label is text, every pattern is bounded literal text without regex metacharacters, and no existing pattern is replaced. Existing hand-authored regex templates remain supported; the literal-only restriction applies to untrusted model additions. No suggestion mutates the ledger, and validated template changes still require local confirmation.
Plan from Explicit Assumptions
means-plan produces exact-cent, dated cashflow and debt projections from a standalone YAML or JSON scenario:
means-plan project --scenario fictional-plan.yaml --strategy avalanche --json
means-plan compare --scenario fictional-plan.yaml --csv --output comparison.csv
This is a conditional deterministic projection, not a prediction or financial advice.
Strategy comparison applies a disclosed rule to the calculated outcomes; its recommended field means rule-selected under that comparison objective, not advised.
Likewise, zero warnings means no implemented rule fired, not that a plan is safe or complete.
The command reads no Ledger, provider, or model data and mutates no Ledger.
Keep private scenarios and reports outside this public repository.
The conditional planning guide provides a complete fictional YAML example, schema, exact-cent/date/strategy rules, warning semantics, JSON/CSV contracts, and honest limitations.
The optional tui and web extras add a full-screen terminal interface (means-tui) and a loopback-only browser interface (means-web) over the same scenario-lab service; the interactive interfaces guide covers their install, keybindings, routes, and security posture.
Reports and Python API
Generate local reports after loading and categorizing the books:
report --directory "$MY_MEANS" overview
Google Sheets upload is optional and explicit (--upload).
Without it, report data stays local.
The validated accounting types are also importable directly:
from datetime import date
from means import Transaction
entry = Transaction.new(
date=date(2026, 7, 23),
memo='Neighborhood market',
posts=[
'costs:owner:food 24.50',
'funds:owner:checking',
],
)
assert entry.remainder == 0
See the full MyST documentation for the data model and API reference.
Safety model
- Provider access is read-only; myMeans has no money-movement API.
- Fetch, normalize, reconcile, preview, and apply are separate boundaries.
- Provider IDs and fetched payloads stay in an owner-only SQLite journal.
- Unknown categories remain visibly
Unknown; an LLM proposal is never written as fact. - Secrets are injected through environment variables or a secret manager, never CLI flags.
- Telemetry is structural and content-free; financial payloads stay local.
Current limitations
- Plaid coverage depends on the linked institution and product; unsupported accounts need an explicit manual/CSV path.
- Existing Plaid Items cannot extend their original transaction-history window without relinking.
- The package assumes an existing ledger-cli directory and configuration; it is not yet a first-run bookkeeping wizard.
- The legacy accounting models use floating-point amounts; provider sync normalizes exact decimal source values before projection.
- Planning is deterministic scenario math over explicit assumptions; it does not infer missing events, model probability or uncertainty, parse a Ledger into a scenario, or provide financial advice.
- The hosted LLM path is optional and advisory, not a deterministic classifier.
Documentation and development
uv sync --all-extras
task eval
task test:cov
task docs
uv build --no-sources
The docs gate is warning-free and verifies that autodoc signatures render as HTML rather than leaking raw directives. The test suite mocks every LLM request; normal tests never send financial content to a provider.
This project follows workflow-gated semver. Final publishing remains a human-approved GitLab/PyPI release action.
Licensed under the Mozilla Public License 2.0.
Release files for my-means 1.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| my_means-1.0.0.tar.gz | 113.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| my_means-1.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 254.9 kB
Release files / my_means-1.0.0.tar.gz
| Download URL | my_means-1.0.0.tar.gz |
|---|---|
| Size | 113.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
03c46dcfef8e93834a738764e9c806ba29c83742f5c7233ce5338a76ed9c93bf
|
|
BLAKE2b-256 checksum How to use checksums |
9dbba08d0963f9f9460b7d92b9c618eaa49fb0c11439d36e7b34c5a477796654
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / my_means-1.0.0-py3-none-any.whl
| Download URL | my_means-1.0.0-py3-none-any.whl |
|---|---|
| Size | 141.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
14e184fe583b2d3461ef651a17de80f06c193bde6489001bc0c39eb8a4315aff
|
|
BLAKE2b-256 checksum How to use checksums |
d7c1a6ebf618f424f24e83d6018987243f00613b787b784726622f188d928632
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.9.30 {"installer":{"name":"uv","version":"0.9.30","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Debian GNU/Linux","version":"12","id":"bookworm","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|