Skip to content
Merged
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
62 changes: 62 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ After creating the OAuth credentials in step 2 (or 3), run:
gro init

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

File-level note: README.md

The two prior review threads about missing gro profiles docs are resolved in this diff: --profile is now listed under gro init flags, and gro profiles list/gro profiles use are documented in both the Configuration Commands quick reference and the Command Reference. One gap remains: the top-level Features section (unchanged by this diff) still doesn't mention the profiles UX, even though the PR's stated purpose is discoverability of profile/token state. Consider adding a short Features bullet (e.g. alongside 'Secure storage') pointing at gro profiles list --check.

Reply inline to this comment.

```

Before touching anything, init names the profile (and account) it is about to
(re)authenticate. To add ANOTHER Google account later without overwriting the
first one, authenticate it as a new named profile:

```bash
gro init --profile work
```

The wizard will:

1. **Ingest credentials.json.** Pick one of three options when prompted:
Expand Down Expand Up @@ -255,6 +263,16 @@ gro me --id
gro me --extended


# List credential profiles (accounts) and their token state
gro profiles list
gro profiles list --check # live-verify each token

# Switch the active profile
gro profiles use work

# Add another account as a new named profile
gro init --profile work

# Check configuration status
gro config show

Expand All @@ -277,6 +295,11 @@ gro -v <command>
All Gmail commands are under `gro mail`:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

File-level note: README.md

The PR's stated purpose is to expose gro profiles list [--check] [--json] and gro profiles use <profile>, and root.go confirms profilescmd.NewCommand() is now registered as a top-level command — but README.md never mentions gro profiles anywhere (not in Features, not in the Configuration Commands quick-reference block ending here, not in the Command Reference section). A user hitting the exact invalid_grant scenario this PR was built to fix has no documented way to discover gro profiles list/gro profiles use. Add a gro profiles list / gro profiles use entry to the Configuration Commands block and a matching ### gro profiles list / ### gro profiles use section under Command Reference, describing the active-profile marker, --check token-health output, and --json.

Reply inline to this comment.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

File-level note: README.md

The PR dossier states gro init --profile <name> adds a new account without touching the active profile's token, but the gro init Command Reference flags list (lines 512-516) only documents --auth-code-stdin, --credentials-file, --no-browser, and --no-verify--profile is missing. Add a --profile string row here (and a short usage example under the '4. Run the wizard' setup walkthrough) so users know how to add an additional account instead of overwriting the active one.

Reply inline to this comment.


```bash
# List recent inbox messages
gro mail list
gro mail list --max 25
gro mail list --ids # Output IDs only (for piping)

# Search messages
gro mail search "is:unread"
gro mail search "from:someone@example.com" --max 20
Expand Down Expand Up @@ -509,6 +532,7 @@ Flags:
--credentials-file string Path to a downloaded OAuth client JSON (bypasses the wizard)
--no-browser Don't try to open the consent URL in a browser
--no-verify Skip connectivity verification after setup
--profile string Authenticate a NEW named profile (stored as google-readonly/<name>) without touching the active profile
```

### gro me
Expand All @@ -523,6 +547,32 @@ Flags:
--extended Add granted scopes, token expiry, and storage backend
```

### gro profiles list

List every credential profile stored in the OS keyring: the account email each
holds (as last verified), whether a token is present, and which profile is
active (marked `*`, with where the selection came from).

```
Usage: gro profiles list [flags]

Flags:
-j, --json Emit JSON
--check Live-verify each profile's token against the API
(ok / expired or revoked / error, one API call per profile)
```

### gro profiles use

Switch the active profile (writes `credential_ref` in `config.yml`). Accepts a
bare profile name or a full `google-readonly/<profile>` ref. Never touches
stored tokens; switching to a profile with no token warns and points at
`gro init`.

```
Usage: gro profiles use <profile>
```

### gro config show

Display current configuration status including credentials and token.
Expand All @@ -549,6 +599,18 @@ removed without removing anything.
Usage: gro config clear [--all] [--dry-run]
```

### gro mail list

List the most recent inbox messages (equivalent to `gro mail search "in:inbox"`).

```
Usage: gro mail list [flags]

