Skip to content

feat(zoho-desk): add zoho-desk#1413

Open
kentrichardmartin wants to merge 2 commits into
mvanhorn:mainfrom
kentrichardmartin:feat/zoho-desk
Open

feat(zoho-desk): add zoho-desk#1413
kentrichardmartin wants to merge 2 commits into
mvanhorn:mainfrom
kentrichardmartin:feat/zoho-desk

Conversation

@kentrichardmartin

Copy link
Copy Markdown

zoho-desk

The only scriptable, agent-native CLI for Zoho Desk: every ticket operation plus a local SQLite store, offline search, and SLA/triage analytics no help-desk tool ships.

API: zoho-desk | Category: sales-and-crm | Press version: 4.27.0
Spec: internal YAML (no official OpenAPI for Zoho Desk; hand-authored from desk.zoho.com/DeskAPIDocument)

Publication Path

New print

CLI Shape

Zoho Desk CLI — The only scriptable, agent-native CLI for Zoho Desk: every ticket operation plus a local SQLite store, offline search, …

Highlights (not in the official API docs):
  • sla-radar   See which open tickets will breach SLA in the next N hours, ranked by time-to-due, before they breach.
  • agent-load   See which agents are actually overloaded right now, weighting open tickets by priority and age versus the team median.
  • triage   One ranked queue merging unassigned, overdue, and high-priority tickets with a combined score.
  • since   Every ticket modified within a time window, with its current status, priority, and assignee, sorted most-recent first.
  • contact-360   Everything about one customer in one view: their contact record, account, and every ticket with status and priority.
  • morning   A single brief composing breach forecast, agent load, and overnight changes.
  • rebalance   Proposes ticket moves from overloaded agents to idle ones, then optionally applies them in bulk.
  • breach-history   Who breached SLA and the trend, grouped by agent or department.

Agent mode: add --agent to any command for JSON output + non-interactive mode.
Health check: run 'zoho-desk-pp-cli doctor' to verify auth and connectivity.
See README.md or the bundled SKILL.md for recipes.

Usage:
  zoho-desk-pp-cli [command]

Available Commands:
  agent-context  Emit structured JSON describing this CLI for agents
  agent-load     See which agents are actually overloaded right now, weighting open tickets by priority and age versus the team median.
  analytics      Run analytics queries on locally synced data
  api            Browse all API endpoints by interface name
  auth           Manage authentication for Zoho Desk
  breach-history Who breached SLA and how often, grouped by agent or department.
  completion     Generate the autocompletion script for the specified shell
  contact-360    Everything about one customer: their contact record, account, and tickets in a single view.
  doctor         Check CLI health
  export         Export data to JSONL or JSON for backup, migration, or analysis
  feedback       Record feedback about this CLI (local by default; upstream opt-in)
  help           Help about any command
  import         Import data from JSONL file via API create/upsert calls
  load           Show workload distribution per assignee
  morning        A single brief composing breach forecast, agent load, and overnight changes.
  orphans        Find items missing key fields like assignee or project
  profile        Named sets of flags saved for reuse
  rebalance      Propose ticket moves from overloaded agents to idle ones, then optionally apply them in bulk.
  search         Full-text search across synced data or live API
  since          Every ticket modified within a time window, most recent first.
  sla-radar      See which open tickets will breach SLA in the next N hours, ranked by time-to-due, before they breach.
  slas           List SLAs
  stale          Find items with no updates in N days
  sync           Sync API data to local SQLite for offline search and analysis
  tags           List tags
  tail           Stream live changes by polling the API at regular intervals
  ticketfields   List ticket fields
  tickets-search Search tickets by criteria
  triage         One ranked queue merging unassigned, overdue, and high-priority tickets with a priority score.
  version        Print version
  which          Find the command that implements a capability
  workflow       Compound workflows that combine multiple API operations

