Metadata-Version: 2.4
Name: my-means
Version: 1.0.0
Summary: Double-entry accounting in Python based on ledger-cli, the C++ precursor to Beancount.
Author: Robb Doering
Author-email: Robb Doering <robb@doering.ai>
License-Expression: MPL-2.0
License-File: LICENSE
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3.13
Requires-Dist: aiohttp>=3.13.5
Requires-Dist: gitpython>=3.1.45
Requires-Dist: iterfzf>=1.9.0.67.0
Requires-Dist: logfire[system-metrics]>=4.37
Requires-Dist: more-itertools>=10.7.0
Requires-Dist: my-basis[metrics,google]
Requires-Dist: pandas>=2.3.2
Requires-Dist: pydantic>=2.11.7
Requires-Dist: pyyaml>=6.0.3
Requires-Dist: regex>=2025.7.34
Requires-Dist: types-pyyaml>=6.0.12.20260518
Requires-Dist: types-regex>=2026.5.9.20260518
Requires-Dist: unidecode>=1.4.0
Requires-Dist: anthropic>=0.96.0 ; extra == 'llms'
Requires-Dist: textual>=0.86.0 ; extra == 'tui'
Requires-Dist: textual>=0.86.0 ; extra == 'ui'
Requires-Dist: fastapi>=0.115.0 ; extra == 'ui'
Requires-Dist: uvicorn>=0.34.0 ; extra == 'ui'
Requires-Dist: fastapi>=0.115.0 ; extra == 'web'
Requires-Dist: uvicorn>=0.34.0 ; extra == 'web'
Requires-Dist: openpyxl>=3.1.5 ; extra == 'workbook'
Requires-Python: >=3.13
Project-URL: Homepage, https://gitlab.com/doering-ai/apps/means
Project-URL: Source, https://gitlab.com/doering-ai/apps/means
Project-URL: Issues, https://gitlab.com/doering-ai/apps/means/-/issues
Project-URL: Documentation, https://gitlab.com/doering-ai/apps/means/-/blob/main/docs/index.md
Provides-Extra: llms
Provides-Extra: tui
Provides-Extra: ui
Provides-Extra: web
Provides-Extra: workbook
Description-Content-Type: text/markdown

# myMeans

[![Pipeline status](https://img.shields.io/gitlab/pipeline-status/doering-ai/apps/means?branch=main)](https://gitlab.com/doering-ai/apps/means/-/pipelines) [![Test coverage](https://img.shields.io/gitlab/pipeline-coverage/doering-ai/apps/means?branch=main)](https://gitlab.com/doering-ai/apps/means/-/graphs/main/charts) [![Python 3.13+](https://img.shields.io/badge/python-3.13%2B-blue)](pyproject.toml) [![MPL-2.0 license](https://img.shields.io/badge/license-MPL--2.0-green)](LICENSE)

myMeans maintains [ledger-cli](https://ledger-cli.org) 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](https://pypi.org/project/my-means/):

```sh
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:

```sh
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:

```sh
export MY_MEANS=/path/to/your/means-directory
means-bank --directory "$MY_MEANS" status --json
```

The normal cycle is deliberately staged:

```sh
# 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](docs/cli.md).
The architecture and recovery invariants live in [the bank-sync overview](docs/bank_sync.md).

## Categorize new entries

The deterministic path is interactive and local:

```sh
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:

```sh
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:** `suggest` sends uncategorized memo strings, the existing templates, and the account structure to Anthropic.
> It never sends API keys through the prompt or telemetry.
> `--dry-run` prevents 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:

```sh
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](docs/planning.md) 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](docs/interfaces.md) covers their install, keybindings, routes, and security posture.

## Reports and Python API

Generate local reports after loading and categorizing the books:

```sh
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:

```python
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](docs/index.md) 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

```sh
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](https://gitlab.com/doering-ai/corpus/-/blob/main/docs/versioning.md).
Final publishing remains a human-approved GitLab/PyPI release action.

Licensed under the [Mozilla Public License 2.0](LICENSE).
