Skip to content

feat: add local currency display support with auto-fetched exchange rates#1

Merged
backstabslash merged 2 commits intobackstabslash:mainfrom
GordonBeeming:gb/currencies-1
Mar 5, 2026
Merged

feat: add local currency display support with auto-fetched exchange rates#1
backstabslash merged 2 commits intobackstabslash:mainfrom
GordonBeeming:gb/currencies-1

Conversation

@GordonBeeming
Copy link
Contributor

Summary

  • Add local currency display support via ~/.goccc.json config file — set "currency": "ZAR" (or any ISO 4217 code) and costs are automatically converted
  • Exchange rates auto-fetched from open.er-api.com (free, no API key) and cached for 24 hours in the config file; falls back to cached rate when offline
  • Built-in symbol table for 20 common currencies (e.g., ZAR→R, EUR→€, GBP→£, AUD→A$)
  • CLI overrides with -currency-symbol and -currency-rate flags for one-off use (both required together)
  • Currency info line shown in terminal output (e.g., Costs in AUD (1 USD = 1.4158 AUD))
  • JSON output remains in USD for backward compatibility; adds currency metadata object when non-USD currency is active
  • Color thresholds unchanged — still evaluated against USD cost internally

Config example

{
  "currency": "AUD"
}

After first run, the file is updated with cached rate:

{
  "currency": "AUD",
  "cached_rate": 1.4158,
  "rate_updated": "2026-03-05T08:44:04Z"
}
Warp 2026-03-05 18 48 43

Copilot AI review requested due to automatic review settings March 5, 2026 08:51
@GordonBeeming
Copy link
Contributor Author

Great app @backstabslash ... a small addition that I think will be awesome ☺️

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds local-currency display support to goccc by introducing a currency config (~/.goccc.json) with auto-fetched USD exchange rates, optional CLI overrides, and optional currency metadata in JSON output (while keeping all cost calculations and JSON cost fields in USD for compatibility).

Changes:

  • Add currency config/exchange-rate fetching + caching logic and a symbol table.
  • Update terminal formatting to display converted costs when a currency is active and print an informational “Costs in …” line; add currency metadata object to JSON output.
  • Add CLI flags for one-off currency overrides and add unit tests + docs.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
main.go Adds -currency-symbol / -currency-rate flags and initializes currency handling at startup.
format.go Makes fmtCost currency-aware; adds JSON currency metadata; updates summary output to include currency info.
currency.go Implements config load/save, symbol lookup, rate fetching, and 24h caching.
currency_test.go Adds unit tests for config parsing, symbol lookup, formatting, and cached-rate behavior.
README.md Documents local currency configuration and CLI override flags.
CLAUDE.md Updates module map and feature notes to include the new currency support.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Copy link
Owner

@backstabslash backstabslash left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice feature, clean implementation! A few things to address:

1. No HTTP timeout on fetchExchangeRate (high priority)

http.Get uses the default client with no timeout — if the API is slow or unresponsive, the CLI hangs indefinitely. Use a client with a timeout:

var httpClient = &http.Client{Timeout: 5 * time.Second}

func fetchExchangeRate(currency string) (float64, error) {
	resp, err := httpClient.Get("https://open.er-api.com/v6/latest/USD")

2. initCurrency should return error, not string

Every other error path in the codebase returns error. Returning a string message is non-idiomatic Go:

func initCurrency(symbolFlag string, rateFlag float64) error {

3. CLI override sets Code to the symbol value

When using -currency-symbol "€" -currency-rate 0.92, both Code and Symbol get set to "€", which makes the info line print Costs in € (1 USD = 0.9200 €). Code is meant for ISO codes like EUR.

Either leave Code empty and skip the info line for CLI overrides, or accept a separate flag for the ISO code.

4. Config write errors silently swallowed

saveCurrencyConfig ignores the os.WriteFile error. A stderr warning would be more helpful — consistent with how fetch failures are already handled a few lines below:

if err := os.WriteFile(path, append(data, '\n'), 0644); err != nil {
	fmt.Fprintf(os.Stderr, "goccc: warning: failed to save currency config: %v\n", err)
}

@GordonBeeming
Copy link
Contributor Author

Updated, I used 2s as the timeout as it felt more reasonable to not be blocking for the tool ☺️

@backstabslash backstabslash merged commit 0eae00f into backstabslash:main Mar 5, 2026
1 check passed
@GordonBeeming GordonBeeming deleted the gb/currencies-1 branch March 5, 2026 10:52
@backstabslash
Copy link
Owner

Thanks for the contribution! Merged and released as v0.1.5 🎉

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants