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

cncjs-pendant-alexa

v0.2.0

Published

Voice jog control for cncjs via a custom Alexa skill ("Alexa, X plus 20")

Downloads

321

Readme

cncjs-pendant-alexa

Voice jog control for cncjs through a custom Alexa skill:

One-shot: "Alexa, ask mill x plus 20" — or open CNC mode: "Alexa, open mill" … "x plus 20" … "position x 130 y 100" … "close"

One-shot: "Alexa, peça pra fresa xis mais vinte" — ou modo CNC: "Alexa, abrir fresa" … "xis mais vinte" … "fechar"

Numbers are millimeters. The pendant connects to the cncjs server's socket.io API (like any other cncjs-pendant-*), sends Grbl $J= jog commands and exposes a small HTTPS-tunneled endpoint that your own Alexa developer skill calls. No cloud service in the middle besides Alexa itself; no skill-store publication needed (a development-mode skill works forever on the Echos of your Amazon account, for free).

Interaction models for en-US and pt-BR are included, ready to paste.

Safety model

Voice is a lossy input, so the pendant refuses instead of trusting:

  • Only $J= jog commands are ever sent — cancellable instantly, no parser state pollution. Never raw G0/G1.
  • Per-command travel limits (default: 50 mm on X/Y, 10 mm on Z). Asking for 200 mm gets a spoken refusal, not a move.
  • Jogs are refused unless the controller is Idle/Jog and the cncjs workflow is idle — a running job can never be disturbed.
  • Alarm is reported, never auto-unlocked by voice.
  • Z uses a slower feed rate than X/Y (defaults: F300 vs F1000).
  • "halt" / "para" (and exiting the skill) send Grbl jog-cancel (0x85).
  • Every request is cryptographically verified as coming from Alexa (certificate + timestamp) and, with --skill-id, from your skill only.

Install

npm install -g cncjs-pendant-alexa

Run it on the same host as the cncjs server (it reads the secret from the server's ~/.cncrc to authenticate, exactly like the other community pendants):

cncjs-pendant-alexa --port /dev/ttyUSB0 --skill-id amzn1.ask.skill.xxxx

Options: --baudrate 115200, --cncjs-url ws://127.0.0.1:8000, --http-port 8977, --http-path /alexa, --secret-file /home/cnc/.cncrc, --max-xy 50 --max-z 10 --feed-xy 1000 --feed-z 300, --controller-type Grbl.

Sanity check (connects, prints machine state as JSON, exits):

cncjs-pendant-alexa --port /dev/ttyUSB0 --check

Set up the Alexa skill (one time, ~15 min, free)

  1. HTTPS tunnel — Alexa must reach your endpoint over public HTTPS with a valid certificate. Easiest free option: ngrok with the one free static domain every account gets (ngrok http 8977 --url=yourname.ngrok-free.app). Alternatives: Cloudflare Tunnel (if you own a domain) or Tailscale Funnel. See examples/systemd/alexa-tunnel-ngrok.service.

  2. Go to the Alexa developer consoleCreate Skill → name it (e.g. "CNC Pendant") → primary locale English (US) or Portuguese (BR) → type Custom → host Provision your own.

  3. In Build → Interaction Model → JSON Editor, paste models/en-US.json or models/pt-BR.json (add the other locale under Language Settings if you want both) → Save ModelBuild Model.

  4. In Build → Endpoint, choose HTTPS, set the default region to https://yourname.ngrok-free.app/alexa, and pick the SSL certificate type that matches your host — this choice matters and the errors it causes are silent:

    • Behind Cloudflare (or any host whose certificate covers your subdomain via a wildcard like *.example.com): pick "My development endpoint is a sub-domain of a domain that has a wildcard certificate" (Wildcard).
    • Only if the certificate names your exact hostname: "...has a certificate from a trusted certificate authority" (Trusted).

    With the wrong type, Alexa rejects the TLS handshake before any request reaches you, and the simulator only says "endpoint error". The skill invocation API is the one tool that reports the real reason (e.g. "Certificate for host contains wildcard").

  5. Copy Your Skill ID (top of the Endpoint page) and pass it to the pendant via --skill-id.

  6. In Test, enable testing in Development. The skill is now live on every Echo logged into your account — no certification, no publication.

Run as a service

Copy the units from examples/systemd/, edit port/skill-id/domain:

sudo cp examples/systemd/*.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now cncjs-pendant-alexa alexa-tunnel-ngrok

GET /healthz on the HTTP port reports the live machine state for monitoring.

Voice reference

The default invocation name is "mill" (pt-BR: "fresa") — change the invocationName in the model JSON to whatever you prefer before pasting it. Every command works one-shot ("Alexa, ask my mill x plus 20") or inside CNC mode ("Alexa, open c. n. c.", then bare commands). While CNC mode is open, unrelated phrases get a spoken reminder that Alexa is in CNC mode and how to leave; Alexa closes an idle session on its own after a few seconds of silence (platform limit — a custom skill cannot hold the microphone open indefinitely).

| Intent | en-US | pt-BR | |---|---|---| | Move (relative) | "x plus 20", "move y minus 5" | "xis mais vinte", "mover y menos cinco" | | Go to (absolute, 1-3 axes) | "position x 130 y 100 z 5", "go to x 50" | "posição x 130 y 100 z 5", "vai para x 50" | | Cancel jog | "halt", "stop moving" | "para", "pare" | | Position | "where are you", "position" | "onde está", "posição" | | Help | "help" | "ajuda" | | Exit CNC mode | "close", "exit cnc mode" | "fechar", "sair do modo cnc" |

Absolute moves use work coordinates and the same per-axis travel limits, measured from the current position.

Development

npm test          # unit tests (jog math, state gating, slot parsing)
node bin/cncjs-pendant-alexa --port /dev/ttyUSB0 --no-verify   # local testing

--no-verify disables Alexa signature verification so you can curl synthetic request envelopes at the endpoint. Never expose an unverified endpoint.

License

MIT