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

dododentist

v1.0.0

Published

DodoDentist CLI — manage the patients, appointments, treatments, invoices and payments of your dental clinic from the terminal

Readme

dododentist

Command-line interface for DodoDentist — manage the clinics, patients, appointments, treatments, invoices and payments of your dental practice from the terminal.

npm install -g dododentist
dododentist --help

or run it without installing:

npx dododentist --help

Requires Node.js 18 or newer.

Create an account

No account yet? The CLI can create one — no browser needed. The generated password is printed exactly once, the organization's first clinic is created along with the account, and the session is stored so every other command works immediately:

dododentist signup --email [email protected]
dododentist signup --email [email protected] --json      # machine-readable
dododentist signup --email [email protected] --password 'your own password'

--first-name and --last-name are optional; they default to whatever the email address suggests.

Log in

Two ways in, both stored in ~/.dododentist/:

dododentist login               # interactive: choose browser or API key
dododentist login --browser     # opens app.dododentist.com to authorize
dododentist login --with-key    # masked prompt for an API key secret
dododentist logout              # clears the stored session and any stored key

Browser stores a session that refreshes itself. API key stores a long-lived secret. Create keys in the DodoDentist web app: they belong to your organization, can be locked to a single clinic, and start with read-only scopes that an administrator widens explicitly.

The key secret is never accepted as a command argument — argv lands in shell history and in every ps listing. Prompt or environment variable only.

Headless and CI

Export the key instead of logging in:

export DODODENTIST_API_KEY=<key secret>
dododentist clinics list --json

Credential precedence is: stored browser session → stored API key → DODODENTIST_API_KEY. A stored login therefore always wins over a key exported globally in your shell.

Without a terminal and without credentials, commands fail immediately with exit code 1 and instructions on stderr. Nothing ever opens a browser headlessly or waits on a prompt nobody is there to answer.

Commands

Every resource follows the same shape: list (filtered summary), get <id> (raw JSON), read <id> (formatted for a terminal), and — where the API and your key's scopes allow it — add, update <id> and delete <id...>.

Clinics — read-only

dododentist clinics list
dododentist clinics get <clinicId>
dododentist clinics read <clinicId>

Requires clinics:read. There is no clinics:write scope, so clinics cannot be created or edited through the API.

Patients

dododentist patients list --clinicId <id> -n 25
dododentist patients list --email [email protected]
dododentist patients list --clinicId <id> --fields name,email,phone
dododentist patients list --_ids <id1>,<id2>
dododentist patients get <patientId>
dododentist patients read <patientId>
dododentist patients add --clinicId <id> --name "Ada Lovelace" --email [email protected]
dododentist patients update <patientId> --phone "+15555550111"
dododentist patients delete <patientId> [<patientId> …]

list also takes --userId, --skip, --sortField (name, lastEditTime or _id) and --sortDirection (ASC/DESC). add and update take --name, --email, --phone, --language, --clinicId and --body for any other field. Requires patients:read / patients:write.

Appointments

dododentist appointments list --clinicId <id> \
  --startTime 2026-09-01T00:00:00.000Z --endTime 2026-09-08T00:00:00.000Z
dododentist appointments list --patientId <id> --sortField startTime --sortDirection ASC
dododentist appointments get <appointmentId>
dododentist appointments read <appointmentId>
dododentist appointments add --clinicId <id> --patientId <id> \
  --startTime 2026-09-01T09:00:00.000Z --endTime 2026-09-01T09:30:00.000Z
dododentist appointments update <appointmentId> --status CANCELED
dododentist appointments delete <appointmentId> [<appointmentId> …]

Times are ISO 8601 instants: --startTime matches appointments starting at or after it, --endTime those ending strictly before it. Statuses are REQUESTED, SCHEDULED (the default), PATIENT_ARRIVED, NO_SHOW and CANCELED. list also takes --limit, --skip, --fields and --sortField (_id, startTime, endTime, lastEditTime). Requires appointments:read / appointments:write.

Treatments — read-only

dododentist treatments list --patientId <id>
dododentist treatments list --clinicId <id> --startTime 2026-01-01T00:00:00.000Z
dododentist treatments get <treatmentId>
dododentist treatments read <treatmentId>

Requires treatments:read. There is no treatments:write scope.

Invoices

dododentist invoices list --patientId <id>
dododentist invoices get <invoiceId>
dododentist invoices read <invoiceId>
dododentist invoices add --clinicId <id> --patientId <id> --status DRAFT \
  --body '{"lines":[{"name":"Cleaning","price":80,"quantity":1}]}'
dododentist invoices update <invoiceId> --status PAID
dododentist invoices delete <invoiceId> [<invoiceId> …]

Statuses are DRAFT, PENDING, PARTIALLY_PAID, PAID, OVERDUE, REFUNDED and UNCOLLECTIBLE. An invoice's value lives in lines (or the legacy procedures), which are set through --body. Requires invoices:read / invoices:write.

Payments

dododentist payments list --clinicId <id> --startTime 2026-08-01T00:00:00.000Z
dododentist payments get <paymentId>
dododentist payments read <paymentId>
dododentist payments add --clinicId <id> --patientId <id> --amount 120
dododentist payments update <paymentId> --note "paid in cash"
dododentist payments delete <paymentId> [<paymentId> …]

A payment carries its value in lines, the legacy procedures, or a flat --amount. A manually recorded payment has no status; SUCCEEDED, FAILED and CANCELED come from the card-terminal flow. Requires payments:read / payments:write.

Agent skills

dododentist skills list           # the guides bundled with this version
dododentist skills get dododentist

Writes need a clinic

Every create and update resolves its clinic from --clinicId, or from the clinic a clinic-scoped key is locked to. update falls back to the clinic of the record being edited. Without any of those the API answers missing clinicId.

Output contract

Every data subcommand accepts --json, which prints real, parseable JSON to stdout — no colors, no ANSI escapes. Without it, output is formatted for humans. Mutations with --json print a small result object such as { "ok": true, "id": "…" }.

Errors always go to stderr with exit code 1. In --json mode the error is one JSON line, so stdout stays parseable:

{ "error": { "message": "…", "status": 401 } }

schema prints the whole command tree — every option, argument and subcommand — as JSON, so a script or an agent can discover what the CLI does without scraping --help:

dododentist schema
dododentist schema patients list

Usage with AI agents

DodoDentist publishes Agent Skills that teach coding agents how to drive this CLI:

npx skills add dododentist/skills

That works with Claude Code, Cursor, Codex, Gemini CLI, GitHub Copilot, OpenCode and any other agent following the Skills standard. The same guides ship inside this package, version-matched to the commands it exposes, and dododentist skills get <name> prints one on demand.

Practice records are health data. Give each integration its own key with the narrowest scopes it can work with, prefer a clinic-scoped key, and delete a key the moment the integration is retired.

Environment variables

| Variable | Purpose | | ---------------------- | ---------------------------------------------------------------- | | DODODENTIST_API_KEY | API key secret used when no login is stored | | DODODENTIST_API_URL | Override the API endpoint (only for non-production deployments) |

License

Apache-2.0