diff --git a/docs/content/docs/get-started/quickstart.mdx b/docs/content/docs/get-started/quickstart.mdx index e9118bd8..e7b2afeb 100644 --- a/docs/content/docs/get-started/quickstart.mdx +++ b/docs/content/docs/get-started/quickstart.mdx @@ -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. @@ -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 ``` @@ -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" diff --git a/docs/content/docs/libraries/cua-cli/commands.mdx b/docs/content/docs/libraries/cua-cli/commands.mdx index c60d5a12..5335f432 100644 --- a/docs/content/docs/libraries/cua-cli/commands.mdx +++ b/docs/content/docs/libraries/cua-cli/commands.mdx @@ -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 --configuration --region +cua create --os --configuration --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 +cua start ``` **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 +cua stop ``` **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 +cua restart ``` **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 +cua delete ``` **Example:** ```bash -$ cua vm delete old-test-vm -VM deletion initiated: deleting +$ cua delete old-test-sandbox +Sandbox deletion initiated: deleting ``` - 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. -### `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 +cua open ``` **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 +cua chat ``` **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 diff --git a/docs/content/docs/libraries/cua-cli/index.mdx b/docs/content/docs/libraries/cua-cli/index.mdx index 3fe90c0f..6f0f740a 100644 --- a/docs/content/docs/libraries/cua-cli/index.mdx +++ b/docs/content/docs/libraries/cua-cli/index.mdx @@ -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 diff --git a/docs/content/docs/libraries/cua-cli/installation.mdx b/docs/content/docs/libraries/cua-cli/installation.mdx index 5a2fd49b..3d2f3c1a 100644 --- a/docs/content/docs/libraries/cua-cli/installation.mdx +++ b/docs/content/docs/libraries/cua-cli/installation.mdx @@ -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 diff --git a/libs/typescript/cua-cli/src/commands/auth.ts b/libs/typescript/cua-cli/src/commands/auth.ts index ada7944d..8706c765 100644 --- a/libs/typescript/cua-cli/src/commands/auth.ts +++ b/libs/typescript/cua-cli/src/commands/auth.ts @@ -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) => { - 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) => { + 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) => { - const token = await ensureApiKeyInteractive(); - const out = await writeEnvFile(process.cwd(), token); - console.log(`Wrote ${out}`); - } - ) - .command( - 'logout', - 'Remove stored API key', - () => {}, - async (_argv: Record) => { - 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) => { + const token = await ensureApiKeyInteractive(); + const out = await writeEnvFile(process.cwd(), token); + console.log(`Wrote ${out}`); + } + ) + .command( + 'logout', + 'Remove stored API key', + () => {}, + async (_argv: Record) => { + clearApiKey(); + console.log('Logged out'); + } + ); } diff --git a/libs/typescript/cua-cli/src/commands/vm.ts b/libs/typescript/cua-cli/src/commands/vm.ts index a1f58df2..c54e14e9 100644 --- a/libs/typescript/cua-cli/src/commands/vm.ts +++ b/libs/typescript/cua-cli/src/commands/vm.ts @@ -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) => { - 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) => { + 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) => { 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 ', - 'Delete a VM', - (y) => y.positional('name', { type: 'string', describe: 'VM name' }), + .command( + 'delete ', + 'Delete a sandbox', + (y) => y.positional('name', { type: 'string', describe: 'Sandbox name' }), async (argv: Record) => { 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 ', - 'Start a VM', - (y) => y.positional('name', { type: 'string', describe: 'VM name' }), + .command( + 'start ', + 'Start a sandbox', + (y) => y.positional('name', { type: 'string', describe: 'Sandbox name' }), async (argv: Record) => { 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 ', - 'Stop a VM', - (y) => y.positional('name', { type: 'string', describe: 'VM name' }), + .command( + 'stop ', + 'Stop a sandbox', + (y) => y.positional('name', { type: 'string', describe: 'Sandbox name' }), async (argv: Record) => { 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 ', - 'Restart a VM', - (y) => y.positional('name', { type: 'string', describe: 'VM name' }), + .command( + 'restart ', + 'Restart a sandbox', + (y) => y.positional('name', { type: 'string', describe: 'Sandbox name' }), async (argv: Record) => { 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 ', - 'Open NoVNC for a VM in your browser', - (y) => y.positional('name', { type: 'string', describe: 'VM name' }), + .command( + 'open ', + 'Open NoVNC for a sandbox in your browser', + (y) => y.positional('name', { type: 'string', describe: 'Sandbox name' }), async (argv: Record) => { 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 ', - 'Open CUA dashboard playground for a VM', - (y) => y.positional('name', { type: 'string', describe: 'VM name' }), + .command( + 'chat ', + 'Open CUA playground for a sandbox', + (y) => y.positional('name', { type: 'string', describe: 'Sandbox name' }), async (argv: Record) => { 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') - ); + ); } diff --git a/libs/typescript/cua-cli/src/util.ts b/libs/typescript/cua-cli/src/util.ts index 482df0e6..9992adc0 100644 --- a/libs/typescript/cua-cli/src/util.ts +++ b/libs/typescript/cua-cli/src/util.ts @@ -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'); }