# gogcli Agent-Friendly Shortcuts: How to Use send, ls, and search for Automation

> Streamline automation with gogcli's agent-friendly shortcuts. Use send, ls, and search for JSON-friendly Gmail and Google Drive operations without nested subcommands.

- Repository: [Peter Steinberger/gogcli](https://github.com/steipete/gogcli)
- Tags: how-to-guide
- Published: 2026-02-16

---

**Use the top-level `send`, `ls`, and `search` commands in gogcli to execute Gmail and Google Drive operations without nested subcommands, enabling streamlined automation and JSON-friendly agent integration.**

The `gogcli` tool provides **agent-friendly shortcuts** that flatten the command hierarchy for automated workflows. These shortcuts—`send`, `ls`, and `search`—map directly to `gmail send`, `drive ls`, and `drive search`, eliminating the need for verbose subcommand chains when scripting or piping output to other programs.

## How gogcli Shortcut Architecture Works

### Top-Level Command Registration

The shortcuts are implemented as top-level fields in the `CLI` struct defined in [`internal/cmd/root.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/root.go). By embedding `GmailSendCmd`, `DriveLsCmd`, and `DriveSearchCmd` directly into the root structure, Kong treats them as first-class commands:

```go
type CLI struct {
    Send     GmailSendCmd    `cmd:"" name:"send" help:"Send an email (alias for 'gmail send')"`
    Ls       DriveLsCmd      `cmd:"" name:"ls" aliases:"list" help:"List Drive files (alias for 'drive ls')"`
    Search   DriveSearchCmd  `cmd:"" name:"search" aliases:"find" help:"Search Drive files (alias for 'drive search')"`
}

```

*Source: [`internal/cmd/root.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/root.go) lines 50-60.*

### Execution Flow

When you invoke a shortcut, the `Execute` function in [`root.go`](https://github.com/steipete/gogcli/blob/main/root.go) processes argument rewriting and then builds a Kong parser for the `CLI` struct. If the parser matches `send`, `ls`, or `search`, it instantiates the corresponding command struct and calls its `Run` method directly, bypassing the nested `gmail` or `drive` subcommand groups.

## Using the send Shortcut for Gmail Automation

The `send` command provides direct access to `GmailSendCmd` without the `gmail` prefix. This is ideal for CI pipelines that need to dispatch notifications.

### Command Syntax and Parameters

The shortcut accepts all standard Gmail parameters defined in [`internal/cmd/gmail_send.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/gmail_send.go):

```go
type GmailSendCmd struct {
    To          []string `arg:"" name:"to" help:"Recipient email addresses"`
    Subject     string   `short:"s" help:"Email subject"`
    Body        string   `short:"b" help:"Email body text"`
    BodyFile    string   `help:"File containing email body"`
    Attachments []string `short:"a" help:"File attachments"`
    Track       bool     `help:"Enable open tracking"`
}

```

*Source: [`internal/cmd/gmail_send.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/gmail_send.go) lines 20-34.*

### Practical Example: Sending Emails from Scripts

To send an email with attachments from a bash script:

```bash
gog send \
    --to "team@example.com" \
    --subject "Deployment Complete" \
    --body-file /tmp/deploy.log \
    --attach release-notes.pdf

```

When running in a non-interactive environment, the CLI automatically switches to JSON output if `GOG_AUTO_JSON` is set, returning structured data including `message_id` and `thread_id` for downstream processing.

## Using the ls Shortcut for Google Drive Listings

The `ls` shortcut (aliased as `list`) executes `DriveLsCmd` to enumerate files without the `drive` prefix.

### Filtering and Pagination Options

Defined in [`internal/cmd/drive.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/drive.go), the command supports:

```go
type DriveLsCmd struct {
    Parent      string `help:"Parent folder ID to list"`
    Max         int    `short:"n" default:"30" help:"Maximum results to return"`
    Query       string `help:"Raw Drive query string"`
    SharedDrives bool `help:"Include shared drives"`
}

```

*Source: [`internal/cmd/drive.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/drive.go) lines 82-88.*

### JSON Output for Agent Consumption

To list the ten most recent PDFs in a specific folder for agent processing:

```bash
gog ls --parent 1a2B3cD4e5F6g7H8I9J0K \
       --max 10 \
       --query "mimeType = 'application/pdf' and trashed = false" \
       --json

```

The `--json` flag forces structured output even in interactive terminals, returning an array of file objects with `id`, `name`, `mimeType`, and `modifiedTime` fields.

## Using the search Shortcut for Drive Queries

The `search` shortcut (aliased as `find`) triggers `DriveSearchCmd` for full-text Drive searches.

### Raw Query Mode vs. Simplified Search

The implementation in [`internal/cmd/drive.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/drive.go) supports two modes:

```go
type DriveSearchCmd struct {
    Query     string `arg:"" help:"Search query string"`
    Max       int    `short:"n" default:"10" help:"Maximum results"`
    RawQuery  bool   `help:"Pass query directly to Drive API without escaping"`
}

```

*Source: [`internal/cmd/drive.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/drive.go) lines 54-60.*

For simple keyword searches, the CLI escapes and formats the query automatically. For complex Drive query language (e.g., `name contains 'budget' and modifiedTime > '2024-01-01'`), use `--raw-query` to pass the string directly to the API.

Example of a raw query search:

```bash
gog search "name contains 'Q4' and mimeType = 'application/vnd.google-apps.spreadsheet'" \
    --raw-query \
    --max 5

```

## Agent Mode and Automatic JSON Detection

### Automatic JSON Output for Pipelines

The `Execute` function in [`internal/cmd/root.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/root.go) detects non-interactive environments and automatically enables JSON output when the `GOG_AUTO_JSON` environment variable is set:

```go
if envBool("GOG_AUTO_JSON") && !cli.JSON && !cli.Plain && !term.IsTerminal(int(os.Stdout.Fd())) {
    cli.JSON = true
}

```

*Source: [`internal/cmd/root.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/root.go) lines 33-37.*

This behavior ensures that agents and CI systems receive structured data without requiring explicit `--json` flags in every command.

### Desire-Path Rewriting for AI Prompts

To accommodate common AI prompt patterns, `gogcli` includes argument rewriting that maps `--fields` to the global `--select` flag. The `rewriteDesirePathArgs` function in [`root.go`](https://github.com/steipete/gogcli/blob/main/root.go) handles this translation:

```go
func rewriteDesirePathArgs(args []string) []string {
    // Maps --fields to --select for backward compatibility with Calendar API
    // while maintaining agent-friendly syntax
}

```

*Source: [`internal/cmd/root.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/root.go) starting at line 94.*

This allows agents to use intuitive `--fields` syntax while the CLI internally routes it to the correct selection mechanism.

## Summary

- **Top-level shortcuts** (`send`, `ls`, `search`) in `gogcli` bypass nested subcommand structures, providing direct access to Gmail and Drive functionality.
- **Implementation** relies on Kong struct tags in [`internal/cmd/root.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/root.go), where `GmailSendCmd`, `DriveLsCmd`, and `DriveSearchCmd` are embedded as root-level fields.
- **Agent optimization** includes automatic JSON detection via `GOG_AUTO_JSON` and desire-path rewriting that translates `--fields` to `--select`.
- **Practical usage** covers email dispatch from CI pipelines, Drive file enumeration with query filters, and full-text search with raw Drive query language support.

## Frequently Asked Questions

### How do gogcli shortcuts differ from standard subcommands?

Standard subcommands require nested invocation like `gogcli gmail send` or `gogcli drive ls`. The **shortcuts** (`send`, `ls`, `search`) are registered as top-level commands in the `CLI` struct within [`internal/cmd/root.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/root.go), allowing direct invocation as `gogcli send` or `gogcli ls`. This flat hierarchy reduces token count for AI agents and simplifies shell scripting.

### Can I use the send shortcut without interactive authentication?

Yes. The `send` shortcut uses the same OAuth token management as the standard `gmail send` command, defined in `internal/googleauth/`. Once you have authenticated interactively once and stored the token, subsequent `gogcli send` invocations from scripts or CI pipelines will reuse the cached credentials. For headless environments, ensure the token file path is accessible via the `GOG_CONFIG` environment variable.

### Why does gogcli automatically output JSON in some environments?

The `Execute` function in [`internal/cmd/root.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/root.go) (lines 33-37) detects non-TTY environments by checking `term.IsTerminal(int(os.Stdout.Fd()))`. When `GOG_AUTO_JSON` is set and stdout is not a terminal, the CLI automatically sets `cli.JSON = true`. This ensures that agents and pipeline tools receive structured data without requiring explicit `--json` flags, preventing parsing errors in automated workflows.

### How do I perform complex Drive searches with the search shortcut?

The `search` shortcut accepts a `--raw-query` flag that bypasses automatic query escaping and passes your string directly to the Google Drive API. According to the `DriveSearchCmd` struct in [`internal/cmd/drive.go`](https://github.com/steipete/gogcli/blob/main/internal/cmd/drive.go) (lines 54-60), you can use Drive query language syntax such as `name contains 'budget' and modifiedTime > '2024-01-01'`. Without `--raw-query`, the CLI treats the argument as a simple full-text search term and handles the API query construction internally.