Skip to content

Releases: DigiMonk73/BTCTX-MCP

v1.2.4 · StartOS package 1.2.4:0

Choose a tag to compare

@github-actions github-actions released this 01 Oct 00:15

Small fixes found by the 1.2.3 test walk on StartOS, with no change to any
tax figure: checked on every test ledger and, before release, on the owner's
own ledger upgraded from 1.2.3 (every row, form, gain and CSV row the same).
The database moves to schema 0005 once (a copy is kept in backups/ first).

Removed

  • The unused transaction lock. Nothing in the app could lock a row (no
    button, API field or import set it), yet a locked row would have refused
    edits and deletes with "not found" while recalculation still changed its
    figures. It is gone rather than finished: database schema 0005 drops the
    column (the usual copy of the database goes to backups/ first), API
    answers no longer carry is_locked, and editing or deleting a missing
    transaction says "Transaction not found." No figure changes (checked on
    every test ledger). As with any schema change, an older BitcoinTX then
    refuses the database; the backup copy is the way back.

Fixed

  • Escape closes the transaction panel, like a click outside it: at
    once when nothing was changed, else after "Discard changes?". With that
    question showing, Escape answers Go back and keeps your changes. The panel
    learns of a change at once, so Escape or a click outside right after one
    still asks. Found by the 1.2.3 VM walk.
  • On a phone, every tab in the header fits on screen. At 375 px the
    header needed 407 px, so Logout was cut off at the edge ("Logo") and only
    reachable by scrolling the header sideways. Up to 480 px wide the tabs are
    now a little smaller and spread across the width; they fit from 340 px
    (narrower screens still scroll). Found by the 1.2.3 VM walk.
  • A CSV export re-imported gives back its zero fees. The import dropped
    a fee of 0, so rows saved with "0 USD" or "0 BTC" came back with no fee
    and no fee currency. Every figure was already the same (a zero fee and no
    fee count alike), but a CSV backup now restores exactly what was saved. A
    blank fee in a file still means no fee. Found by the 1.2.3 VM walk.

Development

  • CI and the release build pin Node 22.23.2 for the StartOS package.
    GitHub's runners moved to Node 22.23.3, whose headers fail to build
    diskusage, a native module that Start9's mempool-startos dependency
    pulls in; the release's package build would have failed the same way.
  • The web app's error-message helper moved from hooks/useApiCall.ts
    (it held no hooks) into utils/apiError.ts, beside the other one; its
    tests moved unchanged.
  • The stress tests fail on a refused save instead of carrying on
    without the row, except where a random ledger may ask for more than is on
    hand, and their random amounts and dates are the same on every run. The
    backdating test now checks that its ten backdates were saved.
  • The CSV export prints numbers from their exact value, not through a
    float. Nothing an export writes changes (checked on every test ledger):
    a value is already rounded to its column's decimals when it is read, so
    the float could only lose digits past about 16, far beyond real amounts.
  • A release's title names its StartOS package version, for example
    "v1.2.3 · StartOS package 1.2.3:0", and so does its StartOS download line:
    the number StartOS and the mirror's releases show (the app version plus
    the package's own revision). The tag stays vX.Y.Z, which the Mac app,
    the Docker image and the AI connector share. v1.2.3's release was
    retitled to match.

Downloads

  • StartOS: btctx.s9pk, package 1.2.4:0. In StartOS, open Sideload and upload it; installs of earlier versions update in place.
  • macOS: BitcoinTX-macOS.dmg (or the .zip). The app is not signed by Apple: the first time, right-click (Control-click) BitcoinTX in Applications and choose Open; on macOS 15 or later, open it once, then go to System Settings > Privacy & Security and click Open Anyway.
  • Docker: ghcr.io/digimonk73/btctx-mcp:v1.2.4 (amd64 and arm64).
  • AI connector: uvx btctx-mcp==1.2.4 (PyPI); Settings → Connect an AI Assistant has it ready to paste.

v1.2.3 · StartOS package 1.2.3:0

Choose a tag to compare

@github-actions github-actions released this 30 Sep 02:10

A maintenance release with no new features. The code behind the app was
reorganized (long functions divided into named steps, the web app's big
components split, filler comments and unused code removed) with one rule:
nothing it produces may change. Every figure, database row, Form 8949 field,
report PDF (byte for byte), CSV, import preview, API answer, AI tool output
and error message was compared with 1.2.2-1's on the golden ledger, the
seed ledger, 40 random ledgers in three timezones and about 2,200 bad
inputs; every page and form was recorded before and after. The only
differences are the two fixes below. Recalculation is about 7% faster.

Fixed

  • A CSV row with an unknown fee_usd_typed value (anything but yes, no
    or blank) crashed the import preview with a server error; it is now a row
    error, "Must be yes, no or blank." Found by the new equivalence check's
    bad inputs.
  • Ledger Review's fee check no longer hides errors. Looking for
    transfers whose fee value is off the day's price, it passed over a
    transfer on any error while getting that day's price, so a broken
    database or a bug looked like "nothing to fix". It now passes over only
    a day with no price; anything else is reported as an error.

