Gorgias CLI (Printing Press)

CLI

Unofficial Gorgias CLI built with Printing Press for e-commerce support: lets AI list, reply to and update tickets, look up customers, find stale or incomplete tickets, and sync data locally for full-text search and SQL. Includes a skill and MCP server. Needs a Gorgias account and API key.

mvanhorn/printing-press-library · library/sales-and-crm/gorgias2.1k
GitHub에서 보기
README

Gorgias CLI

Generated by Printing Press Category: Sales and CRM

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.

Created by @chrisyoungcooks (Chris Young).

Install

The recommended path installs both the gorgias-pp-cli binary and the pp-gorgias agent skill (Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, and other agents supported by the upstream skills CLI) in one shot:

npx -y @mvanhorn/printing-press-library install gorgias

For CLI only (no skill):

npx -y @mvanhorn/printing-press-library install gorgias --cli-only

For skill only — installs the skill into the same agents as the default command above, but skips the CLI binary (use this to update or reinstall just the skill):

npx -y @mvanhorn/printing-press-library install gorgias --skill-only

To constrain the skill install to one or more specific agents (repeatable — agent names match the skills CLI):

npx -y @mvanhorn/printing-press-library install gorgias --agent claude-code
npx -y @mvanhorn/printing-press-library install gorgias --agent claude-code --agent codex

Without Node (Go fallback)

If npx isn't available (no Node, offline), install the CLI directly via Go (requires Go 1.26.6 or newer):

go install github.com/mvanhorn/printing-press-library/library/sales-and-crm/gorgias/cmd/gorgias-pp-cli@latest

This installs the CLI only — no skill.

Pre-built binary

Download a pre-built binary for your platform from the latest release. On macOS, clear the Gatekeeper quarantine: xattr -d com.apple.quarantine <binary>. On Unix, mark it executable: chmod +x <binary>.

Install for Hermes

Install the CLI binary first. The installer writes binaries to a per-user managed bin directory by default: $HOME/.local/bin on macOS/Linux and %LOCALAPPDATA%\Programs\PrintingPress\bin on Windows.

npx -y @mvanhorn/printing-press-library install gorgias --cli-only

Then install the focused Hermes skill.

From the Hermes CLI:

hermes skills install mvanhorn/printing-press-library/cli-skills/pp-gorgias --force

Inside a Hermes chat session:

/skills install mvanhorn/printing-press-library/cli-skills/pp-gorgias --force

Restart the Hermes session or gateway if the newly installed skill is not visible immediately.

Install for OpenClaw

Install both the CLI binary and the focused OpenClaw skill. The installer defaults binaries to a per-user bin directory ($HOME/.local/bin on macOS/Linux, %LOCALAPPDATA%\Programs\PrintingPress\bin on Windows):

npx -y @mvanhorn/printing-press-library install gorgias --agent openclaw

Restart the OpenClaw session or gateway if the newly installed skill is not visible immediately.

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="account-email-placeholder"
    export GORGIAS_API_KEY="<your-api-key>"
    export GORGIAS_BASE_URL="https://<tenant>.gorgias.com/api"
    
  3. Verify with gorgias-pp-cli doctor — Credentials: 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 customer-lookup-placeholder --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-email-placeholder"},
 "source":{"from":{"address":"support-address-placeholder"},
           "to":[{"address":"customer-email-placeholder"}]},
 "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 --resource tickets --interval 30s --agent

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

# 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

CommandWhat it does
tickets listList 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 listLook up a customer by email or external id
stale --days NTickets with no activity in N days
orphansTickets missing assignee/team/priority/tags
loadWorkload per assignee

Local mirror + analytics

CommandWhat it does
syncMirror API data to local SQLite
search <query>FTS5 full-text search over synced data
sql "<query>"Read-only SQL over the mirror
analyticsPre-built metrics over the mirror
tail <resource>Stream live changes by polling
exportDump a resource to JSON/CSV/JSONL
importBulk-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

CommandWhat it does
doctorHealth check: config + auth + API reachability
auth setup / auth set-token / auth statusCredential management
which "<capability>"Fuzzy-match a capability to a command
apiBrowse all 108 endpoints by resource
agent-context --jsonMachine-readable CLI descriptor
versionPrint 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

VariableDescription
GORGIAS_USERNAMEYour Gorgias account email; the username half of HTTP Basic auth.
GORGIAS_API_KEYYour Gorgias API key; the password half. Generated in Settings → Account → REST API.
GORGIAS_BASE_URLYour tenant's API URL, e.g. https://<tenant>.gorgias.com/api. Gorgias is multi-tenant — there is no default.
GORGIAS_CONFIGOverride path to the TOML config file (default $XDG_CONFIG_HOME/gorgias-pp-cli/config.toml).
GORGIAS_AUTO_REFRESH_TTLWhen 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 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.

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.