Skip to content

Commit f8508b9

Browse files
committed
feat(computers): expose viewer password commands
1 parent 8fcd1f6 commit f8508b9

5 files changed

Lines changed: 120 additions & 3 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22

33
All notable changes to @miosa/cli will be documented in this file.
44

5+
## [1.0.82] - 2026-06-22
6+
7+
### Added
8+
- `miosa computers viewer-password <computer-id>` shows external desktop viewer-password status.
9+
- `miosa computers rotate-viewer-password <computer-id>` rotates and prints the raw external desktop viewer password once.
10+
511
## [1.0.54] - 2026-06-10
612

713
### Changed

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,25 @@ miosa ssh my-mac
364364
miosa ssh my-mac --cmd "ls -la"
365365
```
366366

367+
### `miosa computers viewer-password <computer-id> [--json]`
368+
369+
Show whether a Computer's raw external desktop viewer password is set.
370+
Authenticated MIOSA platform desktop links do not need this password.
371+
372+
```bash
373+
miosa computers viewer-password comp_123
374+
```
375+
376+
### `miosa computers rotate-viewer-password <computer-id> [--json]`
377+
378+
Rotate and print the raw external desktop viewer password once. Use this when
379+
sharing a direct `*.computer.miosa.ai/desktop/index.html` viewer link outside
380+
the authenticated platform UI.
381+
382+
```bash
383+
miosa computers rotate-viewer-password comp_123
384+
```
385+
367386
### `miosa exec <host> <cmd> [args...] [--cwd dir] [--env KEY=VAL] [--timeout 30s]`
368387

369388
Run a command non-interactively and stream output. Exits with the remote exit code.

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@miosa/cli",
3-
"version": "1.0.81",
3+
"version": "1.0.82",
44
"description": "MIOSA platform CLI — projects, sandboxes, deploys, databases, more",
55
"type": "module",
66
"bin": {

src/commands/computers.ts

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,98 @@ export function register(program: Command): void {
243243
}),
244244
);
245245

246+
computers!
247+
.command("viewer-password <computer-id>")
248+
.alias("password")
249+
.description("Show external desktop viewer-password status")
250+
.option("--json", "Output as JSON")
251+
.action((id: string, opts: JsonOptions) =>
252+
runAction(async () => {
253+
const raw = unwrap<Record<string, unknown>>(
254+
await client().apiGet<unknown>(
255+
apiPath(`/computers/${enc(id)}/viewer-password`),
256+
),
257+
);
258+
259+
if (isJsonMode(opts)) {
260+
console.log(JSON.stringify(raw, null, 2));
261+
return;
262+
}
263+
264+
printBanner({ subtitle: "External desktop viewer password" });
265+
console.log(
266+
kvPanel([
267+
{ icon: icon.info, label: "computer", value: chalk.dim(id) },
268+
{
269+
label: "password_set",
270+
value: raw["password_set"] ? chalk.green("yes") : chalk.yellow("no"),
271+
},
272+
...(raw["viewer_password_set_at"] || raw["password_set_at"]
273+
? [
274+
{
275+
label: "set_at",
276+
value: chalk.dim(
277+
String(raw["viewer_password_set_at"] ?? raw["password_set_at"]),
278+
),
279+
},
280+
]
281+
: []),
282+
]),
283+
);
284+
console.log();
285+
console.log(
286+
hintBlock("Use", [
287+
`miosa computers rotate-viewer-password ${id}`,
288+
"Authenticated platform desktop links do not need this password.",
289+
]),
290+
);
291+
console.log();
292+
}),
293+
);
294+
295+
computers!
296+
.command("rotate-viewer-password <computer-id>")
297+
.alias("rotate-password")
298+
.description("Rotate and print the external desktop viewer password once")
299+
.option("--json", "Output as JSON")
300+
.action((id: string, opts: JsonOptions) =>
301+
runAction(async () => {
302+
const raw = unwrap<Record<string, unknown>>(
303+
await client().apiPost<unknown>(
304+
apiPath(`/computers/${enc(id)}/viewer-password/rotate`),
305+
{},
306+
),
307+
);
308+
309+
if (isJsonMode(opts)) {
310+
console.log(JSON.stringify(raw, null, 2));
311+
return;
312+
}
313+
314+
const password = String(raw["viewer_password"] ?? raw["password"] ?? "");
315+
printBanner({ subtitle: "Rotated external viewer password" });
316+
console.log(
317+
kvPanel([
318+
{ icon: icon.ok, label: "computer", value: chalk.dim(id) },
319+
{
320+
label: "viewer_password",
321+
value: password ? chalk.bold(password) : chalk.dim("not returned"),
322+
},
323+
...(raw["rotated_at"]
324+
? [{ label: "rotated_at", value: chalk.dim(String(raw["rotated_at"])) }]
325+
: []),
326+
]),
327+
);
328+
console.log();
329+
console.log(
330+
chalk.yellow(
331+
"This password is for raw external desktop viewer links. Store it now; it may not be returned again.",
332+
),
333+
);
334+
console.log();
335+
}),
336+
);
337+
246338
// Workspace-aware create (skipped in resourceCommands via skipCommands).
247339
addDataOption(
248340
computers!

0 commit comments

Comments
 (0)