Development

  • Code cleanup, no change in behaviour:
    the standards are written down in docs/CODE_STYLE.md, and CLAUDE.md
    points to them. scripts/equivalence_check.py compares everything the
    app produces (database rows, API answers, Form 8949 field values, report
    PDFs byte for byte, CSV files, import previews, MCP tool outputs, the
    error message of each of about 2,200 bad inputs) with v1.2.2-1's, and
    times recalculation (docs/TESTING.md).
  • Every Transaction column is in the CSV export or on a list saying why
    not
    (test_csv_export_columns.py), so a new column can't be left out of
    the export unnoticed, as three were before 1.2.1.
  • Comments and docstrings say what each module is for and why the code
    does what it does: no file-path headers, banner dividers, history notes
    or narration. The Transaction model's column descriptions no longer call
    its main fields "legacy". Two pieces of dead code went: main.py's empty
    __main__ block and an unused services.user.delete_user.
  • Modern type hints (list[str], dict, X | None) in the app code,
    and ruff's UP rules keep it that way (tests and migrations excepted).
  • The complete tax report is built one section at a time
    (complete_tax_report.py, from one 510-line function), with the paragraph
    styles and grid tables it shares with the transaction history in
    reports/pdf_layout.py. Its PDFs are byte-identical.
  • The transaction history and the Form 8949 field mapping are divided
    the same way: the history's columns and widths are one table, its PDF
    uses the shared layout; a Form 8949 page's checkbox, row fields and line 2
    totals are named steps. Same PDFs, CSVs and field values.
  • The CSV import guide's script keeps its tables as data and builds
    one section per method (backend/scripts/generate_csv_instructions_pdf.py,
    from one 395-line function); the PDF it writes is byte-identical, and the
    committed one is unchanged.
  • The CSV import checks a row one field at a time (csv_import.py:
    _validate_row was 276 lines), with the account rules per type as a
    table and each type's own rules in their own function; the template's
    sample rows are data. Two branches that could never run are gone.
    Checked on 40,728 generated rows: the same errors, warnings, previews and
    transactions.
  • The River import reads each kind of River row in its own step, finds
    duplicates in an exact and a rough pass, and the import endpoint checks,
    stubs and saves rows in named steps. Same proposals, warnings, matches and
    imports (3,000 random files and 3,000 random ledgers compared).
  • The dashboard's gains (get_gains_and_losses, 179 lines) add up
    realized gains, proceeds, income by source, fees and this year's gain in
    one step each. Same figures on every ledger compared, including ones with
    sales this year.
  • Ledger Review, the CSV export, the AI entry dry run, the public price
    download, the IRS form filler, the adoption of a pre-migration database
    and the AI connector's request and update_transaction
    are divided
    into named steps too; the connector's tools, their schemas and outputs
    are unchanged.
  • The ledger engine (transaction.py) reads as its steps: create and
    edit (check, complete, insert or apply, recalculate), the ledger lines per
    kind of transaction, FIFO disposal and transfer lot moves, the input checks
    in their fixed order and each type's account rules as a table. Two unused
    functions are gone. Same lines, lots, disposals, figures and messages on
    every ledger and bad input compared; recalculation no slower.
  • The transaction form (TransactionForm.tsx, 1,049 lines) keeps the
    form's state, saving and deleting; each transaction type's fields, the
    shared account and fee fields, the autofill and the save request are their
    own files in components/transactionForm/. Every form variant renders the
    same labels, roles and HTML (e2e/ui-snapshot.e2e.ts).
  • The Settings page (799 lines) is its sections: Account, Data
    Management (with the CSV import's preview) and Backup & Restore are their
    own components, next to the ones it already had; the page keeps the one
    action at a time and the message line they share. Same page, labels and
    messages.
  • The River import panel (486 lines) keeps the upload and the import;
    the preview, one row and its editable cells are their own components, and
    the row logic (the accounts a new type implies, the import request) is in
    utils/riverImport.ts with a unit test. The two import previews share
    one date format and one "server's reason, else…" message helper. Same
    preview after every edit a row allows (recorded before and after).
  • The Dashboard (470 lines) fetches its figures and lays out four
    cards, each its own component; the account totals and the gain/loss
    colour are in utils/dashboard.ts with a unit test. Same cards, figures
    and HTML.
  • The rest of the frontend over the limit: the transaction form's
    mapping to and from the API is one small step per transaction type (the
    same results on 40,000 random forms and transactions, compared), the
    Transactions page's sorting, paging and day groups are in
    utils/transactionList.ts, Privacy & network's "anything changed?" is
    one tested function, and the error message for a failed request is read
    in two steps (the same message for 20,000 random failures).
  • Frontend comments and unused code, as in the backend: no file-path
    headers, banner dividers, history notes ("NEW", "ADDED", "legacy") or
    comments that repeat the code. Gone because nothing used them: three hook
    files and four API hooks (src/hooks/ keeps the error message),
    formatTimestamp, two types, and five dashboard fields the server has
    never sent. The built app is byte-identical but for those five fields.
  • Lint limits each function's size, so the long functions can't grow
    back: Python (ruff: complexity 10, 12 branches, 50 statements, 6 returns;
    tests and migrations exempt) and the frontend (ESLint: complexity 15 per
    function, 400 lines per file; tests exempt).
  • The StartOS mirror stays current between releases: a docs-only change
    to startos/ goes to DigiMonk73/BTCTX-StartOS right away (CLAUDE.md),
    since Start9's build there ignores those files. Anything else waits for a
    release.
  • Roadmap: the AI connector will follow the app's version, chosen over
    uvx btctx-mcp@latest.

Downloads

  • StartOS: btctx.s9pk, package 1.2.3:0. In StartOS, open Sideload and upload it; installs of earlier versions update in place.
  • macOS: BitcoinTX-macOS.dmg (or the .zip). The app is not signed by Apple: the first time, right-click (Control-click) BitcoinTX in Applications and choose Open; on macOS 15 or later, open it once, then go to System Settings > Privacy & Security and click Open Anyway.
  • Docker: ghcr.io/digimonk73/btctx-mcp:v1.2.3 (amd64 and arm64).
  • AI connector: uvx btctx-mcp==1.2.3 (PyPI); Settings → Connect an AI Assistant has it ready to paste.

v1.2.2-1

Choose a tag to compare

@github-actions github-actions released this 29 Sep 20:58

Package-only update; BitcoinTX itself is unchanged.

StartOS package

  • The icon is BitcoinTX's own logo, the gold coin the app, the landing
    page and the screenshots show, as a 39 KB WebP (startos/icon.webp, under
    Start9's 40 KiB limit). It replaces the simplified vector copy drawn for
    the size limit (decision of 2026-09-23); Start9's guide asks for the real
    asset rather than a redrawn one. The release notes still carry 1.2.2's
    for anyone updating from 1.2.1 or earlier.

Documentation

  • Screenshots of 1.2.2 in the README and on the landing page (same demo
    ledger): the whole taller calculator, 2025 picked in Reports, and the
    AI setup prompt with today's uvx btctx-mcp==1.2.2 instead of 1.1.0's.

Development

  • To-dos are checkboxes. Specific to-dos live in docs/temp/TODO.md,
    the StartOS package's in startos/TODO.md (Start9's standard file, so it
    reaches the repository Start9 forks), and what's next in docs/ROADMAP.md.
    Every item is - [ ], ticked when done and cleared at the release that
    ships it; a finished plan is deleted and its roadmap box ticked.
    test_todo_lists.py checks the format. The 1.2.2 privacy audit is now
    docs/PRIVACY_AUDIT.md; the finished stabilization plan is gone.
  • The StartOS package always keeps Start9's packaging rules, checked by
    test_startos_conformance.py: the standard layout, the README's fixed
    headings (each opening with a sentence) and no version numbers,
    documentation links Start9's indexer can parse, and TODO.md as Start9's
    worklist (# TODO, an item removed when done rather than ticked). Fixed
    on the way: the Quick Reference section now opens with a sentence, and
    instructions.md links whole files without #anchors and drops the
    package's own README, which isn't upstream documentation.
  • After Start9 forks the package, releases reach them only by pull
    request, and the release makes sure it isn't forgotten.
    The release
    workflow's first job runs scripts/start9-pull.sh --check and stops before
    publishing anything if Start9 changed their fork and startos/ doesn't
    have it yet (the mirror sync would undo it). After the mirror push it
    opens an issue, "Send vX.Y.Z to Start9", with a link that opens the pull
    request ready to create, unless one of ours is still open there (it then
    carries the new release). The script finds the fork itself (--fork),
    since Start9 renames forks and may use another branch; tests cover it
    with local repositories.

Downloads

  • StartOS: btctx.s9pk. In StartOS, open Sideload and upload it; installs of earlier versions update in place.
  • macOS: BitcoinTX-macOS.dmg (or the .zip). The app is not signed by Apple: the first time, right-click (Control-click) BitcoinTX in Applications and choose Open; on macOS 15 or later, open it once, then go to System Settings > Privacy & Security and click Open Anyway.
  • Docker: ghcr.io/digimonk73/btctx-mcp:v1.2.2 (amd64 and arm64).
  • AI connector: uvx btctx-mcp==1.2.2 (PyPI); Settings → Connect an AI Assistant has it ready to paste.

v1.2.2

Choose a tag to compare

@github-actions github-actions released this 29 Sep 14:50

Stabilization after 1.2.1: no new features. Found by testing the published
1.2.1 on a StartOS VM, a bug hunt of the tax engine, the imports and the AI
connector, and a privacy audit (2026-09-29). Each fix has a test that
failed before it.

Changed

  • The sidebar calculator is a little taller (owner's request): its keys
    are slightly longer, so it ends level with the Dashboard's Realized
    Gains/Losses card. The Sats Converter's price area is now the same height
    in Manual, Auto and Date, so the calculator no longer moves when you
    switch; in Date mode the day's price sits beside "Select date".

Fixes to tax figures

  • Changing a transaction's type no longer keeps the old type's fields.
    A Gift changed into a Sell stayed a "gift" and was missing from Form 8949
    and Schedule D; a withdrawal changed into an Income deposit reported the
    old lots' cost basis as the income instead of that day's value. (Only the
    AI connector or the API can change a type; the form locks it.)
  • A fee entered without its currency now counts. Adding a fee on its
    own (e.g. by the AI connector) left a Sell's proceeds and a Buy's cost
    basis without it, and took a withdrawal's BTC fee from the balance with
    no disposal or value. The fee now gets its type's currency (USD for Buy
    and Sell, else the account's) and is saved with it; entries already saved
    that way are fixed by the next recalculation (which needs that day's
    price, or the fee's value typed in, for a BTC fee).
  • Pay the AI adds as an Income deposit into Bank or Exchange USD is no
    longer valued at the BTC price
    ($5,000 became $250 million of income);
    likewise a Spent or Gift withdrawal from a USD account. Only BTC accounts
    are valued at the day's BTC price.
  • Dates given to the AI connector are read as when adding. Changing a
    transaction's date read it as UTC, so in the US a sale moved to Jan 1
    landed on Dec 31, in the previous tax year; a date alone is now midday in
    your tax timezone. A time ending in " UTC" is read as UTC (it was read in
    the tax timezone), and finding transactions by date uses days in your tax
    timezone.
  • A second Buy of the same amount at another price can be saved through
    the AI.
    A Buy of the same BTC amount within 48 hours was taken for a
    duplicate even at a different price, skipped, and could never be saved.
    It's now a possible duplicate the AI asks you about; only the very same
    buy (same amount and price) is skipped.
  • Export CSV then Import CSV keeps the order of same-time entries. The
    import put them in a fixed type order (moves before sales), which could
    change which coins a sale used and its gain; rows at the same time now go
    in the file's order (the export's is the ledger's). A hand-made file that
    lists a sale before the same-time buy paying for it is refused, and the
    message says to list the buy first.
  • Form 8949 line 2 "Totals" is filled. Each page now shows the totals of
    its own rows in (d), (e) and (h), which add up to the Schedule D line; it
    was left blank on the locked PDF, so it couldn't be typed in either.
  • A sale drawn from several lots no longer loses cents. Each lot's share
    of the proceeds was rounded on its own ($100.00 over three lots showed as
    $99.99 on Form 8949); the last share now takes the remainder.
  • A withdrawal of 1 satoshi more than you hold is refused, like a
    transfer or sale. It was accepted and left the balance at -1 sat.
  • A time with fractions of a second no longer lands in the wrong year.
    A sale entered (through the API or the AI connector) half a second after
    midnight on Jan 1 counted in the year before; times are now saved in
    whole seconds.
  • A Spent withdrawal changed into a Gift, Donation or Lost no longer keeps
    its proceeds
    , which the complete tax report printed in its Gifts
    section. (The network fee is still its own taxable disposal.)

Other fixes

  • The Sats Converter no longer shows "BTC Price: $0.00" without a price.
    With prices off it says "Prices off", after an error or for a day with no
    stored price "No price", and the USD field empties instead of keeping an
    old figure (BTC and sats still convert).
  • My Mempool not answering is an error, not "Prices off". With your
    Mempool chosen but missing or not answering (and the fallback off), the
    Dashboard said "Prices off"; it now says "Error", and hovering it shows
    why (e.g. install and start Mempool).
  • Clearer messages when no price is stored. A transfer's missing fee
    value names the form's Fee value (USD) field (and fee_usd for
    imports), and a new Spent withdrawal without proceeds is no longer told
    to "edit that transaction".
  • The complete tax report says where its prices come from. It claimed
    "the average market value at the time of disposal"; it now says values
    are the ones entered, a blank one comes from that day's stored daily
    price, and dates are in the tax timezone (named).
  • An import no longer freezes the whole app while it works. A CSV,
    River or AI-assistant import (or its preview) held up every other
    request, StartOS's health check included, for as long as it ran (10
    seconds in one test); that work now runs beside them.
  • The CSV import reads Excel's "CSV UTF-8" files. Their invisible
    byte-order mark made the import say "Missing required columns: date".
  • A River file row with one comma too many is that row's error. A
    trailing comma or an amount written 1,000.00 made the River import fail
    with a server error.
  • A River Sell whose Fee Currency is blank is no longer a fee short. A
    blank fee currency on a River Buy or Sell counts as USD, as River charges
    it, so the sale lands at River's Received Amount.
  • When BitcoinTX's address redirects (e.g. http:// to https://), the
    AI connector says so and which address to set in BTCTX_URL, instead of
    an unclear error or a blank price. It still never follows a redirect, so
    the AI key only goes to that address.
  • Keyboard focus shows in the Mac app on older macOS. On Safari before
    15.4 (macOS 10.15 to 12.2) no focus ring was drawn at all; the browser's
    own ring now stays there, and newer versions keep the gold one.

Privacy (docs/temp/privacy-audit.md)

  • The AI connector no longer writes request addresses to the AI app's log
    files; past-price lookups named your transaction dates there.
  • An .onion mempool address needs the proxy: it's refused without one (it
    was looked up through the normal DNS, which then saw the name).
  • An encrypted backup no longer passes through a plain copy in the system's
    temp folder, and a restore's decrypted file is owner-only from the moment
    it's written.
  • Making reports no longer logs how many transactions, disposals and lots
    each year has (now only at the DEBUG log level).
  • The Docker instructions start BitcoinTX reachable from your computer
    only (-p 127.0.0.1:8080:80), with a note to put it behind HTTPS for
    other devices; the old command sent your password and ledger unencrypted
    across your network. The AI connector warns once in its log when it talks
    to another machine over plain http:// (owner decision).
  • The encrypted backup's password is typed in a hidden field, twice: it
    was a plain pop-up that showed it and asked once, so a typo made a backup
    no one could open (owner decision).
  • Deleted transactions are erased from the database file (SQLite's secure
    delete), instead of staying readable in it and its copies until it was
    compacted.
  • Settings > Backup & Restore says BitcoinTX keeps a few unencrypted safety
    copies of its database in its data folder.
  • Responses no longer name the web server ("server: uvicorn"), and the
    Docker image's data folder is owner-only (it was writable by everyone).
  • The READMEs say that uvx downloads the AI connector from PyPI once,
    which sees your IP address and the version.
  • Settings (and StartOS's Price Source & Privacy action and instructions)
    name every public site BitcoinTX may contact (mempool.space and Coinbase
    were missing) and say the sites see your IP address and when BitcoinTX is
    open, never your transaction dates (owner decision).
  • Fewer requests to public price sites: the live price asks Kraken first
    and CoinGecko only if Kraken fails (CoinGecko refuses VPN and Tor users,
    so each refresh used to contact both), and the block height is kept for a
    minute like the price instead of being asked on every Dashboard visit
    (owner decision).
  • Restoring a backup in the app keeps the price settings in use, as it
    keeps your login and AI key: a backup from before a switch to Tor or Off
    brought back direct lookups of the public sites (owner decision).

Downloads

  • StartOS: btctx.s9pk. In StartOS, open Sideload and upload it; installs of earlier versions update in place.
  • macOS: BitcoinTX-macOS.dmg (or the .zip). The app is not signed by Apple: the first time, right-click (Control-click) BitcoinTX in Applications and choose Open; on macOS 15 or later, open it once, then go to System Settings > Privacy & Security and click Open Anyway.
  • Docker: ghcr.io/digimonk73/btctx-mcp:v1.2.2 (amd64 and arm64).
  • AI connector: uvx btctx-mcp==1.2.2 (PyPI); Settings → Connect an AI Assistant has it ready to paste.

v1.2.1

Choose a tag to compare

@github-actions github-actions released this 29 Sep 01:25

Fixes

  • Adding transactions before choosing a price source no longer turns
    public price sites on.
    Since 1.1.0, an install with transactions but no
    price choice yet was taken for one from before 1.1.0 (when public sites
    were on by default), so its next restart, e.g. an update, switched it to
    Public price sites and asked them for prices, although you never
    chose that. Now only an install that stored past prices before 1.1.0
    keeps public sites; any other stays unasked until you choose. If you
    added entries before answering the price question and BitcoinTX has
    restarted since, check Settings → Privacy & Network (on StartOS, the
    Price Source & Privacy action decides instead). Found testing the 1.2.0
    package on a StartOS VM.

  • The complete tax report works with price lookups off. It looked up
    the Jan 1 BTC price even when nothing was held then, and a missing price
    failed the whole report; a missing Dec 31 price valued the holdings at
    $0. Holdings with no price for that day now read "not priced", and the
    rest of the report is unchanged.

  • The complete tax report's Beginning of Year Holdings were wrong
    whenever BTC had moved or been sold in earlier years: lots were counted
    twice (in the checklist's ledger, 1.8797 BTC on Jan 1, 2024 instead of
    the 0.9898 held on Dec 31, 2023). They are now taken the same way as the
    year-end holdings, so Jan 1 always matches the previous Dec 31. Only this
    section of that report was affected: IRS forms and gains were right.

  • Export CSV now imports back to the same ledger. The export had no
    column for a BTC fee's USD value, a gift's fair market value or the
    Broker form override (all added after the export was written), so a
    re-import priced every BTC fee again at that day's price, changing gains,
    lost Broker form choices and failed outright with price lookups off. The
    export, the import and the template now share one list of columns, with
    three new optional ones at the end: fee_usd, fmv_usd and
    broker_reporting. Older CSV files import as before. A CSV import a row
    can't be saved from (e.g. a BTC fee with no price to value it) now says
    why instead of answering with a server error. The CSV import guide
    describes the new columns and no longer calls a BTC deposit's basis
    optional.

  • Deleting a transaction that later ones depend on (a buy whose BTC a later
    sell or transfer spends) is refused and changes nothing. Before, it showed
    an error but deleted the row anyway, and every later save then failed
    until the row was entered again. The message now says why: "Not deleted:
    later transactions depend on this one. …".

  • Restoring a backup made before 0.9.2 with the wrong password now always
    says "Wrong password?". About 1 time in 256 it said the file wasn't a
    BitcoinTX backup instead (the live database was never touched either way).

  • The log is readable again. Every health check (StartOS asks every 30
    seconds) logged two database lines, half of a running install's log. It
    now logs nothing.

  • Loading the dashboard asked for the live price twice (the dashboard and
    the sidebar converter at the same moment). Requests at the same moment
    now share one.

  • The dashboard's BTC Cost Basis is now labeled Avg. Cost per BTC:
    it always was the average cost of one bitcoin you hold, not your total
    cost.

  • The login page shows Create account only on a fresh install that
    still has the default login. Once the account is set up, that page
    resets it (deleting every transaction, after asking for the current
    password), which the link didn't say; Settings still has Reset
    Username & Password.

  • A report that can't be made now says why. Reports showed only "Failed
    to generate the report" and dropped the reason. They now show it, and
    when an old withdrawal's network fee (or a Spent withdrawal's proceeds)
    has no USD value and no price is available, the message names that
    transaction, e.g. "Withdrawal of 0.01 BTC on 2024-06-01: its network fee
    has no USD value (edit that transaction to enter it)".

  • Restoring a backup file in the app keeps your current login. It
    brought back the backup's username and password, so a password changed
    since stopped working, and on StartOS Show Credentials showed one that
    no longer logged in. Like the AI key, the login in use now stays; the
    ledger and settings come from the backup. StartOS's own backups were
    never affected (they restore the login and the ledger together).

  • With prices off, the dashboard's Unrealized Gains/Losses said
    "Loading..." forever; it now says "Prices off" (or "No price" when a
    lookup failed).

  • When public price sites go through a proxy that's down (e.g. Tor
    stopped), the error says so and asks whether Tor is running, instead of
    only "No public site answered".

  • Deleting a transaction asks "Are you sure?" once, not twice.

  • Export CSV has a fourth new optional column, fee_usd_typed: whether
    a BTC fee's USD value was typed (yes) or that day's price (no). A
    re-import marked every fee value as typed, so editing such a
    transaction's date later kept the old value instead of pricing it
    again. Files without the column import as before.

  • A missing file (the browser's /favicon.ico, an outdated script after an
    update) is a 404 instead of the app's page.

  • Sats Converter: a price you type in Manual mode is no longer replaced
    by the starting price arriving late (on a slow server it could land after
    you had typed yours).

