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

hairdora

v1.0.0

Published

HairDora CLI — manage the salons, clients, services and appointments of your hair salon from the terminal

Readme

hairdora

The HairDora command-line interface — read and manage the salons, clients, services and appointments of your hair salon from the terminal, and from scripts and AI agents.

It wraps the public HairDora REST API documented at hairdora.com/developers.

Install

npm install -g hairdora
# or run it without installing
npx hairdora --help

Requires Node.js 18 or newer.

Create an account

No HairDora account yet? You do not need a browser:

hairdora signup --email [email protected]

The password is generated and printed exactly once (pass --password to choose your own). Signing up creates your organization and its first salon, and stores the session, so every command below works immediately afterwards. Add --json for a machine-readable result.

Log in

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

hairdora login               # asks which method to use
hairdora login --browser     # opens app.hairdora.com to authorize
hairdora login --with-key    # masked prompt for an API key secret
hairdora logout              # clears the session and any stored key

API keys are created by an organization administrator in the HairDora dashboard, in the salon's API keys section; the secret is shown once, at creation. The secret is never accepted as a command argument — it would land in your shell history and in every ps listing — so it is prompted for, or read from the environment:

export HAIRDORA_API_KEY=<key secret>
hairdora salons list

Precedence is: stored browser session, then stored key, then HAIRDORA_API_KEY. Without a terminal and without credentials, commands fail immediately with instructions on stderr and exit code 1 — nothing opens a browser you cannot see.

Keys carry per-resource scopes and new keys start read-only, so a write can fail with 403 on a valid key; widen it in the dashboard. The scope vocabulary is appointments:read, appointments:write, clients:read, clients:write, services:read, services:write and salons:read. There is no salons:write scope — a salon is created when you sign up, not by an integration.

Commands

Salons (read-only)

hairdora salons list                 # id, name, city
hairdora salons get <salonId>        # raw JSON
hairdora salons read <salonId>       # formatted: contact, currency, timezone

Clients

hairdora clients list [--salonId <id>] [--email <email>] [--userId <id>]
                      [--ids id1,id2] [--fields name,email] [-n 25] [--skip 0]
hairdora clients get <clientId>
hairdora clients read <clientId>
hairdora clients add --name "Jane Fonda" [--salonId <id>] [--email <email>]
                     [--phone <phone>] [--language en] [--body '<json>']
hairdora clients update <clientId> [--name] [--email] [--phone] [--language]
                                   [--salonId] [--body '<json>']
hairdora clients delete <clientId...>

Services

hairdora services list [--salonId <id>] [--fields name,price] [-n 50] [--skip 0]
hairdora services get <serviceId>
hairdora services read <serviceId>
hairdora services add --name "Cut and blow-dry" [--price 45] [--salonId <id>]
                      [--description <text>] [--body '<json>']
hairdora services update <serviceId> [--name] [--price] [--description]
                                     [--salonId] [--body '<json>']
hairdora services delete <serviceId...>

Prices are plain numbers in the salon's own currency.

Appointments

hairdora appointments list [--salonId <id>] [--clientId <id>]
                           [--startTime <iso>] [--endTime <iso>]
                           [--sortField startTime] [--sortDirection ASC]
                           [--fields ...] [-n 25] [--skip 0]
hairdora appointments get <appointmentId>
hairdora appointments read <appointmentId>
hairdora appointments add --startTime <iso> [--endTime <iso>] [--salonId <id>]
                          [--clientId <id>] [--note <text>] [--body '<json>']
hairdora appointments update <appointmentId> [--startTime] [--endTime]
                             [--status SCHEDULED|CLIENT_ARRIVED|NO_SHOW|CANCELED]
                             [--clientId] [--note] [--salonId] [--body '<json>']
hairdora appointments delete <appointmentId...>

--startTime/--endTime are ISO 8601 instants and the list filter is a half-open window (startTime >= from, endTime < to). Prefer --status CANCELED over delete: deleting is permanent and also removes the appointment's scheduled reminders.

Every write needs a --salonId unless the key is locked to a single salon; update reuses the record's own salon when the flag is omitted (one extra read). Writes fire your organization's webhook subscriptions (client.created, appointment.updated, …) exactly like dashboard edits.

Skills and introspection

hairdora skills list           # the agent guides bundled with this version
hairdora skills get hairdora   # print one in full
hairdora schema                # the whole command tree as JSON
hairdora schema clients list   # one subtree only

Output contract

Every data command accepts --json and then prints real, parseable JSON on stdout — no colors, no ANSI escapes. Mutations with --json print a small result object ({ "ok": true, "id": … }). Errors always go to stderr with exit code 1; with --json they are a single JSON line ({"error":{"message":…,"status":…}}), so stdout stays parseable.

hairdora clients list --json | jq '.[] | {id: ._id, name, email}'

hairdora --help and hairdora <command> --help document every flag.

Configuration

| Variable | Purpose | | ------------------ | ----------------------------------------------------------- | | HAIRDORA_API_KEY | API key secret used when no session is stored | | HAIRDORA_API_URL | Override the API endpoint (defaults to the production API) |

Usage with AI agents

HairDora publishes Agent Skills that teach coding agents how to drive this CLI and the HairDora MCP connector:

npx skills add hairdora/skills

That installs into Claude Code, Cursor, Codex, Gemini CLI and any other agent following the Skills standard. The same guides ship inside this package, version-matched to the commands you have installed — hairdora skills get hairdora prints one on demand — and hairdora schema lets an agent discover the command tree without scraping help text.

For a chat-native connector instead of a CLI, add the MCP server at https://mcp.hairdora.com/mcp; setup for each client is documented at hairdora.com/developers.

License

Apache-2.0