Claude
Skills
Sign in
Back

gmail-access

Included with Lifetime
$97 forever

Access Gmail via CLI with 1Password OAuth. Use when user wants to read emails, search inbox, export messages, create drafts, or.

Productivity

What this skill does


# Gmail Access

Read and search Gmail programmatically via Claude Code.

> **Self-Evolving Skill**: This skill improves through use. If instructions are wrong, parameters drifted, or a workaround was needed — fix this file immediately, don't defer. Only update for real, reproducible issues.

## MANDATORY PREFLIGHT (Execute Before Any Gmail Operation)

**CRITICAL**: You MUST complete this preflight checklist before running any Gmail commands. Do NOT skip steps.

### Step 1: Check CLI Binary Exists

```bash
ls -la "$HOME/.claude/plugins/marketplaces/cc-skills/plugins/gmail-commander/scripts/gmail-cli/gmail" 2>/dev/null || echo "BINARY_NOT_FOUND"
```

**If BINARY_NOT_FOUND**: Build it first:

```bash
cd ~/.claude/plugins/marketplaces/cc-skills/plugins/gmail-commander/scripts/gmail-cli && bun install && bun run build
```

### Step 2: Check GMAIL_OP_UUID Environment Variable

```bash
echo "GMAIL_OP_UUID: ${GMAIL_OP_UUID:-NOT_SET}"
```

**If NOT_SET**: You MUST run the Setup Flow below. Do NOT proceed to Gmail commands.

### Step 2.5: Verify Account Context (CRITICAL)

**ALWAYS verify you're accessing the correct email account for the current project.**

```bash
# Show current project context
echo "=== Gmail Account Context ==="
echo "Working directory: $(pwd)"
echo "GMAIL_OP_UUID: ${GMAIL_OP_UUID}"

# Check where GMAIL_OP_UUID is defined (mise hierarchy)
echo ""
echo "=== mise Config Source ==="
grep -l "GMAIL_OP_UUID" .mise.local.toml .mise.toml ~/.config/mise/config.toml 2>/dev/null || echo "Not found in standard locations"

# Quick connectivity test — shows the account email from a real email
echo ""
echo "=== Account Verification ==="
$GMAIL_CLI list -n 1 2>&1 | head -5
```

**STOP and confirm with user** before proceeding:

- The `list -n 1` output shows the account's inbox — verify this matches the project's intended email
- If the wrong account is shown, check which `.mise.local.toml` sets `GMAIL_OP_UUID` in the mise hierarchy
- If mismatch, inform user and do NOT proceed

**Multi-account disambiguation (when `GMAIL_OP_UUID` is NOT_SET but tokens exist).**
There is no `whoami` subcommand; map each cached token UUID to its mailbox by
probing, then pick the one that fits the project:

```bash
# Which accounts are cached, and which mailbox does each resolve to?
for f in ~/.claude/tools/gmail-tokens/*.json; do
  case "$(basename "$f")" in *.app-credentials.json|'*.json') continue ;; esac
  uuid=$(basename "$f" .json)
  who=$(GMAIL_OP_UUID="$uuid" $GMAIL_CLI list -n 1 --json 2>/dev/null \
        | jq -r '.[0].to // "(probe failed / token expired)"')
  echo "$uuid → $who"
done
```

A probe that returns `invalid_grant` means that account's refresh token is dead
(see "Diagnosing `invalid_grant`"). Pick the working UUID whose mailbox matches
the project, pin it in `.mise.local.toml`, and confirm it's gitignored. A child
project often needs a DIFFERENT account than its parent — verify, never assume
the parent's UUID.

### Step 3: Verify Token Health

```bash
# Check cached token exists and is not expired
TOKEN_FILE="$HOME/.claude/tools/gmail-tokens/${GMAIL_OP_UUID}.json"
APP_CREDS="$HOME/.claude/tools/gmail-tokens/${GMAIL_OP_UUID}.app-credentials.json"
echo "Token file: $([ -f "$TOKEN_FILE" ] && echo "EXISTS" || echo "MISSING")"
echo "App credentials: $([ -f "$APP_CREDS" ] && echo "CACHED" || echo "MISSING — will need 1Password on first run")"
```

**If token file is MISSING**: First run will open a browser for OAuth consent. This is expected.
**If app credentials are MISSING**: 1Password will be called once to cache `client_id`/`client_secret`, then never again.

---

## Setup Flow (When GMAIL_OP_UUID is NOT_SET)

Follow these steps IN ORDER. Use AskUserQuestion at decision points.

### Setup Step 1: Check 1Password CLI

