hairdora
v1.0.0
Published
HairDora CLI — manage the salons, clients, services and appointments of your hair salon from the terminal
Maintainers
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 --helpRequires 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 keyAPI 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 listPrecedence 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, timezoneClients
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 onlyOutput 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/skillsThat 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.