Flags:
      --agent                   Set all agent-friendly defaults (--json --compact --no-input --no-color --yes)
      --allow-partial-failure   Downgrade response-body partial-failure (e.g. partialFailureError) to a warning instead of a non-zero exit
      --compact                 Return only key fields (id, name, status, timestamps) for minimal token usage
      --config string           Config file path
      --csv                     Output as CSV (table and array responses)
      --data-source string      Data source for read commands: auto (live with local fallback), live (API only), local (synced data only) (default "auto")
      --deliver string          Route output to a sink: stdout (default), file:<path>, webhook:<url>
      --dry-run                 Show request without sending
  -h, --help                    help for zoho-desk-pp-cli
      --home string             Root directory for config, data, state, and cache files
      --human-friendly          Enable colored output and rich formatting
      --idempotent              Treat already-existing create results as a successful no-op
      --ignore-missing          Treat missing delete targets as a successful no-op
      --json                    Output as JSON
      --max-age duration        Maximum acceptable age of local-store data before a stderr hint suggests sync; 0 disables (default 30m0s)
      --no-cache                Bypass response cache
      --no-color                Disable colored output
      --no-input                Disable all interactive prompts (for CI/agents)
      --plain                   Output as plain tab-separated text
      --profile string          Apply values from a saved profile (see 'zoho-desk-pp-cli profile list')
      --quiet                   Bare output, one value per line
      --rate-limit float        Max requests per second (0 to disable)
      --select string           Comma-separated fields to include in output (e.g. --select id,name,status)
      --timeout duration        Request timeout (default 1m0s)
  -v, --version                 version for zoho-desk-pp-cli
      --yes                     Skip confirmation prompts (for agents and scripts)

Use "zoho-desk-pp-cli [command] --help" for more information about a command.

Novel Commands

Command Name Description
sla-radar SLA breach forecast See which open tickets will breach SLA in the next N hours, ranked by time-to-due, before they breach.
agent-load Weighted agent load See which agents are actually overloaded right now, weighting open tickets by priority and age versus the team median.
triage Composite triage queue One ranked queue merging unassigned, overdue, and high-priority tickets with a combined score.
since Overnight changes Every ticket modified within a time window, with its current status, priority, and assignee, sorted most-recent first.
contact-360 Contact 360 Everything about one customer in one view: their contact record, account, and every ticket with status and priority.
morning Morning dashboard A single brief composing breach forecast, agent load, and overnight changes.
rebalance Rebalance planner Proposes ticket moves from overloaded agents to idle ones, then optionally applies them in bulk.
breach-history Breach history Who breached SLA and the trend, grouped by agent or department.

What This CLI Does

The only scriptable, agent-native CLI for Zoho Desk: every ticket operation plus a local SQLite store, offline search, and SLA/triage analytics no help-desk tool ships.

Manage tickets, contacts, accounts, and agents from the command line with automatic OAuth token refresh, multi-data-center handling, and auto-pagination with 429 backoff. Then go beyond the API: sla-radar forecasts breaches before they happen, agent-load finds the real bottleneck, triage builds one ranked queue, and morning composes your whole shift brief.

Manuscripts

Validation Results

Check Result
Manifest PASS
Transcendence PASS
Phase 5 PASS
go mod tidy PASS
govulncheck (this CLI only, reachable) PASS
go vet PASS
go build PASS
--help PASS
--version PASS
verify-skill PASS
Manuscripts PASS

Scorecard 95/100 (Grade A), verify 100% (34/34), shipcheck 7/7.

Publish Live Gate

Live dogfood (read-only OAuth scopes) passed against the real upstream API: 13/13 read-path tests passed, 11 write commands skipped (read-only token, no fixtures). doctor green, OAuth2 refresh verified, agents/departments/tickets listed live, sync + agent-load/triage/morning produced correct output over real synced data. Proof: proofs/phase5-acceptance.json.

Gaps

  • Internal hand-authored YAML spec (no official OpenAPI exists for Zoho Desk).
  • Live gate run at read-only scope; write-side lifecycle (create/update/close/reply) not exercised against the live portal by design.

@github-actions

Copy link
Copy Markdown
Contributor

@greptileai review

Auto-nudge from greptile-policy-gate.yml because no Greptile Review check appeared for 0b1c6164c2db7326862b7910e0dc924f26cfcf6d after 187s. This usually means the PR is over Greptile auto-review size cap; manual triggers bypass it.

@greptile-apps

