This file provides guidance for AI agents working with the gro codebase.
gro is a non-destructive command-line interface for Google services written in Go. It uses OAuth2 for authentication and supports read-only access plus non-destructive organizational operations (labeling, archiving, starring, marking read/unread). No send, delete, or destructive operations are possible.
Binary name: gro
Module: github.com/open-cli-collective/google-readonly
- Gmail: Search, read, thread viewing, labels, attachments, archive, star, mark read/unread, label, categorize, draft (compose-only, never sent — supports reply-to-thread)
- Google Calendar: List calendars, view events, today/week shortcuts
- Google Contacts: List contacts, search, view details, list groups
- Google Drive: List files, search, get details, download, tree view, shared drives
make build # Build binary
make test # Run tests with race detection
make test-cover # Tests with HTML coverage report
make lint # Run golangci-lint
make fmt # Format code
make check # CI gate: tidy, lint, test, build
make install # Install to /usr/local/bin| Document | Contents |
|---|---|
docs/architecture.md |
Dependency graph, package responsibilities, file naming conventions |
docs/golden-principles.md |
Mechanical rules enforced by structural tests |
docs/adding-a-domain.md |
Step-by-step checklist for adding a new Google API |
- Non-destructive by design: Only allowlisted scopes in
auth.AllScopes. No destructive API methods (send, delete, trash). Non-destructive modify operations (label, archive, star) are permitted. - Interface-at-consumer: Each
internal/cmd/{domain}/output.godefines its client interface. - ClientFactory DI: Swappable factory for test mock injection.
- --json on all leaf commands: Every leaf subcommand supports
--json/-j. - Structural enforcement:
internal/architecture/architecture_test.goenforces all patterns at CI time.
See docs/golden-principles.md for the full set of enforced rules.
- Gmail browser parity: Mail features must integrate with how people expect Gmail to behave in the browser.
grois one client among many on a shared mailbox — drafts, quoting, threading, and labels should look and behave like native Gmail when later opened or sent from the web UI. Emit the conventions/markers Gmail's own client recognizes (e.g. wrap reply quotes ingmail_quotemarkup so Gmail collapses them behind its…toggle;Re:subject handling; RFC threading headers) rather than reimplementing client-side rendering. Prefer Gmail-native parity over technically-valid-but-foreign output.
Run tests: make test
Coverage: make test-cover && open coverage.html
Tests use internal/testutil/ for assertions (testutil.Equal, testutil.NoError, etc.) and fixtures (testutil.SampleMessage(), testutil.SampleEvent(), etc.). See docs/golden-principles.md for mock and test helper patterns.
Credentials: ~/.config/google-readonly/credentials.json (from Google Cloud Console)
Tokens stored securely per platform:
- macOS: System Keychain (via
securityCLI) - Linux: libsecret (via
secret-tool) if available, otherwise config file - Fallback:
~/.config/google-readonly/token.jsonwith 0600 permissions
Follow Go conventions: lowercase, no trailing punctuation, use %w for wrapping.
Use conventional commits: type(scope): description
| Prefix | Purpose | Triggers Release? |
|---|---|---|
feat: |
New features | Yes |
fix: |
Bug fixes | Yes |
docs: |
Documentation only | No |
test: |
Adding/updating tests | No |
refactor: |
Code changes (no bug fix or feature) | No |
chore: |
Maintenance tasks | No |
ci: |
CI/CD changes | No |
github.com/spf13/cobra- CLI frameworkgolang.org/x/oauth2- OAuth2 clientgoogle.golang.org/api/*- Google API clients (Gmail, Calendar, People, Drive)
"Unable to read credentials file": Run gro init and follow the OAuth setup wizard.
"Token has been expired or revoked": Run gro config clear && gro init.