Development

  • docs/AGENT-TESTS.md: the release tests an AI agent runs on a StartOS VM
    before each release (install, actions, the update from the last release,
    backups, price sources, TLS, the MCP connector, the Mac app), against a
    14-transaction ledger whose every figure is known, with its known issues.
  • Dependabot opens weekly pull requests against develop, grouped per
    directory (Python in backend/, mcp_server/ and the dev tools, npm in
    frontend/ and startos/, GitHub Actions). It leaves the StartOS SDK and its service
    packages, @playwright/test and the deferred upgrades alone
    (docs/MAINTENANCE.md, "Dependabot").
  • First updates taken: uvicorn 0.54.0; vitest 5.0.2,
    eslint-plugin-react-refresh 0.5.7, globals 17 (frontend); prettier, ncc and
    the Node types (StartOS package build); GitHub Actions on their current
    majors (Node 24).
  • The release job downloads its two artifacts by name, so a Docker build
    record can't get mixed in.
  • make preview runs the checked-out code in a browser on a throwaway
    database with offline test prices; make docker-smoke builds the Docker
    image locally and runs CI's container checks on it (docs/TESTING.md).

Downloads

  • StartOS: btctx.s9pk. In StartOS, open Sideload and upload it; installs of earlier versions update in place.
  • macOS: BitcoinTX-macOS.dmg (or the .zip). The app is not signed by Apple: the first time, right-click (Control-click) BitcoinTX in Applications and choose Open; on macOS 15 or later, open it once, then go to System Settings > Privacy & Security and click Open Anyway.
  • Docker: ghcr.io/digimonk73/btctx-mcp:v1.2.1 (amd64 and arm64).
  • AI connector: uvx btctx-mcp==1.2.1 (PyPI); Settings → Connect an AI Assistant has it ready to paste.

