mirror of
https://github.com/trycua/computer.git
synced 2025-12-31 02:19:58 -06:00
flatten CLI, rename VM to sandbox
This commit is contained in:
@@ -332,7 +332,7 @@ Learn more about agents in [Agent Loops](/agent-sdk/agent-loops) and available m
|
||||
|
||||
## CLI Quickstart
|
||||
|
||||
Get started quickly with the CUA CLI - the easiest way to manage cloud VMs and run AI agents.
|
||||
Get started quickly with the CUA CLI - the easiest way to manage cloud sandboxes and run AI agents.
|
||||
|
||||
<Steps>
|
||||
<Step>
|
||||
@@ -386,10 +386,10 @@ Login to your CUA account:
|
||||
|
||||
```bash
|
||||
# Interactive browser login (recommended)
|
||||
cua auth login
|
||||
cua login
|
||||
|
||||
# Or provide your API key directly
|
||||
cua auth login --api-key sk-your-api-key-here
|
||||
cua login --api-key sk-your-api-key-here
|
||||
```
|
||||
|
||||
If you don't have a CUA account yet, sign up at [cua.ai/signin](https://cua.ai/signin).
|
||||
@@ -404,10 +404,10 @@ Create a cloud sandbox where your AI agents will run:
|
||||
|
||||
```bash
|
||||
# Create a Linux sandbox (recommended for most use cases)
|
||||
cua vm create --os linux --configuration small --region north-america
|
||||
cua create --os linux --configuration small --region north-america
|
||||
|
||||
# Or create a Windows sandbox
|
||||
cua vm create --os windows --configuration small --region north-america
|
||||
cua create --os windows --configuration small --region north-america
|
||||
|
||||
```
|
||||
|
||||
@@ -430,7 +430,7 @@ You can now interact with your sandbox in multiple ways:
|
||||
#### Option 1: Open the AI Playground (Recommended)
|
||||
|
||||
```bash
|
||||
cua vm chat my-vm-abc123
|
||||
cua chat my-vm-abc123
|
||||
```
|
||||
|
||||
This opens the full CUA playground in your browser where you can chat with AI agents that control your sandbox.
|
||||
@@ -438,7 +438,7 @@ This opens the full CUA playground in your browser where you can chat with AI ag
|
||||
#### Option 2: Access VNC Desktop
|
||||
|
||||
```bash
|
||||
cua vm vnc my-vm-abc123
|
||||
cua open my-vm-abc123
|
||||
```
|
||||
|
||||
This opens a remote desktop connection to your sandbox.
|
||||
@@ -447,14 +447,14 @@ This opens a remote desktop connection to your sandbox.
|
||||
|
||||
```bash
|
||||
# List all your sandboxes
|
||||
cua vm list
|
||||
cua list
|
||||
|
||||
# Start/stop sandboxes as needed
|
||||
cua vm stop my-vm-abc123
|
||||
cua vm start my-vm-abc123
|
||||
cua stop my-vm-abc123
|
||||
cua start my-vm-abc123
|
||||
|
||||
# Delete sandboxes when done
|
||||
cua vm delete my-vm-abc123
|
||||
cua delete my-vm-abc123
|
||||
```
|
||||
|
||||
</Step>
|
||||
@@ -463,7 +463,7 @@ cua vm delete my-vm-abc123
|
||||
|
||||
### Try Some AI Tasks
|
||||
|
||||
Once you have the playground open (`cua vm chat`), try asking the AI to:
|
||||
Once you have the playground open (`cua chat`), try asking the AI to:
|
||||
|
||||
- "Take a screenshot and tell me what's on the screen"
|
||||
- "Open Firefox and navigate to github.com"
|
||||
|
||||
@@ -8,23 +8,23 @@ import { Callout } from 'fumadocs-ui/components/callout';
|
||||
|
||||
## Overview
|
||||
|
||||
The CUA CLI provides two main command groups:
|
||||
The CUA CLI provides commands for authentication and sandbox management:
|
||||
|
||||
- **`cua auth`** - Authentication and API key management
|
||||
- **`cua vm`** - Virtual machine lifecycle management
|
||||
- **Authentication** - `cua login`, `cua env`, `cua logout`
|
||||
- **Sandbox Management** - `cua list`, `cua create`, `cua start`, `cua stop`, `cua restart`, `cua delete`, `cua open`, `cua chat`
|
||||
|
||||
## Authentication Commands
|
||||
|
||||
### `cua auth login`
|
||||
### `cua login`
|
||||
|
||||
Authenticate with your CUA account using browser-based OAuth flow.
|
||||
|
||||
```bash
|
||||
# Interactive browser login
|
||||
cua auth login
|
||||
cua login
|
||||
|
||||
# Direct API key login
|
||||
cua auth login --api-key sk-your-api-key-here
|
||||
cua login --api-key sk-your-api-key-here
|
||||
```
|
||||
|
||||
**Options:**
|
||||
@@ -32,22 +32,22 @@ cua auth login --api-key sk-your-api-key-here
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
$ cua auth login
|
||||
$ cua login
|
||||
Opening browser for CLI auth...
|
||||
API key saved
|
||||
```
|
||||
|
||||
### `cua auth pull`
|
||||
### `cua env`
|
||||
|
||||
Create or update a `.env` file in the current directory with your CUA API key.
|
||||
|
||||
```bash
|
||||
cua auth pull
|
||||
cua env
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
$ cua auth pull
|
||||
$ cua env
|
||||
Wrote /path/to/your/project/.env
|
||||
```
|
||||
|
||||
@@ -56,172 +56,184 @@ The generated `.env` file will contain:
|
||||
CUA_API_KEY=sk-your-api-key-here
|
||||
```
|
||||
|
||||
### `cua auth logout`
|
||||
### `cua logout`
|
||||
|
||||
Remove the stored API key from your system.
|
||||
|
||||
```bash
|
||||
cua auth logout
|
||||
cua logout
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
$ cua auth logout
|
||||
$ cua logout
|
||||
Logged out
|
||||
```
|
||||
|
||||
## Virtual Machine Commands
|
||||
## Sandbox Commands
|
||||
|
||||
### `cua vm list`
|
||||
### `cua list`
|
||||
|
||||
List all your virtual machines with their current status.
|
||||
List all your sandboxes with their current status. Passwords are hidden by default for security.
|
||||
|
||||
```bash
|
||||
cua vm list
|
||||
# List sandboxes (passwords hidden)
|
||||
cua list
|
||||
|
||||
# Show passwords explicitly
|
||||
cua list --show-passwords
|
||||
|
||||
# Alternative aliases
|
||||
cua ls
|
||||
cua ps
|
||||
```
|
||||
|
||||
**Example Output:**
|
||||
**Example Output (default, passwords hidden):**
|
||||
```
|
||||
┌─────────────────┬──────────┬────────┬─────────────────┬──────────────────────────────────────┐
|
||||
│ Name │ Status │ OS │ Configuration │ Host │
|
||||
├─────────────────┼──────────┼────────┼─────────────────┼──────────────────────────────────────┤
|
||||
│ my-dev-vm │ running │ linux │ small │ my-dev-vm.containers.cloud.trycua.com │
|
||||
│ test-windows │ stopped │ windows│ medium │ test-windows.containers.cloud.trycua.com │
|
||||
└─────────────────┴──────────┴────────┴─────────────────┴──────────────────────────────────────┘
|
||||
NAME STATUS HOST
|
||||
my-dev-sandbox running my-dev-sandbox.containers.cloud.trycua.com
|
||||
test-windows stopped test-windows.containers.cloud.trycua.com
|
||||
```
|
||||
|
||||
### `cua vm create`
|
||||
**Example Output (with --show-passwords):**
|
||||
```
|
||||
NAME STATUS PASSWORD HOST
|
||||
my-dev-sandbox running secure-pass-123 my-dev-sandbox.containers.cloud.trycua.com
|
||||
test-windows stopped another-pass-456 test-windows.containers.cloud.trycua.com
|
||||
```
|
||||
|
||||
Create a new virtual machine.
|
||||
### `cua create`
|
||||
|
||||
Create a new sandbox.
|
||||
|
||||
```bash
|
||||
cua vm create --os <OS> --configuration <SIZE> --region <REGION>
|
||||
cua create --os <OS> --configuration <SIZE> --region <REGION>
|
||||
```
|
||||
|
||||
**Required Options:**
|
||||
- `--os` - Operating system: `linux`, `windows`, `macos`
|
||||
- `--configuration` - VM size: `small`, `medium`, `large`
|
||||
- `--configuration` - Sandbox size: `small`, `medium`, `large`
|
||||
- `--region` - Region: `north-america`, `europe`, `asia-pacific`, `south-america`
|
||||
|
||||
**Examples:**
|
||||
```bash
|
||||
# Create a small Linux VM in North America
|
||||
cua vm create --os linux --configuration small --region north-america
|
||||
# Create a small Linux sandbox in North America
|
||||
cua create --os linux --configuration small --region north-america
|
||||
|
||||
# Create a medium Windows VM in Europe
|
||||
cua vm create --os windows --configuration medium --region europe
|
||||
# Create a medium Windows sandbox in Europe
|
||||
cua create --os windows --configuration medium --region europe
|
||||
|
||||
# Create a large macOS VM in Asia Pacific
|
||||
cua vm create --os macos --configuration large --region asia-pacific
|
||||
# Create a large macOS sandbox in Asia Pacific
|
||||
cua create --os macos --configuration large --region asia-pacific
|
||||
```
|
||||
|
||||
**Response Types:**
|
||||
|
||||
**Immediate (Status 200):**
|
||||
```bash
|
||||
VM created and ready: my-new-vm-abc123
|
||||
Sandbox created and ready: my-new-sandbox-abc123
|
||||
Password: secure-password-here
|
||||
Host: my-new-vm-abc123.containers.cloud.trycua.com
|
||||
Host: my-new-sandbox-abc123.containers.cloud.trycua.com
|
||||
```
|
||||
|
||||
**Provisioning (Status 202):**
|
||||
```bash
|
||||
VM provisioning started: my-new-vm-abc123
|
||||
Sandbox provisioning started: my-new-sandbox-abc123
|
||||
Job ID: job-xyz789
|
||||
Use 'cua vm list' to monitor provisioning progress
|
||||
Use 'cua list' to monitor provisioning progress
|
||||
```
|
||||
|
||||
### `cua vm start`
|
||||
### `cua start`
|
||||
|
||||
Start a stopped virtual machine.
|
||||
Start a stopped sandbox.
|
||||
|
||||
```bash
|
||||
cua vm start <name>
|
||||
cua start <name>
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
$ cua vm start my-dev-vm
|
||||
$ cua start my-dev-sandbox
|
||||
Start accepted
|
||||
```
|
||||
|
||||
### `cua vm stop`
|
||||
### `cua stop`
|
||||
|
||||
Stop a running virtual machine.
|
||||
Stop a running sandbox.
|
||||
|
||||
```bash
|
||||
cua vm stop <name>
|
||||
cua stop <name>
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
$ cua vm stop my-dev-vm
|
||||
$ cua stop my-dev-sandbox
|
||||
stopping
|
||||
```
|
||||
|
||||
### `cua vm restart`
|
||||
### `cua restart`
|
||||
|
||||
Restart a virtual machine.
|
||||
Restart a sandbox.
|
||||
|
||||
```bash
|
||||
cua vm restart <name>
|
||||
cua restart <name>
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
$ cua vm restart my-dev-vm
|
||||
$ cua restart my-dev-sandbox
|
||||
restarting
|
||||
```
|
||||
|
||||
### `cua vm delete`
|
||||
### `cua delete`
|
||||
|
||||
Delete a virtual machine permanently.
|
||||
Delete a sandbox permanently.
|
||||
|
||||
```bash
|
||||
cua vm delete <name>
|
||||
cua delete <name>
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
$ cua vm delete old-test-vm
|
||||
VM deletion initiated: deleting
|
||||
$ cua delete old-test-sandbox
|
||||
Sandbox deletion initiated: deleting
|
||||
```
|
||||
|
||||
<Callout type="warn">
|
||||
This action is irreversible. All data on the VM will be permanently lost.
|
||||
This action is irreversible. All data on the sandbox will be permanently lost.
|
||||
</Callout>
|
||||
|
||||
### `cua vm vnc`
|
||||
### `cua open`
|
||||
|
||||
Open the VNC interface for a VM in your browser.
|
||||
Open the VNC interface for a sandbox in your browser.
|
||||
|
||||
```bash
|
||||
cua vm vnc <name>
|
||||
cua open <name>
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
$ cua vm vnc my-dev-vm
|
||||
Opening NoVNC: https://my-dev-vm.containers.cloud.trycua.com/vnc.html?autoconnect=true&password=...
|
||||
$ cua open my-dev-sandbox
|
||||
Opening NoVNC: https://my-dev-sandbox.containers.cloud.trycua.com/vnc.html?autoconnect=true&password=...
|
||||
```
|
||||
|
||||
This command automatically opens your default browser to the VNC interface with the correct password pre-filled.
|
||||
|
||||
### `cua vm chat`
|
||||
### `cua chat`
|
||||
|
||||
Open the CUA Dashboard Playground for a VM in your browser.
|
||||
Open the CUA playground for a sandbox in your browser.
|
||||
|
||||
```bash
|
||||
cua vm chat <name>
|
||||
cua chat <name>
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
$ cua vm chat my-dev-vm
|
||||
$ cua chat my-dev-sandbox
|
||||
Opening Playground: https://cua.ai/dashboard/playground?host=...
|
||||
```
|
||||
|
||||
This opens the full CUA playground interface where you can interact with your VM using AI agents.
|
||||
This opens the full CUA playground interface where you can interact with your sandbox using AI agents.
|
||||
|
||||
## Global Options
|
||||
|
||||
@@ -231,9 +243,9 @@ Get help for any command:
|
||||
|
||||
```bash
|
||||
cua --help
|
||||
cua auth --help
|
||||
cua vm --help
|
||||
cua vm create --help
|
||||
cua login --help
|
||||
cua create --help
|
||||
cua list --help
|
||||
```
|
||||
|
||||
### Environment Variables
|
||||
@@ -258,32 +270,32 @@ The CLI provides clear error messages for common issues:
|
||||
|
||||
### Authentication Errors
|
||||
```bash
|
||||
$ cua vm list
|
||||
Unauthorized. Try 'cua auth login' again.
|
||||
$ cua list
|
||||
Unauthorized. Try 'cua login' again.
|
||||
```
|
||||
|
||||
### VM Not Found
|
||||
### Sandbox Not Found
|
||||
```bash
|
||||
$ cua vm start nonexistent-vm
|
||||
VM not found
|
||||
$ cua start nonexistent-sandbox
|
||||
Sandbox not found
|
||||
```
|
||||
|
||||
### Invalid Configuration
|
||||
```bash
|
||||
$ cua vm create --os invalid --configuration small --region north-america
|
||||
$ cua create --os invalid --configuration small --region north-america
|
||||
Invalid request or unsupported configuration
|
||||
```
|
||||
|
||||
## Tips and Best Practices
|
||||
|
||||
### 1. Use Descriptive VM Names
|
||||
### 1. Use Descriptive Sandbox Names
|
||||
```bash
|
||||
# Good
|
||||
cua vm create --os linux --configuration small --region north-america
|
||||
cua create --os linux --configuration small --region north-america
|
||||
# Then rename or use meaningful names in the dashboard
|
||||
|
||||
# Better workflow
|
||||
cua vm list # Check the generated name
|
||||
cua list # Check the generated name
|
||||
# Use that name consistently
|
||||
```
|
||||
|
||||
@@ -291,26 +303,26 @@ cua vm list # Check the generated name
|
||||
```bash
|
||||
# Set up your project with API key
|
||||
cd my-project
|
||||
cua auth pull
|
||||
cua env
|
||||
# Now your project has CUA_API_KEY in .env
|
||||
```
|
||||
|
||||
### 3. Quick VM Access
|
||||
### 3. Quick Sandbox Access
|
||||
```bash
|
||||
# Create aliases for frequently used VMs
|
||||
alias dev-vm="cua vm chat my-development-vm"
|
||||
alias prod-vm="cua vm vnc my-production-vm"
|
||||
# Create aliases for frequently used sandboxes
|
||||
alias dev-sandbox="cua chat my-development-sandbox"
|
||||
alias prod-sandbox="cua open my-production-sandbox"
|
||||
```
|
||||
|
||||
### 4. Monitoring Provisioning
|
||||
```bash
|
||||
# For VMs that need provisioning time
|
||||
cua vm create --os windows --configuration large --region europe
|
||||
# VM provisioning started: my-vm-abc123
|
||||
# For sandboxes that need provisioning time
|
||||
cua create --os windows --configuration large --region europe
|
||||
# Sandbox provisioning started: my-sandbox-abc123
|
||||
# Job ID: job-xyz789
|
||||
|
||||
# Check status periodically
|
||||
watch -n 5 cua vm list
|
||||
watch -n 5 cua list
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
---
|
||||
title: Cua CLI
|
||||
description: Command-line interface for managing Cua cloud VMs and authentication
|
||||
description: Command-line interface for managing Cua cloud sandboxes and authentication
|
||||
---
|
||||
|
||||
import { Tabs, Tab } from 'fumadocs-ui/components/tabs';
|
||||
|
||||
The Cua CLI is a command-line tool that provides an intuitive interface for managing your Cua cloud virtual machines and authentication. It offers a streamlined workflow for creating, managing, and connecting to cloud sandboxes.
|
||||
The Cua CLI is a command-line tool that provides an intuitive interface for managing your Cua cloud sandboxes and authentication. It offers a streamlined workflow for creating, managing, and connecting to cloud sandboxes.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Authentication Management**: Secure login with browser-based OAuth flow
|
||||
- **VM Lifecycle**: Create, start, stop, restart, and delete cloud VMs
|
||||
- **Sandbox Lifecycle**: Create, start, stop, restart, and delete cloud sandboxes
|
||||
- **Quick Access**: Direct links to VNC and playground interfaces
|
||||
- **Cross-Platform**: Works on macOS, Linux, and Windows
|
||||
- **Environment Integration**: Automatic `.env` file generation
|
||||
@@ -22,32 +22,32 @@ The Cua CLI is a command-line tool that provides an intuitive interface for mana
|
||||
curl -LsSf https://cua.ai/cli/install.sh | sh
|
||||
|
||||
# Login to your CUA account
|
||||
cua auth login
|
||||
cua login
|
||||
|
||||
# Create a new Linux VM
|
||||
cua vm create --os linux --configuration small --region north-america
|
||||
# Create a new Linux sandbox
|
||||
cua create --os linux --configuration small --region north-america
|
||||
|
||||
# List your VMs
|
||||
cua vm list
|
||||
# List your sandboxes
|
||||
cua list
|
||||
|
||||
# Open the playground for your VM
|
||||
cua vm chat my-vm-name
|
||||
# Open the playground for your sandbox
|
||||
cua chat my-sandbox-name
|
||||
```
|
||||
|
||||
## Use Cases
|
||||
|
||||
### Development Workflow
|
||||
- Quickly spin up cloud sandboxes for testing
|
||||
- Manage multiple VMs across different regions
|
||||
- Manage multiple sandboxes across different regions
|
||||
- Integrate with CI/CD pipelines
|
||||
|
||||
### Team Collaboration
|
||||
- Share VM configurations and access
|
||||
- Share sandbox configurations and access
|
||||
- Standardize development environments
|
||||
- Quick onboarding for new team members
|
||||
|
||||
### Automation
|
||||
- Script VM provisioning and management
|
||||
- Script sandbox provisioning and management
|
||||
- Integrate with deployment workflows
|
||||
- Automate environment setup
|
||||
|
||||
|
||||
@@ -59,10 +59,10 @@ After installation, you'll need to authenticate with your CUA account:
|
||||
|
||||
```bash
|
||||
# Login with browser-based OAuth flow
|
||||
cua auth login
|
||||
cua login
|
||||
|
||||
# Or provide your API key directly
|
||||
cua auth login --api-key sk-your-api-key-here
|
||||
cua login --api-key sk-your-api-key-here
|
||||
```
|
||||
|
||||
## Updating
|
||||
|
||||
@@ -4,47 +4,44 @@ import { writeEnvFile } from '../util';
|
||||
import type { Argv } from 'yargs';
|
||||
|
||||
export function registerAuthCommands(y: Argv) {
|
||||
return y.command('auth', 'Auth commands', (ya) =>
|
||||
ya
|
||||
.command(
|
||||
'login',
|
||||
'Open browser to authorize and store API key',
|
||||
(y) =>
|
||||
y.option('api-key', {
|
||||
type: 'string',
|
||||
describe: 'API key to store directly',
|
||||
}),
|
||||
async (argv: Record<string, unknown>) => {
|
||||
if (argv['api-key']) {
|
||||
setApiKey(String(argv['api-key']));
|
||||
console.log('API key saved');
|
||||
return;
|
||||
}
|
||||
console.log('Opening browser for CLI auth...');
|
||||
const token = await loginViaBrowser();
|
||||
setApiKey(token);
|
||||
return y
|
||||
.command(
|
||||
'login',
|
||||
'Open browser to authorize and store API key',
|
||||
(y) =>
|
||||
y.option('api-key', {
|
||||
type: 'string',
|
||||
describe: 'API key to store directly',
|
||||
}),
|
||||
async (argv: Record<string, unknown>) => {
|
||||
if (argv['api-key']) {
|
||||
setApiKey(String(argv['api-key']));
|
||||
console.log('API key saved');
|
||||
return;
|
||||
}
|
||||
)
|
||||
.command(
|
||||
'pull',
|
||||
'Create or update .env with CUA_API_KEY (login if needed)',
|
||||
() => {},
|
||||
async (_argv: Record<string, unknown>) => {
|
||||
const token = await ensureApiKeyInteractive();
|
||||
const out = await writeEnvFile(process.cwd(), token);
|
||||
console.log(`Wrote ${out}`);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
'logout',
|
||||
'Remove stored API key',
|
||||
() => {},
|
||||
async (_argv: Record<string, unknown>) => {
|
||||
clearApiKey();
|
||||
console.log('Logged out');
|
||||
}
|
||||
)
|
||||
.demandCommand(1, 'Specify an auth subcommand')
|
||||
);
|
||||
console.log('Opening browser for CLI auth...');
|
||||
const token = await loginViaBrowser();
|
||||
setApiKey(token);
|
||||
console.log('API key saved');
|
||||
}
|
||||
)
|
||||
.command(
|
||||
'env',
|
||||
'Create or update .env with CUA_API_KEY (login if needed)',
|
||||
() => {},
|
||||
async (_argv: Record<string, unknown>) => {
|
||||
const token = await ensureApiKeyInteractive();
|
||||
const out = await writeEnvFile(process.cwd(), token);
|
||||
console.log(`Wrote ${out}`);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
'logout',
|
||||
'Remove stored API key',
|
||||
() => {},
|
||||
async (_argv: Record<string, unknown>) => {
|
||||
clearApiKey();
|
||||
console.log('Logged out');
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,37 +1,40 @@
|
||||
import type { Argv } from 'yargs';
|
||||
import { ensureApiKeyInteractive } from '../auth';
|
||||
import { http } from '../http';
|
||||
import { printVmList, openInBrowser } from '../util';
|
||||
import { WEBSITE_URL } from '../config';
|
||||
import type { VmItem } from '../util';
|
||||
import { http } from '../http';
|
||||
import { clearApiKey } from '../storage';
|
||||
import type { VmItem } from '../util';
|
||||
import { openInBrowser, printVmList } from '../util';
|
||||
|
||||
export function registerVmCommands(y: Argv) {
|
||||
return y.command('vm', 'VM commands', (yv) =>
|
||||
yv
|
||||
.command(
|
||||
'list',
|
||||
'List VMs',
|
||||
() => {},
|
||||
async (_argv: Record<string, unknown>) => {
|
||||
const token = await ensureApiKeyInteractive();
|
||||
const res = await http('/v1/vms', { token });
|
||||
if (res.status === 401) {
|
||||
clearApiKey();
|
||||
console.error("Unauthorized. Try 'cua auth login' again.");
|
||||
process.exit(1);
|
||||
}
|
||||
if (!res.ok) {
|
||||
console.error(`Request failed: ${res.status}`);
|
||||
process.exit(1);
|
||||
}
|
||||
const data = (await res.json()) as VmItem[];
|
||||
printVmList(data);
|
||||
return y
|
||||
.command(
|
||||
['list', 'ls', 'ps'],
|
||||
'List sandboxes',
|
||||
(y) => y.option('show-passwords', {
|
||||
type: 'boolean',
|
||||
default: false,
|
||||
describe: 'Show sandbox passwords in output'
|
||||
}),
|
||||
async (argv: Record<string, unknown>) => {
|
||||
const token = await ensureApiKeyInteractive();
|
||||
const res = await http('/v1/vms', { token });
|
||||
if (res.status === 401) {
|
||||
clearApiKey();
|
||||
console.error("Unauthorized. Try 'cua login' again.");
|
||||
process.exit(1);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
'create',
|
||||
'Create a new VM',
|
||||
if (!res.ok) {
|
||||
console.error(`Request failed: ${res.status}`);
|
||||
process.exit(1);
|
||||
}
|
||||
const data = (await res.json()) as VmItem[];
|
||||
printVmList(data, Boolean(argv['show-passwords']));
|
||||
}
|
||||
)
|
||||
.command(
|
||||
'create',
|
||||
'Create a new sandbox',
|
||||
(y) =>
|
||||
y
|
||||
.option('os', {
|
||||
@@ -44,7 +47,7 @@ export function registerVmCommands(y: Argv) {
|
||||
type: 'string',
|
||||
choices: ['small', 'medium', 'large'],
|
||||
demandOption: true,
|
||||
describe: 'VM size configuration',
|
||||
describe: 'Sandbox size configuration',
|
||||
})
|
||||
.option('region', {
|
||||
type: 'string',
|
||||
@@ -55,7 +58,7 @@ export function registerVmCommands(y: Argv) {
|
||||
'south-america',
|
||||
],
|
||||
demandOption: true,
|
||||
describe: 'VM region',
|
||||
describe: 'Sandbox region',
|
||||
}),
|
||||
async (argv: Record<string, unknown>) => {
|
||||
const token = await ensureApiKeyInteractive();
|
||||
@@ -73,7 +76,7 @@ export function registerVmCommands(y: Argv) {
|
||||
|
||||
if (res.status === 401) {
|
||||
clearApiKey();
|
||||
console.error("Unauthorized. Try 'cua auth login' again.");
|
||||
console.error("Unauthorized. Try 'cua login' again.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -88,29 +91,29 @@ export function registerVmCommands(y: Argv) {
|
||||
}
|
||||
|
||||
if (res.status === 200) {
|
||||
// VM ready immediately
|
||||
// Sandbox ready immediately
|
||||
const data = (await res.json()) as {
|
||||
status: string;
|
||||
name: string;
|
||||
password: string;
|
||||
host: string;
|
||||
};
|
||||
console.log(`VM created and ready: ${data.name}`);
|
||||
console.log(`Sandbox created and ready: ${data.name}`);
|
||||
console.log(`Password: ${data.password}`);
|
||||
console.log(`Host: ${data.host}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.status === 202) {
|
||||
// VM provisioning started
|
||||
// Sandbox provisioning started
|
||||
const data = (await res.json()) as {
|
||||
status: string;
|
||||
name: string;
|
||||
job_id: string;
|
||||
};
|
||||
console.log(`VM provisioning started: ${data.name}`);
|
||||
console.log(`Sandbox provisioning started: ${data.name}`);
|
||||
console.log(`Job ID: ${data.job_id}`);
|
||||
console.log("Use 'cua vm list' to monitor provisioning progress");
|
||||
console.log("Use 'cua list' to monitor provisioning progress");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -118,10 +121,10 @@ export function registerVmCommands(y: Argv) {
|
||||
process.exit(1);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
'delete <name>',
|
||||
'Delete a VM',
|
||||
(y) => y.positional('name', { type: 'string', describe: 'VM name' }),
|
||||
.command(
|
||||
'delete <name>',
|
||||
'Delete a sandbox',
|
||||
(y) => y.positional('name', { type: 'string', describe: 'Sandbox name' }),
|
||||
async (argv: Record<string, unknown>) => {
|
||||
const token = await ensureApiKeyInteractive();
|
||||
const name = String((argv as any).name);
|
||||
@@ -134,18 +137,18 @@ export function registerVmCommands(y: Argv) {
|
||||
const body = (await res.json().catch(() => ({}))) as {
|
||||
status?: string;
|
||||
};
|
||||
console.log(`VM deletion initiated: ${body.status ?? 'deleting'}`);
|
||||
console.log(`Sandbox deletion initiated: ${body.status ?? 'deleting'}`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (res.status === 404) {
|
||||
console.error('VM not found or not owned by you');
|
||||
console.error('Sandbox not found or not owned by you');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
if (res.status === 401) {
|
||||
clearApiKey();
|
||||
console.error("Unauthorized. Try 'cua auth login' again.");
|
||||
console.error("Unauthorized. Try 'cua login' again.");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -153,10 +156,10 @@ export function registerVmCommands(y: Argv) {
|
||||
process.exit(1);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
'start <name>',
|
||||
'Start a VM',
|
||||
(y) => y.positional('name', { type: 'string', describe: 'VM name' }),
|
||||
.command(
|
||||
'start <name>',
|
||||
'Start a sandbox',
|
||||
(y) => y.positional('name', { type: 'string', describe: 'Sandbox name' }),
|
||||
async (argv: Record<string, unknown>) => {
|
||||
const token = await ensureApiKeyInteractive();
|
||||
const name = String((argv as any).name);
|
||||
@@ -169,22 +172,22 @@ export function registerVmCommands(y: Argv) {
|
||||
return;
|
||||
}
|
||||
if (res.status === 404) {
|
||||
console.error('VM not found');
|
||||
console.error('Sandbox not found');
|
||||
process.exit(1);
|
||||
}
|
||||
if (res.status === 401) {
|
||||
clearApiKey();
|
||||
console.error("Unauthorized. Try 'cua auth login' again.");
|
||||
console.error("Unauthorized. Try 'cua login' again.");
|
||||
process.exit(1);
|
||||
}
|
||||
console.error(`Unexpected status: ${res.status}`);
|
||||
process.exit(1);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
'stop <name>',
|
||||
'Stop a VM',
|
||||
(y) => y.positional('name', { type: 'string', describe: 'VM name' }),
|
||||
.command(
|
||||
'stop <name>',
|
||||
'Stop a sandbox',
|
||||
(y) => y.positional('name', { type: 'string', describe: 'Sandbox name' }),
|
||||
async (argv: Record<string, unknown>) => {
|
||||
const token = await ensureApiKeyInteractive();
|
||||
const name = String((argv as any).name);
|
||||
@@ -200,22 +203,22 @@ export function registerVmCommands(y: Argv) {
|
||||
return;
|
||||
}
|
||||
if (res.status === 404) {
|
||||
console.error('VM not found');
|
||||
console.error('Sandbox not found');
|
||||
process.exit(1);
|
||||
}
|
||||
if (res.status === 401) {
|
||||
clearApiKey();
|
||||
console.error("Unauthorized. Try 'cua auth login' again.");
|
||||
console.error("Unauthorized. Try 'cua login' again.");
|
||||
process.exit(1);
|
||||
}
|
||||
console.error(`Unexpected status: ${res.status}`);
|
||||
process.exit(1);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
'restart <name>',
|
||||
'Restart a VM',
|
||||
(y) => y.positional('name', { type: 'string', describe: 'VM name' }),
|
||||
.command(
|
||||
'restart <name>',
|
||||
'Restart a sandbox',
|
||||
(y) => y.positional('name', { type: 'string', describe: 'Sandbox name' }),
|
||||
async (argv: Record<string, unknown>) => {
|
||||
const token = await ensureApiKeyInteractive();
|
||||
const name = String((argv as any).name);
|
||||
@@ -234,29 +237,29 @@ export function registerVmCommands(y: Argv) {
|
||||
return;
|
||||
}
|
||||
if (res.status === 404) {
|
||||
console.error('VM not found');
|
||||
console.error('Sandbox not found');
|
||||
process.exit(1);
|
||||
}
|
||||
if (res.status === 401) {
|
||||
clearApiKey();
|
||||
console.error("Unauthorized. Try 'cua auth login' again.");
|
||||
console.error("Unauthorized. Try 'cua login' again.");
|
||||
process.exit(1);
|
||||
}
|
||||
console.error(`Unexpected status: ${res.status}`);
|
||||
process.exit(1);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
'vnc <name>',
|
||||
'Open NoVNC for a VM in your browser',
|
||||
(y) => y.positional('name', { type: 'string', describe: 'VM name' }),
|
||||
.command(
|
||||
'open <name>',
|
||||
'Open NoVNC for a sandbox in your browser',
|
||||
(y) => y.positional('name', { type: 'string', describe: 'Sandbox name' }),
|
||||
async (argv: Record<string, unknown>) => {
|
||||
const token = await ensureApiKeyInteractive();
|
||||
const name = String((argv as any).name);
|
||||
const listRes = await http('/v1/vms', { token });
|
||||
if (listRes.status === 401) {
|
||||
clearApiKey();
|
||||
console.error("Unauthorized. Try 'cua auth login' again.");
|
||||
console.error("Unauthorized. Try 'cua login' again.");
|
||||
process.exit(1);
|
||||
}
|
||||
if (!listRes.ok) {
|
||||
@@ -266,7 +269,7 @@ export function registerVmCommands(y: Argv) {
|
||||
const vms = (await listRes.json()) as VmItem[];
|
||||
const vm = vms.find((v) => v.name === name);
|
||||
if (!vm) {
|
||||
console.error('VM not found');
|
||||
console.error('Sandbox not found');
|
||||
process.exit(1);
|
||||
}
|
||||
const host =
|
||||
@@ -278,17 +281,17 @@ export function registerVmCommands(y: Argv) {
|
||||
await openInBrowser(url);
|
||||
}
|
||||
)
|
||||
.command(
|
||||
'chat <name>',
|
||||
'Open CUA dashboard playground for a VM',
|
||||
(y) => y.positional('name', { type: 'string', describe: 'VM name' }),
|
||||
.command(
|
||||
'chat <name>',
|
||||
'Open CUA playground for a sandbox',
|
||||
(y) => y.positional('name', { type: 'string', describe: 'Sandbox name' }),
|
||||
async (argv: Record<string, unknown>) => {
|
||||
const token = await ensureApiKeyInteractive();
|
||||
const name = String((argv as any).name);
|
||||
const listRes = await http('/v1/vms', { token });
|
||||
if (listRes.status === 401) {
|
||||
clearApiKey();
|
||||
console.error("Unauthorized. Try 'cua auth login' again.");
|
||||
console.error("Unauthorized. Try 'cua login' again.");
|
||||
process.exit(1);
|
||||
}
|
||||
if (!listRes.ok) {
|
||||
@@ -298,7 +301,7 @@ export function registerVmCommands(y: Argv) {
|
||||
const vms = (await listRes.json()) as VmItem[];
|
||||
const vm = vms.find((v) => v.name === name);
|
||||
if (!vm) {
|
||||
console.error('VM not found');
|
||||
console.error('Sandbox not found');
|
||||
process.exit(1);
|
||||
}
|
||||
const host =
|
||||
@@ -310,7 +313,5 @@ export function registerVmCommands(y: Argv) {
|
||||
console.log(`Opening Playground: ${url}`);
|
||||
await openInBrowser(url);
|
||||
}
|
||||
)
|
||||
.demandCommand(1, 'Specify a vm subcommand')
|
||||
);
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,17 +25,29 @@ export type VmItem = {
|
||||
host?: string;
|
||||
};
|
||||
|
||||
export function printVmList(items: VmItem[]) {
|
||||
export function printVmList(items: VmItem[], showPasswords: boolean = false) {
|
||||
const headers = showPasswords
|
||||
? ['NAME', 'STATUS', 'PASSWORD', 'HOST']
|
||||
: ['NAME', 'STATUS', 'HOST'];
|
||||
|
||||
const rows: string[][] = [
|
||||
['NAME', 'STATUS', 'PASSWORD', 'HOST'],
|
||||
...items.map((v) => [v.name, String(v.status), v.password, v.host || '']),
|
||||
headers,
|
||||
...items.map((v) => showPasswords
|
||||
? [v.name, String(v.status), v.password, v.host || '']
|
||||
: [v.name, String(v.status), v.host || '']
|
||||
),
|
||||
];
|
||||
const widths: number[] = [0, 0, 0, 0];
|
||||
|
||||
const numCols = headers.length;
|
||||
const widths: number[] = new Array(numCols).fill(0);
|
||||
|
||||
for (const r of rows)
|
||||
for (let i = 0; i < 4; i++)
|
||||
for (let i = 0; i < numCols; i++)
|
||||
widths[i] = Math.max(widths[i] ?? 0, (r[i] ?? '').length);
|
||||
|
||||
for (const r of rows)
|
||||
console.log(r.map((c, i) => (c ?? '').padEnd(widths[i] ?? 0)).join(' '));
|
||||
|
||||
if (items.length === 0) console.log('No VMs found');
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user