Skip to content

chrisyoungcooks/gorgias-pp-cli

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Gorgias CLI

Generated by Printing Press Category: Customer Support

Drive your Gorgias support inbox from the terminal — ticket triage, agent replies, customer lookup, and bulk operations across all 108 endpoints, plus a local SQLite mirror for instant search and analytics.

The helpdesk for e-commerce support teams. This CLI gives you (or an AI agent) full control over a Gorgias tenant from a single binary: list, create, update, and reply to tickets via tickets list / get / update / messages-create; sweep stuck work with stale and orphans; query locally with sync + sql for SQL-grade analytics the live API doesn't expose; full-text search across synced data with search; and a sibling gorgias-pp-mcp server that lets Claude Desktop, Cursor, or Claude Code drive the surface natively.

The MCP server runs in code-orchestration mode: ~15 tools (a gorgias_search + gorgias_execute gateway over all 108 endpoints, plus typed local-mirror surfaces). Measured tool descriptions + JSON schemas together total ~9K tokens for the full surface — vs. roughly 5× that if every endpoint shipped its own typed tool. See MCP.md for the protocol-level design.

Learn more at Gorgias.

Install

go install github.com/chrisyoungcooks/gorgias-pp-cli/cmd/gorgias-pp-cli@latest
go install github.com/chrisyoungcooks/gorgias-pp-cli/cmd/gorgias-pp-mcp@latest

Pre-built binaries are attached to every GitHub Release — macOS (arm64 + amd64), Linux (arm64 + amd64), Windows (arm64 + amd64). On macOS, clear the Gatekeeper quarantine with xattr -d com.apple.quarantine <binary>; on Unix, chmod +x <binary>.

Or via Homebrew on macOS/Linux:

brew install chrisyoungcooks/tap/gorgias-pp-cli

The brew cask installs both gorgias-pp-cli and gorgias-pp-mcp and clears the Gatekeeper quarantine for you.

Authentication

Gorgias uses HTTP Basic auth: your account email is the username, an API key is the password.

  1. In Gorgias: Settings → Account → REST API → Create API key. Copy the key once — Gorgias won't show it again.
  2. Set three environment variables:
    export GORGIAS_USERNAME="you@example.com"
    export GORGIAS_API_KEY="<your-api-key>"
    export GORGIAS_BASE_URL="https://<tenant>.gorgias.com/api"
  3. Verify with gorgias-pp-cli doctorCredentials: valid means the values authenticate against /account. Alternatively, gorgias-pp-cli auth set-token <email> <api-key> persists them to $XDG_CONFIG_HOME/gorgias-pp-cli/config.toml.

Quick Start

# 1. Confirm credentials authenticate against the live tenant.
gorgias-pp-cli doctor --json

# 2. Sync the last 7 days into the local SQLite mirror.
gorgias-pp-cli sync --resources tickets,customers,tags --since 7d --agent

# 3. Today's queue — open tickets, oldest first.
gorgias-pp-cli tickets list --view-id <view-id> --limit 20 --agent

# 4. Full-text search the synced mirror (FTS5).
gorgias-pp-cli search refund --agent

# 5. Pull the full message thread on a specific ticket.
gorgias-pp-cli tickets messages-list <ticket-id> --agent

# 6. Stale-ticket sweep — open tickets with no activity for 7+ days.
gorgias-pp-cli stale --days 7 --agent

# 7. Workload distribution across the team.
gorgias-pp-cli load --agent

Unique Features

These capabilities are designed for agent-driven work and don't exist in the Gorgias web app or in a raw curl-against-the-API workflow.

Local state that compounds

  • gorgias-pp-cli sync — Mirror Gorgias resources into local SQLite. Incremental by default (each resource records a cursor and resumes from there); --full clears the cursor; --since 7d constrains the window. For tickets, --since uses documented order_by=updated_datetime:desc plus a local cutoff because Gorgias does not expose a documented ticket datetime filter. Mirror lives at $XDG_DATA_HOME/gorgias-pp-cli/data.db.
  • gorgias-pp-cli search <query> — FTS5 full-text search across the local mirror. Subsecond against tens of thousands of tickets/customers/messages once synced.
  • gorgias-pp-cli sql "SELECT ..." — Read-only SQL escape hatch over the mirror. SELECT/WITH only; comment-prefix bypass gated. Answers analytical questions the Gorgias API doesn't expose (cohort, group-by, top-N, joins).
  • gorgias-pp-cli stale --days N — Tickets with no activity in N days. Sources from the local mirror; never hammers the API.
  • gorgias-pp-cli orphans — Tickets missing required fields (assignee, team, priority, tags). Pipeline-hygiene check for managers.
  • gorgias-pp-cli load — Ticket workload distribution per assignee. Sources from the local mirror.

