Add support for the following contact fields in create/update commands:
- --org: Organization/company name
- --title: Job title
- --url: URLs (can be repeated for multiple)
- --note: Note/biography
- --custom: Custom key=value fields (can be repeated)
Also updates the read mask to include these fields in list/get output.
Closes#198
Adds `gog sheets insert <id> <sheet> <rows|cols> <start>` to insert
empty rows or columns at a specific position using the Sheets API
InsertDimensionRequest via batchUpdate.
Supports --count for multiple rows/columns and --after to insert after
the specified position instead of before.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(secrets): recognize empty GOG_KEYRING_PASSWORD in non-TTY environments
Use os.LookupEnv to distinguish between "env var not set" and "env var
set to empty string". Previously fileKeyringPasswordFuncFrom checked
password != "", which caused an empty passphrase to fall through to the
TTY prompt path, failing in headless/CI environments.
Fixes#268
Co-Authored-By: Claude <noreply@anthropic.com>
* fix(secrets): respect empty GOG_KEYRING_PASSWORD (#269) (thanks @zerone0x)
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix: only patch Attendees in calendar respond to avoid reminders validation error
When responding to a calendar event, the previous code was patching the
entire event object including Reminders. This caused a Google API error
'Missing override reminder minutes' when the event had custom reminders.
The fix creates a minimal patch object containing only the Attendees
field, avoiding the reminders validation issue.
Fixes events with custom reminders failing to accept RSVP responses.
* fix(calendar): add RSVP reminders regression test (#265) (thanks @sebasrodriguez)
---------
Co-authored-by: J.A.R.V.I.S. <sebasrodriguez@users.noreply.github.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(drive,gmail): pass-through filter queries and encode non-ASCII headers
Drive search now detects raw API filter syntax (field comparisons,
contains, membership, has) and passes it through instead of wrapping
in fullText contains. Plain-text searches always append trashed=false
to prevent false positives.
Gmail MIME now RFC 2047-encodes display names with non-ASCII characters
in From/To/Cc/Bcc/Reply-To headers using net/mail.
Fixes#254, fixes#255
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix(drive,gmail): tighten trashed predicate detection
* chore(lint): silence goconst for auth services
* fix(auth): avoid goconst on services=all
---------
Co-authored-by: salmonumbrella <182032677+salmonumbrella@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
`drive delete` was calling `Files.Delete()` which permanently destroys
files. This contradicts the help text ("moves to trash") and user
expectations. The fix changes the default behavior to use
`Files.Update()` with `Trashed: true`, which moves files to trash
(recoverable for 30 days).
A new `--permanent` flag is added for users who explicitly want
irreversible deletion.
Fixes#261
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add `docs comments` subcommand for managing Google Doc comments
Add a full `gog docs comments` command tree that provides a
doc-centric interface for managing comments on Google Docs via
the Drive API v3 comments endpoint.
Subcommands:
list - List comments (filters resolved by default, --include-resolved to show all)
get - Get a single comment with full details including replies
add - Add a comment, optionally anchored to quoted text
reply - Reply to a comment
resolve - Resolve a comment (mark as done), with optional message
delete - Delete a comment
Key differences from `drive comments`:
- `list` filters resolved comments by default (--include-resolved to include)
- `list` always shows quoted text column (no separate flag needed)
- `resolve` subcommand (drive comments has no equivalent)
- Accepts Google Doc URLs in addition to bare IDs (via normalizeGoogleID)
- Doc-centric naming and help text
Follows existing patterns: uses shared helpers (collectAllPages,
tableWriter, formatDateTime, truncateString, normalizeGoogleID,
failEmptyExit, dryRunExit, confirmDestructive), same auth/token
flow, consistent output formatting.
* fix: improve docs comments list and anchoring (#263) (thanks @alextnetto)
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* feat: add `sheets notes` command to read cell notes
The existing `sheets get` uses the Values API which doesn't expose cell
notes. This adds `sheets notes <spreadsheetId> <range>` which uses the
full Spreadsheets.Get API with a narrow field mask to fetch only notes
and formatted values, keeping the response payload minimal.
Supports both text (tabwriter table) and JSON output modes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: harden sheets notes output (#208) (thanks @andybergon)
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* feat(calendar): add --send-updates flag to update and delete commands
Add --send-updates flag to CalendarUpdateCmd and CalendarDeleteCmd to
control notification behavior when modifying or canceling events with
attendees.
Without this flag, attendees are not notified of updates or cancellations,
causing:
- Stale events remaining in attendees' calendars
- Duplicate/overlapping events when updates are made
- Data synchronization issues for systems managing calendars at arm's length
Changes:
- Add SendUpdates field to CalendarUpdateCmd and CalendarDeleteCmd
- Validate SendUpdates value (all, externalOnly, none)
- Pass SendUpdates to Patch and Delete API calls
- Update truncateParentRecurrence helper to accept sendUpdates parameter
- Add tests for validation and API integration
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* test(calendar): add integration tests for --send-updates flag
Add TestCalendarSendUpdates Go integration test and shell live test
that verify attendee notifications are sent on create/update/delete.
Tests are opt-in via GOG_IT_ATTENDEE / GOG_LIVE_CALENDAR_ATTENDEE env vars.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(calendar): polish --send-updates landing
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* feat: add --quote flag to include original message in replies
Adds a --quote flag to gog gmail send that automatically quotes the original message when replying.
Changes:
- Added --quote flag to GmailSendCmd struct
- Modified fetchReplyInfo to optionally fetch message body
- Added formatQuotedMessage function for attribution and quoting
- Updated validation to require reply target when --quote is used
* feat(gmail): add --quote flag to gmail send command
Add automatic message quoting when replying to emails. The new --quote flag
includes the original message body with proper attribution line and quote
prefixes when using --reply-to-message-id or --thread-id.
Changes:
- Add Quote bool flag to GmailSendCmd struct
- Validate --quote requires reply target (--reply-to-message-id or --thread-id)
- Modify fetchReplyInfo to support fetching full message format for quoting
- Add Date and Body fields to replyInfo struct
- Add formatQuotedMessage function to format original message as quote
- Append quoted message to user's body when --quote is set
- Update test calls to replyInfoFromMessage with new includeBody parameter
- Use gmailFormatFull/gmailFormatMetadata constants instead of string literals
- Use body += for appending instead of body = body +
* feat(gmail): add HTML blockquote support for --quote feature
* fix(gmail): include user body in HTML when using --quote
* feat(gmail): preserve original HTML formatting when quoting
* fix(gmail): handle --body-file and --body-html edge cases with --quote
* fix(gmail): handle HTML-only messages when using --quote
- Quote now works when original message has only HTML content (no plain text body)
- Removed unused formatQuotedMessageHTML function
Fixes edge cases where --quote would skip messages with HTML-only bodies.
* fix(gmail): harden --quote body selection + watch includeBody format (#169) (thanks @terry-li-hm)
---------
Co-authored-by: OpenCode <opencode@local>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
* fix(auth): use non-privileged port for manual OAuth redirect
Change the manual auth flow redirect URI from http://localhost:1 to
http://127.0.0.1:9004. Port 1 is a privileged port that browsers may
block or handle differently, causing the redirect to fail. Using port
9004 (non-privileged) ensures the browser will properly attempt the
navigation and display the redirect URL in the address bar.
https://claude.ai/code/session_01Huxgf7YcpWvp6MzZGLyjcP
* fix(auth): use non-privileged port for manual OAuth redirect
Change the manual auth flow redirect URI from http://localhost:1 to
http://127.0.0.1:9004. Port 1 is a privileged port that browsers may
block or handle differently, causing the redirect to fail. Using port
9004 (non-privileged) ensures the browser will properly attempt the
navigation and display the redirect URL in the address bar.
https://claude.ai/code/session_01Huxgf7YcpWvp6MzZGLyjcP
* fix(auth): tighten manual oauth formatting
* docs(changelog): thank @spookyuser for #172
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>