v1.2.0

Choose a tag to compare

@github-actions github-actions released this 28 Sep 12:19

StartOS: your own Mempool and Tor, chosen in one action

  • New action: Price Source & Privacy. Choose My Mempool on this
    server
    , Public price sites (optionally over Tor), Off, or
    Choose in BitcoinTX. A fresh install asks right after Show
    Credentials; updating installs get an optional reminder. What you choose
    there shows read-only in the app (Settings → Privacy & Network).
  • Your Mempool on the same server now just works. BitcoinTX reaches it
    inside StartOS, so there's no address to copy, no https certificate that
    fails, and no LAN address that can change. This replaces the 1.1.0 advice
    to turn on the fallback for .local/https addresses (which, with the
    fallback off, meant no prices at all). Mempool and Tor are optional
    dependencies, only while you use them.
  • Tor for public sites: with the Tor service installed, requests to
    public price sites go through it, so they never see your IP address. If
    Tor stops, those requests fail rather than go out directly.
  • Old default logins retired. An install from before generated passwords
    that still had admin/password gets a generated password at this update,
    and StartOS asks you to copy it (Show Credentials) before starting.
  • Translated: every action, task and message of the package in Spanish,
    German, Polish and French (the app itself stays English, US tax forms).
  • The package follows Start9's conventions for the community registry: its
    mirror (DigiMonk73/BTCTX-StartOS) runs Start9's standard build and release
    workflows, and changes Start9 makes to their fork come back with
    scripts/start9-pull.sh.

