Skip to content

Commit 1d6ba2f

Browse files
wesmclaude
andauthored
Show helpful OAuth setup instructions when client_secrets is missing (#5)
## Summary - Replace the cryptic `oauth.client_secrets not configured in config.toml` error with step-by-step setup instructions and a link to the OAuth guide - Extract a shared `errOAuthNotConfigured()` helper in `root.go` used by all 5 commands that check for client secrets - Make the OAuth prerequisite more prominent in the README Quick Start section Fixes #1 ## Test plan - [x] Run `msgvault add-account foo@bar.com` without configuring OAuth → verify helpful multi-line error with setup link - [x] `make build` succeeds - [x] README Quick Start reads clearly with the prerequisite callout 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 048f163 commit 1d6ba2f

File tree

7 files changed

+37
-13
lines changed

7 files changed

+37
-13
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,16 @@ make install
4646

4747
## Quick Start
4848

49+
> **Prerequisites:** You need a Google Cloud OAuth credential before adding an account.
50+
> Follow the **[OAuth Setup Guide](https://msgvault.io/guides/oauth-setup/)** to create one (~5 minutes).
51+
4952
```bash
5053
msgvault init-db
5154
msgvault add-account you@gmail.com # opens browser for OAuth
5255
msgvault sync-full you@gmail.com --limit 100
5356
msgvault tui
5457
```
5558

56-
OAuth requires a Google Cloud project with the Gmail API enabled.
57-
See the **[Setup Guide](https://msgvault.io/guides/oauth-setup/)** for step-by-step instructions.
58-
5959
## Commands
6060

6161
| Command | Description |

cmd/msgvault/cmd/addaccount.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Example:
2929

3030
// Validate config
3131
if cfg.OAuth.ClientSecrets == "" {
32-
return fmt.Errorf("oauth.client_secrets not configured in config.toml")
32+
return errOAuthNotConfigured()
3333
}
3434

3535
// Initialize database (in case it's new)
@@ -47,7 +47,7 @@ Example:
4747
// Create OAuth manager
4848
oauthMgr, err := oauth.NewManager(cfg.OAuth.ClientSecrets, cfg.TokensDir(), logger)
4949
if err != nil {
50-
return fmt.Errorf("create oauth manager: %w", err)
50+
return wrapOAuthError(fmt.Errorf("create oauth manager: %w", err))
5151
}
5252

5353
// Check if already authorized

cmd/msgvault/cmd/deletions.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ Examples:
212212

213213
// Validate config
214214
if cfg.OAuth.ClientSecrets == "" {
215-
return fmt.Errorf("oauth.client_secrets not configured in config.toml")
215+
return errOAuthNotConfigured()
216216
}
217217

218218
// Collect unique accounts from manifests
@@ -280,7 +280,7 @@ Examples:
280280
// Create OAuth manager with appropriate scopes
281281
oauthMgr, err := oauth.NewManagerWithScopes(cfg.OAuth.ClientSecrets, cfg.TokensDir(), logger, scopes)
282282
if err != nil {
283-
return fmt.Errorf("create oauth manager: %w", err)
283+
return wrapOAuthError(fmt.Errorf("create oauth manager: %w", err))
284284
}
285285

286286
tokenSource, err := oauthMgr.TokenSource(ctx, account)

cmd/msgvault/cmd/root.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package cmd
22

33
import (
4+
"errors"
45
"fmt"
56
"log/slog"
67
"os"
@@ -54,6 +55,29 @@ func Execute() error {
5455
return rootCmd.Execute()
5556
}
5657

58+
// oauthSetupHint is the common help text for OAuth configuration issues.
59+
const oauthSetupHint = `
60+
To use msgvault, you need a Google Cloud OAuth credential:
61+
1. Follow the setup guide: https://msgvault.io/guides/oauth-setup/
62+
2. Download the client_secret.json file
63+
3. Add to your config.toml:
64+
[oauth]
65+
client_secrets = "/path/to/client_secret.json"`
66+
67+
// errOAuthNotConfigured returns a helpful error when OAuth client secrets are missing.
68+
func errOAuthNotConfigured() error {
69+
return fmt.Errorf("OAuth client secrets not configured." + oauthSetupHint)
70+
}
71+
72+
// wrapOAuthError wraps an oauth/client-secrets error with setup instructions
73+
// if the root cause is a missing or unreadable secrets file.
74+
func wrapOAuthError(err error) error {
75+
if errors.Is(err, os.ErrNotExist) {
76+
return fmt.Errorf("OAuth client secrets file not found." + oauthSetupHint)
77+
}
78+
return err
79+
}
80+
5781
func init() {
5882
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default: ~/.msgvault/config.toml)")
5983
rootCmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output")

cmd/msgvault/cmd/sync.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ Examples:
3535

3636
// Validate config
3737
if cfg.OAuth.ClientSecrets == "" {
38-
return fmt.Errorf("oauth.client_secrets not configured in config.toml")
38+
return errOAuthNotConfigured()
3939
}
4040

4141
// Open database
@@ -65,7 +65,7 @@ Examples:
6565
// Create OAuth manager and get token source
6666
oauthMgr, err := oauth.NewManager(cfg.OAuth.ClientSecrets, cfg.TokensDir(), logger)
6767
if err != nil {
68-
return fmt.Errorf("create oauth manager: %w", err)
68+
return wrapOAuthError(fmt.Errorf("create oauth manager: %w", err))
6969
}
7070

7171
// Set up context with cancellation

cmd/msgvault/cmd/syncfull.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ Examples:
4646

4747
// Validate config
4848
if cfg.OAuth.ClientSecrets == "" {
49-
return fmt.Errorf("oauth.client_secrets not configured in config.toml")
49+
return errOAuthNotConfigured()
5050
}
5151

5252
// Open database
@@ -64,7 +64,7 @@ Examples:
6464
// Create OAuth manager and get token source
6565
oauthMgr, err := oauth.NewManager(cfg.OAuth.ClientSecrets, cfg.TokensDir(), logger)
6666
if err != nil {
67-
return fmt.Errorf("create oauth manager: %w", err)
67+
return wrapOAuthError(fmt.Errorf("create oauth manager: %w", err))
6868
}
6969

7070
// Set up context with cancellation

cmd/msgvault/cmd/verify.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ Examples:
3737

3838
// Validate config
3939
if cfg.OAuth.ClientSecrets == "" {
40-
return fmt.Errorf("oauth.client_secrets not configured in config.toml")
40+
return errOAuthNotConfigured()
4141
}
4242

4343
// Open database
@@ -51,7 +51,7 @@ Examples:
5151
// Create OAuth manager and get token source
5252
oauthMgr, err := oauth.NewManager(cfg.OAuth.ClientSecrets, cfg.TokensDir(), logger)
5353
if err != nil {
54-
return fmt.Errorf("create oauth manager: %w", err)
54+
return wrapOAuthError(fmt.Errorf("create oauth manager: %w", err))
5555
}
5656

5757
// Set up context with cancellation

0 commit comments

Comments
 (0)