- Go 67.7%
- JavaScript 21.6%
- CSS 4.4%
- HTML 3.2%
- Shell 2.3%
- Other 0.8%
|
All checks were successful
Release / Prepare Release (push) Successful in 4s
Release / Build Binaries-1 (push) Successful in 1m16s
Release / Build Binaries (push) Successful in 1m19s
Release / Create Release (push) Successful in 6s
Release / Publish Docker Image (push) Successful in 2m2s
Reviewed-on: #20 |
||
|---|---|---|
| .beads | ||
| .forgejo/workflows | ||
| cmd/hsa-history | ||
| internal | ||
| .gitignore | ||
| AGENTS.md | ||
| Dockerfile | ||
| Dockerfile.builder | ||
| go.mod | ||
| go.sum | ||
| LICENSE | ||
| main | ||
| README.md | ||
HSA Tracker
A web-based application for tracking Health Savings Account (HSA) expenses. Upload receipts, automatically extract expense details using AI, and track reimbursements—all from your phone or computer.
Features
- 📸 Upload Receipts: Upload images (JPG, PNG) or PDFs from your phone or computer
- 🤖 AI-Powered Scanning: Automatically extracts store name, date, and amount from receipts using Google Gemini or Ollama
- 💾 Local Storage: All receipts and data stored locally on your machine
- 📱 Mobile-Friendly: Web interface optimized for taking photos on your phone
- 💰 Expense Tracking: View total receipts and total value at a glance
- ✅ Reimbursement Tracking: Mark receipts as reimbursed and track reimbursement events
- 🔒 Optional Authentication: Basic auth protection for your data
Installation
Prerequisites
- Go 1.24 or later
- Google Gemini API key (for cloud-based scanning) OR Ollama installed locally (for local scanning)
Build
git clone <repository-url>
cd hsa-tracker
go build -o hsa-tracker ./cmd/hsa-tracker
Download Pre-built Binaries
Pre-built binaries are available in the Releases section for Linux and macOS (both amd64 and arm64).
macOS Gatekeeper Warning
When downloading binaries from GitHub, macOS may show a security warning because the binary is not code-signed. To run the binary:
Option 1: Right-click method (recommended)
- Right-click (or Control-click) on the
hsa-historybinary - Select "Open" from the context menu
- Click "Open" in the security dialog
- The binary will now run normally
Option 2: Remove quarantine attribute
# After extracting the tar.gz file
xattr -d com.apple.quarantine hsa-history
./hsa-history
Option 3: Allow in System Settings
- Go to System Settings → Privacy & Security
- Scroll down to find the blocked app message
- Click "Open Anyway"
Usage
Quick Start
-
Set your Gemini API key (if using Gemini):
export GEMINI_API_KEY=your-api-key-here -
Run the server:
./hsa-tracker -
Open your browser: Navigate to
http://localhost:8080
Configuration Options
All configuration can be done via command-line flags or environment variables (prefixed with HSA_TRACKER_):
Basic Options
--port(default:8080): HTTP server port--db(default:hsa-tracker.db): Path to the database file--storage(default:./receipts): Directory where receipt files are stored
Scanner Options
--scanner(default:gemini): Scanner type -geminiorollama--gemini-key: Google Gemini API key (or setGEMINI_API_KEYenv var)--gemini-model(default:gemini-2.5-pro): Gemini model to use--ollama-url(default:http://localhost:11434): Ollama API URL--ollama-model(default:llava): Ollama model name (e.g.,llava,llava-phi3,bakllava,qwen2-vl)
Security Options
--auth-user: Basic auth username (optional)--auth-pass: Basic auth password (optional)
Example: Using Gemini (Cloud)
export GEMINI_API_KEY=your-api-key-here
./hsa-tracker --port 8080 --storage ~/hsa-receipts
Example: Using Ollama (Local)
# Make sure Ollama is running with a vision model installed
# e.g., ollama pull llava
./hsa-tracker --scanner ollama --ollama-model llava --port 8080
Example: With Authentication
./hsa-tracker --auth-user myuser --auth-pass mypassword
Using the Web Interface
-
Upload Receipts:
- Click "Upload Receipts" or use the file input
- Select one or multiple receipt images/PDFs
- The app will automatically scan and extract details
- Progress is shown during bulk uploads
-
View Receipts:
- All receipts are listed on the main page, sorted by date (newest first)
- View total receipt count and total value at the top
- Click "View" to see the original receipt file
- Click "Delete" to remove a receipt (only if not reimbursed)
-
Mark as Reimbursed:
- Select one or more receipts using the checkboxes
- Click "Mark as Reimbursed" in the selection bar
- This creates a reimbursement event linking all selected receipts
-
View Reimbursements:
- Switch to the "Reimbursements" tab
- See a list of all reimbursement events
- Click on a reimbursement to see details and associated receipts
Data Storage
- Database: Receipt metadata is stored in
hsa-tracker.db(BoltDB) - Files: Original receipt files are stored in the
--storagedirectory (default:./receipts) - Both are stored locally on your machine—your data never leaves your control
Development
Running Tests
# Run all tests
go test ./...
# Run tests with coverage
go test -cover ./...
# Run tests for a specific package
go test ./internal/receipt/...
Project Structure
hsa-tracker/
├── cmd/hsa-tracker/ # Main application entry point
├── internal/
│ ├── receipt/ # Receipt domain logic (DB, storage, service, handlers)
│ └── scanning/ # LLM scanning abstraction (Gemini, Ollama)
└── go.mod # Go module dependencies
Key Technologies
- Go 1.23+: Core language
- BoltDB: Embedded key-value database
- Google Gemini API: Cloud-based LLM for receipt scanning
- Ollama: Local LLM option for receipt scanning
- Ginkgo/Gomega: BDD testing framework
- Stimulus.js: Frontend JavaScript framework
- Tailwind CSS: Styling
Adding New Features
- New LLM Provider: Implement the
scanning.Scannerinterface - New Storage Backend: Implement the
receipt.Storageinterface - New Database Backend: Implement the
receipt.DBinterface
Testing Conventions
- Use Ginkgo/Gomega for all tests
- Use
When()blocks instead ofContext() - Set up state in
BeforeEach, execute inJustBeforeEach - One logical assertion per
Itblock - Use
MatchError()for error assertions - Wrap errors with
fmt.Errorf()in production code
License
This project is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
See the LICENSE file for details.