Agent-native plumbing

  • gorgias-pp-cli doctor --json — Probes /account with configured credentials. Reports credentials: valid only when an authenticated call actually succeeds. Exits non-zero on failure by default so CI gates work as expected. Saves the first-five-minutes credential-debug cycle when wiring up an agent.
  • gorgias-pp-cli agent-context --json — Machine-readable descriptor of the CLI: commands, global flags, env vars, MCP surface, capability count. Let an agent introspect the CLI without parsing --help text.
  • gorgias-pp-cli which "<capability>" — Fuzzy match a natural-language capability to the best command. Curated index (35+ entries) ranked with stopword-aware scoring.
  • gorgias-pp-cli api — Browse all 108 endpoints with their HTTP method and path. Discovery for the long tail.
  • --deliver file:./out.json / --deliver webhook:https://... — Route command output to a file (atomic write) or POST it to a webhook. No piping or shell redirection required.
  • GORGIAS_AUTO_REFRESH_TTL=15m — Every read syncs first if the mirror is older than the TTL. Trust local without losing freshness.
  • gorgias-pp-cli profile save <name> — Capture the current non-default flags as a named profile reusable via --profile <name>. Cuts repetition for agents that always reach for --agent --view-id 123456789 --limit 50.

Code-orchestration MCP

The sibling gorgias-pp-mcp exposes two gateway tools (gorgias_search + gorgias_execute) covering all 108 endpoints, plus typed tools for the local-mirror capabilities (sync, search, sql, stale, orphans, load, tail, export, import) and the compound workflows. The full tool surface (description + JSON schemas) measures ~9K context tokens, vs. roughly 5× that if every endpoint shipped its own typed tool. See MCP.md.

Cookbook

# Open tickets in a saved view.
gorgias-pp-cli tickets list --view-id <view-id> --limit 50 --agent

# Customer record by email.
gorgias-pp-cli customers list --channel-type email --channel-address user@example.com --agent

# Apply a tag to a ticket (find the tag id first with `tags list`).
gorgias-pp-cli tickets update 12345 --tags '[{"id": 67890}]' --agent

# Reply to a ticket as a specific support agent. The from-address MUST match
# the dispatching integration's meta.address or the email won't actually send.
gorgias-pp-cli tickets messages-create 12345 --stdin --agent <<'JSON'
{"channel":"email","via":"email","from_agent":true,"public":true,
 "sender":{"id":111111111},
 "receiver":{"email":"customer@example.com"},
 "source":{"from":{"address":"support@your-tenant.com"},
           "to":[{"address":"customer@example.com"}]},
 "body_html":"<p>Hi …</p><p>Best,<br>Agent Name</p>",
 "integration_id":22222}
JSON

# Stream live ticket changes (polling every 30s).
gorgias-pp-cli tail tickets --interval 30s --agent

# Export the local mirror to JSONL for downstream tooling.
gorgias-pp-cli export tickets --format jsonl --output tickets.jsonl

# Save a named profile of global defaults, then opt in per-call.
gorgias-pp-cli profile save agent-defaults --agent --compact
gorgias-pp-cli --profile agent-defaults tickets list

Commands

Run gorgias-pp-cli --help for the full reference. Grouped here by use case:

Daily workflow

Command What it does
tickets list List tickets, scoped by view/customer/rule/external_id/ticket_ids
tickets get <id> Fetch one ticket (status, assignee, customer, tags)
tickets update <id> Change status, assignee, tags, priority
tickets messages-create <id> Post a reply or internal note
customers list Look up a customer by email or external id
stale --days N Tickets with no activity in N days
orphans Tickets missing assignee/team/priority/tags
load Workload per assignee

Local mirror + analytics

Command What it does
sync Mirror API data to local SQLite
search <query> FTS5 full-text search over synced data
sql "<query>" Read-only SQL over the mirror
analytics Pre-built metrics over the mirror
tail <resource> Stream live changes by polling
export Dump a resource to JSON/CSV/JSONL
import Bulk-create from a JSON/CSV file

