AI / Vibecoding and Taxes
For 2025 I’m trying something new: Itemizing and claiming sales taxes paid on my federal tax return. With the help of a couple of browser extensions I was able to pull raw data from Costco, Walmart and amazon.
The problem? Costco and Walmart data exports don’t make it easy to get a tally of sales taxes paid. That’s where a little vibe coding comes into the picture.
References
- Amazon “Request my data” Portal [amazon.com]
- Tip To Download Amazon Order/Return Information, Chat History, etc. [reddit.com/r/amazonprime]
- Walmart Invoice Exporter [chromewebstore.google.com]
- Costco Receipts Downloader [chromewebstore.google.com]
- Kagi Assistant [blog.kagi.com]
Overview
For various reasons, my 2025 taxes are pretty complicated and I’m looking to minimize my tax burden as much as any mere mortal without tax shelters can accomplish. As part of this I kept track of my receipts through the year and made a note to pull online sales data from the ‘big players’ that I use often. Amazon makes it “easy” to pull your purchase and return history (as long as you are ok waiting between 1 day and 1 month for the data export), Walmart and Costco make it a giant pain
Exporting Purchase Data
For amazon, follow the guide here: Tip To Download Amazon Order/Return Information, Chat History, etc. which takes you through the following steps:
- Login to the data portal
- Request your order history
- Wait
- Download order history
- Extract your purchases for your tax year
Walmart.com orders are more complicated, and require the use of the Walmart Invoice Exporter chrome plugin. I wish it had a Firefox equivalent as I don’t daily drive a chromium based browser. To get this to work:
- Install the plugin
- Visit the walmart.com orders page
- Set your orders preferences to what you are looking for (in my case, all 2025 purchases)
- Use the plugin to download everything as individual files… the combined download doesn’t include sales tax details for reasons that I can’t fathom
- The individual file exports require some variable parsing to pull the sales tax data, see the AI Vibecoding section below
Costco.com orders are similarly complicated and require the Costco Receipts Downloader chrome extension. To get this to work:
- Install the plugin
- Visit costco.com orders page
-
Use the plugin to download the JSON from costco
- NOTE: If you try to download the ‘CSV’ it will be BROKEN and WILL NOT BE COMPLETE (at least as of January 2026)
- The JSON has everything you need, it’s just not very human readable
AI Vibecoding and Sales Tax Extraction
I don’t trust an LLM to tally up the sales tax totals from the Walmart and Costco exports. Instead, I used AI to vibecode 2 tools which can parse the exported data. For simple tasks like this, I like to use the Kagi Assistant as I pay for the high end package which includes access to pretty much every decent AI assistant under the sun. I highly recommend Kagi, they’re awesome.
Prompting the assistant, I asked (in separate sessions) for golang programs to parse the output from the Walmart and Costco data export plugins and after a couple of quick rounds of review (less than 5 minutes overall) I had a couple of quick and dirty sales tax calculator programs.
This saved me the tedium of manually creating parsing programs and while it probably only saved me about 30 minutes, those are 30 minutes where I was able to keep my head focused on the task at hand rather than implementation details.
Vibecoded AI Tools
Walmart
Parse the output of the Walmart Invoice Exporter (as of January 2026):
package main
import (
"fmt"
"log"
"os"
"path/filepath"
"strconv"
"strings"
"github.com/xuri/excelize/v2"
)
func main() {
// Directory containing XLSX files
dir := "."
if len(os.Args) > 1 {
dir = os.Args[1]
}
total, err := processTaxFiles(dir)
if err != nil {
log.Fatal(err)
}
fmt.Printf("Total Tax Amount: $%.2f\n", total)
}
func processTaxFiles(dir string) (float64, error) {
var grandTotal float64
files, err := filepath.Glob(filepath.Join(dir, "*.xlsx"))
if err != nil {
return 0, fmt.Errorf("error finding xlsx files: %w", err)
}
if len(files) == 0 {
return 0, fmt.Errorf("no xlsx files found in directory: %s", dir)
}
for _, file := range files {
total, err := processFile(file)
if err != nil {
log.Printf("Warning: error processing %s: %v", file, err)
continue
}
grandTotal += total
fmt.Printf("File: %s - Tax: $%.2f\n", filepath.Base(file), total)
}
return grandTotal, nil
}
func processFile(filename string) (float64, error) {
f, err := excelize.OpenFile(filename)
if err != nil {
return 0, err
}
defer f.Close()
var fileTotal float64
// Get all sheet names
sheets := f.GetSheetList()
for _, sheet := range sheets {
rows, err := f.GetRows(sheet)
if err != nil {
continue
}
for _, row := range rows {
if len(row) < 2 {
continue
}
// Check if column A contains "Tax"
if strings.Contains(strings.ToLower(row[0]), "tax") {
value := parseCurrency(row[1])
fileTotal += value
}
}
}
return fileTotal, nil
}
func parseCurrency(s string) float64 {
// Remove common currency symbols and formatting
s = strings.TrimSpace(s)
s = strings.ReplaceAll(s, "$", "")
s = strings.ReplaceAll(s, "€", "")
s = strings.ReplaceAll(s, "£", "")
s = strings.ReplaceAll(s, "¥", "")
s = strings.ReplaceAll(s, ",", "")
s = strings.TrimSpace(s)
value, err := strconv.ParseFloat(s, 64)
if err != nil {
return 0
}
return value
}
Costco
Parse the output of the Costco Receipts Downloader (as of January 2026):
package main
import (
"encoding/json"
"fmt"
"os"
"strconv"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: go run main.go <json_file>")
os.Exit(1)
}
data, err := os.ReadFile(os.Args[1])
if err != nil {
fmt.Printf("Error reading file: %v\n", err)
os.Exit(1)
}
var objects []map[string]interface{}
if err := json.Unmarshal(data, &objects); err != nil {
fmt.Printf("Error parsing JSON: %v\n", err)
os.Exit(1)
}
total := 0.0
count := 0
for _, obj := range objects {
// Skip FuelReceipts
if docType, exists := obj["documentType"]; exists {
if dt, ok := docType.(string); ok && dt == "FuelReceipts" {
continue
}
}
// Check if this is an online order
isOnline := false
if channel, exists := obj["channel"]; exists {
if ch, ok := channel.(string); ok && ch == "online" {
isOnline = true
}
}
if isOnline {
// For online orders, use top-level "taxes" field
if taxAmount, exists := obj["taxes"]; exists {
var val float64
switch v := taxAmount.(type) {
case float64:
val = v
case string:
if v == "" {
val = 0.0
} else {
val, err = strconv.ParseFloat(v, 64)
if err != nil {
continue
}
}
default:
continue
}
total += val
count++
}
} else {
// For in-store orders, use subTaxes.cTaxAmount
if subTaxes, exists := obj["subTaxes"]; exists {
if subTaxObj, ok := subTaxes.(map[string]interface{}); ok {
if taxAmount, exists := subTaxObj["cTaxAmount"]; exists {
var val float64
switch v := taxAmount.(type) {
case float64:
val = v
case string:
if v == "" {
val = 0.0
} else {
val, err = strconv.ParseFloat(v, 64)
if err != nil {
continue
}
}
default:
continue
}
total += val
count++
}
}
}
}
}
fmt.Printf("Total sales tax paid: $%.2f (from %d transactions)\n", total, count)
}
