@azx-pbc/helix-cli 0.0.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (4) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +186 -7
  3. package/dist/helix.js +1553 -0
  4. package/package.json +32 -6
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AZX, PBC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,14 +1,193 @@
1
- # `@azx-pbc/helix-cli` — 0.0.0 placeholder
1
+ # `helix` — Helix deploy CLI
2
2
 
3
- This version is an empty placeholder. It exists only because npm requires a
4
- package to exist before a [trusted publisher](https://docs.npmjs.com/trusted-publishers/)
5
- (OIDC) can be attached to it, and we wanted every real release to carry a
6
- provenance attestation rather than starting with a hand-published one.
3
+ `helix` is a **per-app CLI**, like `git` or `vercel`: you run it **from inside an
4
+ app's directory**. It reads that app's `helix.json`, zips the build output, uploads
5
+ it to the portal as a new version, and manages the live pointer.
7
6
 
8
- **Install `0.1.0` or later** — that is the actual CLI, published from CI:
7
+ ## The mental model
9
8
 
10
9
  ```
10
+ my-app/
11
+ helix.json ← helix reads this from the current working directory
12
+ dist/ ← the folder helix zips and uploads (configurable)
13
+ ```
14
+
15
+ Everything keys off the **current working directory**. `cd` into your app, then
16
+ run `helix <command>`. There is no "select an app" flag you normally need — the app
17
+ is wherever you're standing.
18
+
19
+ ## Configuration
20
+
21
+ Each setting is resolved **flags → environment → `helix.json` → built-in default**
22
+ (first match wins):
23
+
24
+ | Setting | Flag | Env | `helix.json` key | Default |
25
+ | ---------- | -------------- | ------------------ | ---------------- | -------------------------- |
26
+ | App slug | `--slug` | — | `slug` | _(required)_ |
27
+ | Portal URL | `--portal-url` | `HELIX_PORTAL_URL` | `portalUrl` | `http://localhost:3001` |
28
+ | Build dir | `--dir` | — | `dir` | `dist` |
29
+ | Auth token | `--token` | `HELIX_TOKEN` | — | _(`helix login` if unset)_ |
30
+
31
+ A minimal `helix.json` is just:
32
+
33
+ ```json
34
+ { "slug": "my-app" }
35
+ ```
36
+
37
+ `--dir` is resolved **relative to the current working directory**, and so is
38
+ `helix.json` — another reason to run `helix` from the app directory.
39
+
40
+ ## Commands
41
+
42
+ ```
43
+ helix login # browser sign-in (OIDC device flow)
44
+ helix logout # forget the cached tokens
45
+ helix whoami # who the portal thinks you are
46
+ helix create [--display-name <name>] [--visibility <v>] # register the app
47
+ helix deploy [--dir <dir>] [--bundle <zip>] [--promote] # upload a version
48
+ helix versions # list versions
49
+ helix promote <number> # make a version live
50
+ helix rollback [number] # revert the live pointer
51
+ ```
52
+
53
+ `deploy` uploads the bundle as a **preview**; `--promote` flips it live in the
54
+ same step (architecture §5.1). `visibility` is `internal | group:<id> | password
55
+ | public`.
56
+
57
+ > **Breaking in 0.2.0:** the `private` visibility mode was renamed to `internal`.
58
+ > It never checked _which_ user signed in, only that someone had. Passing the old
59
+ > value now **errors** rather than mapping to the new one, deliberately: the name
60
+ > is reserved for a future owner-only mode, so a silent alias would come to mean
61
+ > the opposite of what it says. Update scripts to use `internal`.
62
+
63
+ ## Authentication (M3)
64
+
65
+ Two paths, in precedence order:
66
+
67
+ 1. **Static token** — `HELIX_TOKEN` / `--token`. Sends the value as a bearer
68
+ token verbatim. This is the CI/scripts path, and also how the portal's
69
+ dev-token stub keeps working (`HELIX_TOKEN=$PORTAL_DEV_TOKEN`). It is never
70
+ accepted by a production portal.
71
+ 2. **`helix login`** — the OIDC device flow. The CLI asks the portal
72
+ (`GET /api/v1/auth/config`) which issuer to use (the local dev IdP on
73
+ `:3002` in dev; Entra later), prints a verification URL + code, and polls
74
+ while you approve in a browser. Tokens land in
75
+ `~/.config/helix/tokens.json` (mode 0600, keyed by issuer) and are silently
76
+ renewed with the refresh token. On 401, nothing is auto-launched — agents
77
+ run headless; the error says to run `helix login`.
78
+
79
+ ## Running it
80
+
81
+ ### Installed from npm
82
+
83
+ ```bash
11
84
  npm i -g @azx-pbc/helix-cli
85
+ cd my-app
86
+ export HELIX_TOKEN="…"
87
+ helix deploy --promote
88
+ ```
89
+
90
+ Needs **Node 24+** — the bundle is emitted at that target, so older runtimes
91
+ may not merely warn, they may fail to parse it.
92
+
93
+ `0.0.0` is a deprecated placeholder that exists only because npm requires a
94
+ package to exist before a trusted publisher can be attached to it. Every real
95
+ version is `0.1.0` or later and carries a provenance attestation.
96
+
97
+ ### From this monorepo today
98
+
99
+ Build the real binary once and link it; from then on `helix` behaves exactly as
100
+ it will when installed from npm:
101
+
102
+ ```bash
103
+ pnpm --filter @azx-pbc/helix-cli build
104
+ npm link ./packages/cli # puts `helix` on your PATH
105
+
106
+ cd examples/hello-world
107
+ export HELIX_TOKEN="$PORTAL_DEV_TOKEN" # the portal's dev-token stub
108
+ helix create --display-name "Hello World"
109
+ helix deploy --promote
110
+ helix versions
111
+ ```
112
+
113
+ Run it **from your app directory** so `helix.json` and a relative `--dir`
114
+ resolve against the app, not the repo.
115
+
116
+ Without linking, `node packages/cli/dist/helix.js <cmd>` works the same way. To
117
+ skip the build during CLI development, `node --import tsx packages/cli/src/bin.ts <cmd>`
118
+ runs straight from source.
119
+
120
+ ## About `pnpm --filter @azx-pbc/helix-cli helix -- <cmd>`
121
+
122
+ This form runs the CLI's dev script through pnpm. It works for flags now (the
123
+ CLI strips the `--` that pnpm forwards — see `src/args.ts`), **but pnpm runs the
124
+ script in `packages/cli`, not your app**. So it will not find your app's
125
+ `helix.json`, and a relative `--dir` resolves against `packages/cli`. Use it only
126
+ for `--help` or with explicit `--slug` + an absolute `--dir`:
127
+
128
+ ```bash
129
+ pnpm --filter @azx-pbc/helix-cli helix -- deploy --slug my-app \
130
+ --dir /abs/path/to/my-app/dist --promote
131
+ ```
132
+
133
+ For real deploys, prefer running from the app directory (`npm link`, above).
134
+
135
+ ## Packaging
136
+
137
+ This is the **only package in the repo that emits JS**. Everything else runs
138
+ from TypeScript source via `tsx` and is `private: true`; a published CLI can't.
139
+
140
+ `pnpm build` runs `scripts/build.mjs`, which esbuild-bundles `src/bin.ts` into a
141
+ single `dist/helix.js` with a `#!/usr/bin/env node` banner. Two things make that
142
+ the right shape rather than a `tsc --outDir`:
143
+
144
+ - **`@azx-pbc/shared` gets inlined.** It's a private `workspace:*` package whose
145
+ `exports` point straight at `./src/index.ts`, and the edge/portal/egress all
146
+ consume it as raw TS deliberately. Publishing must not force a build+dist+d.ts
147
+ onto `shared` for one consumer, and must not ship a manifest depending on
148
+ `@azx-pbc/shared@0.0.0` — a version no registry has. Bundling solves both, so
149
+ `shared` is a **devDependency** here, not a dependency.
150
+ - **No tsx at runtime.** The `bin` used to point at `src/bin.ts` behind a
151
+ `#!/usr/bin/env -S tsx` shebang while `tsx` was only a devDependency, so a real
152
+ global install would have been broken on arrival.
153
+
154
+ `archiver`, `openid-client`, and `zod` stay external and install from the
155
+ registry — bundling archiver's transitive tree buys nothing.
156
+
157
+ CI's `package` job builds, runs `pnpm pack`, asserts the tarball ships `dist/`
158
+ and no `src/`, then globally installs the tarball in a clean prefix **with tsx
159
+ off `PATH`** and runs `helix --help`. That last step is what actually proves
160
+ publishability; the unit tests never touch the bundle. It runs on every PR, so
161
+ a broken artifact fails before a release is ever cut.
162
+
163
+ ## Releasing
164
+
165
+ Releases are cut by tag and published by
166
+ [`.github/workflows/release-cli.yml`](../../.github/workflows/release-cli.yml):
167
+
168
+ ```bash
169
+ cd packages/cli
170
+ npm version patch # or minor — edits package.json only
171
+ cd ../.. && git commit -am "release(cli): v0.1.1"
172
+ git tag cli-v0.1.1 && git push && git push --tags
12
173
  ```
13
174
 
14
- Source: https://github.com/AZX-PBC-OSS/helix/tree/main/packages/cli
175
+ The workflow re-runs the whole build → pack → assert → global-install sequence
176
+ against the tag, refuses to publish if the tag and `package.json` disagree, and
177
+ then publishes with provenance.
178
+
179
+ Three things to know before touching it:
180
+
181
+ - **The tag prefix is `cli-v`, not `v`.** `v*` is the platform's version and
182
+ already drives the container-image builds in `ci.yml`. The CLI versions
183
+ independently.
184
+ - **There is no `NPM_TOKEN`.** Auth is npm trusted publishing (OIDC): npmjs.com
185
+ has a registered trust relationship with `AZX-PBC-OSS/helix` +
186
+ `release-cli.yml`. Renaming or moving that workflow file breaks publishing
187
+ until the registration is updated — that narrowness is the point.
188
+ - **It packs with pnpm and publishes with npm.** Only pnpm rewrites `catalog:`
189
+ and `workspace:*` into real ranges; npm is the client whose OIDC support is
190
+ documented and reliable. Each does the half it's good at.
191
+
192
+ See [ADR-0032](../../docs/adr/0032-cli-naming-and-distribution.md) for why
193
+ public npm rather than GitHub Packages.