A CLI tool to calculate UK Capital Gains Tax for share disposals using HMRC Same Day, Bed & Breakfast, and Section 104 matching rules.
The main idea is a small, line-based DSL that describes your transactions (buys, sells, dividends, splits) in a consistent format. You can write it by hand, or convert broker exports into this intermediate format and then generate CGT reports from it. Everything runs locally; your data is not uploaded anywhere.
Warning
I am not an accountant or tax lawyer, and I do not provide consultations. Use this tool at your own risk.
Important
This is a 0.x project. The CLI, DSL, and outputs may change even though the calculations are carefully tested.
brew tap velikodniy/tap
brew install cgt-tool
cgt-tool --versionDownload the latest release for your platform from GitHub Releases.
chmod +x cgt-tool-*
./cgt-tool-linux-x86_64 --helpRequires Rust 1.85+ (2024 edition):
cargo install --path crates/cgt-cliConvert broker data (optional):
cgt-tool convert schwab transactions.json --output transactions.cgtOr write a small .cgt file:
2024-04-01 BUY AAPL 100 @ 150.00 USD FEES 5.00 USD
2024-06-20 SELL AAPL 50 @ 180.00 USD
Generate a report:
cgt-tool report transactions.cgtSample output:
Tax year Gain Proceeds Allowance Taxable
2024/2025 £1,200 £7,200 £3,000 £0
SELL 50 AAPL on 20/06/2024 - GAIN £1,200
Section 104: 50 shares @ £120.00
Proceeds: £7,200 | Cost: £6,000 | Gain: £1,200
Output formats: plain text (default), PDF (--format pdf), JSON (--format json).
You can pass multiple .cgt files if your broker limits export ranges (e.g., Schwab exports max 4 years):
cgt-tool report part1.cgt part2.cgt --format pdf --output report.pdf- Your transactions: broker exports (preferred) or a hand-written
.cgtfile - Full history for each holding (you need the buys before the sells; partial exports can produce incorrect gains)
- Fees/commissions where applicable (they affect the gain)
- For foreign assets: currency codes (otherwise values are treated as GBP)
report: calculate gains/losses and produce plain text, PDF, or JSONconvert: convert supported broker exports into the.cgtDSLparse: parse/normalize.cgtand print JSON (debugging and scripting)mcp: run an MCP server so AI apps can call the calculator
Run cgt-tool --help or cgt-tool <subcommand> --help for all options.
One transaction per line. Keywords are uppercase, placeholders are <angle brackets>, optional parts are [square brackets].
# Comment
2025-04-01 BUY AAPL 100 @ 150.00 FEES 5.00
2025-05-01 SELL AAPL 50 @ 160.00 FEES 5.00
Input format details
BUY/SELL: <date> BUY|SELL <ticker> <quantity> @ <price> [<currency>] [FEES <amount> [<currency>]]
DIVIDEND: <date> DIVIDEND <ticker> TOTAL <value> [<currency>] [TAX <amount> [<currency>]]
ACCUMULATION: <date> ACCUMULATION <ticker> <quantity> TOTAL <value> [<currency>] [TAX <amount> [<currency>]]
CAPRETURN: <date> CAPRETURN <ticker> <quantity> TOTAL <value> [<currency>] [FEES <amount> [<currency>]]
SPLIT: <date> SPLIT|UNSPLIT <ticker> RATIO <ratio>
- GBP is the default currency. Add ISO 4217 codes after amounts to use foreign currencies.
- The tool uses HMRC monthly average exchange rates for UK tax calculations.
- Bundled FX rates are updated regularly in releases to track the latest HMRC data.
FX rates source: UK Trade Tariff Exchange Rates
Use a custom folder with newer or missing rates:
cgt-tool report transactions.cgt --year 2024 --fx-folder ./my-ratesDownload rates:
./scripts/download-fx-rates.sh
./scripts/download-fx-rates.sh ./my-ratesTransactions export (JSON):
- Accounts -> Transaction History
- Pick -> Brokerage Accounts in the main drop-down
- Click the download icon (top right) -> choose JSON
Awards export (for RSUs / FMV):
- Follow the steps above, but in the main drop-down choose -> Equity Awards Center
Convert to .cgt:
cgt-tool convert schwab transactions.json --output transactions.cgtSchwab limits downloads to 4 years. If you need 5+ years, export multiple chunks, convert each, and report them together. The chunks must not overlap (otherwise you will duplicate transactions).
cgt-tool convert schwab schwab_2019_2022.json --output schwab_2019_2022.cgt
cgt-tool convert schwab schwab_2023_2026.json --output schwab_2023_2026.cgt
cgt-tool report schwab_2019_2022.cgt schwab_2023_2026.cgtSupported transaction types:
- Buy/Sell transactions
- RSU vesting (Stock Plan Activity) with
--awardsFair Market Value data - Dividends (Cash Dividend, Qualified Dividend, Short/Long Term Cap Gain)
- Dividend tax withholding (NRA Tax Adj, NRA Withholding)
- Date formats:
MM/DD/YYYYandas of MM/DD/YYYY
Unsupported/skipped:
- Wire transfers (Wire Sent/Received)
- Interest payments (Credit Interest)
- Stock splits (requires manual ratio entry)
- Other non-CGT-relevant transactions
Conversion examples:
# Basic conversion (transactions only)
cgt-tool convert schwab transactions.json
# With RSU vesting data (requires equity awards file)
cgt-tool convert schwab transactions.json --awards awards.json
# Save to file instead of stdout
cgt-tool convert schwab transactions.json --output output.cgt- If numbers look wrong, check currency: amounts without a currency code are treated as GBP.
- UK tax years run 6 April to 5 April; use
--yearif you want to focus on a specific year. - If you are missing buys (only have recent exports), your gains may be wrong because the matching rules require earlier acquisitions.
Embedded defaults for CGT exemption amounts live in crates/cgt-core/data/config.toml.
Override locations: ./config.toml or ~/.config/cgt-tool/config.toml.
parse reads .cgt and prints normalized JSON. It is useful for sanity-checking your input and piping into tools like jq.
cgt-tool parse transactions.cgt | jqFor browser or Node.js usage (experimental). Download the .tgz from GitHub Releases and install:
npm install cgt-tool-wasm-<version>.tgzSee crates/cgt-wasm/README.md and web/ for full docs and the demo.
MCP (Model Context Protocol) is an open standard for connecting AI apps to external tools.
Start the server:
cgt-tool mcpTo connect it to clients like Claude Desktop, you typically add a small JSON config that points to the cgt-tool binary and passes mcp as an argument. See MCP’s client docs for step-by-step setup:
- What is MCP
- Connecting local servers (includes Claude Desktop setup)
For detailed CGT matching rules, see docs/tax-rules.md.
Tests and ideas reused from cgtcalc made this project possible.