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

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)
}