One CLI for every Zoho service
zone is the unified command line for the Zoho suite — 64 services, 9,432 typed commands, one OAuth login.
Every Zoho service ships its own API, its own scopes, and its own quirks — so anyone automating Zoho ends up writing the same OAuth dance, the same pagination loop, and the same retry logic over and over. zone does that once. You authenticate once, then drive CRM, Books, Desk, People, Projects and 59 more services from a single tool with one consistent output contract.
npm install -g wanas-zone-cli
zone loginNode.js and an npm registry are all you need. Published by Wanas Apps FZ-LLC — a Zoho Premium Partner.
One consent. No token juggling.
Authentication is the part everyone rewrites and nobody enjoys. zone treats it as solved infrastructure.
One OAuth consent
A single browser consent covers every service you pick at login. No per-service client registration, no copying refresh tokens between scripts.
Tokens stay on your machine
Sessions are written to a local store, one file per service. Refresh and 401-retry happen automatically, so a long-running script never dies on an expired token.
Per-project identities
zone login writes a ./.zone store and finds it the way git finds .git — walking up from the working directory. Each project folder can therefore hold a different Zoho identity: a client org here, a sandbox there. --global falls back to ~/.zone.
Datacenter-aware from the start
The datacenter is chosen at login and baked into every base URL, so a UAE org and an EU org never get crossed.
Two ways to drive it
Typed commands for the surface that is already wrapped; a universal proxy for everything else. Both share the same auth, the same output contract, and the same exit codes.
Typed commands
A real command for each operation — request bodies, pagination, file downloads and Zoho’s per-endpoint quirks are handled for you. Every group is discoverable with --help.
zone crm record list Deals --fields Deal_Name,Stage,Amount
zone crm field list Deals
zone books invoice list --status overdue
zone desk ticket list --jsonThe zone api proxy
Anything not yet typed is still one command away. The proxy signs the request with the same session, resolves the datacenter base URL, and returns the raw body — so a brand-new Zoho endpoint never blocks you.
zone api crm GET /crm/v8/settings/modules
zone api books POST /invoices --data @invoice.json
zone api desk GET /api/v1/tickets --jsonBuilt for AI coding agents
Ask a coding agent to "pull our overdue invoices and match them to CRM deals" and, without tooling, it will do three things badly: hand-roll an OAuth flow it cannot complete, guess REST paths from memory, and invent field API names that do not exist in your org. Every one of those failures is silent — you get plausible code that returns nothing. zone replaces all three guesses with one authenticated, typed, self-documenting command surface.
Why it changes the outcome
Auth is already done
A human runs zone login once. The agent never sees a secret, never writes an OAuth handler, and never asks you to paste a token into a chat window.
Field names come from your org
zone crm field list Deals returns the real API names from your CRM. The agent reads them instead of hallucinating Deal_Name vs dealName — the single most common cause of a Zoho script that runs cleanly and does nothing.
Output it can actually parse
--json and --toon put machine-readable data on stdout and keep progress messages on stderr, so nothing has to be scraped out of prose. TOON is the more compact of the two when context budget matters.
Failures it can detect
Exit codes mean something: 0 ok, 2 usage, 3 not authenticated, 4 missing scope, 5 Zoho rejected it, 6 blocked by policy, 7 retryable (network, 429, 5xx). With --json the last stderr line is always a structured error object — even for a missing argument — with a hint naming the fix. An agent branches on that instead of retrying blindly.
Discoverable, so it explores instead of guessing
zone <service> --help lists the command groups; zone <svc> <group> --help lists the leaves. An agent that does not know a command can find it in one call rather than inventing one.
The whole guide, on demand
zone llm prints a complete usage guide generated from the live command specs, so it can never drift from what actually ships. zone llm <service> narrows it to one service when the context window is tight.
Install the guide where your agent already looks
zone skill installs a router plus one skill per service — the real command names, the flags Zoho requires, payload shapes and live-org traps — as native skill or rules files for your agent. Only each skill’s one-line description is resident per prompt; the body loads when it triggers. Re-running after an upgrade refreshes zone’s own files and never touches text you wrote.
zone skill --ide claude- Claude Code — .claude/skills/zoho-zone/SKILL.md
- Antigravity / Gemini agent — .agents/skills/zoho-zone/SKILL.md
- Cursor — .cursor/rules/zoho-zone.mdc
- Windsurf — .windsurfrules
- GitHub Copilot — .github/copilot-instructions.md
- Cline / Roo Code — .clinerules
- Gemini CLI — GEMINI.md
- Codex / AGENTS.md standard — AGENTS.md
- Plain Markdown — ZOHO_ZONE_AI_CONTEXT.md
A realistic agent workflow
The task: find every Closed Won deal in CRM with no matching paid invoice in Books. Here is what the agent actually runs.
- 01
A human authenticates the project, once
The browser consent is the one step that needs a person. Run in the project folder, it writes ./.zone, so this identity applies to this repository only.
zone login crm books - 02
The agent loads the command surface
One command puts every typed command group into the agent’s rules file. From here it selects commands rather than inventing them.
zone skill --ide claude - 03
It reads your real schema before writing a query
The field list comes from your org, so the filter it builds next uses API names that exist.
zone crm field list Deals --json - 04
It pulls both sides with one identity
Same session, two services, no second OAuth flow. Pagination is handled by the command.
zone crm record list Deals --fields Deal_Name,Stage,Amount --per-page 200 --json zone books invoice list --status paid --json - 05
It handles failure instead of hiding it
If Books was never consented, the command exits 3 and prints a structured error. The agent stops and asks you to run login for that one service — rather than retrying a call that can never succeed.
# exit 3 — not authenticated {"ok":false,"error":{"code":"NOT_AUTHENTICATED","message":"Not signed in to books.","hint":"Run \"zone login books\" (or \"zone login --all\").","http_status":null,"zoho":null,"context":null}}
Write operations run only when they are explicitly invoked. Nothing above mutates a record, and an agent cannot acquire a scope you did not consent to.
Safe to hand to an agent pointed at a live org
A coding harness that grants shell access to zone has granted every write to every authenticated Zoho service — it cannot express “reads only”. So the guardrails live inside zone, at the one seam every request passes through, and a test fails if any call ever walks around it.
--dry-run on every command
A write is resolved and printed — method, path, body — instead of sent, exit 0. Reads still run, so an agent can leave it on while it builds a call. Uploads, downloads and zone bug honour it too.
zone crm record delete Leads 123 --dry-run --json
{"dry_run":true,"service":"crm","method":"DELETE","path":"/Leads/123","query":{},"body":null,"api_version":null}A read-only policy that means read-only
ZONE_POLICY (or --allow / --deny) gates by service and method; deny always wins and a blocked call exits 6 naming the rule. Endpoints are classified by what they do, not their verb — COQL and bulk read count as reads, and the Campaigns writes Zoho serves over GET count as writes.
ZONE_POLICY='*:GET' zone crm record create Leads --data @lead.json --json
{"ok":false,"error":{"code":"POLICY_DENIED","message":"Blocked by policy: crm:POST /Leads — not in the allow list.", ...}}Secrets never leave in the clear
Fields named like credentials are masked on every path out — stdout, --verbose details and the machine error line alike — and the literal value of any ZONE_* secret is scrubbed from free text. Tokens are only ever attached to Zoho hosts, and a path with “..” is refused before the policy runs.
zone books org list --json | grep -c "«redacted»"An audit log you can hand to a client
--audit <file> appends one JSONL line per request — real, denied or dry-run — with method, path, effect (read or write), status and timing. Metadata only, never a body, so the log cannot become a new place client data leaks.
{"ts":"2026-09-04T16:35:54.367Z","service":"crm","method":"DELETE","path":"/Leads/1","effect":"write","status":null,"outcome":"denied","policy":"denied","dry_run":false,"ms":null,"pid":40992}All four are enforced at one seam — zone’s own API client — through which every typed command, the zone api proxy, every file upload and download, and zone bug pass. The suite fails if a raw HTTP call appears anywhere outside it.
Coverage, measured against Zoho’s own docs
Every service was checked against its official API documentation and the gap closed. 30 of the 64 sit at 100% of their documented surface; across the suite that is roughly 7,280 documented operations. Where Zoho publishes a machine-readable spec, the commands are generated from it rather than from prose.
| Service | Commands | What that covers |
|---|---|---|
| Zoho Desk | 931 | Tickets, knowledge base, community, assignment rules, gamification |
| Zoho Books | 903 | Generated from Zoho’s own OpenAPI specs, alongside Invoice, Billing and Expense |
| Zoho CRM | 792 | V8/V9 metadata end-to-end — customization, process automation, security, Zia — plus COQL, bulk jobs and the Deluge toolchain |
| Zoho Inventory | 556 | Items, warehouses, orders, shipments, the full stock lifecycle |
| Zoho Projects | 507 | The complete V3 surface, including the v3.1 endpoints |
| Zoho People | 447 | Both published versions: v1/v2 for LMS and timesheets, v3 for leave and shifts |
Deluge, from your editor
Push, pull and test Deluge functions as files. Compilation errors come back with real line numbers that match the file on disk, not a blank 400.
Full CRM metadata extraction
zone crm extract pulls your org’s modules, fields, layouts and functions to disk — the authoritative reference for writing Deluge or REST code against that org, and a natural input for an AI agent.
Every datacenter, including the regional exceptions
The datacenter is part of the login, not an afterthought — and zone knows which products actually exist in each one.
- com
- eu
- in
- com.au
- jp
- uk
- ca
- sa
- ae
- cn
Regional products are enforced at login rather than failing later: Zoho Payroll, for example, exists only in com, in, ae and sa, so zone rejects a Payroll login on any other datacenter up front. Requesting a regional scope on the wrong datacenter would otherwise void the entire consent.
The published packages
zone is a thin CLI over four reusable packages. All five are open source and free, published on npm by Wanas Apps FZ-LLC; the source is on GitHub.
We built zone because we run Zoho implementations every day and needed one tool instead of forty-four. It is free, and it stays free.
Need this wired into your own Zoho stack?
We are a Zoho Premium Partner with 300+ implementations behind us. If you want custom integrations, Deluge automation, or AI agents working against your Zoho org, we can help.