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.
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@latestPre-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-cliThe brew cask installs both gorgias-pp-cli and gorgias-pp-mcp and clears the Gatekeeper quarantine for you.
Gorgias uses HTTP Basic auth: your account email is the username, an API key is the password.
- In Gorgias: Settings → Account → REST API → Create API key. Copy the key once — Gorgias won't show it again.
- 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"
- Verify with
gorgias-pp-cli doctor—Credentials: validmeans 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.
# 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 --agentThese 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.
gorgias-pp-cli sync— Mirror Gorgias resources into local SQLite. Incremental by default (each resource records a cursor and resumes from there);--fullclears the cursor;--since 7dconstrains the window. For tickets,--sinceuses documentedorder_by=updated_datetime:descplus 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.
gorgias-pp-cli doctor --json— Probes/accountwith configured credentials. Reportscredentials: validonly 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--helptext.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.
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.
# 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 listRun gorgias-pp-cli --help for the full reference. Grouped here by use case:
| 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 |
| 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 |
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.
| 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) |
# 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 --agentBuilt for AI-agent consumption:
- Non-interactive — never prompts; every input is a flag.
- Pipeable —
--jsonto stdout, errors to stderr. - Filterable —
--select id,namereturns only the named fields. - Previewable —
--dry-runshows the request without sending. - Explicit retries —
--idempotent(creates),--ignore-missing(deletes). - Confirmable —
--yesskips destructive-action prompts. - Stdin-capable —
--stdinaccepts a full JSON body for create/update commands. - Offline-friendly — sync/search/sql work against the local mirror.
- No color by default —
--human-friendlyopts 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.
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.
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/apiInstall 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.
See CURSOR.md.
| 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.
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 command — GORGIAS_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.
Non-obvious behaviors of the Gorgias API itself that you'll hit if you exercise these endpoints directly:
POST /viewsrequiresslug, 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 get400 "Missing data for required field". Pass any URL-safe string.POST /viewsfilter DSL only accepts a fixed allowlist ofticket.*paths, not arbitraryticket.<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 /integrationswithtype: "http"requireshttp.url,http.method,http.request_content_type, andhttp.response_content_type. The docs treathttpas an opaque object; these requirements are visible only in an example body.POST /rulesrejects thecodefield unless it matches Gorgias's internal AST grammar. Plain JavaScript is rejected even when syntactically complete. Passcode_ast(a pre-parsed AST) and confirm the shape with Gorgias support.POST /ticketsrequiresmessages[0].source.fromeven whenfrom_agent: true. Omitting it returns400 "From field is missing or empty".GET /ticketshas no documented server-side updated-time cutoff. Usesync --resources tickets --since ...for local mirroring; it requests documentedorder_by=updated_datetime:descand filters locally. Avoidupdated_datetime__gteunless 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 /ticketsoutbound dispatch fails silently ifsource.from.addressdoesn't match the integration'smeta.address. The create returns 201 and the message is processed, butsent_datetimestays null andlast_sending_errorrecords"No integration was found to send this email."Always pairintegration_idwith asource.from.addressthat matchesGET /integrations/{id}.meta.address. A 201 does not mean the email was delivered.
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.
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.