← Work

006 · 2026

EsSalud appointments, from the terminal

Booking a medical appointment on Peru's EsSalud portal is slow and fragile. I built a CLI that runs the whole flow (profile, slots, reserve, cancel) in seconds, with a login where your token and data never leave your machine.

Role
Design engineer · solo build
Status
Published to npm · source-available
TypeScriptNodePlaywrightcommander@clack/promptsCLI
Capture coming

Where it came from

It started as a piece of something bigger. The EsSalud flow already worked inside tramites-pe, a WhatsApp bot project, and it was the part I kept reaching for, so at a quarter to one in the morning I pulled it out into its own repo. The CLI worked that same night. The project did not exist yet: no tests, no lint, no CI, and no way for anyone else to install it.

Decision

Privacy-first, no official API

There is no public EsSalud API, so login opens an ephemeral Playwright browser with a clean profile, catches the auth token off the network, validates it, and stores it locally with chmod 600. Nothing is ever sent anywhere else. Booking and cancelling are dry-run by default and need an explicit confirm before anything real happens.

Decision

Usable, then contributable, then worth reading

I wrote the plan down as three layers in that order and did not let myself skip one. Usable meant the token living in its own directory with a clean migration from the old path, and every string in Peruvian Spanish. Contributable meant Biome, Vitest over the pure functions gating every pull request, a contributing guide, and Changesets. Worth reading meant no names or paths left over from the bot it came out of. It took three days, and the gate on the last layer was a written PASS verdict rather than my own opinion.

How it's built

Agents that grade the work

Part of the repo is a small set of agents I wrote for it: a quality reviewer that opens one issue per finding and returns PASS or FAIL, a test writer, a release manager that publishes through Changesets and dry-runs by default, and an endpoint mapper that re-derives the reverse-engineered API from a fresh HAR capture and opens a pull request with the diff. That last one is the load-bearing one: with no official API, the day EsSalud changes its backend the fix is a capture, not an archaeology session.

How it's built

One binary, two ways in

Run it with no arguments for an interactive prompts menu, or pass subcommands for one-shot use. The reverse-engineered API is wrapped so its quirky response envelope and empty-data cases normalize cleanly, and the end-to-end test books a real appointment then cancels it inside a finally block, so it can never leave a real medical appointment hanging. If the cancel itself fails, it says so loudly rather than exiting quiet.

What actually broke

The reviewer caught things I had missed, including a flag the cancel command never registered and a prompt that offered appointments that were already annulled. Getting the Spanish register consistent took three passes, because voseo kept surviving in files I was sure I had already fixed. And the last bug was the most embarrassing kind: I published to npm and the command did not exist. The bin path carried a leading ./, which npm 11 treats as invalid, so it dropped the binary without complaining. The pack gate I had added the day before did not catch it either, because packing a tarball is not the same as installing one.