How to Batch Modify Gmail Labels with gogcli: Commands and Code Examples

Use the gog gmail batch modify command with --add and --remove flags to modify labels on multiple messages via a single API call, automatically resolving label names to IDs.

The steipete/gogcli repository provides a command-line interface for managing Gmail programmatically. Batch modifying Gmail labels with gogcli allows you to efficiently add or remove labels from hundreds of messages without exhausting API quotas through individual calls.

How gogcli Implements Batch Label Modification

The batch modify functionality resides in the internal/cmd package and executes label changes through a single Gmail API request. This approach minimizes network overhead and respects Google's rate limits by bundling operations.

Parsing Arguments and CSV Labels

In internal/cmd/gmail_batch.go, the GmailBatchModifyCmd function handles argument parsing. It collects message IDs from positional arguments and processes the --add and --remove flags using the splitCSV helper defined in internal/cmd/csv.go.

This design allows you to specify multiple labels as comma-separated values:

--add=Work,Urgent --remove=Spam,Promotions

Resolving Label Names to IDs

Gmail's API requires label IDs, not display names. The fetchLabelNameToID function in internal/cmd/gmail_labels.go retrieves the complete label mapping, while resolveLabelIDs in internal/cmd/gmail_labels_utils.go converts user-supplied names to their canonical IDs, falling back to raw values if no match exists.

This resolution happens automatically, allowing you to use familiar names like "Important" while the tool handles the underlying "Label_123" identifiers.

Executing the BatchModify API Call

Once resolved, the command invokes svc.Users.Messages.BatchModify at lines 119-128 of internal/cmd/gmail_batch.go. This sends a single HTTP request to Gmail's batchModify endpoint containing all message IDs and label modifications.

The operation is atomic from the client's perspective—either all specified modifications succeed in one network round-trip, or the command reports the failure.

Dry-Run and Output Formatting

The implementation respects the global --dry-run flag via the dryRunExit helper, echoing the intended operation without modifying data. Output formatting is handled conditionally: when --json is specified, the command emits structured JSON via WriteJSON in internal/outfmt/outfmt.go; otherwise, it prints a human-friendly count of affected messages.

Practical Code Examples

Basic Batch Modification

Add the "Important" label and remove the "Newsletters" label from three specific messages:

gog gmail batch modify \
    --add=Important \
    --remove=Newsletters \
    17c2a3f4b5d6e7f8 23d5b7c9e1a2f3g4 9a8b7c6d5e4f3g2h1

The --add and --remove flags accept comma-separated lists or single values. The command resolves "Important" and "Newsletters" to their Gmail IDs before sending the batch request.

Using Label IDs Directly

When you already know the internal label IDs, specify them to skip the name lookup step:

gog gmail batch modify \
    --add=Label_123456 \
    --remove=Label_987654 \
    $(cat ids.txt)

This approach avoids the extra Labels.List API call, making it faster for bulk operations where you have cached the label mappings.

Dry-Run to Preview Operations

Verify your command before executing it:

gog --dry-run gmail batch modify \
    --add=Work,Personal \
    --remove=Spam \
    1a2b3c4d5e6f7g8h9i0j

Output when using --json:

{
  "message_ids": ["1a2b3c4d5e6f7g8h9i0j"],
  "add": ["Work","Personal"],
  "remove": ["Spam"]
}

No changes are sent to Gmail; this helps verify CSV parsing and label resolution.

Mixing Names and IDs

You can combine human-readable names with raw label IDs in the same command:

gog gmail batch modify \
    --add=Label_123456,ProjectX \
    --remove=Inbox \
    5f6e7d8c9b0a1b2c3d4e

ProjectX is resolved to its ID, while Label_123456 is used unchanged.

Key Source Files and Functions

File Role Relevant Sections
internal/cmd/gmail_batch.go Implements the batch-modify and batch-delete commands. GmailBatchModifyCmd.Run (label parsing, API call)
internal/cmd/csv.go Utility for splitting CSV strings into slices. splitCSV
internal/cmd/gmail_labels_utils.go Helper for converting human-readable label names to Gmail IDs. resolveLabelIDs
internal/cmd/gmail_labels.go Retrieves the full label map from Gmail (ID ↔︎ name). fetchLabelNameToID
internal/outfmt/outfmt.go Formats command output (JSON vs. plain text). IsJSON, WriteJSON
internal/ui/ui.go Handles UI printing and error handling. ui.FromContext calls used throughout

These files provide the end-to-end flow: CLI flag parsing → CSV splitting → label resolution → batch API request → formatted output.

Summary

  • Single API call efficiency: The gog gmail batch modify command bundles multiple label operations into one BatchModify request, conserving Gmail API quota.
  • Automatic label resolution: Human-readable names are automatically converted to Gmail label IDs via fetchLabelNameToID and resolveLabelIDs, though raw IDs are also accepted.
  • Safety features: The global --dry-run flag lets you preview changes without executing them, while --json provides machine-readable output.
  • Flexible input: Labels can be specified as comma-separated values, and message IDs can be passed as arguments or piped from files.

Frequently Asked Questions

Can I use label names instead of IDs with gogcli batch modify?

Yes, gogcli accepts human-readable label names via the --add and --remove flags. The resolveLabelIDs function in internal/cmd/gmail_labels_utils.go automatically converts these names to Gmail's internal label IDs before making the API call, falling back to the raw value if no match is found.

Does gogcli support dry-run mode for batch label operations?

Yes, the global --dry-run flag is fully supported by the batch modify command. When enabled, the dryRunExit helper in internal/cmd/gmail_batch.go prints the intended operation as JSON or plain text without actually calling the Gmail API, allowing you to verify your command before execution.

How many messages can I modify in a single batch command?

While gogcli itself does not enforce a hard limit, the underlying Gmail API typically allows batch operations on hundreds of messages per request. You should pass all target message IDs as positional arguments to the gog gmail batch modify command, and the tool will process them in a single BatchModify API call.

What happens if a label name cannot be resolved?

If a label name cannot be resolved to an existing ID, the resolveLabelIDs function falls back to using the raw value provided. This allows you to specify label IDs directly, but means typos in label names may result in API errors rather than client-side validation failures.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →