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-zcrm-extractor

v2.6.0

Published

Local Zoho CRM V8/V9 Metadata Extractor & 100% REST API Execution CLI Utility

Readme

🛡️ Read-only extraction & Opt-in V8 API Execution / Customizations

By default, zcrm pull is strictly read-only: it never creates, updates, or deletes anything in Zoho CRM. It pulls schema / metadata only — module and field definitions, layouts, picklists, related lists, tags, profiles, roles, webhooks, org-wide settings, and custom function source code — with no access to your CRM records.

Explicit V8 API capabilities (zcrm api, zcrm record, zcrm coql, zcrm composite, zcrm var, zcrm tag, zcrm note, zcrm attachment, zcrm bulk, zcrm notify, zcrm recycle, zcrm mail, zcrm blueprint, zcrm workflow), module/field/layout management (zcrm module, zcrm field, zcrm layout), and function lifecycle/testing (zcrm fn create/push/test) are confirm-gated, opt-in operations that execute REST payloads or Deluge scripts in your live org when explicitly invoked (skip in CI via --force).


🚀 Quick Start

# 1. Install globally
npm install -g wanas-zcrm-extractor

# 2. Authenticate (opens your browser for Zoho OAuth)
zcrm login

# 3. Pull all metadata into ./metadata
zcrm pull

# 4. Call ANY Zoho CRM V8 API endpoint directly (100% surface coverage)
zcrm api GET /settings/variables

# 5. (Optional) Generate an AI-assistant context file for your IDE
zcrm skill

💡 Prefer not to install globally? Use npx wanas-zcrm-extractor <command> instead.


🌟 Key Features


⚙️ Installation

npm install -g wanas-zcrm-extractor

zcrm login
zcrm pull
npm install wanas-zcrm-extractor

npx zcrm login
npx zcrm pull

On Windows you may need an Administrator terminal; on macOS/Linux you may need sudo for a global install.

The same release is also published to GitHub Packages as the scoped package @wanas-apps/wanas-zcrm-extractor. GitHub Packages requires authentication even for public packages, so point the @wanas-apps scope at GitHub and authenticate with a GitHub token that has the read:packages scope:

# ~/.npmrc  (or a project-local .npmrc)
@wanas-apps:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=YOUR_GITHUB_TOKEN
npm install -g @wanas-apps/wanas-zcrm-extractor

Most users should prefer the public npmjs package above — it needs no token. GitHub Packages is provided for org-internal/CI consumers.


🔑 Setup & Registration

To authenticate, register a Zoho API client in the Zoho Developer Console:

  1. Visit the Zoho Developer Console.
  2. Click Add Client → select Server-based Applications.
  3. Configure your application:
    • Client Name: Zoho CRM Metadata Extractor
    • Homepage URL: http://localhost:14890
    • Authorized Redirect URI: http://localhost:14890/zoho/callback (or your preferred local port)
  4. Click Create to receive your Client ID and Client Secret.

🚀 CLI Commands Reference

| Command | Purpose | | :--- | :--- | | zcrm login | Authenticate the CLI with Zoho OAuth2. | | zcrm pull | Extract & sync all CRM metadata into a local folder. | | zcrm skill | Generate an AI-assistant context file for your IDE. | | zcrm audit | Export the CRM audit log (async job). | | zcrm fn create · push | Create a function / push local code to live CRM (writes). | | zcrm fn test · pull | Execute any Deluge function live (all categories) · fetch function .ds. | | zcrm module create · update | Create custom modules (display_field text/autonumber) or update properties (writes). | | zcrm field create · update · delete | Create, update properties, or delete custom fields (writes). | | zcrm layout update · activate · deactivate · delete | Update sections/fields, activate, deactivate, or delete layouts (writes). | | zcrm dashboard | Launch the local web explorer dashboard. | | zcrm whoami · zcrm llm · zcrm logout | Session info · AI guide · Sign out. |

Authenticates the CLI to access your Zoho CRM account.

zcrm login [options]

Options

| Option | Description | | :--- | :--- | | --client-id <id> | Zoho OAuth Client ID. | | --client-secret <secret> | Zoho OAuth Client Secret. | | --dc <dc> | Data Center: com, eu, in, jp, com.au, com.cn. | | --redirect-uri <uri> | Zoho OAuth Redirect URI. | | --refresh-token <token> | Headless auth (bypasses the browser flow). |

# Interactive (prompts for missing details)
zcrm login

# Express login with explicit credentials
zcrm login --client-id 1000.x --client-secret x --dc com --redirect-uri http://localhost:14890/zoho/callback

# Headless login (CI/CD or servers)
zcrm login --client-id 1000.x --client-secret x --dc com --refresh-token 1000.x

Crawls all Zoho CRM endpoints (read-only) and syncs metadata + Deluge scripts into your local folder.

zcrm pull [options]

Options

| Option | Description | | :--- | :--- | | -o, --output <dir> | Destination folder (default: auto-detected project root, else ./metadata). | | -c, --concurrency <n> | Max simultaneous Zoho API calls, 125 (default 5). | | --with-counts | Also fetch each module's record count — reads record data and costs ~50 API credits/module, so it is off by default. |

Unified project root (shared with the VS Code extension): when -o is not passed, the CLI walks up from the current directory looking for an existing extraction root — a folder containing zcrm-project.json, a .zcrm/.store/, or the extension's .zoho-crm-ide.json pointer. If found, the pull refreshes that tree instead of creating a second ./metadata folder, so the CLI and the Zoho CRM IDE extension always share one metadata tree. An explicit -o always wins. The same detection applies to status -d, audit -o, fn pull/create/test -o, and skill -m.