greptile-apps Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds the zoho-desk CLI to the library — a full-featured, agent-native tool covering tickets, contacts, accounts, agents, and departments with OAuth token refresh, multi-data-center support, and a local SQLite store for offline analytics. All four previously flagged issues (morning.go help guard, isClosedStatus missing "Resolved", rebalance --plan dead flag, and breach-history SLA denominator) have been addressed in this revision.

  • Eight novel analytics commands (sla-radar, agent-load, triage, since, contact-360, morning, rebalance, breach-history) are introduced alongside the standard CRUD surface for every Zoho Desk resource.
  • The shared helper file zoho_transcend.go centralises time parsing, priority weighting, status matching, and store reads, keeping the command bodies lean.
  • agent-load, triage, sla-radar, and breach-history all retain a help guard (if len(args) == 0 && cmd.Flags().NFlag() == 0) that was already removed from morning.go after the same defect was found; all four commands take no positional arguments and have fully-defaulted flags, so a bare invocation shows the help page rather than running.

Confidence Score: 4/5

The core read-only analytics commands are blocked from zero-argument invocation by a retained help guard; everything else is well-structured and the previous iteration's issues were resolved.

Four analytics commands — agent-load, triage, sla-radar, and breach-history — silently show their help page when invoked with no explicit flags, even though all their flags have sensible defaults and none accept positional arguments. The identical guard was already identified and removed from morning.go in this same PR, so the fix pattern is clear, but it was not applied consistently. All other previously-flagged issues (isClosedStatus, rebalance --plan, breach-rate denominator) are resolved in the current code.

library/sales-and-crm/zoho-desk/internal/cli/agent_load.go, triage.go, sla_radar.go, and breach_history.go — each contains the help guard that needs to be removed.

Important Files Changed

Filename Overview
library/sales-and-crm/zoho-desk/internal/cli/agent_load.go Novel agent-load command; help guard on line 34 prevents zero-argument invocations from running despite all flags having defaults.
library/sales-and-crm/zoho-desk/internal/cli/triage.go Novel triage command; same help guard pattern as agent-load blocks bare invocations even though --limit defaults to 20.
library/sales-and-crm/zoho-desk/internal/cli/sla_radar.go Novel sla-radar command; help guard blocks bare invocations though --within defaults to 24h.
library/sales-and-crm/zoho-desk/internal/cli/breach_history.go Novel breach-history command; help guard blocks bare invocations though --by defaults to "agent".
library/sales-and-crm/zoho-desk/internal/cli/zoho_transcend.go Shared helpers for analytics commands; isClosedStatus now correctly matches both "closed" and "resolved".
library/sales-and-crm/zoho-desk/internal/cli/morning.go Morning dashboard command; help guard correctly removed — zero-argument invocation runs as intended.
library/sales-and-crm/zoho-desk/internal/cli/rebalance.go Rebalance command; --plan flag now correctly vetoes --apply via cmd.Flags().Changed("plan") check.
library/sales-and-crm/zoho-desk/internal/cli/contact_360.go Contact-360 command; help guard is appropriate since command requires a positional email argument.
library/sales-and-crm/zoho-desk/internal/cli/since.go Since command; help guard appropriate as command requires a positional duration argument.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A["zoho-desk-pp-cli <command>"] --> B{has positional args\nor explicit flags?}
    B -- "YES (NFlag > 0 or len(args) > 0)" --> C[Execute command logic]
    B -- "NO" --> D{command type}
    D -- "morning" --> C
    D -- "since / contact-360\n(require positional args)" --> E[Show Help ✓ correct]
    D -- "agent-load / triage /\nsla-radar / breach-history\n(no args, defaults exist)" --> F["Show Help ✗ bug\n(default run blocked)"]
    C --> G[Load tickets from SQLite]
    G --> H{analytics type}
    H -- "sla-radar" --> I[Filter: open + due within window]
    H -- "agent-load" --> J[Group by assignee, weight by priority+age]
    H -- "triage" --> K[Score: unassigned+overdue+priority+age]
    H -- "breach-history" --> L[Group SLA breaches by agent/dept]
    H -- "morning" --> M[Compose breach forecast + agent load + recent changes]
    H -- "rebalance" --> N{flagApply?}
    N -- "plan mode" --> O[Emit move proposals]
    N -- "apply mode" --> P[PATCH /tickets/id via API]
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A["zoho-desk-pp-cli <command>"] --> B{has positional args\nor explicit flags?}
    B -- "YES (NFlag > 0 or len(args) > 0)" --> C[Execute command logic]
    B -- "NO" --> D{command type}
    D -- "morning" --> C
    D -- "since / contact-360\n(require positional args)" --> E[Show Help ✓ correct]
    D -- "agent-load / triage /\nsla-radar / breach-history\n(no args, defaults exist)" --> F["Show Help ✗ bug\n(default run blocked)"]
    C --> G[Load tickets from SQLite]
    G --> H{analytics type}
    H -- "sla-radar" --> I[Filter: open + due within window]
    H -- "agent-load" --> J[Group by assignee, weight by priority+age]
    H -- "triage" --> K[Score: unassigned+overdue+priority+age]
    H -- "breach-history" --> L[Group SLA breaches by agent/dept]
    H -- "morning" --> M[Compose breach forecast + agent load + recent changes]
    H -- "rebalance" --> N{flagApply?}
    N -- "plan mode" --> O[Emit move proposals]
    N -- "apply mode" --> P[PATCH /tickets/id via API]