```bash
command -v op && echo "OP_CLI_INSTALLED" || echo "OP_CLI_MISSING"
```

**If OP_CLI_MISSING**: Stop and inform user:

> 1Password CLI is required. Install with: `brew install 1password-cli`

### Setup Step 2: Discover Gmail OAuth Items in 1Password

```bash
# Try common vaults — "Claude Automation" for service accounts, "Employee" for interactive
for VAULT in "Claude Automation" "Employee" "Personal"; do
  ITEMS=$(op item list --vault "$VAULT" --format json 2>/dev/null | jq -r '.[] | select(.title | test("gmail|oauth|google"; "i")) | "\(.id)\t\(.title)"')
  [ -n "$ITEMS" ] && echo "=== Vault: $VAULT ===" && echo "$ITEMS"
done
```

**Parse the output** and proceed based on results:

### Setup Step 3: User Selects OAuth Credentials

**If items found**, use AskUserQuestion with discovered items:

```
AskUserQuestion({
  questions: [{
    question: "Which 1Password item contains your Gmail OAuth credentials?",
    header: "Gmail OAuth",
    options: [
      // POPULATE FROM op item list RESULTS - example:
      { label: "Gmail API - dental-quizzes (56peh...)", description: "OAuth client in Employee vault" },
      { label: "Gmail API - personal (abc12...)", description: "Personal OAuth client" },
    ],
    multiSelect: false
  }]
})
```

**If NO items found**, use AskUserQuestion to guide setup:

```
AskUserQuestion({
  questions: [{
    question: "No Gmail OAuth credentials found in 1Password. How would you like to proceed?",
    header: "Setup",
    options: [
      { label: "Create new OAuth credentials (Recommended)", description: "I'll guide you through Google Cloud Console setup" },
      { label: "I have credentials elsewhere", description: "Help me add them to 1Password" },
      { label: "Skip for now", description: "I'll set this up later" }
    ],
    multiSelect: false
  }]
})
```

- If "Create new OAuth credentials": Read and present [references/gmail-api-setup.md](./references/gmail-api-setup.md)
- If "I have credentials elsewhere": Guide user to add to 1Password with required fields
- If "Skip for now": Inform user the skill won't work until configured

### Setup Step 4: Confirm mise Configuration

After user selects an item (with UUID), use AskUserQuestion:

```
AskUserQuestion({
  questions: [{
    question: "Add GMAIL_OP_UUID to .mise.local.toml in current project?",
    header: "Configure",
    options: [
      { label: "Yes, add to .mise.local.toml (Recommended)", description: "Creates/updates gitignored config file" },
      { label: "Show me the config only", description: "I'll add it manually" }
    ],
    multiSelect: false
  }]
})
```

**If "Yes, add to .mise.local.toml"**:

1. Check if `.mise.local.toml` exists
2. If exists, append `GMAIL_OP_UUID` to `[env]` section
3. If not exists, create with:

```toml
[env]
GMAIL_OP_UUID = "<selected-uuid>"
```

1. Verify `.mise.local.toml` is in `.gitignore`

**If "Show me the config only"**: Output the TOML for user to add manually.

### Setup Step 5: Reload and Verify

```bash
mise trust 2>/dev/null || true
cd . && echo "GMAIL_OP_UUID after reload: ${GMAIL_OP_UUID:-NOT_SET}"
```

**If still NOT_SET**: Inform user to restart their shell or run `source ~/.zshrc`.

### Setup Step 6: Test Connection

```bash
GMAIL_OP_UUID="${GMAIL_OP_UUID}" $HOME/.claude/plugins/marketplaces/cc-skills/plugins/gmail-commander/scripts/gmail-cli/gmail list -n 1
```

**If OAuth prompt appears**: This is expected on first run. Browser will open for Google consent.

---

## Gmail Commands (Only After Preflight Passes)

```bash
GMAIL_CLI="$HOME/.claude/plugins/marketplaces/cc-skills/plugins/gmail-commander/scripts/gmail-cli/gmail"

# List recent emails
$GMAIL_CLI list -n 10

# Search emails
$GMAIL_CLI search "from:[email protected]" -n 20

# Search with date range
$GMAIL_CLI search "from:phoebe after:2026/01/27" -n 10

# Read specific email with full body
$GMAIL_CLI read <message_id>

# Read and download inline images (copy-pasted screenshots in compose)
$GMAIL_CLI read <message_id> --save-images

# Download inline images to a specific directory
$GMAIL_CLI read <message_id> --save-images --image-dir ./attachments/my-folder/

# Shorthand: --image-dir implies --save-images
$GMAIL_CLI read <mess

Related in Productivity