Every pull also:

  • 📋 Generates a README.md in the output folder describing the snapshot — org, counts, a per-module table, and the directory layout — rebuilt from the real data each run.
  • 📝 Writes a debug log to <output>/.zcrm/.logs/ZCRM-CLI-<date>.log (includes the quiet "skipped" entries that aren't printed to the console).
  • 🔒 Holds a cross-process sync lock (.zcrm/.store/.sync-in-progress) for the duration of the run, so a CLI pull and a VS Code extension pull into the same folder can't corrupt each other. A second pull started while one is running aborts with a clear message; a lock left by a crashed run is reclaimed automatically after 10 minutes.

Requests run in parallel under a global cap that respects Zoho's per-org concurrency limit: 5 (Free) · 10 (Standard/Starter) · 15 (Professional) · 20 (Enterprise/Zoho One) · 25 (Ultimate/CRM Plus). The default 5 is safe for every edition; raise it on higher tiers for faster pulls:

zcrm pull -o ./metadata --concurrency 15

If the limit is hit (HTTP 429), the client backs off exponentially and retries — a pull never fails just because it was briefly throttled.

A pull is a one-way sync from Zoho into your folder:

  • Existing files are overwritten in place.
  • Files that no longer exist on Zoho are removed locally — but only within scopes whose authoritative fetch succeeded this run.
  • If a fetch fails, the previous local data for that scope is kept — a partial or interrupted pull never wipes your data.

Launches the premium local web dashboard to explore the pulled metadata in a browser.

zcrm dashboard [options]      # -p, --port <port>  (default 14890)

Open http://localhost:14890 to view live extraction logs, browse modules, inspect fields & picklists, search APIs, and download .zip archives.

Displays the authenticated user (name, email, role, profile), organization details, Org ID, and configured Data Center.

zcrm whoami

Displays the active Zoho CRM OAuth access token, token type (Bearer), API domain, expiry timestamp, remaining seconds/minutes, and authorization header. Auto-refreshes if expired.

# Pretty output with token status & expiry details
zcrm token

# Raw access token string only (ideal for curl, scripts & AI tool chaining)
zcrm token --raw
# or short flag
zcrm token -r

# JSON output with expiry metadata
zcrm token --json

# Force immediate refresh from Zoho OAuth accounts server
zcrm token --force-refresh

Prints the AI/LLM system reference guide — how an AI assistant should ingest the extracted schema to generate valid Zoho Deluge scripts and REST payloads.

zcrm llm

Generates an AI-assistant skill / rules file for your IDE, derived from the zcrm llm guide, so your assistant writes valid Deluge using exact API names.

zcrm skill [options]

Options

| Option | Description | | :--- | :--- | | --ide <ide> | Target tool (skips the prompt): antigravity, claude, cursor, windsurf, copilot, cline, gemini, codex, markdown. | | -d, --dir <dir> | Project directory to write into (default: current). | | -m, --metadata-dir <dir> | Path to your extracted metadata (default ./metadata). | | -f, --force | Overwrite an existing dedicated skill file without prompting. |

| Tool | Generated file | | :--- | :--- | | Google Antigravity | .agents/skills/zoho-crm-deluge/SKILL.md | | Claude Code | .claude/skills/zoho-crm-deluge/SKILL.md | | Cursor | .cursor/rules/zoho-crm-deluge.mdc | | Windsurf | .windsurf/rules/zoho-crm-deluge.md | | GitHub Copilot | .github/copilot-instructions.md | | Cline / Roo Code | .clinerules/zoho-crm-deluge.md | | Gemini CLI | GEMINI.md | | Codex / generic | AGENTS.md | | Plain Markdown | ZOHO_CRM_AI_CONTEXT.md |

zcrm skill                                   # interactive menu
zcrm skill --ide antigravity --metadata-dir ./crm-meta

Triggers an asynchronous export of the Zoho CRM audit log, polls until it completes (with a bounded timeout), and downloads the resulting CSV/ZIP into the result folder's CRM root — metadata/crm/audit_logs/ by default (override with -o, --output). A subsequent zcrm pull never deletes this folder.

zcrm audit                      # last 3 years by default → ./metadata/crm/audit_logs/
zcrm audit --filter input.json  # custom export criteria
zcrm audit -o ./my-export       # save into ./my-export/crm/audit_logs/

Requires the audit-log OAuth scopesZohoCRM.settings.audit_logs.CREATE and ZohoCRM.settings.audit_logs.READ (both in the default scopes). If you authenticated before they were added you'll see 401 invalid oauth scope — just re-authenticate: zcrm logout then zcrm login. (If the download step later reports a file-scope error, add ZohoFiles.files.READ to ZOHO_SCOPES and log in again.)

Clears stored credentials, OAuth tokens, and the active session.

zcrm logout

Work with one Deluge function at a time — the full loop: create a Standalone function, push code edits, pull the latest, and test-run it.

⚠️ fn create, fn push, and fn test write to / execute on your live Zoho CRM org and are outside the read-only guarantee. Each is confirm-gated (use --force to skip in CI). fn pull is read-only.

Creates a new Standalone function on CRM and writes its .ds into your metadata tree. With --from, it also pushes that file's code; without it, you get an empty stub to edit and fn push later.

Names are lowercased. Zoho lowercases generated function code signatures, so zcrm normalizes api_names to lowercase end-to-end (My_Fnmy_fn, file standalone.my_fn.ds) to keep the function, its code, and the filename consistent. Lookups (push/test/pull) are case-insensitive.

zcrm fn create My_Fn                                   # empty stub + local .ds
zcrm fn create My_Fn --from ./My_Fn.ds                 # create + push code in one step
zcrm fn create My_Fn --return-type string              # stub with a chosen return type

| Option | Description | | :--- | :--- | | --from <file.ds> | Seed the function with code from a local .ds (its signature name must match <apiName>). | | --return-type <t> | Return type for an empty stub (default void; ignored with --from). | | -o, --output <dir> | Metadata root for the written .ds (default ./metadata). | | --force | Skip the write-confirmation prompt. |

Reads a local .ds, resolves the function from its signature, and uploads the code to the matching existing function. Create it first with fn create if it doesn't exist yet.

zcrm fn push ./metadata/crm/functions/standalone/standalone.My_Fn.ds

Unlike every other command, fn test executes Deluge in your live Zoho CRM org (the function editor's "test" action). It can create/update/delete records, send mail/SMS, and call external APIs — exactly what the script does. It is therefore an explicit, opt-in command, gated behind a confirmation prompt (use --force to skip it in CI).

<function> is either a local .ds file (runs your local edits) or the api_name of a Standalone function (fetches & runs the saved code). Only Standalone functions can be tested.

# Test local edits to a function before saving them in CRM:
zcrm fn test ./metadata/crm/functions/standalone/standalone.My_Fn.ds

# Run a live function with arguments:
zcrm fn test My_Fn --args '{"Data":"hello"}'

# No prompt + raw JSON (automation):
zcrm fn test My_Fn --force --json

| Option | Description | | :--- | :--- | | --args <json> | Inline JSON argument map, e.g. '{"Data":"hi"}'. | | --args-file <path> | JSON file containing the argument map. | | -o, --output <dir> | Where to save the result artifact — <dir>/crm/function_tests/ (default ./metadata). | | --json | Print Zoho's raw JSON response to stdout. | | --force | Skip the execution warning + confirmation prompt (CI/automation). |

It prints the return value, info logs, every network/integration call (with its HTTP status), and execution metrics, and saves the full response to <output>/crm/function_tests/<api_name>-<timestamp>.json. The exit code is non-zero if the run failed.

Fetches a single function's Deluge code into <output>/crm/functions/<namespace>/<namespace>.<api_name>.ds — the same path zcrm pull uses — without running a full pull. Strictly read-only; never deletes anything.

zcrm fn pull My_Fn
zcrm fn pull My_Fn -o ./metadata

Typical loop: zcrm fn create My_Fn → edit the .dszcrm fn push <file>zcrm fn test My_Fn. Only Standalone functions are supported (the namespace these endpoints resolve).

Call ANY of Zoho CRM's 405 V8 API operations directly using raw HTTP methods and endpoints.

zcrm api <method> <endpoint> [options]

Examples:

# Get org variables
zcrm api GET /settings/variables

# Execute COQL query
zcrm api POST /coql --body '{"select_query":"select Last_Name, Email from Contacts limit 5"}'

# Delete a tag by ID
zcrm api DELETE /settings/tags/410543000001234005

# Save response to a file
zcrm api GET /Leads --params '{"per_page":10}' --out ./leads.json

First-class CLI interface to list, get, list/get converted leads, reverse lookup originating leads by Contact/Account/Deal ID, inspect record timelines, create, update, delete, search, upsert, and count records across any standard or custom CRM module.

# List active leads
zcrm record list Leads --per-page 20

# Get a record by ID (supports converted leads with --converted true)
zcrm record get Leads 410543000001234001 --converted true

# Work with converted leads & reverse lookup by Contact, Account, or Deal ID
zcrm record converted Leads                           # List converted leads
zcrm record converted Leads 410543000001234001         # Fetch single converted lead by Lead ID
zcrm record converted Contacts 410543000005555001      # Lookup originating lead by Contact ID
zcrm record converted Accounts 410543000006666001      # Lookup originating lead by Account ID
zcrm record converted Deals 410543000007777001         # Lookup originating lead by Deal ID
zcrm record converted --contact 410543000005555001     # Flag syntax for Contact lookup
zcrm record converted --account 410543000006666001     # Flag syntax for Account lookup
zcrm record converted --deal 410543000007777001        # Flag syntax for Deal lookup

# Get record audit & activity timeline
zcrm record timeline Leads 410543000001234001          # Complete audit & activity timeline
zcrm record timeline Leads 410543000001234001 --include-inner-details audit_log --per-page 50

# Search, create, update, delete, upsert & count
zcrm record search Leads --criteria "(Last_Name:equals:Smith)"
zcrm record create Leads --body '{"data":[{"Last_Name":"Smith","Company":"Acme"}]}'
zcrm record update Leads --id 410543000001234001 --body '{"data":[{"Company":"Acme Corp"}]}'
zcrm record delete Leads 410543000001234001 --force
zcrm record count Leads

Run CRM Object Query Language (COQL) queries directly from your terminal.

zcrm coql "select Last_Name, Email, Phone from Contacts where Created_Time >= '2026-01-01T00:00:00+00:00' limit 20"

List, retrieve, set (create/update), and delete org-wide variables and variable groups.

zcrm var list
zcrm var get 410543000000123005
zcrm var set Target_Quarter_Goal "500000" --group 410543000000123001 --type integer
zcrm var delete 410543000000123005 --force
zcrm var groups

Manage module tags, assign/remove tags to/from records, and delete tags.

zcrm tag list --module Leads
zcrm tag create "VIP Client" --module Leads --color "#FF0000"
zcrm tag add Leads 410543000001234001 --tags "VIP Client,Follow Up"
zcrm tag remove Leads 410543000001234001 --tags "Follow Up"
zcrm tag delete 410543000000999001 --force

List notes, view single notes, create notes attached to CRM records, and delete notes.

zcrm note list --per-page 10
zcrm note get 410543000000888001
zcrm note create --body '{"data":[{"Note_Title":"Call Summary","Note_Content":"Client agreed to proposal","Parent_Id":"410543000001234001","se_module":"Leads"}]}'
zcrm note delete 410543000000888001 --force

Inspect active, inactive, or admin users and single user profiles.

zcrm user list --type ActiveUsers
zcrm user get 410543000000002011

Initiate and monitor high-volume asynchronous bulk export and import operations.

zcrm bulk read Leads --body '{"query":{"module":{"api_name":"Leads"}}}'
zcrm bulk status read 410543000007770001

List and manage live data-change notification webhooks (watch subscriptions).

zcrm notify list
zcrm notify create --body '{"watch":[{"channel_id":"1001","events":["Leads.create","Leads.edit"],"notify_url":"https://example.com/webhook"}]}'
zcrm notify delete --force

List deleted items in the CRM recycle bin, restore records, or permanently empty the recycle bin.

zcrm recycle list
zcrm recycle count
zcrm recycle restore 410543000001234001
zcrm recycle empty --force

Sends a real email from a record via the Zoho CRM Send Mail API — works on Leads, Contacts, Accounts, Deals, Sales/Purchase Orders, Invoices, Quotes, Cases, Vendors, and Custom modules. Confirm-gated (--force to skip). The email is logged on the record's Emails related list in CRM.

zcrm mail send Leads 410543000001234001 --to [email protected] --subject "Intro" --content "<p>Hello!</p>"
zcrm mail send Contacts 410543000001234001 --to [email protected],[email protected] --cc [email protected] --subject "Update" --content @body.html
zcrm mail send Accounts 410543000001234001 --body @mail.json --force

Options

| Option | Description | | :--- | :--- | | --to <emails> | Comma-separated recipient email(s) — required unless --body. | | --cc / --bcc <emails> | Comma-separated CC / BCC email(s). | | --from <email> | Sender — must be an allowed CRM from-address (defaults to the logged-in user). | | --subject <text> | Email subject. | | --content <text\|@file> | Body — HTML by default; @body.html loads from a file. | | --text | Send as plain text (mail_format: text). | | --org-email | Send via the organization email address. | | --body <json\|@file> | Full raw Send Mail payload (overrides the options above). | | --json / --force | Raw response output / skip confirmation. |

Scope note: requires ZohoCRM.send_mail.all.CREATE. It is included in the default login scopes as of this version — if you logged in with an older version, re-authorize once: zcrm logout && zcrm login.

Read a record's current Blueprint state and available next transitions, execute a transition (confirm-gated write), and inspect the org's Blueprint definitions.

zcrm blueprint get Deals 410543000001234001                # current state + next transition IDs (read-only)
zcrm blueprint update Deals 410543000001234001 --transition 410543000000287001 --data '{"Stage":"Qualification"}'
zcrm blueprint config                                      # org Blueprint process configurations (read-only)
zcrm blueprint transitions 410543000000287001,410543000000287002   # transition definitions by ID (read-only)

blueprint update options

| Option | Description | | :--- | :--- | | --transition <id> | Transition ID to execute (find it via zcrm blueprint get). | | --data <json\|@file> | Field values the transition requires. | | --body <json\|@file> | Full raw {"blueprint":[…]} payload (overrides the options above). | | --force | Skip confirmation. |

Scope note (documented): record get/update use ZohoCRM.modules.ALL; config uses ZohoCRM.settings.blueprint.READ; transitions uses ZohoCRM.settings.transitions.readall already covered by the default login scopes (ZohoCRM.modules.ALL + ZohoCRM.settings.ALL), so no re-authorization is needed for Blueprints.


📂 Generated Directory Structure

metadata/
├── README.md                   # 📋 auto-generated snapshot summary (org, counts, modules)
├── .zcrm/                      # Internal ZCRM CLI stores
│   ├── .logs/                  # 📝 per-pull debug log (ZCRM-CLI-<date>.log)
│   ├── .org/org.json           # Organization metadata
│   └── .store/                 # Consolidated indexes
│       ├── index.json          # Master index of extracted modules
│       ├── field_map.json      # { Module: { Field: data_type } } lookup
│       ├── complete_metadata.json  # Unified database of all endpoints
│       ├── webhooks.json       # Webhooks metadata
│       └── functions.json      # Functions catalog
│
├── crm/                        # Standard Zoho CRM metadata layout
│   ├── meta/
│   │   ├── modules/<Module_API_Name>/
│   │   │   ├── <Module>.modules-meta.json
│   │   │   ├── summary.json            # counts, required/picklist/lookup/subform fields
│   │   │   ├── fields/                 # <Field>.fields-meta.json
│   │   │   ├── layouts/                # + map_dependencies/
│   │   │   ├── custom_views/
│   │   │   ├── custom_links/           # module links/buttons
│   │   │   ├── related_lists/
│   │   │   ├── tags/
│   │   │   ├── record_locking_configurations/
│   │   │   └── workflow_configurations/
│   │   ├── profiles/                   # permission profiles
│   │   ├── roles/                      # role hierarchy
│   │   ├── email_templates/<Module>/   # .meta.json + .html (body)
│   │   ├── inventory_templates/<Module>/  # .meta.json + .html (body)
│   │   ├── workflow_rules/<Trigger_Module>/<Rule>.json
│   │   └── ...                         # variables, wizards, global picklists, data sharing, territories
│   └── functions/              # custom Deluge scripts (.ds), by namespace
│
├── zcrm-project.json           # ZCRM project config
├── meta.json                   # resource configuration
└── .zcrmignore                 # cache ignore rules

🏢 About Wanas Apps

Wanas Apps is an elite Zoho Premium Partner and advanced technical consulting firm serving the Middle East and North Africa (MENA) region. We bridge the gap between standard business processes and advanced technical architecture, specializing in end-to-end digital transformation.

We don't just implement software; we build custom features that fit seamlessly around your unique business blueprint.


🩺 Troubleshooting

Errors are reported in a single, consistent format: expected problems (e.g. not logged in, bad input) show a clean message with an actionable hint, while unexpected errors show the real underlying reason plus how to reach support — so you're never left with a raw stack trace.

Every command also writes a timestamped debug log to ~/.zcrm/logs/ (e.g. pull-<timestamp>.log, audit-<timestamp>.log) capturing all activity for that run — including the quiet "skipped" lines and the full API error bodies that aren't printed to the console. When a command fails, its log path is shown in the output. zcrm pull additionally writes a copy into its output folder at <output>/.zcrm/.logs/.

The CLI also checks npm for a newer version once a day in the background (never blocking your command) and shows a one-line update notice when one is available. To disable it, set NO_UPDATE_NOTIFIER=1 (or ZCRM_NO_UPDATE_CHECK=1); it is skipped automatically in CI.


✉️ Support & Feedback

Found a bug, have a feature request, or need custom Zoho integrations? Reach out: