Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ You'll be prompted for your Client ID and Client Secret. The CLI opens your brow

> **Note:** Splitwise ignores `redirect_uri` in OAuth requests and always uses the registered callback URL. If you hit `ERR_CONNECTION_REFUSED` after authorizing, do a manual token exchange with `curl` using the `code` from the URL.

Alternatively, you can skip the OAuth flow by setting the `SPLITWISE_API_KEY` environment variable with an API key generated from [secure.splitwise.com/apps](https://secure.splitwise.com/apps):

```bash
export SPLITWISE_API_KEY="your_api_key_here"
```

## Usage

```bash
Expand Down Expand Up @@ -82,8 +88,9 @@ This CLI ships with an [OpenClaw](https://github.com/openclaw/openclaw) / [Gemin

## Configuration

| File | Purpose |
|------|---------|
| File/Variable | Purpose |
|---------------|---------|
| `SPLITWISE_API_KEY` | Environment variable for API key (bypasses OAuth) |
| `~/.config/splitwise-cli/auth.json` | OAuth token |
| `~/.config/splitwise-cli/config.json` | User preferences |

Expand Down
2 changes: 1 addition & 1 deletion internal/api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ func (c *Client) do(req *http.Request) ([]byte, error) {
}

if resp.StatusCode == 401 {
return nil, fmt.Errorf("unauthorized — run `splitwise auth` to re-authenticate")
return nil, fmt.Errorf("unauthorized — run `splitwise auth` to re-authenticate or set SPLITWISE_API_KEY")
}
if resp.StatusCode == 403 {
return nil, fmt.Errorf("forbidden — you don't have access to this resource")
Expand Down
11 changes: 9 additions & 2 deletions internal/auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,13 @@ func Login(clientID, clientSecret string) error {

// LoadToken returns a valid token, refreshing if needed.
func LoadToken() (string, error) {
if apiKey := os.Getenv("SPLITWISE_API_KEY"); apiKey != "" {
return apiKey, nil
}

stored, err := loadAuth()
if err != nil {
return "", fmt.Errorf("not logged in — run `splitwise auth` first")
return "", fmt.Errorf("not logged in — run `splitwise auth` first or set SPLITWISE_API_KEY")
}

if stored.Token.Valid() {
Expand All @@ -128,7 +132,7 @@ func LoadToken() (string, error) {
src := cfg.TokenSource(context.Background(), stored.Token)
newToken, err := src.Token()
if err != nil {
return "", fmt.Errorf("token expired and refresh failed — run `splitwise auth` again: %w", err)
return "", fmt.Errorf("token expired and refresh failed — run `splitwise auth` again or set SPLITWISE_API_KEY: %w", err)
}

stored.Token = newToken
Expand All @@ -141,6 +145,9 @@ func LoadToken() (string, error) {

// IsLoggedIn checks if credentials exist.
func IsLoggedIn() bool {
if os.Getenv("SPLITWISE_API_KEY") != "" {
return true
}
_, err := loadAuth()
return err == nil
}
Expand Down