Flags:
-m, --max int Maximum number of results (default 10)
--ids Output only message IDs (one per line, for piping)
```

### gro mail search

Search for Gmail messages using Gmail's search syntax.
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ go 1.26.4
require (
github.com/charmbracelet/lipgloss v1.1.0
github.com/muesli/termenv v0.16.0
github.com/open-cli-collective/cli-common v0.4.1
github.com/open-cli-collective/cli-common v0.5.0
github.com/spf13/cobra v1.10.2
golang.org/x/oauth2 v0.36.0
google.golang.org/api v0.289.0
Expand Down Expand Up @@ -66,7 +66,7 @@ require (
github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect
github.com/muesli/cancelreader v0.2.2 // indirect
github.com/noamcohen97/touchid-go v0.3.0 // indirect
github.com/open-cli-collective/google-cli-common v0.2.0
github.com/open-cli-collective/google-cli-common v0.3.0
github.com/opentracing/opentracing-go v1.2.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,10 @@ github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/noamcohen97/touchid-go v0.3.0 h1:fcXxVCizysD7KHRR6hrURt3nyNIs5JBGSbOIidD/3wo=
github.com/noamcohen97/touchid-go v0.3.0/go.mod h1:X9MRNIBGEmPqwpDm1G3fQOAQX7fwBlhzUbnkDTxuta0=
github.com/open-cli-collective/cli-common v0.4.1 h1:6oNaUVmMtXWi4pJn1X+W6KZVDP/WAJwbyZUyxYpGdbQ=
github.com/open-cli-collective/cli-common v0.4.1/go.mod h1:3AzjCT0V8xgslHlGi1+rUkcV+Vf5wONGwISQkufLZLQ=
github.com/open-cli-collective/google-cli-common v0.2.0 h1:yJ9x1gijQ0rgPTvhuCg74a19XhSteiGWkCcqhcVknLc=
github.com/open-cli-collective/google-cli-common v0.2.0/go.mod h1:EgRDUOb7s6cRa8PncoUrablPL3OcEDjTU8TByE7tsqs=
github.com/open-cli-collective/cli-common v0.5.0 h1:HA+ctKhVMugvVPf3zoke3ewhQvs6ur4H4Z7q7RJewyU=
github.com/open-cli-collective/cli-common v0.5.0/go.mod h1:3AzjCT0V8xgslHlGi1+rUkcV+Vf5wONGwISQkufLZLQ=
github.com/open-cli-collective/google-cli-common v0.3.0 h1:iIxFT8NJXKIfF53Lk940pRofwFfXQg11z10GLOEyXZs=
github.com/open-cli-collective/google-cli-common v0.3.0/go.mod h1:lPrPo5pD9s0eyU8YtTXjsXE8DszelDqGKh35SPUW1Nc=
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
Expand Down
2 changes: 2 additions & 0 deletions internal/cmd/root/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
config "github.com/open-cli-collective/google-cli-common/configcmd"
"github.com/open-cli-collective/google-cli-common/initcmd"
mail "github.com/open-cli-collective/google-cli-common/mailcmd"
"github.com/open-cli-collective/google-cli-common/profilescmd"
"github.com/open-cli-collective/google-cli-common/refreshcmd"
"github.com/open-cli-collective/google-cli-common/rootutil"
"github.com/open-cli-collective/google-cli-common/setcred"
Expand Down Expand Up @@ -86,6 +87,7 @@ func init() {
// Register commands
rootCmd.AddCommand(initcmd.NewCommand())
rootCmd.AddCommand(config.NewCommand())
rootCmd.AddCommand(profilescmd.NewCommand())
rootCmd.AddCommand(setcred.NewCmd())
rootCmd.AddCommand(me.NewCommand())
rootCmd.AddCommand(mail.NewCommand())
Expand Down
1 change: 1 addition & 0 deletions internal/cmd/root/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func TestRootCommand(t *testing.T) {
}
testutil.SliceContains(t, names, "init")
testutil.SliceContains(t, names, "config")
testutil.SliceContains(t, names, "profiles")
testutil.SliceContains(t, names, "mail")
testutil.SliceContains(t, names, "calendar")
testutil.SliceContains(t, names, "contacts")
Expand Down
Loading