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

@syncmatters/cli

v0.4.11

Published

SyncMatters CLI (sm) - develop syncs, connectors and scripts locally

Readme

SyncMatters CLI

sm is the command-line companion to the SyncMatters platform: pull your organization's connectors, integration scripts, and sync configuration into a local folder, edit them in your own editor (VS Code, Cursor, anything) with full IntelliSense, and push changes back safely.

Requirements

  • Node.js 22.12.0 or later
  • A SyncMatters account (you will mint a developer token in the web app)

Installation

npm install -g @syncmatters/cli
sm --help

Quick start

  1. Mint a developer token: in the SyncMatters web app, open your user settings, select Developer tokens, and create a token. Copy it — it is shown once.

  2. Sign in — the token is stored in your OS keychain, never in a file:

    sm auth
  3. Pull your workspace into a new folder:

    mkdir my-workspace && cd my-workspace
    sm pull

    This mirrors your organization's script tree into files/ (code) and meta/ (configuration sidecars), writes connection object lists under connections/ and sync/group snapshots under syncs/ and groups/, and sets up editor tooling so the SDK types light up. First time you open the folder in VS Code/Cursor, accept the "Use workspace TypeScript" prompt - the CLI's import-resolver plugin (which makes the platform's extensionless .mjs imports resolve) only loads with the workspace TypeScript version.

  4. Edit, then push:

    sm status                     # what changed locally (files + syncs)
    sm files diff                 # see the file changes
    sm files push -m "describe change"  # write them back (--yes skips the confirm prompt)

    Or leave sm files watch running and every save is pushed automatically.

Create and test a connector

Example: scaffold a connector for the public Swagger Petstore API, implement it, then run platform tests from the CLI.

  1. Scaffold (from a pulled workspace):

    sm connector init Petstore

    Wizard tips for Petstore: cloud only, OAuth2 none, include the Base URL setting preset. The entry file is created on the platform and locally at files/Connectors/Petstore/Petstore.mjs.

  2. Implement test(), meta(), and (for query coverage) query() in that file. The authoring guide ships with the SDK types package — see AGENTS.md after sm pull.

  3. Push, then create a connection in the web app for the Petstore connector type (Base URL: https://petstore3.swagger.io/api/v3). Open/save the connection so the platform can cache metadata.

    sm files push -m "Petstore: Pet query" --yes
  4. Generate the test-features module from that connection's cached metadata. This writes mod ObjectTestFeatures.mjs beside the connector entry (override with --file if needed). Re-run after meta() changes so new objects/relationships are actually exercised:

    sm connector features Petstore
    # or: sm connector features Petstore --connection "Petstore Demo"

    Requires a clean local copy of the target features file (push or discard local edits first — regeneration overwrites the platform copy).

  5. Run tests on the platform (streams logs, then prints the structured result):

    sm connector test Petstore --only connection   # connection.test()
    sm connector test Petstore --only meta         # connection.metaRefresh()
    sm connector test Petstore --only discover     # connection.discover() (two-phase connectors)
    sm connector test Petstore --only query        # every object's list/query feature
    sm connector test Petstore --only query --object pet   # one object's query feature (repeat --object for more)
    sm connector test Petstore                     # full suite (same as the web UI — includes writes)
    sm connector test Petstore --object pet        # full suite, but only the selected object(s)
    sm connector test Petstore --check exec        # only the named custom check(s) (repeat --check for more)

    A test module's customChecks() are named checks the engine runs after the object features; the result prints one line per check after the object lines (check <id> [on <object>]: <status>). --check alone runs just the named checks — no connection.test(), refresh or object features, the quick rerun for one failing check; with --object it adds them to that object's suite. It cannot be combined with --only.

    --only discover prints the catalogue size, which settings discovery overrides and how long it took, then refreshes the connection's selection and fails (exit 1) if a selected object is not in the catalogue. On a connection whose configuration is not two-phase (a version option marked discovery: false) it prints the engine's "does not implement discover()" line and passes. Before anything runs, the engine checks that every object the run would test is on the connection, and fails the run (exit 1) naming any that are not selected on the connection or not returned by meta().

    Use a sandbox connection for bare sm connector test. --connection picks by id or display name when the type has more than one; the listing sm prints when it cannot pick shows each connection's owed next step (or failing). When the connection it uses owes a next step — reconnect after a scope change, re-collect objects, refresh metadata — sm prints a note first: results reflect the old grant, catalogue or metadata until the step is run from the connection page in the web UI (sm reports the step; it does not run it). Token scopes: scripts:read, connections:read, scripts:execute. If you get a 403 about missing scope or “not available to developer token sessions”, fix the token/environment — --only modes all use the same execute routes, so retrying another --only will not help. If sm says the org's Developer tools setting withholds record data (data:read) or disables developer tools, a new token will not help either: an Owner has to change that setting in the web app's account Settings.

Inspect connections

sm pull writes an object list to connections/<uid>/objects.txt for every connection the token can read. Each line is <object> src:<ops> dest:<ops> [name] [custom] [match:<rules>] (- = none): the sync source and destination operations the object supports and the match rules it can use. The sm connection commands print the same catalogs on demand, including field shapes, without editing connector code:

sm connection list
sm connection objects <uid>
sm connection fields <uid> <object>
sm connection fields <uid> <object> --save    # writes connections/<uid>/fields/

--save and sm connection pull write generated references. sm files push does not upload them. If a connection owes a next step (reconnect, re-collect objects, refresh metadata), these commands say so. Run that step from the connection page in the web app; sm only reports it.

Work on integration scripts and syncs

Integration scripts and sync logic modules use the same files/ + meta/ layout as connectors. Sync and group snapshots under syncs/ and groups/ are read-only context. Author sync changes in changes/*.sync-changes.json, then preview, propose, or publish that file. Do not sm files push snapshots, drafts, or connections/.

  1. Pull scripts, catalogs, and snapshots:

    sm pull
    sm sync pull              # snapshots only; needs syncs:read
  2. Read the authoring guide shipped with @syncmatters/script-api (linked from AGENTS.md):

    node_modules/@syncmatters/script-api/docs/script-sync-authoring.md

  3. Edit scripts under files/Scripts/ only (connector code under files/Connectors/; the platform rejects other top-level folders). A pulled syncs/<uid>/sync.config.json shows which module backs a sync and how mappings are wired. Change the sync in a changeset, not by editing the snapshot.

  4. Validate and push scripts (never sync, group, connection, or draft JSON):

    sm validate
    sm status
    sm files push -m "Sync logic: filterFast tweak" --yes

    Sync logic modules are default-exported classes implementing API.SyncLogic hooks. Integration scripts export async function main(ctx) with API.Context. A push saves the file. A schedule keeps running the deployed snapshot until you deploy (below).

  5. Change sync configuration with a changeset. Confirm both connections with sm sync fields before writing mappings:

    sm sync fields --source <connection-uid>:<object-uid> --dest <connection-uid>:<object-uid>
    sm sync inspect --source <connection-uid>:<object-uid> --dest <connection-uid>:<object-uid>
    sm sync validate changes/example.sync-changes.json
    sm sync draft changes/example.sync-changes.json       # live preview; writes draft JSON
    sm sync propose changes/example.sync-changes.json     # store for web review; prints a URL
    sm sync push changes/example.sync-changes.json        # apply to the live org

    propose never applies. push does, and only after the preview is clean. A file stamped $sm.proposed has to be published from the web review page (or the marker removed) before sm sync push will take it.

Deploy

Saving a script or publishing a sync does not change what a schedule runs. Deploy when the saved version should go live, or roll back to an older snapshot:

sm files deploy-status Scripts/orders.mjs
sm files deploy Scripts/orders.mjs
sm files deploy Scripts/orders.mjs --snapshot <id>
sm sync deploy-status <group-uid>
sm sync deploy <group-uid>

Deploy needs the Deploy permission (org:deploy). Deleting a live file with sm files rm prints what will be redeployed and asks; a non-interactive run passes --acknowledge-deploy. Pushing a file that is live and not yet deployed also needs that permission, or that file is reported as REFUSED and the rest of the push continues.

Commands

| Command | What it does | | ----------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | sm auth | Sign in with a developer token. Inside a previously pulled folder it reconnects to that folder's organization. | | sm whoami | Show who you are signed in as, and where. | | sm introspect | Check that your developer token is still active and list what it grants (scopes, org, expiry) - RFC 7662 token introspection. --session asks about the short-lived session JWT instead, --json prints the raw response. Exit 0 = active, 1 = not active, 2 = could not ask. | | sm pull | Download script files, connection object catalogs, slim types, and sync/group configuration snapshots (safe: never overwrites local edits silently). Use --no-connections / --no-syncs / --no-types to skip a layer. Requires connections:read for catalogs and syncs:read for sync export (each skipped with a warning when missing on default pull). | | sm validate | Lint files/meta/state then sync changesets (local only). Exit 1 if either layer has errors. --no-syncs skips changesets. For one changeset file use sm sync validate [file]. | | sm status | Local scan of files then sync snapshots/changesets (no server). --no-syncs skips the sync section. Types drift is sm files types --check. | | sm files pull | Refresh script files and slim types in an existing workspace (no syncs). | | sm files status / sm files diff | Compare working files against what you pulled — new local files show as creation diffs. | | sm files push -m "msg" | Upload changed files with optimistic concurrency — if someone changed a file since your pull, the push is rejected instead of overwriting their work. Also creates new files you added locally (each needs a meta/ sidecar). Pass --yes to skip the confirmation prompt (required for non-interactive / agent runs). Does not publish generated connections/, syncs/, or drafts. | | sm files watch | Auto-push file changes on save (debounced, conflict-safe, never creates). | | sm files validate | Check files, meta sidecars, and workspace state locally, including a connector's two-phase setup flags (discovery, prerequisite, affects_meta, a version option's discovery: false); a missing discover() method is a warning - the engine is the check. | | sm files types | Refresh generated typings under types/ so ctx.connections.<uid>() / ctx.syncGroups.<uid>() and API.connections.<uid> resolve. Slim by default. Use --full <uid> for deep field graphs; --connections <uid,...> to limit connections. --check / --offline live here (not on pull). Requires connections:read. | | sm connection list | List connection uids, names, connector types, health, object counts, and any next step owed. --json. Requires connections:read. | | sm connection objects [uids...] | Print the server-rendered object catalog for named connections, or all connections when omitted. Each line shows the object's src: / dest: sync operations and match: rule names; --json adds source_operations, destination_operations, match_rules. Supports --filter, --names, --limit, and --json. | | sm connection fields <uid> <objects...> | Print compact query/upsert/delete field catalogs for named objects. Supports repeatable --operation, --filter, --options, --tree, --limit, --json; --save writes generated references under connections/<uid>/fields/. | | sm connection pull | Refresh generated connections/<uid>/objects.txt catalogs only. Object lists are also refreshed by sm pull. | | sm files mv / sm files rm | Rename/move or delete platform files, safely. Deleting a live file (its schedule is enabled, or a scheduled script or sync group imports it) changes production: rm says what changes and asks; --acknowledge-deploy confirms it (required when non-interactive), and every scheduled item that depended on the file is deployed at latest. | | sm files deploy-status <file> | Show whether a script is deployed: when, which snapshot, and what changed since (type, name, when); "not deployed" means scheduled runs use the latest saved configuration. A module is deployed with the scripts that import it. --json. Needs scripts:read. | | sm files snapshots <file> | List a script's platform snapshots (its deploy history), newest first, marking the deployed one. --limit, --json. | | sm files deploy <file> | Deploy a script: scheduled runs use the latest saved version from now on (creates a snapshot; -m comments it). --snapshot <id> rolls back to an existing snapshot. Asks [y/N]; --yes skips it. Needs the Deploy permission (org:deploy). | | sm sync validate | Lint authored changes/*.sync-changes.json (schema, $ref graph, snapshot warnings). Also warns on a dest.-prefixed destination_field_path, a set_filter condition whose value_path lacks an origin or does not spell its field_path, a mapping comment over 2000 characters, and, when connections/<uid>/objects.txt is pulled, on a source/destination operation the object does not list. Exit 0 with warnings, 1 on schema/$ref errors, 2 if not in a workspace. | | sm sync pull | Refresh sync/group snapshots only (existing workspace; hard-fail without syncs:read). | | sm sync status | Local scan of snapshot hashes vs pull pins, authored changes/*.sync-changes.json, and leftover drafts. Snapshots are not a sm files push payload. | | sm sync draft <file> | Preview a changeset against the live org (POST previewsyncops). Local schema/$ref errors exit 1 with no network. Prints the server plan and writes draft JSON (syncs/<uid>/sync.config.draft.json and changes/<name>.draft.<handle>.json). A rerun replaces changes/<name>.draft.*.json for that changeset stem. Exit 0 when the preview has no issues, 1 when the server returns issues (including unsupported_operation and unknown_field_path), 2 for setup/403. Drafts are never a sm files push payload. | | sm sync propose <file> | Store a changeset for web review. Local lint, then preview. Preview issues exit 1 and create nothing. A clean preview stores the proposal (syncs:write), stamps $sm.proposed in place, and prints the review URL. Never applies. No prompt. A file that already carries $sm.proposed exits 2. --title, --json, --dir. | | sm sync push <file> | Publish a reviewed changeset (previewsyncops then applysyncops). Local schema/$ref errors exit 1 with no network. Preview issues abort with no prompt (including --yes). A clean preview prints the server plan and asks [y/N]; --yes skips the prompt only. Needs syncs:write. Refuses changes/applied/, files with $sm.applied, and files with $sm.proposed (publish that proposal in the web, or remove the marker). On commit archives immediately, then refreshes snapshots and deletes drafts. Agents push only on human instruction. | | sm sync fields | Compact field catalog for drafting mappings (server-rendered). --sync <uid> or --source/--dest as connection-uid:object-uid. Repeat --related <relationship-uid> or --lookup lookup-uid=src\|dest:object-uid:array\|scalar to include those paths. Human mode prints rendered; --json prints fields + resolved. Needs connections:read. Exit 2 for no workspace / unknown uid / 403; exit 1 for catalog issues. Do not read types/ for field maps. | | sm sync inspect | --source/--dest as connection-uid:object-uid. Prints each object's catalog line (src:/dest: operations, match rule names), the sm sync fields catalog for the pair, and same-name candidates (destination write fields whose last path segment matches a src. field, with number/boolean → string pairs marked AUTO-CONVERT (the runtime converts them), other type differences such as scalar → array marked TYPE MISMATCH, and destination picklists marked OPTIONS, or OPTIONS+ when they accept new values; --json candidates carry destination_is_picklist / destination_can_update_options, type_compatibility (exact/auto_convert/incompatible/unknown) and type_conversion). --dont-convert-types judges pairs as if the mapping sets behaviour.dont_convert_types (no AUTO-CONVERT). --json, --dir. Exit codes as sm sync fields; an object missing from its connection exits 2. | | sm sync deploy-status <group-uid> | As sm files deploy-status, for a sync group (its syncs and sync-module scripts). Needs syncs:read. | | sm sync snapshots <group-uid> | As sm files snapshots, for a sync group. | | sm sync deploy <group-uid> | As sm files deploy, for a sync group. After sm files push / sm sync push of a deployed item, sm prints that the change is saved but not deployed. A push of a file that is live and not deployed needs the Deploy permission (it changes production); without it the file is reported as REFUSED and the other files still push. | | sm connector init | Scaffold a new connector with a guided wizard. | | sm connector update | Update a connector's settings definition. | | sm connector features | Regenerate mod ObjectTestFeatures.mjs (default --file) from a connection's cached metadata and sync it locally — run after meta() changes so sm connector test exercises the new objects/relationships. Warns about discovery catalogue entries the connection did not select. See Create and test a connector. | | sm connector test [connector] | Run the connector test suite on the platform. Prefer --only connection\|meta\|discover\|query while iterating, --check <id> to rerun one custom check; bare sm connector test is the full web-UI suite (including writes — use a sandbox). Notes a next step the connection owes (read-only). Exit 0 / 1 / 2. See Create and test a connector. | | sm bootstrap | Regenerate the editor tooling (IntelliSense overlay, AGENTS.md, and a CLAUDE.md @AGENTS.md shim) — runs automatically after sm pull, and keeps the SDK type packages (and the bundled connector + script-api authoring guides) up to date, checking at most once a day. | | sm profile list/use | Inspect or switch stored sign-ins (profiles are created automatically by sm auth). |

Run any command with --help for options.

Old short names (sm push, sm test, sm types, sm diff, sm watch, sm mv, sm rm, sm pull sync) print the replacement command and exit 2. They are hidden from sm --help.

Sync configuration is authored in changes/*.sync-changes.json (schema stays sm-sync-changes/v0). create_sync may set type / parent for loop children. A parent $handle must be declared on an earlier op; an unknown parent sync_uid is a snapshot warning. Resolve ID maps may use a same-changeset $handle in other_id. Besides create/group and field-map ops, the file may also set_source_operation / set_destination_operation (only operations the object's objects.txt line lists under src: / dest:; sm sync draft reports others as unsupported_operation), add/update/delete match rules, set_match_settings ({"store": true} turns on "Remember matches"; include it when the sync creates destination rows), set_filter (wholesale replace of the filter section — echo unchanged parts; spec: null clears; a condition may give field_path alone, e.g. src.crm_company_id, and the server derives value_path, whose first segment is the origin src / parent / system / related / lookups / dest), set_sync_module (script_full_name), add/update/delete lookups, and add/update/delete calculated fields. Update/delete a lookup by snapshot lookups[].id (platform_id); a calculated field by envelope uid from calculated_fields[].uid. Preview lookup paths with sm sync fields --lookup, then author add_lookup plus mappings that consume lookups.<uid>.* in the same changeset. sm sync validate lints locally; sm sync draft <file> previews against the live org; sm sync propose <file> stores it for web review and prints a URL ($sm.proposed is not a push payload); sm sync push <file> publishes after a human instructs it. Use sm sync fields for the compact field catalog when drafting mappings (not types/). A mapping's destination_field_path is the bare write path exactly as the # dest section prints it (properties.email); source paths keep their src. / calculated. / lookups. prefix. dest. is the read-side prefix (match rules, filters), not part of a write path unless the object really has a field named dest. A path that is not a field of the object is an unknown_field_path issue from sm sync draft. A destination field flagged enum:<n>+ accepts new picklist values: on an upsertClean sync, set option_management.enable_options_add (true adds them, false discards) on a manage_options action; sm sync draft warns when it is unset. A mapping comment is at most 2000 characters. Publish is live. Agents must not push config unless the human instructed it in the session. Snapshots and draft files are preview only — never a sm files push payload. Applied changesets are archived under changes/applied/ and cannot be re-pushed.

How it keeps you safe

  • Your token stays in the OS keychain and is exchanged for a short-lived session per command; nothing secret is ever written to the workspace or config files. Revoking the token in the web app cuts the CLI off immediately.
  • No lost work: every push carries the version you pulled; if the platform copy moved on, you get a conflict instead of a silent overwrite (sm pull, merge, push again).
  • No cross-organization accidents: a workspace is bound to the organization it was pulled from, and every command checks that your current sign-in matches before touching anything.

Working with AI coding assistants

Pulled workspaces are AI-ready: sm pull generates an AGENTS.md that assistants like Cursor pick up automatically, plus a one-line CLAUDE.md (@AGENTS.md) so Claude Code loads the same guide. Both point at the connector-authoring guide (@syncmatters/connector-sdk) and the integration-script / sync-module guide (@syncmatters/script-api). Your assistant learns the SDK contracts, the platform's conventions, sync snapshot rules, and common pitfalls without any manual priming. Typed connections and sync groups resolve locally too: sm files types (slim also runs after sm pull / sm files pull) installs maps and per-connection type definitions under types/ — slim stubs by default so large ERP connections stay fast in the IDE; run sm files types --full <uid> when you need full query/upsert field typing for a connection. sm pull also writes compact, AI-friendly object lists under connections/<uid>/objects.txt; use sm connection fields <uid> <object> --save to cache a focused field catalog without pulling every ERP field graph.

CI and automation

Set SM_TOKEN to a developer token instead of running sm auth — useful for pipelines that pull or push scripts non-interactively. Mint a dedicated token for CI so it can be revoked independently.

Documentation and support

License

MIT © SyncMatters