npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

wanas-zone-cli

v0.8.3

Published

zone — one CLI for the whole Zoho suite: CRM, Mail, Meeting, Books, Inventory, Creator, Partner Store, Social, Projects, Desk, Sign, Writer, Sheet, Learn, TrainerCentral, People, Campaigns, Marketing Automation, WorkDrive, Cliq and Survey. Unified OAuth,

Readme

One CLI for the whole Zoho suite. zone signs you in once and gives you 9,909 typed commands across 64 services — CRM, Books, Desk, Mail, Projects, Inventory, People, WorkDrive, Cliq, Campaigns, Creator, Catalyst, Zoho One, Payments, Contracts, Connect and the rest — plus a raw proxy for any endpoint the typed commands miss. Auth, token refresh, datacenter routing, org/portal context and pagination are handled once, in one place. It is built for coding agents as much as for people: data on stdout, messages on stderr, a JSON error envelope, meaningful exit codes, a dry-run switch and a policy gate that make it safe to hand to an AI tool pointed at a live client org.

npm install -g wanas-zone-cli

Contents

Install and first call · The model · Agent contract · Safety · Skills for AI tools · Finding a command · Services · Authentication · Environment variables · Troubleshooting · Development · Changelog · Support

Install and first call

npm install -g wanas-zone-cli
zone login crm                 # one browser consent; add more services any time

The first real call — a COQL count against your own CRM:

zone crm coql "select COUNT(id) as leads from Leads where id is not null" --json
{
  "data": [
    {
      "leads": 4424
    }
  ],
  "info": {
    "count": 1,
    "more_records": false
  }
}

If an AI coding tool will drive zone, install the skills before you ask it for Zoho work. No model knows 9,909 commands from memory; the skills carry the real names, required flags, payload shapes and the traps found on live orgs. Install the skills BEFORE the first prompt — it is one command:

zone skill                     # this project (interactive picker for the agent)
zone skill --global            # once, for every project on this machine

Prefer not to install globally? npx wanas-zone-cli <command> works too.

The model

Five ideas cover almost everything zone does.

One login, many services. zone login crm books desk opens one consent for the named services (--all takes every core service in one go; extended services are named explicitly). Zoho issues one shared grant; each service gets its own session file under .zone/sessions/, so a token problem in one never touches another. Refresh is automatic.

Sessions are per project. zone login writes to ./.zone, found the way git finds .git — by walking up from the current directory. Each client repo carries its own Zoho identity and cd switches org with no re-login. --global uses ~/.zone; ZONE_HOME overrides both. .zone directories self-ignore in git.

Typed commands, with a proxy underneath. Every command has the shape zone <service> <group> <name> [args] [flags]:

zone crm record list Leads --fields Last_Name,Company --per-page 5
zone books invoice list --per-page 5 --toon
zone mail folder list --toon
zone crm coql "select id, Deal_Name from Deals where Stage = 'Closed Won'"

Anything not typed yet is one call away through the same client, with the same auth, refresh, datacenter routing and 401 retry:

zone api crm GET /Leads --query fields=Last_Name,Company --query per_page=5
zone api crm GET /org --out org.json
echo '{"data":[{"Last_Name":"Doe"}]}' | zone api crm POST /Leads --data - --dry-run

--data takes inline JSON, @file, or - for stdin; --form k=v sends urlencoded fields; --out saves raw bytes.

Context is injected for you. Zoho scopes calls inconsistently — Books wants organization_id in the query, Desk an orgId header, Projects a portal id in the path. Store each once and every later call carries it; an explicit --query organization_id=... always wins.

zone ctx books organization_id=847058403
zone ctx desk orgId=700123456
zone ctx books                          # show what is stored

CRM sandbox and developer edition. Zoho CRM serves the same API on three hosts — production (www.zohoapis.<dc>), the org's sandbox (sandbox.zohoapis.<dc>) and the developer edition (developer.zohoapis.<dc>) — and binds every OAuth token to the organization picked on the consent screen. Log in to the sandbox in its own store (ZONE_HOME=./.zone-sandbox zone login crm, choose the Sandbox organization): zone asks the org which environment it is (GET /org → type), stores env=sandbox, and every zone crm … command, zone api crm, bulk, functions and the absolute-URL rows go to the sandbox host. zone status grows an ENV column while any service is off production (and shows SANDBOX ≠ token production when the context and the token disagree), each command prints one stderr line naming the environment, and --dry-run reports environment and base. zone ctx crm env=… moves the host by hand and warns when the stored token is bound elsewhere; a production token on the sandbox host gets DOMAIN_TOKEN_MISMATCH with the fix in its hint.

Output is a contract. Data goes to stdout, messages to stderr, so a pipe is never polluted. --json renders JSON; --toon renders TOON, a compact form that costs an LLM 30–60% fewer tokens for the same data. Both wrap plain-text responses so JSON.parse(stdout) always works. The rest of that contract is the next section.

Agent contract

zone's primary users are coding agents. What they can rely on:

  • stdout is data, stderr is messages. Progress, hints and warnings never land in the data stream; -q silences them.

  • Exit codes mean something.

    | Code | Meaning | What a caller should do | |--:|---|---| | 0 | success | parse stdout | | 1 | unexpected error | report it (zone bug) | | 2 | usage error — bad flags, bad input, missing argument | fix the command; --help has the shape | | 3 | not authenticated | a human must run zone login | | 4 | missing OAuth scope | re-login that service | | 5 | Zoho rejected the request (4xx) | read the zoho body; do not retry blindly | | 6 | blocked by policy | report it; the rule that blocked is named | | 7 | retryable — network, 429, 5xx | back off and retry |

  • The last stderr line is JSON on failure when --json or --toon is set (or ZONE_JSON_ERRORS=1): {"ok":false,"error":{code,message,hint,http_status,zoho,context}}. Commander's own usage errors are included, so a missing argument parses the same way a Zoho error does:

    zone --json crm record get
    {"ok":false,"error":{"code":"BAD_INPUT","message":"missing required argument 'module'","hint":"Run \"zone --help\" or \"zone <command> --help\" for the exact arguments and flags.","http_status":null,"zoho":null,"context":null}}
  • Help is machine-readable too. zone crm record create --help --json returns the arguments (with required), options and subcommands as a JSON shape, so an agent can learn a command without parsing prose.

  • hint is the fix. Every structured error that has a known remedy names it — the missing flag, the zone ctx line to run, the zone login to redo.

  • API versions fall back on their own. Zoho serves several CRM API versions side by side and they drift: a path dropped from v9 still answers on v8, and a settings config that 500s on v9 and v8 reads in full on v7. When a call fails with a drift signature (404 INVALID_URL_PATTERN, "deprecated in this version", or a 500 INTERNAL_ERROR on a read), zone walks v9 → v8 → v7 → … → v2 until one answers, never below a row's minimum version, and prints one line naming the version that served it with the --api-version pin to make it permanent. Writes are only replayed for the 404 case (nothing ran). An explicit --api-version or ZONE_API_FALLBACK=0 switches it off; if every version fails, the error carries versions_tried and says so.

  • Throttling is handled the way Zoho documents it. CRM meters API credits over a rolling 24 hours plus a concurrency cap; the finance apps allow 100 requests a minute per organization plus a daily cap; all of it arrives as HTTP 429. zone waits out Retry-After or the rate-limit reset header (else exponential backoff) and retries up to ZONE_RETRIES times, each wait capped at ZONE_RETRY_MAX_WAIT_MS; a reset hours away, or Books' daily-limit code 45, fails fast instead. Connection failures and 5xx are retried for reads only — a write may already have been applied. Exit 7 means the limit did not clear: the error carries rate_limit.reset_at, and zone status shows the quota each service last reported.

Safety

zone is the tool an agent calls to reach live client orgs, so the safety properties a harness would normally provide have to live here — a harness granting shell(zone) has granted every write to every authenticated service and cannot express "reads only".

--dry-run works on every command. A mutating request is resolved and printed instead of sent, exit 0. Reads still run, so an agent can leave it on while building a call. zone bug honours 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
}

Policy gate. --allow / --deny (or ZONE_POLICY / ZONE_POLICY_DENY) match service:METHOD with * on either side. Deny always wins; no policy means no restriction. A blocked call exits 6 and names the rule. Classification is by what an endpoint does, not its verb: COQL and bulk read are POSTs that count as reads, and the Campaigns / Marketing Automation writes that Zoho serves over GET count as writes — so *:GET really is read-only.

ZONE_POLICY='*:GET' zone crm record create Leads --data '{"data":[{"Last_Name":"x"}]}' --json
error: Blocked by policy: crm:POST /Leads — not in the allow list.
  hint: Add "crm:POST" (or "crm:*") to the allow list to permit this.
{"ok":false,"error":{"code":"POLICY_DENIED","message":"Blocked by policy: crm:POST /Leads — not in the allow list.","hint":"Add \"crm:POST\" (or \"crm:*\") to the allow list to permit this.","http_status":null,"zoho":null,"context":null}}

Secret redaction, on by default. Fields named like credentials (access_token, client_secret, password, api_key, …) are masked on every path out — stdout, --verbose details and the machine error line alike — and the literal value of any ZONE_* secret in the environment is scrubbed from free text. zone token is exempt because emitting the token is the command; zone vault takes --reveal, refused under --json/--toon or off a TTY unless ZONE_REVEAL_UNSAFE=1.

Audit log. --audit <file> (or ZONE_AUDIT) appends one JSONL line per request — real, denied or dry-run — with the method, path, effect (read/write), status and timing. Metadata only, never a body. A write failure warns once and never fails the command.