Resources

account custom-fields customers events gorgias-jobs integrations macros messages phone pickups reporting rules satisfaction-surveys tags teams ticket-search tickets users views widgets — every resource has list, get, create, update, delete (where the Gorgias API exposes them). Run gorgias-pp-cli <resource> --help for the full list.

Utilities

Command What it does
doctor Health check: config + auth + API reachability
auth setup / auth set-token / auth status Credential management
which "<capability>" Fuzzy-match a capability to a command
api Browse all 108 endpoints by resource
agent-context --json Machine-readable CLI descriptor
version Print the CLI version (add --json for the envelope)

Output formats

# Human-readable table (default in terminal, JSON when piped).
gorgias-pp-cli account get

# JSON for scripting and agents.
gorgias-pp-cli account get --json

# Filter to specific fields.
gorgias-pp-cli account get --json --select id,name,status

# Preview the request without sending.
gorgias-pp-cli account get --dry-run

# Agent mode: JSON + compact + no prompts + no color, in one flag.
gorgias-pp-cli account get --agent

Agent usage

Built for AI-agent consumption:

  • Non-interactive — never prompts; every input is a flag.
  • Pipeable--json to stdout, errors to stderr.
  • Filterable--select id,name returns only the named fields.
  • Previewable--dry-run shows the request without sending.
  • Explicit retries--idempotent (creates), --ignore-missing (deletes).
  • Confirmable--yes skips destructive-action prompts.
  • Stdin-capable--stdin accepts a full JSON body for create/update commands.
  • Offline-friendly — sync/search/sql work against the local mirror.
  • No color by default--human-friendly opts in to color and tables.

Exit codes: 0 success, 2 usage error, 3 not found, 4 auth error, 5 API error, 7 rate limited, 10 config error.

Error envelope

Under --json (or --agent), failures emit a single JSON document on stderr:

{"error": {"message": "<human-readable cause>", "exit_code": <int>}}

Commands that already carry status in their own JSON body (e.g. doctor --json) embed the failure inside the report instead, so jq always sees a single JSON document per stream.

Claude Code

See SKILL.md for the Claude Code skill descriptor. Quick wiring:

claude mcp add gorgias gorgias-pp-mcp \
  -e GORGIAS_USERNAME=<your-email> \
  -e GORGIAS_API_KEY=<your-api-key> \
  -e GORGIAS_BASE_URL=https://<tenant>.gorgias.com/api

Claude Desktop

Install gorgias-pp-mcp (see Install), then add it to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "gorgias": {
      "command": "gorgias-pp-mcp",
      "env": {
        "GORGIAS_USERNAME": "<your-email>",
        "GORGIAS_API_KEY": "<your-api-key>",
        "GORGIAS_BASE_URL": "https://<tenant>.gorgias.com/api"
      }
    }
  }
}

Restart Claude Desktop. The full config schema and secret-manager wrapper guidance is in MCP.md.

Cursor

See CURSOR.md.

Configuration

Variable Description
GORGIAS_USERNAME Your Gorgias account email; the username half of HTTP Basic auth.
GORGIAS_API_KEY Your Gorgias API key; the password half. Generated in Settings → Account → REST API.
GORGIAS_BASE_URL Your tenant's API URL, e.g. https://<tenant>.gorgias.com/api. Gorgias is multi-tenant — there is no default.
GORGIAS_CONFIG Override path to the TOML config file (default $XDG_CONFIG_HOME/gorgias-pp-cli/config.toml).
GORGIAS_AUTO_REFRESH_TTL When set, reads sync first if the local mirror is older than this duration (e.g. 15m).

XDG paths are honored on Unix; on Windows the CLI falls back to os.UserConfigDir / os.UserCacheDir.

Troubleshooting

Authentication errors (exit 4) — run gorgias-pp-cli doctor. Verify env vars are set (printenv GORGIAS_USERNAME GORGIAS_API_KEY GORGIAS_BASE_URL).

404 Not Found on every commandGORGIAS_BASE_URL isn't picked up, or points at the wrong tenant. The doctor warns when the slug looks like app or your-company.

MCP server exposes ~15 tools but I expected one per endpoint — by design. Two of those tools (gorgias_search + gorgias_execute) are the gateway that reaches every Gorgias endpoint; the rest (context, search, sql, sync, analytics, orphans, stale, load, tail, export, import, workflow_archive, workflow_status) are typed surfaces for local-mirror queries and compound workflows. Call context for the live count + manifest.

