{"_id":"@azx-pbc/helix-cli","_rev":"5-289c6e90576d86d5f1344f67877da301","name":"@azx-pbc/helix-cli","dist-tags":{"latest":"0.3.0"},"versions":{"0.0.0":{"name":"@azx-pbc/helix-cli","version":"0.0.0","license":"MIT","_id":"@azx-pbc/helix-cli@0.0.0","maintainers":[{"name":"kjw-azx","email":"kyle.wilcox@azx.io"},{"name":"rich-azx","email":"re@azx.io"}],"homepage":"https://github.com/AZX-PBC-OSS/helix#readme","bugs":{"url":"https://github.com/AZX-PBC-OSS/helix/issues"},"dist":{"shasum":"0bb20306d9c12fc97e551ec4a28973b12e773afc","tarball":"https://registry.npmjs.org/@azx-pbc/helix-cli/-/helix-cli-0.0.0.tgz","fileCount":2,"integrity":"sha512-Z6fPH+8yWnY/jaBb6n6OmUagBSu1jRHwooe4JAfVGmcyFdMxRVZoNn58vBFtV6gdmI1FtYqMy16bsBj7kFULug==","signatures":[{"sig":"MEUCIQClKmBbtPGZE3h0KgRBFFnPPvE469DtR4KkOWnyxGjFjgIgWLDi+faDoihObPHNRAGcXdcnCUEUxxcmgAt6vVVkEFo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":946},"_npmUser":{"name":"kjw-azx","email":"kyle.wilcox@azx.io"},"deprecated":"Placeholder — install 0.1.0 or later","repository":{"url":"git+https://github.com/AZX-PBC-OSS/helix.git","type":"git","directory":"packages/cli"},"_npmVersion":"11.12.1","description":"Placeholder to bootstrap trusted publishing — the Helix deploy CLI ships from 0.1.0 onward","directories":{},"_nodeVersion":"24.15.0","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/helix-cli_0.0.0_1785541419585_0.8873797048171848","host":"s3://npm-registry-packages-npm-production"}},"0.1.0":{"name":"@azx-pbc/helix-cli","version":"0.1.0","license":"MIT","_id":"@azx-pbc/helix-cli@0.1.0","maintainers":[{"name":"kjw-azx","email":"kyle.wilcox@azx.io"},{"name":"rich-azx","email":"re@azx.io"}],"homepage":"https://github.com/AZX-PBC-OSS/helix#readme","bugs":{"url":"https://github.com/AZX-PBC-OSS/helix/issues"},"bin":{"helix":"dist/helix.js"},"dist":{"shasum":"096a14b5a550b840e1693ddbd9e8a0d988095bc1","tarball":"https://registry.npmjs.org/@azx-pbc/helix-cli/-/helix-cli-0.1.0.tgz","fileCount":4,"integrity":"sha512-LB4+m3oF3wDUPAxXe4aCqC7zaP1YfG7/zXeFnc3F0zKdKzHK/7bmgM9dpB9Co+QxsdNBWRDh0qT/QJC96GOogA==","signatures":[{"sig":"MEUCIEGP/Cfyv3VfedDhRnMFvMiUbfA+0yw95bV+BAz4H4umAiEA3MeRTJDbcrDaSXy0gFlp6pKfQuy0HatifXCwe50DZts=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@azx-pbc%2fhelix-cli@0.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":52692},"type":"module","_from":"file:/home/runner/work/_temp/helix-cli.tgz","engines":{"node":">=24"},"scripts":{"build":"node scripts/build.mjs","helix":"tsx src/bin.ts","typecheck":"tsc"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:786e8214-04c2-41e2-8c34-4c16e73d6d99"}},"_resolved":"/home/runner/work/_temp/helix-cli.tgz","_integrity":"sha512-LB4+m3oF3wDUPAxXe4aCqC7zaP1YfG7/zXeFnc3F0zKdKzHK/7bmgM9dpB9Co+QxsdNBWRDh0qT/QJC96GOogA==","repository":{"url":"git+https://github.com/AZX-PBC-OSS/helix.git","type":"git","directory":"packages/cli"},"_npmVersion":"12.0.2","description":"Deploy CLI for Helix, the AZX App Platform","directories":{},"_nodeVersion":"24.18.0","dependencies":{"zod":"^4.4.3","archiver":"^8.0.0","openid-client":"^6.8.4"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","esbuild":"^0.28.0","typescript":"^6.0.3","@azx-pbc/shared":"0.0.0","@types/archiver":"^8.0.0","@azx-pbc/dev-idp":"0.0.0"},"_npmOperationalInternal":{"tmp":"tmp/helix-cli_0.1.0_1785543207392_0.6576955247884588","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@azx-pbc/helix-cli","version":"0.2.0","license":"MIT","_id":"@azx-pbc/helix-cli@0.2.0","maintainers":[{"name":"kjw-azx","email":"kyle.wilcox@azx.io"},{"name":"rich-azx","email":"re@azx.io"}],"homepage":"https://github.com/AZX-PBC-OSS/helix#readme","bugs":{"url":"https://github.com/AZX-PBC-OSS/helix/issues"},"bin":{"helix":"dist/helix.js"},"dist":{"shasum":"16a21e7a5ba02b88289dcfcd144d6d92d0a11ff6","tarball":"https://registry.npmjs.org/@azx-pbc/helix-cli/-/helix-cli-0.2.0.tgz","fileCount":4,"integrity":"sha512-XkPlQmY3Dkm/dxl4QZX6j397SClMp2/eNl6V6aXxX2BaAF6afJm+jYdxV/aEOYbbJSYt6tozEpRxAbg3KELR/g==","signatures":[{"sig":"MEQCICO29adhlCnuQVBI3zheqR0qhuRMZQZA/Up3hFGOSPXcAiB/QK+kUIC0kFe7/xPrFkcYj7AzgP47rWHyCWcjBSTOdA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@azx-pbc%2fhelix-cli@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":68485},"type":"module","_from":"file:/home/runner/work/_temp/helix-cli.tgz","engines":{"node":">=24"},"scripts":{"build":"node scripts/build.mjs","helix":"tsx src/bin.ts","typecheck":"tsc"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:786e8214-04c2-41e2-8c34-4c16e73d6d99"}},"_resolved":"/home/runner/work/_temp/helix-cli.tgz","_integrity":"sha512-XkPlQmY3Dkm/dxl4QZX6j397SClMp2/eNl6V6aXxX2BaAF6afJm+jYdxV/aEOYbbJSYt6tozEpRxAbg3KELR/g==","repository":{"url":"git+https://github.com/AZX-PBC-OSS/helix.git","type":"git","directory":"packages/cli"},"_npmVersion":"12.0.2","description":"Deploy CLI for Helix, the AZX App Platform","directories":{},"_nodeVersion":"24.18.0","dependencies":{"zod":"^4.4.3","archiver":"^8.0.0","openid-client":"^6.8.4"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","esbuild":"^0.28.0","typescript":"^6.0.3","@azx-pbc/shared":"0.0.0","@types/archiver":"^8.0.0","@azx-pbc/dev-idp":"0.0.0"},"_npmOperationalInternal":{"tmp":"tmp/helix-cli_0.2.0_1786642753557_0.39012962706965726","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"_id":"@azx-pbc/helix-cli@0.3.0","bin":{"helix":"dist/helix.js"},"bugs":{"url":"https://github.com/AZX-PBC-OSS/helix/issues"},"dist":{"shasum":"98a879de68e09a1909099061ae780cf1d23d967d","tarball":"https://registry.npmjs.org/@azx-pbc/helix-cli/-/helix-cli-0.3.0.tgz","fileCount":4,"integrity":"sha512-Fc00XYGQQE7wHdt/jSd2DIWjxKuAEiJgZoqvvTBfrtNVsLP7dl1YX33KYTygWKP+CoFoFg4zk11HhwgFxOoKig==","signatures":[{"sig":"MEQCIARGqhZZz9Wu5PsOWzeY3ihoqjEh4KaKpAE/YzDVAk0GAiAx+eoc2Y16lG74HgSKxKy1JDOKbuAAYjvK7nfF0LNdiA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC2wzFJ1NGmOWPBtI85oO+GUQFRbrWWsLJzIzGDLu/3twIhAPPzOUwWT/AP1DsxnbHkpxmj5rgkSmZBRVrwnfI3IobR"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@azx-pbc%2fhelix-cli@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":92656},"name":"@azx-pbc/helix-cli","type":"module","_from":"file:/home/runner/work/_temp/helix-cli.tgz","engines":{"node":"^22.12.0 || >=24.0.0"},"license":"MIT","scripts":{"build":"node scripts/build.mjs","helix":"tsx src/bin.ts","typecheck":"tsc"},"version":"0.3.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:786e8214-04c2-41e2-8c34-4c16e73d6d99"}},"homepage":"https://github.com/AZX-PBC-OSS/helix#readme","_resolved":"/home/runner/work/_temp/helix-cli.tgz","_integrity":"sha512-Fc00XYGQQE7wHdt/jSd2DIWjxKuAEiJgZoqvvTBfrtNVsLP7dl1YX33KYTygWKP+CoFoFg4zk11HhwgFxOoKig==","repository":{"url":"git+https://github.com/AZX-PBC-OSS/helix.git","type":"git","directory":"packages/cli"},"_npmVersion":"12.0.2","description":"Deploy CLI for Helix, the AZX App Platform","directories":{},"maintainers":[{"name":"kjw-azx","email":"kyle.wilcox@azx.io"},{"name":"rich-azx","email":"re@azx.io"}],"_nodeVersion":"24.20.0","dependencies":{"zod":"^4.4.3","archiver":"^8.0.0","openid-client":"^6.8.4"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"tsx":"^4.22.4","esbuild":"^0.28.2","typescript":"^6.0.3","@azx-pbc/shared":"0.0.0","@types/archiver":"^8.0.0","@azx-pbc/dev-idp":"0.0.0","@azx-pbc/deploy-skill":"0.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/helix-cli_0.3.0_1789500599930_0.7095947887368013"}}},"time":{"created":"2026-07-31T23:43:39.465Z","modified":"2026-09-15T19:30:00.374Z","0.0.0":"2026-07-31T23:43:39.734Z","0.1.0":"2026-08-01T00:13:27.554Z","0.2.0":"2026-08-13T17:39:13.768Z","0.3.0":"2026-09-15T19:30:00.060Z"},"bugs":{"url":"https://github.com/AZX-PBC-OSS/helix/issues"},"license":"MIT","homepage":"https://github.com/AZX-PBC-OSS/helix#readme","repository":{"url":"git+https://github.com/AZX-PBC-OSS/helix.git","type":"git","directory":"packages/cli"},"description":"Deploy CLI for Helix, the AZX App Platform","maintainers":[{"name":"kjw-azx","email":"kyle.wilcox@azx.io"},{"name":"rich-azx","email":"re@azx.io"}],"readme":"# `helix` — Helix deploy CLI\n\n`helix` is a **per-app CLI**, like `git` or `vercel`: you run it **from inside an\napp's directory**. It reads that app's `helix.json`, zips the build output, uploads\nit to the portal as a new version, and manages the live pointer.\n\n## The mental model\n\n```\nmy-app/\n  helix.json        ← helix reads this from the current working directory\n  dist/           ← the folder helix zips and uploads (configurable)\n```\n\nEverything keys off the **current working directory**. `cd` into your app, then\nrun `helix <command>`. There is no \"select an app\" flag you normally need — the app\nis wherever you're standing.\n\n## Configuration\n\nEach setting is resolved **flags → environment → `helix.json` → built-in default**\n(first match wins):\n\n| Setting    | Flag           | Env                | `helix.json` key | Default                    |\n| ---------- | -------------- | ------------------ | ---------------- | -------------------------- |\n| App slug   | `--slug`       | —                  | `slug`           | _(required)_               |\n| Portal URL | `--portal-url` | `HELIX_PORTAL_URL` | `portalUrl`      | `http://localhost:3001`    |\n| Build dir  | `--dir`        | —                  | `dir`            | `dist`                     |\n| Auth token | `--token`      | `HELIX_TOKEN`      | —                | _(`helix login` if unset)_ |\n\nA `helix.json` looks like:\n\n```json\n{ \"slug\": \"my-app\", \"dir\": \"dist\", \"portalUrl\": \"https://portal.example.com\" }\n```\n\n**`portalUrl` is the one you cannot leave to the default.** `http://localhost:3001`\nis right only for a portal running on your own machine; against a deployed one,\nset `portalUrl` (or `HELIX_PORTAL_URL`, or `--portal-url`) or every command —\nstarting with `helix login` — fails to connect to a portal that was never there.\nYour portal prints the exact file to copy under **How to develop → On your\nmachine**. The file is the form worth checking in: `login`, `create`, `deploy`\nand `promote` all resolve it the same way, so it is set once.\n\nThe repo's `examples/*/helix.json` deliberately omit it — a checked-in portal URL\nwould be wrong for every deployment but one — so to deploy an example, add\n`portalUrl` to its file or export `HELIX_PORTAL_URL` first.\n\n`--dir` is resolved **relative to the current working directory**, and so is\n`helix.json` — another reason to run `helix` from the app directory.\n\n## Commands\n\n```\nhelix login                                                   # browser sign-in (OIDC device flow)\nhelix logout                                                  # forget the cached tokens\nhelix whoami                                                  # who the portal thinks you are\nhelix create   [--display-name <name>] [--visibility <v>]   # register the app\nhelix deploy   [--dir <dir>] [--bundle <zip>] [--promote]    # upload a version\nhelix versions                                               # list versions\nhelix promote  <number>                                      # make a version live\nhelix rollback [number]                                      # revert the live pointer\nhelix skill    [--path <file>]                               # write this deployment's agent skill to disk\n```\n\n`deploy` uploads the bundle as a **preview**; `--promote` flips it live in the\nsame step (architecture §5.1). `visibility` is `internal | group:<id>[,<id>…] | password\n| public`.\n\n`helix skill` fetches this deployment's rendered agent skill (`GET /api/v1/skill`,\nADR-0036) — the same document the portal's **How to develop** modal hands out, with\nthis deployment's hosts, servable models, and approval baselines already substituted\nin. It needs no app slug or `helix.json`, only a portal URL and a token. Defaults to\n`./SKILL.md`; `--path .claude/skills/helix/SKILL.md` drops it where a Claude Code\nagent reads it off disk.\n\n> **Breaking in 0.2.0:** the `private` visibility mode was renamed to `internal`.\n> It never checked _which_ user signed in, only that someone had. Passing the old\n> value now **errors** rather than mapping to the new one, deliberately: the name\n> is reserved for a future owner-only mode, so a silent alias would come to mean\n> the opposite of what it says. Update scripts to use `internal`.\n\n## Authentication (M3)\n\nTwo paths, in precedence order:\n\n1. **Static token** — `HELIX_TOKEN` / `--token`. Sends the value as a bearer\n   token verbatim. This is the CI/scripts path, and also how the portal's\n   dev-token stub keeps working (`HELIX_TOKEN=$PORTAL_DEV_TOKEN`). It is never\n   accepted by a production portal.\n2. **`helix login`** — the OIDC device flow. The CLI asks the portal\n   (`GET /api/v1/auth/config`) which issuer to use (the local dev IdP on\n   `:3002` in dev; Entra later), prints a verification URL + code, and polls\n   while you approve in a browser. Tokens land in\n   `~/.config/helix/tokens.json` (mode 0600, keyed by issuer) and are silently\n   renewed with the refresh token. On 401, nothing is auto-launched — agents\n   run headless; the error says to run `helix login`.\n\n## Running it\n\n### Installed from npm\n\n```bash\nnpm i -g @azx-pbc/helix-cli\ncd my-app\nexport HELIX_TOKEN=\"…\"\nhelix deploy --promote\n```\n\nNeeds **Node 22.12+** (or 24+). The engines range and the bundle's esbuild\ntarget move together (see `scripts/build.mjs`), so the declared floor is real:\nolder runtimes may not merely warn, they may fail to parse it.\n\n`0.0.0` is a deprecated placeholder that exists only because npm requires a\npackage to exist before a trusted publisher can be attached to it. Every real\nversion is `0.1.0` or later and carries a provenance attestation. npm filters\nregistry versions by `engines` against the running runtime, so before 0.3.0\ndeclared 22.12+ an install on Node 22 fell all the way back to that\nplaceholder — the reason a supported-looking Node could yield a\nnon-functional package.\n\n### From this monorepo today\n\nBuild the real binary once and link it; from then on `helix` behaves exactly as\nit will when installed from npm:\n\n```bash\npnpm --filter @azx-pbc/helix-cli build\nnpm link ./packages/cli          # puts `helix` on your PATH\n\ncd examples/hello-world\nexport HELIX_TOKEN=\"$PORTAL_DEV_TOKEN\"          # the portal's dev-token stub\nhelix create --display-name \"Hello World\"\nhelix deploy --promote\nhelix versions\n```\n\nRun it **from your app directory** so `helix.json` and a relative `--dir`\nresolve against the app, not the repo.\n\nWithout linking, `node packages/cli/dist/helix.js <cmd>` works the same way. To\nskip the build during CLI development, `node --import tsx packages/cli/src/bin.ts <cmd>`\nruns straight from source.\n\n## About `pnpm --filter @azx-pbc/helix-cli helix -- <cmd>`\n\nThis form runs the CLI's dev script through pnpm. It works for flags now (the\nCLI strips the `--` that pnpm forwards — see `src/args.ts`), **but pnpm runs the\nscript in `packages/cli`, not your app**. So it will not find your app's\n`helix.json`, and a relative `--dir` resolves against `packages/cli`. Use it only\nfor `--help` or with explicit `--slug` + an absolute `--dir`:\n\n```bash\npnpm --filter @azx-pbc/helix-cli helix -- deploy --slug my-app \\\n  --dir /abs/path/to/my-app/dist --promote\n```\n\nFor real deploys, prefer running from the app directory (`npm link`, above).\n\n## Packaging\n\nThis is the **only package in the repo that emits JS**. Everything else runs\nfrom TypeScript source via `tsx` and is `private: true`; a published CLI can't.\n\n`pnpm build` runs `scripts/build.mjs`, which esbuild-bundles `src/bin.ts` into a\nsingle `dist/helix.js` with a `#!/usr/bin/env node` banner. Two things make that\nthe right shape rather than a `tsc --outDir`:\n\n- **`@azx-pbc/shared` gets inlined.** It's a private `workspace:*` package whose\n  `exports` point straight at `./src/index.ts`, and the edge/portal/egress all\n  consume it as raw TS deliberately. Publishing must not force a build+dist+d.ts\n  onto `shared` for one consumer, and must not ship a manifest depending on\n  `@azx-pbc/shared@0.0.0` — a version no registry has. Bundling solves both, so\n  `shared` is a **devDependency** here, not a dependency.\n- **No tsx at runtime.** The `bin` used to point at `src/bin.ts` behind a\n  `#!/usr/bin/env -S tsx` shebang while `tsx` was only a devDependency, so a real\n  global install would have been broken on arrival.\n\n`archiver`, `openid-client`, and `zod` stay external and install from the\nregistry — bundling archiver's transitive tree buys nothing.\n\nCI's `package` job builds, runs `pnpm pack`, asserts the tarball ships `dist/`\nand no `src/`, then globally installs the tarball in a clean prefix **with tsx\noff `PATH`** and runs `helix --help`. That last step is what actually proves\npublishability; the unit tests never touch the bundle. It runs on every PR, so\na broken artifact fails before a release is ever cut.\n\n## Releasing\n\nReleases are cut by tag and published by\n[`.github/workflows/release-cli.yml`](../../.github/workflows/release-cli.yml):\n\n```bash\ncd packages/cli\nnpm version patch                       # or minor — edits package.json only\ncd ../.. && git commit -am \"release(cli): v0.1.1\"\ngit tag cli-v0.1.1 && git push && git push --tags\n```\n\nThe workflow re-runs the whole build → pack → assert → global-install sequence\nagainst the tag, refuses to publish if the tag and `package.json` disagree, and\nthen publishes with provenance.\n\nThree things to know before touching it:\n\n- **The tag prefix is `cli-v`, not `v`.** `v*` is the platform's version and\n  already drives the container-image builds in `ci.yml`. The CLI versions\n  independently.\n- **There is no `NPM_TOKEN`.** Auth is npm trusted publishing (OIDC): npmjs.com\n  has a registered trust relationship with `AZX-PBC-OSS/helix` +\n  `release-cli.yml`. Renaming or moving that workflow file breaks publishing\n  until the registration is updated — that narrowness is the point.\n- **It packs with pnpm and publishes with npm.** Only pnpm rewrites `catalog:`\n  and `workspace:*` into real ranges; npm is the client whose OIDC support is\n  documented and reliable. Each does the half it's good at.\n\nSee [ADR-0032](../../docs/adr/0032-cli-naming-and-distribution.md) for why\npublic npm rather than GitHub Packages.\n","readmeFilename":"README.md"}