Loading

Reviews (2): Last reviewed commit: "fix(zoho-desk): correct 4 novel-command ..." | Re-trigger Greptile

Comment thread library/sales-and-crm/zoho-desk/internal/cli/rebalance.go Outdated
totalBreaches := 0
for _, t := range tickets {
key := str(t, keyField)
totals[key]++

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Breach rate denominator includes tickets without SLA

totals[key]++ runs unconditionally for every ticket, including tickets with no dueDate. Tickets without a dueDate are not SLA-governed and can never breach, so they should not count toward the denominator. With many non-SLA tickets in the store the reported breachRate will be significantly lower than the true SLA breach rate. The increment should be guarded by if str(t, "dueDate") != "" so only SLA-governed tickets appear in both numerator and denominator.

Fix in Codex Fix in Claude Code Fix in Cursor Fix in Conductor

Comment thread library/sales-and-crm/zoho-desk/internal/cli/morning.go
Comment thread library/sales-and-crm/zoho-desk/internal/cli/zoho_transcend.go
- isClosedStatus: match Resolved + custom terminal statuses, not only Closed
- morning: run the zero-arg dashboard instead of printing help
- breach-history: exclude non-past-due tickets from the breach denominator
- rebalance: honor explicit --plan (forces dry-run even with --apply)
@github-actions

Copy link
Copy Markdown
Contributor

@greptileai review

Auto-nudge from greptile-policy-gate.yml because no Greptile Review check appeared for 7b1371e853884e69b3f544f1905f56e92da8cabf after 186s. This usually means the PR is over Greptile auto-review size cap; manual triggers bypass it.

@kentrichardmartin

Copy link
Copy Markdown
Author

All four review findings are fixed in commit 7b1371e:

  1. rebalance.go — dead --plan flag: --plan is now read. An explicit --plan forces dry-run even when --apply is also passed (cmd.Flags().Changed("plan") && flagPlandoApply = false). Verified: rebalance --plan --apply returns mode: plan.
  2. breach_history.go — denominator dilution: tickets without a past-due dueDate are now excluded from the breach denominator (the totals[key]++ moved after the dueDate/past-due guard). Breach rate now reflects only SLA-applicable, past-due tickets.
  3. morning.go — zero-arg help guard: removed the len(args)==0 && NFlag()==0 → Help() guard so a bare morning runs the dashboard (its primary use case). --dry-run short-circuit retained.
  4. zoho_transcend.goisClosedStatus too narrow: now matches closed and resolved case-insensitively (was literal "Closed" only), so terminal statuses aren't treated as open across all five analytics commands.

Updated the breach-history behavioral test to assert the corrected denominator (Total 2, not 3 — the future-due ticket is no longer counted). go build, go vet, and go test ./internal/cli/... all pass; Greptile re-review is 4/5 with the policy gate green.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant