{"_id":"@healos/cli","_rev":"3-1070715a1a0029447a4d445b639f2739","name":"@healos/cli","dist-tags":{"latest":"0.1.1"},"versions":{"0.0.0-stage":{"name":"@healos/cli","version":"0.0.0-stage","_id":"@healos/cli@0.0.0-stage","stub":true,"maintainers":[{"name":"healos","email":"developer@healos.ai"}],"dist":{"shasum":"3a54f27e4707d484835ff9086b09d0b40b1ee21d","tarball":"https://registry.npmjs.org/@healos/cli/-/cli-0.0.0-stage.tgz","fileCount":2,"integrity":"sha512-ZXBXU+0gRYOy57edCVyrObhSUKhkHkV9Icp6anIMiKvxTu0yxR4R4jksC4t75LMrZvXy+at25gU0IO9fKqwBWw==","signatures":[{"sig":"MEUCIQCgml9HCSkagojxZ2f8dMwsl1bD3ek4/bkOPZpSMx9g9gIgGv+OgajCABm20z3P+43LX1JnRhTf670HNKT1dsEx9oU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":333},"_npmUser":{"name":"healos","email":"developer@healos.ai"},"description":"Temporary package placeholder for staged publishing","directories":{}},"0.1.0":{"name":"@healos/cli","version":"0.1.0","keywords":["healos","cli","ehr","clinical-notes","prior-auth"],"license":"UNLICENSED","_id":"@healos/cli@0.1.0","maintainers":[{"name":"healos","email":"developer@healos.ai"}],"homepage":"https://docs.healos.ai/cli","bin":{"healos":"dist/index.js"},"dist":{"shasum":"cbc2dae3b1ba2e8e67a9ddc910f7f8e2d19a8d0d","tarball":"https://registry.npmjs.org/@healos/cli/-/cli-0.1.0.tgz","fileCount":3,"integrity":"sha512-R1b1AZI6eD4+essxyCIVKaRU7FvzWdjXQ9q0KIpkMuxlsY1OUnzvVEwf8N4pnJyvnG5yIma7TYFF/kS9nxfBcA==","signatures":[{"sig":"MEQCICBD0PGk2OGd8X83/xokK+fhEMYtojoWGU1sEP/xfuxxAiBPKLcDoMs9VTq+OPo4LSYWLxmB2hmjv3R68a7nFvklUw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCICbr0fTJmhKc7oZYmk9BUm8zwvAqhtPM8VqxeptMmMlTAiEAv2UG3LV8In2BEmCZBLzQr4/dc9/DUTiteePaeGTYCT8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":121511},"type":"module","engines":{"node":">=18"},"gitHead":"75b9363916984f9a606b1463bced338d2f41ab0c","scripts":{"dev":"bun src/index.ts","fix":"ultracite fix .","lint":"ultracite check .","test":"bun test src/__tests__","build":"npm run build:sdk && bun scripts/build.ts","clean":"rimraf dist .turbo","pretest":"npm run build:sdk","build:sdk":"tsc -p ../../packages/sdk/tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit","build:binary":"npm run build:sdk && bun build src/index.ts --compile --outfile dist/healos","prepublishOnly":"npm run build"},"_npmUser":{"name":"healos","email":"developer@healos.ai"},"_npmVersion":"10.9.9","description":"The HealOS command line: patients, notes, eligibility and prior auth from your terminal, over the HealOS External API","directories":{},"_nodeVersion":"22.23.4","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"citty":"^0.2.2","@types/bun":"^1.2.5","typescript":"^5.8.2","@healos/sdk":"*","@types/node":"^22.15.18"},"_npmOperationalInternal":{"tmp":"tmp/cli_0.1.0_1793121270125_0.11605047131510937","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"_id":"@healos/cli@0.1.1","bin":{"healos":"dist/index.js"},"dist":{"shasum":"f55287547780841d298155e12a68d6634feba18a","tarball":"https://registry.npmjs.org/@healos/cli/-/cli-0.1.1.tgz","fileCount":3,"integrity":"sha512-grBn1Bedf0DgoWSMd1+XPv7EBGW48QU8oh8UNB07BSS6GWyZxeqPE4bOBotMzojI7eFcnmwsAs9gTfbV7tefuw==","signatures":[{"sig":"MEYCIQC8p6WfpaTIDun81mhqBWWr5rq3ACxbyTBVRhQsVobhwAIhAPb6G/yrk4xZd8vric3T1InlR10NNlZok2uihmmFSqH9","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIH2ka5ZjwDo7iCGYBSmNThpw8QVa1s6u97KHMRMaUx8bAiBSD0HjyUndqMw53Qf40De1Gu1E9RQviKvUEP1Ga8iwCg=="}],"unpackedSize":121801},"name":"@healos/cli","type":"module","engines":{"node":">=18"},"gitHead":"b004ded8117265c0dc4f4f7be4c634ec9ac56409","license":"UNLICENSED","scripts":{"dev":"bun src/index.ts","fix":"ultracite fix .","lint":"ultracite check .","test":"bun test src/__tests__","build":"npm run build:sdk && bun scripts/build.ts","clean":"rimraf dist .turbo","pretest":"npm run build:sdk","build:sdk":"tsc -p ../../packages/sdk/tsconfig.json","typecheck":"tsc -p tsconfig.json --noEmit","build:binary":"npm run build:sdk && bun build src/index.ts --compile --outfile dist/healos","prepublishOnly":"npm run build"},"version":"0.1.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"3b0f1bc2-d363-4da5-b8d6-df4344227555"}},"homepage":"https://docs.healos.ai/cli","keywords":["healos","cli","ehr","clinical-notes","prior-auth"],"_npmVersion":"11.21.1","description":"The HealOS command line: patients, notes, eligibility and prior auth from your terminal, over the HealOS External API","directories":{},"maintainers":[{"name":"healos","email":"developer@healos.ai"}],"_nodeVersion":"22.23.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"citty":"^0.2.2","@types/bun":"^1.2.5","typescript":"^5.8.2","@healos/sdk":"*","@types/node":"^22.15.18"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cli_0.1.1_1793123517382_0.49790330968050933"}}},"time":{"created":"2026-10-27T17:12:53.025Z","modified":"2026-10-27T17:51:57.631Z","0.0.0-stage":"2026-10-27T17:12:53.025Z","0.1.0":"2026-10-27T17:14:30.203Z","0.1.1":"2026-10-27T17:51:57.459Z"},"license":"UNLICENSED","homepage":"https://docs.healos.ai/cli","keywords":["healos","cli","ehr","clinical-notes","prior-auth"],"description":"The HealOS command line: patients, notes, eligibility and prior auth from your terminal, over the HealOS External API","maintainers":[{"name":"healos","email":"developer@healos.ai"}],"readme":"# healos\n\nThe HealOS command line. It is a client of the public ext-api (`/ext-api/v1`) through\n`@healos/sdk`, so every command is documented, scoped, rate-limited and audited per API key, and it\nworks the same for people and for scripts or AI agents (`--json`). User docs: https://docs.healos.ai/cli\n\n## Install\n\n```bash\nnpm install -g @healos/cli     # or: bun add -g / pnpm add -g / yarn global add\nnpx @healos/cli@latest whoami  # or: bunx / pnpm dlx / yarn dlx, without installing\nhealos login\n```\n\nNode.js 18+ or Bun. The package is one bundled file (`dist/index.js`) with no runtime dependencies.\n\n## Run it from source\n\n```bash\nnpm run build -w @healos/sdk          # once, the CLI imports the built SDK\nbun apps/cli/src/index.ts --help      # from source\nnpm run build -w @healos/cli          # the npm bundle: apps/cli/dist/index.js (node)\nnpm run build:binary -w @healos/cli   # single binary for this machine: apps/cli/dist/healos\n```\n\n## Release\n\nBump `version` in `package.json` and `VERSION` in `src/main.ts` (a test keeps them equal), merge,\nthen push the tag `cli-v<version>` on a commit that is on staging or main. `.github/workflows/cli-publish.yml`\ntests, builds, smoke-tests the packed tarball and publishes to npm with Trusted Publishing (OIDC, no\nstored npm token). There is no provenance attestation: npm only accepts provenance from public\nrepositories. The trusted publisher is configured on npmjs.com for\n`medinoteorg/healos` and `cli-publish.yml`; renaming the workflow file breaks publishing.\n\n## Sign in\n\n```bash\nhealos login --env staging                         # opens the browser; approve, and the CLI saves a new read-only key\nhealos login --env staging --scopes all            # ask for every scope (writes too)\npbpaste | healos login --api-key - --env prod --profile prod   # a key from Settings → API keys, over stdin\nhealos whoami                                      # user, org, scopes and key expiry (GET /me)\nhealos logout                                      # removes the key from this machine\n```\n\n`--api-key hlsk_...` also works, but it prints a warning: a key in argv is kept in shell history and\nvisible to other users in `ps`. Prefer `--api-key -` (stdin) or `HEALOS_API_KEY`.\n\n`logout` does not revoke the key. Revoke it in Settings → API keys (it prints the link).\n\n**Browser login** (`healos login` without `--api-key`): the CLI listens on `127.0.0.1:<random port>`,\nopens `<web>/cli/authorize` (staging `https://beta.healos.ai`, prod `https://app.healos.ai`,\n`HEALOS_WEB_URL` to override, limited to those two hosts or localhost) and waits up to 5 minutes. On approval the API creates a\nuser-bound key labeled `CLI · <host> · <date>` (shown with a CLI badge in Settings → API keys) that\nexpires after 90 days, and hands it to the CLI through a 60-second code bound to `state` and PKCE.\nOnly org admins can approve (ext-api keys are org-wide). The key is **read-only by default** (every\n`*:read` scope); `--scopes all` asks for `*`, and `--scopes patients:read,notes:write` for a list. The\napproval page shows the scopes. Members get a 403 and should use a key an admin creates for them.\n\n- **Config:** `~/.config/healos/config.json` (or `$XDG_CONFIG_HOME/healos`). One entry per\n  profile: `{ \"baseUrl\": \"prod\" | \"staging\" | \"local\" | \"<url ending in /ext-api/v1>\", \"keyPrefix\" }`.\n  `--profile <name>` picks one; the default is `default`.\n- **Key storage:** the macOS Keychain (service `healos-cli`, account = profile) when the `security`\n  tool is available, else `~/.config/healos/credentials.json` with mode 0600.\n  `HEALOS_NO_KEYCHAIN=1` forces the file.\n- **Environment overrides:** `HEALOS_API_KEY` and `HEALOS_BASE_URL` take precedence over the profile\n  (for CI and agents). A key saved for a profile is only ever sent to the host it was saved for, so\n  `HEALOS_BASE_URL` can redirect `HEALOS_API_KEY` but not a stored key.\n- **Allowed hosts:** the key is only sent over https to `api.healos.ai` or `api-beta.healos.ai`. Any\n  other base URL (http, another host, credentials in the URL) is refused before a request is made.\n  `localhost`, `127.0.0.1` and `[::1]` (http allowed) need `--allow-insecure-localhost` on each command.\n- **File permissions:** `config.json` and `credentials.json` are written with mode 0600 in a 0700\n  directory. A `credentials.json` that other users can read or write is refused until you `chmod 600` it.\n\n## Commands\n\n| Command | ext-api |\n|---|---|\n| `patients list [--q] [--external-id]` | `GET /patients` |\n| `patients search <name>` | `GET /patients?q=` |\n| `patients get <id>` | `GET /patients/{id}` |\n| `patients create --name \\| --first-name --last-name [--dob --phone --email --mrn --gender --provider-id --external-id]` | `POST /patients` |\n| `patients update <id> [field flags, --pronouns, --notes, --consent/--no-consent]` | `PATCH /patients/{id}` |\n| `patients delete <id>` | `DELETE /patients/{id}` |\n| `documents list --patient <id> [--external-id]` | `GET /patients/{id}/documents` (extraction status) |\n| `documents upload <file> --patient <id> [--external-id]` | `POST /patients/{id}/documents` (.pdf .jpg .png .docx, up to 10 MB) |\n| `documents extract <documentId> --patient <id>` | `POST /patients/{id}/documents/{documentId}/extract` |\n| `documents delete <documentId> --patient <id>` | `DELETE /patients/{id}/documents/{documentId}` |\n| `sessions get <id>` | `GET /sessions/{id}` |\n| `sessions update <id> --patient <id>` | `PATCH /sessions/{id}` (assign patient) |\n| `notes list [--patient --session --template --created-by --type --from --to]` | `GET /notes` |\n| `notes get <id> [--include transcript,patient]` | `GET /notes/{id}` |\n| `notes export [same filters as list] [--format json\\|csv\\|ndjson] [--out file]` | `GET /notes/export` (json/csv cap at 1000 notes; ndjson has no cap; `--out` creates the file 0600) |\n| `notes create --text \"...\" \\| --text-file f \\| --audio f.wav [--patient --template --model] [--wait [--timeout 300]]` | `POST /notes/from-text`, `POST /notes/from-audio` (then `GET /sessions/{id}/notes` with `--wait`) |\n| `notes from-documents --patient <id> [--template --model] [--wait [--timeout 300]]` | `POST /patients/{id}/notes/from-documents` |\n| `notes regenerate <sessionId> [--template --model]` | `POST /sessions/{id}/notes/regenerate` |\n| `templates list [--type built_in\\|custom]` | `GET /templates` |\n| `templates get <id>` | pages `GET /templates` (there is no single-template endpoint) |\n| `providers list [--npi]`, `providers get <id>` | `GET /providers`, `GET /providers/{id}` |\n| `appointments list [--date --from --to --external-id]` | `GET /appointments` |\n| `appointments create --patient --type --visit-type --start --duration [--provider --notes --status --external-id]` | `POST /appointments` |\n| `appointments get <id>` | `GET /appointments/{id}` |\n| `appointments update <id> [--patient --provider --type --visit-type --start --duration --notes --status]` | `PATCH /appointments/{id}` |\n| `appointments delete <id>` | `DELETE /appointments/{id}` |\n| `eligibility check --payer --provider-name --npi (--patient \\| --member-id --first-name --last-name --dob)` | `POST /benefits/eligibility-checks` |\n| `eligibility list [--patient]`, `eligibility get <id>` | `GET /benefits/eligibility-checks[/{id}]` |\n| `benefits payers search <name>` | `GET /benefits/payers/search` |\n| `whoami` | `GET /me` |\n| `prior-auth list [--track --status --decision --updated-since]` | `GET /prior-auth/requests` |\n| `prior-auth get <id>`, `prior-auth events <id>` | `GET /prior-auth/requests/{id}[/events]` |\n| `prior-auth workflows` | `GET /prior-auth/workflows` |\n| `prior-auth check-status` | `POST /prior-auth/status-checks` (Availity, at most every 10 min) |\n| `ehr actions list [--ehr athena]` | `GET /ehr/actions` (scope `ehr:read`) |\n| `ehr actions get <ehr.action>` | `GET /ehr/actions/{actionName}`, e.g. `athena.search_patients` |\n| `ehr connections` | `GET /ehr/connections` (which EHRs your org has connected) |\n\nLists take `--page`, `--limit` and `--all` (every page, up to 100). Every command has `--help`.\n\nEvery operation in `apps/docs/openapi/ext-api-v1.json` (40 today) maps to a command in `src/coverage.ts`.\n`src/__tests__/coverage.test.ts` fails when the spec gains an operation with no command (or no\nreasoned entry in `NOT_IN_CLI`), and runs each mapped command against a fake fetch to check it sends\nthat request. Adding a route to the ext-api means adding the command, or the exception, in the same PR.\n\n`notes create` and `notes from-documents` return as soon as the note is queued; follow it with `healos sessions get <sessionId>`.\nWith `--wait` it polls `GET /sessions/{id}/notes` every 5 s until the note exists, then prints it\n(`--json`: `{ \"data\": <note> }`). After `--timeout` seconds (default 300) it exits `3`; the note may\nstill be generating.\n\n`whoami` needs only a valid key. Against an API that predates `GET /me` it falls back to\n`GET /templates?limit=1` and leaves user, org and scopes empty.\n\n## Output, exit codes, safety\n\n- Human tables by default; `--json` prints the raw API response (errors go to stderr as JSON too).\n- Exit codes: `0` ok, `1` usage (bad flags, cancelled), `2` API 4xx, `3` API 5xx or network,\n  `4` auth (no key, 401, 403).\n- Writes (POST/PATCH/DELETE) against prod ask for confirmation unless `--yes`. Deletes\n  (`patients delete`, `appointments delete`, `documents delete`) ask on every environment. Without a\n  terminal to ask on, they are refused unless `--yes` is passed.\n- `--dry-run` prints the method, URL and body and sends nothing (no key needed).\n\n## Development\n\n```bash\nnpm test -w @healos/cli        # bun test, with a temp HOME and a fake fetch\nnpm run typecheck -w @healos/cli\nnpx ultracite check apps/cli\n```\n\nCommands receive a `Runtime` (env, fetch, output, prompt), so tests run them end to end without the\nnetwork, the keychain or the real home directory.\n","readmeFilename":"README.md"}