Price settings the server can set

  • BTCTX_PRICE_SOURCE, BTCTX_MEMPOOL_URL, BTCTX_MEMPOOL_FALLBACK and
    BTCTX_PROXY_URL (Docker too): when set, they replace Settings →
    Privacy & Network, which shows them read-only; your stored settings come
    back once they're removed. An invalid value turns lookups off. See
    docs/STARTOS_COMPATIBILITY.md.
  • The log now says where each download of past prices came from ("Price
    history from your mempool server: N days", "… from public site bitstamp"),
    so you can check no public site was asked.

Fixes

  • Recalculate Ledger (StartOS action, python -m backend.cli) can look up
    a missing day's price.
    The maintenance commands never read the price
    settings, so they behaved as if no source was chosen.

AI connector on PyPI

  • The connector is published to PyPI as
    btctx-mcp with every release, by
    trusted publishing (no token is stored anywhere). The setup prompt,
    configurations, StartOS action and docs now install it with
    uvx btctx-mcp==X.Y.Z, still pinned to your BitcoinTX version; nothing
    needs git on your computer any more. Versions before 1.2.0 stay
    installable from GitHub (uvx --from "git+…@vX.Y.Z#subdirectory=mcp_server" btctx-mcp).

Downloads

  • StartOS: btctx.s9pk. In StartOS, open Sideload and upload it; installs of earlier versions update in place.
  • macOS: BitcoinTX-macOS.dmg (or the .zip). The app is not signed by Apple: the first time, right-click (Control-click) BitcoinTX in Applications and choose Open; on macOS 15 or later, open it once, then go to System Settings > Privacy & Security and click Open Anyway.
  • Docker: ghcr.io/digimonk73/btctx-mcp:v1.2.0 (amd64 and arm64).
  • AI connector: uvx btctx-mcp==1.2.0 (PyPI); Settings → Connect an AI Assistant has it ready to paste.

v1.1.0

Choose a tag to compare

@github-actions github-actions released this 28 Sep 01:29

Privacy: you choose where prices come from, and no lookup reveals a date

  • Nothing is contacted until you choose. A fresh install asks, right
    after the first login, where Bitcoin prices come from: My mempool
    server
    , Public price sites, or Off (Settings → Privacy &
    Network). Before that the dashboard says "Prices off". Installs from
    before 1.1.0 keep what they did.
  • Your own mempool server now also gives past prices (its hourly record
    at 00:00 UTC), and it's used only: the public sites are asked when it
    can't answer only if you turn on Fall back to public price sites. A
    mempool server on your network is reached directly, not through the proxy
    (an .onion still is).
  • Past prices never reveal your dates. Before, a missing day started a
    ~1,000-day download that began exactly 500 days before it, so the site
    could work out the date, and the Coinbase backup never covered the day,
    so BitcoinTX often asked for the day by name. Now the public sites send
    the whole daily history once, in the same requests for every install, and
    after that only "the latest days". The single-day lookups (CoinGecko,
    Kraken, CoinDesk) are gone. Days before 2011-08-18 (Bitstamp's first) have
    no public price: type the value in.
  • The live price is asked at most once a minute however many tabs are open,
    and the sidebar converter doesn't ask while its tab is hidden.
  • Correction: the 1.0.3 README, StartOS docs and website said that
    download kept lookups from pointing at your dates; it didn't, as above.
  • StartOS: a mempool address starting with https (the .local ones)
    doesn't answer BitcoinTX yet (it can't check StartOS's own certificate);
    1.0.3 then quietly used the public sites. Turn on Fall back to public
    price sites
    with such an address for now; a direct connection inside
    StartOS comes next.

Security

  • PDF reports can't be made to fetch anything. Text stored in a
    transaction (for example from an imported file or an AI) could make the
    server contact any web address while drawing a report, skipping the
    proxy. Report text is now escaped and the PDF library may fetch nothing
    remote. A deposit's source must be one of the listed values. The IRS forms
    (filled by a different tool) are unchanged.
  • Docker/source first run: a setup code. Until you set your own login,
    logging in with admin/password or claiming the account needs a one-time
    code from the log (docker logs) or /data/setup-code.txt, so nobody
    else on the network can claim it first. An older install that still uses
    admin/password: the login page asks for the code; log in, then change the
    password in Settings (your transactions are untouched).
  • Login protection: repeated wrong passwords make everyone wait longer
    (1 s up to 5 min); new passwords need at least 12 characters (existing
    ones still work); changing the password needs the current one.
  • Requests from other sites are refused: a page on another site (or
    another app on the same server) can't make your browser restore a backup
    or import a file. Cross-origin requests (CORS) are off unless configured.
  • A restore refuses files over 1 GiB and unreasonable key-strength settings;
    two old example session keys from the project's history are refused; an
    empty session key file is replaced.
  • CSV exports can't start a spreadsheet formula; Docker and StartOS keep no
    access log (request paths can hold dates), and transaction dates left the
    normal log.

AI connector

  • The setup texts pin the connector to your BitcoinTX version (@vX.Y.Z)
    instead of following main: your AI app runs exactly that code and
    fetches nothing new at each start. After an update, every tool reply says
    which version to set. (PyPI will come once publishing is set up.)

Downloads

  • StartOS: btctx.s9pk. In StartOS, open Sideload and upload it; installs of earlier versions update in place.
  • macOS: BitcoinTX-macOS.dmg (or the .zip). The app is not signed by Apple: the first time, right-click (Control-click) BitcoinTX in Applications and choose Open; on macOS 15 or later, open it once, then go to System Settings > Privacy & Security and click Open Anyway.
  • Docker: ghcr.io/digimonk73/btctx-mcp:v1.1.0 (amd64 and arm64).

v1.0.3

Choose a tag to compare

@github-actions github-actions released this 27 Sep 20:58

AI keys instead of passwords

  • The AI connector no longer uses your password. On Docker and StartOS,
    Settings → Connect an AI Assistant now has the Let AI assistants use
    BitcoinTX
    switch (off by default) and Create AI key: a key shown
    once, which you paste into your AI app's settings. New key replaces
    it, Revoke deletes it. BitcoinTX stores only a hash of it. The Mac app
    keeps its automatic key file.
  • The key can do only what the AI tools need: read the ledger, add,
    change or delete single entries, recalculate, and make a backup copy. It
    can't log in, change the username or password, restore or download a
    backup, export or import files, delete everything, apply Ledger Review
    fixes, open reports or change settings: those answer 403 (an allow-list,
    so anything added later is closed to the key too).
  • New AI tool backup_ledger: a copy of the database in BitcoinTX's
    backups folder on your server before a big change (the newest 3 are
    kept, apart from the pre-upgrade copies; one a minute).
  • A restore keeps the current AI key and switch, so an old backup can't
    bring back a key you revoked.
  • The connector refuses a password. While BTCTX_PASSWORD is in its
    settings, every tool says how to switch to a key and sends nothing.
  • Breaking: the undocumented API_KEY setting (X-API-Key header) is
    gone; use an AI key.
  • The StartOS Connect an AI Assistant action no longer shows your login;
    its configuration has a YOUR_BITCOINTX_AI_KEY placeholder.

AI connector updates itself

  • The setup prompt, configs and docs install the connector from this repo's
    main branch, which now holds released code only: uvx checks it each time
    the AI app starts, so you never edit a version again. Pinning @vX.Y.Z
    still works.
  • The connector has the app's version number, and when the two differ every
    tool reply starts with a line saying so and what to do (restart the AI
    app, or update BitcoinTX).

If you use an AI assistant with BitcoinTX on Docker or StartOS: your AI
app's settings file held your BitcoinTX password in plain text. After
upgrading: (1) in BitcoinTX, Settings → Connect an AI Assistant, turn on AI
access and create an AI key; (2) in your AI app's settings, replace
BTCTX_PASSWORD (and BTCTX_USERNAME) with BTCTX_AI_KEY set to that key,
and delete the password; (3) change your BitcoinTX password (Settings →
Reset Username & Password), or on StartOS run Reset Login Credentials,
because the old one sat in that file. Mac app users: nothing to do.

Documentation

  • The MCP README no longer says a local model means "nothing leaves your
    computer": what the AI reads stays there, but BitcoinTX still looks up
    prices unless Live data is off. It also says a preview can look up prices.
  • Correction: v0.9.2 said past-day price requests "no longer name
    individual transaction dates", and the README said lookups "don't reveal
    your transaction dates". A missing day is filled by one download of about
    1,000 days, but if that download fails BitcoinTX asks CoinGecko, Kraken or
    CoinDesk for the single day, which names it. The README now says so; Live
    data off sends no request at all.
  • The StartOS listing says BitcoinTX sends your ledger nowhere (instead of
    "your ledger stays on your server", which a cloud AI would contradict), in
    all five languages. The README and StartOS docs list every outside service
    (single-day fallback and block-height sources included).
  • docs/startos-research/btctx-requirements.md (it described v0.8.0) moved to
    docs/archive/.

Development

  • Work now happens on develop; main holds released code only and moves
    by fast-forwarding to develop (CLAUDE.md, "Branches"). The pre-push
    hook refuses a push to main of anything not already on develop, and
    any delete, rewind or force-push of main; the release workflow refuses a
    release commit that isn't on main.

Downloads

  • StartOS: btctx.s9pk. In StartOS, open Sideload and upload it; installs of earlier versions update in place.
  • macOS: BitcoinTX-macOS.dmg (or the .zip). The app is not signed by Apple: the first time, right-click (Control-click) BitcoinTX in Applications and choose Open; on macOS 15 or later, open it once, then go to System Settings > Privacy & Security and click Open Anyway.
  • Docker: ghcr.io/digimonk73/btctx-mcp:v1.0.3 (amd64 and arm64).

v1.0.2-1

Choose a tag to compare

@github-actions github-actions released this 27 Sep 12:55

Package-only update; BitcoinTX itself is unchanged.

  • The StartOS store listing and release notes are also in Spanish, German,
    Polish and French. The app stays in English and produces US (IRS) tax
    forms, which the listing says.
  • The listing's website link points to the BitcoinTX site.
  • The package README names no versions (Start9's rule): old upgrade paths
    are described by what changed.

Downloads

  • StartOS: btctx.s9pk. In StartOS, open Sideload and upload it; installs of earlier versions update in place.
  • macOS: BitcoinTX-macOS.dmg (or the .zip). The app is not signed by Apple: the first time, right-click (Control-click) BitcoinTX in Applications and choose Open; on macOS 15 or later, open it once, then go to System Settings > Privacy & Security and click Open Anyway.
  • Docker: ghcr.io/digimonk73/btctx-mcp:v1.0.2 (amd64 and arm64).

v1.0.2

Choose a tag to compare

@github-actions github-actions released this 27 Sep 02:48

AI assistant privacy

  • Settings → Connect an AI Assistant now opens with a warning: the AI's
    model reads what BitcoinTX hands it (transactions, balances, gains) and
    whatever you paste, and with a cloud AI (Claude, Grok…) that goes to the
    provider. It points to local-model apps (LM Studio, Goose with Ollama).
  • The AI setup guide tells the AI to say this before it installs anything;
    the MCP README has a "Privacy: cloud or local model" section with LM Studio
    and Goose setup; the README and the StartOS instructions carry the warning.
  • Mac app: AI assistant access is now off by default, including on
    installs upgraded from 0.9.2–1.0.1 that never touched the switch. If you
    use an AI with the Mac app, turn on Settings → Connect an AI Assistant →
    Let AI assistants use BitcoinTX
    once; until then the AI gets "AI
    assistant access is turned off". A line under the switch says what it
    allows. The docs say AI entry is optional, what the switch
    does, and that Docker/StartOS have no switch (the server logs in with the
    password).
  • StartOS: the MCP API address, the Connect an AI Assistant action and the
    package description say the same, and name LM Studio. Text only; AI access
    on StartOS still works by username and password, as before.

Documentation

  • Install from the release downloads (macOS .dmg, btctx.s9pk, the
    ghcr.io/digimonk73/btctx-mcp image) instead of building; README features
    now include Ledger Review, stored price history and Privacy & Network; the
    upgrade steps use Ledger Review; price and outbound-request sources updated.
  • The AI's ledger guide: income with no price available is refused (ask the
    user), a withdrawal's BTC fee is taxable even for Gift, Donation and Lost,
    River's Received is net of its fee, and when to use review_ledger.
  • Mac app docs: the port-busy dialog replaces the old random-port fallback,
    the MCP server needs no settings, Gatekeeper steps for macOS 15.
  • Developer docs: test counts and what make check covers, make e2e, the
    weekly workflows, new modules in CLAUDE.md, missing pinned packages,
    network-fee disposals on withdrawals in the IRS docs, frozen StartOS ids.
    The finished hardening/redesign and StartOS package plans moved to
    docs/archive/; the roadmap lists only open work.

Releases

  • The release workflow now also publishes each version's btctx.s9pk as a
    release on the StartOS mirror (DigiMonk73/BTCTX-StartOS), marked Latest,
    so the mirror's releases page stays current with no work in that repo
    (scripts/mirror-startos-release.sh).
  • The mirror's only branch is now main (was master, plus four stale
    branches); the sync script and the mirror's CI follow it.

Downloads

  • StartOS: btctx.s9pk. In StartOS, open Sideload and upload it; installs of earlier versions update in place.
  • macOS: BitcoinTX-macOS.dmg (or the .zip). The app is not signed by Apple: the first time, right-click (Control-click) BitcoinTX in Applications and choose Open; on macOS 15 or later, open it once, then go to System Settings > Privacy & Security and click Open Anyway.
  • Docker: ghcr.io/digimonk73/btctx-mcp:v1.0.2 (amd64 and arm64).