{"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}

One seam, no bypasses. Every request — declarative rows, the zone api proxy, every stateful handler, every file upload and download — goes through src/core/apiClient.js. A test fails if any raw HTTP call in the tree sits outside that gate. The same seam refuses ./.. path segments, refuses to attach a token to a non-Zoho host, and treats an HTML page where JSON was expected as an error rather than a result.

Skills for AI tools

zone skill writes skill files where your agent already looks — no plugin, no MCP server, no config. Each per-service skill carries that service's real commands, the flags Zoho requires, where a --data body goes, base URL, context ids and quirks, generated from the installed CLI; 21 services add a hand-written guide of live-org behaviour (CRM, Books, Inventory, Desk, Projects, Mail, WorkDrive, Sheet, Writer, Meetings, Social, People, Sprints, Invoice, Billing, Analytics, Cliq, SalesIQ, Partner, Commerce, Payroll). Only a skill's one-line description is resident on each prompt; the body loads when it triggers, so an agent pays for the service it is using rather than for all 64.

zone skill --ide claude             # all skills into .claude/skills/  (add --global for every project)
zone skill crm --ide cursor         # one service as .cursor/rules/zoho-crm.mdc
zone skill deluge --ide codex       # a marked section in AGENTS.md — never overwrites your own text
zone skill --stdout                 # print instead of writing (pipe into any agent config)

| Agent / IDE | --ide | Project file | --global file | |---|---|---|---| | Claude Code | claude | .claude/skills/<skill>/SKILL.md | ~/.claude/skills/… | | Antigravity / Gemini Agent | antigravity | .agents/skills/<skill>/SKILL.md | ~/.agents/skills/… | | Cursor | cursor | .cursor/rules/<skill>.mdc | — (paste into Settings › Rules) | | Windsurf / Cascade | windsurf | .windsurfrules | ~/.codeium/windsurf/memories/global_rules.md | | GitHub Copilot | copilot | .github/copilot-instructions.md | — (per repository) | | Cline / Roo Code | cline | .clinerules | ~/Documents/Cline/Rules/zoho-zone.md | | Gemini CLI | gemini | GEMINI.md | ~/.gemini/GEMINI.md | | Codex / any AGENTS.md tool | codex | AGENTS.md | ~/.codex/AGENTS.md | | Anything else | markdown | ZOHO_ZONE_AI_CONTEXT.md | ~/ZOHO_ZONE_AI_CONTEXT.md |

Per-skill targets (Claude, Antigravity, Cursor) get one file per topic: the router, the Deluge language guide with its full reference, one per service, the delivery workflow, accounting safety, and the CRM widget subtypes. Shared-file targets (AGENTS.md, GEMINI.md, .clinerules, .windsurfrules, Copilot) have no trigger mechanism, so there zone skill adds the router and Deluge as marked sections and a service is added when you name it (zone skill crm --ide codex). Sections are rewritten in place between their own begin/end markers; text you wrote is never touched, and a per-skill file you wrote yourself is refused without --force. Re-run zone skill after upgrading zone.

For agents without file-based rules, zone llm prints the same guide to stdout (zone llm crm for one service, zone llm core for the router only).

Finding a command

You never have to leave the terminal, and you do not need an inventory:

zone services                      # all 64 services, auth state, doc links
zone crm --help                    # a service's command groups
zone crm blueprint --help          # a group's commands
zone crm blueprint create --help   # arguments, flags and notes for one command (add --json for a machine shape)
zone help books                    # service card: scopes, base URL, context, every group and leaf, quirks
zone llm crm                       # the whole typed inventory for one service, agent-readable

The full list of all 9,909 commands is generated into docs/COMMANDS.md and, with method, path and scope per command plus live search, into docs/zone-commands.html (npm run gen:docs).

Services

64 services. Extended ones carry newer, larger scope sets and are excluded from zone login --all — name them explicitly (zone login desk analytics). The last column lists the first command groups; zone help <key> shows them all.

| Service | Key | Commands | Groups | |---|---|--:|---| | Zoho CRM | crm | 982 | record, coql, whoami, module, field, layout, … (109 groups) | | Zoho Mail | mail | 229 | account, folder, label, mail, attach, thread, … (13 groups) | | Zoho Meeting | meetings | 41 | org, meeting, webinar, recording, poll, report, … (9 groups) | | Zoho Books | books | 945 | org, contact, contactperson, estimate, salesorder, invoice, … (59 groups) | | Zoho Inventory | inventory | 598 | orgs, contact, contactperson, item, group, composite, … (51 groups) | | Zoho Creator | creator | 29 | meta, record, bulk, fn, pull, publish | | Zoho Partner Store | partner | 15 | leads, subscriptions, transactions, commissions, pull | | Zoho Social | social | 36 | post, portal, brand, channel, posts, media, … (13 groups) | | Zoho Projects | projects | 513 | portal, project, tasklist, task, timelog, event, … (52 groups) | | Zoho Desk | desk | 969 | ticket, thread, ticket-comment, ticket-attach, ticket-time, ticket-timer, … (111 groups) | | Zoho Sign | sign | 36 | request, template, folder, fieldtype, doctype, signgroup | | Zoho Writer | writer | 47 | document, template, merge, bulk, combine, sign, … (8 groups) | | Zoho Sheet | sheet | 130 | workbook, worksheet, records, table, chart, pivot, … (17 groups) | | Zoho Learn | learn | 63 | course, lesson, hub, space, manual, article, … (10 groups) | | TrainerCentral | training | 24 | course, chapter, lesson, material, assignment, learner, … (8 groups) | | Zoho People | people | 447 | record, form, employee, leave, attendance, timetracker, … (52 groups) | | Zoho Campaigns | campaigns | 91 | list, topic, campaign, coupon, contact, segment, … (18 groups) | | Zoho Marketing Automation | marketing | 42 | list, campaign, coupon, lead, segment, tag, … (9 groups) | | Zoho WorkDrive | workdrive | 165 | file, folder, workspace, team, user, share, … (32 groups) | | Zoho Cliq | cliq | 159 | channel, chat, message, user, bot, buddy, … (25 groups) | | Zoho Survey | survey | 10 | user, portal, survey, collector, distribution, webhook | | Zoho Analytics (extended) | analytics | 182 | org, workspace, view, data, row, table, … (28 groups) | | Zoho Bigin (extended) | bigin | 76 | record, note, user, org, meta, pipeline, … (16 groups) | | Zoho Recruit (extended) | recruit | 78 | record, candidate, attachment, meta, user, interview, … (18 groups) | | Zoho Billing (extended) | billing | 277 | org, customer, subscription, plan, product, addon, … (28 groups) | | Zoho Invoice (extended) | invoice | 268 | org, contact, invoice, estimate, payment, creditnote, … (21 groups) | | Zoho Expense (extended) | expense | 146 | expense, report, trip, category, user, setting, … (11 groups) | | Zoho Sprints (extended) | sprints | 214 | team, project, sprint, item, epic, release, … (36 groups) | | Zoho Bookings (extended) | bookings | 29 | workspace, service, staff, resource, availability, appointment, … (8 groups) | | Zoho FSM (extended) | fsm | 155 | work-order, appointment, request, estimate, contact, work-type, … (30 groups) | | Zoho SalesIQ (extended) | salesiq | 186 | portal, operator, department, brand, conversation, call, … (30 groups) | | Zoho Vault (extended) | vault | 35 | secret, share, chamber, user, usergroup, audit, … (7 groups) | | Zoho Calendar (extended) | calendar | 61 | calendar, event, settings, group, notification, activity, … (13 groups) | | Zoho Contacts (extended) | contacts | 19 | contact, category | | Zoho Tables (extended) | tables | 40 | portal, workspace, base, table, view, field, … (12 groups) | | Zoho Commerce (extended) | commerce | 178 | store, product, order, webhook, page, import, … (35 groups) | | Zoho Payroll (extended) | payroll | 133 | org, employee, salary, statutory, tax, payrun, … (19 groups) | | Zoho Catalyst (extended) | catalyst | 104 | project, zcql, table, row, bulk, fn, … (22 groups) | | Zoho Assist (extended) | assist | 18 | user, session, unattended, report | | Zoho Lens (extended) | lens | 27 | user, session, report, schedule, org, department, … (9 groups) | | Qntrl (extended) | qntrl | 233 | user, org, card, workspace, circuit, function, … (36 groups) | | Zoho Voice (extended) | voice | 53 | user, log, agent, queue, powerdialer, number, … (14 groups) | | ZeptoMail (extended) | zeptomail | 35 | domain, agent, template, suppression, email, file, … (10 groups) | | Zoho Backstage (extended) | backstage | 80 | event, attendee, member, sponsor, portal, event-clone, … (22 groups) | | Zoho One (extended) | one | 31 | org, field, location, designation, user, group, … (8 groups) | | Zoho Directory (extended) | directory | 30 | geo, org, field, location, designation, user, … (8 groups) | | Zoho Payments (extended) | payments | 55 | customer, payment-method-session, payment-method, payment-session, terminal-session, mandate, … (16 groups) | | Zoho Webinar (extended) | webinar | 32 | org, webinar, recording, poll, report, user, … (9 groups) | | Zoho Connect (extended) | connect | 279 | network, profile, user-follow, favourite, block, activity, … (43 groups) | | Zoho Contracts (extended) | contracts | 86 | org, user, department, counterparty-type, counterparty, counterparty-contact, … (15 groups) | | Zoho Shifts (extended) | shifts | 45 | org, employee, access-level, skill, shift, timesheet, … (12 groups) | | Zoho Workerly (extended) | workerly | 18 | meta, record, timelog | | Zoho Thrive (extended) | thrive | 2 | purchase, activity | | Zoho POS (extended) | pos | 210 | org, contact, contact-person, item-group, item, composite-item, … (22 groups) | | Zoho PageSense (extended) | pagesense | 20 | experiment, goal, audience, report, projectgoal, customevent | | Zoho BugTracker (extended) | bugtracker | 86 | portal, project, activity, status, milestone, timelog, … (17 groups) | | Zoho DataPrep (extended) | dataprep | 43 | org, workspace, pipeline, connection, datasource, stage, … (12 groups) | | Zoho Apptics (extended) | apptics | 16 | project, crash, event, screen, device | | Zoho IoT (extended) | iot | 78 | product, product-gallery, device, asset, location, record, … (12 groups) | | Zoho Office Integrator (extended) | officeintegrator | 49 | document, template, fillable, pdf, spreadsheet, presentation, … (7 groups) | | Zoho PDF Editor (extended) | pdfeditor | 52 | document, image, page, pagenumber, watermark, link, … (12 groups) | | Zoho Show (extended) | show | 65 | presentation, member, publish, workspace, theme, slide, … (15 groups) | | Zoho Vani (extended) | vani | 171 | edition, subscription, template, team, team-member, team-request, … (33 groups) | | Zoho Vertical Studio (extended) | vertical | 343 | org, user, record, subform, lead, inventory, … (59 groups) |

Not addable, because Zoho publishes no API for them: Forms, Sites, Flow (no management API), Notebook, TeamInbox, RouteIQ, CommandCenter, LandingPage, CommunitySpaces. Reach their data through the products that do have one (Creator, Analytics, CRM).

A few services sit on hosts outside *.zoho.<dc>: POS is the former Zakya (api.zakya.com|in), Vani is api.app.vanihq.<dc>, Office Integrator is api.office-integrator.<dc>. All are on zone's host allow-list, so a token or key is never sent anywhere else. Office Integrator has no OAuth at all — it authenticates with an API key you store once: zone ctx officeintegrator apikey=<key> (and dc=eu if your account is not on .com); zone login officeintegrator tells you the same.

Beyond REST rows, a few commands carry real logic: zone crm pull snapshots an org's metadata (modules, fields, picklists, layouts, Deluge functions) to disk; zone books pull and zone inventory pull walk every organization's settings into a folder each; zone crm fn push/pull/test/invoke and zone crm fmt form a Deluge toolchain; zone transcribe runs Whisper locally on meeting recordings; zone zet wraps Zoho's Marketplace widget toolkit; zone bug files a bug report without a GitHub account. Each has --help with examples.

Authentication

  • zone login [services...] — one browser consent for the named services; --all for every core service; --dc eu (or in, com.au, jp, uk, ca, sa, ae, sg, cn) for another datacenter; --no-browser prints the consent URL for headless machines. Omit --dc in a terminal to be prompted.
  • Scopes are minimized before the consent URL is built (a broader scope in the same list implies the narrower ones), and a request too long for one URL is split into consent rounds. --raw-scopes and ZONE_CONSENT_BUDGET adjust that.
  • Zoho keeps 20 refresh tokens per client per user and silently invalidates the rest, so grants no service points at are revoked after each login; zone grants lists them, zone grants --prune cleans up by hand, --no-prune opts out.
  • zone status [--live] shows auth state per service; --live probes a real read-only endpoint each. zone token <service> prints a valid access token for scripts. zone logout [services...] removes sessions.
  • The default OAuth client is shared. Bring your own with --client-id / --client-secret or ZONE_CLIENT_ID / ZONE_CLIENT_SECRET (redirect URI http://localhost:14893/zoho/callback, or your own port with --port).
  • Session files are mode 0600, one per service, under the store zone status names.
  • API-key products (Office Integrator) have no session: zone status reports them as ok (api key) once zone ctx <service> apikey=<key> is stored, and the key rides on every request from context.

Environment variables

| Variable | Purpose | |---|---| | ZONE_HOME | Session directory; overrides both the project-local ./.zone and ~/.zone | | ZONE_CLIENT_ID / ZONE_CLIENT_SECRET | Custom OAuth client | | ZONE_PORT | OAuth callback port (default 14893) | | ZONE_TIMEOUT | Per-request timeout in ms (default 60000; 300000 for uploads and downloads) | | ZONE_RETRIES | How many times a throttled (429) or transient call is retried before exit 7 (default 3; 0 disables) | | ZONE_RETRY_MAX_WAIT_MS | Longest single wait zone will sit out for a retry (default 30000); a reset further away fails fast with the reset time | | ZONE_JSON_ERRORS | 1 → the JSON error envelope on stderr's last line, without --json | | ZONE_POLICY / ZONE_POLICY_DENY | Allow / deny rules, e.g. *:GET — same grammar as --allow / --deny | | ZONE_AUDIT | Audit log path — same as --audit | | ZONE_API_VERSION | Pin the Zoho API version (e.g. v8) — same as --api-version | | ZONE_API_FALLBACK | 0 disables the automatic CRM API-version fallback (v9 → v8 → … → v2 when the default version fails with a version-drift signature) | | ZONE_CONSENT_BUDGET | Max consent URL length before a login is split into rounds (default 7500) | | ZONE_BUG_ENDPOINT | Bug relay for zone bug; unset means nothing is ever sent | | ZONE_NO_UPDATE_CHECK | 1 → no "newer version" notice (NO_UPDATE_NOTIFIER and CI=true also) | | NO_COLOR / DEBUG | Disable colours / true prints error details |

Troubleshooting

  • zone status --live is the fastest diagnosis: per service, does the stored grant work right now?
  • Exit 3 — not signed in for that service: zone login <service>. Exit 4 — the grant lacks a scope: zone login <service> again picks up the current scope set.
  • Exit 5 — Zoho rejected the call. The zoho field carries Zoho's own body; --verbose prints full details (redacted). CRM names the offending field in details.param_name, and the hint translates the common ones.
  • "belongs to multiple organizations" — set the org once: zone ctx <service> organization_id=<id> (discover with zone api <service> GET /organizations).
  • Git Bash rewrites /Leads into a Windows path. zone detects and undoes it; if you still see a filesystem path in an error, prefix the command with MSYS_NO_PATHCONV=1.
  • Something looks wrong? zone bug "<title>" -m "<what happened>" collects versions, platform, the command shape and the structured error, shows you the exact payload and asks before sending anything. It never includes tokens, .zone contents or request/response bodies, and --dry-run, --print and --out let you see or save the report without transmitting it.

Development

zone is a thin CLI over four packages, each published on its own and developed in sibling repos:

| Package | Owns | |---|---| | @wanasapps/deluge-core | Deluge formatter, signature parser, grammar, snippets — no I/O | | @wanasapps/zoho-auth | OAuth, datacenters, the session store | | @wanasapps/zoho-api | Service registry and the REST client, including the Zoho host allow-list | | @wanasapps/zcrm-core | CRM services and the metadata extractor behind zone crm pull |

npm install && npm test          # offline suite, no sessions needed
npm run relink                   # re-point @wanasapps deps at sibling working copies (any npm install replaces the links)
npm run gen:commands             # regenerate docs/COMMANDS.md from the specs
npm run gen:docs                 # regenerate docs/zone-commands.html
npm run publish:all -- --dry-run # plan a bottom-up publish of every package that is ahead of npm

Where commands come from. Each service's commands are declarative rows (method, path, args, flags, notes) that src/core/commandSpec.js turns into zone <service> <group> <name>:

| Location | Holds | |---|---| | src/specs/<service>.js (or src/specs/crm/, src/specs/desk/) | hand-written rows, checked against live orgs | | src/specs/oas-extras/<service>.js | rows generated from Zoho's own OpenAPI specs for operations the hand-written file lacks — merged automatically by the loader; every row's notes name its source file and operationId, and say whether a live call has confirmed it | | src/specs/finance-shared/ | resources Books and Inventory serve identically (purchase returns, item masters and variants, categories), loaded by both | | src/core/guides/<service>.md | the hand-written part of each service's skill: payload shapes and traps |

Coverage is audited against Zoho's published definitions where they exist — openapi-all.zip bundles on zoho.com, the zoho/*-oas repos on GitHub, and CRM's runtime GET /crm/<v>/__apis registry (scripts/discover-crm-apis.js). src/core/specValidate.js rejects a row whose path placeholder is neither a declared arg nor a known context key.

prepublishOnly runs scripts/check-publish.js (shebang line endings, shipped files, lockfile versions inside their ranges, every @wanasapps range resolving on npm) and then the suite. The history of what changed in each release is in CHANGELOG.md.

Library use is possible but secondary:

const zone = require('wanas-zone-cli');
const org = await zone.api.request('crm', 'GET', '/org');

Support

Wanas Apps is a Zoho Premium Partner and technical consulting firm in Ras al-Khaimah and Cairo, building Zoho implementations, Catalyst applications and integrations for the MENA region. zone is the tool we use to do that work.