search <query> returns nothing live — Gorgias's /search indexes customers/agents/tags/teams/integrations, not tickets or messages. For ticket text search, sync first: gorgias-pp-cli sync --resources tickets --since 30d && gorgias-pp-cli search <query> --data-source local.

sync --resources tickets --since 7d scans more pages than expected — Ticket --since is intentionally a local cutoff over documented order_by=updated_datetime:desc. Do not "fix" this by adding undocumented filters like updated_datetime__gte; a live test on May 23, 2026 returned HTTP 400 Unknown field for that parameter. If the API ever returns tickets out of newest-first order, the CLI emits a sync_warning and continues scanning/filtering locally rather than stopping early.

HTTP 400 "Must be at most 100" on a list — Gorgias caps --limit at 100. Paginate via --cursor <meta.next_cursor>.

HTTP 400 on customers list --language en --cursor ... — Gorgias rejects language/timezone filters when combined with cursor/limit/order-by. Drop the pagination flags or use --name/--email instead.

HTTP 400 on events list --object-type Ticket — Gorgias requires --object-id alongside --object-type.

Rate limited (exit 7) — slow down with --rate-limit 2 or fetch from the local mirror after sync.

Local data feels stale — set GORGIAS_AUTO_REFRESH_TTL=15m, or run gorgias-pp-cli sync --full to wipe and rebuild.

Gorgias API gotchas

Non-obvious behaviors of the Gorgias API itself that you'll hit if you exercise these endpoints directly:

  • POST /views requires slug, which is also marked DEPRECATED. The deprecation label means the field is on its way out, not that it's optional today — omit it and you get 400 "Missing data for required field". Pass any URL-safe string.
  • POST /views filter DSL only accepts a fixed allowlist of ticket.* paths, not arbitrary ticket.<anything>. Supported: assignee_team.id, assignee_user.id, customer.id, messages.integration_id, channel, language, status, priority, store_id, custom_fields, customer.custom_fields. Anything else returns 400 with the full list in the error.
  • POST /integrations with type: "http" requires http.url, http.method, http.request_content_type, and http.response_content_type. The docs treat http as an opaque object; these requirements are visible only in an example body.
  • POST /rules rejects the code field unless it matches Gorgias's internal AST grammar. Plain JavaScript is rejected even when syntactically complete. Pass code_ast (a pre-parsed AST) and confirm the shape with Gorgias support.
  • POST /tickets requires messages[0].source.from even when from_agent: true. Omitting it returns 400 "From field is missing or empty".
  • GET /tickets has no documented server-side updated-time cutoff. Use sync --resources tickets --since ... for local mirroring; it requests documented order_by=updated_datetime:desc and filters locally. Avoid updated_datetime__gte unless Gorgias documents it and a live smoke confirms it for the tenant.
  • DELETE /custom-fields/{id} returns 405. The Gorgias API has no path to delete custom fields. Archive via the admin UI; plan create-once-and-keep accordingly.
  • POST /tickets outbound dispatch fails silently if source.from.address doesn't match the integration's meta.address. The create returns 201 and the message is processed, but sent_datetime stays null and last_sending_error records "No integration was found to send this email." Always pair integration_id with a source.from.address that matches GET /integrations/{id}.meta.address. A 201 does not mean the email was delivered.

Known gaps

See KNOWN_GAPS.md for the long form. The short version: write endpoints have dry-run request-shape coverage and confirmation guards, but tenant-specific live validation should be run against a sandbox tenant before production mutation. Phone/voice endpoints haven't been exercised against a tenant with a voice integration.

Sources & inspiration

This CLI was scaffolded end-to-end by CLI Printing Press from the upstream Gorgias OpenAPI spec, then hardened across seven rounds of adversarial review focused on the patterns top-10% PP CLIs share: tenant-agnostic install, single-emission JSON error envelopes, XDG paths, dynamic MCP tool count, doctor exits non-zero on failure. The local-mirror design (sync + FTS5 + sql) mirrors what the Linear PP CLI pioneered for compounding agent context.


Generated by CLI Printing Press.

About

Token-efficient Go CLI + MCP server for the Gorgias customer support REST API. Built with the Printing Press framework.

Topics

Resources

License

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors