@m8t-stack/cli 0.0.1-bootstrap
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.
- package/LICENSE +21 -0
- package/README.md +213 -0
- package/dist/cli.js +7528 -0
- package/dist/cli.js.map +1 -0
- package/package.json +63 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Or Keren (m8t)
|
|
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
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# `@m8t-stack/cli`
|
|
2
|
+
|
|
3
|
+
The `m8t` CLI for managing m8t-stack deployments.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# npm (any OS with Node 20+)
|
|
9
|
+
npm install -g @m8t-stack/cli
|
|
10
|
+
|
|
11
|
+
# Homebrew (macOS / Linux)
|
|
12
|
+
brew install m8t-run/tap/m8t
|
|
13
|
+
|
|
14
|
+
# Scoop (Windows)
|
|
15
|
+
scoop bucket add m8t https://github.com/m8t-run/scoop-bucket
|
|
16
|
+
scoop install m8t
|
|
17
|
+
|
|
18
|
+
# Verify
|
|
19
|
+
m8t version
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
The CLI bundles the shared workspace types into a single `dist/cli.js`, so the
|
|
23
|
+
npm install is self-contained (only the external runtime deps resolve from npm).
|
|
24
|
+
Publishing is automated by `.github/workflows/release-cli.yml` (OIDC trusted
|
|
25
|
+
publishing); see `publish/npm-trusted-publishing-setup.md`.
|
|
26
|
+
|
|
27
|
+
### Build from source (contributors)
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pnpm --filter "@m8t-stack/cli" build # produces dist/cli.js with shebang
|
|
31
|
+
cd apps/cli && pnpm pack # produces m8t-stack-cli-<version>.tgz
|
|
32
|
+
npm install -g ./m8t-stack-cli-*.tgz
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
m8t version # CLI version
|
|
39
|
+
m8t whoami # Identity + which gateway you're talking to (probes the backend)
|
|
40
|
+
m8t status # Full local snapshot: az identity, config.yaml, gateway cache, azd mode
|
|
41
|
+
m8t doctor # Health checks (az · config · tenant align · gateway · Foundry data-plane · model-quota) + fixes
|
|
42
|
+
m8t doctor --agent <name> # + delivery-grant check: verifies the agent's MI holds Key Vault Secrets User
|
|
43
|
+
m8t open [webapp|foundry|portal] # Open the deployed app / Foundry portal / resource group in a browser
|
|
44
|
+
|
|
45
|
+
# Local config (~/.m8t-stack)
|
|
46
|
+
m8t config show # config.yaml (tenant/client/project) + the cached gateway
|
|
47
|
+
m8t config set <key> <value> # set tenantId | clientId | projectEndpoint
|
|
48
|
+
m8t config reset # clear the gateway discovery cache
|
|
49
|
+
m8t switch --subscription <id|name> # re-point local config at another deployment (snapshots first)
|
|
50
|
+
m8t switch <profile> # restore a saved profile; m8t switch --list
|
|
51
|
+
|
|
52
|
+
# Team management
|
|
53
|
+
m8t team add <handle> --display "<name>" [--telegram <id>] [--slack <id>] [--teams <upn>]
|
|
54
|
+
m8t team list
|
|
55
|
+
m8t team show <handle>
|
|
56
|
+
m8t team add-identity <handle> [--telegram <id>] [--slack <id>] [--teams <upn>]
|
|
57
|
+
m8t team remove-identity <handle> --telegram|--slack|--teams
|
|
58
|
+
m8t team remove <handle>
|
|
59
|
+
|
|
60
|
+
# Deploy / update the gateway stack (replaces the old deploy/setup.mjs)
|
|
61
|
+
m8t deploy [--client-id <appId>] [--image-ref <ref>] [--location <region>] [--resource-group <name>]
|
|
62
|
+
|
|
63
|
+
# Brain management
|
|
64
|
+
m8t brain link <name> --repo <owner>/<repo> [--persona <path>] [--allow-non-reasoning]
|
|
65
|
+
# --persona: override the recorded persona file (or use when no local agent yaml exists)
|
|
66
|
+
# --allow-non-reasoning: suppress the reasoning-model warning
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### `--subscription <id>` flag
|
|
70
|
+
|
|
71
|
+
Available on all gateway-using commands (`whoami`, `config show`, `config reset`,
|
|
72
|
+
`team add`, `team list`, `team show`, `team add-identity`, `team remove-identity`,
|
|
73
|
+
`team remove`, `bind add`, `bind list`, `bind show`, `bind remove`, `bind cleanup`).
|
|
74
|
+
Pins gateway discovery to the named subscription, bypassing the active `az`
|
|
75
|
+
subscription. Useful when you manage multiple m8t-stack deployments across
|
|
76
|
+
subscriptions or when your shell's active subscription differs from the deployment
|
|
77
|
+
target.
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
m8t team list --subscription <subscription-id-or-name>
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Local context & config — `status` / `doctor` / `switch`
|
|
84
|
+
|
|
85
|
+
The CLI reads two local files under `~/.m8t-stack/`: **`config.yaml`** (your `tenantId`, `clientId`, and Foundry `projectEndpoint` — used by the web app + architect) and **`cli-config.yaml`** (the auto-discovered gateway URL cache).
|
|
86
|
+
|
|
87
|
+
- **`m8t status`** — a read-only snapshot of everything local: your signed-in `az` identity + active subscription/tenant, `config.yaml` (tenant / client / project), the gateway cache, the `azd` auth mode, and whether your `az` tenant matches `config.yaml` (tenant alignment). `--output json` for scripting.
|
|
88
|
+
- **`m8t doctor`** — runs health checks and prints a fix for each failure; exits non-zero if any check FAILs. Checks: `az` signed in · `config.yaml` valid · tenant alignment · gateway reachable (`/api/me`) · **Foundry data-plane reachable** (a 401/403 prints the exact `az role assignment create … "Cognitive Services User"` command) · **model-quota check** (warns for any deployed model with 0 TPM quota in the region). Results stream as each check runs. Pass `--agent <name>` to add a targeted delivery-grant check: reads the agent's deployed env and verifies its managed identity holds `Key Vault Secrets User` on the configured vault.
|
|
89
|
+
- **`m8t config set <key> <value>`** — write `tenantId`, `clientId`, or `projectEndpoint` into `config.yaml` (validated). `m8t config show` now displays `config.yaml` alongside the gateway cache.
|
|
90
|
+
- **`m8t switch`** — re-point your local config at another deployment in one step. `--subscription <id|name>` discovers the gateway there and derives every `config.yaml` value from its container env (zero manual IDs); `<profile>` restores a saved profile; `--list` lists profiles. Every switch **snapshots the outgoing config to a profile first** (label it with `--as <name>`), so it's reversible — e.g. `m8t switch --subscription <new> --as work`, then later `m8t switch personal`.
|
|
91
|
+
|
|
92
|
+
## Open in the browser — `m8t open`
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
m8t open # the deployed webapp (gateway URL) — default
|
|
96
|
+
m8t open foundry # the Microsoft Foundry portal (ai.azure.com)
|
|
97
|
+
m8t open portal # the resource group in the Azure portal
|
|
98
|
+
m8t open --print # print the URL instead of launching a browser (pipe-friendly)
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
## Deploy / update the gateway — `m8t deploy`
|
|
102
|
+
|
|
103
|
+
Provisions (or updates) the gateway/webapp stack via Bicep — the successor to the old `node deploy/setup.mjs`. See [`deploy/README.md`](../../deploy/README.md) for the full flow.
|
|
104
|
+
|
|
105
|
+
```bash
|
|
106
|
+
# Bring-your-own app registration (required if you can't create Entra app regs, e.g. a directory guest):
|
|
107
|
+
m8t deploy --client-id <appId> --image-ref <acr-or-ghcr-ref> --location <region>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Key flags: `--client-id <appId>` (reuse an existing app reg + skip **all** Microsoft Graph writes), `--image-ref <ref>` (full image ref; default `ghcr.io/m8t-run/m8t:latest` — pass an `*.azurecr.io/...` ref for ACR images), `--resource-group` (default `rg-m8t-stack`), `--location`, `--suffix`, `--foundry-endpoint`, `--foundry-resource-id`.
|
|
111
|
+
|
|
112
|
+
> ⚠️ `m8t deploy` is **declarative** — it makes the live stack match the Bicep template. If a deployment was hand-modified after provisioning (e.g. switched to a private-ACR image with a UserAssigned pull identity), re-running the bicep can revert those changes. **Preview with `az deployment group create --what-if` before applying against a live stack.**
|
|
113
|
+
|
|
114
|
+
## Binding management — `m8t bind`
|
|
115
|
+
|
|
116
|
+
Wire channel bots (Telegram, Slack, Teams) to Foundry workers. F4 ships
|
|
117
|
+
the management API + CLI scaffolding; the actual adapters (which deliver
|
|
118
|
+
inbound messages from each channel) ship in later features.
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
# Create a binding (requires the channel adapter — Telegram ships in F6)
|
|
122
|
+
m8t bind add telegram \
|
|
123
|
+
--worker cmo \
|
|
124
|
+
--bot-token <from-botfather> \
|
|
125
|
+
--slug cmo-tg \
|
|
126
|
+
--bot-username "@startup_cmo_bot"
|
|
127
|
+
|
|
128
|
+
# List all bindings, optionally filtered
|
|
129
|
+
m8t bind list
|
|
130
|
+
m8t bind list --channel telegram
|
|
131
|
+
m8t bind list --status orphaned
|
|
132
|
+
|
|
133
|
+
# Inspect one binding (token NEVER returned — only the KV URI)
|
|
134
|
+
m8t bind show cmo-tg
|
|
135
|
+
|
|
136
|
+
# Remove a binding (cascade: unregister webhook → KV → conversations → row)
|
|
137
|
+
m8t bind remove cmo-tg
|
|
138
|
+
m8t bind remove cmo-tg --yes # skip confirm
|
|
139
|
+
|
|
140
|
+
# Orphan-only cleanup (refuses to act on active bindings)
|
|
141
|
+
m8t bind cleanup <bindingId>
|
|
142
|
+
m8t bind cleanup --all-orphaned
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
> `--worker` is the **case-sensitive, lowercase** Foundry agent name as deployed (e.g. `cmo`). A wrong name isn't rejected at bind time — it surfaces later as an orphaned binding on the first message.
|
|
146
|
+
|
|
147
|
+
### Pre-F6 behavior
|
|
148
|
+
|
|
149
|
+
`m8t bind add telegram ...` currently fails with:
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
error: no adapter for channel 'telegram'. This is expected for F4 alone;
|
|
153
|
+
the channel-specific adapter ships in a later feature.
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
This is correct. F6 (Telegram adapter) will register the adapter at
|
|
157
|
+
startup and unlock the create flow.
|
|
158
|
+
|
|
159
|
+
### Cascade-delete idempotency
|
|
160
|
+
|
|
161
|
+
If `m8t bind remove` fails mid-cascade, it prints which steps completed
|
|
162
|
+
and which step failed, and recommends re-running the command. Each step
|
|
163
|
+
is independently idempotent — a re-run resumes safely from the failure
|
|
164
|
+
point.
|
|
165
|
+
|
|
166
|
+
## Output modes
|
|
167
|
+
|
|
168
|
+
Pretty table or key-value block by default; pipe or redirect, and the CLI auto-switches to JSON:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
m8t team list # pretty
|
|
172
|
+
m8t team list | jq # auto-JSON
|
|
173
|
+
m8t team list --output json # explicit JSON
|
|
174
|
+
m8t team list --output pretty # force pretty even on pipe
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## Exit codes
|
|
178
|
+
|
|
179
|
+
- `0` success
|
|
180
|
+
- `1` any failure (auth, network, validation, backend)
|
|
181
|
+
- `2` user-cancelled
|
|
182
|
+
|
|
183
|
+
Granular error info in stderr's structured JSON envelope.
|
|
184
|
+
|
|
185
|
+
## Prerequisites
|
|
186
|
+
|
|
187
|
+
- Node 20+
|
|
188
|
+
- `az login` against the customer's Azure tenant. CLI uses `DefaultAzureCredential` — no per-admin pre-registration.
|
|
189
|
+
|
|
190
|
+
## Troubleshooting
|
|
191
|
+
|
|
192
|
+
### `error: You are not signed in to Azure.`
|
|
193
|
+
Run `az login` first. The CLI uses your active `az` session to acquire a token for the gateway.
|
|
194
|
+
|
|
195
|
+
### `error: No m8t-stack deployment found in subscription <name>.`
|
|
196
|
+
The deployment is in a different subscription. Switch with:
|
|
197
|
+
```bash
|
|
198
|
+
az account set --subscription <other-sub>
|
|
199
|
+
m8t config reset
|
|
200
|
+
m8t team list
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### `error: Multiple m8t-stack deployments found ...`
|
|
204
|
+
You have more than one gateway in this subscription. The CLI prompts you to pick one when running interactively (e.g. `m8t whoami`). The choice is cached at `~/.m8t-stack/cli-config.yaml`. Or pass `--subscription <id>` to target a specific subscription and skip the picker entirely.
|
|
205
|
+
|
|
206
|
+
### `(gateway is starting up...)`
|
|
207
|
+
The deployed gateway is configured with `min-replicas=0` (scale-to-zero). First request after idle pays ~10–20s cold start. The CLI retries once on 502/503/504.
|
|
208
|
+
|
|
209
|
+
### `error: partial write — <channel-A> succeeded, <channel-B> failed.`
|
|
210
|
+
A multi-identity `m8t team add` partially succeeded. Run `m8t team show <handle>` to verify the current state, then `m8t team add-identity <handle> --<channel-B> <id>` to fill in the missing identity.
|
|
211
|
+
|
|
212
|
+
### CLI version vs gateway version drift
|
|
213
|
+
The CLI and the gateway share `@m8t-stack/api-contract` types at compile time (the CLI bundles them at build). If the gateway is on an older version and returns a response in an unknown shape, the CLI surfaces `BAD_RESPONSE` with a "this may be a gateway version mismatch" hint.
|