# API key
Source: https://docs.hopx.ai/api-key
How to obtain, manage, and use your HopX API keys for authentication. Complete guide to API key management, security best practices, and configuration for HopX SDK, CLI, and API access.
Your API key is required to authenticate all requests to the HopX API. This guide shows you how to get your API key, configure it securely, and use it with the SDKs, CLI, or REST API.
## Get Your API key
Sign up at [console.hopx.dev](https://console.hopx.dev) to get your free API key. After creating an account, you'll find your API key in the dashboard.
Your API key is shown only once when created. Make sure to save it securely. If you lose your key, you'll need to create a new one.
## API key Format
HopX API keys follow this format:
```
hopx_live_.
```
**Example:**
```
hopx_live_NXAXAV4sU3Ii.EXi3vR9kOJuhfbR5z42aFx5rhGjH1xnzFdjn9caAqps
```
Never share your API key publicly or commit it to version control. Treat it like a password.
## Setting Your API key
You can provide your API key in several ways. The SDKs check these sources in order:
### Method 1: Environment Variable (Recommended)
Set the `HOPX_API_KEY` environment variable. This is the most secure method and keeps your key out of your code.
```bash theme={null}
# Linux/macOS
export HOPX_API_KEY="hopx_live_..."
# Windows (PowerShell)
$env:HOPX_API_KEY="hopx_live_..."
# Windows (Command Prompt)
set HOPX_API_KEY=hopx_live_...
```
Then use the SDK without specifying the key:
```python theme={null}
from hopx_ai import Sandbox
# API key is automatically read from HOPX_API_KEY environment variable
sandbox = Sandbox.create(template="code-interpreter")
```
```bash theme={null}
# Linux/macOS
export HOPX_API_KEY="hopx_live_..."
# Windows (PowerShell)
$env:HOPX_API_KEY="hopx_live_..."
# Windows (Command Prompt)
set HOPX_API_KEY=hopx_live_...
```
Then use the SDK without specifying the key:
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// API key is automatically read from HOPX_API_KEY environment variable
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
```
### Method 2: Pass Directly to SDK
You can pass the API key directly when creating a sandbox:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(
template="code-interpreter",
api_key="hopx_live_..." # Pass directly
)
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: 'hopx_live_...' // Pass directly
});
```
Avoid hardcoding API keys in your source code. Use environment variables or secure secret management systems instead.
### Method 3: Configuration File
You can use configuration files or secret management systems:
```bash theme={null}
# .env file
HOPX_API_KEY=hopx_live_...
```
```python theme={null}
# Install python-dotenv: pip install python-dotenv
from dotenv import load_dotenv
load_dotenv()
from hopx_ai import Sandbox
# API key is automatically loaded from .env
sandbox = Sandbox.create(template="code-interpreter")
```
```bash theme={null}
# .env file
HOPX_API_KEY=hopx_live_...
```
```javascript theme={null}
// Install dotenv: npm install dotenv
import 'dotenv/config';
import { Sandbox } from '@hopx-ai/sdk';
// API key is automatically loaded from .env
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
```
The CLI automatically uses the `HOPX_API_KEY` environment variable. You can also configure it via:
```bash theme={null}
# Set environment variable
export HOPX_API_KEY="hopx_live_..."
# Or use CLI login (interactive)
hopx auth login
# Or set via CLI config
hopx config set api_key "hopx_live_..."
```
See [CLI Authentication](/cli/commands/auth) for more options.
## Using API Keys with Direct API Calls
When making direct HTTP requests to the HopX API, include your API key in the request headers:
### Header Format
You can use either of these header formats:
```bash theme={null}
# Option 1: Authorization header (recommended)
Authorization: Bearer hopx_live_...
# Option 2: X-API-Key header
X-API-Key: hopx_live_...
```
### Example: Creating a Sandbox
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer hopx_live_..." \
-H "Content-Type: application/json" \
-d '{
"template_id": "code-interpreter"
}'
```
### Example: Listing Sandboxes
```bash theme={null}
curl https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer hopx_live_..."
```
## Security Best Practices
Never commit API keys to version control. Use environment variables, secret management services (AWS Secrets Manager, HashiCorp Vault), or secure configuration files.
Periodically rotate your API keys, especially if you suspect they may have been compromised. Create new keys in the console and update your applications.
Use separate API keys for development, staging, and production environments. This allows you to revoke access to specific environments without affecting others.
Regularly review your API key usage in the console to detect any unauthorized access or unusual activity.
If your organization supports it, create API keys with limited permissions for specific use cases (e.g., read-only keys for monitoring).
## Testing Your API key
You can test your API key by making a simple API call:
```python theme={null}
from hopx_ai import Sandbox
try:
# Try to list templates (requires valid API key)
templates = Sandbox.list_templates()
print(f"✅ API key is valid! Found {len(templates)} templates.")
except Exception as e:
print(f"❌ API key error: {e}")
```
**Expected Output:**
```
✅ API key is valid! Found 15 templates.
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
try {
// Try to list templates (requires valid API key)
const templates = await Sandbox.listTemplates();
console.log(`✅ API key is valid! Found ${templates.length} templates.`);
} catch (error) {
console.error(`❌ API key error: ${error.message}`);
}
```
**Expected Output:**
```
✅ API key is valid! Found 15 templates.
```
```bash theme={null}
curl https://api.hopx.dev/v1/templates \
-H "Authorization: Bearer hopx_live_..."
```
If your key is valid, you'll receive a JSON response with available templates. If invalid, you'll get a `401 Unauthorized` error.
## Troubleshooting
### Invalid API key Error
If you receive an authentication error:
1. **Verify the key format**: Ensure your key starts with `hopx_live_` and contains both the key ID and secret separated by a dot.
2. **Check for extra spaces**: Make sure there are no leading or trailing spaces when copying the key.
3. **Verify environment variable**: If using environment variables, confirm it's set correctly:
```bash theme={null}
echo $HOPX_API_KEY # Linux/macOS
echo %HOPX_API_KEY% # Windows
```
4. **Check key status**: Log into [console.hopx.dev](https://console.hopx.dev) to verify your key is active and not revoked.
### Key Not Found
If the SDK can't find your API key:
1. **Check environment variable name**: Ensure it's exactly `HOPX_API_KEY` (case-sensitive on some systems).
2. **Restart your terminal/IDE**: Environment variables may not be loaded in your current session.
3. **Verify the key is set**: Use the troubleshooting commands above to confirm the variable is set.
### Rate Limiting
If you receive rate limit errors:
* Your API key has usage limits based on your plan
* Wait a few moments and retry your request
* Consider implementing exponential backoff in your application
* Upgrade your plan if you need higher rate limits
## Related
* **[API Authentication](/api/authentication)** - Learn about API authentication
* **[Python SDK Quickstart](/sdk/python/quickstart)** - Get started with the Python SDK
* **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Get started with the JavaScript SDK
* **[API Quickstart](/api/quickstart)** - Make your first API request
## Next Steps
* Follow the [Quickstart Guide](/quickstart) to create your first sandbox
* Learn about [Supported Languages](/supported-languages) for code execution
* Explore [MCP Integration](/guides/integrations/mcp-integration) for AI assistant integration
# Authentication
Source: https://docs.hopx.ai/api/authentication
Learn how to authenticate requests to the HopX API using API keys. Secure your API requests with authentication headers, manage API keys, and understand authentication best practices. Essential for accessing HopX Control Plane and VM Agent APIs. Includes authentication examples, security guidelines, and API key management.
All requests to the HopX API require authentication using an API key. This guide shows you how to get your API key, configure it securely, and use it in API requests.
## Get Your API key
Sign up at [console.hopx.dev](https://console.hopx.dev) to get your free API key. After creating an account, navigate to the API Keys section in your dashboard to create and manage keys.
Your API key is shown only once when created. Make sure to save it securely. If you lose your key, you'll need to create a new one from the dashboard.
## API key Format
HopX API keys follow this format:
```
hopx_live_.
```
**Example:**
```
hopx_live_NXAXAV4sU3Ii.EXi3vR9kOJuhfbR5z42aFx5rhGjH1xnzFdjn9caAqps
```
The key consists of:
* **Prefix**: `hopx_live_` (indicates a live/production key)
* **Key ID**: 12-character alphanumeric identifier (public, used for identification)
* **Secret**: 32-byte cryptographically random secret (base64url encoded)
Never share your API key publicly or commit it to version control. Treat it like a password. If your key is exposed, revoke it immediately and create a new one.
## Authentication Methods
The HopX API supports two authentication header formats:
### Method 1: Authorization Header (Recommended)
Include your API key in the `Authorization` header using Bearer authentication:
```bash theme={null}
curl -H "Authorization: Bearer $HOPX_API_KEY" \
https://api.hopx.dev/v1/sandboxes
```
Replace `$HOPX_API_KEY` with your actual API key from [console.hopx.dev](https://console.hopx.dev), or set it as an environment variable: `export HOPX_API_KEY="your-API key-here"`
### Method 2: X-API key Header
Alternatively, use the `X-API key` header:
```bash theme={null}
curl -H "X-API key: $HOPX_API_KEY" \
https://api.hopx.dev/v1/sandboxes
```
Replace `$HOPX_API_KEY` with your actual API key from [console.hopx.dev](https://console.hopx.dev), or set it as an environment variable: `export HOPX_API_KEY="your-API key-here"`
Both methods are equivalent. Use whichever is more convenient for your setup.
## Complete Request Example
Here's a complete authenticated request to create a sandbox:
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer hopx_live_NXAXAV4sU3Ii.EXi3vR9kOJuhfbR5z42aFx5rhGjH1xnzFdjn9caAqps" \
-H "Content-Type: application/json" \
-d '{
"template_id": "73",
"timeout_seconds": 3600
}'
```
## Security Best Practices
### 1. Use Environment Variables
Store your API key in an environment variable rather than hardcoding it:
```bash theme={null}
# Set environment variable
export HOPX_API_KEY="hopx_live_NXAXAV4sU3Ii.EXi3vR9kOJuhfbR5z42aFx5rhGjH1xnzFdjn9caAqps"
# Use in request
curl -H "Authorization: Bearer $HOPX_API_KEY" \
https://api.hopx.dev/v1/sandboxes
```
### 2. Use Least Privilege
Only grant API keys the minimum permissions needed for your use case. If you're only reading sandbox information, don't use a key with full write access.
### 3. Rotate Keys Regularly
Periodically rotate your API keys, especially if you suspect they may have been compromised. Create new keys in the dashboard and update your applications.
### 4. Monitor Key Usage
Review API key usage in your dashboard to detect any unauthorized access. If you see unexpected activity, revoke the key immediately.
## Authentication Errors
### 401 Unauthorized
If your API key is missing, invalid, or expired, you'll receive a 401 error:
```json theme={null}
{
"error": "Unauthorized",
"code": "AUTHENTICATION_REQUIRED",
"request_id": "req_abc123"
}
```
**Common causes:**
* Missing `Authorization` or `X-API key` header
* Invalid API key format
* Revoked or expired API key
**Fix:**
* Verify your API key is correct
* Check that the key hasn't been revoked in your dashboard
* Ensure you're using the correct header format
### 403 Forbidden
If your API key doesn't have permission for the requested operation:
```json theme={null}
{
"error": "Forbidden",
"code": "INSUFFICIENT_PERMISSIONS",
"request_id": "req_abc123"
}
```
**Fix:**
* Verify your API key has the required permissions
* Check your account's access level in the dashboard
## Public Endpoints
The following endpoints do **not** require authentication:
* `GET /health` - Health check endpoint
All other endpoints require a valid API key.
## Related
* **\[API key Management]\(/API key)** - Manage API keys in the dashboard
* **[Python SDK Quickstart](/sdk/python/quickstart)** - Get started with the Python SDK
* **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Get started with the JavaScript SDK
* **[API Quickstart](/api/quickstart)** - Make your first API request
* [CLI Reference](/cli/introduction) - Command-line interface
## Next Steps
* **[Quickstart](/api/quickstart)** - Create your first sandbox with a complete example
* **[Control Plane API](/api/control-plane/overview)** - Learn about sandbox management endpoints
* **\[Get API key]\(/API key)** - Detailed guide on obtaining and managing API keys
# Data Model
Source: https://docs.hopx.ai/api/concepts/data-model
Core resources and data structures in the HopX API. Understand sandbox objects, template structures, execution results, file metadata, and other data models used throughout the HopX API. Essential for working with API responses and building integrations. Includes data model reference and field descriptions.
The HopX API uses a consistent data model across all endpoints. Understanding these core resources and their relationships is essential for effective API usage.
## Core Resources
### Sandbox
A sandbox is an isolated virtual machine environment for code execution. Each sandbox has:
| Field | Type | Description |
| ------------------ | ------- | ----------------------------------- |
| `id` | string | Unique sandbox identifier |
| `status` | string | Current status (see statuses below) |
| `template_id` | string | Template ID used to create sandbox |
| `template_name` | string | Template name |
| `region` | string | Deployment region |
| `resources` | object | Allocated vCPU, memory, disk |
| `auth_token` | string | JWT token for VM Agent API access |
| `token_expires_at` | string | JWT token expiration (ISO 8601) |
| `public_host` | string | VM Agent API base URL |
| `timeout_seconds` | integer | Auto-shutdown timeout |
| `created_at` | string | Creation timestamp (ISO 8601) |
| `updated_at` | string | Last update timestamp (ISO 8601) |
#### Sandbox Statuses
| Status | Description |
| ---------- | ------------------------------------- |
| `creating` | Sandbox is being created |
| `running` | Sandbox is active and ready |
| `stopped` | Sandbox is stopped (can be restarted) |
| `paused` | Sandbox is paused (RAM preserved) |
| `error` | Sandbox creation or operation failed |
| `deleted` | Sandbox has been deleted |
#### Sandbox Lifecycle
```
creating → running ⟷ stopped
↓
paused → running
↓
deleted
```
### Template
A template defines the base image and resources for creating sandboxes:
| Field | Type | Description |
| ------------------- | ------- | ------------------------------------------------ |
| `id` | string | Unique template identifier |
| `name` | string | Template name (unique, used as identifier) |
| `display_name` | string | Human-readable name |
| `description` | string | Template description |
| `category` | string | Template category (python, nodejs, ubuntu, etc.) |
| `language` | string | Primary programming language |
| `default_resources` | object | Default vCPU, memory, disk allocation |
| `features` | array | Supported features |
| `is_public` | boolean | Whether template is publicly available |
| `is_active` | boolean | Whether template is ready for use |
| `status` | string | Template status (active, building, failed) |
#### Template Categories
* **python** - Python environments (various versions)
* **nodejs** - Node.js environments
* **ubuntu** - Ubuntu base images
* **code-interpreter** - Multi-language execution environments
* **custom** - Custom organization templates
### Execution Result
Result from code execution or command:
| Field | Type | Description |
| ---------------- | ------- | --------------------------- |
| `success` | boolean | Whether execution succeeded |
| `stdout` | string | Standard output |
| `stderr` | string | Standard error |
| `exit_code` | integer | Exit code (0 = success) |
| `execution_time` | number | Execution time in seconds |
For rich output capture, additional fields:
| Field | Type | Description |
| -------------- | ----- | ---------------------------- |
| `rich_outputs` | array | Array of rich output objects |
Each rich output object:
| Field | Type | Description |
| ---------- | ------ | -------------------------------------- |
| `type` | string | MIME type (image/png, text/html, etc.) |
| `format` | string | Data format (base64, text) |
| `data` | string | Output data |
| `metadata` | object | Additional metadata |
### Process
Background execution process:
| Field | Type | Description |
| -------------- | ------- | --------------------------------------------------- |
| `process_id` | string | Unique process identifier |
| `execution_id` | string | Execution ID |
| `name` | string | Process name (optional) |
| `status` | string | Process status (queued, running, completed, failed) |
| `language` | string | Programming language |
| `started_at` | string | Start timestamp (ISO 8601) |
| `completed_at` | string | Completion timestamp (ISO 8601, if complete) |
| `stdout` | string | Standard output |
| `stderr` | string | Standard error |
| `exit_code` | integer | Exit code (null if still running) |
## Object Types
All API responses include an `object` field identifying the resource type:
| Object Type | Description |
| ----------- | --------------------------------- |
| `sandbox` | Sandbox resource |
| `template` | Template resource |
| `list` | List of resources with pagination |
| `error` | Error response |
## List Objects
List endpoints return a consistent structure:
```json theme={null}
{
"object": "list",
"data": [...],
"has_more": false,
"next_cursor": null,
"url": "/v1/sandboxes",
"request_id": "req_abc123"
}
```
| Field | Type | Description |
| ------------- | ------- | ----------------------------------- |
| `object` | string | Always "list" |
| `data` | array | Array of resource objects |
| `has_more` | boolean | Whether more results exist |
| `next_cursor` | string | Cursor for next page (if has\_more) |
| `url` | string | Endpoint URL |
| `request_id` | string | Request ID for debugging |
## Timestamps
All timestamps use ISO 8601 format with UTC timezone:
```
2025-01-28T00:00:00Z
```
Example timestamps:
* `created_at` - Resource creation time
* `updated_at` - Last modification time
* `completed_at` - Task completion time
* `expires_at` - Expiration time
* `token_expires_at` - JWT token expiration
## Identifiers
### Format
Identifiers follow consistent patterns:
| Prefix | Resource Type | Example |
| ----------- | -------------- | ------------------- |
| `sandbox_` | Sandbox | `sandbox_abc123xyz` |
| `template_` | Template | `template_xyz789` |
| `proc_` | Process | `proc_abc123` |
| `exec_` | Execution | `exec_xyz789` |
| `req_` | Request | `req_abc123` |
| `build_` | Template Build | `build_abc123` |
### Usage
* Identifiers are **case-sensitive**
* Store identifiers as returned by the API
* Use template `name` or `id` when creating sandboxes
## Resource Relationships
```
Template (1) ──creates──> (N) Sandbox
│
├──has──> (1) JWT Token
│
└──runs──> (N) Process/Execution
```
* One template can create multiple sandboxes
* Each sandbox has one JWT token (refreshable)
* Each sandbox can have multiple concurrent processes/executions
## Common Patterns
### Create → Poll → Use
```bash theme={null}
# 1. Create resource
RESPONSE=$(curl -X POST https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"template_id": "code-interpreter"}')
SANDBOX_ID=$(echo "$RESPONSE" | jq -r '.id')
# 2. Poll until ready (status: running)
while true; do
STATUS=$(curl -s "https://api.hopx.dev/v1/sandboxes/$SANDBOX_ID" \
-H "Authorization: Bearer $HOPX_API_KEY" | jq -r '.status')
[ "$STATUS" == "running" ] && break
sleep 2
done
# 3. Use resource
JWT_TOKEN=$(curl -s "https://api.hopx.dev/v1/sandboxes/$SANDBOX_ID" \
-H "Authorization: Bearer $HOPX_API_KEY" | jq -r '.auth_token')
curl -X POST "https://$SANDBOX_ID.hopx.dev/execute" \
-H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"code": "print(\"Hello World\")", "language": "python"}'
```
## Related
* **[API Introduction](/api/introduction)** - Learn about the HopX API
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn about sandbox creation
* **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle
* **[Control Plane API Overview](/api/control-plane/overview)** - Manage sandboxes via API
* **[VM Agent API Overview](/api/vm-agent/overview)** - Execute code via API
* [CLI Reference](/cli/introduction) - Command-line interface
## Next Steps
* **[Errors](/api/concepts/errors)** - Error handling and codes
* **[Rate Limits](/api/concepts/rate-limits)** - Request rate limits
* **[Pagination](/api/concepts/pagination)** - Paginating list results
# Error Handling
Source: https://docs.hopx.ai/api/concepts/errors
Error handling, error codes, and troubleshooting in the HopX API. Understand API error responses, HTTP status codes, error message formats, and how to handle errors gracefully in your applications. Essential for building robust integrations with HopX APIs. Includes error code reference and troubleshooting guides.
The HopX API uses conventional HTTP status codes and returns detailed error responses to help you troubleshoot issues.
## Error Response Format
All errors return a JSON response with this structure:
```json theme={null}
{
"error": "Error message describing what went wrong",
"code": "ERROR_CODE",
"request_id": "req_abc123"
}
```
| Field | Type | Description |
| ------------ | ------ | -------------------------------- |
| `error` | string | Human-readable error message |
| `code` | string | Machine-readable error code |
| `request_id` | string | Request ID for support/debugging |
## HTTP Status Codes
| Code | Meaning | Description |
| ---- | --------------------- | ---------------------------------------- |
| 200 | OK | Request succeeded |
| 202 | Accepted | Request accepted (async operation) |
| 204 | No Content | Request succeeded, no response body |
| 400 | Bad Request | Invalid request parameters |
| 401 | Unauthorized | Authentication failed or missing |
| 403 | Forbidden | Access denied |
| 404 | Not Found | Resource not found |
| 408 | Request Timeout | Request exceeded timeout |
| 409 | Conflict | Resource conflict (e.g., already exists) |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server error |
| 503 | Service Unavailable | Service temporarily unavailable |
## Error Codes
### Authentication Errors
#### AUTHENTICATION\_REQUIRED (401)
```json theme={null}
{
"error": "Authentication required",
"code": "AUTHENTICATION_REQUIRED",
"request_id": "req_abc123"
}
```
**Cause:** No API key or JWT token provided.
**Fix:** Include `Authorization: Bearer $HOPX_API_KEY` header.
#### INVALID\_TOKEN (401)
```json theme={null}
{
"error": "Invalid or expired token",
"code": "INVALID_TOKEN",
"request_id": "req_abc123"
}
```
**Cause:** JWT token is invalid or expired.
**Fix:** Refresh the JWT token using the Control Plane API.
### Request Errors
#### INVALID\_REQUEST (400)
```json theme={null}
{
"error": "Invalid request: missing required field 'code'",
"code": "INVALID_REQUEST",
"request_id": "req_abc123"
}
```
**Cause:** Missing required parameters or invalid request format.
**Fix:** Check the request body and ensure all required fields are present.
#### RESOURCE\_NOT\_FOUND (404)
```json theme={null}
{
"error": "Sandbox not found",
"code": "RESOURCE_NOT_FOUND",
"request_id": "req_abc123"
}
```
**Cause:** The requested resource doesn't exist.
**Fix:** Verify the resource ID is correct.
#### CONFLICT (409)
```json theme={null}
{
"error": "Template already exists. Set update=true to update it.",
"code": "CONFLICT",
"request_id": "req_abc123"
}
```
**Cause:** Resource already exists.
**Fix:** Use a different name or set `update=true`.
### Execution Errors
#### EXECUTION\_TIMEOUT (408)
```json theme={null}
{
"error": "Execution timeout after 60 seconds",
"code": "EXECUTION_TIMEOUT",
"request_id": "req_abc123"
}
```
**Cause:** Code execution exceeded the timeout limit.
**Fix:** Increase the timeout or optimize your code.
#### CODE\_EXECUTION\_ERROR (500)
```json theme={null}
{
"success": false,
"stdout": "",
"stderr": "NameError: name 'x' is not defined\n",
"exit_code": 1,
"execution_time": 0.05
}
```
**Cause:** Code execution failed (syntax error, runtime error, etc.).
**Fix:** Check the `stderr` field for error details and fix your code.
### Resource Errors
#### PAYMENT\_REQUIRED (402)
```json theme={null}
{
"error": "Payment required: credit limit exceeded",
"code": "PAYMENT_REQUIRED",
"request_id": "req_abc123"
}
```
**Cause:** Account credit limit reached or payment method required.
**Fix:** Add payment method or increase credit limit.
#### RESOURCE\_LIMIT\_ERROR (429)
```json theme={null}
{
"error": "Sandbox limit reached (10/10)",
"code": "RESOURCE_LIMIT_ERROR",
"request_id": "req_abc123"
}
```
**Cause:** Account resource limit reached.
**Fix:** Delete unused sandboxes or upgrade your plan.
#### FORBIDDEN (403)
```json theme={null}
{
"error": "Path not allowed: /etc/passwd",
"code": "FORBIDDEN",
"request_id": "req_abc123"
}
```
**Cause:** Access to resource or path is forbidden.
**Fix:** Only access allowed paths (e.g., `/workspace`, `/tmp`).
### Rate Limiting
#### RATE\_LIMIT\_EXCEEDED (429)
```json theme={null}
{
"error": "Rate limit exceeded: 100 requests per minute",
"code": "RATE_LIMIT_EXCEEDED",
"request_id": "req_abc123",
"retry_after": 30
}
```
**Cause:** Too many requests in a short time.
**Fix:** Wait and retry. Use exponential backoff.
See [Rate Limits](/api/concepts/rate-limits) for details.
### Service Errors
#### SERVICE\_UNAVAILABLE (503)
```json theme={null}
{
"error": "Service temporarily unavailable",
"code": "SERVICE_UNAVAILABLE",
"request_id": "req_abc123"
}
```
**Cause:** Service is temporarily down or overloaded.
**Fix:** Retry with exponential backoff.
#### INTERNAL\_ERROR (500)
```json theme={null}
{
"error": "Internal server error",
"code": "INTERNAL_ERROR",
"request_id": "req_abc123"
}
```
**Cause:** Unexpected server error.
**Fix:** Retry the request. Contact support with `request_id` if issue persists.
## Error Handling Best Practices
### 1. Check Status Codes
```bash theme={null}
RESPONSE=$(curl -s -w "\n%{http_code}" https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY")
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
BODY=$(echo "$RESPONSE" | sed '$d')
if [ "$HTTP_CODE" -ge 400 ]; then
echo "Error: $BODY"
exit 1
fi
```
### 2. Parse Error Responses
```python theme={null}
import requests
response = requests.post(
"https://api.hopx.dev/v1/sandboxes",
headers={"Authorization": "Bearer $HOPX_API_KEY"},
json={"template_id": "code-interpreter"}
)
if response.status_code >= 400:
error = response.json()
print(f"Error: {error['error']}")
print(f"Code: {error['code']}")
print(f"Request ID: {error['request_id']}")
exit(1)
```
### 3. Implement Retry Logic
```python theme={null}
import time
import requests
def create_sandbox_with_retry(max_retries=3):
for attempt in range(max_retries):
try:
response = requests.post(
"https://api.hopx.dev/v1/sandboxes",
headers={"Authorization": "Bearer $HOPX_API_KEY"},
json={"template_id": "code-interpreter"},
timeout=30
)
if response.status_code == 200:
return response.json()
# Retry on 5xx errors or rate limits
if response.status_code >= 500 or response.status_code == 429:
wait_time = 2 ** attempt # Exponential backoff
print(f"Retry {attempt + 1}/{max_retries} after {wait_time}s")
time.sleep(wait_time)
continue
# Don't retry on 4xx errors (except 429)
response.raise_for_status()
except requests.exceptions.RequestException as e:
if attempt == max_retries - 1:
raise
time.sleep(2 ** attempt)
raise Exception("Max retries exceeded")
```
### 4. Handle Specific Errors
```python theme={null}
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 401:
# Refresh token and retry
refresh_token()
response = requests.post(url, headers=headers, json=payload)
elif response.status_code == 404:
# Resource not found - create it
create_resource()
elif response.status_code == 429:
# Rate limited - wait and retry
time.sleep(60)
response = requests.post(url, headers=headers, json=payload)
```
## Getting Support
When contacting support, always include:
1. **Request ID** - From the error response
2. **Timestamp** - When the error occurred
3. **API endpoint** - The URL you called
4. **HTTP status code** - The response status
5. **Error message** - The full error response
Example support request:
```
Request ID: req_abc123
Timestamp: 2025-01-28T00:00:00Z
Endpoint: POST /v1/sandboxes
Status: 500
Error: Internal server error
```
## Related
* **[API Introduction](/api/introduction)** - Learn about the HopX API
* **[Rate Limits](/api/concepts/rate-limits)** - Understand rate limit errors
* **[Troubleshooting](/api/concepts/troubleshooting)** - Debug common issues
* **[Data Model](/api/concepts/data-model)** - Learn about API resources
* **[Python SDK Quickstart](/sdk/python/quickstart)** - Use the Python SDK (handles errors automatically)
* [CLI Reference](/cli/introduction) - Command-line interface
## Next Steps
* **[Rate Limits](/api/concepts/rate-limits)** - Understand rate limiting
* **[Data Model](/api/concepts/data-model)** - Core resources and data structures
* **[Troubleshooting](/api/concepts/troubleshooting)** - Common issues and solutions
# Pagination
Source: https://docs.hopx.ai/api/concepts/pagination
Paginating HopX API list results using cursor-based pagination. Navigate through large result sets efficiently using cursor-based pagination. Learn how to use pagination parameters, handle page boundaries, and iterate through all results. Essential for listing sandboxes, templates, and other resources. Includes pagination examples and best practices.
The HopX API uses cursor-based pagination for list endpoints. This provides consistent, efficient pagination even when data is being added or removed.
## List Response Format
All list endpoints return a consistent structure:
```json theme={null}
{
"object": "list",
"data": [
{"id": "sandbox_1", ...},
{"id": "sandbox_2", ...}
],
"has_more": true,
"next_cursor": "cursor_abc123",
"url": "/v1/sandboxes",
"request_id": "req_abc123"
}
```
| Field | Type | Description |
| ------------- | ------- | ---------------------------------------------- |
| `object` | string | Always "list" |
| `data` | array | Array of resource objects |
| `has_more` | boolean | Whether more results exist |
| `next_cursor` | string | Cursor for next page (null if no more results) |
| `url` | string | Endpoint URL |
| `request_id` | string | Request ID |
## Pagination Parameters
### cursor
Use the `cursor` query parameter to fetch the next page:
```bash theme={null}
# First page
curl "https://api.hopx.dev/v1/sandboxes" \
-H "Authorization: Bearer $HOPX_API_KEY"
# Next page (using cursor from previous response)
curl "https://api.hopx.dev/v1/sandboxes?cursor=cursor_abc123" \
-H "Authorization: Bearer $HOPX_API_KEY"
```
### limit
Control the number of results per page with the `limit` parameter:
```bash theme={null}
curl "https://api.hopx.dev/v1/sandboxes?limit=50" \
-H "Authorization: Bearer $HOPX_API_KEY"
```
Default limits vary by endpoint:
* Sandboxes: 20 per page
* Templates: 50 per page
Maximum limit: 100 per page
## Paginating Through Results
### Example: Fetch All Sandboxes
```python theme={null}
import requests
def get_all_sandboxes(api_key):
url = "https://api.hopx.dev/v1/sandboxes"
headers = {"Authorization": f"Bearer {api_key}"}
all_sandboxes = []
cursor = None
while True:
params = {"limit": 100}
if cursor:
params["cursor"] = cursor
response = requests.get(url, headers=headers, params=params)
data = response.json()
all_sandboxes.extend(data["data"])
if not data["has_more"]:
break
cursor = data["next_cursor"]
return all_sandboxes
sandboxes = get_all_sandboxes("$HOPX_API_KEY")
print(f"Total sandboxes: {len(sandboxes)}")
```
### Example: Fetch with Progress
```python theme={null}
def get_all_sandboxes_with_progress(api_key):
url = "https://api.hopx.dev/v1/sandboxes"
headers = {"Authorization": f"Bearer {api_key}"}
all_sandboxes = []
cursor = None
page = 1
while True:
params = {"limit": 50}
if cursor:
params["cursor"] = cursor
response = requests.get(url, headers=headers, params=params)
data = response.json()
page_sandboxes = data["data"]
all_sandboxes.extend(page_sandboxes)
print(f"Page {page}: Fetched {len(page_sandboxes)} sandboxes (total: {len(all_sandboxes)})")
if not data["has_more"]:
print("No more results")
break
cursor = data["next_cursor"]
page += 1
return all_sandboxes
```
## Cursor-Based Pagination Benefits
### Consistent Results
Cursor-based pagination provides consistent results even when data changes:
```python theme={null}
# Offset-based (bad) - can miss or duplicate items if data changes
response1 = get("/sandboxes?offset=0&limit=10")
# New sandbox created here
response2 = get("/sandboxes?offset=10&limit=10") # Might miss items!
# Cursor-based (good) - consistent results
response1 = get("/sandboxes?limit=10")
cursor = response1["next_cursor"]
# New sandbox created here
response2 = get(f"/sandboxes?cursor={cursor}&limit=10") # No duplicates or misses
```
### Performance
Cursor-based pagination is more efficient for large datasets:
* O(1) lookups using the cursor
* No need to count or skip rows
* Works well with databases
## Filtering with Pagination
Combine filters with pagination:
```bash theme={null}
# List running sandboxes with pagination
curl "https://api.hopx.dev/v1/sandboxes?status=running&limit=50" \
-H "Authorization: Bearer $HOPX_API_KEY"
# Next page
curl "https://api.hopx.dev/v1/sandboxes?status=running&limit=50&cursor=cursor_abc123" \
-H "Authorization: Bearer $HOPX_API_KEY"
```
Example with filters:
```python theme={null}
def get_running_sandboxes(api_key):
url = "https://api.hopx.dev/v1/sandboxes"
headers = {"Authorization": f"Bearer {api_key}"}
running_sandboxes = []
cursor = None
while True:
params = {
"status": "running",
"limit": 50
}
if cursor:
params["cursor"] = cursor
response = requests.get(url, headers=headers, params=params)
data = response.json()
running_sandboxes.extend(data["data"])
if not data["has_more"]:
break
cursor = data["next_cursor"]
return running_sandboxes
```
## Endpoints with Pagination
All list endpoints support pagination:
| Endpoint | Default Limit | Max Limit |
| ------------------- | ------------- | --------- |
| `GET /v1/sandboxes` | 20 | 100 |
| `GET /v1/templates` | 50 | 100 |
## Best Practices
### 1. Use Reasonable Page Sizes
```python theme={null}
# Good: Fetch manageable chunks
response = get("/v1/sandboxes?limit=50")
# Bad: Fetching too many at once
response = get("/v1/sandboxes?limit=1000") # Over max limit (100)
```
### 2. Store and Reuse Cursors
```python theme={null}
# Save cursor for resuming later
last_cursor = None
for page in range(5):
params = {"limit": 20}
if last_cursor:
params["cursor"] = last_cursor
response = get("/v1/sandboxes", params=params)
data = response.json()
process_sandboxes(data["data"])
if not data["has_more"]:
break
last_cursor = data["next_cursor"]
# Resume later with last_cursor
```
### 3. Handle Empty Results
```python theme={null}
response = requests.get(url, headers=headers)
data = response.json()
if not data["data"]:
print("No results found")
elif not data["has_more"]:
print("This is the last page")
```
## Shell Script Example
```bash theme={null}
#!/bin/bash
API_KEY="$HOPX_API_KEY"
URL="https://api.hopx.dev/v1/sandboxes"
CURSOR=""
PAGE=1
while true; do
# Build URL with cursor if available
if [ -z "$CURSOR" ]; then
REQUEST_URL="$URL?limit=50"
else
REQUEST_URL="$URL?limit=50&cursor=$CURSOR"
fi
# Fetch page
RESPONSE=$(curl -s "$REQUEST_URL" -H "Authorization: Bearer $API_KEY")
# Extract data
COUNT=$(echo "$RESPONSE" | jq '.data | length')
HAS_MORE=$(echo "$RESPONSE" | jq -r '.has_more')
echo "Page $PAGE: $COUNT sandboxes"
# Check if more pages exist
if [ "$HAS_MORE" != "true" ]; then
echo "No more results"
break
fi
# Get next cursor
CURSOR=$(echo "$RESPONSE" | jq -r '.next_cursor')
PAGE=$((PAGE + 1))
done
```
## Related
* **[API Introduction](/api/introduction)** - Learn about the HopX API
* **[Rate Limits](/api/concepts/rate-limits)** - Understand API rate limits
* **[Data Model](/api/concepts/data-model)** - Learn about API resources
* **[Python SDK Quickstart](/sdk/python/quickstart)** - Use the Python SDK (handles pagination automatically)
* [CLI Reference](/cli/introduction) - Command-line interface
## Next Steps
* **[Data Model](/api/concepts/data-model)** - Core resources and data structures
* **[Rate Limits](/api/concepts/rate-limits)** - Request rate limits
* **[Errors](/api/concepts/errors)** - Error handling and codes
# Rate Limits
Source: https://docs.hopx.ai/api/concepts/rate-limits
API rate limits, headers, and best practices for the HopX API. Understand rate limit policies, check rate limit headers, handle rate limit errors, and implement best practices for high-volume API usage. Essential for building scalable applications with HopX APIs. Includes rate limit examples and optimization strategies.
The HopX API implements rate limiting to ensure fair usage and system stability. Rate limits vary by endpoint and account plan.
## Rate Limit Tiers
### Default Limits
| Endpoint Type | Limit | Window |
| ----------------- | ------------ | ---------- |
| Control Plane API | 100 requests | per minute |
| VM Agent API | 300 requests | per minute |
| Template Builds | 10 builds | per hour |
| Sandbox Creation | 20 sandboxes | per minute |
### Plan-Based Limits
Rate limits may vary based on your account plan:
* **Free Tier** - Default limits
* **Pro Tier** - 2x default limits
* **Enterprise** - Custom limits
## Rate Limit Headers
Every API response includes rate limit headers:
```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1706400060
```
| Header | Description |
| ----------------------- | -------------------------------------- |
| `X-RateLimit-Limit` | Maximum requests allowed in the window |
| `X-RateLimit-Remaining` | Requests remaining in current window |
| `X-RateLimit-Reset` | Unix timestamp when the limit resets |
## Rate Limit Exceeded
When you exceed the rate limit, you'll receive a `429 Too Many Requests` response:
```json theme={null}
{
"error": "Rate limit exceeded: 100 requests per minute",
"code": "RATE_LIMIT_EXCEEDED",
"request_id": "req_abc123",
"retry_after": 30
}
```
The `retry_after` field indicates how many seconds to wait before retrying.
## Best Practices
### 1. Monitor Rate Limit Headers
```python theme={null}
import requests
response = requests.get(
"https://api.hopx.dev/v1/sandboxes",
headers={"Authorization": "Bearer $HOPX_API_KEY"}
)
remaining = int(response.headers.get('X-RateLimit-Remaining', 0))
limit = int(response.headers.get('X-RateLimit-Limit', 0))
print(f"Rate limit: {remaining}/{limit}")
if remaining < 10:
print("Warning: Approaching rate limit")
```
### 2. Implement Exponential Backoff
```python theme={null}
import time
import requests
def make_request_with_backoff(url, headers, max_retries=5):
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code != 429:
return response
# Rate limited - wait and retry
retry_after = int(response.headers.get('Retry-After', 2 ** attempt))
print(f"Rate limited. Retrying after {retry_after}s")
time.sleep(retry_after)
raise Exception("Max retries exceeded")
```
### 3. Batch Operations
Instead of making many individual requests, batch operations when possible:
```python theme={null}
# Bad: One request per sandbox
for sandbox_id in sandbox_ids:
response = requests.get(
f"https://api.hopx.dev/v1/sandboxes/{sandbox_id}",
headers=headers
)
process(response.json())
# Good: One request for all sandboxes
response = requests.get(
"https://api.hopx.dev/v1/sandboxes",
headers=headers
)
sandboxes = response.json()["data"]
for sandbox in sandboxes:
process(sandbox)
```
### 4. Cache Responses
Cache responses that don't change frequently:
```python theme={null}
import time
from functools import lru_cache
@lru_cache(maxsize=100)
def get_template(template_id, cache_time):
response = requests.get(
f"https://api.hopx.dev/v1/templates/{template_id}",
headers={"Authorization": "Bearer $HOPX_API_KEY"}
)
return response.json()
# Cache for 5 minutes
cache_key = int(time.time() // 300)
template = get_template("code-interpreter", cache_key)
```
### 5. Distribute Requests Over Time
```python theme={null}
import time
sandboxes_to_create = 50
rate_limit_per_minute = 20
delay = 60 / rate_limit_per_minute # 3 seconds
for i in range(sandboxes_to_create):
create_sandbox()
if i < sandboxes_to_create - 1:
time.sleep(delay)
```
## Rate Limit Strategies
### Sliding Window
Rate limits use a sliding window algorithm, not a fixed window. This means:
* Limits are enforced per 60-second rolling window
* Request counts decay as time passes
* Burst traffic is allowed up to the limit
### Per-Endpoint Limits
Some endpoints have separate rate limits:
| Endpoint | Limit | Reason |
| ---------------------- | ---------- | ---------------------------- |
| `/v1/templates/build` | 10/hour | Resource-intensive operation |
| `/v1/sandboxes` (POST) | 20/minute | Prevent abuse |
| `/v1/sandboxes` (GET) | 100/minute | Standard limit |
## Handling Rate Limits in Production
### Production-Ready Handler
```python theme={null}
import time
import requests
from typing import Optional
class RateLimitedClient:
def __init__(self, api_key: str):
self.api_key = api_key
self.base_url = "https://api.hopx.dev"
self.headers = {"Authorization": f"Bearer {api_key}"}
def request(self, method: str, path: str, **kwargs) -> requests.Response:
max_retries = 5
for attempt in range(max_retries):
response = requests.request(
method,
f"{self.base_url}{path}",
headers=self.headers,
**kwargs
)
# Success
if response.status_code < 400:
return response
# Rate limited
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 2 ** attempt))
print(f"Rate limited. Waiting {retry_after}s (attempt {attempt + 1}/{max_retries})")
time.sleep(retry_after)
continue
# Other errors - don't retry
response.raise_for_status()
raise Exception("Max retries exceeded due to rate limiting")
def get(self, path: str, **kwargs) -> requests.Response:
return self.request("GET", path, **kwargs)
def post(self, path: str, **kwargs) -> requests.Response:
return self.request("POST", path, **kwargs)
# Usage
client = RateLimitedClient("$HOPX_API_KEY")
response = client.get("/v1/sandboxes")
sandboxes = response.json()
```
## Increasing Rate Limits
If you need higher rate limits:
1. **Upgrade Your Plan** - Higher tiers include increased limits
2. **Contact Support** - Request custom limits for your use case
3. **Optimize Your Code** - Reduce unnecessary API calls
## Monitoring Usage
Check your current usage via the API:
```bash theme={null}
curl https://api.hopx.dev/v1/account/usage \
-H "Authorization: Bearer $HOPX_API_KEY"
```
Response:
```json theme={null}
{
"rate_limits": {
"control_plane": {
"limit": 100,
"remaining": 85,
"reset_at": "2025-01-28T00:01:00Z"
},
"vm_agent": {
"limit": 300,
"remaining": 250,
"reset_at": "2025-01-28T00:01:00Z"
}
}
}
```
## Related
* **[API Introduction](/api/introduction)** - Learn about the HopX API
* **[Error Handling](/api/concepts/errors)** - Handle rate limit errors
* **[Pagination](/api/concepts/pagination)** - Paginate list results
* **[Troubleshooting](/api/concepts/troubleshooting)** - Debug API issues
* [CLI Reference](/cli/introduction) - Command-line interface
## Next Steps
* **[Errors](/api/concepts/errors)** - Error handling and codes
* **[Pagination](/api/concepts/pagination)** - Paginating list results
* **[Troubleshooting](/api/concepts/troubleshooting)** - Common issues and solutions
# Troubleshooting
Source: https://docs.hopx.ai/api/concepts/troubleshooting
Common issues, solutions, and debugging tips for the HopX API. Resolve authentication errors, handle API errors, debug connection issues, and troubleshoot common problems when using HopX APIs. Essential for building reliable integrations. Includes troubleshooting guides, error solutions, and debugging strategies.
This guide covers common issues you might encounter when using the HopX API and how to resolve them.
## Authentication Issues
### Invalid API key
**Problem:** Receiving `401 Unauthorized` errors.
```json theme={null}
{
"error": "Invalid API key",
"code": "AUTHENTICATION_REQUIRED"
}
```
**Solutions:**
1. Verify your API key is correct
2. Check the `Authorization` header format: `Authorization: Bearer $HOPX_API_KEY`
3. Ensure no extra spaces or newlines in the API key
4. Generate a new API key from the dashboard
```bash theme={null}
# Correct
curl https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer sk-live-abc123xyz"
# Wrong - missing "Bearer"
curl https://api.hopx.dev/v1/sandboxes \
-H "Authorization: sk-live-abc123xyz"
```
### Expired JWT Token
**Problem:** VM Agent API returns `401` with expired token error.
**Solution:** Refresh the JWT token using the Control Plane API:
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/sandboxes/{sandbox_id}/refresh \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Sandbox Creation Issues
### Sandbox Stuck in "Creating" Status
**Problem:** Sandbox status remains "creating" for more than 2 minutes.
**Solutions:**
1. Wait up to 5 minutes for large templates
2. Check template status - ensure it's "active"
3. Try a different region if available
4. Delete and recreate the sandbox
```bash theme={null}
# Check sandbox status
curl https://api.hopx.dev/v1/sandboxes/{sandbox_id} \
-H "Authorization: Bearer $HOPX_API_KEY" | jq '.status'
# If stuck, delete and recreate
curl -X DELETE https://api.hopx.dev/v1/sandboxes/{sandbox_id} \
-H "Authorization: Bearer $HOPX_API_KEY"
```
### Template Not Found
**Problem:** `404 Template not found` when creating sandbox.
```json theme={null}
{
"error": "Template not found",
"code": "RESOURCE_NOT_FOUND"
}
```
**Solutions:**
1. List available templates to find valid IDs
2. Use template `name` instead of ID
3. Check if template is active
```bash theme={null}
# List available templates
curl https://api.hopx.dev/v1/templates \
-H "Authorization: Bearer $HOPX_API_KEY" | jq '.data[] | {id, name, is_active}'
# Use name instead of ID
curl -X POST https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"template_id": "code-interpreter"}'
```
### Resource Limits Exceeded
**Problem:** Cannot create more sandboxes.
```json theme={null}
{
"error": "Sandbox limit reached (10/10)",
"code": "RESOURCE_LIMIT_ERROR"
}
```
**Solutions:**
1. Delete unused sandboxes
2. Upgrade your plan for higher limits
3. Use sandbox pooling/reuse
```bash theme={null}
# List all sandboxes
curl https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY"
# Delete stopped sandboxes
for ID in $(curl -s https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY" | \
jq -r '.data[] | select(.status == "stopped") | .id'); do
curl -X DELETE "https://api.hopx.dev/v1/sandboxes/$ID" \
-H "Authorization: Bearer $HOPX_API_KEY"
done
```
## Code Execution Issues
### Execution Timeout
**Problem:** Code execution times out.
```json theme={null}
{
"error": "Execution timeout after 60 seconds",
"code": "EXECUTION_TIMEOUT"
}
```
**Solutions:**
1. Increase the timeout parameter
2. Optimize your code
3. Use background execution for long tasks
```bash theme={null}
# Increase timeout
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import time; time.sleep(120)",
"language": "python",
"timeout": 180
}'
# Or use background execution
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/background \
-H "Authorization: Bearer JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import time; time.sleep(600)",
"language": "python",
"timeout": 900
}'
```
### Import/Module Errors
**Problem:** Python packages not found.
```
ModuleNotFoundError: No module named 'requests'
```
**Solutions:**
1. Install packages before use
2. Use a template with pre-installed packages
3. Check package spelling
```bash theme={null}
# Install package first
curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \
-H "Authorization: Bearer JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"command": "pip install requests numpy pandas",
"timeout": 120
}'
# Then use it
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import requests; print(requests.__version__)",
"language": "python"
}'
```
## File Operation Issues
### Path Not Allowed
**Problem:** `403 Forbidden` when accessing files.
```json theme={null}
{
"error": "Path not allowed: /etc/passwd",
"code": "FORBIDDEN"
}
```
**Solutions:**
1. Only access allowed paths: `/workspace`, `/tmp`
2. Use relative paths from allowed directories
```bash theme={null}
# Good - allowed paths
curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/data.txt" \
-H "Authorization: Bearer JWT_TOKEN"
# Bad - forbidden path
curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/etc/passwd" \
-H "Authorization: Bearer JWT_TOKEN"
```
### File Not Found
**Problem:** File doesn't exist when trying to read.
**Solutions:**
1. Check if file exists first
2. Create the file before reading
3. Verify the file path
```bash theme={null}
# Check if file exists
EXISTS=$(curl -s "https://sandbox_abc123xyz.hopx.dev/files/exists?path=/workspace/data.txt" \
-H "Authorization: Bearer JWT_TOKEN" | jq -r '.exists')
if [ "$EXISTS" == "true" ]; then
# File exists, read it
curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/data.txt" \
-H "Authorization: Bearer JWT_TOKEN"
else
# File doesn't exist, create it
curl -X POST https://sandbox_abc123xyz.hopx.dev/files/write \
-H "Authorization: Bearer JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"path": "/workspace/data.txt",
"content": "Initial content"
}'
fi
```
## Connection Issues
### Network Timeout
**Problem:** Requests timing out.
**Solutions:**
1. Increase client timeout
2. Check network connectivity
3. Use retry logic with exponential backoff
```python theme={null}
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry
# Configure retries
session = requests.Session()
retries = Retry(
total=5,
backoff_factor=1,
status_forcelist=[502, 503, 504]
)
session.mount('https://', HTTPAdapter(max_retries=retries))
# Make request with retries
response = session.post(
"https://api.hopx.dev/v1/sandboxes",
headers={"Authorization": "Bearer $HOPX_API_KEY"},
json={"template_id": "code-interpreter"},
timeout=30
)
```
### SSL Certificate Errors
**Problem:** SSL verification failures.
**Solutions:**
1. Update your SSL certificates
2. Update your HTTP client library
3. Check system time (certificate validation depends on correct time)
```bash theme={null}
# Update certificates (Ubuntu/Debian)
sudo apt-get update
sudo apt-get install ca-certificates
# Update Python certifi
pip install --upgrade certifi
```
## Rate Limiting
### Rate Limit Exceeded
**Problem:** `429 Too Many Requests` errors.
```json theme={null}
{
"error": "Rate limit exceeded: 100 requests per minute",
"code": "RATE_LIMIT_EXCEEDED",
"retry_after": 30
}
```
**Solutions:**
1. Implement exponential backoff
2. Respect the `retry_after` header
3. Distribute requests over time
4. Cache responses when possible
```python theme={null}
import time
import requests
def make_request_with_rate_limiting(url, headers):
max_retries = 5
for attempt in range(max_retries):
response = requests.get(url, headers=headers)
if response.status_code != 429:
return response
# Get retry_after from header or response body
retry_after = int(response.headers.get('Retry-After', 0))
if retry_after == 0:
error_data = response.json()
retry_after = error_data.get('retry_after', 2 ** attempt)
print(f"Rate limited. Waiting {retry_after}s")
time.sleep(retry_after)
raise Exception("Max retries exceeded")
```
## Debugging Tips
### Enable Verbose Logging
```bash theme={null}
# cURL with verbose output
curl -v https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY"
# Python with logging
import logging
import requests
logging.basicConfig(level=logging.DEBUG)
response = requests.get(
"https://api.hopx.dev/v1/sandboxes",
headers={"Authorization": "Bearer $HOPX_API_KEY"}
)
```
### Check Request ID
Every response includes a `request_id` for debugging:
```bash theme={null}
curl -i https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY" | grep request_id
```
Include the `request_id` when contacting support.
### Inspect Full Response
```bash theme={null}
# Save full response for debugging
curl -i https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY" \
> response.txt
```
### Test with cURL First
Before implementing in your application, test with cURL:
```bash theme={null}
# Test sandbox creation
curl -X POST https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{"template_id": "code-interpreter"}' | jq '.'
```
## Getting Help
If you're still experiencing issues:
1. **Check Status Page** - [https://status.hopx.dev](https://status.hopx.dev)
2. **Review Documentation** - Complete API reference
3. **Contact Support** - Include:
* Request ID
* Timestamp
* Full error message
* Code snippet (remove sensitive data)
* Expected vs actual behavior
## Common Patterns
### Healthcheck Pattern
```python theme={null}
def check_sandbox_health(sandbox_id, jwt_token):
"""Check if sandbox is ready for use"""
try:
response = requests.get(
f"https://{sandbox_id}.hopx.dev/health",
headers={"Authorization": f"Bearer {jwt_token}"},
timeout=5
)
return response.status_code == 200
except:
return False
```
### Cleanup Pattern
```python theme={null}
def cleanup_old_sandboxes(api_key, hours=24):
"""Delete sandboxes older than specified hours"""
from datetime import datetime, timedelta
response = requests.get(
"https://api.hopx.dev/v1/sandboxes",
headers={"Authorization": f"Bearer {api_key}"}
)
cutoff = datetime.utcnow() - timedelta(hours=hours)
for sandbox in response.json()["data"]:
created_at = datetime.fromisoformat(sandbox["created_at"].replace('Z', '+00:00'))
if created_at < cutoff:
print(f"Deleting old sandbox: {sandbox['id']}")
requests.delete(
f"https://api.hopx.dev/v1/sandboxes/{sandbox['id']}",
headers={"Authorization": f"Bearer {api_key}"}
)
```
## Related
* **[Error Handling](/api/concepts/errors)** - Understand error codes and responses
* **[Rate Limits](/api/concepts/rate-limits)** - Handle rate limit issues
* **[Authentication](/api/authentication)** - Fix authentication problems
* **[API Introduction](/api/introduction)** - Learn about the HopX API
* **[Python SDK Quickstart](/sdk/python/quickstart)** - Use the Python SDK (simpler error handling)
* [CLI Reference](/cli/introduction) - Command-line interface
## Next Steps
* **[Errors](/api/concepts/errors)** - Complete error reference
* **[Rate Limits](/api/concepts/rate-limits)** - Rate limiting details
* **[Data Model](/api/concepts/data-model)** - Core resources
# Build Template
Source: https://docs.hopx.ai/api/control-plane/build-template
Create a custom template from a Docker image with build steps using the HopX Control Plane API. Build custom sandbox templates with specific configurations, dependencies, and resources. Learn how to use POST /v1/templates/build endpoint to create templates from Docker images. Includes request examples and template configuration.
Build a custom template from a Docker image. Define the base image, build steps, resources, and ready checks. The API will build and cache your template for creating sandboxes.
## Endpoint
```
POST /v1/templates/build
```
## Request
### Headers
```
Authorization: Bearer $HOPX_API_KEY
Content-Type: application/json
```
### Body Parameters
| Parameter | Type | Required | Description |
| ---------------------- | ------- | -------- | ------------------------------------------------------------ |
| `name` | string | Yes | Unique template name |
| `from_image` | string | Yes | Base Docker image (e.g., `ubuntu:22.04`, `python:3.11-slim`) |
| `cpu` | integer | Yes | Number of vCPUs (min/max from your plan) |
| `memory` | integer | Yes | Memory in MB (min: 512, max: 64000) |
| `diskGB` | integer | Yes | Disk size in GB (min: 1, max: 250) |
| `steps` | array | No | Build steps (RUN, COPY, ENV, WORKDIR, USER, CMD) |
| `startCmd` | string | No | Command to run on sandbox start |
| `readyCmd` | object | No | Ready check configuration |
| `skipCache` | boolean | No | Skip build cache (default: false) |
| `registry_credentials` | object | No | Private registry authentication |
| `update` | boolean | No | Update existing template (default: false) |
**Alpine Linux is not supported.** Use glibc-based images like `ubuntu:*`, `debian:*`, `python:*-slim`, `node:*-slim`.
### Example Request
Build a Python template:
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/templates/build \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "my-python-template",
"from_image": "python:3.11-slim",
"cpu": 2,
"memory": 4096,
"diskGB": 10,
"steps": [
{
"type": "RUN",
"args": ["pip install pandas numpy matplotlib"]
},
{
"type": "WORKDIR",
"args": ["/workspace"]
},
{
"type": "ENV",
"args": ["PYTHONUNBUFFERED=1"]
}
]
}'
```
Build a Node.js template:
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/templates/build \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "my-nodejs-template",
"from_image": "node:18-slim",
"cpu": 1,
"memory": 2048,
"diskGB": 5,
"steps": [
{
"type": "RUN",
"args": ["npm install -g typescript ts-node"]
},
{
"type": "WORKDIR",
"args": ["/app"]
}
]
}'
```
## Response
### Success (202 Accepted)
```json theme={null}
{
"build_id": "build_abc123",
"template_id": "template_xyz789",
"status": "building",
"logs_url": "https://api.hopx.dev/v1/templates/build/build_abc123/logs",
"request_id": "req_abc123"
}
```
### Response Fields
| Field | Type | Description |
| ------------- | ------ | --------------------------------------------- |
| `build_id` | string | Build ID (same as template\_id) |
| `template_id` | string | Template ID |
| `status` | string | Build status (`building`, `active`, `failed`) |
| `logs_url` | string | URL to stream build logs |
| `request_id` | string | Request ID for debugging |
## Status Codes
| Code | Description |
| ----- | ------------------------------------------------- |
| `202` | Build triggered (accepted) |
| `400` | Invalid request (Alpine, invalid resources, etc.) |
| `401` | Authentication required |
| `404` | Template not found (when `update=true`) |
| `409` | Template exists (when `update=false`) |
| `503` | Service unavailable (no available nodes) |
## Build Steps
### Supported Step Types
| Type | Description | Example |
| --------- | --------------------------------- | -------------------------------------------------------------- |
| `RUN` | Run a shell command | `{"type": "RUN", "args": ["apt-get update"]}` |
| `COPY` | Copy files (requires file upload) | `{"type": "COPY", "args": ["/app"], "filesHash": "sha256..."}` |
| `ENV` | Set environment variable | `{"type": "ENV", "args": ["KEY=value"]}` |
| `WORKDIR` | Set working directory | `{"type": "WORKDIR", "args": ["/workspace"]}` |
| `USER` | Set user | `{"type": "USER", "args": ["1000"]}` |
| `CMD` | Set default command | `{"type": "CMD", "args": ["python", "app.py"]}` |
### RUN Steps
```json theme={null}
{
"type": "RUN",
"args": ["pip install pandas numpy"]
}
```
### ENV Steps
```json theme={null}
{
"type": "ENV",
"args": ["PYTHONUNBUFFERED=1", "DEBUG=true"]
}
```
### WORKDIR Steps
```json theme={null}
{
"type": "WORKDIR",
"args": ["/workspace"]
}
```
## Errors
### Alpine Not Supported (400)
```json theme={null}
{
"error": "Alpine Linux is not supported. Use glibc-based images like ubuntu, debian, python-slim, node-slim",
"code": "INVALID_REQUEST",
"request_id": "req_abc123"
}
```
**Cause:** The base image is Alpine Linux, which is not supported.
**Fix:** Use a glibc-based image like `ubuntu:22.04`, `python:3.11-slim`, or `node:18-slim`.
### Template Exists (409)
```json theme={null}
{
"error": "Template already exists. Set update=true to update it.",
"code": "CONFLICT",
"request_id": "req_abc123"
}
```
**Cause:** A template with the same name already exists and `update` is false.
**Fix:** Either:
* Use a different template name
* Set `"update": true` to update the existing template
### Invalid Resources (400)
```json theme={null}
{
"error": "Invalid memory: must be between 512 and 64000 MB",
"code": "INVALID_REQUEST",
"request_id": "req_abc123"
}
```
**Cause:** Resource values are outside allowed limits.
**Fix:** Ensure:
* `cpu`: 1-8 (depends on your plan)
* `memory`: 512-64000 MB
* `diskGB`: 1-250 GB
## Monitor Build Progress
After triggering a build, monitor its progress:
```bash theme={null}
# Get build status
curl https://api.hopx.dev/v1/templates/build/build_abc123/status \
-H "Authorization: Bearer $HOPX_API_KEY"
# Stream build logs
curl https://api.hopx.dev/v1/templates/build/build_abc123/logs \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Use Cases
### Create Data Science Template
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/templates/build \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "data-science",
"from_image": "python:3.11-slim",
"cpu": 4,
"memory": 8192,
"diskGB": 20,
"steps": [
{
"type": "RUN",
"args": ["pip install pandas numpy matplotlib scikit-learn jupyter"]
},
{
"type": "WORKDIR",
"args": ["/workspace"]
},
{
"type": "ENV",
"args": ["PYTHONUNBUFFERED=1"]
}
]
}'
```
### Update Existing Template
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/templates/build \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "my-template",
"from_image": "python:3.11-slim",
"cpu": 2,
"memory": 4096,
"diskGB": 10,
"update": true,
"steps": [
{
"type": "RUN",
"args": ["pip install --upgrade pandas"]
}
]
}'
```
## Related
* **[Building Templates](/core-concepts/templates/building)** - Learn about template building
* **[Template Configuration](/core-concepts/templates/configuration)** - Configure template resources
* **[Template Caching](/core-concepts/templates/caching)** - Optimize build performance
* **[Get Template](/api/control-plane/get-template)** - Check template details after build
* [CLI Template Commands](/cli/commands/template) - Template management from CLI
## Next Steps
* **[Get Template](/api/control-plane/get-template)** - Check template details after build
* **[Stream Build Logs](/api/control-plane/stream-logs)** - Monitor build progress
* **[Create Sandbox](/api/control-plane/create-sandbox)** - Use your new template
# Create Sandbox
Source: https://docs.hopx.ai/api/control-plane/create-sandbox
Create a new sandbox from a template using the HopX Control Plane API. Provision isolated cloud environments with custom configuration, resources, and environment variables. Learn how to use POST /v1/sandboxes endpoint with Python and JavaScript SDK examples.
Create a new sandbox from a template. The sandbox will be provisioned with resources (vCPU, memory, disk) defined by the template.
## Endpoint
```
POST /v1/sandboxes
```
## Request
### Headers
```
Authorization: Bearer $HOPX_API_KEY
Content-Type: application/json
```
### Body Parameters
| Parameter | Type | Required | Description |
| ----------------- | ----------------- | -------- | --------------------------------------------- |
| `template_id` | string or integer | Yes\* | Template ID to use |
| `template_name` | string | Yes\* | Template name (alternative to `template_id`) |
| `region` | string | No | Preferred region (e.g., `us-east`, `eu-west`) |
| `timeout_seconds` | integer | No | Auto-kill timeout in seconds |
| `internet_access` | boolean | No | Enable internet access (default: `true`) |
| `env_vars` | object | No | Environment variables to set in sandbox |
Either `template_id` or `template_name` must be provided. Resources (vcpu, memory, disk) are **always loaded from the template** - you cannot specify custom resources.
### Example Request
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "73",
"timeout_seconds": 3600,
"internet_access": true,
"env_vars": {
"MY_VAR": "my_value",
"API_KEY": "secret123"
}
}'
```
Replace `$HOPX_API_KEY` with your actual API key from [console.hopx.dev](https://console.hopx.dev), or set it as an environment variable: `export HOPX_API_KEY="your-API key-here"`
Or using template name:
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_name": "code-interpreter",
"timeout_seconds": 3600
}'
```
Replace `$HOPX_API_KEY` with your actual API key from [console.hopx.dev](https://console.hopx.dev), or set it as an environment variable: `export HOPX_API_KEY="your-API key-here"`
## Response
### Success (201 Created)
```json theme={null}
{
"id": "sandbox_abc123xyz",
"object": "sandbox",
"status": "running",
"public_host": "https://sandbox_abc123xyz.hopx.dev",
"direct_url": "https://sandbox_abc123xyz.hopx.dev",
"template_id": "73",
"template_name": "code-interpreter",
"organization_id": 123,
"node_id": "node_xyz789",
"region": "us-east",
"resources": {
"vcpu": 2,
"memory_mb": 4096,
"disk_mb": 10240
},
"internet_access": true,
"timeout_seconds": 3600,
"expires_at": "2025-01-29T00:00:00Z",
"created_at": "2025-01-28T00:00:00Z",
"auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_expires_at": "2025-01-28T01:00:00Z",
"request_id": "req_abc123"
}
```
### Response Fields
| Field | Type | Description |
| ------------------ | ------ | ---------------------------------------------------- |
| `id` | string | Sandbox ID (use for all subsequent operations) |
| `status` | string | Current sandbox status (`creating`, `running`, etc.) |
| `public_host` | string | VM Agent API base URL for this sandbox |
| `direct_url` | string | Alternative VM Agent API URL (same as `public_host`) |
| `template_id` | string | Template ID used to create sandbox |
| `template_name` | string | Template name |
| `resources` | object | Allocated resources (from template) |
| `auth_token` | string | JWT token for VM Agent API authentication |
| `token_expires_at` | string | ISO 8601 timestamp when token expires |
## Status Codes
| Code | Description |
| ----- | --------------------------------------------------------- |
| `201` | Sandbox created successfully |
| `400` | Invalid request (missing template, invalid timeout, etc.) |
| `401` | Authentication required |
| `402` | Payment required (insufficient balance) |
| `404` | Template not found |
| `503` | Service unavailable (no available nodes) |
## Errors
### Template Not Found (404)
```json theme={null}
{
"error": "Template not found",
"code": "RESOURCE_NOT_FOUND",
"request_id": "req_abc123"
}
```
**Cause:** The specified `template_id` or `template_name` doesn't exist.
**Fix:** List available templates using `GET /v1/templates` to find valid template IDs or names.
### Invalid Request (400)
```json theme={null}
{
"error": "Invalid request: timeout_seconds must be positive",
"code": "INVALID_REQUEST",
"request_id": "req_abc123"
}
```
**Cause:** Invalid parameter value (e.g., negative timeout, missing template).
**Fix:** Verify all parameters meet requirements:
* `timeout_seconds` must be positive
* Either `template_id` or `template_name` must be provided
* `env_vars` must be a valid object
### Service Unavailable (503)
```json theme={null}
{
"error": "Service unavailable: no available nodes",
"code": "SERVICE_UNAVAILABLE",
"request_id": "req_abc123"
}
```
**Cause:** No compute nodes are available to provision the sandbox.
**Fix:** Retry the request after a few moments. This is usually temporary.
## Use Cases
### Quick Code Execution
Create a sandbox for quick code execution:
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_name": "code-interpreter",
"timeout_seconds": 300
}'
```
### Long-Running Job
Create a sandbox for a long-running task:
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "73",
"timeout_seconds": 7200,
"env_vars": {
"DATABASE_URL": "postgres://...",
"API_KEY": "secret"
}
}'
```
### Region-Specific Deployment
Create a sandbox in a specific region:
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_name": "code-interpreter",
"region": "eu-west"
}'
```
## Related
* **SDK**: [Sandbox.create()](/sdk/python/sandbox#create) - Python SDK method
* **[Get Sandbox](/api/control-plane/get-sandbox)** - Retrieve sandbox information
* **[List Sandboxes](/api/control-plane/list-sandboxes)** - Query all your sandboxes
* **[VM Agent API](/api/vm-agent/overview)** - Execute code in your new sandbox
* [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI
## Next Steps
* **[Get Sandbox](/api/control-plane/get-sandbox)** - Retrieve sandbox information
* **[List Sandboxes](/api/control-plane/list-sandboxes)** - Query all your sandboxes
* **[VM Agent API](/api/vm-agent/overview)** - Execute code in your new sandbox
# Delete Sandbox
Source: https://docs.hopx.ai/api/control-plane/delete-sandbox
Permanently delete a sandbox and free its resources using the HopX Control Plane API. Remove sandboxes when no longer needed to free up resources and manage costs. Learn how to use DELETE /v1/sandboxes/:id endpoint to permanently delete sandboxes and clean up resources. Includes request examples and cleanup best practices.
Delete a sandbox to permanently destroy it and free all allocated resources. This action cannot be undone.
## Endpoint
```
DELETE /v1/sandboxes/:id
```
## Request
### Headers
```
Authorization: Bearer $HOPX_API_KEY
```
### Path Parameters
| Parameter | Type | Description |
| --------- | ------ | -------------------- |
| `id` | string | Sandbox ID to delete |
### Example Request
```bash theme={null}
curl -X DELETE https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Response
### Success (200 OK)
```json theme={null}
{
"status": "deleted",
"id": "sandbox_abc123xyz",
"request_id": "req_abc123"
}
```
### Response Fields
| Field | Type | Description |
| ------------ | ------ | ------------------------ |
| `status` | string | Always `"deleted"` |
| `id` | string | Deleted sandbox ID |
| `request_id` | string | Request ID for debugging |
## Status Codes
| Code | Description |
| ----- | ---------------------------- |
| `200` | Sandbox deleted successfully |
| `401` | Authentication required |
| `404` | Sandbox not found |
## Errors
### Sandbox Not Found (404)
```json theme={null}
{
"error": "Sandbox not found",
"code": "RESOURCE_NOT_FOUND",
"request_id": "req_abc123"
}
```
**Cause:** The sandbox ID doesn't exist or belongs to another organization.
**Fix:** Verify the sandbox ID is correct. List your sandboxes using `GET /v1/sandboxes` to find valid IDs.
## Important Notes
Deleting a sandbox is **permanent and irreversible**. All data, files, and state in the sandbox will be lost. Make sure to save any important data before deleting.
* **Immediate deletion** - The sandbox is destroyed immediately upon successful deletion
* **Resource cleanup** - All allocated resources (vCPU, memory, disk) are freed
* **VM Agent API** - The sandbox's VM Agent API endpoint becomes unavailable immediately
* **No recovery** - Deleted sandboxes cannot be recovered
## Use Cases
### Clean Up After Task Completion
```bash theme={null}
# Execute your task
# ... code execution ...
# Delete when done
curl -X DELETE https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz \
-H "Authorization: Bearer $HOPX_API_KEY"
```
### Delete All Stopped Sandboxes
```bash theme={null}
#!/bin/bash
# Get all stopped sandboxes
STOPPED=$(curl -s "https://api.hopx.dev/v1/sandboxes?status=stopped" \
-H "Authorization: Bearer $HOPX_API_KEY" | \
jq -r '.data[].id')
# Delete each one
for ID in $STOPPED; do
curl -X DELETE "https://api.hopx.dev/v1/sandboxes/$ID" \
-H "Authorization: Bearer $HOPX_API_KEY"
echo "Deleted $ID"
done
```
### Delete Sandbox with Verification
```bash theme={null}
#!/bin/bash
SANDBOX_ID="sandbox_abc123xyz"
# Verify sandbox exists
STATUS=$(curl -s "https://api.hopx.dev/v1/sandboxes/$SANDBOX_ID" \
-H "Authorization: Bearer $HOPX_API_KEY" | jq -r '.status')
if [ "$STATUS" != "null" ]; then
# Delete it
curl -X DELETE "https://api.hopx.dev/v1/sandboxes/$SANDBOX_ID" \
-H "Authorization: Bearer $HOPX_API_KEY"
echo "Sandbox $SANDBOX_ID deleted"
else
echo "Sandbox not found"
fi
```
## Related
* **SDK**: [sandbox.kill()](/sdk/python/sandbox#kill) - Python SDK method
* [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI
## Next Steps
* **[List Sandboxes](/api/control-plane/list-sandboxes)** - View all your sandboxes
* **[Create Sandbox](/api/control-plane/create-sandbox)** - Create a new sandbox
* **[Get Sandbox](/api/control-plane/get-sandbox)** - Retrieve sandbox information
# Get Sandbox
Source: https://docs.hopx.ai/api/control-plane/get-sandbox
Retrieve information about a specific sandbox using the HopX Control Plane API. Get sandbox details including status, resources, connection information, and metadata. Learn how to use GET /v1/sandboxes/:id endpoint to connect to existing sandboxes and retrieve their current state.
Get detailed information about a sandbox, including its current status, resources, and configuration.
## Endpoint
```
GET /v1/sandboxes/:id
```
## Request
### Headers
```
Authorization: Bearer $HOPX_API_KEY
```
### Path Parameters
| Parameter | Type | Description |
| --------- | ------ | ----------- |
| `id` | string | Sandbox ID |
### Example Request
```bash theme={null}
curl https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Response
### Success (200 OK)
```json theme={null}
{
"id": "sandbox_abc123xyz",
"object": "sandbox",
"status": "running",
"public_host": "https://sandbox_abc123xyz.hopx.dev",
"direct_url": "https://sandbox_abc123xyz.hopx.dev",
"template_id": "73",
"template_name": "code-interpreter",
"organization_id": 123,
"node_id": "node_xyz789",
"region": "us-east",
"resources": {
"vcpu": 2,
"memory_mb": 4096,
"disk_mb": 10240
},
"internet_access": true,
"timeout_seconds": 3600,
"expires_at": "2025-01-29T00:00:00Z",
"created_at": "2025-01-28T00:00:00Z"
}
```
### Response Fields
| Field | Type | Description |
| ----------------- | ------- | ----------------------------------------------------------- |
| `id` | string | Sandbox ID |
| `status` | string | Current status (`running`, `stopped`, `paused`, `creating`) |
| `public_host` | string | VM Agent API base URL |
| `template_id` | string | Template ID used to create sandbox |
| `resources` | object | Allocated resources (vcpu, memory\_mb, disk\_mb) |
| `timeout_seconds` | integer | Auto-kill timeout in seconds |
| `expires_at` | string | ISO 8601 timestamp when sandbox expires |
## Status Codes
| Code | Description |
| ----- | ----------------------- |
| `200` | Success |
| `401` | Authentication required |
| `404` | Sandbox not found |
## Errors
### Sandbox Not Found (404)
```json theme={null}
{
"error": "Sandbox not found",
"code": "RESOURCE_NOT_FOUND",
"request_id": "req_abc123"
}
```
**Cause:** The sandbox ID doesn't exist or belongs to another organization.
**Fix:** Verify the sandbox ID is correct. List your sandboxes using `GET /v1/sandboxes` to find valid IDs.
## Use Cases
### Check Sandbox Status
Monitor sandbox status before executing code:
```bash theme={null}
curl https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz \
-H "Authorization: Bearer $HOPX_API_KEY" | jq '.status'
```
### Verify Resources
Confirm allocated resources match expectations:
```bash theme={null}
curl https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz \
-H "Authorization: Bearer $HOPX_API_KEY" | jq '.resources'
```
## Related
* **SDK**: [Sandbox.connect()](/sdk/python/sandbox#connect) - Python SDK method
* **SDK**: [sandbox.get\_info()](/sdk/python/sandbox#get_info) - Python SDK method
* [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI
## Next Steps
* **[List Sandboxes](/api/control-plane/list-sandboxes)** - Query all your sandboxes
* **[Update Sandbox](/api/control-plane/set-timeout)** - Modify sandbox configuration
* **[Delete Sandbox](/api/control-plane/delete-sandbox)** - Clean up resources
# Get Template
Source: https://docs.hopx.ai/api/control-plane/get-template
Get detailed information about a specific template using the HopX Control Plane API. Retrieve template configuration, resources, build steps, and metadata for pre-built or custom templates. Learn how to use GET /v1/templates/:name endpoint to view template details before creating sandboxes. Includes request examples and response formats.
Get detailed information about a specific template, including its configuration, resources, features, and availability.
## Endpoint
```
GET /v1/templates/:name
```
## Request
### Headers
```
Authorization: Bearer $HOPX_API_KEY
```
### Path Parameters
| Parameter | Type | Description |
| --------- | ------ | ------------------- |
| `name` | string | Template name or ID |
### Example Request
Get by template name:
```bash theme={null}
curl https://api.hopx.dev/v1/templates/code-interpreter \
-H "Authorization: Bearer $HOPX_API_KEY"
```
Get by template ID:
```bash theme={null}
curl https://api.hopx.dev/v1/templates/73 \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Response
### Success (200 OK)
```json theme={null}
{
"id": "73",
"object": "template",
"name": "code-interpreter",
"display_name": "Code Interpreter",
"description": "Pre-built environment for Python, JavaScript, and Bash execution with common packages pre-installed",
"category": "python",
"language": "python",
"icon": "python",
"default_resources": {
"vcpu": 2,
"memory_mb": 4096,
"disk_gb": 10
},
"min_resources": {
"vcpu": 1,
"memory_mb": 512,
"disk_gb": 1
},
"max_resources": {
"vcpu": 8,
"memory_mb": 16384,
"disk_gb": 100
},
"features": [
"python",
"javascript",
"bash",
"desktop",
"internet"
],
"tags": [
"code-execution",
"multi-language",
"data-science"
],
"popularity_score": 950,
"docs_url": "https://docs.hopx.dev/templates/code-interpreter",
"is_active": true,
"status": "active",
"build_id": "build_abc123",
"is_public": true,
"created_at": "2025-01-01T00:00:00Z",
"updated_at": "2025-01-15T00:00:00Z",
"request_id": "req_abc123"
}
```
### Response Fields
| Field | Type | Description |
| ------------------- | ------- | ------------------------------------------------ |
| `id` | string | Template ID |
| `name` | string | Template name (unique identifier) |
| `display_name` | string | Human-readable name |
| `description` | string | Template description |
| `category` | string | Template category |
| `language` | string | Primary programming language |
| `default_resources` | object | Default resource allocation |
| `min_resources` | object | Minimum resource requirements |
| `max_resources` | object | Maximum resource limits |
| `features` | array | Supported features |
| `tags` | array | Template tags for categorization |
| `is_active` | boolean | Whether template is ready for use |
| `status` | string | Template status (`active`, `building`, `failed`) |
| `is_public` | boolean | Whether template is publicly available |
## Status Codes
| Code | Description |
| ----- | ----------------------- |
| `200` | Success |
| `401` | Authentication required |
| `404` | Template not found |
## Errors
### Template Not Found (404)
```json theme={null}
{
"error": "Template not found",
"code": "RESOURCE_NOT_FOUND",
"request_id": "req_abc123"
}
```
**Cause:** The template name or ID doesn't exist or is not accessible to your organization.
**Fix:** List available templates using `GET /v1/templates` to find valid template names or IDs.
## Template Features
Common template features:
* **`python`** - Python runtime available
* **`javascript`** - JavaScript/Node.js runtime available
* **`bash`** - Bash shell available
* **`desktop`** - Desktop environment with VNC support
* **`internet`** - Internet access enabled
* **`gpu`** - GPU support (for ML/AI workloads)
## Use Cases
### Check Template Resources
```bash theme={null}
curl https://api.hopx.dev/v1/templates/code-interpreter \
-H "Authorization: Bearer $HOPX_API_KEY" | \
jq '.default_resources'
```
### Verify Template Status
```bash theme={null}
STATUS=$(curl -s https://api.hopx.dev/v1/templates/my-custom-template \
-H "Authorization: Bearer $HOPX_API_KEY" | jq -r '.status')
if [ "$STATUS" == "active" ]; then
echo "Template is ready"
else
echo "Template is not ready: $STATUS"
fi
```
### Check Template Features
```bash theme={null}
curl https://api.hopx.dev/v1/templates/code-interpreter \
-H "Authorization: Bearer $HOPX_API_KEY" | \
jq '.features[]'
```
### Compare Template Resources
```bash theme={null}
#!/bin/bash
TEMPLATES=("code-interpreter" "python-3.11" "nodejs-18")
for TEMPLATE in "${TEMPLATES[@]}"; do
echo "=== $TEMPLATE ==="
curl -s "https://api.hopx.dev/v1/templates/$TEMPLATE" \
-H "Authorization: Bearer $HOPX_API_KEY" | \
jq '{name: .name, resources: .default_resources}'
done
```
## Related
* **SDK**: [Sandbox.get\_template()](/sdk/python/sandbox#get_template) - Python SDK method
* [CLI Template Commands](/cli/commands/template) - Template management from CLI
## Next Steps
* **[List Templates](/api/control-plane/list-templates)** - Browse all available templates
* **[Build Template](/api/control-plane/build-template)** - Create a custom template
* **[Create Sandbox](/api/control-plane/create-sandbox)** - Create a sandbox from this template
# Kill Sandbox
Source: https://docs.hopx.ai/api/control-plane/kill-sandbox
Forcefully terminate a sandbox immediately using the HopX Control Plane API. Immediately stop a sandbox and free all resources without waiting for graceful shutdown. Learn how to use POST /v1/sandboxes/:id/kill endpoint to force-terminate sandboxes. Includes request examples and termination behavior.
Kill a sandbox to forcefully terminate it immediately. This is similar to delete but may be used when a sandbox is unresponsive. The sandbox is destroyed and cannot be recovered.
## Endpoint
```
POST /v1/sandboxes/:id/kill
```
## Request
### Headers
```
Authorization: Bearer $HOPX_API_KEY
```
### Path Parameters
| Parameter | Type | Description |
| --------- | ------ | ------------------ |
| `id` | string | Sandbox ID to kill |
### Example Request
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/kill \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Response
### Success (200 OK)
```json theme={null}
{
"id": "sandbox_abc123xyz",
"status": "killed",
"request_id": "req_abc123"
}
```
### Response Fields
| Field | Type | Description |
| ------------ | ------ | ------------------------ |
| `id` | string | Sandbox ID |
| `status` | string | New status (`killed`) |
| `request_id` | string | Request ID for debugging |
## Status Codes
| Code | Description |
| ----- | --------------------------- |
| `200` | Sandbox killed successfully |
| `401` | Authentication required |
| `404` | Sandbox not found |
## Errors
### Sandbox Not Found (404)
```json theme={null}
{
"error": "Sandbox not found",
"code": "RESOURCE_NOT_FOUND",
"request_id": "req_abc123"
}
```
**Cause:** The sandbox ID doesn't exist or belongs to another organization.
**Fix:** Verify the sandbox ID is correct. List your sandboxes using `GET /v1/sandboxes` to find valid IDs.
## Important Notes
Killing a sandbox is **permanent and irreversible**. All data, files, and state in the sandbox will be lost. This action forcefully terminates the sandbox even if it's unresponsive.
* **Immediate termination** - The sandbox is forcefully terminated immediately
* **No graceful shutdown** - Running processes are killed without cleanup
* **Resource cleanup** - All allocated resources are freed
* **VM Agent API** - The sandbox's VM Agent API endpoint becomes unavailable immediately
* **No recovery** - Killed sandboxes cannot be recovered
## Use Cases
### Kill Unresponsive Sandbox
```bash theme={null}
# Kill a sandbox that's not responding
curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/kill \
-H "Authorization: Bearer $HOPX_API_KEY"
```
### Force Cleanup
```bash theme={null}
# Kill instead of delete when sandbox is stuck
curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/kill \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Difference from Delete
* **Kill** - Forcefully terminates the sandbox immediately, even if unresponsive
* **Delete** - Gracefully deletes the sandbox (may fail if sandbox is stuck)
Use `kill` when a sandbox is unresponsive and `delete` doesn't work.
## Related
* **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Learn about sandbox lifecycle
* **[Delete Sandbox](/api/control-plane/delete-sandbox)** - Gracefully delete a sandbox
* **[Stop Sandbox](/api/control-plane/stop-sandbox)** - Stop instead of killing
* **SDK**: [sandbox.kill()](/sdk/python/sandbox#kill) - Python SDK method
* [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI
## Next Steps
* **[Delete Sandbox](/api/control-plane/delete-sandbox)** - Gracefully delete a sandbox
* **[Stop Sandbox](/api/control-plane/stop-sandbox)** - Stop instead of killing
* **[Get Sandbox](/api/control-plane/get-sandbox)** - Check sandbox status
# List Sandboxes
Source: https://docs.hopx.ai/api/control-plane/list-sandboxes
List and filter all your sandboxes with pagination support using the HopX Control Plane API. Query sandboxes by status, region, template, or other criteria. Learn how to use GET /v1/sandboxes endpoint with filtering, pagination, and sorting options. Includes Python and JavaScript SDK examples.
List all sandboxes in your organization. Filter by status, region, or use pagination to handle large result sets.
## Endpoint
```
GET /v1/sandboxes
```
## Request
### Headers
```
Authorization: Bearer $HOPX_API_KEY
```
### Query Parameters
| Parameter | Type | Required | Description |
| --------- | ------- | -------- | ------------------------------------------------------------ |
| `limit` | integer | No | Maximum number of results (default: 100, max: 1000) |
| `status` | string | No | Filter by status: `running`, `stopped`, `paused`, `creating` |
| `region` | string | No | Filter by region (e.g., `us-east`, `eu-west`) |
| `cursor` | string | No | Pagination cursor for next page |
### Example Request
List all running sandboxes:
```bash theme={null}
curl "https://api.hopx.dev/v1/sandboxes?status=running&limit=10" \
-H "Authorization: Bearer $HOPX_API_KEY"
```
Filter by region:
```bash theme={null}
curl "https://api.hopx.dev/v1/sandboxes?region=us-east" \
-H "Authorization: Bearer $HOPX_API_KEY"
```
Paginated request:
```bash theme={null}
curl "https://api.hopx.dev/v1/sandboxes?limit=20&cursor=abc123" \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Response
### Success (200 OK)
```json theme={null}
{
"object": "list",
"data": [
{
"id": "sandbox_abc123",
"object": "sandbox",
"status": "running",
"public_host": "https://sandbox_abc123.hopx.dev",
"template_name": "code-interpreter",
"region": "us-east",
"created_at": "2025-01-28T00:00:00Z"
},
{
"id": "sandbox_xyz789",
"object": "sandbox",
"status": "stopped",
"public_host": "https://sandbox_xyz789.hopx.dev",
"template_name": "python",
"region": "eu-west",
"created_at": "2025-01-27T12:00:00Z"
}
],
"has_more": true,
"next_cursor": "def456",
"request_id": "req_abc123"
}
```
### Response Fields
| Field | Type | Description |
| ------------- | ------- | ------------------------------------------------ |
| `object` | string | Always `"list"` |
| `data` | array | Array of sandbox objects |
| `has_more` | boolean | Whether more results are available |
| `next_cursor` | string | Cursor for the next page (if `has_more` is true) |
| `request_id` | string | Request ID for debugging |
Each sandbox object in `data` includes:
* `id` - Sandbox ID
* `status` - Current status
* `public_host` - VM Agent API URL
* `template_name` - Template used
* `region` - Deployment region
* `created_at` - Creation timestamp
## Status Codes
| Code | Description |
| ----- | ------------------------ |
| `200` | Success |
| `401` | Authentication required |
| `400` | Invalid query parameters |
## Pagination
Use cursor-based pagination to retrieve large result sets:
1. **First request** - Omit `cursor` parameter:
```bash theme={null}
curl "https://api.hopx.dev/v1/sandboxes?limit=10" \
-H "Authorization: Bearer $HOPX_API_KEY"
```
2. **Check for more** - If `has_more` is `true`, use `next_cursor`:
```bash theme={null}
curl "https://api.hopx.dev/v1/sandboxes?limit=10&cursor=def456" \
-H "Authorization: Bearer $HOPX_API_KEY"
```
3. **Repeat** - Continue until `has_more` is `false`
## Filtering
### Filter by Status
```bash theme={null}
# Only running sandboxes
curl "https://api.hopx.dev/v1/sandboxes?status=running" \
-H "Authorization: Bearer $HOPX_API_KEY"
# Only stopped sandboxes
curl "https://api.hopx.dev/v1/sandboxes?status=stopped" \
-H "Authorization: Bearer $HOPX_API_KEY"
```
### Filter by Region
```bash theme={null}
curl "https://api.hopx.dev/v1/sandboxes?region=us-east" \
-H "Authorization: Bearer $HOPX_API_KEY"
```
### Combine Filters
```bash theme={null}
curl "https://api.hopx.dev/v1/sandboxes?status=running®ion=us-east&limit=50" \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Use Cases
### Count Running Sandboxes
```bash theme={null}
curl "https://api.hopx.dev/v1/sandboxes?status=running" \
-H "Authorization: Bearer $HOPX_API_KEY" | jq '.data | length'
```
### List All Sandboxes (Paginated)
```bash theme={null}
#!/bin/bash
CURSOR=""
while true; do
if [ -z "$CURSOR" ]; then
RESPONSE=$(curl -s "https://api.hopx.dev/v1/sandboxes?limit=100" \
-H "Authorization: Bearer $HOPX_API_KEY")
else
RESPONSE=$(curl -s "https://api.hopx.dev/v1/sandboxes?limit=100&cursor=$CURSOR" \
-H "Authorization: Bearer $HOPX_API_KEY")
fi
echo "$RESPONSE" | jq '.data[]'
HAS_MORE=$(echo "$RESPONSE" | jq -r '.has_more')
if [ "$HAS_MORE" != "true" ]; then
break
fi
CURSOR=$(echo "$RESPONSE" | jq -r '.next_cursor')
done
```
### Find Sandboxes by Template
```bash theme={null}
curl "https://api.hopx.dev/v1/sandboxes" \
-H "Authorization: Bearer $HOPX_API_KEY" | \
jq '.data[] | select(.template_name == "code-interpreter")'
```
## Related
* **SDK**: [Sandbox.list()](/sdk/python/sandbox#list) - Python SDK method
* **SDK**: [Sandbox.iter()](/sdk/python/sandbox#iter) - Python SDK method
* [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI
## Next Steps
* **[Get Sandbox](/api/control-plane/get-sandbox)** - Get details for a specific sandbox
* **[Create Sandbox](/api/control-plane/create-sandbox)** - Create a new sandbox
* **[Delete Sandbox](/api/control-plane/delete-sandbox)** - Clean up unused sandboxes
# List Templates
Source: https://docs.hopx.ai/api/control-plane/list-templates
List all available sandbox templates using the HopX Control Plane API. Browse pre-built and custom templates, filter by category or language, and view template configurations. Learn how to use GET /v1/templates endpoint with filtering options to discover templates for your sandbox needs. Includes request examples and response formats.
List all available templates that can be used to create sandboxes. This includes both public pre-built templates and your organization's custom templates.
## Endpoint
```
GET /v1/templates
```
## Request
### Headers
```
Authorization: Bearer $HOPX_API_KEY
```
### Query Parameters
| Parameter | Type | Required | Description |
| ---------- | ------ | -------- | ------------------------------------------------------- |
| `category` | string | No | Filter by category (e.g., `python`, `nodejs`, `ubuntu`) |
| `language` | string | No | Filter by language (e.g., `python`, `javascript`) |
### Example Request
List all templates:
```bash theme={null}
curl https://api.hopx.dev/v1/templates \
-H "Authorization: Bearer $HOPX_API_KEY"
```
Filter by category:
```bash theme={null}
curl "https://api.hopx.dev/v1/templates?category=python" \
-H "Authorization: Bearer $HOPX_API_KEY"
```
Filter by language:
```bash theme={null}
curl "https://api.hopx.dev/v1/templates?language=javascript" \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Response
### Success (200 OK)
```json theme={null}
{
"object": "list",
"data": [
{
"id": "73",
"name": "code-interpreter",
"display_name": "Code Interpreter",
"description": "Pre-built environment for Python, JavaScript, and Bash execution",
"category": "python",
"language": "python",
"is_public": true,
"is_active": true,
"default_resources": {
"vcpu": 2,
"memory_mb": 4096,
"disk_gb": 10
}
},
{
"id": "74",
"name": "python-3.11",
"display_name": "Python 3.11",
"description": "Python 3.11 environment with pip and common packages",
"category": "python",
"language": "python",
"is_public": true,
"is_active": true,
"default_resources": {
"vcpu": 1,
"memory_mb": 2048,
"disk_gb": 5
}
}
],
"has_more": false,
"url": "/v1/templates",
"request_id": "req_abc123"
}
```
### Response Fields
| Field | Type | Description |
| ------------ | ------- | ---------------------------------- |
| `object` | string | Always `"list"` |
| `data` | array | Array of template objects |
| `has_more` | boolean | Whether more results are available |
| `url` | string | Endpoint URL |
| `request_id` | string | Request ID for debugging |
Each template object includes:
* `id` - Template ID (use for creating sandboxes)
* `name` - Template name (alternative identifier)
* `display_name` - Human-readable name
* `description` - Template description
* `category` - Template category
* `language` - Primary language (if applicable)
* `is_public` - Whether template is publicly available
* `is_active` - Whether template is active and ready for use
* `default_resources` - Default vCPU, memory, and disk allocation
## Status Codes
| Code | Description |
| ----- | ----------------------- |
| `200` | Success |
| `401` | Authentication required |
## Template Categories
Common template categories:
* **`python`** - Python environments (various versions)
* **`nodejs`** - Node.js environments
* **`ubuntu`** - Ubuntu base images
* **`code-interpreter`** - Multi-language code execution
* **`custom`** - Custom templates created by your organization
## Use Cases
### Find Python Templates
```bash theme={null}
curl "https://api.hopx.dev/v1/templates?category=python" \
-H "Authorization: Bearer $HOPX_API_KEY" | jq '.data[]'
```
### List Only Custom Templates
```bash theme={null}
curl https://api.hopx.dev/v1/templates \
-H "Authorization: Bearer $HOPX_API_KEY" | \
jq '.data[] | select(.is_public == false)'
```
### Find Template ID by Name
```bash theme={null}
curl https://api.hopx.dev/v1/templates \
-H "Authorization: Bearer $HOPX_API_KEY" | \
jq '.data[] | select(.name == "code-interpreter") | .id'
```
### Check Template Resources
```bash theme={null}
curl https://api.hopx.dev/v1/templates \
-H "Authorization: Bearer $HOPX_API_KEY" | \
jq '.data[] | {name: .name, resources: .default_resources}'
```
## Related
* **SDK**: [Sandbox.list\_templates()](/sdk/python/sandbox#list_templates) - Python SDK method
* [CLI Template Commands](/cli/commands/template) - Template management from CLI
## Next Steps
* **[Get Template](/api/control-plane/get-template)** - Get detailed template information
* **[Build Template](/api/control-plane/build-template)** - Create a custom template
* **[Create Sandbox](/api/control-plane/create-sandbox)** - Create a sandbox from a template
# Overview
Source: https://docs.hopx.ai/api/control-plane/overview
Manage sandboxes, templates, and monitor resources with the HopX Control Plane API. Create and manage sandbox lifecycle, list and build templates, monitor resources, and stream real-time events. Complete reference for all Control Plane API endpoints with authentication, request formats, and response handling.
The Control Plane API (`https://api.hopx.dev`) manages the lifecycle of sandboxes and templates. Use it to create, list, manage, and monitor your cloud sandboxes.
## Base URL
```
https://api.hopx.dev
```
All endpoints are prefixed with `/v1/`:
```
https://api.hopx.dev/v1/sandboxes
https://api.hopx.dev/v1/templates
```
## Authentication
All Control Plane API requests require an API key. Include it in the `Authorization` header:
```bash theme={null}
curl -H "Authorization: Bearer $HOPX_API_KEY" \
https://api.hopx.dev/v1/sandboxes
```
See the [Authentication guide](/api/authentication) for details.
## What You Can Do
### Sandbox Lifecycle
* **Create sandboxes** - Spin up isolated environments from templates
* **List and filter** - Query sandboxes by status, region, or other criteria
* **Manage state** - Start, stop, pause, resume, and delete sandboxes
* **Set timeouts** - Configure auto-shutdown timers
* **Refresh tokens** - Renew JWT tokens for VM Agent API access
### Template Management
* **List templates** - Browse available pre-built and custom templates
* **Get template details** - View template configuration and resources
* **Build templates** - Create custom templates from Docker images
* **Delete templates** - Remove custom templates (when not in use)
### Real-Time Monitoring
* **Stream sandbox events** - Server-Sent Events (SSE) for sandbox lifecycle changes
* **Stream metrics** - Real-time VM metrics for running sandboxes
* **Stream template updates** - Real-time template list changes
## API Endpoints
### Sandbox Lifecycle
| Endpoint | Method | Description |
| --------------------------------- | ------ | ----------------------------- |
| `/v1/sandboxes` | POST | Create a new sandbox |
| `/v1/sandboxes` | GET | List all sandboxes |
| `/v1/sandboxes/:id` | GET | Get sandbox details |
| `/v1/sandboxes/:id` | DELETE | Delete a sandbox |
| `/v1/sandboxes/:id/start` | POST | Start a stopped sandbox |
| `/v1/sandboxes/:id/stop` | POST | Stop a running sandbox |
| `/v1/sandboxes/:id/pause` | POST | Pause a running sandbox |
| `/v1/sandboxes/:id/resume` | POST | Resume a paused sandbox |
| `/v1/sandboxes/:id/timeout` | PUT | Set or extend sandbox timeout |
| `/v1/sandboxes/:id/token/refresh` | POST | Refresh JWT token |
### Templates
| Endpoint | Method | Description |
| --------------------------- | ------ | ------------------------ |
| `/v1/templates` | GET | List available templates |
| `/v1/templates/:name` | GET | Get template details |
| `/v1/templates/:templateID` | DELETE | Delete a custom template |
### Template Building
| Endpoint | Method | Description |
| ------------------------------------- | ------ | ---------------------------------- |
| `/v1/templates/files/upload-link` | POST | Get presigned URL for file uploads |
| `/v1/templates/build` | POST | Trigger template build |
| `/v1/templates/build/:buildID/status` | GET | Get build status |
| `/v1/templates/build/:buildID/logs` | GET | Stream build logs |
### Streaming
| Endpoint | Method | Description |
| ---------------------------------- | ------ | ---------------------------- |
| `/v1/sandboxes/stream` | GET | Stream sandbox events (SSE) |
| `/v1/sandboxes/:id/metrics/stream` | GET | Stream sandbox metrics (SSE) |
| `/v1/templates/stream` | GET | Stream template events (SSE) |
## Response Format
All responses use JSON with a consistent structure:
### Success Response
```json theme={null}
{
"id": "sandbox_abc123",
"object": "sandbox",
"status": "running",
...
}
```
### List Response
```json theme={null}
{
"object": "list",
"data": [...],
"has_more": false,
"next_cursor": null,
"request_id": "req_abc123"
}
```
### Error Response
```json theme={null}
{
"error": "Error message",
"code": "ERROR_CODE",
"request_id": "req_abc123"
}
```
## Status Codes
| Code | Description |
| ---- | --------------------------- |
| 200 | Success |
| 201 | Created |
| 202 | Accepted (async operations) |
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 409 | Conflict |
| 402 | Payment Required |
| 503 | Service Unavailable |
## Rate Limits
The Control Plane API has rate limits to ensure fair usage. Rate limit headers are included in responses:
```
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1640995200
```
If you exceed the rate limit, you'll receive a `429 Too Many Requests` response.
## Related
* **[VM Agent API Overview](/api/vm-agent/overview)** - Execute code and manage sandbox resources
* **[Python SDK Quickstart](/sdk/python/quickstart)** - Use the Python SDK instead
* **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Use the JavaScript SDK instead
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn about sandbox creation
* **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle
* [CLI Reference](/cli/introduction) - Command-line interface
## Next Steps
* **[Create Sandbox](/api/control-plane/create-sandbox)** - Create your first sandbox
* **[List Sandboxes](/api/control-plane/list-sandboxes)** - Query and filter sandboxes
* **[Manage Sandboxes](/api/control-plane/get-sandbox)** - Get, update, and delete sandboxes
* **[Templates](/api/control-plane/list-templates)** - Work with templates
# Pause Sandbox
Source: https://docs.hopx.ai/api/control-plane/pause-sandbox
Pause a running sandbox to temporarily suspend execution using the HopX Control Plane API. Temporarily stop sandbox execution while preserving filesystem and state. Learn how to use POST /v1/sandboxes/:id/pause endpoint to pause sandboxes, free resources, and resume later. Includes request examples and state management.
Pause a running sandbox to temporarily suspend all execution. The sandbox will transition from `running` to `paused` status. You can resume it later to continue where it left off.
## Endpoint
```
POST /v1/sandboxes/:id/pause
```
## Request
### Headers
```
Authorization: Bearer $HOPX_API_KEY
```
### Path Parameters
| Parameter | Type | Description |
| --------- | ------ | ------------------- |
| `id` | string | Sandbox ID to pause |
### Example Request
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/pause \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Response
### Success (200 OK)
```json theme={null}
{
"id": "sandbox_abc123xyz",
"status": "paused",
"request_id": "req_abc123"
}
```
### Response Fields
| Field | Type | Description |
| ------------ | ------ | ------------------------ |
| `id` | string | Sandbox ID |
| `status` | string | New status (`paused`) |
| `request_id` | string | Request ID for debugging |
## Status Codes
| Code | Description |
| ----- | --------------------------- |
| `200` | Sandbox paused successfully |
| `401` | Authentication required |
| `404` | Sandbox not found |
## Errors
### Sandbox Not Found (404)
```json theme={null}
{
"error": "Sandbox not found",
"code": "RESOURCE_NOT_FOUND",
"request_id": "req_abc123"
}
```
**Cause:** The sandbox ID doesn't exist or belongs to another organization.
**Fix:** Verify the sandbox ID is correct. List your sandboxes using `GET /v1/sandboxes` to find valid IDs.
## Important Notes
* **Execution suspended** - All running processes are paused
* **State preserved** - Memory state and files are retained
* **Can be resumed** - Use [Resume Sandbox](/api/control-plane/resume-sandbox) to continue
* **VM Agent API** - VM Agent API endpoints are unavailable while paused
## Use Cases
### Pause Long-Running Task
```bash theme={null}
# Pause a sandbox running a long computation
curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/pause \
-H "Authorization: Bearer $HOPX_API_KEY"
```
### Temporarily Free Resources
```bash theme={null}
# Pause to free resources temporarily
curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/pause \
-H "Authorization: Bearer $HOPX_API_KEY"
# ... later, resume ...
curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/resume \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Related
* **SDK**: [sandbox.pause()](/sdk/python/sandbox#pause) - Python SDK method
* [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI
## Next Steps
* **[Resume Sandbox](/api/control-plane/resume-sandbox)** - Resume a paused sandbox
* **[Stop Sandbox](/api/control-plane/stop-sandbox)** - Stop instead of pausing
* **[Get Sandbox](/api/control-plane/get-sandbox)** - Check sandbox status
# Resume Sandbox
Source: https://docs.hopx.ai/api/control-plane/resume-sandbox
Resume a paused sandbox to continue execution using the HopX Control Plane API. Restart a previously paused sandbox to continue work where you left off. Learn how to use POST /v1/sandboxes/:id/resume endpoint to resume paused sandboxes and restore execution state. Includes request examples and state transitions.
Resume a paused sandbox to continue execution from where it was paused. The sandbox will transition from `paused` to `running` status.
## Endpoint
```
POST /v1/sandboxes/:id/resume
```
## Request
### Headers
```
Authorization: Bearer $HOPX_API_KEY
```
### Path Parameters
| Parameter | Type | Description |
| --------- | ------ | -------------------- |
| `id` | string | Sandbox ID to resume |
### Example Request
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/resume \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Response
### Success (200 OK)
```json theme={null}
{
"id": "sandbox_abc123xyz",
"status": "running",
"request_id": "req_abc123"
}
```
### Response Fields
| Field | Type | Description |
| ------------ | ------ | ------------------------ |
| `id` | string | Sandbox ID |
| `status` | string | New status (`running`) |
| `request_id` | string | Request ID for debugging |
## Status Codes
| Code | Description |
| ----- | ---------------------------- |
| `200` | Sandbox resumed successfully |
| `401` | Authentication required |
| `404` | Sandbox not found |
## Errors
### Sandbox Not Found (404)
```json theme={null}
{
"error": "Sandbox not found",
"code": "RESOURCE_NOT_FOUND",
"request_id": "req_abc123"
}
```
**Cause:** The sandbox ID doesn't exist or belongs to another organization.
**Fix:** Verify the sandbox ID is correct. List your sandboxes using `GET /v1/sandboxes` to find valid IDs.
## Important Notes
* **Execution continues** - All paused processes resume from where they were paused
* **State preserved** - Memory state and files remain intact
* **VM Agent API** - VM Agent API endpoints become available again
## Use Cases
### Resume After Pausing
```bash theme={null}
# Pause a sandbox
curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/pause \
-H "Authorization: Bearer $HOPX_API_KEY"
# ... later, resume it ...
curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/resume \
-H "Authorization: Bearer $HOPX_API_KEY"
```
### Resume All Paused Sandboxes
```bash theme={null}
#!/bin/bash
# Get all paused sandboxes
PAUSED=$(curl -s "https://api.hopx.dev/v1/sandboxes?status=paused" \
-H "Authorization: Bearer $HOPX_API_KEY" | \
jq -r '.data[].id')
# Resume each one
for ID in $PAUSED; do
curl -X POST "https://api.hopx.dev/v1/sandboxes/$ID/resume" \
-H "Authorization: Bearer $HOPX_API_KEY"
echo "Resumed $ID"
done
```
## Related
* **SDK**: [sandbox.resume()](/sdk/python/sandbox#resume) - Python SDK method
* [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI
## Next Steps
* **[Pause Sandbox](/api/control-plane/pause-sandbox)** - Pause a running sandbox
* **[Get Sandbox](/api/control-plane/get-sandbox)** - Check sandbox status
* **[Stop Sandbox](/api/control-plane/stop-sandbox)** - Stop instead of pausing
description: Resume a paused sandbox to continue execution
***
Resume a paused sandbox to continue execution from where it was paused. The sandbox will transition from `paused` to `running` status.
## Endpoint
```
POST /v1/sandboxes/:id/resume
```
## Request
### Headers
```
Authorization: Bearer $HOPX_API_KEY
```
### Path Parameters
| Parameter | Type | Description |
| --------- | ------ | -------------------- |
| `id` | string | Sandbox ID to resume |
### Example Request
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/resume \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Response
### Success (200 OK)
```json theme={null}
{
"id": "sandbox_abc123xyz",
"status": "running",
"request_id": "req_abc123"
}
```
### Response Fields
| Field | Type | Description |
| ------------ | ------ | ------------------------ |
| `id` | string | Sandbox ID |
| `status` | string | New status (`running`) |
| `request_id` | string | Request ID for debugging |
## Status Codes
| Code | Description |
| ----- | ---------------------------- |
| `200` | Sandbox resumed successfully |
| `401` | Authentication required |
| `404` | Sandbox not found |
## Errors
### Sandbox Not Found (404)
```json theme={null}
{
"error": "Sandbox not found",
"code": "RESOURCE_NOT_FOUND",
"request_id": "req_abc123"
}
```
**Cause:** The sandbox ID doesn't exist or belongs to another organization.
**Fix:** Verify the sandbox ID is correct. List your sandboxes using `GET /v1/sandboxes` to find valid IDs.
## Important Notes
* **Execution continues** - All paused processes resume from where they were paused
* **State preserved** - Memory state and files remain intact
* **VM Agent API** - VM Agent API endpoints become available again
## Use Cases
### Resume After Pausing
```bash theme={null}
# Pause a sandbox
curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/pause \
-H "Authorization: Bearer $HOPX_API_KEY"
# ... later, resume it ...
curl -X POST https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/resume \
-H "Authorization: Bearer $HOPX_API_KEY"
```
### Resume All Paused Sandboxes
```bash theme={null}
#!/bin/bash
# Get all paused sandboxes
PAUSED=$(curl -s "https://api.hopx.dev/v1/sandboxes?status=paused" \
-H "Authorization: Bearer $HOPX_API_KEY" | \
jq -r '.data[].id')
# Resume each one
for ID in $PAUSED; do
curl -X POST "https://api.hopx.dev/v1/sandboxes/$ID/resume" \
-H "Authorization: Bearer $HOPX_API_KEY"
echo "Resumed $ID"
done
```
## Next Steps
* **[Pause Sandbox](/api/control-plane/pause-sandbox)** - Pause a running sandbox
* **[Get Sandbox](/api/control-plane/get-sandbox)** - Check sandbox status
* **[Stop Sandbox](/api/control-plane/stop-sandbox)** - Stop instead of pausing
# Set Sandbox Timeout
Source: https://docs.hopx.ai/api/control-plane/set-timeout
Set or extend the auto-shutdown timeout for a sandbox using the HopX Control Plane API. Configure when sandboxes are automatically destroyed to manage resources and costs. Learn how to use PUT /v1/sandboxes/:id/timeout endpoint to set initial timeouts or extend existing timeouts for long-running tasks. Includes request examples and timeout management.
Set or extend the auto-shutdown timeout for a sandbox. When the timeout expires, the sandbox will be automatically deleted.
## Endpoint
```
PUT /v1/sandboxes/:id/timeout
```
## Request
### Headers
```
Authorization: Bearer $HOPX_API_KEY
Content-Type: application/json
```
### Path Parameters
| Parameter | Type | Description |
| --------- | ------ | ----------- |
| `id` | string | Sandbox ID |
### Body Parameters
| Parameter | Type | Required | Description |
| ----------------- | ------- | -------- | ---------------------------------------- |
| `timeout_seconds` | integer | Yes | New timeout duration in seconds from now |
### Example Request
Set timeout to 1 hour (3600 seconds):
```bash theme={null}
curl -X PUT https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/timeout \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"timeout_seconds": 3600
}'
```
Extend timeout by 2 hours:
```bash theme={null}
curl -X PUT https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/timeout \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"timeout_seconds": 7200
}'
```
## Response
### Success (200 OK)
```json theme={null}
{
"id": "sandbox_abc123xyz",
"timeout_seconds": 3600,
"expires_at": "2025-01-28T01:00:00Z",
"request_id": "req_abc123"
}
```
### Response Fields
| Field | Type | Description |
| ----------------- | ------- | ------------------------------------------- |
| `id` | string | Sandbox ID |
| `timeout_seconds` | integer | New timeout duration in seconds |
| `expires_at` | string | ISO 8601 timestamp when sandbox will expire |
| `request_id` | string | Request ID for debugging |
## Status Codes
| Code | Description |
| ----- | ---------------------------- |
| `200` | Timeout updated successfully |
| `400` | Invalid timeout value |
| `401` | Authentication required |
| `404` | Sandbox not found |
## Errors
### Invalid Timeout (400)
```json theme={null}
{
"error": "Invalid timeout value: must be positive",
"code": "INVALID_REQUEST",
"request_id": "req_abc123"
}
```
**Cause:** The `timeout_seconds` value is negative, zero, or invalid.
**Fix:** Ensure `timeout_seconds` is a positive integer.
### Sandbox Not Found (404)
```json theme={null}
{
"error": "Sandbox not found",
"code": "RESOURCE_NOT_FOUND",
"request_id": "req_abc123"
}
```
**Cause:** The sandbox ID doesn't exist or belongs to another organization.
**Fix:** Verify the sandbox ID is correct.
## Important Notes
* **Absolute timeout** - The timeout is set from the current time, not relative to the previous timeout
* **Auto-deletion** - When the timeout expires, the sandbox is automatically deleted
* **Can be extended** - You can extend the timeout multiple times
* **No maximum** - There's no maximum timeout limit (subject to your plan)
## Use Cases
### Extend Timeout for Long-Running Task
```bash theme={null}
# Check current expiration
curl https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz \
-H "Authorization: Bearer $HOPX_API_KEY" | jq '.expires_at'
# Extend by 2 hours
curl -X PUT https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/timeout \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"timeout_seconds": 7200
}'
```
### Set Timeout on Creation
```bash theme={null}
# Create sandbox with 1 hour timeout
curl -X POST https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "73",
"timeout_seconds": 3600
}'
```
### Keep Sandbox Alive Indefinitely
```bash theme={null}
# Set a very long timeout (e.g., 30 days)
curl -X PUT https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz/timeout \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"timeout_seconds": 2592000
}'
```
## Related
* **SDK**: [sandbox.set\_timeout()](/sdk/python/sandbox#set_timeout) - Python SDK method
* [CLI Reference](/cli/introduction) - Command-line interface
## Next Steps
* **[Get Sandbox](/api/control-plane/get-sandbox)** - Check current timeout and expiration
* **[Create Sandbox](/api/control-plane/create-sandbox)** - Set timeout on creation
* **[Delete Sandbox](/api/control-plane/delete-sandbox)** - Manually delete before timeout
# Overview
Source: https://docs.hopx.ai/api/introduction
Learn what the HopX REST API does, its main resources, and who uses it. The HopX API provides two interfaces: Control Plane API for sandbox lifecycle management and VM Agent API for code execution, file operations, and desktop automation. Get started with authentication, endpoints, and API best practices. For SDK or CLI usage, see the SDK Reference or CLI Reference sections.
The HopX REST API enables you to create, manage, and interact with cloud sandboxes programmatically. Use the API to build automation workflows, integrate sandbox execution into your applications, or create custom tooling on top of HopX.
## What the API Does
The HopX API provides two main interfaces:
### Control Plane API
The **Control Plane API** (`https://api.hopx.dev`) manages sandbox lifecycle and templates:
* **Create and manage sandboxes** - Spin up isolated cloud environments from templates
* **Template management** - List, view, and build custom templates
* **Real-time monitoring** - Stream sandbox events and metrics via Server-Sent Events (SSE)
* **Resource management** - Start, stop, pause, resume, and delete sandboxes
### VM Agent API
The **VM Agent API** (sandbox-specific URLs) executes code and manages sandbox resources:
* **Code execution** - Run Python, JavaScript, Bash, and Go code synchronously or asynchronously
* **File operations** - Read, write, list, upload, and download files
* **Command execution** - Run shell commands in the sandbox environment
* **Desktop automation** - Control VNC, mouse, keyboard, screenshots, and screen recording
* **Observability** - Monitor processes, metrics, cache, and terminal access
## Main Resources
### Sandboxes
Sandboxes are isolated cloud environments created from templates. Each sandbox has:
* **Unique ID** - Identifier for all operations
* **Status** - `running`, `stopped`, `paused`, `creating`
* **Resources** - vCPU, memory, and disk allocated from template
* **Public URL** - Accessible endpoint for VM Agent API
* **JWT Token** - Authentication token for VM Agent API calls
### Templates
Templates define the base environment for sandboxes:
* **Pre-built templates** - Python, Node.js, Ubuntu, and more
* **Custom templates** - Build your own with Docker images and build steps
* **Resource specifications** - vCPU, memory, and disk limits
* **Features** - Desktop support, internet access, pre-installed packages
## When to Use the API vs SDK vs CLI
### Use the REST API when:
* ✅ You're building in a language without an official SDK
* ✅ You need fine-grained control over HTTP requests
* ✅ You're integrating with existing HTTP client libraries
* ✅ You need custom retry logic or connection pooling
* ✅ You're building serverless functions or edge workers
### Use the SDK when:
* ✅ You're building Python or JavaScript/TypeScript applications
* ✅ You want type safety and IDE autocomplete
* ✅ You prefer language-native error handling
* ✅ You want automatic resource management
### Use the CLI when:
* ✅ You prefer command-line workflows
* ✅ You're scripting or automating from shell
* ✅ You want quick one-off operations
* ✅ You're working in CI/CD pipelines
## Typical Consumers
The HopX API is used by:
* **Backend developers** - Integrating sandbox execution into applications
* **DevOps engineers** - Automating infrastructure and testing workflows
* **AI/ML engineers** - Running model training and inference in isolated environments
* **CI/CD pipelines** - Executing tests and builds in clean sandboxes
* **Automation tools** - Building custom tooling and workflows
## Base URLs
### Control Plane API
```
https://api.hopx.dev
```
All Control Plane endpoints are prefixed with `/v1/`:
```
https://api.hopx.dev/v1/sandboxes
https://api.hopx.dev/v1/templates
```
### VM Agent API
Each sandbox has its own VM Agent API endpoint:
```
https://{sandbox_id}.hopx.dev
```
Or using the direct URL format:
```
https://{port}-{vmId}.{serverId}.hopx.dev
```
The VM Agent base URL is returned in the `public_host` or `direct_url` field when creating a sandbox.
## API Specification
The HopX API follows RESTful principles:
* **HTTP methods** - GET, POST, PUT, DELETE for resource operations
* **JSON request/response** - All request bodies and responses use JSON
* **Standard status codes** - 200, 201, 400, 401, 404, 503, etc.
* **Error format** - Consistent error response structure with codes and messages
An OpenAPI specification is available for the Control Plane API. The spec is kept in sync with the API implementation and can be used to generate client SDKs or mock servers.
## Related
* **[API Quickstart](/api/quickstart)** - Get started with the API
* **[Authentication](/api/authentication)** - Learn about API authentication
* **[Python SDK Quickstart](/sdk/python/quickstart)** - Use the Python SDK instead
* **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Use the JavaScript SDK instead
* **[VM Agent API Overview](/api/vm-agent/overview)** - Learn about the VM Agent API
* [CLI Reference](/cli/introduction) - Command-line interface
## Next Steps
* **[Authentication](/api/authentication)** - Learn how to authenticate API requests
* **[Quickstart](/api/quickstart)** - Get your first sandbox running in minutes
* **[Control Plane API](/api/control-plane/overview)** - Manage sandboxes and templates
* **[VM Agent API](/api/vm-agent/overview)** - Execute code and manage sandbox resources
# Quickstart
Source: https://docs.hopx.ai/api/quickstart
Get your first sandbox running with the HopX API in minutes. Complete quickstart guide for using the HopX REST API to create sandboxes, execute code, manage files, and clean up resources. Learn authentication, make your first API call, and understand API response formats. Includes curl examples and response handling.
Get up and running with the HopX API in minutes. This quickstart walks you through creating your first sandbox, executing code, and cleaning up.
## What You'll Learn
In this quickstart, you'll learn how to:
* Authenticate with the HopX API using API keys
* Create sandboxes using the Control Plane API
* Execute code using the VM Agent API
* Handle API responses and extract results
* Delete sandboxes to free resources
* Use common API patterns and variations
## Prerequisites
Before you begin, you'll need:
* An API key from [console.hopx.dev](https://console.hopx.dev)
* `curl` installed (or any HTTP client)
* Basic familiarity with REST APIs
## Step 1: Set Your API key
Set your API key as an environment variable:
```bash theme={null}
export HOPX_API_KEY="hopx_live_YOUR_KEY_ID.YOUR_SECRET"
```
Replace `YOUR_KEY_ID` and `YOUR_SECRET` with your actual API key from the dashboard.
## Step 2: Create a Sandbox
Create a sandbox from a pre-built template:
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "73",
"timeout_seconds": 3600
}'
```
**Response:**
```json theme={null}
{
"id": "sandbox_abc123xyz",
"object": "sandbox",
"status": "running",
"public_host": "https://sandbox_abc123xyz.hopx.dev",
"direct_url": "https://sandbox_abc123xyz.hopx.dev",
"template_id": "73",
"template_name": "code-interpreter",
"organization_id": 123,
"region": "us-east",
"resources": {
"vcpu": 2,
"memory_mb": 4096,
"disk_mb": 10240
},
"internet_access": true,
"timeout_seconds": 3600,
"created_at": "2025-01-28T00:00:00Z",
"auth_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_expires_at": "2025-01-28T01:00:00Z",
"request_id": "req_abc123"
}
```
Save the `id` and `auth_token` from the response. You'll need them for the next steps.
## Step 3: Execute Code
Execute Python code in your sandbox using the VM Agent API:
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." \
-H "Content-Type: application/json" \
-d '{
"code": "print(\"Hello from HopX!\")",
"language": "python"
}'
```
**Response:**
```json theme={null}
{
"success": true,
"stdout": "Hello from HopX!\n",
"stderr": "",
"exit_code": 0,
"execution_time": 0.15
}
```
🎉 **Success!** You've executed your first code in a HopX sandbox. The output shows "Hello from HopX!" was printed successfully.
## Step 4: Clean Up
Delete the sandbox when you're done:
```bash theme={null}
curl -X DELETE https://api.hopx.dev/v1/sandboxes/sandbox_abc123xyz \
-H "Authorization: Bearer $HOPX_API_KEY"
```
**Response:**
```json theme={null}
{
"status": "deleted",
"id": "sandbox_abc123xyz",
"request_id": "req_abc123"
}
```
## What Just Happened?
1. **Created a sandbox** - You spun up an isolated cloud environment from the `code-interpreter` template
2. **Executed code** - You ran Python code in the sandbox and received the output
3. **Cleaned up** - You deleted the sandbox to free resources
The sandbox was completely isolated - any code you run can't access your local system or other sandboxes.
## Related
* **[Python SDK Quickstart](/sdk/python/quickstart)** - Get started with the Python SDK
* **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Get started with the JavaScript SDK
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn more about sandbox creation
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Understand code execution concepts
* [CLI Reference](/cli/introduction) - Command-line interface
## Next Steps
* **[Control Plane API](/api/control-plane/overview)** - Learn about all sandbox management endpoints
* **[VM Agent API](/api/vm-agent/overview)** - Explore code execution, file operations, and more
* **[Authentication](/api/authentication)** - Deep dive into API key management and security
* **[SDK Quickstart](/sdk/python/quickstart)** - Use the Python or JavaScript SDK for easier integration
## Common Variations
### Create Sandbox with Environment Variables
```bash theme={null}
curl -X POST https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"template_id": "73",
"env_vars": {
"MY_VAR": "my_value",
"API_KEY": "secret123"
}
}'
```
### Execute JavaScript Code
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer $AUTH_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "console.log(\"Hello from JavaScript!\");",
"language": "javascript"
}'
```
### List All Sandboxes
```bash theme={null}
curl https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer $HOPX_API_KEY"
```
## Troubleshooting
### Error: 401 Unauthorized
Your API key is missing or invalid. Verify:
* The `HOPX_API_KEY` environment variable is set correctly
* You're using the `Authorization: Bearer` header format
* Your API key hasn't been revoked in the dashboard
### Error: 404 Template Not Found
The template ID doesn't exist. Try:
* Listing available templates: `GET /v1/templates`
* Using a template name instead: `"template_name": "code-interpreter"`
### Error: 503 Service Unavailable
No sandboxes are available at the moment. This is usually temporary. Try again in a few moments.
For more help, see the [Errors & Troubleshooting](/api/errors) guide.
# Clear Execution Cache
Source: https://docs.hopx.ai/api/vm-agent/clear-cache
Clear the sandbox execution result cache to free memory using the HopX VM Agent API. Remove cached execution results to free resources, force re-execution, or reset cache statistics. Learn how to use POST /cache/clear endpoint to clear all cached results. Includes request examples and cache management.
Clear the execution result cache to free memory or force re-execution of previously cached code.
## Endpoint
```
POST /cache/clear
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
```
### Example Request
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/cache/clear \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Response
### Success (200 OK)
```json theme={null}
{
"message": "Cache cleared successfully",
"cleared_entries": 25,
"freed_bytes": 512000
}
```
## Status Codes
| Code | Description |
| ---- | ------------- |
| 200 | Cache cleared |
| 401 | Unauthorized |
## Use Cases
### Force Code Re-execution
```bash theme={null}
# Clear cache
curl -X POST https://sandbox_abc123xyz.hopx.dev/cache/clear \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
# Execute code (will not use cache)
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "print(\"Fresh execution\")",
"language": "python"
}'
```
## Related
* **SDK**: [sandbox.cache.clear()](/sdk/python/cache#clear) - Python SDK method
* [CLI System Commands](/cli/commands/system) - System operations from CLI
## Next Steps
* **[Get Cache Statistics](/api/vm-agent/get-cache-stats)** - View cache metrics
* **[Execute Code](/api/vm-agent/execute)** - Execute code
# Clear Environment Variables
Source: https://docs.hopx.ai/api/vm-agent/clear-env
Remove all global environment variables from the sandbox using the HopX VM Agent API. Clear all environment variables to reset configuration or start fresh. Learn how to use DELETE /env endpoint to remove all variables at once. Includes request examples and cleanup best practices.
Remove all custom environment variables from the sandbox. System environment variables may be preserved.
This removes ALL custom environment variables. This operation cannot be undone.
## Endpoint
```
DELETE /env
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
```
### Example Request
```bash theme={null}
curl -X DELETE https://sandbox_abc123xyz.hopx.dev/env \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Response
### Success (204 No Content)
Empty response on success.
## Status Codes
| Code | Description |
| ---- | ------------------------------ |
| 204 | Variables cleared successfully |
| 401 | Unauthorized |
## Use Cases
### Reset Environment
```bash theme={null}
curl -X DELETE https://sandbox_abc123xyz.hopx.dev/env \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Related
* **SDK**: [sandbox.env.clear()](/sdk/python/environment-variables#clear) - Python SDK method
* [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI
## Next Steps
* **[Get Environment Variables](/api/vm-agent/get-env)** - View all variables
* **[Set Environment Variables](/api/vm-agent/set-env)** - Set new variables
# Execute Code
Source: https://docs.hopx.ai/api/vm-agent/execute
Execute code synchronously in a sandbox and get results. Run Python, JavaScript, Bash, or Go code in isolated cloud environments using the HopX VM Agent API. Learn how to use POST /execute endpoint with code examples, error handling, and result processing.
Execute code synchronously in the sandbox. The request waits until execution completes and returns the output.
## Endpoint
```
POST /execute
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
```
### Body Parameters
| Parameter | Type | Required | Description |
| ------------- | ------- | -------- | ------------------------------------------------------------------ |
| `code` | string | Yes | Code to execute |
| `language` | string | No | Language: `python`, `javascript`, `bash`, `go` (default: `python`) |
| `timeout` | integer | No | Execution timeout in seconds (default: 60, max: 300) |
| `working_dir` | string | No | Working directory (default: `/workspace`) |
| `env` | object | No | Environment variables for this execution only |
### Example Request
Execute Python code:
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "print(\"Hello from HopX!\")",
"language": "python"
}'
```
Execute JavaScript code:
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "console.log(\"Hello from Node.js!\");",
"language": "javascript"
}'
```
Execute with custom environment:
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import os; print(os.getenv(\"MY_VAR\"))",
"language": "python",
"env": {
"MY_VAR": "my_value"
}
}'
```
## Response
### Success (200 OK)
```json theme={null}
{
"success": true,
"stdout": "Hello from HopX!\n",
"stderr": "",
"exit_code": 0,
"execution_time": 0.15
}
```
### Response Fields
| Field | Type | Description |
| ---------------- | ------- | ---------------------------------------- |
| `success` | boolean | Whether execution completed successfully |
| `stdout` | string | Standard output |
| `stderr` | string | Standard error |
| `exit_code` | integer | Exit code (0 = success) |
| `execution_time` | number | Execution time in seconds |
## Status Codes
| Code | Description |
| ---- | ------------------------------------------------ |
| 200 | Execution completed |
| 400 | Invalid request (missing code, invalid language) |
| 401 | Unauthorized (invalid or expired JWT) |
| 408 | Execution timeout |
| 500 | Execution failed |
## Supported Languages
### Python
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import pandas as pd\ndf = pd.DataFrame({\"a\": [1,2,3]})\nprint(df)",
"language": "python"
}'
```
### JavaScript (Node.js)
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "const fs = require(\"fs\");\nconsole.log(fs.readdirSync(\".\"));",
"language": "javascript"
}'
```
### Bash
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "ls -la /workspace",
"language": "bash"
}'
```
## Errors
### Timeout (408)
```json theme={null}
{
"error": "Execution timeout after 60 seconds",
"code": "EXECUTION_TIMEOUT"
}
```
**Cause:** Code execution exceeded the timeout limit.
**Fix:** Increase the timeout or optimize your code.
### Invalid Language (400)
```json theme={null}
{
"error": "Invalid language: ruby",
"code": "INVALID_REQUEST"
}
```
**Cause:** Unsupported language specified.
**Fix:** Use one of the supported languages: `python`, `javascript`, `bash`, `go`.
### Execution Failed (500)
```json theme={null}
{
"success": false,
"stdout": "",
"stderr": "NameError: name 'x' is not defined\n",
"exit_code": 1,
"execution_time": 0.05
}
```
**Cause:** Code execution failed (syntax error, runtime error, etc.).
**Fix:** Check the `stderr` field for error details.
## Use Cases
### Data Analysis
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import pandas as pd\nimport numpy as np\n\ndata = {\"sales\": [100, 150, 200, 180, 220]}\ndf = pd.DataFrame(data)\n\nprint(f\"Mean: ${df[\"sales\"].mean():.2f}\")\nprint(f\"Median: ${df[\"sales\"].median():.2f}\")",
"language": "python"
}'
```
### File Processing
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "with open(\"/workspace/data.txt\", \"r\") as f:\n lines = f.readlines()\n print(f\"File has {len(lines)} lines\")",
"language": "python"
}'
```
### System Information
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import platform\nimport os\n\nprint(f\"OS: {platform.system()}\")\nprint(f\"Python: {platform.python_version()}\")\nprint(f\"CPU Count: {os.cpu_count()}\")",
"language": "python"
}'
```
## Related
* **SDK**: [sandbox.run\_code()](/sdk/python/sandbox#run_code) - Python SDK method
* [CLI Code Execution](/cli/commands/run) - Execute code from CLI
## Next Steps
* **[Rich Output](/api/vm-agent/execute-rich)** - Capture plots and visualizations
* **[Background Execution](/api/vm-agent/execute-background)** - Run long-running tasks
* **[Async Execution](/api/vm-agent/execute-async)** - Execute with webhook callbacks
# Async Code Execution with Webhooks
Source: https://docs.hopx.ai/api/vm-agent/execute-async
Execute very long-running code and receive results via webhook callback using the HopX VM Agent API. Run code asynchronously for long-running tasks and receive execution results via webhook when complete. Learn how to use POST /execute/async endpoint with webhook configuration. Includes request examples and webhook setup.
Execute very long-running code (>5 minutes) and receive results via webhook callback when complete. Perfect for tasks that take hours or need to run independently of your connection.
## Endpoint
```
POST /execute/async
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
```
### Body Parameters
| Parameter | Type | Required | Description |
| --------------------------- | ------- | -------- | --------------------------------------------- |
| `code` | string | Yes | Code to execute |
| `callback_url` | string | Yes | URL to POST results to when complete |
| `language` | string | No | Language (default: `python`) |
| `timeout` | integer | No | Max execution time in seconds (default: 3600) |
| `working_dir` | string | No | Working directory |
| `env` | object | No | Environment variables |
| `callback_headers` | object | No | Custom headers for callback request |
| `callback_signature_secret` | string | No | Secret to sign callback payload (HMAC-SHA256) |
### Example Request
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/async \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import time\nfor i in range(3600):\n if i % 60 == 0:\n print(f\"Progress: {i//60} minutes\")\n time.sleep(1)\nprint(\"Complete!\")",
"callback_url": "https://your-server.com/webhook",
"language": "python",
"timeout": 7200,
"callback_signature_secret": "your-secret-key"
}'
```
## Response
### Success (200 OK)
```json theme={null}
{
"execution_id": "exec_abc123",
"status": "queued",
"callback_url": "https://your-server.com/webhook"
}
```
### Response Fields
| Field | Type | Description |
| -------------- | ------ | ------------------------------------- |
| `execution_id` | string | Execution ID for tracking |
| `status` | string | Initial status (`queued`) |
| `callback_url` | string | Webhook URL that will receive results |
## Callback Behavior
When execution completes, the API POSTs results to your `callback_url`:
### Callback Request
```
POST https://your-server.com/webhook
Content-Type: application/json
X-HopX-Signature: sha256=abc123...
X-HopX-Timestamp: 1706400000
```
### Callback Payload
```json theme={null}
{
"execution_id": "exec_abc123",
"status": "completed",
"success": true,
"stdout": "Progress: 0 minutes\nProgress: 1 minutes\n...\nComplete!\n",
"stderr": "",
"exit_code": 0,
"execution_time": 3600.5,
"started_at": "2025-01-28T00:00:00Z",
"completed_at": "2025-01-28T01:00:00Z"
}
```
### Callback Headers
| Header | Description |
| ------------------ | ----------------------------------------------------- |
| `X-HopX-Signature` | HMAC-SHA256 signature of payload (if secret provided) |
| `X-HopX-Timestamp` | Unix timestamp of callback |
| Custom headers | From `callback_headers` in request |
## Status Codes
| Code | Description |
| ---- | ---------------------------------------------------- |
| 200 | Execution queued |
| 400 | Invalid request (missing callback\_url, invalid URL) |
| 401 | Unauthorized |
| 500 | Failed to queue execution |
## Verify Webhook Signature
To verify the webhook signature:
### Python
```python theme={null}
import hmac
import hashlib
import json
def verify_webhook(payload_bytes, signature, secret):
"""Verify HMAC-SHA256 signature"""
expected_signature = hmac.new(
secret.encode('utf-8'),
payload_bytes,
hashlib.sha256
).hexdigest()
# Remove 'sha256=' prefix if present
if signature.startswith('sha256='):
signature = signature[7:]
return hmac.compare_digest(signature, expected_signature)
# In your webhook handler
@app.route('/webhook', methods=['POST'])
def webhook():
signature = request.headers.get('X-HopX-Signature')
timestamp = request.headers.get('X-HopX-Timestamp')
payload_bytes = request.get_data()
if not verify_webhook(payload_bytes, signature, 'your-secret-key'):
return 'Invalid signature', 401
data = json.loads(payload_bytes)
print(f"Execution {data['execution_id']}: {data['status']}")
return 'OK', 200
```
### JavaScript
```javascript theme={null}
const crypto = require('crypto');
function verifyWebhook(payloadString, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payloadString)
.digest('hex');
// Remove 'sha256=' prefix if present
const actualSignature = signature.startsWith('sha256=')
? signature.slice(7)
: signature;
return crypto.timingSafeEqual(
Buffer.from(actualSignature),
Buffer.from(expectedSignature)
);
}
// In your webhook endpoint
app.post('/webhook', express.raw({type: 'application/json'}), (req, res) => {
const signature = req.headers['x-HopX-signature'];
const timestamp = req.headers['x-HopX-timestamp'];
const payloadString = req.body.toString('utf8');
if (!verifyWebhook(payloadString, signature, 'your-secret-key')) {
return res.status(401).send('Invalid signature');
}
const data = JSON.parse(payloadString);
console.log(`Execution ${data.execution_id}: ${data.status}`);
res.send('OK');
});
```
## Use Cases
### Long-Running Model Training
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/async \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import tensorflow as tf\nimport time\n\nprint(\"Starting model training...\")\nmodel = tf.keras.Sequential([...])\nmodel.fit(X_train, y_train, epochs=100, batch_size=32)\nmodel.save(\"/workspace/trained_model.h5\")\nprint(\"Training complete!\")",
"callback_url": "https://your-server.com/training-complete",
"language": "python",
"timeout": 14400,
"callback_signature_secret": "your-secret-key"
}'
```
### Batch Data Processing
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/async \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import pandas as pd\nimport glob\n\nprint(\"Processing batch files...\")\nall_files = glob.glob(\"/workspace/data/*.csv\")\ndfs = [pd.read_csv(f) for f in all_files]\ncombined = pd.concat(dfs, ignore_index=True)\ncombined.to_csv(\"/workspace/combined_result.csv\")\nprint(f\"Processed {len(all_files)} files\")",
"callback_url": "https://your-server.com/batch-complete",
"language": "python",
"timeout": 7200
}'
```
### Custom Callback Headers
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/async \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "print(\"Task complete\")",
"callback_url": "https://your-server.com/webhook",
"language": "python",
"callback_headers": {
"X-Custom-Header": "my-value",
"X-Task-ID": "task-123"
}
}'
```
## Related
* **[Async Execution with Webhooks](/core-concepts/code-execution/async-webhooks)** - Learn about async execution
* **[Background Execution](/api/vm-agent/execute-background)** - Shorter background tasks
* **[List Processes](/api/vm-agent/list-processes)** - Check process status
* **SDK**: [sandbox.run\_code\_async()](/sdk/python/sandbox#run_code_async) - Python SDK method
* [CLI Code Execution](/cli/commands/run) - Execute code from CLI
## Next Steps
* **[Background Execution](/api/vm-agent/execute-background)** - Shorter background tasks
* **[List Processes](/api/vm-agent/list-processes)** - Check process status
* **[Execute Code](/api/vm-agent/execute)** - Simple synchronous execution
# Background Execution
Source: https://docs.hopx.ai/api/vm-agent/execute-background
Execute code in the background and return immediately with a process ID using the HopX VM Agent API. Run long-running code without blocking, monitor process status, and retrieve results when complete. Learn how to use POST /execute/background endpoint for asynchronous code execution. Includes request examples and process management.
Execute code in the background and return immediately. The code continues running asynchronously, and you can check its status using the process ID.
## Endpoint
```
POST /execute/background
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
```
### Body Parameters
| Parameter | Type | Required | Description |
| ------------- | ------- | -------- | -------------------------------------------- |
| `code` | string | Yes | Code to execute |
| `language` | string | No | Language (default: `python`) |
| `timeout` | integer | No | Max execution time in seconds (default: 300) |
| `working_dir` | string | No | Working directory |
| `env` | object | No | Environment variables |
| `name` | string | No | Process name for identification |
### Example Request
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/background \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import time\nfor i in range(10):\n print(f\"Step {i+1}/10\")\n time.sleep(1)\nprint(\"Done!\")",
"language": "python",
"name": "long-task"
}'
```
## Response
### Success (200 OK)
```json theme={null}
{
"process_id": "proc_abc123",
"execution_id": "exec_xyz789",
"status": "running"
}
```
### Response Fields
| Field | Type | Description |
| -------------- | ------ | ---------------------------------------- |
| `process_id` | string | Process ID (use to check status or kill) |
| `execution_id` | string | Execution ID |
| `status` | string | Initial status (`queued` or `running`) |
## Status Codes
| Code | Description |
| ---- | ----------------------- |
| 200 | Process started |
| 400 | Invalid request |
| 401 | Unauthorized |
| 500 | Failed to start process |
## Check Process Status
Use the List Processes endpoint to check status:
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
Response:
```json theme={null}
{
"processes": [
{
"process_id": "proc_abc123",
"execution_id": "exec_xyz789",
"name": "long-task",
"status": "running",
"language": "python",
"started_at": "2025-01-28T00:00:00Z",
"stdout": "Step 1/10\nStep 2/10\n",
"stderr": "",
"exit_code": null
}
],
"count": 1
}
```
## Kill Background Process
Use the Kill Process endpoint to terminate:
```bash theme={null}
curl -X DELETE https://sandbox_abc123xyz.hopx.dev/execute/kill \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"process_id": "proc_abc123"
}'
```
## Use Cases
### Long-Running Data Processing
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/background \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import pandas as pd\nimport time\n\nprint(\"Processing large dataset...\")\ntime.sleep(30)\ndf = pd.read_csv(\"/workspace/large_file.csv\")\nresult = df.groupby(\"category\").sum()\nresult.to_csv(\"/workspace/result.csv\")\nprint(\"Processing complete!\")",
"language": "python",
"timeout": 600,
"name": "data-processing"
}'
```
### Model Training
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/background \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "from sklearn.ensemble import RandomForestClassifier\nimport numpy as np\nimport time\n\nprint(\"Training model...\")\nX = np.random.rand(10000, 20)\ny = np.random.randint(0, 2, 10000)\n\nmodel = RandomForestClassifier(n_estimators=100)\nmodel.fit(X, y)\n\nprint(f\"Model accuracy: {model.score(X, y):.2f}\")\nprint(\"Training complete!\")",
"language": "python",
"timeout": 1800,
"name": "model-training"
}'
```
### Monitoring Background Process
```bash theme={null}
#!/bin/bash
PROCESS_ID="proc_abc123"
while true; do
STATUS=$(curl -s https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq -r ".processes[] | select(.process_id == \"$PROCESS_ID\") | .status")
echo "Status: $STATUS"
if [ "$STATUS" == "completed" ] || [ "$STATUS" == "failed" ]; then
echo "Process finished"
break
fi
sleep 5
done
```
### Parallel Execution
```bash theme={null}
#!/bin/bash
# Start multiple background tasks
for i in {1..5}; do
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute/background \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"code\": \"import time\\ntime.sleep(10)\\nprint('Task $i complete')\",
\"language\": \"python\",
\"name\": \"task-$i\"
}"
echo "Started task $i"
done
echo "All tasks started, check status:"
curl https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Related
* **SDK**: [sandbox.run\_code\_background()](/sdk/python/sandbox#run_code_background) - Python SDK method
* [CLI Code Execution](/cli/commands/run) - Execute code from CLI
## Next Steps
* **[List Processes](/api/vm-agent/list-processes)** - Check background process status
* **[Kill Process](/api/vm-agent/kill-process)** - Terminate a background process
* **[Async Execution](/api/vm-agent/execute-async)** - Execute with webhook callbacks
# Check File Exists
Source: https://docs.hopx.ai/api/vm-agent/file-exists
Check if a file or directory exists in the sandbox using the HopX VM Agent API. Verify file existence before reading or writing, check directory presence, and handle missing files gracefully. Learn how to use GET /files/exists endpoint to check file existence. Includes request examples and error handling.
Check if a file or directory exists before reading or writing. Useful for conditional logic and error prevention.
## Endpoint
```
GET /files/exists
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
```
### Query Parameters
| Parameter | Type | Required | Description |
| --------- | ------ | -------- | ------------- |
| `path` | string | Yes | Path to check |
### Example Request
```bash theme={null}
curl "https://sandbox_abc123xyz.hopx.dev/files/exists?path=/workspace/data.txt" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Response
### Success (200 OK)
```json theme={null}
{
"exists": true,
"path": "/workspace/data.txt"
}
```
## Status Codes
| Code | Description |
| ---- | --------------------------------- |
| 200 | Success (exists is true or false) |
| 401 | Unauthorized |
## Use Cases
### Conditional Read
```bash theme={null}
#!/bin/bash
EXISTS=$(curl -s "https://sandbox_abc123xyz.hopx.dev/files/exists?path=/workspace/config.json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | jq -r '.exists')
if [ "$EXISTS" == "true" ]; then
curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/config.json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
else
echo "Config file not found"
fi
```
## Related
* **SDK**: [sandbox.files.exists()](/sdk/python/files#exists) - Python SDK method
* [CLI File Operations](/cli/commands/files) - File operations from CLI
## Next Steps
* **[Read File](/api/vm-agent/read-file)** - Read file if exists
* **[Write File](/api/vm-agent/write-file)** - Create file
# Get Cache Statistics
Source: https://docs.hopx.ai/api/vm-agent/get-cache-stats
Get cache hit rate and usage statistics for sandbox code execution results using the HopX VM Agent API. Monitor cache performance, view hit rates, and track cached items to optimize execution speed. Learn how to use GET /cache/stats endpoint to retrieve cache statistics. Includes request examples and performance metrics.
Get the VM agent status, version, and basic health information. This endpoint provides agent metadata rather than cache statistics.
For clearing the execution cache, use the [Clear Cache](/api/vm-agent/clear-cache) endpoint.
## Endpoint
```
GET /cache
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
```
### Example Request
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/cache \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Response
### Success (200 OK)
```json theme={null}
{
"agent": "HopX VM Agent (Go)",
"status": "running",
"version": "3.2.8",
"vm_id": "17633354502w4l8eiy",
"message": "success",
"timestamp": "2025-11-16T23:25:45Z"
}
```
### Response Fields
| Field | Type | Description |
| ----------- | ------ | ------------------------------- |
| `agent` | string | Agent name and runtime |
| `status` | string | Agent status (running, stopped) |
| `version` | string | Agent version |
| `vm_id` | string | Sandbox/VM identifier |
| `message` | string | Status message |
| `timestamp` | string | Response timestamp (ISO 8601) |
## Status Codes
| Code | Description |
| ---- | ------------ |
| 200 | Success |
| 401 | Unauthorized |
## Use Cases
### Check Agent Status
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/cache \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq '{agent, status, version}'
```
### Verify Agent Version
```bash theme={null}
VERSION=$(curl -s https://sandbox_abc123xyz.hopx.dev/cache \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | jq -r '.version')
echo "Agent version: $VERSION"
```
### Monitor Agent Health
```bash theme={null}
STATUS=$(curl -s https://sandbox_abc123xyz.hopx.dev/cache \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | jq -r '.status')
if [ "$STATUS" == "running" ]; then
echo "✅ Agent is healthy"
else
echo "⚠️ Agent status: $STATUS"
fi
```
## Related
* **SDK**: [sandbox.cache.stats()](/sdk/python/cache#stats) - Python SDK method
* [CLI System Commands](/cli/commands/system) - System operations from CLI
## Next Steps
* **[Clear Cache](/api/vm-agent/clear-cache)** - Clear execution cache
* **[Get System Metrics](/api/vm-agent/get-system-metrics)** - View resource usage
# Get Environment Variables
Source: https://docs.hopx.ai/api/vm-agent/get-env
Get all global environment variables in the sandbox using the HopX VM Agent API. Retrieve environment variable values for configuration, debugging, or processing. Learn how to use GET /env endpoint to access all environment variables, handle sensitive values, and process environment data. Includes request examples and response formats.
Retrieve all global environment variables set in the sandbox. Sensitive values (containing KEY, SECRET, PASSWORD, TOKEN) are masked for security.
## Endpoint
```
GET /env
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
```
### Example Request
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/env \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Response
### Success (200 OK)
```json theme={null}
{
"env_vars": {
"PATH": "/usr/local/bin:/usr/bin:/bin",
"HOME": "/root",
"DATABASE_URL": "postgres://localhost/mydb",
"API_KEY": "***MASKED***",
"SECRET_TOKEN": "***MASKED***"
}
}
```
## Status Codes
| Code | Description |
| ---- | ------------ |
| 200 | Success |
| 401 | Unauthorized |
## Use Cases
### View All Variables
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/env \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | jq '.env_vars'
```
### Check Specific Variable
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/env \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | jq -r '.env_vars.DATABASE_URL'
```
## Related
* **SDK**: [sandbox.env.get()](/sdk/python/environment-variables#get) - Python SDK method
* [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI
## Next Steps
* **[Set Environment Variables](/api/vm-agent/set-env)** - Replace all variables
* **[Update Environment Variables](/api/vm-agent/update-env)** - Merge variables
# Get System Metrics
Source: https://docs.hopx.ai/api/vm-agent/get-system-metrics
Get current CPU, memory, and disk usage metrics for HopX sandboxes using the HopX VM Agent API. Monitor system resources in real-time, track performance metrics, and use data for optimization and troubleshooting. Learn how to use GET /system/metrics endpoint to retrieve comprehensive system information. Includes request examples and response formats.
Get current system metrics for the sandbox including CPU, memory, and disk usage.
## Endpoint
```
GET /system
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
```
### Example Request
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/system \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Response
### Success (200 OK)
```json theme={null}
{
"os": {
"name": "Ubuntu 22.04.5 LTS",
"version": "22.04.5 LTS (Jammy Jellyfish)",
"kernel": "5.10.186",
"arch": "amd64",
"hostname": "169.254.0.22",
"timezone": "Etc/UTC"
},
"hardware": {
"cpu_cores": 2,
"cpu_model": "AMD EPYC",
"memory_mb": 1995,
"disk_mb": 19987
},
"network": {
"interfaces": [
{
"name": "eth0",
"ip": "192.168.1.100",
"mac": "02:fc:00:00:00:1c"
}
],
"hostname": "169.254.0.22"
},
"environment": {
"shell": "",
"path": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"user": "",
"home": "",
"working_dir": "/",
"environment": {
"LANG": "C.UTF-8",
"TERM": "linux"
}
},
"capabilities": [
"Go",
"Git",
"Curl",
"Nano",
"Make",
"Wget",
"Vim",
"Bash",
"GCC",
"Pip",
"NPM",
"Python",
"Node.js"
]
}
```
### Response Fields
| Field | Type | Description |
| -------------------- | ------- | ---------------------------- |
| `os` | object | Operating system information |
| `os.name` | string | OS name and version |
| `os.kernel` | string | Kernel version |
| `os.arch` | string | System architecture |
| `hardware` | object | Hardware specifications |
| `hardware.cpu_cores` | integer | Number of CPU cores |
| `hardware.cpu_model` | string | CPU model |
| `hardware.memory_mb` | integer | Total memory in MB |
| `hardware.disk_mb` | integer | Total disk space in MB |
| `network` | object | Network configuration |
| `network.interfaces` | array | Network interfaces |
| `environment` | object | Environment configuration |
| `environment.path` | string | System PATH |
| `capabilities` | array | Installed software and tools |
## Status Codes
| Code | Description |
| ---- | ------------ |
| 200 | Success |
| 401 | Unauthorized |
## Use Cases
### Get System Information
```bash theme={null}
curl -s https://sandbox_abc123xyz.hopx.dev/system \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq '{os: .os.name, cpu_cores: .hardware.cpu_cores, memory_mb: .hardware.memory_mb}'
```
### Check Hardware Specs
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/system \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq '.hardware'
```
### List Installed Capabilities
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/system \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq '.capabilities[]'
```
### Check OS Version
```bash theme={null}
OS=$(curl -s https://sandbox_abc123xyz.hopx.dev/system \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | jq -r '.os.name')
echo "Operating System: $OS"
```
### Get Network Configuration
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/system \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq '.network.interfaces[]'
```
## Related
* **SDK**: [sandbox.get\_agent\_metrics()](/sdk/python/sandbox#get_agent_metrics) - Python SDK method
* [CLI System Commands](/cli/commands/system) - System operations from CLI
## Next Steps
* **[Get Cache Statistics](/api/vm-agent/get-cache-stats)** - View cache metrics
* **[List Processes](/api/vm-agent/list-system-processes)** - View running processes
# Kill Background Process
Source: https://docs.hopx.ai/api/vm-agent/kill-process
Terminate a running background code execution process in sandboxes using the HopX VM Agent API. Stop long-running or stuck processes to free resources and manage execution. Learn how to use DELETE /execute/kill endpoint to terminate processes by process ID. Includes request examples and process management.
Terminate a running background process. The process is killed immediately and cannot be restarted.
## Endpoint
```
DELETE /execute/kill
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
```
### Body Parameters
| Parameter | Type | Required | Description |
| ------------ | ------ | -------- | ------------------ |
| `process_id` | string | Yes | Process ID to kill |
### Example Request
```bash theme={null}
curl -X DELETE https://sandbox_abc123xyz.hopx.dev/execute/kill \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"process_id": "proc_abc123"
}'
```
## Response
### Success (200 OK)
```json theme={null}
{
"process_id": "proc_abc123",
"status": "killed",
"message": "Process terminated successfully"
}
```
### Response Fields
| Field | Type | Description |
| ------------ | ------ | -------------------------- |
| `process_id` | string | Process ID that was killed |
| `status` | string | New status (`killed`) |
| `message` | string | Confirmation message |
## Status Codes
| Code | Description |
| ---- | ------------------------------------- |
| 200 | Process killed successfully |
| 400 | Invalid request (missing process\_id) |
| 401 | Unauthorized |
| 404 | Process not found |
## Errors
### Process Not Found (404)
```json theme={null}
{
"error": "Process not found",
"code": "RESOURCE_NOT_FOUND"
}
```
**Cause:** The process ID doesn't exist or has already completed.
**Fix:** Verify the process ID using the List Processes endpoint.
## Use Cases
### Kill Long-Running Task
```bash theme={null}
# Start a long-running task
RESPONSE=$(curl -s -X POST https://sandbox_abc123xyz.hopx.dev/execute/background \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "import time\nfor i in range(3600):\n time.sleep(1)",
"language": "python"
}')
PROCESS_ID=$(echo "$RESPONSE" | jq -r '.process_id')
echo "Started process: $PROCESS_ID"
# ... later, kill it ...
curl -X DELETE https://sandbox_abc123xyz.hopx.dev/execute/kill \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"process_id\": \"$PROCESS_ID\"}"
```
### Kill All Running Processes
```bash theme={null}
#!/bin/bash
# Get all running processes
PROCESSES=$(curl -s https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq -r '.processes[] | select(.status == "running") | .process_id')
# Kill each one
for PROCESS_ID in $PROCESSES; do
curl -X DELETE https://sandbox_abc123xyz.hopx.dev/execute/kill \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"process_id\": \"$PROCESS_ID\"}"
echo "Killed $PROCESS_ID"
done
```
### Kill Process with Confirmation
```bash theme={null}
#!/bin/bash
PROCESS_ID="proc_abc123"
# Check if process exists
PROCESS=$(curl -s https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq ".processes[] | select(.process_id == \"$PROCESS_ID\")")
if [ -n "$PROCESS" ]; then
STATUS=$(echo "$PROCESS" | jq -r '.status')
NAME=$(echo "$PROCESS" | jq -r '.name')
echo "Found process: $NAME (status: $STATUS)"
echo "Killing..."
curl -X DELETE https://sandbox_abc123xyz.hopx.dev/execute/kill \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"process_id\": \"$PROCESS_ID\"}"
echo "Process killed"
else
echo "Process not found"
fi
```
### Timeout and Kill
```bash theme={null}
#!/bin/bash
PROCESS_ID="proc_abc123"
TIMEOUT=60 # seconds
START_TIME=$(date +%s)
while true; do
CURRENT_TIME=$(date +%s)
ELAPSED=$((CURRENT_TIME - START_TIME))
if [ $ELAPSED -gt $TIMEOUT ]; then
echo "Timeout reached, killing process"
curl -X DELETE https://sandbox_abc123xyz.hopx.dev/execute/kill \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"process_id\": \"$PROCESS_ID\"}"
break
fi
STATUS=$(curl -s https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq -r ".processes[] | select(.process_id == \"$PROCESS_ID\") | .status")
if [ "$STATUS" == "completed" ] || [ "$STATUS" == "failed" ]; then
echo "Process finished naturally"
break
fi
sleep 5
done
```
## Important Notes
Killing a process terminates it immediately without cleanup. Any unsaved data or partial results will be lost.
* **Immediate termination** - Process is killed without graceful shutdown
* **No recovery** - Killed processes cannot be restarted
* **Check status** - Use List Processes to verify the process was killed
## Related
* **SDK**: [sandbox.kill\_process()](/sdk/python/sandbox#kill_process) - Python SDK method
* [CLI System Commands](/cli/commands/system) - System operations from CLI
## Next Steps
* **[List Processes](/api/vm-agent/list-processes)** - View all background processes
* **[Background Execution](/api/vm-agent/execute-background)** - Start new background processes
* **[Execute Code](/api/vm-agent/execute)** - Synchronous code execution
# List Files
Source: https://docs.hopx.ai/api/vm-agent/list-files
List directory contents in the sandbox using the HopX VM Agent API. Browse filesystem structure, view file metadata including size and modification times, and navigate directories. Learn how to use GET /files/list endpoint to list files and directories with filtering options. Includes request examples and response formats.
List files and directories in a specified path. Returns metadata including size, permissions, and modification time.
## Endpoint
```
GET /files/list
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
```
### Query Parameters
| Parameter | Type | Required | Description |
| --------- | ------ | -------- | -------------------------------------- |
| `path` | string | No | Directory path (default: `/workspace`) |
### Example Request
```bash theme={null}
curl "https://sandbox_abc123xyz.hopx.dev/files/list?path=/workspace" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Response
### Success (200 OK)
```json theme={null}
{
"files": [
{
"name": "data.txt",
"path": "/workspace/data.txt",
"size": 1024,
"is_directory": false,
"permissions": "rw-r--r--",
"modified_time": "2025-01-28T00:00:00Z"
},
{
"name": "scripts",
"path": "/workspace/scripts",
"size": 4096,
"is_directory": true,
"permissions": "rwxr-xr-x",
"modified_time": "2025-01-28T00:00:00Z"
}
]
}
```
## Status Codes
| Code | Description |
| ---- | ------------------- |
| 200 | Success |
| 401 | Unauthorized |
| 404 | Directory not found |
## Use Cases
### Browse Workspace
```bash theme={null}
curl "https://sandbox_abc123xyz.hopx.dev/files/list?path=/workspace" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | jq '.files[] | {name, size, is_directory}'
```
### Find Large Files
```bash theme={null}
curl "https://sandbox_abc123xyz.hopx.dev/files/list?path=/workspace" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq '.files[] | select(.size > 1000000) | {name, size}'
```
### List Only Directories
```bash theme={null}
curl "https://sandbox_abc123xyz.hopx.dev/files/list?path=/workspace" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq '.files[] | select(.is_directory == true) | .name'
```
## Related
* **SDK**: [sandbox.files.list()](/sdk/python/files#list) - Python SDK method
* [CLI File Operations](/cli/commands/files) - File operations from CLI
## Next Steps
* **[Read File](/api/vm-agent/read-file)** - Read file contents
* **[File Exists](/api/vm-agent/file-exists)** - Check if file exists
# List Background Processes
Source: https://docs.hopx.ai/api/vm-agent/list-processes
List all background code execution processes in sandboxes and check their status using the HopX VM Agent API. Monitor running background processes, check execution status, and track process lifecycle. Learn how to use GET /processes endpoint to list processes, view status, and manage background executions. Includes request examples and response formats.
List all background execution processes started with the background execution endpoint. Check their status, output, and execution details.
## Endpoint
```
GET /execute/processes
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
```
### Example Request
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Response
### Success (200 OK)
```json theme={null}
{
"processes": [
{
"process_id": "proc_abc123",
"execution_id": "exec_xyz789",
"name": "data-processing",
"status": "running",
"language": "python",
"started_at": "2025-01-28T00:00:00Z",
"completed_at": null,
"stdout": "Processing step 1/10\nProcessing step 2/10\n",
"stderr": "",
"exit_code": null,
"execution_time": 15.5
},
{
"process_id": "proc_def456",
"execution_id": "exec_uvw012",
"name": "model-training",
"status": "completed",
"language": "python",
"started_at": "2025-01-27T23:00:00Z",
"completed_at": "2025-01-27T23:30:00Z",
"stdout": "Training complete! Accuracy: 0.95\n",
"stderr": "",
"exit_code": 0,
"execution_time": 1800.3
}
],
"count": 2
}
```
### Response Fields
| Field | Type | Description |
| ----------- | ------- | ------------------------- |
| `processes` | array | Array of process objects |
| `count` | integer | Total number of processes |
### Process Object
| Field | Type | Description |
| ---------------- | ------- | -------------------------------------------------- |
| `process_id` | string | Process ID |
| `execution_id` | string | Execution ID |
| `name` | string | Process name (if provided) |
| `status` | string | Status: `queued`, `running`, `completed`, `failed` |
| `language` | string | Programming language |
| `started_at` | string | ISO 8601 start timestamp |
| `completed_at` | string | ISO 8601 completion timestamp (if complete) |
| `stdout` | string | Standard output |
| `stderr` | string | Standard error |
| `exit_code` | integer | Exit code (null if still running) |
| `execution_time` | number | Execution time in seconds |
## Status Codes
| Code | Description |
| ---- | ------------ |
| 200 | Success |
| 401 | Unauthorized |
## Process Statuses
| Status | Description |
| ----------- | ------------------------------- |
| `queued` | Process is queued for execution |
| `running` | Process is currently running |
| `completed` | Process completed successfully |
| `failed` | Process failed with error |
## Use Cases
### Monitor All Processes
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | jq '.'
```
### Check Specific Process
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq '.processes[] | select(.process_id == "proc_abc123")'
```
### Filter Running Processes
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq '.processes[] | select(.status == "running")'
```
### Get Process Output
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq -r '.processes[] | select(.process_id == "proc_abc123") | .stdout'
```
### Wait for Completion
```bash theme={null}
#!/bin/bash
PROCESS_ID="proc_abc123"
while true; do
RESPONSE=$(curl -s https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN")
PROCESS=$(echo "$RESPONSE" | jq ".processes[] | select(.process_id == \"$PROCESS_ID\")")
STATUS=$(echo "$PROCESS" | jq -r '.status')
echo "Status: $STATUS"
if [ "$STATUS" == "completed" ]; then
echo "Output:"
echo "$PROCESS" | jq -r '.stdout'
break
elif [ "$STATUS" == "failed" ]; then
echo "Error:"
echo "$PROCESS" | jq -r '.stderr'
break
fi
sleep 5
done
```
### List Completed Processes
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq '.processes[] | select(.status == "completed") | {name, execution_time, exit_code}'
```
### Count Processes by Status
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq '[.processes | group_by(.status) | .[] | {status: .[0].status, count: length}]'
```
## Related
* **SDK**: [sandbox.list\_processes()](/sdk/python/sandbox#list_processes) - Python SDK method
* [CLI System Commands](/cli/commands/system) - System operations from CLI
## Next Steps
* **[Background Execution](/api/vm-agent/execute-background)** - Start background processes
* **[Kill Process](/api/vm-agent/kill-process)** - Terminate a running process
* **[Async Execution](/api/vm-agent/execute-async)** - Execute with webhook callbacks
# List System Processes
Source: https://docs.hopx.ai/api/vm-agent/list-system-processes
List all running system processes in the sandbox using the HopX VM Agent API. View all system processes including background executions, system services, and user processes. Learn how to use GET /processes/system endpoint to monitor system activity and debug process issues. Includes request examples and process information.
List all running system processes in the sandbox with PID, command, and user information.
## Endpoint
```
GET /processes
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
```
### Example Request
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Response
### Success (200 OK)
```json theme={null}
{
"processes": [
{
"pid": 1,
"command": "/usr/bin/python3 /app/agent.py",
"user": "root"
},
{
"pid": 123,
"command": "python -m http.server 8000",
"user": "user"
}
],
"count": 2
}
```
## Status Codes
| Code | Description |
| ---- | ------------ |
| 200 | Success |
| 401 | Unauthorized |
## Use Cases
### Find Specific Process
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq '.processes[] | select(.command | contains("python"))'
```
### Count Processes
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | jq '.count'
```
## Related
* **[Process Monitoring](/core-concepts/observability/processes)** - Learn about process monitoring
* **[List Background Processes](/api/vm-agent/list-processes)** - View background execution processes
* **[Get System Metrics](/api/vm-agent/get-system-metrics)** - View resource usage
* **SDK**: [sandbox.list\_system\_processes()](/sdk/python/sandbox#list_system_processes) - Python SDK method
* [CLI System Commands](/cli/commands/system) - System operations from CLI
## Next Steps
* **[Get System Metrics](/api/vm-agent/get-system-metrics)** - View resource usage
* **[List Background Processes](/api/vm-agent/list-processes)** - View background execution processes
# Create Directory in Sandbox
Source: https://docs.hopx.ai/api/vm-agent/mkdir
Create a directory in the sandbox using the HopX VM Agent API. Create new directories or directory structures for organizing files and managing filesystem hierarchy. Learn how to use POST /files/mkdir endpoint to create directories with parent directory creation. Includes request examples and directory management.
Create a directory in the sandbox. Parent directories are created automatically if needed.
## Endpoint
```
POST /files/mkdir
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
```
### Body Parameters
| Parameter | Type | Required | Description |
| --------- | ------ | -------- | ------------------------ |
| `path` | string | Yes | Directory path to create |
### Example Request
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/files/mkdir \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"path": "/workspace/project/src"
}'
```
## Response
### Success (200 OK)
```json theme={null}
{
"path": "/workspace/project/src",
"message": "Directory created successfully"
}
```
## Status Codes
| Code | Description |
| ---- | ----------------- |
| 200 | Directory created |
| 401 | Unauthorized |
| 403 | Path not allowed |
## Use Cases
### Setup Project Structure
```bash theme={null}
for DIR in "src" "tests" "docs" "data"; do
curl -X POST https://sandbox_abc123xyz.hopx.dev/files/mkdir \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d "{\"path\": \"/workspace/project/$DIR\"}"
done
```
## Related
* **SDK**: [sandbox.files.mkdir()](/sdk/python/files#mkdir) - Python SDK method
* [CLI Reference](/cli/introduction) - Command-line interface
## Next Steps
* **[Write File](/api/vm-agent/write-file)** - Create files in directory
* **[List Files](/api/vm-agent/list-files)** - Verify directory created
# Overview
Source: https://docs.hopx.ai/api/vm-agent/overview
Execute code, manage files, and control sandbox resources with the HopX VM Agent API. Run code in multiple languages, perform file operations, execute shell commands, manage environment variables, and automate desktop interactions. Complete reference for all VM Agent API endpoints with authentication and examples.
The VM Agent API runs inside each sandbox and provides endpoints for code execution, file operations, command execution, desktop automation, and observability. Each sandbox has its own VM Agent API instance.
## Base URL
Each sandbox has a unique VM Agent API URL:
```
https://{sandbox_id}.hopx.dev
```
For example:
```
https://sandbox_abc123xyz.hopx.dev
```
The base URL is returned in the `public_host` or `direct_url` field when you create a sandbox.
## Authentication
All VM Agent API requests require a JWT token. This token is automatically generated when you create a sandbox:
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "print(\"Hello World\")",
"language": "python"
}'
```
The JWT token:
* Is returned in the `auth_token` field when creating a sandbox
* Expires after a set time (check `token_expires_at`)
* Can be refreshed using the Control Plane API
## What You Can Do
### Code Execution
* **Synchronous execution** - Execute code and wait for results
* **Rich output capture** - Capture matplotlib plots, pandas DataFrames, and visualizations
* **Background execution** - Run long-running tasks asynchronously
* **Async execution** - Execute code with webhook callbacks
* **Process management** - List and kill running processes
### Command Execution
* **Run commands** - Execute shell commands synchronously
* **Background commands** - Run long-running commands asynchronously
### File Operations
* **Read/write files** - Manage files in the sandbox
* **List directories** - Browse filesystem
* **Upload/download** - Transfer files to/from sandbox
* **File watching** - Monitor file changes
### Environment Variables
* **Get/set variables** - Manage environment variables
* **Update variables** - Merge or replace variables
* **Clear variables** - Remove all variables
### Desktop Automation
* **VNC access** - Remote desktop via VNC
* **Mouse/keyboard control** - Automate user interactions
* **Screenshots** - Capture screen images
* **Screen recording** - Record desktop sessions
* **Window management** - Control application windows
### Observability
* **Metrics** - CPU, memory, disk usage
* **Processes** - System and background processes
* **Cache** - Execution result cache statistics
* **Terminal** - Interactive terminal via WebSocket
## API Endpoints
### Code Execution
| Endpoint | Method | Description |
| --------------------- | ------ | -------------------------------- |
| `/execute` | POST | Execute code synchronously |
| `/execute/rich` | POST | Execute with rich output capture |
| `/execute/background` | POST | Execute in background |
| `/execute/async` | POST | Execute with webhook callback |
| `/execute/processes` | GET | List background processes |
| `/execute/kill` | DELETE | Kill a background process |
### Commands
| Endpoint | Method | Description |
| ---------------------- | ------ | ------------------------- |
| `/commands/run` | POST | Run shell command |
| `/commands/background` | POST | Run command in background |
### Files
| Endpoint | Method | Description |
| --------------- | ------ | ------------------------ |
| `/files/read` | GET | Read file contents |
| `/files/write` | POST | Write file contents |
| `/files/list` | GET | List directory contents |
| `/files/exists` | GET | Check if file exists |
| `/files/remove` | DELETE | Delete file or directory |
| `/files/mkdir` | POST | Create directory |
### Environment
| Endpoint | Method | Description |
| -------- | ------ | --------------------------------- |
| `/env` | GET | Get all environment variables |
| `/env` | PUT | Replace all environment variables |
| `/env` | PATCH | Update environment variables |
| `/env` | DELETE | Clear all environment variables |
### Desktop
| Endpoint | Method | Description |
| --------------------- | -------- | --------------------- |
| `/desktop/vnc` | POST | Start/stop VNC server |
| `/desktop/mouse` | POST | Control mouse |
| `/desktop/keyboard` | POST | Control keyboard |
| `/desktop/clipboard` | GET/POST | Manage clipboard |
| `/desktop/screenshot` | POST | Take screenshot |
| `/desktop/recording` | POST | Start/stop recording |
| `/desktop/windows` | GET | List windows |
| `/desktop/display` | GET/POST | Manage display |
### Observability
| Endpoint | Method | Description |
| -------------- | --------- | --------------------- |
| `/system` | GET | Get system metrics |
| `/processes` | GET | List system processes |
| `/cache` | GET | Get cache statistics |
| `/cache/clear` | POST | Clear cache |
| `/terminal` | WebSocket | Interactive terminal |
## Response Format
All responses use JSON:
### Success Response
```json theme={null}
{
"success": true,
"stdout": "Hello World\n",
"stderr": "",
"exit_code": 0
}
```
### Error Response
```json theme={null}
{
"error": "Error message",
"code": "ERROR_CODE"
}
```
## Status Codes
| Code | Description |
| ---- | -------------------------- |
| 200 | Success |
| 400 | Bad Request |
| 401 | Unauthorized (invalid JWT) |
| 404 | Not Found |
| 500 | Internal Server Error |
## Supported Languages
The VM Agent supports multiple programming languages:
* **Python** - Python 3.x with common packages
* **JavaScript** - Node.js runtime
* **Bash** - Shell scripting
* **Go** - Go runtime (if available in template)
## Related
* **[SDK: File Operations](/sdk/python/files)** - Python SDK file operations
* **[SDK: Code Execution](/sdk/python/sandbox#run_code)** - Python SDK code execution
* **[SDK: Commands](/sdk/python/commands)** - Python SDK command execution
* **[Code Execution Concepts](/core-concepts/code-execution/synchronous)** - Learn about code execution
* [CLI Reference](/cli/introduction) - Command-line interface
## Next Steps
* **[Execute Code](/api/vm-agent/execute)** - Run code synchronously
* **[Rich Output](/api/vm-agent/execute-rich)** - Capture plots and visualizations
* **[Background Execution](/api/vm-agent/execute-background)** - Run long-running tasks
* **[File Operations](/api/vm-agent/read-file)** - Manage files in sandbox
# Read File from Sandbox
Source: https://docs.hopx.ai/api/vm-agent/read-file
Read file contents from the sandbox as text using the HopX VM Agent API. Learn how to use GET /files/read endpoint to retrieve file contents, handle text and binary files, manage encoding, and process file data. Includes request examples and response formats.
Read file contents from the sandbox. Only allowed paths like `/workspace` and `/tmp` can be read.
## Endpoint
```
GET /files/read
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
```
### Query Parameters
| Parameter | Type | Required | Description |
| --------- | ------ | -------- | --------------------------------------- |
| `path` | string | Yes | File path (e.g., `/workspace/data.txt`) |
### Example Request
```bash theme={null}
curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/data.txt" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Response
### Success (200 OK)
```json theme={null}
{
"content": "Hello World\nLine 2\nLine 3\n",
"path": "/workspace/data.txt",
"size": 30
}
```
### Response Fields
| Field | Type | Description |
| --------- | ------- | --------------------- |
| `content` | string | File contents as text |
| `path` | string | File path |
| `size` | integer | File size in bytes |
## Status Codes
| Code | Description |
| ---- | ---------------------------------------------- |
| 200 | Success |
| 401 | Unauthorized |
| 403 | Path not allowed (outside allowed directories) |
| 404 | File not found |
## Errors
### File Not Found (404)
```json theme={null}
{
"error": "File not found: /workspace/nonexistent.txt",
"code": "FILE_NOT_FOUND"
}
```
**Cause:** The file doesn't exist.
**Fix:** Verify the file path and ensure the file exists.
### Path Not Allowed (403)
```json theme={null}
{
"error": "Path not allowed: /etc/passwd",
"code": "FORBIDDEN"
}
```
**Cause:** The path is outside allowed directories.
**Fix:** Only read files from `/workspace`, `/tmp`, or other explicitly allowed paths.
## Allowed Paths
You can read files from:
* `/workspace/*` - Main working directory
* `/tmp/*` - Temporary files
* Other paths may be allowed depending on sandbox configuration
## Use Cases
### Read Configuration File
```bash theme={null}
curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/config.json" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | jq '.content | fromjson'
```
### Read Log File
```bash theme={null}
curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/app.log" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | jq -r '.content'
```
### Read CSV Data
```bash theme={null}
curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/data.csv" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | jq -r '.content' | head -10
```
### Check File Size
```bash theme={null}
curl "https://sandbox_abc123xyz.hopx.dev/files/read?path=/workspace/large_file.txt" \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | jq '.size'
```
### Read and Process
```python theme={null}
import requests
import json
url = "https://sandbox_abc123xyz.hopx.dev/files/read"
headers = {"Authorization": "Bearer YOUR_JWT_TOKEN"}
params = {"path": "/workspace/results.json"}
response = requests.get(url, headers=headers, params=params)
data = response.json()
# Parse JSON content
file_content = json.loads(data["content"])
print(f"Read {data['size']} bytes from {data['path']}")
print(f"Data: {file_content}")
```
## Related
* **SDK**: [sandbox.files.read()](/sdk/python/files#read) - Python SDK method
* [CLI File Operations](/cli/commands/files) - File operations from CLI
## Next Steps
* **[Write File](/api/vm-agent/write-file)** - Write file contents
* **[List Files](/api/vm-agent/list-files)** - List directory contents
* **[File Exists](/api/vm-agent/file-exists)** - Check if file exists
# Remove File
Source: https://docs.hopx.ai/api/vm-agent/remove-file
Delete a file or directory from the sandbox using the HopX VM Agent API. Remove files or directories to clean up sandbox filesystem, free disk space, and manage storage. Learn how to use DELETE /files/remove endpoint to delete files or directories recursively. Includes request examples and cleanup best practices.
Delete a file or directory. Directories are removed recursively.
## Endpoint
```
DELETE /files/remove
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
```
### Query Parameters
| Parameter | Type | Required | Description |
| --------- | ------ | -------- | -------------- |
| `path` | string | Yes | Path to delete |
### Example Request
```bash theme={null}
curl -X DELETE "https://sandbox_abc123xyz.hopx.dev/files/remove?path=/workspace/old_data.txt" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Response
### Success (200 OK)
```json theme={null}
{
"message": "File deleted successfully",
"path": "/workspace/old_data.txt"
}
```
## Status Codes
| Code | Description |
| ---- | -------------- |
| 200 | Deleted |
| 401 | Unauthorized |
| 404 | File not found |
## Use Cases
### Cleanup Old Files
```bash theme={null}
curl -X DELETE "https://sandbox_abc123xyz.hopx.dev/files/remove?path=/workspace/temp.txt" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
### Remove Directory
```bash theme={null}
curl -X DELETE "https://sandbox_abc123xyz.hopx.dev/files/remove?path=/workspace/old_project" \
-H "Authorization: Bearer YOUR_JWT_TOKEN"
```
## Related
* **SDK**: [sandbox.files.remove()](/sdk/python/files#remove) - Python SDK method
* [CLI File Operations](/cli/commands/files) - File operations from CLI
## Next Steps
* **[List Files](/api/vm-agent/list-files)** - Browse files
* **[Write File](/api/vm-agent/write-file)** - Create new files
# Run Command
Source: https://docs.hopx.ai/api/vm-agent/run-command
Execute shell commands synchronously in the sandbox using the HopX VM Agent API. Run shell commands for system administration, package installation, and automation tasks. Learn how to use POST /commands/run endpoint to execute commands, capture output, and handle errors. Includes request examples and command execution best practices.
Execute shell commands in the sandbox and wait for completion. Commands run in `/bin/sh -c` and return stdout, stderr, and exit code.
## Endpoint
```
POST /commands/run
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
```
### Body Parameters
| Parameter | Type | Required | Description |
| ------------- | ------- | -------- | ------------------------------------------- |
| `command` | string | Yes | Shell command to execute |
| `timeout` | integer | No | Command timeout in seconds (default: 30) |
| `working_dir` | string | No | Working directory (default: `/workspace`) |
| `env` | object | No | Environment variables for this command only |
### Example Request
Run a simple command:
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"command": "ls -la /workspace"
}'
```
Run with custom environment:
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"command": "echo $MY_VAR",
"env": {
"MY_VAR": "hello"
}
}'
```
## Response
### Success (200 OK)
```json theme={null}
{
"stdout": "total 8\ndrwxr-xr-x 2 user user 4096 Jan 28 00:00 .\ndrwxr-xr-x 3 user user 4096 Jan 28 00:00 ..\n",
"stderr": "",
"exit_code": 0
}
```
### Response Fields
| Field | Type | Description |
| ----------- | ------- | ----------------------- |
| `stdout` | string | Standard output |
| `stderr` | string | Standard error |
| `exit_code` | integer | Exit code (0 = success) |
## Status Codes
| Code | Description |
| ---- | --------------------------------- |
| 200 | Command completed |
| 400 | Invalid request (missing command) |
| 401 | Unauthorized |
| 408 | Command timeout |
| 500 | Command failed |
## Errors
### Command Failed (500)
```json theme={null}
{
"stdout": "",
"stderr": "ls: cannot access '/nonexistent': No such file or directory\n",
"exit_code": 2
}
```
**Cause:** Command execution failed.
**Fix:** Check the `stderr` field for error details and verify the command.
## Use Cases
### Install Packages
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"command": "pip install requests numpy",
"timeout": 120
}'
```
### Check System Information
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"command": "uname -a && df -h && free -h"
}'
```
### File Operations
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"command": "cat /workspace/data.txt | wc -l",
"working_dir": "/workspace"
}'
```
### Git Operations
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"command": "git clone https://github.com/user/repo.git && cd repo && git log -1",
"working_dir": "/workspace",
"timeout": 60
}'
```
### Build and Test
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"command": "npm install && npm test",
"working_dir": "/workspace/project",
"timeout": 300
}'
```
### Pipeline Multiple Commands
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/run \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"command": "mkdir -p /workspace/output && python process.py && mv result.csv /workspace/output/",
"working_dir": "/workspace"
}'
```
## Related
* **SDK**: [sandbox.commands.run()](/sdk/python/commands#run) - Python SDK method
* [CLI Commands](/cli/commands/cmd) - Shell commands from CLI
## Next Steps
* **[Run Command in Background](/api/vm-agent/run-command-background)** - Run long-running commands
* **[Execute Code](/api/vm-agent/execute)** - Execute code directly
* **[File Operations](/api/vm-agent/read-file)** - Read and write files
# Run Command in Background
Source: https://docs.hopx.ai/api/vm-agent/run-command-background
Execute shell commands in the background and return immediately using the HopX VM Agent API. Run long-running shell commands without blocking, monitor process status, and retrieve results when complete. Learn how to use POST /commands/background endpoint for asynchronous command execution. Includes request examples and process management.
Execute shell commands in the background and return immediately with a process ID. Perfect for long-running commands like servers, monitoring, or batch jobs.
## Endpoint
```
POST /commands/background
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
```
### Body Parameters
| Parameter | Type | Required | Description |
| ------------- | ------- | -------- | -------------------------------------------- |
| `command` | string | Yes | Shell command to execute |
| `timeout` | integer | No | Max execution time in seconds (default: 300) |
| `working_dir` | string | No | Working directory |
| `env` | object | No | Environment variables |
| `name` | string | No | Process name for identification |
### Example Request
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/background \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"command": "python -m http.server 8000",
"working_dir": "/workspace",
"name": "web-server"
}'
```
## Response
### Success (200 OK)
```json theme={null}
{
"process_id": "proc_abc123",
"execution_id": "exec_xyz789",
"status": "running"
}
```
### Response Fields
| Field | Type | Description |
| -------------- | ------ | ---------------------------------------- |
| `process_id` | string | Process ID (use to check status or kill) |
| `execution_id` | string | Execution ID |
| `status` | string | Initial status (`queued` or `running`) |
## Status Codes
| Code | Description |
| ---- | ----------------------- |
| 200 | Command started |
| 400 | Invalid request |
| 401 | Unauthorized |
| 500 | Failed to start command |
## Use Cases
### Start Web Server
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/background \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"command": "python -m http.server 8080",
"working_dir": "/workspace",
"env": {
"PORT": "8080"
},
"name": "http-server"
}'
```
### Run Long Processing Job
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/background \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"command": "for i in {1..3600}; do echo \"Processing batch $i\"; sleep 1; done > /workspace/log.txt",
"timeout": 7200,
"name": "batch-processing"
}'
```
### Monitor Files
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/background \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"command": "tail -f /workspace/application.log",
"name": "log-monitor"
}'
```
### Start Development Server
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/commands/background \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"command": "npm run dev",
"working_dir": "/workspace/myapp",
"env": {
"NODE_ENV": "development",
"PORT": "3000"
},
"name": "dev-server"
}'
```
## Check Process Status
Use the List Processes endpoint:
```bash theme={null}
curl https://sandbox_abc123xyz.hopx.dev/execute/processes \
-H "Authorization: Bearer YOUR_JWT_TOKEN" | \
jq '.processes[] | select(.process_id == "proc_abc123")'
```
## Kill Background Command
Use the Kill Process endpoint:
```bash theme={null}
curl -X DELETE https://sandbox_abc123xyz.hopx.dev/execute/kill \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"process_id": "proc_abc123"
}'
```
## Related
* **SDK**: [sandbox.commands.run\_background()](/sdk/python/commands#run_background) - Python SDK method
* [CLI Commands](/cli/commands/cmd) - Shell commands from CLI
## Next Steps
* **[Run Command](/api/vm-agent/run-command)** - Execute commands synchronously
* **[List Processes](/api/vm-agent/list-processes)** - Check background process status
* **[Kill Process](/api/vm-agent/kill-process)** - Terminate a background process
# Set Environment Variables
Source: https://docs.hopx.ai/api/vm-agent/set-env
Replace all global environment variables in the sandbox using the HopX VM Agent API. Set or replace environment variables for code execution configuration. Learn how to use PUT /env endpoint to set all variables at once, handle variable values, and manage environment configuration. Includes request examples and response formats.
Replace all global environment variables in the sandbox. This operation clears existing variables and sets new ones.
This replaces ALL environment variables. Use PATCH `/env` to merge variables instead.
## Endpoint
```
PUT /env
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
```
### Body Parameters
| Parameter | Type | Required | Description |
| ---------- | ------ | -------- | ----------------------------------- |
| `env_vars` | object | Yes | Dictionary of environment variables |
### Example Request
```bash theme={null}
curl -X PUT https://sandbox_abc123xyz.hopx.dev/env \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"env_vars": {
"DATABASE_URL": "postgres://localhost/prod",
"API_KEY": "sk-prod-123",
"DEBUG": "false"
}
}'
```
## Response
### Success (204 No Content)
Empty response on success.
## Status Codes
| Code | Description |
| ---- | -------------------------- |
| 204 | Variables set successfully |
| 400 | Invalid request |
| 401 | Unauthorized |
## Use Cases
### Reset Variables
```bash theme={null}
curl -X PUT https://sandbox_abc123xyz.hopx.dev/env \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"env_vars": {
"ENVIRONMENT": "production",
"LOG_LEVEL": "info"
}
}'
```
## Related
* **SDK**: [sandbox.env.set()](/sdk/python/environment-variables#set) - Python SDK method
* [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI
## Next Steps
* **[Get Environment Variables](/api/vm-agent/get-env)** - View all variables
* **[Update Environment Variables](/api/vm-agent/update-env)** - Merge variables
* **[Clear Environment Variables](/api/vm-agent/clear-env)** - Remove all variables
# Update Environment Variables
Source: https://docs.hopx.ai/api/vm-agent/update-env
Update or add sandbox environment variables without removing existing ones using the HopX VM Agent API. Merge new variables with existing ones, update specific variables, and manage environment configuration incrementally. Learn how to use PATCH /env endpoint to update variables without clearing others. Includes request examples and merge behavior.
Update or add environment variables. Merges with existing variables - only specified variables are updated, others are preserved.
## Endpoint
```
PATCH /env
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
```
### Body Parameters
| Parameter | Type | Required | Description |
| ---------- | ------- | -------- | ------------------------------------- |
| `env_vars` | object | Yes | Dictionary of variables to update/add |
| `merge` | boolean | Yes | Must be `true` for merge behavior |
### Example Request
```bash theme={null}
curl -X PATCH https://sandbox_abc123xyz.hopx.dev/env \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"env_vars": {
"DEBUG": "true",
"NEW_VAR": "value"
},
"merge": true
}'
```
## Response
### Success (204 No Content)
Empty response on success.
## Status Codes
| Code | Description |
| ---- | ------------------------------ |
| 204 | Variables updated successfully |
| 400 | Invalid request |
| 401 | Unauthorized |
## Use Cases
### Add New Variables
```bash theme={null}
curl -X PATCH https://sandbox_abc123xyz.hopx.dev/env \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"env_vars": {
"FEATURE_FLAG": "enabled"
},
"merge": true
}'
```
## Related
* **SDK**: [sandbox.env.update()](/sdk/python/environment-variables#update) - Python SDK method
* [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI
## Next Steps
* **[Get Environment Variables](/api/vm-agent/get-env)** - View all variables
* **[Set Environment Variables](/api/vm-agent/set-env)** - Replace all variables
# Write File
Source: https://docs.hopx.ai/api/vm-agent/write-file
Write content to a file in the sandbox using the HopX VM Agent API. Create new files or overwrite existing files with text or binary content. Learn how to use POST /files/write endpoint with encoding options, file permissions, and error handling. Includes request examples and response formats.
Write content to a file in the sandbox. Creates the file if it doesn't exist, or overwrites if it does. Only allowed paths can be written.
## Endpoint
```
POST /files/write
```
## Request
### Headers
```
Authorization: Bearer YOUR_JWT_TOKEN
Content-Type: application/json
```
### Body Parameters
| Parameter | Type | Required | Description |
| --------- | ------ | -------- | --------------------- |
| `path` | string | Yes | Destination file path |
| `content` | string | Yes | File content to write |
### Example Request
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/files/write \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"path": "/workspace/data.txt",
"content": "Hello World\nLine 2\nLine 3"
}'
```
Write JSON file:
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/files/write \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"path": "/workspace/config.json",
"content": "{\"api_key\": \"test\", \"timeout\": 30}"
}'
```
## Response
### Success (200 OK)
```json theme={null}
{
"path": "/workspace/data.txt",
"size": 30,
"message": "File written successfully"
}
```
### Response Fields
| Field | Type | Description |
| --------- | ------- | -------------------- |
| `path` | string | File path |
| `size` | integer | File size in bytes |
| `message` | string | Confirmation message |
## Status Codes
| Code | Description |
| ---- | ----------------------------------------- |
| 200 | File written successfully |
| 400 | Invalid request (missing path or content) |
| 401 | Unauthorized |
| 403 | Path not allowed |
| 500 | Write failed |
## Errors
### Path Not Allowed (403)
```json theme={null}
{
"error": "Path not allowed: /etc/config",
"code": "FORBIDDEN"
}
```
**Cause:** The path is outside allowed directories.
**Fix:** Only write files to `/workspace`, `/tmp`, or other explicitly allowed paths.
## Use Cases
### Write Configuration
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/files/write \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"path": "/workspace/app_config.json",
"content": "{\"database\": \"postgres://localhost/mydb\", \"port\": 5000}"
}'
```
### Write Python Script
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/files/write \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"path": "/workspace/script.py",
"content": "import pandas as pd\n\ndf = pd.DataFrame({\"a\": [1,2,3]})\nprint(df)\n"
}'
```
### Write CSV Data
```bash theme={null}
curl -X POST https://sandbox_abc123xyz.hopx.dev/files/write \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"path": "/workspace/data.csv",
"content": "Name,Age,City\nAlice,25,NYC\nBob,30,LA\nCharlie,35,SF\n"
}'
```
### Write and Execute
```bash theme={null}
#!/bin/bash
# Write script
curl -X POST https://sandbox_abc123xyz.hopx.dev/files/write \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"path": "/workspace/hello.py",
"content": "print(\"Hello from HopX!\")"
}'
# Execute it
curl -X POST https://sandbox_abc123xyz.hopx.dev/execute \
-H "Authorization: Bearer YOUR_JWT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"code": "exec(open(\"/workspace/hello.py\").read())",
"language": "python"
}'
```
### Write from Python
```python theme={null}
import requests
import json
url = "https://sandbox_abc123xyz.hopx.dev/files/write"
headers = {"Authorization": "Bearer YOUR_JWT_TOKEN"}
# Prepare data
data = {
"users": [
{"name": "Alice", "age": 25},
{"name": "Bob", "age": 30}
]
}
payload = {
"path": "/workspace/users.json",
"content": json.dumps(data, indent=2)
}
response = requests.post(url, headers=headers, json=payload)
print(f"Wrote {response.json()['size']} bytes")
```
## Related
* **SDK**: [sandbox.files.write()](/sdk/python/files#write) - Python SDK method
* [CLI File Operations](/cli/commands/files) - File operations from CLI
## Next Steps
* **[Read File](/api/vm-agent/read-file)** - Read file contents
* **[List Files](/api/vm-agent/list-files)** - List directory contents
* **[Remove File](/api/vm-agent/remove-file)** - Delete files
# Authentication
Source: https://docs.hopx.ai/cli/commands/auth
Complete reference for HopX CLI authentication commands - login, logout, status, validate, and API key management. Includes OAuth login, API key creation, and authentication verification.
Manage authentication for the HopX CLI using the `auth` command. Authenticate via OAuth, manage API keys, and verify authentication status.
## Command Syntax
```bash theme={null}
hopx auth [options]
```
## Subcommands
### `login`
Authenticate with HopX via browser OAuth.
**Syntax:**
```bash theme={null}
hopx auth login [OPTIONS]
```
**Options:**
* `--provider TEXT` - OAuth provider: `GoogleOAuth`, `GitHubOAuth` (default: `GoogleOAuth`)
* `--no-browser` - Headless mode: manually paste callback URL (for servers without browsers)
**Examples:**
```bash theme={null}
# OAuth login with Google (default)
hopx auth login
# OAuth login with GitHub
hopx auth login --provider GitHubOAuth
# Headless mode (for servers/containers without browsers)
hopx auth login --no-browser
```
**Expected Output:**
```
✓ Authentication successful
✓ You can now create API keys with 'hopx auth keys create'
```
**Exit Codes:**
* `0` - Success
* `1` - Authentication failed
* `5` - Timeout
### `logout`
Log out and clear stored credentials.
**Syntax:**
```bash theme={null}
hopx auth logout [OPTIONS]
```
**Examples:**
```bash theme={null}
# Log out
hopx auth logout
```
**Expected Output:**
```
✓ Logged out successfully
```
**Exit Codes:**
* `0` - Success
### `status`
Check authentication status.
**Syntax:**
```bash theme={null}
hopx auth status [OPTIONS]
```
**Examples:**
```bash theme={null}
# Check authentication status
hopx auth status
```
**Expected Output:**
```
✓ Authenticated
✓ API key: hopx_live_... (configured)
```
**Exit Codes:**
* `0` - Authenticated
* `3` - Not authenticated
### `validate`
Validate current API key.
**Syntax:**
```bash theme={null}
hopx auth validate [OPTIONS]
```
**Examples:**
```bash theme={null}
# Validate API key
hopx auth validate
```
**Expected Output:**
```
✓ API key is valid
```
**Exit Codes:**
* `0` - Valid
* `3` - Invalid or missing
### `refresh`
Refresh OAuth token.
**Syntax:**
```bash theme={null}
hopx auth refresh [OPTIONS]
```
**Examples:**
```bash theme={null}
# Refresh OAuth token
hopx auth refresh
```
**Expected Output:**
```
✓ Token refreshed successfully
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `keys`
Manage API keys.
#### `keys list`
List all API keys.
**Syntax:**
```bash theme={null}
hopx auth keys list [OPTIONS]
```
**Examples:**
```bash theme={null}
# List API keys
hopx auth keys list
```
**Expected Output:**
```
┌──────────────┬─────────────────────┬──────────────┐
│ Name │ Created │ Last Used │
├──────────────┼─────────────────────┼──────────────┤
│ my-key │ 2025-01-27 10:00:00 │ 2025-01-27 │
│ production │ 2025-01-26 09:00:00 │ 2025-01-27 │
└──────────────┴─────────────────────┴──────────────┘
```
#### `keys create`
Create a new API key.
**Syntax:**
```bash theme={null}
hopx auth keys create [OPTIONS]
```
**Options:**
* `--name TEXT` - API key name (auto-generated if not provided)
**Examples:**
```bash theme={null}
# Create API key with name
hopx auth keys create --name "my-key"
# Create with auto-generated name
hopx auth keys create
```
**Expected Output:**
```
✓ API key created: hopx_live_...
✓ Key stored securely
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
#### `keys revoke`
Revoke an API key.
**Syntax:**
```bash theme={null}
hopx auth keys revoke KEY_ID [OPTIONS]
```
**Arguments:**
* `KEY_ID` - API key ID to revoke (required)
**Examples:**
```bash theme={null}
# Revoke API key
hopx auth keys revoke key_abc123
```
**Expected Output:**
```
✓ API key revoked: key_abc123
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Key not found
#### `keys info`
Get information about an API key.
**Syntax:**
```bash theme={null}
hopx auth keys info KEY_ID [OPTIONS]
```
**Arguments:**
* `KEY_ID` - API key ID (required)
**Examples:**
```bash theme={null}
# Get API key info
hopx auth keys info key_abc123
```
**Expected Output:**
```
┌─────────────┬─────────────────────────────────────┐
│ Property │ Value │
├─────────────┼─────────────────────────────────────┤
│ Name │ my-key │
│ Created │ 2025-01-27 10:00:00 │
│ Last Used │ 2025-01-27 12:00:00 │
└─────────────┴─────────────────────────────────────┘
```
## Authentication Methods
### Method 1: OAuth Login (Recommended)
```bash theme={null}
# Login with browser
hopx auth login
# Create API key
hopx auth keys create --name "my-key"
```
### Method 2: Environment Variable
```bash theme={null}
# Set API key
export HOPX_API_KEY="hopx_live_..."
# Verify
hopx auth status
```
### Method 3: Config File
API keys are automatically stored in `~/.hopx/credentials.yaml` after creation.
## Shell Scripting Examples
### Check Authentication Before Running Commands
```bash theme={null}
#!/bin/bash
# Check authentication
if ! hopx auth status > /dev/null 2>&1; then
echo "Not authenticated. Please run 'hopx auth login'"
exit 1
fi
# Proceed with commands
hopx sandbox create --template python
```
### Create and Use API Key
```bash theme={null}
#!/bin/bash
# Create API key
KEY_NAME="ci-$(date +%s)"
hopx auth keys create --name "$KEY_NAME"
# Use in script
export HOPX_API_KEY=$(hopx auth keys info "$KEY_NAME" --output json | jq -r '.key')
```
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI authentication
* **[CLI Installation](/cli/installation)** - Installation guide
* **[API Key Guide](/api-key)** - Complete API key documentation
* **[Configuration](/cli/commands/config)** - Configure CLI settings
## Next Steps
* Complete [CLI Quickstart](/cli/quickstart) to authenticate and create your first sandbox
* Learn about [Configuration](/cli/commands/config) to manage multiple profiles
* Review [API Key Guide](/api-key) for security best practices
# Billing
Source: https://docs.hopx.ai/cli/commands/billing
Complete reference for HopX CLI billing commands - view balance, billing history, invoices, and auto-recharge settings.
Manage billing and payments using the `billing` command. View account balance, billing history, invoices, and configure auto-recharge.
## Command Syntax
```bash theme={null}
hopx billing [options]
```
## Subcommands
### `balance`
View account balance.
**Syntax:**
```bash theme={null}
hopx billing balance [OPTIONS]
```
**Examples:**
```bash theme={null}
# View balance
hopx billing balance
```
**Expected Output:**
```
┌─────────────┬─────────────────────────────────────┐
│ Property │ Value │
├─────────────┼─────────────────────────────────────┤
│ Balance │ $150.00 │
│ Credits │ 1500 │
│ Currency │ USD │
└─────────────┴─────────────────────────────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `history`
View billing history.
**Syntax:**
```bash theme={null}
hopx billing history [OPTIONS]
```
**Options:**
* `--limit INTEGER` - Number of records to show
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# View billing history
hopx billing history
# View with limit
hopx billing history --limit 10
```
**Expected Output:**
```
┌──────────────┬──────────────┬─────────────┐
│ Date │ Amount │ Description │
├──────────────┼──────────────┼─────────────┤
│ 2025-01-27 │ $50.00 │ Payment │
│ 2025-01-20 │ -$10.00 │ Usage │
└──────────────┴──────────────┴─────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `invoices`
List invoices.
**Syntax:**
```bash theme={null}
hopx billing invoices [OPTIONS]
```
**Options:**
* `--limit INTEGER` - Number of invoices to show
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# List invoices
hopx billing invoices
# List with limit
hopx billing invoices --limit 5
```
**Expected Output:**
```
┌──────────────┬──────────────┬─────────────┐
│ Invoice ID │ Date │ Amount │
├──────────────┼──────────────┼─────────────┤
│ inv_abc123 │ 2025-01-27 │ $50.00 │
│ inv_def456 │ 2025-01-20 │ $30.00 │
└──────────────┴──────────────┴─────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `auto-recharge`
Configure auto-recharge settings.
**Syntax:**
```bash theme={null}
hopx billing auto-recharge [OPTIONS]
```
**Examples:**
```bash theme={null}
# Configure auto-recharge
hopx billing auto-recharge
```
**Expected Output:**
```
Auto-recharge configuration
✓ Auto-recharge enabled
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI
* **[Usage Statistics](/cli/commands/usage)** - Monitor usage
* **[Organization Commands](/cli/commands/org)** - Manage organizations
## Next Steps
* Learn about [Usage Statistics](/cli/commands/usage) to monitor resource usage
* Explore [Organization Management](/cli/commands/org) to manage organization settings
* Review [Dashboard](https://console.hopx.dev) for billing management
# Shell Commands
Source: https://docs.hopx.ai/cli/commands/cmd
Execute shell commands in HopX sandboxes using the CLI cmd command. Run commands synchronously or in the background with options for timeouts, working directories, and environment variables.
Execute shell commands in HopX sandboxes using the `cmd` command. Run commands synchronously or in the background with full control over execution environment.
## Command Syntax
```bash theme={null}
hopx cmd [options]
```
## Subcommands
### `run`
Run a shell command synchronously.
**Syntax:**
```bash theme={null}
hopx cmd run SANDBOX_ID COMMAND [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
* `COMMAND` - Shell command to execute (required)
**Options:**
* `--timeout INTEGER` - Command timeout in seconds
* `--workdir TEXT` - Working directory for command execution
* `--env TEXT` - Environment variable in KEY=VALUE format (repeatable)
* `--background` - Run command in background (returns immediately)
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# Run simple command
hopx cmd run sb_abc123 "ls -la"
# Run with timeout
hopx cmd run sb_abc123 "npm install" --timeout 300
# Run in working directory
hopx cmd run sb_abc123 "pwd" --workdir /app
# Run with environment variables
hopx cmd run sb_abc123 "echo $API_KEY" --env API_KEY=secret123
# Run in background
hopx cmd run sb_abc123 "python server.py" --background
# Get JSON output
hopx cmd run sb_abc123 "ls -la" --output json
```
**Expected Output:**
```
total 16
drwxr-xr-x 2 user user 4096 Jan 27 10:00 .
drwxr-xr-x 3 user user 4096 Jan 27 10:00 ..
-rw-r--r-- 1 user user 13 Jan 27 10:00 data.txt
```
**Expected Output (JSON):**
```json theme={null}
{
"stdout": "total 16\ndrwxr-xr-x 2 user user 4096 Jan 27 10:00 .\n",
"stderr": "",
"exit_code": 0,
"execution_time": 0.5
}
```
**Exit Codes:**
* `0` - Success
* `1` - Command execution error
* `3` - Authentication error
* `4` - Sandbox not found
* `5` - Timeout
### `exec`
Execute a shell command (alias for `run`).
**Syntax:**
```bash theme={null}
hopx cmd exec SANDBOX_ID COMMAND [OPTIONS]
```
Same as `run` command. See `run` for options and examples.
## Shell Scripting Examples
### Install Dependencies
```bash theme={null}
#!/bin/bash
set -e
SANDBOX_ID="sb_abc123"
# Install packages
hopx cmd run "$SANDBOX_ID" "pip install requests pandas" --timeout 120
# Verify installation
hopx cmd run "$SANDBOX_ID" "pip list | grep requests"
```
### Run Tests
```bash theme={null}
#!/bin/bash
# Run tests with environment variables
hopx cmd run sb_abc123 "npm test" \
--env NODE_ENV=test \
--env CI=true \
--workdir /app
```
### Background Process
```bash theme={null}
#!/bin/bash
# Start server in background
hopx cmd run sb_abc123 "python server.py" --background
# Server is now running in background
# Use other commands to interact with it
```
### Chain Commands
```bash theme={null}
#!/bin/bash
# Chain multiple commands
hopx cmd run sb_abc123 "cd /app && npm install && npm test"
```
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI
* **[Sandbox Commands](/cli/commands/sandbox)** - Manage sandboxes
* **[Code Execution](/cli/commands/run)** - Execute code in sandboxes
* **[Environment Variables](/cli/commands/env)** - Manage environment variables
* **[Python SDK: Commands](/sdk/python/commands)** - Python SDK command execution
* **[JavaScript SDK: Commands](/sdk/javascript/commands)** - JavaScript SDK command execution
* **[API: Run Command](/api/vm-agent/run-command)** - REST API endpoint
## Next Steps
* Learn about [Code Execution](/cli/commands/run) to run code alongside commands
* Explore [File Operations](/cli/commands/files) to work with files via commands
* Review [Environment Variables](/cli/commands/env) to configure command execution
# Configuration
Source: https://docs.hopx.ai/cli/commands/config
Complete reference for HopX CLI configuration commands - show, set, get, and manage configuration profiles. Configure CLI settings, default values, and multiple profiles for different environments.
Manage CLI configuration using the `config` command. View and modify settings, manage configuration profiles, and configure default values for commands.
## Command Syntax
```bash theme={null}
hopx config [options]
```
## Subcommands
### `show`
Show current configuration.
**Syntax:**
```bash theme={null}
hopx config show [OPTIONS]
```
**Examples:**
```bash theme={null}
# Show current configuration
hopx config show
```
**Expected Output:**
```
┌─────────────────────┬─────────────────────────────────────┐
│ Setting │ Value │
├─────────────────────┼─────────────────────────────────────┤
│ Profile │ default │
│ API Key │ hopx_live_... (configured) │
│ Base URL │ https://api.hopx.dev │
│ Default Template │ code-interpreter │
│ Default Timeout │ 3600 │
│ Output Format │ table │
└─────────────────────┴─────────────────────────────────────┘
```
**Exit Codes:**
* `0` - Success
### `set`
Set a configuration value.
**Syntax:**
```bash theme={null}
hopx config set KEY VALUE [OPTIONS]
```
**Arguments:**
* `KEY` - Configuration key (required)
* `VALUE` - Configuration value (required)
**Examples:**
```bash theme={null}
# Set default template
hopx config set default_template python
# Set default timeout
hopx config set default_timeout 7200
# Set output format
hopx config set output_format json
```
**Expected Output:**
```
✓ Configuration updated: default_template = python
```
**Exit Codes:**
* `0` - Success
* `2` - Invalid key or value
### `get`
Get a configuration value.
**Syntax:**
```bash theme={null}
hopx config get KEY [OPTIONS]
```
**Arguments:**
* `KEY` - Configuration key (required)
**Examples:**
```bash theme={null}
# Get default template
hopx config get default_template
# Get output format
hopx config get output_format
```
**Expected Output:**
```
python
```
**Exit Codes:**
* `0` - Success
* `2` - Key not found
### `path`
Show configuration file path.
**Syntax:**
```bash theme={null}
hopx config path [OPTIONS]
```
**Examples:**
```bash theme={null}
# Show config file path
hopx config path
```
**Expected Output:**
```
~/.hopx/config.yaml
```
**Exit Codes:**
* `0` - Success
### `init`
Initialize configuration (interactive setup).
**Syntax:**
```bash theme={null}
hopx config init [OPTIONS]
```
**Examples:**
```bash theme={null}
# Initialize configuration
hopx config init
```
**Expected Output:**
```
Configuration setup wizard
✓ Configuration initialized
```
**Exit Codes:**
* `0` - Success
### `profiles`
Manage configuration profiles.
#### `profiles list`
List all configuration profiles.
**Syntax:**
```bash theme={null}
hopx config profiles list [OPTIONS]
```
**Examples:**
```bash theme={null}
# List profiles
hopx config profiles list
```
**Expected Output:**
```
┌───────────┬──────────────┐
│ Profile │ Active │
├───────────┼──────────────┤
│ default │ ✓ │
│ production│ │
│ staging │ │
└───────────┴──────────────┘
```
#### `profiles create`
Create a new configuration profile.
**Syntax:**
```bash theme={null}
hopx config profiles create PROFILE_NAME [OPTIONS]
```
**Arguments:**
* `PROFILE_NAME` - Profile name (required)
**Examples:**
```bash theme={null}
# Create profile
hopx config profiles create production
```
**Expected Output:**
```
✓ Profile created: production
```
#### `profiles use`
Switch to a configuration profile.
**Syntax:**
```bash theme={null}
hopx config profiles use PROFILE_NAME [OPTIONS]
```
**Arguments:**
* `PROFILE_NAME` - Profile name (required)
**Examples:**
```bash theme={null}
# Switch to profile
hopx config profiles use production
```
**Expected Output:**
```
✓ Switched to profile: production
```
#### `profiles delete`
Delete a configuration profile.
**Syntax:**
```bash theme={null}
hopx config profiles delete PROFILE_NAME [OPTIONS]
```
**Arguments:**
* `PROFILE_NAME` - Profile name (required)
**Examples:**
```bash theme={null}
# Delete profile
hopx config profiles delete staging
```
**Expected Output:**
```
✓ Profile deleted: staging
```
## Configuration Keys
Common configuration keys:
* `default_template` - Default template for sandbox creation
* `default_timeout` - Default timeout in seconds
* `output_format` - Default output format (`table`, `json`, `plain`)
* `base_url` - API base URL (default: `https://api.hopx.dev`)
## Shell Scripting Examples
### Configure for Different Environments
```bash theme={null}
#!/bin/bash
# Create production profile
hopx config profiles create production
hopx config profiles use production
hopx config set default_template python
hopx config set default_timeout 7200
# Create staging profile
hopx config profiles create staging
hopx config profiles use staging
hopx config set default_template code-interpreter
hopx config set default_timeout 3600
```
### Use Profile for Single Command
```bash theme={null}
#!/bin/bash
# Use production profile for single command
hopx --profile production sandbox create --template python
```
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI
* **[CLI Installation](/cli/installation)** - Installation and initial setup
* **[Authentication](/cli/commands/auth)** - Configure authentication
## Next Steps
* Learn about [Authentication](/cli/commands/auth) to configure API keys
* Explore [Sandbox Management](/cli/commands/sandbox) to use configured defaults
* Review [Environment Variables](/cli/commands/env) for sandbox configuration
# Environment Variables
Source: https://docs.hopx.ai/cli/commands/env
Complete reference for HopX CLI environment variable commands - list, get, set, and delete environment variables in sandboxes. Includes examples for configuring execution environments.
Manage environment variables in HopX sandboxes using the `env` command. List, get, set, and delete environment variables to configure execution environments.
## Command Syntax
```bash theme={null}
hopx env [options]
```
## Subcommands
### `list`
List all environment variables in a sandbox.
**Syntax:**
```bash theme={null}
hopx env list SANDBOX_ID [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
**Options:**
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# List all environment variables
hopx env list sb_abc123
# List with JSON output
hopx env list sb_abc123 --output json
```
**Expected Output (Table):**
```
┌───────────┬─────────────┐
│ Variable │ Value │
├───────────┼─────────────┤
│ API_KEY │ secret123 │
│ DEBUG │ true │
│ NODE_ENV │ production │
└───────────┴─────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
### `get`
Get the value of a specific environment variable.
**Syntax:**
```bash theme={null}
hopx env get SANDBOX_ID VARIABLE [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
* `VARIABLE` - Environment variable name (required)
**Examples:**
```bash theme={null}
# Get environment variable
hopx env get sb_abc123 API_KEY
# Get with JSON output
hopx env get sb_abc123 DEBUG --output json
```
**Expected Output:**
```
secret123
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox or variable not found
### `set`
Set one or more environment variables.
**Syntax:**
```bash theme={null}
hopx env set SANDBOX_ID [KEY] [VALUE] [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
* `KEY` - Environment variable name (optional, use with `--env` for multiple)
* `VALUE` - Environment variable value (optional, use with `--env` for multiple)
**Options:**
* `--env, -e TEXT` - Environment variable in KEY=VALUE format (repeatable)
* `--env-file PATH` - Load environment variables from file
**Examples:**
```bash theme={null}
# Set single variable (positional arguments)
hopx env set sb_abc123 API_KEY secret123
# Set multiple variables using --env flag
hopx env set sb_abc123 --env API_KEY=secret123 --env DEBUG=true --env NODE_ENV=production
# Set from file
hopx env set sb_abc123 --env-file .env
```
**Expected Output:**
```
✓ Environment variables set
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
### `delete`
Delete an environment variable.
**Syntax:**
```bash theme={null}
hopx env delete SANDBOX_ID VARIABLE [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
* `VARIABLE` - Environment variable name to delete (required)
**Examples:**
```bash theme={null}
# Delete environment variable
hopx env delete sb_abc123 DEBUG
```
**Expected Output:**
```
✓ Environment variable deleted: DEBUG
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox or variable not found
## Shell Scripting Examples
### Configure Environment for Code Execution
```bash theme={null}
#!/bin/bash
set -e
SANDBOX_ID="sb_abc123"
# Set environment variables
hopx env set "$SANDBOX_ID" \
API_KEY=secret123 \
DEBUG=true \
NODE_ENV=production
# Execute code that uses environment variables
hopx run "import os; print(os.environ['API_KEY'])" --sandbox "$SANDBOX_ID"
```
### Load Environment from File
```bash theme={null}
#!/bin/bash
# Create .env file
cat > .env << EOF
API_KEY=secret123
DEBUG=true
NODE_ENV=production
EOF
# Load into sandbox
hopx env set sb_abc123 --env-file .env
```
### Conditional Environment Setup
```bash theme={null}
#!/bin/bash
# Check if variable exists
if hopx env get sb_abc123 API_KEY > /dev/null 2>&1; then
echo "API_KEY already set"
else
echo "Setting API_KEY..."
hopx env set sb_abc123 API_KEY=secret123
fi
```
### List and Export Variables
```bash theme={null}
#!/bin/bash
# List variables and export to local environment
hopx env list sb_abc123 --output json | jq -r 'to_entries[] | "export \(.key)=\(.value)"' | source /dev/stdin
```
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI
* **[Sandbox Commands](/cli/commands/sandbox)** - Manage sandboxes
* **[Code Execution](/cli/commands/run)** - Execute code with environment variables
* **[Shell Commands](/cli/commands/cmd)** - Run commands with environment variables
* **[Python SDK: Environment Variables](/sdk/python/environment-variables)** - Python SDK environment management
* **[JavaScript SDK: Environment Variables](/sdk/javascript/environment-variables)** - JavaScript SDK environment management
* **[API: Environment Variables](/api/vm-agent/get-env)** - REST API endpoints
## Next Steps
* Learn about [Code Execution](/cli/commands/run) to use environment variables in code
* Explore [Shell Commands](/cli/commands/cmd) to run commands with environment variables
* Review [Sandbox Management](/cli/commands/sandbox) to create sandboxes with initial environment variables
# File Operations
Source: https://docs.hopx.ai/cli/commands/files
Complete reference for HopX CLI file commands - read, write, list, upload, download, delete, and manage files in sandboxes. Includes all flags, options, examples, and exit codes.
Manage files in HopX sandboxes using the `files` command (alias: `f`). Read, write, list, upload, download, and delete files from the command line.
## Command Syntax
```bash theme={null}
hopx files [options]
```
## Subcommands
### `read`
Read file contents from a sandbox.
**Syntax:**
```bash theme={null}
hopx files read SANDBOX_ID PATH [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
* `PATH` - File path to read (required)
**Options:**
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# Read file
hopx files read sb_abc123 /app/config.json
# Read with JSON output
hopx files read sb_abc123 /app/data.txt --output json
```
**Expected Output:**
```
{"key": "value"}
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox or file not found
### `write`
Write data to a file in a sandbox.
**Syntax:**
```bash theme={null}
hopx files write SANDBOX_ID PATH [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
* `PATH` - File path to write (required)
**Options:**
* `--data, -d TEXT` - Data to write (use `-` to read from stdin)
**Examples:**
```bash theme={null}
# Write file with data
hopx files write sb_abc123 /app/config.json --data '{"key": "value"}'
# Write from stdin
echo "Hello, World!" | hopx files write sb_abc123 /app/data.txt --data -
# Write from file
cat local.txt | hopx files write sb_abc123 /app/data.txt --data -
```
**Expected Output:**
```
✓ File written: /app/config.json
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
### `list`
List files and directories in a sandbox.
**Syntax:**
```bash theme={null}
hopx files list SANDBOX_ID [PATH] [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
* `PATH` - Directory path (optional, default: `/workspace`)
**Options:**
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# List files in workspace
hopx files list sb_abc123
# List files in specific directory
hopx files list sb_abc123 /app/
# List with JSON output
hopx files list sb_abc123 --output json
```
**Expected Output (Table):**
```
┌──────────────┬──────┬─────────────────────┐
│ Name │ Size │ Modified │
├──────────────┼──────┼─────────────────────┤
│ config.json │ 234 │ 2025-01-27 10:00:00 │
│ data.txt │ 13 │ 2025-01-27 10:00:00 │
└──────────────┴──────┴─────────────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
### `delete`
Delete a file or directory from a sandbox.
**Syntax:**
```bash theme={null}
hopx files delete SANDBOX_ID PATH [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
* `PATH` - File or directory path to delete (required)
**Options:**
* `--force` - Skip confirmation prompt
**Examples:**
```bash theme={null}
# Delete file
hopx files delete sb_abc123 /app/temp.txt
# Delete without confirmation
hopx files delete sb_abc123 /app/temp.txt --force
```
**Expected Output:**
```
✓ File deleted: /app/temp.txt
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox or file not found
### `upload`
Upload a local file to a sandbox.
**Syntax:**
```bash theme={null}
hopx files upload SANDBOX_ID LOCAL_PATH REMOTE_PATH [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
* `LOCAL_PATH` - Local file path (required)
* `REMOTE_PATH` - Remote file path in sandbox (required)
**Examples:**
```bash theme={null}
# Upload local file
hopx files upload sb_abc123 ./local.txt /app/remote.txt
# Upload with progress
hopx files upload sb_abc123 ./large.csv /app/data.csv
```
**Expected Output:**
```
✓ File uploaded: /app/remote.txt
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
### `download`
Download a file from a sandbox to local filesystem.
**Syntax:**
```bash theme={null}
hopx files download SANDBOX_ID REMOTE_PATH LOCAL_PATH [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
* `REMOTE_PATH` - Remote file path in sandbox (required)
* `LOCAL_PATH` - Local file path (required)
**Examples:**
```bash theme={null}
# Download file
hopx files download sb_abc123 /app/data.txt ./local.txt
# Download with progress
hopx files download sb_abc123 /app/result.csv ./result.csv
```
**Expected Output:**
```
✓ File downloaded: ./local.txt
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox or file not found
### `info`
Get detailed information about a file or directory.
**Syntax:**
```bash theme={null}
hopx files info SANDBOX_ID PATH [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
* `PATH` - File or directory path (required)
**Options:**
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# Get file info
hopx files info sb_abc123 /app/config.json
# Get info with JSON output
hopx files info sb_abc123 /app/data.txt --output json
```
**Expected Output (Table):**
```
┌─────────────┬─────────────────────────────────────┐
│ Property │ Value │
├─────────────┼─────────────────────────────────────┤
│ Name │ config.json │
│ Path │ /app/config.json │
│ Size │ 234 B │
│ Type │ file │
│ Modified │ 2025-01-27 10:00:00 │
└─────────────┴─────────────────────────────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox or file not found
## Shell Scripting Examples
### Upload and Process File
```bash theme={null}
#!/bin/bash
set -e
SANDBOX_ID="sb_abc123"
# Upload file
hopx files upload "$SANDBOX_ID" ./data.csv /app/data.csv
# Process file
hopx run "import pandas as pd; df = pd.read_csv('/app/data.csv'); print(df.head())" --sandbox "$SANDBOX_ID"
```
### Download Results
```bash theme={null}
#!/bin/bash
# Download file
hopx files download sb_abc123 /app/results.json ./results.json
# Process locally
jq '.summary' ./results.json
```
### Batch File Operations
```bash theme={null}
#!/bin/bash
# List files and download each
hopx files list sb_abc123 /app/ --output json | jq -r '.[].name' | while read file; do
echo "Downloading $file..."
hopx files download sb_abc123 "/app/$file" "./$file"
done
```
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI
* **[Sandbox Commands](/cli/commands/sandbox)** - Manage sandboxes
* **[Code Execution](/cli/commands/run)** - Execute code in sandboxes
* **[Python SDK: Files](/sdk/python/files)** - Python SDK file operations
* **[JavaScript SDK: Files](/sdk/javascript/files)** - JavaScript SDK file operations
* **[API: File Operations](/api/vm-agent/read-file)** - REST API endpoints
## Next Steps
* Learn about [Code Execution](/cli/commands/run) to process files
* Explore [Environment Variables](/cli/commands/env) to configure file operations
* Review [Sandbox Management](/cli/commands/sandbox) to create and manage sandboxes
# Setup Wizard
Source: https://docs.hopx.ai/cli/commands/init
Interactive setup wizard for first-time HopX CLI configuration. Guides you through authentication, API key creation, and initial configuration.
Run the interactive setup wizard using the `init` command. This guides you through first-time CLI configuration including authentication, API key creation, and initial settings.
## Command Syntax
```bash theme={null}
hopx init [OPTIONS]
```
## Options
* `--no-browser` - Headless mode: manually paste callback URL (for servers without browsers)
* `--skip-test` - Skip the sandbox test step
## Description
The `init` command is an interactive setup wizard that helps you configure the HopX CLI for first-time use. It guides you through:
1. **Authentication** - Browser-based OAuth login
2. **API Key Creation** - Create and store your first API key
3. **Configuration** - Set default settings
4. **Verification** - Test your connection (unless `--skip-test` is used)
## Examples
```bash theme={null}
# Full interactive setup
hopx init
# Headless mode (for servers without browsers)
hopx init --no-browser
# Skip the sandbox test
hopx init --skip-test
```
**Expected Output:**
```
Welcome to HopX CLI Setup
✓ Opening browser for authentication...
✓ Authentication successful
✓ Creating API key...
✓ API key created and stored
✓ Configuration complete
✓ Testing connection...
✓ Setup complete!
```
## When to Use
* **First-time setup** - Run `hopx init` after installing the CLI
* **Reconfiguration** - Run `hopx init` to reconfigure your CLI settings
* **New environment** - Run `hopx init` when setting up on a new machine
## Manual Setup Alternative
If you prefer manual setup, you can configure the CLI step by step:
```bash theme={null}
# Authenticate
hopx auth login
# Create API key
hopx auth keys create --name "my-key"
# Configure settings
hopx config set default_template python
```
## Related
* **[CLI Installation](/cli/installation)** - Install the CLI
* **[CLI Quickstart](/cli/quickstart)** - Get started guide
* **[Authentication](/cli/commands/auth)** - Authentication commands
* **[Configuration](/cli/commands/config)** - Configuration commands
## Next Steps
* Complete [CLI Quickstart](/cli/quickstart) to run your first command
* Learn about [Authentication](/cli/commands/auth) for API key management
* Explore [Configuration](/cli/commands/config) to customize CLI settings
# Members
Source: https://docs.hopx.ai/cli/commands/members
Complete reference for HopX CLI members commands - list organization members, invite new members, and remove members.
Manage organization members using the `members` command. List members, invite new members, and remove members from your organization.
## Command Syntax
```bash theme={null}
hopx members [options]
```
## Subcommands
### `list`
List all organization members.
**Syntax:**
```bash theme={null}
hopx members list [OPTIONS]
```
**Examples:**
```bash theme={null}
# List members
hopx members list
```
**Expected Output:**
```
┌──────────────┬──────────────┬─────────────┐
│ Name │ Email │ Role │
├──────────────┼──────────────┼─────────────┤
│ John Doe │ john@ex.com │ owner │
│ Jane Smith │ jane@ex.com │ member │
└──────────────┴──────────────┴─────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `invite`
Invite a new member to the organization.
**Syntax:**
```bash theme={null}
hopx members invite EMAIL [OPTIONS]
```
**Arguments:**
* `EMAIL` - Email address to invite (required)
**Options:**
* `--role TEXT` - Member role: `member`, `admin` (default: `member`)
**Examples:**
```bash theme={null}
# Invite member
hopx members invite user@example.com
# Invite as admin
hopx members invite admin@example.com --role admin
```
**Expected Output:**
```
✓ Invitation sent to user@example.com
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `remove`
Remove a member from the organization.
**Syntax:**
```bash theme={null}
hopx members remove EMAIL [OPTIONS]
```
**Arguments:**
* `EMAIL` - Email address to remove (required)
**Examples:**
```bash theme={null}
# Remove member
hopx members remove user@example.com
```
**Expected Output:**
```
✓ Member removed: user@example.com
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Member not found
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI
* **[Organization Commands](/cli/commands/org)** - Manage organizations
* **[Authentication](/cli/commands/auth)** - Authenticate with CLI
## Next Steps
* Learn about [Organization Management](/cli/commands/org) to manage organization settings
* Explore [Billing](/cli/commands/billing) to view organization billing
* Review [Usage Statistics](/cli/commands/usage) to monitor organization usage
# Organization
Source: https://docs.hopx.ai/cli/commands/org
Complete reference for HopX CLI organization commands - view organization info, update settings, list organizations, and switch between organizations.
Manage organization settings using the `org` command. View organization information, update settings, list organizations, and switch between organizations.
## Command Syntax
```bash theme={null}
hopx org [options]
```
## Subcommands
### `info`
Get organization information.
**Syntax:**
```bash theme={null}
hopx org info [OPTIONS]
```
**Examples:**
```bash theme={null}
# Get organization info
hopx org info
```
**Expected Output:**
```
┌─────────────┬─────────────────────────────────────┐
│ Property │ Value │
├─────────────┼─────────────────────────────────────┤
│ Name │ My Organization │
│ ID │ org_abc123 │
│ Plan │ Pro │
│ Members │ 5 │
└─────────────┴─────────────────────────────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `update`
Update organization settings.
**Syntax:**
```bash theme={null}
hopx org update [OPTIONS]
```
**Options:**
* `--name TEXT` - Organization name
**Examples:**
```bash theme={null}
# Update organization name
hopx org update --name "New Organization Name"
```
**Expected Output:**
```
✓ Organization updated
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `list`
List all organizations you belong to.
**Syntax:**
```bash theme={null}
hopx org list [OPTIONS]
```
**Examples:**
```bash theme={null}
# List organizations
hopx org list
```
**Expected Output:**
```
┌──────────────┬──────────────────────┐
│ Name │ Role │
├──────────────┼──────────────────────┤
│ My Org │ owner │
│ Team Org │ member │
└──────────────┴──────────────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `switch`
Switch to a different organization.
**Syntax:**
```bash theme={null}
hopx org switch ORGANIZATION_ID [OPTIONS]
```
**Arguments:**
* `ORGANIZATION_ID` - Organization ID (required)
**Examples:**
```bash theme={null}
# Switch organization
hopx org switch org_abc123
```
**Expected Output:**
```
✓ Switched to organization: My Organization
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Organization not found
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI
* **[Authentication](/cli/commands/auth)** - Authenticate with CLI
* **[Members](/cli/commands/members)** - Manage organization members
## Next Steps
* Learn about [Members Management](/cli/commands/members) to manage team members
* Explore [Billing](/cli/commands/billing) to view organization billing
* Review [Usage Statistics](/cli/commands/usage) to monitor organization usage
# Profile
Source: https://docs.hopx.ai/cli/commands/profile
Complete reference for HopX CLI profile commands - view and update user profile information.
Manage your user profile using the `profile` command. View and update your profile information.
## Command Syntax
```bash theme={null}
hopx profile [options]
```
## Subcommands
### `info`
Get user profile information.
**Syntax:**
```bash theme={null}
hopx profile info [OPTIONS]
```
**Examples:**
```bash theme={null}
# Get profile info
hopx profile info
```
**Expected Output:**
```
┌─────────────┬─────────────────────────────────────┐
│ Property │ Value │
├─────────────┼─────────────────────────────────────┤
│ Name │ John Doe │
│ Email │ john@example.com │
│ User ID │ user_abc123 │
│ Created │ 2025-01-01 │
└─────────────┴─────────────────────────────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `update`
Update user profile information.
**Syntax:**
```bash theme={null}
hopx profile update [OPTIONS]
```
**Options:**
* `--name TEXT` - Full name
* `--email TEXT` - Email address
**Examples:**
```bash theme={null}
# Update profile name
hopx profile update --name "Jane Doe"
# Update email
hopx profile update --email "jane@example.com"
```
**Expected Output:**
```
✓ Profile updated
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI
* **[Authentication](/cli/commands/auth)** - Authenticate with CLI
* **[Configuration](/cli/commands/config)** - Configure CLI settings
## Next Steps
* Learn about [Authentication](/cli/commands/auth) to manage API keys
* Explore [Configuration](/cli/commands/config) to configure CLI settings
* Review [Organization Settings](/cli/commands/org) for organization management
# Code Execution
Source: https://docs.hopx.ai/cli/commands/run
Execute code in HopX sandboxes using the CLI run command. Run Python, JavaScript, Bash, and Go code with options for files, environment variables, timeouts, and sandbox selection.
Execute code in HopX sandboxes using the `run` command. Supports Python, JavaScript, Bash, and Go with options for files, environment variables, and timeouts.
## Command Syntax
```bash theme={null}
hopx run [CODE|FILE] [OPTIONS]
```
## Options
* `CODE` - Code to execute as argument (use `-` to read from stdin)
* `--file, -f PATH` - File containing code to execute
* `--sandbox, -s TEXT` - Sandbox ID (creates temporary sandbox if omitted)
* `--template, -t TEXT` - Template for temporary sandbox (default: `code-interpreter`)
* `--language, -l TEXT` - Programming language: `python`, `javascript`, `bash`, `go`
* `--timeout INTEGER` - Execution timeout in seconds
* `--env TEXT` - Environment variable in KEY=VALUE format (repeatable)
* `--workdir TEXT` - Working directory for execution
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
## Examples
### Execute Python Code
```bash theme={null}
# Simple Python code
hopx run "print('Hello, World!')"
# Python with imports
hopx run "import sys; print(sys.version)"
# Python with calculations
hopx run "result = 2 + 2; print(f'Result: {result}')"
```
**Expected Output:**
```
Hello, World!
```
### Execute JavaScript
```bash theme={null}
# Simple JavaScript
hopx run "console.log('Hello, World!')" -l javascript
# JavaScript with Node.js APIs
hopx run "console.log(process.version)" -l javascript
```
**Expected Output:**
```
Hello, World!
```
### Execute Bash
```bash theme={null}
# Simple Bash command
hopx run "echo 'Hello, World!'" -l bash
# Bash with system commands
hopx run "ls -la && pwd" -l bash
```
**Expected Output:**
```
Hello, World!
```
### Execute from File
```bash theme={null}
# Create local file
echo "print('Hello from file!')" > script.py
# Execute from file
hopx run -f script.py
# Execute JavaScript from file
hopx run -f script.js -l javascript
```
**Expected Output:**
```
Hello from file!
```
### Execute with Environment Variables
```bash theme={null}
# Single environment variable
hopx run "import os; print(os.environ['API_KEY'])" -e API_KEY=secret123
# Multiple environment variables
hopx run "import os; print(os.environ['API_KEY'], os.environ['DEBUG'])" \
-e API_KEY=secret123 \
-e DEBUG=true
```
**Expected Output:**
```
secret123
```
### Execute in Existing Sandbox
```bash theme={null}
# Create sandbox first
SANDBOX_ID=$(hopx sandbox create --template python --output json | jq -r '.id')
# Execute in existing sandbox
hopx run "print('Hello')" --sandbox "$SANDBOX_ID"
```
**Expected Output:**
```
Hello
```
### Execute with Timeout
```bash theme={null}
# Long-running code with timeout
hopx run "import time; time.sleep(60)" --timeout 120
```
### Execute from stdin
```bash theme={null}
# Pipe code from stdin
echo "print('Hello from stdin!')" | hopx run -
# Pipe file content
cat script.py | hopx run -
```
**Expected Output:**
```
Hello from stdin!
```
## JSON Output
Get JSON output for scripting:
```bash theme={null}
hopx run "print('Hello')" --output json
```
**Expected Output:**
```json theme={null}
{
"stdout": "Hello\n",
"stderr": "",
"exit_code": 0,
"execution_time": 0.5
}
```
## Exit Codes
* `0` - Success
* `1` - General error
* `3` - Authentication error
* `4` - Sandbox not found
* `5` - Timeout
## Shell Scripting Examples
### Execute and Capture Output
```bash theme={null}
#!/bin/bash
# Execute and capture output
OUTPUT=$(hopx run "print('Hello')" --output plain)
echo "Output: $OUTPUT"
```
### Execute with Error Handling
```bash theme={null}
#!/bin/bash
# Execute with error handling
if hopx run "print('Hello')" > /dev/null 2>&1; then
echo "Execution successful"
else
case $? in
3) echo "Authentication failed" ;;
4) echo "Sandbox not found" ;;
5) echo "Execution timed out" ;;
*) echo "Execution failed" ;;
esac
exit 1
fi
```
### Execute Multiple Scripts
```bash theme={null}
#!/bin/bash
# Execute multiple scripts
for script in *.py; do
echo "Running $script..."
hopx run -f "$script"
done
```
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI
* **[Sandbox Commands](/cli/commands/sandbox)** - Manage sandboxes
* **[Python SDK: Code Execution](/sdk/python/code-execution)** - Python SDK code execution
* **[JavaScript SDK: Code Execution](/sdk/javascript/code-execution)** - JavaScript SDK code execution
* **[API: Execute Code](/api/vm-agent/execute)** - REST API endpoint
## Next Steps
* Learn about [Sandbox Management](/cli/commands/sandbox) to create and manage sandboxes
* Explore [File Operations](/cli/commands/files) to work with files
* Review [Environment Variables](/cli/commands/env) to configure execution environment
# Sandbox
Source: https://docs.hopx.ai/cli/commands/sandbox
Complete reference for HopX CLI sandbox commands - create, list, pause, resume, kill, and manage sandboxes. Includes all flags, options, examples, and exit codes for sandbox lifecycle management.
Manage sandbox lifecycle with the `sandbox` command (alias: `sb`). Create, list, pause, resume, and kill sandboxes from the command line.
## Command Syntax
```bash theme={null}
hopx sandbox [options]
```
## Subcommands
### `create`
Create a new sandbox from a template.
**Syntax:**
```bash theme={null}
hopx sandbox create [OPTIONS]
```
**Options:**
* `--template, -t TEXT` - Template name or ID (default: `code-interpreter`)
* `--template-id TEXT` - Template ID (alternative to `--template`)
* `--timeout INTEGER` - Auto-kill timeout in seconds (0 = no timeout)
* `--region TEXT` - Preferred deployment region (e.g., `us-east`, `eu-west`)
* `--env TEXT` - Environment variable in KEY=VALUE format (repeatable)
* `--env-file PATH` - Load environment variables from file
* `--no-internet` - Disable internet access for sandbox
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# Create sandbox with Python template
hopx sandbox create --template python
# Create with timeout
hopx sandbox create --template python --timeout 7200
# Create in specific region
hopx sandbox create --template python --region us-east
# Get JSON output for scripting
hopx sandbox create --template python --output json
```
**Expected Output (Table):**
```
┌──────────────────┬─────────┬────────────┐
│ ID │ Status │ Template │
├──────────────────┼─────────┼────────────┤
│ sb_abc123 │ running │ python │
└──────────────────┴─────────┴────────────┘
```
**Expected Output (JSON):**
```json theme={null}
{
"id": "sb_abc123",
"status": "running",
"template": "python",
"created_at": "2025-01-27T10:00:00Z"
}
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Template not found
* `7` - Rate limit exceeded
### `list`
List all sandboxes.
**Syntax:**
```bash theme={null}
hopx sandbox list [OPTIONS]
```
**Options:**
* `--status TEXT` - Filter by status: `running`, `paused`, `stopped`
* `--template TEXT` - Filter by template
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# List all sandboxes
hopx sandbox list
# List running sandboxes only
hopx sandbox list --status running
# List with JSON output
hopx sandbox list --output json
# Filter by template
hopx sandbox list --template python
```
**Expected Output (Table):**
```
┌──────────────────┬─────────┬────────────┬─────────────────────┐
│ ID │ Status │ Template │ Created │
├──────────────────┼─────────┼────────────┼─────────────────────┤
│ sb_abc123 │ running │ python │ 2025-01-27 10:00:00 │
│ sb_def456 │ paused │ nodejs │ 2025-01-27 09:00:00 │
└──────────────────┴─────────┴────────────┴─────────────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `info`
Get detailed information about a sandbox.
**Syntax:**
```bash theme={null}
hopx sandbox info SANDBOX_ID [OPTIONS]
```
**Options:**
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# Get sandbox info
hopx sandbox info sb_abc123
# Get JSON output
hopx sandbox info sb_abc123 --output json
```
**Expected Output (Table):**
```
┌─────────────────┬─────────────────────────────────────┐
│ Field │ Value │
├─────────────────┼─────────────────────────────────────┤
│ ID │ sb_abc123 │
│ Status │ running │
│ Template │ python │
│ Region │ us-east │
│ Created │ 2025-01-27 10:00:00 │
│ Timeout │ 3600 seconds │
└─────────────────┴─────────────────────────────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
### `pause`
Pause a running sandbox (preserves state, saves resources).
**Syntax:**
```bash theme={null}
hopx sandbox pause SANDBOX_ID [OPTIONS]
```
**Options:**
* `--force` - Skip confirmation prompt
**Examples:**
```bash theme={null}
# Pause sandbox
hopx sandbox pause sb_abc123
# Pause without confirmation
hopx sandbox pause sb_abc123 --force
```
**Expected Output:**
```
✓ Sandbox paused: sb_abc123
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
### `resume`
Resume a paused sandbox.
**Syntax:**
```bash theme={null}
hopx sandbox resume SANDBOX_ID [OPTIONS]
```
**Examples:**
```bash theme={null}
# Resume sandbox
hopx sandbox resume sb_abc123
```
**Expected Output:**
```
✓ Sandbox resumed: sb_abc123
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
### `kill`
Kill a sandbox (permanently delete).
**Syntax:**
```bash theme={null}
hopx sandbox kill SANDBOX_ID [OPTIONS]
```
**Options:**
* `--force` - Skip confirmation prompt
**Examples:**
```bash theme={null}
# Kill sandbox (with confirmation)
hopx sandbox kill sb_abc123
# Kill without confirmation
hopx sandbox kill sb_abc123 --force
```
**Expected Output:**
```
✓ Sandbox killed: sb_abc123
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
### `url`
Get preview URL for a service running on a port.
**Syntax:**
```bash theme={null}
hopx sandbox url SANDBOX_ID --port PORT [OPTIONS]
```
**Options:**
* `--port INTEGER` - Port number (required)
**Examples:**
```bash theme={null}
# Get preview URL for port 8080
hopx sandbox url sb_abc123 --port 8080
```
**Expected Output:**
```
https://8080-sb_abc123.us-east.vms.hopx.dev/
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
## Shell Scripting Examples
### Create and Use Sandbox
```bash theme={null}
#!/bin/bash
set -e
# Create sandbox
SANDBOX_ID=$(hopx sandbox create --template python --output json | jq -r '.id')
echo "Created sandbox: $SANDBOX_ID"
# Use sandbox
hopx run "print('Hello')" --sandbox "$SANDBOX_ID"
# Cleanup
trap "hopx sandbox kill $SANDBOX_ID --force" EXIT
```
### List and Process Sandboxes
```bash theme={null}
#!/bin/bash
# List running sandboxes
hopx sandbox list --status running --output json | jq -r '.[].id' | while read id; do
echo "Processing sandbox: $id"
hopx sandbox info "$id"
done
```
### Conditional Sandbox Management
```bash theme={null}
#!/bin/bash
# Create sandbox with error handling
if SANDBOX_ID=$(hopx sandbox create --template python --output json 2>/dev/null | jq -r '.id'); then
echo "Sandbox created: $SANDBOX_ID"
else
case $? in
3) echo "Authentication failed" ;;
4) echo "Template not found" ;;
7) echo "Rate limit exceeded" ;;
*) echo "Error creating sandbox" ;;
esac
exit 1
fi
```
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI
* **[Code Execution](/cli/commands/run)** - Execute code in sandboxes
* **[File Operations](/cli/commands/files)** - Manage files in sandboxes
* **[Python SDK: Sandbox](/sdk/python/sandbox)** - Python SDK sandbox methods
* **[JavaScript SDK: Sandbox](/sdk/javascript/sandbox)** - JavaScript SDK sandbox methods
* **[API: Create Sandbox](/api/control-plane/create-sandbox)** - REST API endpoint
## Next Steps
* Learn about [Code Execution](/cli/commands/run) to execute code in sandboxes
* Explore [File Operations](/cli/commands/files) to manage files
* Review [Templates](/cli/commands/template) to list and build custom templates
# System
Source: https://docs.hopx.ai/cli/commands/system
Complete reference for HopX CLI system commands - health checks, metrics, agent info, processes, Jupyter access, and system snapshots. Monitor and inspect sandbox system resources.
Monitor and inspect HopX sandbox system resources using the `system` command. Check health, view metrics, get agent information, list processes, access Jupyter, and capture system snapshots.
## Command Syntax
```bash theme={null}
hopx system [options]
```
## Subcommands
### `health`
Check API health status.
**Syntax:**
```bash theme={null}
hopx system health [OPTIONS]
```
**Examples:**
```bash theme={null}
# Check API health
hopx system health
```
**Expected Output:**
```
✓ API is healthy
✓ All services operational
```
**Exit Codes:**
* `0` - Healthy
* `1` - Unhealthy
* `6` - Network error
### `metrics`
Get sandbox system metrics.
**Syntax:**
```bash theme={null}
hopx system metrics SANDBOX_ID [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
**Options:**
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# Get sandbox metrics
hopx system metrics sb_abc123
# Get metrics with JSON output
hopx system metrics sb_abc123 --output json
```
**Expected Output (Table):**
```
┌─────────────┬─────────────────────────────────────┐
│ Metric │ Value │
├─────────────┼─────────────────────────────────────┤
│ CPU Usage │ 15.2% │
│ Memory │ 512 MB / 2 GB (25.6%) │
│ Disk Usage │ 1.2 GB / 10 GB (12.0%) │
│ Uptime │ 2h 15m │
└─────────────┴─────────────────────────────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
### `agent-info`
Get VM agent information.
**Syntax:**
```bash theme={null}
hopx system agent-info SANDBOX_ID [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
**Options:**
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# Get agent info
hopx system agent-info sb_abc123
# Get info with JSON output
hopx system agent-info sb_abc123 --output json
```
**Expected Output (Table):**
```
┌─────────────┬─────────────────────────────────────┐
│ Property │ Value │
├─────────────┼─────────────────────────────────────┤
│ Version │ 1.2.3 │
│ Status │ running │
│ Features │ code-execution, files, terminal │
└─────────────┴─────────────────────────────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
### `processes`
List running processes in a sandbox.
**Syntax:**
```bash theme={null}
hopx system processes SANDBOX_ID [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
**Options:**
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# List processes
hopx system processes sb_abc123
# List with JSON output
hopx system processes sb_abc123 --output json
```
**Expected Output (Table):**
```
┌──────┬──────────────┬─────────┬─────────────┐
│ PID │ Command │ User │ CPU % │
├──────┼──────────────┼─────────┼─────────────┤
│ 1234 │ python │ user │ 5.2 │
│ 1235 │ node │ user │ 2.1 │
└──────┴──────────────┴─────────┴─────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
### `jupyter`
Get Jupyter access information.
**Syntax:**
```bash theme={null}
hopx system jupyter SANDBOX_ID [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
**Options:**
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# Get Jupyter info
hopx system jupyter sb_abc123
```
**Expected Output:**
```
Jupyter URL: https://jupyter-sb_abc123.us-east.vms.hopx.dev/
Token: jupyter-token-abc123
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
### `snapshot`
Capture system snapshot.
**Syntax:**
```bash theme={null}
hopx system snapshot SANDBOX_ID [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
**Options:**
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# Capture system snapshot
hopx system snapshot sb_abc123
```
**Expected Output:**
```
✓ System snapshot captured
✓ Snapshot ID: snap_abc123
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
## Shell Scripting Examples
### Monitor Sandbox Health
```bash theme={null}
#!/bin/bash
# Check API health
if ! hopx system health > /dev/null 2>&1; then
echo "API is unhealthy"
exit 1
fi
# Monitor sandbox metrics
hopx system metrics sb_abc123 --output json | jq '.cpu_percent'
```
### Check Resource Usage
```bash theme={null}
#!/bin/bash
# Get metrics and check memory usage
MEMORY=$(hopx system metrics sb_abc123 --output json | jq -r '.memory_percent')
if (( $(echo "$MEMORY > 80" | bc -l) )); then
echo "Warning: High memory usage: ${MEMORY}%"
fi
```
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI
* **[Sandbox Commands](/cli/commands/sandbox)** - Create and manage sandboxes
* **[Python SDK: Observability](/sdk/python/observability)** - Python SDK system monitoring
* **[JavaScript SDK: Observability](/sdk/javascript/observability)** - JavaScript SDK system monitoring
* **[API: System Metrics](/api/vm-agent/get-system-metrics)** - REST API endpoints
## Next Steps
* Learn about [Sandbox Management](/cli/commands/sandbox) to create sandboxes
* Explore [Observability](/core-concepts/observability/metrics) for monitoring concepts
* Review [Process Management](/core-concepts/observability/processes) for process monitoring
# Template
Source: https://docs.hopx.ai/cli/commands/template
Complete reference for HopX CLI template commands - list, info, build, and delete templates. Manage pre-built and custom templates for sandbox creation.
Manage templates for HopX sandboxes using the `template` command (alias: `tpl`). List available templates, view template details, build custom templates, and delete templates.
## Command Syntax
```bash theme={null}
hopx template [options]
```
## Subcommands
### `list`
List all available templates.
**Syntax:**
```bash theme={null}
hopx template list [OPTIONS]
```
**Options:**
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# List all templates
hopx template list
# List with JSON output
hopx template list --output json
```
**Expected Output (Table):**
```
┌──────────────┬──────────────────────┬─────────────┐
│ Name │ Description │ Category │
├──────────────┼──────────────────────┼─────────────┤
│ python │ Python 3.11 │ language │
│ nodejs │ Node.js 20 │ language │
│ code-interpreter │ Data science stack │ development │
└──────────────┴──────────────────────┴─────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `info`
Get detailed information about a template.
**Syntax:**
```bash theme={null}
hopx template info TEMPLATE_NAME [OPTIONS]
```
**Arguments:**
* `TEMPLATE_NAME` - Template name or ID (required)
**Options:**
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# Get template info
hopx template info python
# Get info with JSON output
hopx template info code-interpreter --output json
```
**Expected Output (Table):**
```
┌─────────────┬─────────────────────────────────────┐
│ Property │ Value │
├─────────────┼─────────────────────────────────────┤
│ Name │ python │
│ ID │ 123 │
│ Description │ Python 3.11 with pip │
│ Category │ language │
│ Language │ python │
└─────────────┴─────────────────────────────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Template not found
### `build`
Build a custom template from a Dockerfile.
**Syntax:**
```bash theme={null}
hopx template build [OPTIONS]
```
**Options:**
* `--name TEXT` - Template name (required)
* `--dockerfile PATH` - Path to Dockerfile
* `--image TEXT` - Base image (e.g., `python:3.11`, `node:20`)
* `--context PATH` - Build context directory
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# Build template from Dockerfile
hopx template build --name my-app --dockerfile ./Dockerfile
# Build with context directory
hopx template build --name my-app --dockerfile ./Dockerfile --context ./build-context
```
**Expected Output:**
```
Building template: my-app
✓ Template built successfully
✓ Template ID: tpl_abc123
```
**Exit Codes:**
* `0` - Success
* `1` - Build failed
* `3` - Authentication error
### `delete`
Delete a custom template.
**Syntax:**
```bash theme={null}
hopx template delete TEMPLATE_ID [OPTIONS]
```
**Arguments:**
* `TEMPLATE_ID` - Template ID to delete (required)
**Options:**
* `--force` - Skip confirmation prompt
**Examples:**
```bash theme={null}
# Delete template
hopx template delete tpl_abc123
# Delete without confirmation
hopx template delete tpl_abc123 --force
```
**Expected Output:**
```
✓ Template deleted: tpl_abc123
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Template not found
## Shell Scripting Examples
### List and Filter Templates
```bash theme={null}
#!/bin/bash
# List templates and filter by category
hopx template list --output json | jq '.[] | select(.category == "language")'
```
### Build and Use Custom Template
```bash theme={null}
#!/bin/bash
set -e
# Build custom template
TEMPLATE_ID=$(hopx template build --name my-app --dockerfile ./Dockerfile --output json | jq -r '.id')
# Create sandbox from custom template
SANDBOX_ID=$(hopx sandbox create --template-id "$TEMPLATE_ID" --output json | jq -r '.id')
echo "Created sandbox $SANDBOX_ID from template $TEMPLATE_ID"
```
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI
* **[Sandbox Commands](/cli/commands/sandbox)** - Create sandboxes from templates
* **[Python SDK: Template Builder](/sdk/python/template-builder)** - Python SDK template building
* **[JavaScript SDK: Template Builder](/sdk/javascript/template-builder)** - JavaScript SDK template building
* **[API: Templates](/api/control-plane/list-templates)** - REST API endpoints
## Next Steps
* Learn about [Sandbox Management](/cli/commands/sandbox) to create sandboxes from templates
* Explore [Template Building](/sdk/python/template-builder) for advanced template creation
* Review [Pre-built Templates](/supported-languages) for available templates
# Terminal
Source: https://docs.hopx.ai/cli/commands/terminal
Complete reference for HopX CLI terminal commands - connect to interactive terminal sessions, get terminal info, and get WebSocket URLs for terminal access.
Connect to interactive terminal sessions in HopX sandboxes using the `terminal` command (alias: `term`). Access WebSocket-based terminal sessions for interactive shell access.
## Command Syntax
```bash theme={null}
hopx terminal [options]
```
## Subcommands
### `connect`
Connect to an interactive terminal session.
**Syntax:**
```bash theme={null}
hopx terminal connect SANDBOX_ID [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
**Options:**
* `--command TEXT` - Command to execute (default: interactive shell)
* `--timeout INTEGER` - Connection timeout in seconds
**Examples:**
```bash theme={null}
# Connect to interactive terminal
hopx terminal connect sb_abc123
# Execute command and exit
hopx terminal connect sb_abc123 --command "ls -la"
# Connect with timeout
hopx terminal connect sb_abc123 --timeout 60
```
**Expected Output:**
```
Connected to terminal session
$
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
* `5` - Connection timeout
### `info`
Get terminal information for a sandbox.
**Syntax:**
```bash theme={null}
hopx terminal info SANDBOX_ID [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
**Options:**
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# Get terminal info
hopx terminal info sb_abc123
# Get info with JSON output
hopx terminal info sb_abc123 --output json
```
**Expected Output (Table):**
```
┌─────────────┬─────────────────────────────────────┐
│ Property │ Value │
├─────────────┼─────────────────────────────────────┤
│ Status │ active │
│ WebSocket │ wss://... │
│ Terminal │ /bin/bash │
└─────────────┴─────────────────────────────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
### `url`
Get WebSocket URL for terminal access.
**Syntax:**
```bash theme={null}
hopx terminal url SANDBOX_ID [OPTIONS]
```
**Arguments:**
* `SANDBOX_ID` - Sandbox ID (required)
**Examples:**
```bash theme={null}
# Get terminal WebSocket URL
hopx terminal url sb_abc123
```
**Expected Output:**
```
wss://terminal-sb_abc123.us-east.vms.hopx.dev/
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
* `4` - Sandbox not found
## Interactive Terminal Usage
When connected to an interactive terminal:
* Type commands as you would in a normal terminal
* Press `Ctrl+C` to interrupt running commands
* Press `Ctrl+D` or type `exit` to disconnect
* Use arrow keys for command history
* Tab completion is available
## Shell Scripting Examples
### Connect and Execute Commands
```bash theme={null}
#!/bin/bash
# Connect and run commands
echo "ls -la" | hopx terminal connect sb_abc123 --command "bash"
```
### Get Terminal URL for External Tools
```bash theme={null}
#!/bin/bash
# Get terminal URL for use with external WebSocket clients
TERMINAL_URL=$(hopx terminal url sb_abc123)
echo "Terminal URL: $TERMINAL_URL"
```
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI
* **[Sandbox Commands](/cli/commands/sandbox)** - Create and manage sandboxes
* **[Shell Commands](/cli/commands/cmd)** - Run non-interactive shell commands
* **[Python SDK: Terminal](/sdk/python/terminal)** - Python SDK terminal access
* **[JavaScript SDK: Terminal](/sdk/javascript/terminal)** - JavaScript SDK terminal access
* **[API: Terminal](/api/vm-agent/terminal)** - REST API endpoints
## Next Steps
* Learn about [Sandbox Management](/cli/commands/sandbox) to create sandboxes
* Explore [Shell Commands](/cli/commands/cmd) for non-interactive command execution
* Review [Code Execution](/cli/commands/run) to run code in sandboxes
# Usage
Source: https://docs.hopx.ai/cli/commands/usage
Complete reference for HopX CLI usage commands - view usage summary, plans, history, and sandbox usage statistics.
Monitor usage statistics using the `usage` command. View usage summary, available plans, usage history, and sandbox usage.
## Command Syntax
```bash theme={null}
hopx usage [options]
```
## Subcommands
### `summary`
View usage summary.
**Syntax:**
```bash theme={null}
hopx usage summary [OPTIONS]
```
**Examples:**
```bash theme={null}
# View usage summary
hopx usage summary
```
**Expected Output:**
```
┌─────────────┬─────────────────────────────────────┐
│ Metric │ Value │
├─────────────┼─────────────────────────────────────┤
│ Sandboxes │ 15 / 100 (15%) │
│ Compute │ 50h / 200h (25%) │
│ Storage │ 5 GB / 50 GB (10%) │
│ Period │ January 2025 │
└─────────────┴─────────────────────────────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `plans`
View available plans.
**Syntax:**
```bash theme={null}
hopx usage plans [OPTIONS]
```
**Examples:**
```bash theme={null}
# View plans
hopx usage plans
```
**Expected Output:**
```
┌──────────────┬──────────────┬─────────────┐
│ Plan │ Price │ Features │
├──────────────┼──────────────┼─────────────┤
│ Free │ $0 │ 10 sandboxes│
│ Pro │ $29/mo │ 100 sandboxes│
│ Enterprise │ Custom │ Unlimited │
└──────────────┴──────────────┴─────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `history`
View usage history.
**Syntax:**
```bash theme={null}
hopx usage history [OPTIONS]
```
**Options:**
* `--limit INTEGER` - Number of records to show
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# View usage history
hopx usage history
# View with limit
hopx usage history --limit 20
```
**Expected Output:**
```
┌──────────────┬──────────────┬─────────────┐
│ Date │ Sandboxes │ Compute │
├──────────────┼──────────────┼─────────────┤
│ 2025-01-27 │ 15 │ 2.5h │
│ 2025-01-26 │ 12 │ 2.0h │
└──────────────┴──────────────┴─────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
### `sandboxes`
View sandbox usage statistics.
**Syntax:**
```bash theme={null}
hopx usage sandboxes [OPTIONS]
```
**Options:**
* `--output, -o FORMAT` - Output format: `table`, `json`, `plain` (default: `table`)
**Examples:**
```bash theme={null}
# View sandbox usage
hopx usage sandboxes
```
**Expected Output:**
```
┌──────────────┬──────────────┬─────────────┐
│ Sandbox ID │ Runtime │ Resources │
├──────────────┼──────────────┼─────────────┤
│ sb_abc123 │ 2h 15m │ 2 CPU, 4GB │
│ sb_def456 │ 1h 30m │ 1 CPU, 2GB │
└──────────────┴──────────────┴─────────────┘
```
**Exit Codes:**
* `0` - Success
* `3` - Authentication error
## Related
* **[CLI Quickstart](/cli/quickstart)** - Get started with CLI
* **[Billing](/cli/commands/billing)** - Manage billing
* **[Organization Commands](/cli/commands/org)** - Manage organizations
## Next Steps
* Learn about [Billing](/cli/commands/billing) to manage payments
* Explore [Organization Management](/cli/commands/org) to manage organization settings
* Review [Dashboard](https://console.hopx.dev) for detailed usage analytics
# Installation
Source: https://docs.hopx.ai/cli/installation
Install the HopX CLI on Linux, macOS, or Windows. Multiple installation methods including quick install script, uv, pipx, and pip. Includes verification steps and troubleshooting.
Install the HopX CLI to manage cloud sandboxes from your terminal. The CLI supports multiple installation methods and works on Linux, macOS, and Windows (including WSL).
## Prerequisites
* **Python 3.12+** - Required for CLI operation
* **Terminal access** - Command-line interface
* **Internet connection** - For installation and API access
## Quick Install (Recommended)
The quick install script handles everything automatically, including PEP 668 environments on macOS/modern Linux:
```bash theme={null}
curl -fsSL https://raw.githubusercontent.com/hopx-ai/hopx/main/cli/scripts/install.sh | bash
```
This script:
* Detects your platform (Linux, macOS, Windows/WSL)
* Installs the CLI using the best method for your system
* Adds the CLI to your PATH
* Verifies the installation
**Expected Output:**
```
✓ HopX CLI installed successfully
✓ Version: 0.1.2
✓ Run 'hopx init' to get started
```
## Alternative Installation Methods
### uv (Fastest)
[uv](https://github.com/astral-sh/uv) is a fast Python package installer:
```bash theme={null}
# Install uv
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install HopX CLI
uv tool install hopx-cli
# Verify installation
hopx --version
```
### pipx (Isolated)
[pipx](https://github.com/pypa/pipx) installs Python applications in isolated environments:
```bash theme={null}
# Install pipx (if not installed)
python3 -m pip install --user pipx
python3 -m pipx ensurepath
# Install HopX CLI
pipx install hopx-cli
# Verify installation
hopx --version
```
### pip (User Install)
Install directly with pip:
```bash theme={null}
# Install for current user
pip install --user hopx-cli
# Add to PATH (if needed)
export PATH="$PATH:$(python3 -m site --user-base)/bin"
# Verify installation
hopx --version
```
On macOS and modern Linux systems with PEP 668, you may need to use `--user` flag or a virtual environment. The quick install script handles this automatically.
## Verify Installation
After installation, verify the CLI is working:
```bash theme={null}
# Check version
hopx --version
# Expected output:
# hopx-cli 0.1.2
# Check help
hopx --help
# Check system health
hopx system health
```
## Update CLI
Update to the latest version:
```bash theme={null}
hopx self-update
```
Or reinstall using your original installation method:
```bash theme={null}
# With uv
uv tool install hopx-cli --force
# With pipx
pipx upgrade hopx-cli
# With pip
pip install --user --upgrade hopx-cli
```
## Post-Installation Setup
After installation, complete first-time setup:
```bash theme={null}
# Interactive setup wizard
hopx init
```
The setup wizard will:
1. Guide you through authentication
2. Help you create an API key
3. Configure default settings
4. Test your connection
Or set up manually:
```bash theme={null}
# Authenticate
hopx auth login
# Create API key
hopx auth keys create --name "my-key"
# Verify authentication
hopx auth status
```
## Troubleshooting
### Command Not Found
If `hopx` command is not found:
**Linux/macOS:**
```bash theme={null}
# Check if installed
pip show hopx-cli
# Add to PATH
export PATH="$PATH:$(python3 -m site --user-base)/bin"
# Add to shell profile (permanent)
echo 'export PATH="$PATH:$(python3 -m site --user-base)/bin"' >> ~/.bashrc
source ~/.bashrc
```
**Windows:**
```powershell theme={null}
# Check if installed
pip show hopx-cli
# Add to PATH (replace USERNAME)
$env:Path += ";C:\Users\USERNAME\AppData\Roaming\Python\Python312\Scripts"
```
### Python Version Issues
The CLI requires Python 3.12+:
```bash theme={null}
# Check Python version
python3 --version
# Should show: Python 3.12.x or higher
# If using older Python, upgrade or use pyenv
pyenv install 3.12.0
pyenv global 3.12.0
```
### Permission Errors
If you encounter permission errors:
```bash theme={null}
# Use --user flag
pip install --user hopx-cli
# Or use virtual environment
python3 -m venv venv
source venv/bin/activate
pip install hopx-cli
```
### PEP 668 Errors (macOS/Linux)
On systems with PEP 668 (external package managers), use `--user` or `pipx`:
```bash theme={null}
# Use pipx (recommended)
pipx install hopx-cli
# Or use --user
pip install --user hopx-cli
```
### Installation Verification
Test the installation:
```bash theme={null}
# Check version
hopx --version
# Check help
hopx --help
# Test system health (requires authentication)
hopx system health
```
## Platform-Specific Notes
### Linux
Works on all major Linux distributions. The quick install script detects your distribution and uses the appropriate method.
### macOS
Works on macOS 10.15+. The quick install script handles Homebrew and system Python correctly.
### Windows
Works on Windows 10+ and Windows Subsystem for Linux (WSL). For native Windows, use WSL or ensure Python 3.12+ is installed.
## Related
* **[CLI Overview](/cli/introduction)** - Learn about the CLI
* **[CLI Quickstart](/cli/quickstart)** - Get started with your first command
* **[API Key Setup](/api-key)** - Get your API key for authentication
## Next Steps
* Complete [CLI Quickstart](/cli/quickstart) to run your first command
* Learn about [Authentication](/cli/commands/auth) for CLI access
* Explore [Command Reference](/cli/commands/sandbox) for all available commands
# Overview
Source: https://docs.hopx.ai/cli/introduction
Official HopX CLI for managing cloud sandboxes from the command line. Install the CLI, authenticate with your API key, and start creating sandboxes, executing code, managing files, and automating workflows. Complete command-line interface reference with examples for all 15 command groups.
The HopX CLI provides terminal access to HopX cloud sandboxes - secure, isolated VMs that start in seconds. Execute code, manage files, run commands, and build custom templates from your terminal.
## What is the HopX CLI?
The HopX CLI is the official command-line interface for HopX.ai cloud sandboxes. It provides terminal-based access to all HopX features including sandbox management, code execution, file operations, and template building.
**Version**: 0.1.2\
**Python Support**: 3.12+\
**Framework**: Typer (built on Click)
## Use Cases
* **AI agent code execution** - Execute AI-generated code safely in isolated environments
* **Running untrusted code** - Test code without risking your local machine
* **Integration testing** - Run tests in clean, reproducible environments
* **Data processing pipelines** - Process data in isolated sandboxes
* **Browser automation** - Automate browser interactions with desktop features
* **Educational environments** - Create learning environments for students
## When to Use CLI vs SDK vs API
### Use CLI When:
* You prefer command-line workflows
* You're writing shell scripts or automation
* You need quick one-off operations
* You're integrating with CI/CD pipelines
* You want interactive terminal sessions
### Use SDK When:
* You're building applications in Python or JavaScript
* You need programmatic control in your code
* You want type safety and IDE support
* You're building libraries or frameworks
### Use API When:
* You're building in languages without SDK support
* You need direct HTTP control
* You're building custom integrations
* You need fine-grained request/response handling
## Command Groups
The CLI provides 15 command groups for complete sandbox management:
| Command | Alias | Description |
| ---------- | ------ | ------------------------------ |
| `init` | - | First-run setup wizard |
| `auth` | - | Authentication management |
| `sandbox` | `sb` | Sandbox lifecycle management |
| `run` | - | Code execution |
| `files` | `f` | File operations |
| `cmd` | - | Shell commands |
| `env` | - | Environment variables |
| `terminal` | `term` | Interactive terminal sessions |
| `template` | `tpl` | Template management |
| `config` | - | Configuration management |
| `system` | - | Health checks and metrics |
| `org` | - | Organization settings |
| `profile` | - | User profile management |
| `members` | - | Organization member management |
| `billing` | - | Billing information |
| `usage` | - | Usage statistics |
## Quick Example
```bash theme={null}
# Install CLI
curl -fsSL https://raw.githubusercontent.com/hopx-ai/hopx/main/cli/scripts/install.sh | bash
# Authenticate
hopx auth login
# Create sandbox
hopx sandbox create --template python
# Execute code
hopx run "print('Hello, World!')"
```
## Features
### Authentication
* Browser-based OAuth login (Google, GitHub)
* API key management (create, list, revoke)
* Secure credential storage via system keyring
* Multi-profile support for different environments
### Output Formats
* **Table** (default) - Human-readable tables with borders
* **JSON** - Machine-readable JSON for scripting
* **Plain** - Minimal text output for piping
### Configuration
* YAML configuration file (`~/.hopx/config.yaml`)
* Environment variable support (`HOPX_*` prefix)
* Multiple profiles for dev/prod environments
* Config precedence: CLI flags > environment > config file > defaults
### Exit Codes
The CLI uses standardized exit codes for scripting automation:
| Code | Meaning |
| ---- | -------------------- |
| 0 | Success |
| 1 | General error |
| 2 | Validation error |
| 3 | Authentication error |
| 4 | Not found |
| 5 | Timeout |
| 6 | Network error |
| 7 | Rate limit |
| 130 | Interrupted (Ctrl+C) |
## Global Options
All commands support these global options:
```
--api-key TEXT API key (overrides HOPX_API_KEY)
--profile TEXT Configuration profile (default: "default")
--output, -o FORMAT Output format: table, json, plain
-q, --quiet Suppress non-essential output
-v, --verbose Increase output verbosity
--no-color Disable colored output
--version Show version and exit
--help Show help message
```
## Related
* **[CLI Installation](/cli/installation)** - Install the CLI
* **[CLI Quickstart](/cli/quickstart)** - Get started in 5 minutes
* **[Python SDK Overview](/sdk/python/introduction)** - Python SDK reference
* **[JavaScript SDK Overview](/sdk/javascript/introduction)** - JavaScript SDK reference
* **[API Overview](/api/introduction)** - REST API reference
## Next Steps
* Follow the [Installation Guide](/cli/installation) to install the CLI
* Complete the [Quickstart Guide](/cli/quickstart) to run your first command
* Explore [Command Reference](/cli/commands/sandbox) for detailed command documentation
# Quickstart
Source: https://docs.hopx.ai/cli/quickstart
Get started with the HopX CLI in 5 minutes. Learn how to install, authenticate, create your first sandbox, execute code, and manage files from the command line.
Get up and running with the HopX CLI in 5 minutes. This guide walks you through installation, authentication, creating your first sandbox, executing code, and managing files.
## What You'll Learn
In this quickstart, you'll learn how to:
* Install the HopX CLI
* Authenticate with your API key
* Create your first sandbox
* Execute code in multiple languages
* Manage files in sandboxes
* Clean up sandboxes
## Prerequisites
* [HopX API key](https://console.hopx.dev) (get one [here](/api-key) if you don't have it)
* Python 3.12+ installed
* Terminal access
## Step 1: Install the CLI
Install the CLI using the quick install script:
```bash theme={null}
curl -fsSL https://raw.githubusercontent.com/hopx-ai/hopx/main/cli/scripts/install.sh | bash
```
**Expected Output:**
```
✓ HopX CLI installed successfully
✓ Version: 0.1.2
✓ Run 'hopx init' to get started
```
Verify installation:
```bash theme={null}
hopx --version
```
**Expected Output:**
```
hopx-cli 0.1.2
```
## Step 2: Authenticate
### Option 1: Interactive Setup (Recommended)
Run the interactive setup wizard:
```bash theme={null}
hopx init
```
The wizard will:
1. Guide you through browser-based OAuth login
2. Help you create an API key
3. Configure default settings
4. Test your connection
### Option 2: Manual Authentication
Authenticate manually:
```bash theme={null}
# Browser login
hopx auth login
# Create API key
hopx auth keys create --name "my-key"
# Verify authentication
hopx auth status
```
**Expected Output:**
```
✓ Authenticated
✓ API key: hopx_live_... (configured)
```
### Option 3: Environment Variable
Set your API key as an environment variable:
```bash theme={null}
export HOPX_API_KEY="hopx_live_..."
```
Get your API key at [console.hopx.dev](https://console.hopx.dev).
## Step 3: Create Your First Sandbox
Create a sandbox from a pre-built template:
```bash theme={null}
hopx sandbox create --template python
```
**Expected Output:**
```
✓ Sandbox created: sb_abc123
✓ Status: running
✓ Template: python
```
List your sandboxes:
```bash theme={null}
hopx sandbox list
```
**Expected Output:**
```
┌──────────────────┬─────────┬────────────┐
│ ID │ Status │ Template │
├──────────────────┼─────────┼────────────┤
│ sb_abc123 │ running │ python │
└──────────────────┴─────────┴────────────┘
```
## Step 4: Execute Code
Execute Python code in your sandbox:
```bash theme={null}
hopx run "print('Hello, World!')"
```
**Expected Output:**
```
Hello, World!
```
Execute code from a file:
```bash theme={null}
# Create a local file
echo "print('Hello from file!')" > script.py
# Execute from file
hopx run -f script.py
```
**Expected Output:**
```
Hello from file!
```
Execute JavaScript:
```bash theme={null}
hopx run "console.log('Hello from JavaScript!')" -l javascript
```
**Expected Output:**
```
Hello from JavaScript!
```
Execute Bash:
```bash theme={null}
hopx run "echo 'Hello from Bash!'" -l bash
```
**Expected Output:**
```
Hello from Bash!
```
## Step 5: Manage Files
Write a file to your sandbox:
```bash theme={null}
hopx files write sb_abc123 /app/data.txt "Hello, World!"
```
**Expected Output:**
```
✓ File written: /app/data.txt
```
Read the file:
```bash theme={null}
hopx files read sb_abc123 /app/data.txt
```
**Expected Output:**
```
Hello, World!
```
List files in a directory:
```bash theme={null}
hopx files list sb_abc123 /app/
```
**Expected Output:**
```
┌──────────────┬──────┬─────────────────────┐
│ Name │ Size │ Modified │
├──────────────┼──────┼─────────────────────┤
│ data.txt │ 13 │ 2025-01-27 10:00:00 │
└──────────────┴──────┴─────────────────────┘
```
Upload a local file:
```bash theme={null}
# Create local file
echo "Local content" > local.txt
# Upload to sandbox
hopx files upload sb_abc123 ./local.txt /app/uploaded.txt
```
**Expected Output:**
```
✓ File uploaded: /app/uploaded.txt
```
Download a file:
```bash theme={null}
hopx files download sb_abc123 /app/data.txt ./downloaded.txt
```
**Expected Output:**
```
✓ File downloaded: ./downloaded.txt
```
## Step 6: Run Shell Commands
Run shell commands in your sandbox:
```bash theme={null}
hopx cmd run sb_abc123 "ls -la /app"
```
**Expected Output:**
```
total 16
drwxr-xr-x 2 user user 4096 Jan 27 10:00 .
drwxr-xr-x 3 user user 4096 Jan 27 10:00 ..
-rw-r--r-- 1 user user 13 Jan 27 10:00 data.txt
-rw-r--r-- 1 user user 14 Jan 27 10:00 uploaded.txt
```
Install packages:
```bash theme={null}
hopx cmd run sb_abc123 "pip install requests"
```
**Expected Output:**
```
Collecting requests
Downloading requests-2.31.0-py3-none-any.whl (62 kB)
...
Successfully installed requests-2.31.0
```
## Step 7: Manage Environment Variables
Set environment variables:
```bash theme={null}
hopx env set sb_abc123 API_KEY=secret123 DEBUG=true
```
**Expected Output:**
```
✓ Environment variables set
```
List environment variables:
```bash theme={null}
hopx env list sb_abc123
```
**Expected Output:**
```
┌───────────┬─────────────┐
│ Variable │ Value │
├───────────┼─────────────┤
│ API_KEY │ secret123 │
│ DEBUG │ true │
└───────────┴─────────────┘
```
Get a specific variable:
```bash theme={null}
hopx env get sb_abc123 API_KEY
```
**Expected Output:**
```
secret123
```
## Step 8: Clean Up
Kill your sandbox when done:
```bash theme={null}
hopx sandbox kill sb_abc123
```
**Expected Output:**
```
✓ Sandbox killed: sb_abc123
```
Or pause it to preserve state:
```bash theme={null}
hopx sandbox pause sb_abc123
```
**Expected Output:**
```
✓ Sandbox paused: sb_abc123
```
Resume later:
```bash theme={null}
hopx sandbox resume sb_abc123
```
**Expected Output:**
```
✓ Sandbox resumed: sb_abc123
```
## Next Steps
Now that you've completed the quickstart, explore more CLI features:
* **[Sandbox Management](/cli/commands/sandbox)** - Complete sandbox lifecycle management
* **[Code Execution](/cli/commands/run)** - Execute code in multiple languages
* **[File Operations](/cli/commands/files)** - Advanced file management
* **[Shell Commands](/cli/commands/cmd)** - Run system commands
* **[Environment Variables](/cli/commands/env)** - Manage environment configuration
* **[Templates](/cli/commands/template)** - List and build custom templates
* **[Configuration](/cli/commands/config)** - Configure CLI settings and profiles
## Related
* **[CLI Overview](/cli/introduction)** - Learn about CLI features
* **[CLI Installation](/cli/installation)** - Detailed installation guide
* **[Python SDK Quickstart](/sdk/python/quickstart)** - Get started with Python SDK
* **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Get started with JavaScript SDK
# Building an AI Code Interpreter Agent
Source: https://docs.hopx.ai/cookbooks/ai-integration/code-interpreter-agent
Create a secure AI code interpreter that safely executes AI-generated code with error handling, rich outputs, and security best practices
Build a production-ready AI code interpreter that safely executes AI-generated code in isolated sandboxes. This cookbook shows you how to create an agent that can execute code, capture rich outputs like plots and dataframes, handle errors gracefully, and maintain security.
## Overview
An AI code interpreter agent allows AI models to generate and execute code safely. This pattern is used by platforms like OpenAI's Code Interpreter and other AI agent systems. HopX provides the secure execution environment needed for this use case.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Basic understanding of async programming
* Familiarity with AI/LLM integration patterns
## Architecture
The AI code interpreter follows this architecture:
```
┌─────────────┐
│ AI Model │ Generates code
└──────┬──────┘
│
▼
┌─────────────────┐
│ Interpreter │ Validates & executes
│ Agent │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandbox │ Secure execution
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Rich Outputs │ Plots, DataFrames, etc.
└─────────────────┘
```
## Implementation
### Step 1: Basic Code Execution
Start with a simple code execution function that safely runs AI-generated code:
```python Python theme={null}
from hopx_ai import Sandbox
from hopx_ai.errors import HopxError, CodeExecutionError
import os
class AICodeInterpreter:
def __init__(self, api_key: str):
self.api_key = api_key
self.sandbox = None
def execute_code(self, code: str, language: str = "python", timeout: int = 30):
"""Execute AI-generated code safely"""
try:
# Create sandbox if needed
if not self.sandbox:
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=600
)
# Execute code with timeout
result = self.sandbox.run_code(
code,
language=language,
timeout=timeout
)
return {
"success": result.success,
"stdout": result.stdout,
"stderr": result.stderr,
"exit_code": result.exit_code,
"execution_time": result.execution_time
}
except CodeExecutionError as e:
return {
"success": False,
"error": f"Execution failed: {e.message}",
"stderr": str(e)
}
except Exception as e:
return {
"success": False,
"error": f"Unexpected error: {str(e)}"
}
def cleanup(self):
"""Clean up sandbox resources"""
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
# Usage
interpreter = AICodeInterpreter(api_key=os.getenv("HOPX_API_KEY"))
result = interpreter.execute_code("print('Hello from AI!')")
print(result)
interpreter.cleanup()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class AICodeInterpreter {
constructor(apiKey) {
this.apiKey = apiKey;
this.sandbox = null;
}
async executeCode(code, language = 'python', timeout = 30) {
try {
// Create sandbox if needed
if (!this.sandbox) {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: 600
});
}
// Execute code with timeout
const result = await this.sandbox.runCode(code, {
language,
timeout
});
return {
success: result.success,
stdout: result.stdout,
stderr: result.stderr,
exitCode: result.exit_code,
executionTime: result.execution_time
};
} catch (error) {
return {
success: false,
error: `Execution failed: ${error.message}`,
stderr: error.toString()
};
}
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
// Usage
const interpreter = new AICodeInterpreter(process.env.HOPX_API_KEY);
const result = await interpreter.executeCode("print('Hello from AI!')");
console.log(result);
await interpreter.cleanup();
```
### Step 2: Rich Output Capture
Capture plots, dataframes, and other rich outputs that AI models generate:
```python Python theme={null}
def execute_with_rich_outputs(self, code: str, language: str = "python"):
"""Execute code and capture rich outputs (plots, dataframes)"""
try:
if not self.sandbox:
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key
)
# Execute with rich output capture
result = self.sandbox.run_code(code, language=language)
rich_outputs = []
if result.rich_outputs:
for output in result.rich_outputs:
rich_outputs.append({
"type": output.type,
"data": output.data
})
return {
"success": result.success,
"stdout": result.stdout,
"stderr": result.stderr,
"rich_outputs": rich_outputs,
"rich_count": len(rich_outputs) if result.rich_outputs else 0
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
# Example: Generate plot
code = """
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.plot(x, y)
plt.title('Sine Wave')
plt.savefig('/tmp/plot.png')
plt.show()
"""
result = interpreter.execute_with_rich_outputs(code)
print(f"Captured {result['rich_count']} rich outputs")
```
```javascript JavaScript theme={null}
async executeWithRichOutputs(code, language = 'python') {
try {
if (!this.sandbox) {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey
});
}
// Execute with rich output capture
const result = await this.sandbox.runCode(code, {
language,
rich: true // Enable rich output capture
});
const richOutputs = [];
if (result.richOutputs) {
for (const output of result.richOutputs) {
richOutputs.push({
type: output.type,
data: output.data
});
}
}
return {
success: result.success,
stdout: result.stdout,
stderr: result.stderr,
richOutputs,
richCount: richOutputs.length
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
// Example: Generate plot
const code = `
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100);
y = np.sin(x);
plt.plot(x, y);
plt.title('Sine Wave');
plt.savefig('/tmp/plot.png');
plt.show();
`;
const result = await interpreter.executeWithRichOutputs(code);
console.log(`Captured ${result.richCount} rich outputs`);
```
### Step 3: Multi-Turn Conversation
Handle multi-turn conversations where the AI builds on previous execution results:
```python Python theme={null}
class MultiTurnInterpreter:
def __init__(self, api_key: str):
self.api_key = api_key
self.sandbox = None
self.conversation_history = []
def execute_turn(self, code: str, context: dict = None):
"""Execute code in conversation context"""
try:
if not self.sandbox:
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key
)
# Add context from previous turns
if context:
# Set environment variables from context
env_vars = context.get('env_vars', {})
if env_vars:
self.sandbox.env.set_all(env_vars)
# Upload files from context
files = context.get('files', {})
for path, content in files.items():
self.sandbox.files.write(path, content)
# Execute code
result = self.sandbox.run_code(code)
# Capture outputs for next turn
outputs = {
"stdout": result.stdout,
"stderr": result.stderr,
"files": {}
}
# List generated files
if result.success:
files_list = self.sandbox.files.list("/workspace")
for file in files_list:
if not file.is_dir:
outputs["files"][file.path] = self.sandbox.files.read(file.path)
# Store in history
self.conversation_history.append({
"code": code,
"result": outputs,
"success": result.success
})
return {
"success": result.success,
"outputs": outputs,
"history_length": len(self.conversation_history)
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def get_context_for_next_turn(self):
"""Get context to pass to next turn"""
if not self.conversation_history:
return {}
last_result = self.conversation_history[-1]["result"]
return {
"stdout": last_result["stdout"],
"files": last_result["files"],
"env_vars": self.sandbox.env.get_all() if self.sandbox else {}
}
# Usage: Multi-turn conversation
interpreter = MultiTurnInterpreter(api_key=os.getenv("HOPX_API_KEY"))
# Turn 1: Create data
result1 = interpreter.execute_turn("""
import pandas as pd
df = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]})
df.to_csv('/workspace/data.csv', index=False)
print("Data created")
""")
# Turn 2: Use previous data
context = interpreter.get_context_for_next_turn()
result2 = interpreter.execute_turn("""
import pandas as pd
df = pd.read_csv('/workspace/data.csv')
print(f"Data shape: {df.shape}")
print(df.describe())
""", context)
interpreter.sandbox.kill()
```
```javascript JavaScript theme={null}
class MultiTurnInterpreter {
constructor(apiKey) {
this.apiKey = apiKey;
this.sandbox = null;
this.conversationHistory = [];
}
async executeTurn(code, context = null) {
try {
if (!this.sandbox) {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey
});
}
// Add context from previous turns
if (context) {
// Set environment variables from context
const envVars = context.envVars || {};
if (Object.keys(envVars).length > 0) {
await this.sandbox.env.setAll(envVars);
}
// Upload files from context
const files = context.files || {};
for (const [path, content] of Object.entries(files)) {
await this.sandbox.files.write(path, content);
}
}
// Execute code
const result = await this.sandbox.runCode(code);
// Capture outputs for next turn
const outputs = {
stdout: result.stdout,
stderr: result.stderr,
files: {}
};
// List generated files
if (result.success) {
const filesList = await this.sandbox.files.list('/workspace');
for (const file of filesList) {
if (!file.isDir) {
outputs.files[file.path] = await this.sandbox.files.read(file.path);
}
}
}
// Store in history
this.conversationHistory.push({
code,
result: outputs,
success: result.success
});
return {
success: result.success,
outputs,
historyLength: this.conversationHistory.length
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
getContextForNextTurn() {
if (this.conversationHistory.length === 0) {
return {};
}
const lastResult = this.conversationHistory[this.conversationHistory.length - 1].result;
return {
stdout: lastResult.stdout,
files: lastResult.files,
envVars: {} // Would get from sandbox.env.getAll() if available
};
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
// Usage: Multi-turn conversation
const interpreter = new MultiTurnInterpreter(process.env.HOPX_API_KEY);
// Turn 1: Create data
const result1 = await interpreter.executeTurn(`
import pandas as pd
df = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]})
df.to_csv('/workspace/data.csv', index=False)
print("Data created")
`);
// Turn 2: Use previous data
const context = interpreter.getContextForNextTurn();
const result2 = await interpreter.executeTurn(`
import pandas as pd
df = pd.read_csv('/workspace/data.csv')
print(f"Data shape: {df.shape}")
print(df.describe())
`, context);
await interpreter.cleanup();
```
### Step 4: Error Handling and Validation
Implement robust error handling and code validation:
```python Python theme={null}
import re
from typing import Dict, Any
class SecureAICodeInterpreter:
def __init__(self, api_key: str):
self.api_key = api_key
self.sandbox = None
self.max_code_length = 100000 # 100KB limit
self.blocked_patterns = [
r'import\s+os\.system',
r'import\s+subprocess',
r'eval\s*\(',
r'exec\s*\(',
r'__import__',
r'open\s*\([^)]*[\'"]/etc',
]
def validate_code(self, code: str) -> Dict[str, Any]:
"""Validate code before execution"""
# Check length
if len(code) > self.max_code_length:
return {
"valid": False,
"error": f"Code exceeds maximum length of {self.max_code_length} characters"
}
# Check for blocked patterns
for pattern in self.blocked_patterns:
if re.search(pattern, code, re.IGNORECASE):
return {
"valid": False,
"error": f"Code contains blocked pattern: {pattern}"
}
return {"valid": True}
def execute_safely(self, code: str, timeout: int = 30):
"""Execute code with validation and error handling"""
# Validate code
validation = self.validate_code(code)
if not validation["valid"]:
return {
"success": False,
"error": validation["error"],
"validation_failed": True
}
try:
if not self.sandbox:
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=600
)
# Execute with timeout
result = self.sandbox.run_code(code, timeout=timeout)
# Check for suspicious output
if result.stderr and any(keyword in result.stderr.lower()
for keyword in ['permission denied', 'access denied', 'unauthorized']):
return {
"success": False,
"error": "Security violation detected in execution",
"stderr": result.stderr
}
return {
"success": result.success,
"stdout": result.stdout,
"stderr": result.stderr,
"exit_code": result.exit_code
}
except Exception as e:
return {
"success": False,
"error": f"Execution error: {str(e)}"
}
def cleanup(self):
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
# Usage
interpreter = SecureAICodeInterpreter(api_key=os.getenv("HOPX_API_KEY"))
# This will be blocked
result = interpreter.execute_safely("import subprocess; subprocess.call(['rm', '-rf', '/'])")
print(result) # {"success": False, "error": "Code contains blocked pattern...", "validation_failed": True}
# This will execute
result = interpreter.execute_safely("print('Hello, safe code!')")
print(result)
interpreter.cleanup()
```
```javascript JavaScript theme={null}
class SecureAICodeInterpreter {
constructor(apiKey) {
this.apiKey = apiKey;
this.sandbox = null;
this.maxCodeLength = 100000; // 100KB limit
this.blockedPatterns = [
/import\s+os\.system/i,
/import\s+subprocess/i,
/eval\s*\(/i,
/exec\s*\(/i,
/__import__/i,
/open\s*\([^)]*['"]\/etc/i
];
}
validateCode(code) {
// Check length
if (code.length > this.maxCodeLength) {
return {
valid: false,
error: `Code exceeds maximum length of ${this.maxCodeLength} characters`
};
}
// Check for blocked patterns
for (const pattern of this.blockedPatterns) {
if (pattern.test(code)) {
return {
valid: false,
error: `Code contains blocked pattern: ${pattern}`
};
}
}
return { valid: true };
}
async executeSafely(code, timeout = 30) {
// Validate code
const validation = this.validateCode(code);
if (!validation.valid) {
return {
success: false,
error: validation.error,
validationFailed: true
};
}
try {
if (!this.sandbox) {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: 600
});
}
// Execute with timeout
const result = await this.sandbox.runCode(code, { timeout });
// Check for suspicious output
if (result.stderr && /permission denied|access denied|unauthorized/i.test(result.stderr)) {
return {
success: false,
error: 'Security violation detected in execution',
stderr: result.stderr
};
}
return {
success: result.success,
stdout: result.stdout,
stderr: result.stderr,
exitCode: result.exit_code
};
} catch (error) {
return {
success: false,
error: `Execution error: ${error.message}`
};
}
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
// Usage
const interpreter = new SecureAICodeInterpreter(process.env.HOPX_API_KEY);
// This will be blocked
const result1 = await interpreter.executeSafely("import subprocess; subprocess.call(['rm', '-rf', '/'])");
console.log(result1); // {success: false, error: "Code contains blocked pattern...", validationFailed: true}
// This will execute
const result2 = await interpreter.executeSafely("print('Hello, safe code!')");
console.log(result2);
await interpreter.cleanup();
```
## Best Practices
### Security
Always validate AI-generated code before execution. Never trust user input or AI output without validation.
1. **Code Validation**: Check for dangerous patterns before execution
2. **Resource Limits**: Set appropriate timeouts and memory limits
3. **Sandbox Isolation**: Each execution should be in a fresh or properly isolated sandbox
4. **Output Sanitization**: Validate outputs before returning to users
### Performance
Reuse sandboxes for multi-turn conversations to maintain state, but create fresh sandboxes for unrelated executions to ensure isolation.
1. **Sandbox Reuse**: Reuse sandboxes within a conversation session
2. **Timeout Management**: Set appropriate timeouts based on expected execution time
3. **Parallel Execution**: Use background execution for long-running tasks
4. **Caching**: Cache environment variables and common setup code
### Error Handling
1. **Graceful Degradation**: Always return structured error responses
2. **Error Logging**: Log errors with context for debugging
3. **User-Friendly Messages**: Transform technical errors into user-friendly messages
4. **Retry Logic**: Implement retry for transient failures
## Real-World Examples
This pattern is used by:
* **OpenAI Code Interpreter**: Executes Python code in isolated environments
* **AI Agent Platforms**: Various platforms that execute code generated by AI models
* **LangChain Code Execution**: Agent frameworks that execute code
## Related Cookbooks
* [Multi-Agent Execution](/cookbooks/ai-integration/multi-agent-execution) - Multi-agent workflows
* [Rich Output Capture](/core-concepts/code-execution/rich-output) - Handling plots and dataframes
## Next Steps
1. Implement code validation based on your security requirements
2. Add rich output handling for your specific use case
3. Integrate with your AI model API
4. Set up monitoring and logging
5. Test with various code scenarios
# Multi-Agent Code Execution Workflow
Source: https://docs.hopx.ai/cookbooks/ai-integration/multi-agent-execution
Coordinate multiple AI agents with code execution, parallel execution, result aggregation, and error recovery patterns
Build a production-ready multi-agent system where multiple AI agents coordinate to execute code, share results, and recover from errors. This cookbook demonstrates how to orchestrate multiple agents using HopX for secure code execution.
## Overview
Multi-agent systems coordinate multiple AI agents to solve complex problems. Each agent can execute code, share results with other agents, and the system aggregates outcomes. This pattern is used in advanced AI systems where agents collaborate on tasks.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of async programming
* Basic knowledge of agent orchestration patterns
## Architecture
```
┌──────────────┐
│ Orchestrator │ Coordinates agents
└──────┬───────┘
│
├──► Agent 1 ──► Sandbox 1
├──► Agent 2 ──► Sandbox 2
└──► Agent 3 ──► Sandbox 3
│
▼
┌──────────────┐
│ Aggregator │ Combine results
└──────────────┘
```
## Implementation
### Step 1: Basic Multi-Agent System
Create a system that coordinates multiple agents:
```python Python theme={null}
from hopx_ai import Sandbox
import os
import asyncio
from typing import Dict, List, Any
from concurrent.futures import ThreadPoolExecutor
class Agent:
def __init__(self, agent_id: str, api_key: str):
self.agent_id = agent_id
self.api_key = api_key
self.sandbox = None
def initialize(self):
"""Initialize agent sandbox"""
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=600
)
def execute_task(self, task_code: str, context: Dict = None) -> Dict[str, Any]:
"""Execute task assigned to this agent"""
try:
# Set context if provided
if context:
for key, value in context.items():
self.sandbox.env.set(key, str(value))
# Execute task
result = self.sandbox.run_code(task_code, timeout=30)
return {
"agent_id": self.agent_id,
"success": result.success,
"stdout": result.stdout,
"stderr": result.stderr,
"execution_time": result.execution_time
}
except Exception as e:
return {
"agent_id": self.agent_id,
"success": False,
"error": str(e)
}
def cleanup(self):
"""Clean up agent resources"""
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
class MultiAgentOrchestrator:
def __init__(self, api_key: str, num_agents: int = 3):
self.api_key = api_key
self.agents = [
Agent(f"agent_{i}", api_key)
for i in range(num_agents)
]
def initialize_agents(self):
"""Initialize all agents"""
for agent in self.agents:
agent.initialize()
def execute_parallel_tasks(self, tasks: List[Dict]) -> List[Dict[str, Any]]:
"""Execute tasks in parallel across agents"""
results = []
with ThreadPoolExecutor(max_workers=len(self.agents)) as executor:
# Assign tasks to agents
future_to_agent = {}
for i, task in enumerate(tasks):
agent = self.agents[i % len(self.agents)]
future = executor.submit(agent.execute_task, task["code"], task.get("context"))
future_to_agent[future] = (agent, task)
# Collect results
for future in future_to_agent:
agent, task = future_to_agent[future]
try:
result = future.result()
results.append(result)
except Exception as e:
results.append({
"agent_id": agent.agent_id,
"success": False,
"error": str(e)
})
return results
def cleanup_all(self):
"""Clean up all agents"""
for agent in self.agents:
agent.cleanup()
# Usage
orchestrator = MultiAgentOrchestrator(api_key=os.getenv("HOPX_API_KEY"), num_agents=3)
orchestrator.initialize_agents()
tasks = [
{"code": "result = 2 + 2\nprint(f'Result: {result}')", "context": None},
{"code": "result = 3 * 4\nprint(f'Result: {result}')", "context": None},
{"code": "result = 10 / 2\nprint(f'Result: {result}')", "context": None}
]
results = orchestrator.execute_parallel_tasks(tasks)
for result in results:
print(f"Agent {result['agent_id']}: {result.get('stdout', result.get('error'))}")
orchestrator.cleanup_all()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class Agent {
constructor(agentId, apiKey) {
this.agentId = agentId;
this.apiKey = apiKey;
this.sandbox = null;
}
async initialize() {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: 600
});
}
async executeTask(taskCode, context = null) {
try {
// Set context if provided
if (context) {
for (const [key, value] of Object.entries(context)) {
await this.sandbox.env.set(key, String(value));
}
}
// Execute task
const result = await this.sandbox.runCode(taskCode, { timeout: 30 });
return {
agentId: this.agentId,
success: result.success,
stdout: result.stdout,
stderr: result.stderr,
executionTime: result.execution_time
};
} catch (error) {
return {
agentId: this.agentId,
success: false,
error: error.message
};
}
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
class MultiAgentOrchestrator {
constructor(apiKey, numAgents = 3) {
this.apiKey = apiKey;
this.agents = Array.from({ length: numAgents }, (_, i) =>
new Agent(`agent_${i}`, apiKey)
);
}
async initializeAgents() {
await Promise.all(this.agents.map(agent => agent.initialize()));
}
async executeParallelTasks(tasks) {
const results = [];
// Execute tasks in parallel
const promises = tasks.map(async (task, index) => {
const agent = this.agents[index % this.agents.length];
return await agent.executeTask(task.code, task.context);
});
const taskResults = await Promise.all(promises);
results.push(...taskResults);
return results;
}
async cleanupAll() {
await Promise.all(this.agents.map(agent => agent.cleanup()));
}
}
// Usage
const orchestrator = new MultiAgentOrchestrator(process.env.HOPX_API_KEY, 3);
await orchestrator.initializeAgents();
const tasks = [
{ code: "result = 2 + 2\nprint(f'Result: {result}')", context: null },
{ code: "result = 3 * 4\nprint(f'Result: {result}')", context: null },
{ code: "result = 10 / 2\nprint(f'Result: {result}')", context: null }
];
const results = await orchestrator.executeParallelTasks(tasks);
for (const result of results) {
console.log(`Agent ${result.agentId}: ${result.stdout || result.error}`);
}
await orchestrator.cleanupAll();
```
### Step 2: Result Aggregation
Aggregate results from multiple agents:
```python Python theme={null}
class ResultAggregator:
def __init__(self):
self.results = []
def add_result(self, result: Dict[str, Any]):
"""Add agent result"""
self.results.append(result)
def aggregate(self) -> Dict[str, Any]:
"""Aggregate all results"""
total = len(self.results)
successful = sum(1 for r in self.results if r.get("success", False))
failed = total - successful
# Extract outputs
outputs = [r.get("stdout", "") for r in self.results if r.get("success")]
# Calculate average execution time
execution_times = [
r.get("execution_time", 0)
for r in self.results
if "execution_time" in r
]
avg_time = sum(execution_times) / len(execution_times) if execution_times else 0
return {
"total_agents": total,
"successful": successful,
"failed": failed,
"success_rate": (successful / total * 100) if total > 0 else 0,
"average_execution_time": avg_time,
"outputs": outputs,
"all_results": self.results
}
# Usage with orchestrator
orchestrator = MultiAgentOrchestrator(api_key=os.getenv("HOPX_API_KEY"), num_agents=3)
orchestrator.initialize_agents()
tasks = [
{"code": "print('Agent 1 result: 10')"},
{"code": "print('Agent 2 result: 20')"},
{"code": "print('Agent 3 result: 30')"}
]
results = orchestrator.execute_parallel_tasks(tasks)
aggregator = ResultAggregator()
for result in results:
aggregator.add_result(result)
summary = aggregator.aggregate()
print(f"Success rate: {summary['success_rate']:.1f}%")
print(f"Average execution time: {summary['average_execution_time']:.2f}s")
orchestrator.cleanup_all()
```
```javascript JavaScript theme={null}
class ResultAggregator {
constructor() {
this.results = [];
}
addResult(result) {
this.results.push(result);
}
aggregate() {
const total = this.results.length;
const successful = this.results.filter(r => r.success).length;
const failed = total - successful;
// Extract outputs
const outputs = this.results
.filter(r => r.success)
.map(r => r.stdout || '');
// Calculate average execution time
const executionTimes = this.results
.map(r => r.executionTime || 0)
.filter(t => t > 0);
const avgTime = executionTimes.length > 0
? executionTimes.reduce((a, b) => a + b, 0) / executionTimes.length
: 0;
return {
totalAgents: total,
successful,
failed,
successRate: total > 0 ? (successful / total * 100) : 0,
averageExecutionTime: avgTime,
outputs,
allResults: this.results
};
}
}
// Usage with orchestrator
const orchestrator = new MultiAgentOrchestrator(process.env.HOPX_API_KEY, 3);
await orchestrator.initializeAgents();
const tasks = [
{ code: "print('Agent 1 result: 10')" },
{ code: "print('Agent 2 result: 20')" },
{ code: "print('Agent 3 result: 30')" }
];
const results = await orchestrator.executeParallelTasks(tasks);
const aggregator = new ResultAggregator();
for (const result of results) {
aggregator.addResult(result);
}
const summary = aggregator.aggregate();
console.log(`Success rate: ${summary.successRate.toFixed(1)}%`);
console.log(`Average execution time: ${summary.averageExecutionTime.toFixed(2)}s`);
await orchestrator.cleanupAll();
```
### Step 3: Error Recovery Patterns
Implement error recovery for failed agents:
```python Python theme={null}
class ResilientMultiAgentOrchestrator(MultiAgentOrchestrator):
def execute_with_retry(self, task: Dict, max_retries: int = 3) -> Dict[str, Any]:
"""Execute task with retry logic"""
agent = self.agents[0] # Use first available agent
for attempt in range(max_retries):
result = agent.execute_task(task["code"], task.get("context"))
if result.get("success"):
return result
# Wait before retry
import time
time.sleep(1)
return {
"agent_id": agent.agent_id,
"success": False,
"error": f"Failed after {max_retries} attempts"
}
def execute_with_fallback(self, tasks: List[Dict]) -> List[Dict[str, Any]]:
"""Execute tasks with fallback agents"""
results = []
for task in tasks:
# Try primary agent
primary_result = self.agents[0].execute_task(task["code"], task.get("context"))
if primary_result.get("success"):
results.append(primary_result)
else:
# Fallback to secondary agent
fallback_result = self.agents[1].execute_task(task["code"], task.get("context"))
results.append({
**fallback_result,
"used_fallback": True,
"primary_failed": True
})
return results
# Usage
orchestrator = ResilientMultiAgentOrchestrator(api_key=os.getenv("HOPX_API_KEY"), num_agents=3)
orchestrator.initialize_agents()
# Task that might fail
task = {"code": "result = 1 / 0\nprint(result)"} # Will fail
# Execute with retry
result = orchestrator.execute_with_retry(task, max_retries=3)
print(f"Result after retry: {result}")
orchestrator.cleanup_all()
```
```javascript JavaScript theme={null}
class ResilientMultiAgentOrchestrator extends MultiAgentOrchestrator {
async executeWithRetry(task, maxRetries = 3) {
const agent = this.agents[0]; // Use first available agent
for (let attempt = 0; attempt < maxRetries; attempt++) {
const result = await agent.executeTask(task.code, task.context);
if (result.success) {
return result;
}
// Wait before retry
await new Promise(resolve => setTimeout(resolve, 1000));
}
return {
agentId: agent.agentId,
success: false,
error: `Failed after ${maxRetries} attempts`
};
}
async executeWithFallback(tasks) {
const results = [];
for (const task of tasks) {
// Try primary agent
const primaryResult = await this.agents[0].executeTask(task.code, task.context);
if (primaryResult.success) {
results.push(primaryResult);
} else {
// Fallback to secondary agent
const fallbackResult = await this.agents[1].executeTask(task.code, task.context);
results.push({
...fallbackResult,
usedFallback: true,
primaryFailed: true
});
}
}
return results;
}
}
// Usage
const orchestrator = new ResilientMultiAgentOrchestrator(process.env.HOPX_API_KEY, 3);
await orchestrator.initializeAgents();
// Task that might fail
const task = { code: "result = 1 / 0\nprint(result)" }; // Will fail
// Execute with retry
const result = await orchestrator.executeWithRetry(task, 3);
console.log(`Result after retry: ${JSON.stringify(result)}`);
await orchestrator.cleanupAll();
```
## Best Practices
### Coordination
Use a message queue or shared state system for agents to communicate results and coordinate tasks.
1. **Task Distribution**: Distribute tasks evenly across agents
2. **State Sharing**: Share necessary state between agents
3. **Result Aggregation**: Aggregate results efficiently
4. **Error Handling**: Handle agent failures gracefully
### Performance
1. **Parallel Execution**: Execute independent tasks in parallel
2. **Resource Management**: Monitor and limit resource usage
3. **Caching**: Cache common results between agents
4. **Load Balancing**: Balance load across agents
### Reliability
1. **Retry Logic**: Implement retry for transient failures
2. **Fallback Agents**: Use fallback agents when primary fails
3. **Health Checks**: Monitor agent health
4. **Graceful Degradation**: Continue with available agents
## Real-World Examples
This pattern is used by:
* **AutoGPT**: Multi-agent AI system
* **LangChain Multi-Agent**: Agent orchestration framework
* **CrewAI**: Multi-agent orchestration platform
## Related Cookbooks
* [AI Code Interpreter Agent](/cookbooks/ai-integration/code-interpreter-agent) - Single agent execution
## Next Steps
1. Implement agent communication protocol
2. Add task queue for agent coordination
3. Create agent health monitoring
4. Implement dynamic agent scaling
5. Add result persistence
# API Testing Automation Platform
Source: https://docs.hopx.ai/cookbooks/automation/api-testing-platform
Build a Postman-style API testing platform with test script execution, environment management, assertion frameworks, and test reporting
Build a production-ready API testing automation platform that executes test scripts, manages environments, validates responses, and generates reports. This cookbook demonstrates how to create a platform similar to Postman or Insomnia using HopX.
## Overview
API testing platforms allow developers to write, execute, and manage API tests. The platform executes test scripts, manages test environments, validates responses with assertions, and generates comprehensive test reports. HopX provides the secure execution environment needed for this use case.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of REST APIs
* Basic knowledge of test frameworks
## Architecture
```
┌──────────────┐
│ Test Script │ API test definition
└──────┬───────┘
│
▼
┌─────────────────┐
│ Test Runner │ Execute, validate
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandbox │ Secure execution
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Test Report │ Results & metrics
└─────────────────┘
```
## Implementation
### Step 1: Basic API Test Execution
Execute API test scripts:
```python Python theme={null}
from hopx_ai import Sandbox
import os
import json
from typing import Dict, Any
class APITestRunner:
def __init__(self, api_key: str):
self.api_key = api_key
self.sandbox = None
def initialize(self):
"""Initialize test sandbox"""
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=600
)
# Install requests library
self.sandbox.commands.run("pip install requests", timeout=30)
def run_test(self, test_code: str, env_vars: Dict[str, str] = None) -> Dict[str, Any]:
"""Execute API test"""
try:
# Set environment variables
if env_vars:
self.sandbox.env.set_all(env_vars)
# Execute test
result = self.sandbox.run_code(test_code, timeout=30)
# Parse test results
test_results = self._parse_test_results(result.stdout)
return {
"success": result.success and test_results.get("all_passed", False),
"stdout": result.stdout,
"stderr": result.stderr,
"test_results": test_results,
"execution_time": result.execution_time
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def _parse_test_results(self, output: str) -> Dict[str, Any]:
"""Parse test output"""
# Simple parsing - in production, use proper test framework
passed = output.count("PASS") or output.count("✓")
failed = output.count("FAIL") or output.count("✗")
return {
"all_passed": failed == 0 and passed > 0,
"passed": passed,
"failed": failed
}
def cleanup(self):
"""Clean up test resources"""
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
# Usage
runner = APITestRunner(api_key=os.getenv("HOPX_API_KEY"))
runner.initialize()
test_code = """
import requests
import json
# Test GET endpoint
response = requests.get('https://jsonplaceholder.typicode.com/posts/1')
assert response.status_code == 200, f"Expected 200, got {response.status_code}"
data = response.json()
assert 'userId' in data, "Missing userId field"
print("PASS: GET test")
"""
result = runner.run_test(test_code)
print(json.dumps(result, indent=2))
runner.cleanup()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class APITestRunner {
constructor(apiKey) {
this.apiKey = apiKey;
this.sandbox = null;
}
async initialize() {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: 600
});
// Install axios
await this.sandbox.commands.run('npm install axios', { timeout: 30 });
}
async runTest(testCode, envVars = null) {
try {
// Set environment variables
if (envVars) {
await this.sandbox.env.setAll(envVars);
}
// Execute test
const result = await this.sandbox.runCode(testCode, { timeout: 30 });
// Parse test results
const testResults = this.parseTestResults(result.stdout);
return {
success: result.success && testResults.allPassed,
stdout: result.stdout,
stderr: result.stderr,
testResults,
executionTime: result.execution_time
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
parseTestResults(output) {
const passed = (output.match(/PASS/g) || []).length || (output.match(/✓/g) || []).length;
const failed = (output.match(/FAIL/g) || []).length || (output.match(/✗/g) || []).length;
return {
allPassed: failed === 0 && passed > 0,
passed,
failed
};
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
// Usage
const runner = new APITestRunner(process.env.HOPX_API_KEY);
await runner.initialize();
const testCode = `
const axios = require('axios');
// Test GET endpoint
const response = await axios.get('https://jsonplaceholder.typicode.com/posts/1');
if (response.status !== 200) {
throw new Error(\`Expected 200, got \${response.status}\`);
}
if (!response.data.userId) {
throw new Error('Missing userId field');
}
console.log('PASS: GET test');
`;
const result = await runner.runTest(testCode);
console.log(JSON.stringify(result, null, 2));
await runner.cleanup();
```
### Step 2: Environment Management
Manage test environments:
```python Python theme={null}
class EnvironmentManager:
def __init__(self, sandbox: Sandbox):
self.sandbox = sandbox
self.environments = {}
def create_environment(self, env_name: str, variables: Dict[str, str]):
"""Create test environment"""
self.environments[env_name] = variables
def use_environment(self, env_name: str):
"""Use environment for tests"""
if env_name in self.environments:
self.sandbox.env.set_all(self.environments[env_name])
return True
return False
# Usage
sandbox = Sandbox.create(template="code-interpreter", api_key=os.getenv("HOPX_API_KEY"))
env_manager = EnvironmentManager(sandbox)
env_manager.create_environment("production", {
"API_URL": "https://api.example.com",
"API_KEY": "prod-key-123"
})
env_manager.create_environment("staging", {
"API_URL": "https://staging-api.example.com",
"API_KEY": "staging-key-456"
})
env_manager.use_environment("production")
sandbox.kill()
```
```javascript JavaScript theme={null}
class EnvironmentManager {
constructor(sandbox) {
this.sandbox = sandbox;
this.environments = {};
}
createEnvironment(envName, variables) {
this.environments[envName] = variables;
}
async useEnvironment(envName) {
if (this.environments[envName]) {
await this.sandbox.env.setAll(this.environments[envName]);
return true;
}
return false;
}
}
// Usage
const sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: process.env.HOPX_API_KEY
});
const envManager = new EnvironmentManager(sandbox);
envManager.createEnvironment('production', {
API_URL: 'https://api.example.com',
API_KEY: 'prod-key-123'
});
envManager.createEnvironment('staging', {
API_URL: 'https://staging-api.example.com',
API_KEY: 'staging-key-456'
});
await envManager.useEnvironment('production');
await sandbox.kill();
```
## Best Practices
1. **Test Isolation**: Each test should be independent
2. **Environment Management**: Use separate environments for different stages
3. **Assertion Framework**: Use proper assertion libraries
4. **Test Reporting**: Generate comprehensive test reports
## Related Cookbooks
* [Isolated Test Execution](/cookbooks/testing/isolated-test-execution) - Test isolation
* [Web Scraping Service](/cookbooks/automation/web-scraping-service) - Automation workflows
## Next Steps
1. Implement test collection management
2. Add support for multiple HTTP methods
3. Create test result visualization
4. Implement test scheduling
5. Add API mocking support
# Web Scraping Service
Source: https://docs.hopx.ai/cookbooks/automation/web-scraping-service
Build a browser automation and scraping service with desktop features, screenshot capture, data extraction workflows, and rate limiting
Build a production-ready web scraping service that automates browsers, captures screenshots, extracts data, and handles rate limiting. This cookbook demonstrates how to create a scraping service using HopX's desktop automation features.
## Overview
Web scraping services automate browser interactions to extract data from websites. The service uses browser automation, captures screenshots, records interactions, and implements ethical scraping practices with rate limiting.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of web scraping
* Basic knowledge of browser automation
## Architecture
```
┌──────────────┐
│ Scraping │ Define targets
│ Request │
└──────┬───────┘
│
▼
┌─────────────────┐
│ Scraping │ Navigate, extract
│ Service │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Desktop │ Browser automation
│ Sandbox │
└─────────────────┘
```
## Implementation
### Step 1: Basic Web Scraping
Scrape websites using code execution:
```python Python theme={null}
from hopx_ai import Sandbox
import os
from typing import Dict, Any
class WebScrapingService:
def __init__(self, api_key: str):
self.api_key = api_key
self.sandbox = None
def initialize(self):
"""Initialize scraping sandbox"""
self.sandbox = Sandbox.create(
template="desktop", # Desktop template for browser automation
api_key=self.api_key,
timeout_seconds=600
)
# Install scraping libraries
self.sandbox.commands.run("pip install requests beautifulsoup4", timeout=60)
def scrape_url(self, url: str, selector: str = None) -> Dict[str, Any]:
"""Scrape data from URL"""
try:
scraping_code = f"""
import requests
from bs4 import BeautifulSoup
response = requests.get('{url}')
soup = BeautifulSoup(response.content, 'html.parser')
if '{selector}':
elements = soup.select('{selector}')
data = [elem.get_text() for elem in elements]
else:
data = soup.get_text()
print(data)
"""
result = self.sandbox.run_code(scraping_code, timeout=30)
return {
"success": result.success,
"data": result.stdout,
"url": url
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def take_screenshot(self, url: str) -> Dict[str, Any]:
"""Take screenshot of webpage"""
try:
# Navigate to URL (would use desktop automation)
# For now, use code execution
code = f"""
import requests
response = requests.get('{url}')
print(f"Page loaded: {{len(response.content)}} bytes")
"""
result = self.sandbox.run_code(code, timeout=30)
# Take screenshot using desktop features
screenshot = self.sandbox.desktop.screenshot()
return {
"success": True,
"screenshot_size": len(screenshot),
"url": url
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def cleanup(self):
"""Clean up scraping resources"""
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
# Usage
service = WebScrapingService(api_key=os.getenv("HOPX_API_KEY"))
service.initialize()
result = service.scrape_url("https://example.com", selector="h1")
print(result)
service.cleanup()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class WebScrapingService {
constructor(apiKey) {
this.apiKey = apiKey;
this.sandbox = null;
}
async initialize() {
this.sandbox = await Sandbox.create({
template: 'desktop', // Desktop template for browser automation
apiKey: this.apiKey,
timeoutSeconds: 600
});
// Install scraping libraries
await this.sandbox.commands.run('pip install requests beautifulsoup4', { timeout: 60 });
}
async scrapeUrl(url, selector = null) {
try {
const scrapingCode = `
import requests
from bs4 import BeautifulSoup
response = requests.get('${url}')
soup = BeautifulSoup(response.content, 'html.parser')
if '${selector}':
elements = soup.select('${selector}')
data = [elem.get_text() for elem in elements]
else:
data = soup.get_text()
print(data)
`;
const result = await this.sandbox.runCode(scrapingCode, { timeout: 30 });
return {
success: result.success,
data: result.stdout,
url
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
async takeScreenshot(url) {
try {
// Navigate to URL
const code = `
import requests
response = requests.get('${url}')
print(f"Page loaded: {len(response.content)} bytes")
`;
const result = await this.sandbox.runCode(code, { timeout: 30 });
// Take screenshot using desktop features
const screenshot = await this.sandbox.desktop.screenshot();
return {
success: true,
screenshotSize: screenshot.length,
url
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
// Usage
const service = new WebScrapingService(process.env.HOPX_API_KEY);
await service.initialize();
const result = await service.scrapeUrl('https://example.com', 'h1');
console.log(result);
await service.cleanup();
```
## Best Practices
Always respect robots.txt, implement rate limiting, and follow website terms of service when scraping.
1. **Rate Limiting**: Implement delays between requests
2. **Respect robots.txt**: Check and follow robots.txt rules
3. **Error Handling**: Handle network errors gracefully
4. **Data Extraction**: Use proper selectors and parsing
## Related Cookbooks
* [API Testing Platform](/cookbooks/automation/api-testing-platform) - Testing automation
## Next Steps
1. Implement browser automation with desktop features
2. Add screenshot and recording capabilities
3. Create data extraction workflows
4. Implement rate limiting and ethics
5. Add proxy support
# Data Analysis Pipeline Service
Source: https://docs.hopx.ai/cookbooks/data-science/analysis-pipeline
Build automated data analysis services with multi-step workflows, data transformation chains, result export, and scheduled jobs
Build a production-ready data analysis pipeline service that processes data through multiple steps, transforms it, and exports results. This cookbook demonstrates how to create automated analysis workflows using HopX.
## Overview
Data analysis pipelines automate the process of ingesting, transforming, analyzing, and exporting data. The service executes multi-step workflows, handles data transformations, and generates reports. This pattern is used in data processing platforms and analytics services.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of data pipelines
* Basic knowledge of data transformation
## Architecture
```
┌──────────────┐
│ Data Input │ Raw data
└──────┬───────┘
│
▼
┌─────────────────┐
│ Pipeline │ Step 1 → Step 2 → Step 3
│ Engine │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandbox │ Execute each step
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Results Export │ Reports, visualizations
└─────────────────┘
```
## Implementation
### Step 1: Pipeline Definition
Define and execute multi-step pipelines:
```python Python theme={null}
from hopx_ai import Sandbox
import os
from typing import Dict, List, Any
class PipelineStep:
def __init__(self, step_id: str, code: str, dependencies: List[str] = None):
self.step_id = step_id
self.code = code
self.dependencies = dependencies or []
class DataAnalysisPipeline:
def __init__(self, api_key: str):
self.api_key = api_key
self.sandbox = None
self.steps = []
def initialize(self):
"""Initialize pipeline sandbox"""
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=3600
)
def add_step(self, step: PipelineStep):
"""Add pipeline step"""
self.steps.append(step)
def execute_pipeline(self, input_data: str = None) -> Dict[str, Any]:
"""Execute entire pipeline"""
results = []
# Upload input data if provided
if input_data:
self.sandbox.files.write("/workspace/input.csv", input_data)
# Execute steps in order
for step in self.steps:
result = self.sandbox.run_code(step.code, timeout=60)
results.append({
"step_id": step.step_id,
"success": result.success,
"stdout": result.stdout,
"stderr": result.stderr
})
if not result.success:
break # Stop on failure
# Export results
export_result = self._export_results()
return {
"success": all(r["success"] for r in results),
"steps_executed": len(results),
"step_results": results,
"export": export_result
}
def _export_results(self) -> Dict[str, Any]:
"""Export pipeline results"""
try:
# Check for output files
files = self.sandbox.files.list("/workspace")
output_files = [f for f in files if f.name.endswith(('.csv', '.json', '.png'))]
exports = {}
for file in output_files:
content = self.sandbox.files.read(file.path)
exports[file.name] = {
"size": len(content),
"type": file.name.split('.')[-1]
}
return {
"success": True,
"files": exports
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def cleanup(self):
"""Clean up pipeline resources"""
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
# Usage
pipeline = DataAnalysisPipeline(api_key=os.getenv("HOPX_API_KEY"))
pipeline.initialize()
# Define pipeline steps
pipeline.add_step(PipelineStep(
step_id="load_data",
code="""
import pandas as pd
df = pd.read_csv('/workspace/input.csv')
print(f"Loaded {len(df)} rows")
"""
))
pipeline.add_step(PipelineStep(
step_id="analyze",
code="""
import pandas as pd
df = pd.read_csv('/workspace/input.csv')
summary = df.describe()
summary.to_csv('/workspace/summary.csv')
print("Analysis complete")
"""
))
# Execute
result = pipeline.execute_pipeline(input_data="name,age\nAlice,25\nBob,30")
print(result)
pipeline.cleanup()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class PipelineStep {
constructor(stepId, code, dependencies = []) {
this.stepId = stepId;
this.code = code;
this.dependencies = dependencies;
}
}
class DataAnalysisPipeline {
constructor(apiKey) {
this.apiKey = apiKey;
this.sandbox = null;
this.steps = [];
}
async initialize() {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: 3600
});
}
addStep(step) {
this.steps.push(step);
}
async executePipeline(inputData = null) {
const results = [];
// Upload input data if provided
if (inputData) {
await this.sandbox.files.write('/workspace/input.csv', inputData);
}
// Execute steps in order
for (const step of this.steps) {
const result = await this.sandbox.runCode(step.code, { timeout: 60 });
results.push({
stepId: step.stepId,
success: result.success,
stdout: result.stdout,
stderr: result.stderr
});
if (!result.success) {
break; // Stop on failure
}
}
// Export results
const exportResult = await this.exportResults();
return {
success: results.every(r => r.success),
stepsExecuted: results.length,
stepResults: results,
export: exportResult
};
}
async exportResults() {
try {
// Check for output files
const files = await this.sandbox.files.list('/workspace');
const outputFiles = files.filter(f =>
f.name.endsWith('.csv') ||
f.name.endsWith('.json') ||
f.name.endsWith('.png')
);
const exports = {};
for (const file of outputFiles) {
const content = await this.sandbox.files.read(file.path);
exports[file.name] = {
size: content.length,
type: file.name.split('.').pop()
};
}
return {
success: true,
files: exports
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
// Usage
const pipeline = new DataAnalysisPipeline(process.env.HOPX_API_KEY);
await pipeline.initialize();
// Define pipeline steps
pipeline.addStep(new PipelineStep(
'load_data',
`
import pandas as pd
df = pd.read_csv('/workspace/input.csv')
print(f"Loaded {len(df)} rows")
`
));
pipeline.addStep(new PipelineStep(
'analyze',
`
import pandas as pd
df = pd.read_csv('/workspace/input.csv')
summary = df.describe()
summary.to_csv('/workspace/summary.csv')
print("Analysis complete")
`
));
// Execute
const result = await pipeline.executePipeline('name,age\nAlice,25\nBob,30');
console.log(result);
await pipeline.cleanup();
```
## Best Practices
1. **Step Isolation**: Each step should be independent and testable
2. **Error Handling**: Handle errors gracefully and provide recovery options
3. **Data Validation**: Validate data between steps
4. **Result Caching**: Cache intermediate results for efficiency
## Related Cookbooks
* [Cloud Jupyter Notebook](/cookbooks/data-science/cloud-jupyter) - Notebook execution
* [ML Model Training Service](/cookbooks/data-science/ml-training-service) - Machine learning workflows
## Next Steps
1. Implement pipeline scheduling
2. Add data validation between steps
3. Create pipeline visualization
4. Implement result caching
5. Add monitoring and alerting
# Cloud Jupyter Notebook Service
Source: https://docs.hopx.ai/cookbooks/data-science/cloud-jupyter
Build a Kaggle/Colab-style notebook hosting service with rich output rendering, large dataset handling, and model training workflows
Build a production-ready cloud Jupyter notebook service that provides notebook execution, rich output rendering, and data science workflows. This cookbook demonstrates how to create a service similar to Kaggle or Google Colab using HopX.
## Overview
Cloud Jupyter notebook services allow data scientists to run notebooks in the cloud without local setup. The service executes notebook cells, captures rich outputs (plots, dataframes), handles large datasets, and supports model training workflows. HopX provides the secure execution environment needed for this use case.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of Jupyter notebook format
* Basic knowledge of data science workflows
## Architecture
```
┌──────────────┐
│ Notebook │ Cell execution requests
│ UI │
└──────┬───────┘
│
▼
┌─────────────────┐
│ Notebook │ Parse, execute, capture
│ Service │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandbox │ Secure execution
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Rich Outputs │ Plots, DataFrames, HTML
└─────────────────┘
```
## Implementation
### Step 1: Notebook Cell Execution
Execute individual notebook cells and capture outputs:
```python Python theme={null}
from hopx_ai import Sandbox
import json
import os
from typing import Dict, List, Any
class JupyterNotebookService:
def __init__(self, api_key: str):
self.api_key = api_key
self.sandbox = None
self.cell_state = {} # Store variables between cells
def initialize_notebook(self, notebook_id: str) -> Dict[str, Any]:
"""Initialize a new notebook session"""
try:
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=3600 # 1 hour session
)
# Set up data science environment
self.sandbox.env.set_all({
"JUPYTER_MODE": "true",
"PYTHONPATH": "/workspace"
})
return {
"success": True,
"notebook_id": notebook_id,
"sandbox_id": self.sandbox.sandbox_id
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def execute_cell(self, cell_code: str, cell_id: str = None) -> Dict[str, Any]:
"""Execute a notebook cell"""
try:
# Use IPython execution for notebook-like behavior
result = self.sandbox.run_ipython(cell_code)
# Capture outputs
outputs = []
if result.rich_outputs:
for output in result.rich_outputs:
outputs.append({
"type": output.type,
"data": output.data
})
# Store cell state
if cell_id:
self.cell_state[cell_id] = {
"code": cell_code,
"outputs": outputs,
"stdout": result.stdout,
"stderr": result.stderr
}
return {
"success": result.success,
"stdout": result.stdout,
"stderr": result.stderr,
"outputs": outputs,
"output_count": len(outputs),
"execution_time": result.execution_time
}
except Exception as e:
return {
"success": False,
"error": str(e),
"stderr": str(e)
}
def execute_notebook(self, notebook_json: Dict) -> Dict[str, Any]:
"""Execute entire notebook"""
cells = notebook_json.get("cells", [])
results = []
for i, cell in enumerate(cells):
if cell.get("cell_type") != "code":
continue
source = "".join(cell.get("source", []))
cell_result = self.execute_cell(source, cell_id=f"cell_{i}")
results.append({
"cell_index": i,
"result": cell_result
})
return {
"success": True,
"cells_executed": len(results),
"results": results
}
def cleanup(self):
"""Clean up notebook session"""
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
# Usage
service = JupyterNotebookService(api_key=os.getenv("HOPX_API_KEY"))
service.initialize_notebook("my-notebook")
# Execute a cell
result = service.execute_cell("""
import pandas as pd
import numpy as np
df = pd.DataFrame({
'x': np.random.rand(10),
'y': np.random.rand(10)
})
df # Display dataframe
""")
print(f"Captured {result['output_count']} outputs")
print(result)
service.cleanup()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class JupyterNotebookService {
constructor(apiKey) {
this.apiKey = apiKey;
this.sandbox = null;
this.cellState = {}; // Store variables between cells
}
async initializeNotebook(notebookId) {
try {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: 3600 // 1 hour session
});
// Set up data science environment
await this.sandbox.env.setAll({
JUPYTER_MODE: 'true',
PYTHONPATH: '/workspace'
});
return {
success: true,
notebookId,
sandboxId: this.sandbox.sandboxId
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
async executeCell(cellCode, cellId = null) {
try {
// Use IPython execution for notebook-like behavior
const result = await this.sandbox.runIpython(cellCode);
// Capture outputs
const outputs = [];
if (result.richOutputs) {
for (const output of result.richOutputs) {
outputs.push({
type: output.type,
data: output.data
});
}
}
// Store cell state
if (cellId) {
this.cellState[cellId] = {
code: cellCode,
outputs,
stdout: result.stdout,
stderr: result.stderr
};
}
return {
success: result.success,
stdout: result.stdout,
stderr: result.stderr,
outputs,
outputCount: outputs.length,
executionTime: result.execution_time
};
} catch (error) {
return {
success: false,
error: error.message,
stderr: error.toString()
};
}
}
async executeNotebook(notebookJson) {
const cells = notebookJson.cells || [];
const results = [];
for (let i = 0; i < cells.length; i++) {
const cell = cells[i];
if (cell.cell_type !== 'code') {
continue;
}
const source = cell.source.join('');
const cellResult = await this.executeCell(source, `cell_${i}`);
results.push({
cellIndex: i,
result: cellResult
});
}
return {
success: true,
cellsExecuted: results.length,
results
};
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
// Usage
const service = new JupyterNotebookService(process.env.HOPX_API_KEY);
await service.initializeNotebook('my-notebook');
// Execute a cell
const result = await service.executeCell(`
import pandas as pd
import numpy as np
df = pd.DataFrame({
'x': np.random.rand(10),
'y': np.random.rand(10)
})
df # Display dataframe
`);
console.log(`Captured ${result.outputCount} outputs`);
console.log(result);
await service.cleanup();
```
### Step 2: Rich Output Rendering
Handle plots, dataframes, and other rich outputs:
```python Python theme={null}
class RichOutputRenderer:
def __init__(self, sandbox: Sandbox):
self.sandbox = sandbox
def render_outputs(self, outputs: List[Dict]) -> List[Dict[str, Any]]:
"""Render rich outputs for display"""
rendered = []
for output in outputs:
output_type = output.get("type", "")
data = output.get("data", {})
if "image/png" in output_type or "image/jpeg" in output_type:
# Image output
rendered.append({
"type": "image",
"format": "png" if "png" in output_type else "jpeg",
"data": data.get("image/png") or data.get("image/jpeg"),
"encoding": "base64"
})
elif "text/html" in output_type:
# HTML output (DataFrames, etc.)
rendered.append({
"type": "html",
"data": data.get("text/html", ""),
"mime_type": "text/html"
})
elif "application/json" in output_type:
# JSON output
rendered.append({
"type": "json",
"data": data.get("application/json", {}),
"mime_type": "application/json"
})
else:
# Plain text
rendered.append({
"type": "text",
"data": str(data),
"mime_type": "text/plain"
})
return rendered
# Usage
service = JupyterNotebookService(api_key=os.getenv("HOPX_API_KEY"))
service.initialize_notebook("notebook-1")
# Execute cell with plot
result = service.execute_cell("""
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.plot(x, y)
plt.title('Sine Wave')
plt.show()
""")
# Render outputs
renderer = RichOutputRenderer(service.sandbox)
rendered = renderer.render_outputs(result["outputs"])
for output in rendered:
print(f"Output type: {output['type']}")
if output['type'] == 'image':
print(f" Image data length: {len(output['data'])} bytes")
service.cleanup()
```
```javascript JavaScript theme={null}
class RichOutputRenderer {
constructor(sandbox) {
this.sandbox = sandbox;
}
renderOutputs(outputs) {
const rendered = [];
for (const output of outputs) {
const outputType = output.type || '';
const data = output.data || {};
if (outputType.includes('image/png') || outputType.includes('image/jpeg')) {
// Image output
rendered.push({
type: 'image',
format: outputType.includes('png') ? 'png' : 'jpeg',
data: data['image/png'] || data['image/jpeg'],
encoding: 'base64'
});
} else if (outputType.includes('text/html')) {
// HTML output (DataFrames, etc.)
rendered.push({
type: 'html',
data: data['text/html'] || '',
mimeType: 'text/html'
});
} else if (outputType.includes('application/json')) {
// JSON output
rendered.push({
type: 'json',
data: data['application/json'] || {},
mimeType: 'application/json'
});
} else {
// Plain text
rendered.push({
type: 'text',
data: String(data),
mimeType: 'text/plain'
});
}
}
return rendered;
}
}
// Usage
const service = new JupyterNotebookService(process.env.HOPX_API_KEY);
await service.initializeNotebook('notebook-1');
// Execute cell with plot
const result = await service.executeCell(`
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.plot(x, y)
plt.title('Sine Wave')
plt.show()
`);
// Render outputs
const renderer = new RichOutputRenderer(service.sandbox);
const rendered = renderer.renderOutputs(result.outputs);
for (const output of rendered) {
console.log(`Output type: ${output.type}`);
if (output.type === 'image') {
console.log(` Image data length: ${output.data.length} bytes`);
}
}
await service.cleanup();
```
### Step 3: Large Dataset Handling
Handle large datasets efficiently:
```python Python theme={null}
class LargeDatasetHandler:
def __init__(self, sandbox: Sandbox):
self.sandbox = sandbox
def upload_dataset(self, file_path: str, data: bytes) -> Dict[str, Any]:
"""Upload large dataset to sandbox"""
try:
# For large files, use upload method
self.sandbox.files.write(f"/workspace/data/{file_path}", data)
return {
"success": True,
"path": f"/workspace/data/{file_path}",
"size": len(data)
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def process_large_dataset(self, dataset_path: str, chunk_size: int = 10000) -> Dict[str, Any]:
"""Process large dataset in chunks"""
try:
# Process in chunks to avoid memory issues
code = f"""
import pandas as pd
import os
# Read dataset in chunks
chunk_size = {chunk_size}
dataset_path = '{dataset_path}'
chunks = []
for chunk in pd.read_csv(dataset_path, chunksize=chunk_size):
# Process chunk
processed = chunk.describe()
chunks.append(processed)
# Combine results
result = pd.concat(chunks)
print(f"Processed {{len(chunks)}} chunks")
print(result)
"""
result = self.sandbox.run_code(code, timeout=300) # 5 minute timeout
return {
"success": result.success,
"stdout": result.stdout,
"chunks_processed": result.stdout.count("chunks") if result.success else 0
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
# Usage
sandbox = Sandbox.create(template="code-interpreter", api_key=os.getenv("HOPX_API_KEY"))
handler = LargeDatasetHandler(sandbox)
# Upload dataset
with open("large_dataset.csv", "rb") as f:
data = f.read()
result = handler.upload_dataset("large_dataset.csv", data)
print(result)
# Process
result = handler.process_large_dataset("/workspace/data/large_dataset.csv")
print(result)
sandbox.kill()
```
```javascript JavaScript theme={null}
class LargeDatasetHandler {
constructor(sandbox) {
this.sandbox = sandbox;
}
async uploadDataset(filePath, data) {
try {
// For large files, use write method
await this.sandbox.files.write(`/workspace/data/${filePath}`, data);
return {
success: true,
path: `/workspace/data/${filePath}`,
size: data.length
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
async processLargeDataset(datasetPath, chunkSize = 10000) {
try {
// Process in chunks to avoid memory issues
const code = `
import pandas as pd
import os
# Read dataset in chunks
chunk_size = ${chunkSize}
dataset_path = '${datasetPath}'
chunks = []
for chunk in pd.read_csv(dataset_path, chunksize=chunk_size):
# Process chunk
processed = chunk.describe()
chunks.append(processed)
# Combine results
result = pd.concat(chunks)
print(f"Processed {len(chunks)} chunks")
print(result)
`;
const result = await this.sandbox.runCode(code, { timeout: 300 }); // 5 minute timeout
return {
success: result.success,
stdout: result.stdout,
chunksProcessed: result.success ? (result.stdout.match(/chunks/g) || []).length : 0
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
}
// Usage
const sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: process.env.HOPX_API_KEY
});
const handler = new LargeDatasetHandler(sandbox);
// Upload dataset (assuming you have the file data)
const fs = require('fs');
const data = fs.readFileSync('large_dataset.csv');
const uploadResult = await handler.uploadDataset('large_dataset.csv', data);
console.log(uploadResult);
// Process
const processResult = await handler.processLargeDataset('/workspace/data/large_dataset.csv');
console.log(processResult);
await sandbox.kill();
```
### Step 4: Model Training Workflows
Support ML model training:
```python Python theme={null}
class ModelTrainingService:
def __init__(self, sandbox: Sandbox):
self.sandbox = sandbox
def train_model(self, training_code: str, timeout: int = 1800) -> Dict[str, Any]:
"""Train ML model with progress monitoring"""
try:
# Use background execution for long training
execution_id = self.sandbox.run_code_background(training_code)
# Monitor progress
import time
max_wait = timeout
waited = 0
while waited < max_wait:
time.sleep(5) # Check every 5 seconds
waited += 5
# Check if process is still running
processes = self.sandbox.list_processes()
training_process = any(
'python' in p.get('name', '').lower() or
'train' in p.get('name', '').lower()
for p in processes
)
if not training_process:
# Training completed
break
# Check for model file
if self.sandbox.files.exists("/workspace/model.pkl"):
model_data = self.sandbox.files.read("/workspace/model.pkl")
return {
"success": True,
"model_saved": True,
"model_size": len(model_data),
"execution_id": execution_id
}
else:
return {
"success": True,
"model_saved": False,
"execution_id": execution_id
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
# Usage
sandbox = Sandbox.create(template="code-interpreter", api_key=os.getenv("HOPX_API_KEY"))
trainer = ModelTrainingService(sandbox)
training_code = """
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
import pickle
# Load data
iris = load_iris()
X, y = iris.data, iris.target
# Train model
model = RandomForestClassifier(n_estimators=100)
model.fit(X, y)
# Save model
with open('/workspace/model.pkl', 'wb') as f:
pickle.dump(model, f)
print("Model trained and saved!")
"""
result = trainer.train_model(training_code)
print(result)
sandbox.kill()
```
```javascript JavaScript theme={null}
class ModelTrainingService {
constructor(sandbox) {
this.sandbox = sandbox;
}
async trainModel(trainingCode, timeout = 1800) {
try {
// Use background execution for long training
const executionId = await this.sandbox.runCodeBackground(trainingCode);
// Monitor progress
const maxWait = timeout;
let waited = 0;
while (waited < maxWait) {
await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5 seconds
waited += 5;
// Check if process is still running
const processes = await this.sandbox.listProcesses();
const trainingProcess = processes.some(p => {
const name = (p.name || '').toLowerCase();
return name.includes('python') || name.includes('train');
});
if (!trainingProcess) {
// Training completed
break;
}
}
// Check for model file
const modelExists = await this.sandbox.files.exists('/workspace/model.pkl');
if (modelExists) {
const modelData = await this.sandbox.files.read('/workspace/model.pkl');
return {
success: true,
modelSaved: true,
modelSize: modelData.length,
executionId
};
} else {
return {
success: true,
modelSaved: false,
executionId
};
}
} catch (error) {
return {
success: false,
error: error.message
};
}
}
}
// Usage
const sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: process.env.HOPX_API_KEY
});
const trainer = new ModelTrainingService(sandbox);
const trainingCode = `
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
import pickle
# Load data
iris = load_iris()
X, y = iris.data, iris.target
# Train model
model = RandomForestClassifier(n_estimators=100)
model.fit(X, y)
# Save model
with open('/workspace/model.pkl', 'wb') as f:
pickle.dump(model, f)
print("Model trained and saved!")
`;
const result = await trainer.trainModel(trainingCode);
console.log(result);
await sandbox.kill();
```
## Best Practices
### Performance
Use IPython execution mode for notebook cells to automatically capture rich outputs like DataFrames and plots.
1. **Cell State Management**: Maintain state between cells for interactive workflows
2. **Output Caching**: Cache rendered outputs to avoid re-rendering
3. **Chunked Processing**: Process large datasets in chunks
4. **Background Execution**: Use background execution for long-running training
### Resource Management
1. **Session Timeouts**: Set appropriate session timeouts
2. **Memory Monitoring**: Monitor memory usage for large datasets
3. **Cleanup**: Clean up temporary files and models
4. **Resource Limits**: Set limits based on user tier
### User Experience
1. **Progress Indicators**: Show execution progress for long operations
2. **Error Messages**: Provide clear, actionable error messages
3. **Output Formatting**: Format outputs for easy reading
4. **Auto-Save**: Auto-save notebook state
## Real-World Examples
This pattern is used by:
* **Kaggle Notebooks**: Data science competition platform
* **Google Colab**: Free Jupyter notebook environment
* **Azure Notebooks**: Cloud-based Jupyter service
* **Binder**: Turn GitHub repos into interactive notebooks
## Related Cookbooks
* [Data Analysis Pipeline](/cookbooks/data-science/analysis-pipeline) - Analysis workflows
* [ML Model Training Service](/cookbooks/data-science/ml-training-service) - Machine learning workflows
## Next Steps
1. Implement notebook format parsing (Jupyter .ipynb format)
2. Add support for markdown and code cells
3. Create a web UI for notebook editing
4. Implement cell execution queue
5. Add collaboration features
# ML Model Training Service
Source: https://docs.hopx.ai/cookbooks/data-science/ml-training-service
Build a cloud-based ML training platform with resource allocation, long-running execution, progress monitoring, and model checkpointing
Build a production-ready ML model training service that handles resource allocation, monitors training progress, and manages model checkpoints. This cookbook demonstrates how to create a training platform using HopX.
## Overview
ML training services provide cloud-based environments for training machine learning models. The service allocates resources, executes long-running training jobs, monitors progress, and saves model checkpoints.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of ML training workflows
* Basic knowledge of model checkpointing
## Architecture
```
┌──────────────┐
│ Training │ Submit training job
│ Request │
└──────┬───────┘
│
▼
┌─────────────────┐
│ Training │ Allocate resources
│ Service │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandbox │ Execute training
│ (High resources)│
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Model Storage │ Save checkpoints
└─────────────────┘
```
## Implementation
### Step 1: Training Job Execution
Execute ML training jobs:
```python Python theme={null}
from hopx_ai import Sandbox
import os
import time
from typing import Dict, Any
class MLTrainingService:
def __init__(self, api_key: str):
self.api_key = api_key
self.sandbox = None
def start_training(self, training_code: str, resources: Dict[str, int] = None) -> Dict[str, Any]:
"""Start ML training job"""
try:
# Create sandbox with appropriate resources
# Note: Resources come from template, but we can request high-resource template
self.sandbox = Sandbox.create(
template="code-interpreter", # Use ML-optimized template if available
api_key=self.api_key,
timeout_seconds=7200 # 2 hour timeout for training
)
# Start training in background
execution_id = self.sandbox.run_code_background(training_code)
return {
"success": True,
"execution_id": execution_id,
"sandbox_id": self.sandbox.sandbox_id
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def monitor_training(self, execution_id: str) -> Dict[str, Any]:
"""Monitor training progress"""
try:
# Check processes
processes = self.sandbox.list_processes()
training_processes = [
p for p in processes
if 'python' in p.get('name', '').lower() or 'train' in p.get('name', '').lower()
]
# Check for checkpoint files
files = self.sandbox.files.list("/workspace")
checkpoints = [f for f in files if 'checkpoint' in f.name.lower() or f.name.endswith('.pkl')]
return {
"training_active": len(training_processes) > 0,
"checkpoints": len(checkpoints),
"processes": len(training_processes)
}
except Exception as e:
return {
"error": str(e)
}
def get_checkpoint(self, checkpoint_path: str) -> Dict[str, Any]:
"""Retrieve model checkpoint"""
try:
checkpoint_data = self.sandbox.files.read(checkpoint_path)
return {
"success": True,
"data": checkpoint_data,
"size": len(checkpoint_data)
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def cleanup(self):
"""Clean up training resources"""
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
# Usage
service = MLTrainingService(api_key=os.getenv("HOPX_API_KEY"))
training_code = """
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
import pickle
iris = load_iris()
X, y = iris.data, iris.target
model = RandomForestClassifier(n_estimators=100)
model.fit(X, y)
with open('/workspace/model.pkl', 'wb') as f:
pickle.dump(model, f)
"""
result = service.start_training(training_code)
print(result)
# Monitor
time.sleep(5)
status = service.monitor_training(result["execution_id"])
print(status)
service.cleanup()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class MLTrainingService {
constructor(apiKey) {
this.apiKey = apiKey;
this.sandbox = null;
}
async startTraining(trainingCode, resources = null) {
try {
// Create sandbox with appropriate resources
this.sandbox = await Sandbox.create({
template: 'code-interpreter', // Use ML-optimized template if available
apiKey: this.apiKey,
timeoutSeconds: 7200 // 2 hour timeout for training
});
// Start training in background
const executionId = await this.sandbox.runCodeBackground(trainingCode);
return {
success: true,
executionId,
sandboxId: this.sandbox.sandboxId
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
async monitorTraining(executionId) {
try {
// Check processes
const processes = await this.sandbox.listProcesses();
const trainingProcesses = processes.filter(p => {
const name = (p.name || '').toLowerCase();
return name.includes('python') || name.includes('train');
});
// Check for checkpoint files
const files = await this.sandbox.files.list('/workspace');
const checkpoints = files.filter(f =>
f.name.toLowerCase().includes('checkpoint') ||
f.name.endsWith('.pkl')
);
return {
trainingActive: trainingProcesses.length > 0,
checkpoints: checkpoints.length,
processes: trainingProcesses.length
};
} catch (error) {
return {
error: error.message
};
}
}
async getCheckpoint(checkpointPath) {
try {
const checkpointData = await this.sandbox.files.read(checkpointPath);
return {
success: true,
data: checkpointData,
size: checkpointData.length
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
// Usage
const service = new MLTrainingService(process.env.HOPX_API_KEY);
const trainingCode = `
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier
import pickle
iris = load_iris()
X, y = iris.data, iris.target
model = RandomForestClassifier(n_estimators=100)
model.fit(X, y)
with open('/workspace/model.pkl', 'wb') as f:
pickle.dump(model, f)
`;
const result = await service.startTraining(trainingCode);
console.log(result);
// Monitor
await new Promise(resolve => setTimeout(resolve, 5000));
const status = await service.monitorTraining(result.executionId);
console.log(status);
await service.cleanup();
```
## Best Practices
1. **Resource Allocation**: Request appropriate resources for training
2. **Progress Monitoring**: Monitor training progress regularly
3. **Checkpointing**: Save model checkpoints frequently
4. **Error Recovery**: Handle training failures gracefully
## Related Cookbooks
* [Cloud Jupyter Notebook](/cookbooks/data-science/cloud-jupyter) - Notebook execution
* [Data Analysis Pipeline](/cookbooks/data-science/analysis-pipeline) - Analysis workflows
## Next Steps
1. Implement distributed training support
2. Add hyperparameter tuning
3. Create training dashboard
4. Implement model versioning
5. Add training job scheduling
# Browser-Based Code Editor
Source: https://docs.hopx.ai/cookbooks/development/browser-editor
Build a StackBlitz-style browser IDE with client-server architecture, file operations via API, hot reload patterns, and package management
Build a production-ready browser-based code editor that runs entirely in the browser with a backend API. This cookbook demonstrates how to create a platform similar to StackBlitz or CodeSandbox using HopX.
## Overview
Browser-based code editors provide a full IDE experience in the browser. The frontend handles editing, and the backend manages file operations, code execution, and package management through APIs.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of client-server architecture
* Basic knowledge of web APIs
## Architecture
```
┌──────────────┐
│ Browser │ Editor UI
└──────┬───────┘
│ HTTP/WebSocket
▼
┌─────────────────┐
│ Editor Backend │ File ops, execution
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandbox │ Secure execution
└─────────────────┘
```
## Implementation
### Step 1: File Operations API
Provide file operations via API:
```python Python theme={null}
from hopx_ai import Sandbox
import os
from typing import Dict, Any
class EditorBackend:
def __init__(self, api_key: str):
self.api_key = api_key
self.sandbox = None
def initialize_project(self, project_id: str) -> Dict[str, Any]:
"""Initialize editor project"""
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=3600
)
self.sandbox.files.mkdir("/workspace/project")
return {
"success": True,
"project_id": project_id,
"sandbox_id": self.sandbox.sandbox_id
}
def handle_file_request(self, method: str, path: str, content: str = None) -> Dict[str, Any]:
"""Handle file operation requests"""
full_path = f"/workspace/project{path}"
if method == "GET":
# Read file
try:
content = self.sandbox.files.read(full_path)
return {"success": True, "content": content}
except Exception as e:
return {"success": False, "error": str(e)}
elif method == "PUT":
# Write file
try:
self.sandbox.files.write(full_path, content)
return {"success": True, "path": path}
except Exception as e:
return {"success": False, "error": str(e)}
elif method == "DELETE":
# Delete file
try:
self.sandbox.files.remove(full_path)
return {"success": True, "path": path}
except Exception as e:
return {"success": False, "error": str(e)}
elif method == "LIST":
# List directory
try:
files = self.sandbox.files.list(full_path)
return {
"success": True,
"files": [
{
"name": f.name,
"path": f.path,
"is_dir": f.is_dir,
"size": f.size
}
for f in files
]
}
except Exception as e:
return {"success": False, "error": str(e)}
return {"success": False, "error": f"Unknown method: {method}"}
def cleanup(self):
"""Clean up editor resources"""
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
# Usage
backend = EditorBackend(api_key=os.getenv("HOPX_API_KEY"))
backend.initialize_project("my-project")
# File operations
result = backend.handle_file_request("PUT", "/app.js", "console.log('Hello');")
print(result)
result = backend.handle_file_request("GET", "/app.js")
print(result)
backend.cleanup()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class EditorBackend {
constructor(apiKey) {
this.apiKey = apiKey;
this.sandbox = null;
}
async initializeProject(projectId) {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: 3600
});
await this.sandbox.files.mkdir('/workspace/project');
return {
success: true,
projectId,
sandboxId: this.sandbox.sandboxId
};
}
async handleFileRequest(method, path, content = null) {
const fullPath = `/workspace/project${path}`;
if (method === 'GET') {
try {
const fileContent = await this.sandbox.files.read(fullPath);
return { success: true, content: fileContent };
} catch (error) {
return { success: false, error: error.message };
}
} else if (method === 'PUT') {
try {
await this.sandbox.files.write(fullPath, content);
return { success: true, path };
} catch (error) {
return { success: false, error: error.message };
}
} else if (method === 'DELETE') {
try {
await this.sandbox.files.remove(fullPath);
return { success: true, path };
} catch (error) {
return { success: false, error: error.message };
}
} else if (method === 'LIST') {
try {
const files = await this.sandbox.files.list(fullPath);
return {
success: true,
files: files.map(f => ({
name: f.name,
path: f.path,
isDir: f.isDir,
size: f.size
}))
};
} catch (error) {
return { success: false, error: error.message };
}
}
return { success: false, error: `Unknown method: ${method}` };
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
// Usage
const backend = new EditorBackend(process.env.HOPX_API_KEY);
await backend.initializeProject('my-project');
// File operations
const result1 = await backend.handleFileRequest('PUT', '/app.js', "console.log('Hello');");
console.log(result1);
const result2 = await backend.handleFileRequest('GET', '/app.js');
console.log(result2);
await backend.cleanup();
```
## Best Practices
1. **API Design**: Design RESTful APIs for file operations
2. **Hot Reload**: Implement file watching for live updates
3. **Package Management**: Support npm, pip, etc.
4. **Error Handling**: Provide clear error messages
## Related Cookbooks
* [Cloud-Based IDE Backend](/cookbooks/development/cloud-ide-backend) - Full IDE backend
## Next Steps
1. Implement WebSocket for real-time updates
2. Add package installation support
3. Create frontend editor interface
4. Implement hot reload functionality
5. Add collaboration features
# Cloud-Based IDE Backend
Source: https://docs.hopx.ai/cookbooks/development/cloud-ide-backend
Build a Replit/CodeSandbox-style online IDE with file system management, terminal emulation, and multi-file project execution
Build a production-ready cloud-based IDE backend that provides file system management, terminal access, and code execution. This cookbook demonstrates how to create a backend similar to Replit or CodeSandbox using HopX for secure execution.
## Overview
Cloud-based IDEs allow developers to code, run, and debug applications entirely in the browser. The backend manages file systems, provides terminal access, executes code, and handles real-time updates. HopX provides the secure execution environment needed for this use case.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of WebSocket connections
* Basic knowledge of IDE architecture
## Architecture
```
┌──────────────┐
│ Browser │ Editor, Terminal UI
└──────┬───────┘
│ WebSocket/HTTP
▼
┌─────────────────┐
│ IDE Backend │ File ops, Terminal, Execution
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandbox │ Secure execution environment
└─────────────────┘
```
## Implementation
### Step 1: File System Management
Create a file system manager for the IDE:
```python Python theme={null}
from hopx_ai import Sandbox
import os
from typing import Dict, List, Any
class IDEFileSystem:
def __init__(self, api_key: str):
self.api_key = api_key
self.sandbox = None
def initialize_project(self, project_id: str) -> Dict[str, Any]:
"""Initialize a new project sandbox"""
try:
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=3600 # 1 hour for IDE session
)
# Create project structure
self.sandbox.files.mkdir("/workspace/project")
self.sandbox.files.write("/workspace/project/.gitignore", "__pycache__/\n*.pyc\n")
return {
"success": True,
"sandbox_id": self.sandbox.sandbox_id,
"project_path": "/workspace/project"
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def list_files(self, path: str = "/workspace/project") -> List[Dict[str, Any]]:
"""List files and directories"""
try:
files = self.sandbox.files.list(path)
return [
{
"name": f.name,
"path": f.path,
"is_dir": f.is_dir,
"size": f.size,
"modified": f.modified_time.isoformat() if hasattr(f.modified_time, 'isoformat') else str(f.modified_time)
}
for f in files
]
except Exception as e:
return []
def read_file(self, file_path: str) -> Dict[str, Any]:
"""Read file contents"""
try:
content = self.sandbox.files.read(file_path)
return {
"success": True,
"content": content,
"path": file_path
}
except Exception as e:
return {
"success": False,
"error": str(e),
"path": file_path
}
def write_file(self, file_path: str, content: str) -> Dict[str, Any]:
"""Write file contents"""
try:
self.sandbox.files.write(file_path, content)
return {
"success": True,
"path": file_path,
"size": len(content)
}
except Exception as e:
return {
"success": False,
"error": str(e),
"path": file_path
}
def create_directory(self, dir_path: str) -> Dict[str, Any]:
"""Create a directory"""
try:
self.sandbox.files.mkdir(dir_path)
return {
"success": True,
"path": dir_path
}
except Exception as e:
return {
"success": False,
"error": str(e),
"path": dir_path
}
def delete_file(self, file_path: str) -> Dict[str, Any]:
"""Delete a file or directory"""
try:
self.sandbox.files.remove(file_path)
return {
"success": True,
"path": file_path
}
except Exception as e:
return {
"success": False,
"error": str(e),
"path": file_path
}
def cleanup(self):
"""Clean up sandbox"""
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
# Usage
fs = IDEFileSystem(api_key=os.getenv("HOPX_API_KEY"))
result = fs.initialize_project("my-project")
print(result)
# List files
files = fs.list_files()
print(files)
# Create a file
fs.write_file("/workspace/project/main.py", "print('Hello, World!')")
# Read the file
content = fs.read_file("/workspace/project/main.py")
print(content)
fs.cleanup()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class IDEFileSystem {
constructor(apiKey) {
this.apiKey = apiKey;
this.sandbox = null;
}
async initializeProject(projectId) {
try {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: 3600 // 1 hour for IDE session
});
// Create project structure
await this.sandbox.files.mkdir('/workspace/project');
await this.sandbox.files.write('/workspace/project/.gitignore', '__pycache__/\n*.pyc\n');
return {
success: true,
sandboxId: this.sandbox.sandboxId,
projectPath: '/workspace/project'
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
async listFiles(path = '/workspace/project') {
try {
const files = await this.sandbox.files.list(path);
return files.map(f => ({
name: f.name,
path: f.path,
isDir: f.isDir,
size: f.size,
modified: f.modifiedTime
}));
} catch (error) {
return [];
}
}
async readFile(filePath) {
try {
const content = await this.sandbox.files.read(filePath);
return {
success: true,
content,
path: filePath
};
} catch (error) {
return {
success: false,
error: error.message,
path: filePath
};
}
}
async writeFile(filePath, content) {
try {
await this.sandbox.files.write(filePath, content);
return {
success: true,
path: filePath,
size: content.length
};
} catch (error) {
return {
success: false,
error: error.message,
path: filePath
};
}
}
async createDirectory(dirPath) {
try {
await this.sandbox.files.mkdir(dirPath);
return {
success: true,
path: dirPath
};
} catch (error) {
return {
success: false,
error: error.message,
path: dirPath
};
}
}
async deleteFile(filePath) {
try {
await this.sandbox.files.remove(filePath);
return {
success: true,
path: filePath
};
} catch (error) {
return {
success: false,
error: error.message,
path: filePath
};
}
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
// Usage
const fs = new IDEFileSystem(process.env.HOPX_API_KEY);
const result = await fs.initializeProject('my-project');
console.log(result);
// List files
const files = await fs.listFiles();
console.log(files);
// Create a file
await fs.writeFile('/workspace/project/main.py', "print('Hello, World!')");
// Read the file
const content = await fs.readFile('/workspace/project/main.py');
console.log(content);
await fs.cleanup();
```
### Step 2: Terminal Emulation
Implement terminal access using WebSocket:
```python Python theme={null}
import asyncio
from typing import AsyncIterator, Dict, Any
class IDETerminal:
def __init__(self, sandbox: Sandbox):
self.sandbox = sandbox
self.terminal_session = None
async def connect(self) -> Dict[str, Any]:
"""Connect to terminal"""
try:
self.terminal_session = await self.sandbox.terminal.connect()
return {
"success": True,
"session_id": str(self.terminal_session)
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
async def send_command(self, command: str) -> None:
"""Send command to terminal"""
if self.terminal_session:
await self.sandbox.terminal.send_input(
self.terminal_session,
command + "\n"
)
async def receive_output(self) -> AsyncIterator[Dict[str, Any]]:
"""Receive terminal output"""
if not self.terminal_session:
return
async for message in self.sandbox.terminal.iter_output(self.terminal_session):
yield {
"type": message.get("type", "output"),
"data": message.get("data", ""),
"timestamp": message.get("timestamp")
}
async def resize(self, rows: int, cols: int) -> None:
"""Resize terminal"""
if self.terminal_session:
await self.sandbox.terminal.resize(
self.terminal_session,
rows=rows,
cols=cols
)
async def disconnect(self):
"""Disconnect from terminal"""
self.terminal_session = None
# Usage
sandbox = Sandbox.create(template="code-interpreter", api_key=os.getenv("HOPX_API_KEY"))
terminal = IDETerminal(sandbox)
await terminal.connect()
await terminal.send_command("pwd")
await terminal.send_command("ls -la")
async for output in terminal.receive_output():
print(output)
# Break after some outputs
break
await terminal.disconnect()
sandbox.kill()
```
```javascript JavaScript theme={null}
class IDETerminal {
constructor(sandbox) {
this.sandbox = sandbox;
this.terminalSession = null;
}
async connect() {
try {
this.terminalSession = await this.sandbox.terminal.connect();
return {
success: true,
sessionId: String(this.terminalSession)
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
async sendCommand(command) {
if (this.terminalSession) {
await this.sandbox.terminal.sendInput(
this.terminalSession,
command + '\n'
);
}
}
async *receiveOutput() {
if (!this.terminalSession) {
return;
}
for await (const message of this.sandbox.terminal.iterOutput(this.terminalSession)) {
yield {
type: message.type || 'output',
data: message.data || '',
timestamp: message.timestamp
};
}
}
async resize(rows, cols) {
if (this.terminalSession) {
await this.sandbox.terminal.resize(
this.terminalSession,
rows,
cols
);
}
}
async disconnect() {
this.terminalSession = null;
}
}
// Usage
const sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: process.env.HOPX_API_KEY
});
const terminal = new IDETerminal(sandbox);
await terminal.connect();
await terminal.sendCommand('pwd');
await terminal.sendCommand('ls -la');
for await (const output of terminal.receiveOutput()) {
console.log(output);
// Break after some outputs
break;
}
await terminal.disconnect();
await sandbox.kill();
```
### Step 3: Multi-File Project Execution
Execute projects with multiple files:
```python Python theme={null}
class IDEProjectExecutor:
def __init__(self, sandbox: Sandbox):
self.sandbox = sandbox
def execute_project(self, entry_point: str, working_dir: str = "/workspace/project") -> Dict[str, Any]:
"""Execute a multi-file project"""
try:
# Determine language from file extension
language = self._detect_language(entry_point)
# Execute in project directory
result = self.sandbox.run_code(
self._get_execution_code(entry_point, language),
language=language,
working_dir=working_dir,
timeout=30
)
return {
"success": result.success,
"stdout": result.stdout,
"stderr": result.stderr,
"exit_code": result.exit_code,
"execution_time": result.execution_time
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def _detect_language(self, file_path: str) -> str:
"""Detect language from file extension"""
ext = file_path.split('.')[-1].lower()
language_map = {
'py': 'python',
'js': 'javascript',
'ts': 'typescript',
'java': 'java',
'go': 'go'
}
return language_map.get(ext, 'python')
def _get_execution_code(self, entry_point: str, language: str) -> str:
"""Get code to execute based on language"""
if language == 'python':
return f"exec(open('{entry_point}').read())"
elif language == 'javascript':
return f"require('{entry_point.replace('.js', '')}')"
else:
# For other languages, use appropriate execution method
return f"# Execute {entry_point}"
# Usage
sandbox = Sandbox.create(template="code-interpreter", api_key=os.getenv("HOPX_API_KEY"))
executor = IDEProjectExecutor(sandbox)
# Create a multi-file project
sandbox.files.write("/workspace/project/utils.py", """
def greet(name):
return f"Hello, {name}!"
""")
sandbox.files.write("/workspace/project/main.py", """
from utils import greet
print(greet("World"))
""")
# Execute
result = executor.execute_project("main.py")
print(result)
sandbox.kill()
```
```javascript JavaScript theme={null}
class IDEProjectExecutor {
constructor(sandbox) {
this.sandbox = sandbox;
}
async executeProject(entryPoint, workingDir = '/workspace/project') {
try {
// Determine language from file extension
const language = this.detectLanguage(entryPoint);
// Execute in project directory
const executionCode = this.getExecutionCode(entryPoint, language);
const result = await this.sandbox.runCode(executionCode, {
language,
workingDir,
timeout: 30
});
return {
success: result.success,
stdout: result.stdout,
stderr: result.stderr,
exitCode: result.exit_code,
executionTime: result.execution_time
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
detectLanguage(filePath) {
const ext = filePath.split('.').pop().toLowerCase();
const languageMap = {
'py': 'python',
'js': 'javascript',
'ts': 'typescript',
'java': 'java',
'go': 'go'
};
return languageMap[ext] || 'python';
}
getExecutionCode(entryPoint, language) {
if (language === 'python') {
return `exec(open('${entryPoint}').read())`;
} else if (language === 'javascript') {
return `require('${entryPoint.replace('.js', '')}')`;
} else {
return `# Execute ${entryPoint}`;
}
}
}
// Usage
const sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: process.env.HOPX_API_KEY
});
const executor = new IDEProjectExecutor(sandbox);
// Create a multi-file project
await sandbox.files.write('/workspace/project/utils.py', `
def greet(name):
return f"Hello, {name}!"
`);
await sandbox.files.write('/workspace/project/main.py', `
from utils import greet
print(greet("World"))
`);
// Execute
const result = await executor.executeProject('main.py');
console.log(result);
await sandbox.kill();
```
### Step 4: Complete IDE Backend
Combine all components into a complete IDE backend:
```python Python theme={null}
class CloudIDEBackend:
def __init__(self, api_key: str):
self.api_key = api_key
self.fs = IDEFileSystem(api_key)
self.sandbox = None
self.terminal = None
self.executor = None
def initialize(self, project_id: str) -> Dict[str, Any]:
"""Initialize IDE session"""
result = self.fs.initialize_project(project_id)
if result["success"]:
self.sandbox = self.fs.sandbox
self.terminal = IDETerminal(self.sandbox)
self.executor = IDEProjectExecutor(self.sandbox)
return result
async def handle_file_operation(self, operation: str, **kwargs) -> Dict[str, Any]:
"""Handle file operations"""
if operation == "list":
return {"files": self.fs.list_files(kwargs.get("path", "/workspace/project"))}
elif operation == "read":
return self.fs.read_file(kwargs["path"])
elif operation == "write":
return self.fs.write_file(kwargs["path"], kwargs["content"])
elif operation == "create_dir":
return self.fs.create_directory(kwargs["path"])
elif operation == "delete":
return self.fs.delete_file(kwargs["path"])
else:
return {"success": False, "error": f"Unknown operation: {operation}"}
async def handle_terminal_command(self, command: str) -> Dict[str, Any]:
"""Handle terminal command"""
if not self.terminal.terminal_session:
await self.terminal.connect()
await self.terminal.send_command(command)
# Collect output
outputs = []
async for output in self.terminal.receive_output():
outputs.append(output)
if len(outputs) >= 10: # Limit output
break
return {"outputs": outputs}
def handle_execution(self, entry_point: str) -> Dict[str, Any]:
"""Handle code execution"""
return self.executor.execute_project(entry_point)
def cleanup(self):
"""Clean up all resources"""
if self.terminal:
asyncio.run(self.terminal.disconnect())
self.fs.cleanup()
# Usage
ide = CloudIDEBackend(api_key=os.getenv("HOPX_API_KEY"))
ide.initialize("my-project")
# File operations
result = asyncio.run(ide.handle_file_operation("write", path="/workspace/project/app.py", content="print('Hello')"))
print(result)
# Terminal
result = asyncio.run(ide.handle_terminal_command("ls -la"))
print(result)
# Execution
result = ide.handle_execution("app.py")
print(result)
ide.cleanup()
```
```javascript JavaScript theme={null}
class CloudIDEBackend {
constructor(apiKey) {
this.apiKey = apiKey;
this.fs = new IDEFileSystem(apiKey);
this.sandbox = null;
this.terminal = null;
this.executor = null;
}
async initialize(projectId) {
const result = await this.fs.initializeProject(projectId);
if (result.success) {
this.sandbox = this.fs.sandbox;
this.terminal = new IDETerminal(this.sandbox);
this.executor = new IDEProjectExecutor(this.sandbox);
}
return result;
}
async handleFileOperation(operation, ...args) {
const kwargs = args[0] || {};
if (operation === 'list') {
return { files: await this.fs.listFiles(kwargs.path || '/workspace/project') };
} else if (operation === 'read') {
return await this.fs.readFile(kwargs.path);
} else if (operation === 'write') {
return await this.fs.writeFile(kwargs.path, kwargs.content);
} else if (operation === 'createDir') {
return await this.fs.createDirectory(kwargs.path);
} else if (operation === 'delete') {
return await this.fs.deleteFile(kwargs.path);
} else {
return { success: false, error: `Unknown operation: ${operation}` };
}
}
async handleTerminalCommand(command) {
if (!this.terminal.terminalSession) {
await this.terminal.connect();
}
await this.terminal.sendCommand(command);
// Collect output
const outputs = [];
for await (const output of this.terminal.receiveOutput()) {
outputs.push(output);
if (outputs.length >= 10) { // Limit output
break;
}
}
return { outputs };
}
async handleExecution(entryPoint) {
return await this.executor.executeProject(entryPoint);
}
async cleanup() {
if (this.terminal) {
await this.terminal.disconnect();
}
await this.fs.cleanup();
}
}
// Usage
const ide = new CloudIDEBackend(process.env.HOPX_API_KEY);
await ide.initialize('my-project');
// File operations
const result1 = await ide.handleFileOperation('write', {
path: '/workspace/project/app.py',
content: "print('Hello')"
});
console.log(result1);
// Terminal
const result2 = await ide.handleTerminalCommand('ls -la');
console.log(result2);
// Execution
const result3 = await ide.handleExecution('app.py');
console.log(result3);
await ide.cleanup();
```
## Best Practices
### Security
Always validate file paths to prevent directory traversal attacks. Never allow access to files outside the project directory.
1. **Path Validation**: Sanitize all file paths
2. **Resource Limits**: Set appropriate timeouts and memory limits
3. **Sandbox Isolation**: One sandbox per user/project
4. **Input Validation**: Validate all user inputs
### Performance
Use file watching to detect changes and update the UI in real-time, reducing the need for polling.
1. **Sandbox Reuse**: Reuse sandboxes for the duration of an IDE session
2. **Caching**: Cache file listings and metadata
3. **Async Operations**: Use async/await for all I/O operations
4. **Connection Pooling**: Manage WebSocket connections efficiently
### User Experience
1. **Real-Time Updates**: Use file watching for live file updates
2. **Auto-Save**: Implement auto-save functionality
3. **Error Handling**: Provide clear error messages
4. **Progress Indicators**: Show execution progress
## Real-World Examples
This pattern is used by:
* **Replit**: Online IDE and coding platform
* **CodeSandbox**: Online code editor and prototyping tool
* **Gitpod**: Cloud development environments
* **GitHub Codespaces**: Cloud-based VS Code
## Related Cookbooks
* [Browser-Based Code Editor](/cookbooks/development/browser-editor) - Client-side implementation
* [Terminal WebSocket](/core-concepts/terminal/websocket) - Terminal integration
* [Code Execution](/core-concepts/code-execution/synchronous) - Execution concepts
## Next Steps
1. Implement WebSocket server for real-time communication
2. Add file watching for live updates
3. Create a frontend editor interface
4. Implement package management (pip, npm, etc.)
5. Add debugging support
# Coding Interview Platform
Source: https://docs.hopx.ai/cookbooks/educational/coding-interviews
Build a technical interview platform with problem execution environments, time limit enforcement, test case management, and performance monitoring
Build a production-ready coding interview platform where candidates solve problems under time constraints. This cookbook demonstrates how to create a platform similar to LeetCode or HackerRank for technical interviews.
## Overview
Coding interview platforms provide a controlled environment for technical assessments. Candidates solve problems within time limits, and the system validates solutions, monitors performance, and generates assessment reports.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of interview assessment workflows
* Basic knowledge of performance monitoring
## Architecture
```
┌──────────────┐
│ Candidate │ Submits solution
└──────┬───────┘
│
▼
┌─────────────────┐
│ Interview │ Validate, monitor
│ Platform │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandbox │ Execute & time
└─────────────────┘
```
## Implementation
### Step 1: Time-Limited Execution
Execute code with strict time limits:
```python Python theme={null}
from hopx_ai import Sandbox
import os
import time
from typing import Dict, Any
class InterviewPlatform:
def __init__(self, api_key: str):
self.api_key = api_key
def execute_with_time_limit(self, code: str, time_limit: int, language: str = "python") -> Dict[str, Any]:
"""Execute code with strict time limit"""
sandbox = None
start_time = time.time()
try:
sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=time_limit + 5
)
# Execute with timeout
result = sandbox.run_code(code, language=language, timeout=time_limit)
elapsed = time.time() - start_time
# Check if timeout was exceeded
if elapsed >= time_limit:
return {
"success": False,
"timeout": True,
"elapsed_time": elapsed,
"time_limit": time_limit,
"error": "Time limit exceeded"
}
return {
"success": result.success,
"stdout": result.stdout,
"stderr": result.stderr,
"elapsed_time": elapsed,
"time_limit": time_limit,
"within_limit": elapsed < time_limit
}
except Exception as e:
return {
"success": False,
"error": str(e),
"elapsed_time": time.time() - start_time
}
finally:
if sandbox:
sandbox.kill()
# Usage
platform = InterviewPlatform(api_key=os.getenv("HOPX_API_KEY"))
result = platform.execute_with_time_limit(
code="print('Hello')",
time_limit=5 # 5 second limit
)
print(result)
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class InterviewPlatform {
constructor(apiKey) {
this.apiKey = apiKey;
}
async executeWithTimeLimit(code, timeLimit, language = 'python') {
let sandbox = null;
const startTime = Date.now();
try {
sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: timeLimit + 5
});
// Execute with timeout
const result = await sandbox.runCode(code, {
language,
timeout: timeLimit
});
const elapsed = (Date.now() - startTime) / 1000;
// Check if timeout was exceeded
if (elapsed >= timeLimit) {
return {
success: false,
timeout: true,
elapsedTime: elapsed,
timeLimit,
error: 'Time limit exceeded'
};
}
return {
success: result.success,
stdout: result.stdout,
stderr: result.stderr,
elapsedTime: elapsed,
timeLimit,
withinLimit: elapsed < timeLimit
};
} catch (error) {
return {
success: false,
error: error.message,
elapsedTime: (Date.now() - startTime) / 1000
};
} finally {
if (sandbox) {
await sandbox.kill();
}
}
}
}
// Usage
const platform = new InterviewPlatform(process.env.HOPX_API_KEY);
const result = await platform.executeWithTimeLimit(
"print('Hello')",
5 // 5 second limit
);
console.log(result);
```
### Step 2: Performance Monitoring
Monitor code performance:
```python Python theme={null}
class PerformanceMonitor:
def __init__(self, sandbox: Sandbox):
self.sandbox = sandbox
def monitor_execution(self, code: str) -> Dict[str, Any]:
"""Monitor code execution performance"""
import time
start_time = time.time()
result = self.sandbox.run_code(code, timeout=30)
elapsed = time.time() - start_time
# Get system metrics
metrics = self.sandbox.get_metrics_snapshot()
return {
"execution_time": elapsed,
"code_execution_time": result.execution_time,
"memory_usage": getattr(metrics, 'memory_usage_mb', 0) if hasattr(metrics, 'memory_usage_mb') else 0,
"cpu_usage": getattr(metrics, 'cpu_percent', 0) if hasattr(metrics, 'cpu_percent') else 0,
"success": result.success
}
# Usage
sandbox = Sandbox.create(template="code-interpreter", api_key=os.getenv("HOPX_API_KEY"))
monitor = PerformanceMonitor(sandbox)
metrics = monitor.monitor_execution("print('Hello')")
print(f"Execution time: {metrics['execution_time']:.2f}s")
print(f"Memory usage: {metrics['memory_usage']}MB")
sandbox.kill()
```
```javascript JavaScript theme={null}
class PerformanceMonitor {
constructor(sandbox) {
this.sandbox = sandbox;
}
async monitorExecution(code) {
const startTime = Date.now();
const result = await this.sandbox.runCode(code, { timeout: 30 });
const elapsed = (Date.now() - startTime) / 1000;
// Get system metrics
const metrics = await this.sandbox.getSystemMetrics();
return {
executionTime: elapsed,
codeExecutionTime: result.execution_time,
memoryUsage: metrics.memory_usage_mb || 0,
cpuUsage: metrics.cpu_percent || 0,
success: result.success
};
}
}
// Usage
const sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: process.env.HOPX_API_KEY
});
const monitor = new PerformanceMonitor(sandbox);
const metrics = await monitor.monitorExecution("print('Hello')");
console.log(`Execution time: ${metrics.executionTime.toFixed(2)}s`);
console.log(`Memory usage: ${metrics.memoryUsage}MB`);
await sandbox.kill();
```
## Best Practices
1. **Time Enforcement**: Strictly enforce time limits
2. **Performance Tracking**: Monitor execution time and resource usage
3. **Test Case Management**: Organize test cases efficiently
4. **Result Reporting**: Generate comprehensive assessment reports
## Related Cookbooks
* [Online Coding Platform](/cookbooks/educational/online-coding-platform) - Full coding platform
* [Interactive Tutorials](/cookbooks/educational/interactive-tutorials) - Learning platform
* [Isolated Test Execution](/cookbooks/testing/isolated-test-execution) - Test isolation
## Next Steps
1. Implement problem database
2. Add candidate authentication
3. Create assessment dashboard
4. Implement result analytics
5. Add video/audio interview features
# Interactive Programming Tutorials
Source: https://docs.hopx.ai/cookbooks/educational/interactive-tutorials
Build Codecademy-style interactive learning with step-by-step code execution, progress tracking, hint systems, and solution validation
Build an interactive programming tutorial platform where students learn by writing and executing code step-by-step. This cookbook demonstrates how to create a Codecademy-style learning experience using HopX.
## Overview
Interactive programming tutorials guide students through learning by executing code at each step. The system validates solutions, provides hints, tracks progress, and ensures students understand concepts before moving forward.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of educational content structure
* Basic knowledge of progress tracking
## Architecture
```
┌──────────────┐
│ Student │ Submits code
└──────┬───────┘
│
▼
┌─────────────────┐
│ Tutorial │ Validate, provide hints
│ Engine │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandbox │ Execute & validate
└─────────────────┘
```
## Implementation
### Step 1: Tutorial Step Execution
Execute and validate tutorial steps:
```python Python theme={null}
from hopx_ai import Sandbox
import os
from typing import Dict, List, Any
class TutorialStep:
def __init__(self, step_id: str, instructions: str, solution: str, hints: List[str]):
self.step_id = step_id
self.instructions = instructions
self.solution = solution
self.hints = hints
class InteractiveTutorial:
def __init__(self, api_key: str):
self.api_key = api_key
self.sandbox = None
self.current_step = 0
self.steps = []
def initialize(self):
"""Initialize tutorial session"""
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=3600
)
def add_step(self, step: TutorialStep):
"""Add tutorial step"""
self.steps.append(step)
def validate_step(self, step_index: int, student_code: str) -> Dict[str, Any]:
"""Validate student code for a step"""
step = self.steps[step_index]
# Execute student code
result = self.sandbox.run_code(student_code, timeout=10)
# Check if solution matches
solution_result = self.sandbox.run_code(step.solution, timeout=10)
# Compare outputs
student_output = result.stdout.strip() if result.success else ""
solution_output = solution_result.stdout.strip() if solution_result.success else ""
passed = student_output == solution_output and result.success
return {
"passed": passed,
"student_output": student_output,
"expected_output": solution_output,
"hint": step.hints[0] if not passed and step.hints else None,
"success": result.success
}
def get_next_hint(self, step_index: int, hint_index: int) -> str:
"""Get hint for current step"""
step = self.steps[step_index]
if hint_index < len(step.hints):
return step.hints[hint_index]
return "No more hints available"
def cleanup(self):
"""Clean up tutorial session"""
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
# Usage
tutorial = InteractiveTutorial(api_key=os.getenv("HOPX_API_KEY"))
tutorial.initialize()
# Add steps
tutorial.add_step(TutorialStep(
step_id="step_1",
instructions="Print 'Hello, World!'",
solution="print('Hello, World!')",
hints=["Use the print() function", "Remember to use quotes around the text"]
))
# Validate student code
result = tutorial.validate_step(0, "print('Hello, World!')")
print(f"Passed: {result['passed']}")
tutorial.cleanup()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class TutorialStep {
constructor(stepId, instructions, solution, hints) {
this.stepId = stepId;
this.instructions = instructions;
this.solution = solution;
this.hints = hints;
}
}
class InteractiveTutorial {
constructor(apiKey) {
this.apiKey = apiKey;
this.sandbox = null;
this.currentStep = 0;
this.steps = [];
}
async initialize() {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: 3600
});
}
addStep(step) {
this.steps.push(step);
}
async validateStep(stepIndex, studentCode) {
const step = this.steps[stepIndex];
// Execute student code
const result = await this.sandbox.runCode(studentCode, { timeout: 10 });
// Check if solution matches
const solutionResult = await this.sandbox.runCode(step.solution, { timeout: 10 });
// Compare outputs
const studentOutput = result.success ? result.stdout.trim() : '';
const solutionOutput = solutionResult.success ? solutionResult.stdout.trim() : '';
const passed = studentOutput === solutionOutput && result.success;
return {
passed,
studentOutput,
expectedOutput: solutionOutput,
hint: !passed && step.hints.length > 0 ? step.hints[0] : null,
success: result.success
};
}
getNextHint(stepIndex, hintIndex) {
const step = this.steps[stepIndex];
if (hintIndex < step.hints.length) {
return step.hints[hintIndex];
}
return 'No more hints available';
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
// Usage
const tutorial = new InteractiveTutorial(process.env.HOPX_API_KEY);
await tutorial.initialize();
// Add steps
tutorial.addStep(new TutorialStep(
'step_1',
"Print 'Hello, World!'",
"print('Hello, World!')",
['Use the print() function', 'Remember to use quotes around the text']
));
// Validate student code
const result = await tutorial.validateStep(0, "print('Hello, World!')");
console.log(`Passed: ${result.passed}`);
await tutorial.cleanup();
```
### Step 2: Progress Tracking
Track student progress through tutorials:
```python Python theme={null}
class ProgressTracker:
def __init__(self):
self.progress = {}
def update_progress(self, student_id: str, step_id: str, passed: bool):
"""Update student progress"""
if student_id not in self.progress:
self.progress[student_id] = {
"completed_steps": [],
"current_step": 0,
"total_steps": 0
}
if passed and step_id not in self.progress[student_id]["completed_steps"]:
self.progress[student_id]["completed_steps"].append(step_id)
def get_progress(self, student_id: str) -> Dict[str, Any]:
"""Get student progress"""
if student_id not in self.progress:
return {
"completed_steps": [],
"current_step": 0,
"completion_percentage": 0
}
student_progress = self.progress[student_id]
total = student_progress.get("total_steps", 1)
completed = len(student_progress["completed_steps"])
return {
"completed_steps": student_progress["completed_steps"],
"current_step": student_progress["current_step"],
"completion_percentage": (completed / total * 100) if total > 0 else 0
}
# Usage
tracker = ProgressTracker()
tracker.update_progress("student_1", "step_1", True)
tracker.update_progress("student_1", "step_2", True)
progress = tracker.get_progress("student_1")
print(f"Completion: {progress['completion_percentage']:.1f}%")
```
```javascript JavaScript theme={null}
class ProgressTracker {
constructor() {
this.progress = {};
}
updateProgress(studentId, stepId, passed) {
if (!this.progress[studentId]) {
this.progress[studentId] = {
completedSteps: [],
currentStep: 0,
totalSteps: 0
};
}
if (passed && !this.progress[studentId].completedSteps.includes(stepId)) {
this.progress[studentId].completedSteps.push(stepId);
}
}
getProgress(studentId) {
if (!this.progress[studentId]) {
return {
completedSteps: [],
currentStep: 0,
completionPercentage: 0
};
}
const studentProgress = this.progress[studentId];
const total = studentProgress.totalSteps || 1;
const completed = studentProgress.completedSteps.length;
return {
completedSteps: studentProgress.completedSteps,
currentStep: studentProgress.currentStep,
completionPercentage: total > 0 ? (completed / total * 100) : 0
};
}
}
// Usage
const tracker = new ProgressTracker();
tracker.updateProgress('student_1', 'step_1', true);
tracker.updateProgress('student_1', 'step_2', true);
const progress = tracker.getProgress('student_1');
console.log(`Completion: ${progress.completionPercentage.toFixed(1)}%`);
```
## Best Practices
1. **Step-by-Step Learning**: Break concepts into small, digestible steps
2. **Immediate Feedback**: Provide instant validation feedback
3. **Progressive Hints**: Offer hints that guide without giving away solutions
4. **Progress Persistence**: Save progress so students can resume
## Related Cookbooks
* [Online Coding Platform](/cookbooks/educational/online-coding-platform) - Full coding platform
* [Coding Interview Platform](/cookbooks/educational/coding-interviews) - Interview preparation
## Next Steps
1. Create tutorial content management system
2. Implement hint system with multiple levels
3. Add progress persistence
4. Create tutorial authoring tools
5. Add analytics and reporting
# Building an Online Coding Platform
Source: https://docs.hopx.ai/cookbooks/educational/online-coding-platform
Create a LeetCode/HackerRank-style platform with secure code execution, test case validation, and multi-language support
Build a production-ready online coding platform where students can submit code, run test cases, and receive instant feedback. This cookbook demonstrates how to create a platform similar to LeetCode or HackerRank using HopX for secure code execution.
## Overview
Online coding platforms enable students to practice programming by solving problems and submitting solutions. The platform executes code securely, validates against test cases, and provides feedback.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of test case validation
* Basic knowledge of educational platform architecture
## Architecture
```
┌──────────────┐
│ Student │ Submits code
└──────┬───────┘
│
▼
┌─────────────────┐
│ Platform API │ Validates & queues
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandbox │ Execute code
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Test Runner │ Validate results
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Feedback │ Return results
└─────────────────┘
```
## Implementation
### Step 1: Basic Code Submission and Execution
Create a system that accepts code submissions and executes them:
```python Python theme={null}
from hopx_ai import Sandbox
import os
import json
from typing import Dict, List, Any
class CodingPlatform:
def __init__(self, api_key: str):
self.api_key = api_key
def execute_submission(self, code: str, language: str, timeout: int = 10) -> Dict[str, Any]:
"""Execute student code submission"""
sandbox = None
try:
# Create isolated sandbox for this submission
sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=timeout + 5 # Extra buffer
)
# Execute code
result = sandbox.run_code(code, language=language, timeout=timeout)
return {
"success": result.success,
"stdout": result.stdout,
"stderr": result.stderr,
"exit_code": result.exit_code,
"execution_time": result.execution_time,
"timeout": result.execution_time >= timeout
}
except Exception as e:
return {
"success": False,
"error": str(e),
"stderr": str(e)
}
finally:
if sandbox:
sandbox.kill()
def validate_solution(self, code: str, test_cases: List[Dict], language: str = "python") -> Dict[str, Any]:
"""Validate solution against test cases"""
results = []
all_passed = True
for i, test_case in enumerate(test_cases):
# Prepare test code
test_code = self._prepare_test_code(code, test_case, language)
# Execute
execution_result = self.execute_submission(test_code, language, timeout=5)
# Check result
passed = self._check_test_result(execution_result, test_case)
results.append({
"test_case": i + 1,
"passed": passed,
"input": test_case.get("input"),
"expected": test_case.get("expected"),
"actual": execution_result.get("stdout", "").strip(),
"error": execution_result.get("stderr") if not passed else None
})
if not passed:
all_passed = False
return {
"all_passed": all_passed,
"total_tests": len(test_cases),
"passed_tests": sum(1 for r in results if r["passed"]),
"results": results
}
def _prepare_test_code(self, code: str, test_case: Dict, language: str) -> str:
"""Prepare code with test case"""
if language == "python":
input_data = test_case.get("input", "")
expected = test_case.get("expected", "")
# Wrap student code with test
test_code = f"""
{code}
# Test case
test_input = {input_data}
result = solution(test_input) # Assuming function named 'solution'
expected = {expected}
if result == expected:
print("PASS")
else:
print(f"FAIL: Expected {{expected}}, got {{result}}")
"""
return test_code
else:
# Similar for other languages
return code
def _check_test_result(self, execution_result: Dict, test_case: Dict) -> bool:
"""Check if test case passed"""
if not execution_result.get("success"):
return False
stdout = execution_result.get("stdout", "").strip()
return "PASS" in stdout or stdout == str(test_case.get("expected", "")).strip()
# Usage
platform = CodingPlatform(api_key=os.getenv("HOPX_API_KEY"))
# Student submission
student_code = """
def solution(nums):
return sum(nums)
"""
# Test cases
test_cases = [
{"input": "[1, 2, 3]", "expected": 6},
{"input": "[10, 20, 30]", "expected": 60},
{"input": "[]", "expected": 0}
]
# Validate
result = platform.validate_solution(student_code, test_cases)
print(json.dumps(result, indent=2))
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class CodingPlatform {
constructor(apiKey) {
this.apiKey = apiKey;
}
async executeSubmission(code, language, timeout = 10) {
let sandbox = null;
try {
// Create isolated sandbox for this submission
sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: timeout + 5 // Extra buffer
});
// Execute code
const result = await sandbox.runCode(code, {
language,
timeout
});
return {
success: result.success,
stdout: result.stdout,
stderr: result.stderr,
exitCode: result.exit_code,
executionTime: result.execution_time,
timeout: result.execution_time >= timeout
};
} catch (error) {
return {
success: false,
error: error.message,
stderr: error.toString()
};
} finally {
if (sandbox) {
await sandbox.kill();
}
}
}
async validateSolution(code, testCases, language = 'python') {
const results = [];
let allPassed = true;
for (let i = 0; i < testCases.length; i++) {
const testCase = testCases[i];
// Prepare test code
const testCode = this.prepareTestCode(code, testCase, language);
// Execute
const executionResult = await this.executeSubmission(testCode, language, 5);
// Check result
const passed = this.checkTestResult(executionResult, testCase);
results.push({
testCase: i + 1,
passed,
input: testCase.input,
expected: testCase.expected,
actual: executionResult.stdout ? executionResult.stdout.trim() : '',
error: !passed ? executionResult.stderr : null
});
if (!passed) {
allPassed = false;
}
}
return {
allPassed,
totalTests: testCases.length,
passedTests: results.filter(r => r.passed).length,
results
};
}
prepareTestCode(code, testCase, language) {
if (language === 'python') {
const inputData = testCase.input || '';
const expected = testCase.expected || '';
// Wrap student code with test
return `
${code}
# Test case
test_input = ${inputData}
result = solution(test_input) # Assuming function named 'solution'
expected = ${expected}
if result == expected:
print("PASS")
else:
print(f"FAIL: Expected {expected}, got {result}")
`;
} else {
// Similar for other languages
return code;
}
}
checkTestResult(executionResult, testCase) {
if (!executionResult.success) {
return false;
}
const stdout = executionResult.stdout ? executionResult.stdout.trim() : '';
return stdout.includes('PASS') || stdout === String(testCase.expected).trim();
}
}
// Usage
const platform = new CodingPlatform(process.env.HOPX_API_KEY);
// Student submission
const studentCode = `
def solution(nums):
return sum(nums)
`;
// Test cases
const testCases = [
{ input: '[1, 2, 3]', expected: 6 },
{ input: '[10, 20, 30]', expected: 60 },
{ input: '[]', expected: 0 }
];
// Validate
const result = await platform.validateSolution(studentCode, testCases);
console.log(JSON.stringify(result, null, 2));
```
### Step 2: Multi-Language Support
Support multiple programming languages:
```python Python theme={null}
class MultiLanguagePlatform(CodingPlatform):
SUPPORTED_LANGUAGES = {
"python": {
"template": "code-interpreter",
"extension": ".py",
"runner": "python"
},
"javascript": {
"template": "code-interpreter",
"extension": ".js",
"runner": "node"
},
"java": {
"template": "code-interpreter",
"extension": ".java",
"runner": "javac && java"
}
}
def execute_submission(self, code: str, language: str, timeout: int = 10) -> Dict[str, Any]:
"""Execute code in specified language"""
if language not in self.SUPPORTED_LANGUAGES:
return {
"success": False,
"error": f"Unsupported language: {language}"
}
lang_config = self.SUPPORTED_LANGUAGES[language]
sandbox = None
try:
sandbox = Sandbox.create(
template=lang_config["template"],
api_key=self.api_key,
timeout_seconds=timeout + 5
)
# Write code to file
filename = f"/workspace/solution{lang_config['extension']}"
sandbox.files.write(filename, code)
# Execute based on language
if language == "python":
result = sandbox.run_code(code, language="python", timeout=timeout)
elif language == "javascript":
result = sandbox.run_code(code, language="javascript", timeout=timeout)
elif language == "java":
# Compile and run Java
compile_result = sandbox.commands.run(
f"javac {filename}",
timeout=5
)
if not compile_result.exit_code == 0:
return {
"success": False,
"stderr": compile_result.stderr,
"error": "Compilation failed"
}
# Run compiled class
result = sandbox.commands.run(
"java -cp /workspace Solution",
timeout=timeout
)
return {
"success": result.success if hasattr(result, 'success') else result.exit_code == 0,
"stdout": result.stdout if hasattr(result, 'stdout') else result.stdout,
"stderr": result.stderr if hasattr(result, 'stderr') else result.stderr,
"exit_code": result.exit_code if hasattr(result, 'exit_code') else result.exit_code,
"language": language
}
except Exception as e:
return {
"success": False,
"error": str(e),
"language": language
}
finally:
if sandbox:
sandbox.kill()
# Usage
platform = MultiLanguagePlatform(api_key=os.getenv("HOPX_API_KEY"))
# Python submission
python_code = "print('Hello from Python!')"
result = platform.execute_submission(python_code, "python")
print(result)
# JavaScript submission
js_code = "console.log('Hello from JavaScript!');"
result = platform.execute_submission(js_code, "javascript")
print(result)
```
```javascript JavaScript theme={null}
class MultiLanguagePlatform extends CodingPlatform {
constructor(apiKey) {
super(apiKey);
this.supportedLanguages = {
python: {
template: 'code-interpreter',
extension: '.py',
runner: 'python'
},
javascript: {
template: 'code-interpreter',
extension: '.js',
runner: 'node'
},
java: {
template: 'code-interpreter',
extension: '.java',
runner: 'javac && java'
}
};
}
async executeSubmission(code, language, timeout = 10) {
if (!this.supportedLanguages[language]) {
return {
success: false,
error: `Unsupported language: ${language}`
};
}
const langConfig = this.supportedLanguages[language];
let sandbox = null;
try {
sandbox = await Sandbox.create({
template: langConfig.template,
apiKey: this.apiKey,
timeoutSeconds: timeout + 5
});
// Write code to file
const filename = `/workspace/solution${langConfig.extension}`;
await sandbox.files.write(filename, code);
// Execute based on language
let result;
if (language === 'python') {
result = await sandbox.runCode(code, { language: 'python', timeout });
} else if (language === 'javascript') {
result = await sandbox.runCode(code, { language: 'javascript', timeout });
} else if (language === 'java') {
// Compile and run Java
const compileResult = await sandbox.commands.run(
`javac ${filename}`,
{ timeout: 5 }
);
if (compileResult.exit_code !== 0) {
return {
success: false,
stderr: compileResult.stderr,
error: 'Compilation failed'
};
}
// Run compiled class
result = await sandbox.commands.run(
'java -cp /workspace Solution',
{ timeout }
);
}
return {
success: result.success !== undefined ? result.success : result.exit_code === 0,
stdout: result.stdout || '',
stderr: result.stderr || '',
exitCode: result.exit_code || result.exit_code,
language
};
} catch (error) {
return {
success: false,
error: error.message,
language
};
} finally {
if (sandbox) {
await sandbox.kill();
}
}
}
}
// Usage
const platform = new MultiLanguagePlatform(process.env.HOPX_API_KEY);
// Python submission
const pythonCode = "print('Hello from Python!')";
const result1 = await platform.executeSubmission(pythonCode, 'python');
console.log(result1);
// JavaScript submission
const jsCode = "console.log('Hello from JavaScript!');";
const result2 = await platform.executeSubmission(jsCode, 'javascript');
console.log(result2);
```
### Step 3: Resource Limits and Timeout Management
Implement resource limits to prevent abuse:
```python Python theme={null}
class ResourceLimitedPlatform(CodingPlatform):
def __init__(self, api_key: str, max_execution_time: int = 10, max_memory_mb: int = 512):
super().__init__(api_key)
self.max_execution_time = max_execution_time
self.max_memory_mb = max_memory_mb
def execute_submission(self, code: str, language: str, timeout: int = None) -> Dict[str, Any]:
"""Execute with resource limits"""
# Enforce maximum timeout
actual_timeout = min(timeout or self.max_execution_time, self.max_execution_time)
sandbox = None
try:
# Create sandbox with resource limits
sandbox = Sandbox.create(
template="code-interpreter", # Template defines resources
api_key=self.api_key,
timeout_seconds=actual_timeout + 2 # Small buffer
)
# Set environment variables for resource monitoring
sandbox.env.set_all({
"MAX_EXECUTION_TIME": str(actual_timeout),
"MAX_MEMORY_MB": str(self.max_memory_mb)
})
# Execute with strict timeout
result = sandbox.run_code(code, language=language, timeout=actual_timeout)
# Check if timeout was exceeded
if result.execution_time >= actual_timeout:
return {
"success": False,
"error": "Execution timeout exceeded",
"timeout": True,
"execution_time": result.execution_time
}
# Check memory usage (if available)
metrics = sandbox.get_metrics_snapshot()
memory_used = metrics.get('memory_usage_mb', 0) if hasattr(metrics, 'get') else 0
if memory_used > self.max_memory_mb:
return {
"success": False,
"error": f"Memory limit exceeded: {memory_used}MB > {self.max_memory_mb}MB",
"memory_exceeded": True
}
return {
"success": result.success,
"stdout": result.stdout,
"stderr": result.stderr,
"execution_time": result.execution_time,
"memory_used_mb": memory_used
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
finally:
if sandbox:
sandbox.kill()
# Usage
platform = ResourceLimitedPlatform(
api_key=os.getenv("HOPX_API_KEY"),
max_execution_time=5, # 5 second limit
max_memory_mb=256 # 256MB limit
)
result = platform.execute_submission("print('Hello')", "python")
print(result)
```
```javascript JavaScript theme={null}
class ResourceLimitedPlatform extends CodingPlatform {
constructor(apiKey, maxExecutionTime = 10, maxMemoryMB = 512) {
super(apiKey);
this.maxExecutionTime = maxExecutionTime;
this.maxMemoryMB = maxMemoryMB;
}
async executeSubmission(code, language, timeout = null) {
// Enforce maximum timeout
const actualTimeout = Math.min(timeout || this.maxExecutionTime, this.maxExecutionTime);
let sandbox = null;
try {
// Create sandbox with resource limits
sandbox = await Sandbox.create({
template: 'code-interpreter', // Template defines resources
apiKey: this.apiKey,
timeoutSeconds: actualTimeout + 2 // Small buffer
});
// Set environment variables for resource monitoring
await sandbox.env.setAll({
MAX_EXECUTION_TIME: String(actualTimeout),
MAX_MEMORY_MB: String(this.maxMemoryMB)
});
// Execute with strict timeout
const result = await sandbox.runCode(code, {
language,
timeout: actualTimeout
});
// Check if timeout was exceeded
if (result.execution_time >= actualTimeout) {
return {
success: false,
error: 'Execution timeout exceeded',
timeout: true,
executionTime: result.execution_time
};
}
// Check memory usage (if available)
const metrics = await sandbox.getSystemMetrics();
const memoryUsed = metrics.memory_usage_mb || 0;
if (memoryUsed > this.maxMemoryMB) {
return {
success: false,
error: `Memory limit exceeded: ${memoryUsed}MB > ${this.maxMemoryMB}MB`,
memoryExceeded: true
};
}
return {
success: result.success,
stdout: result.stdout,
stderr: result.stderr,
executionTime: result.execution_time,
memoryUsedMB: memoryUsed
};
} catch (error) {
return {
success: false,
error: error.message
};
} finally {
if (sandbox) {
await sandbox.kill();
}
}
}
}
// Usage
const platform = new ResourceLimitedPlatform(
process.env.HOPX_API_KEY,
5, // 5 second limit
256 // 256MB limit
);
const result = await platform.executeSubmission("print('Hello')", 'python');
console.log(result);
```
### Step 4: Grading and Feedback System
Create a comprehensive grading system:
```python Python theme={null}
class GradingSystem:
def __init__(self, platform: CodingPlatform):
self.platform = platform
def grade_submission(self, code: str, problem: Dict, language: str = "python") -> Dict[str, Any]:
"""Grade a student submission"""
# Validate solution
validation_result = self.platform.validate_solution(
code,
problem.get("test_cases", []),
language
)
# Calculate score
score = self._calculate_score(validation_result, problem)
# Generate feedback
feedback = self._generate_feedback(validation_result, problem)
return {
"score": score,
"max_score": problem.get("max_score", 100),
"percentage": (score / problem.get("max_score", 100)) * 100,
"all_tests_passed": validation_result["all_passed"],
"test_results": validation_result["results"],
"feedback": feedback,
"submission_time": self._get_timestamp()
}
def _calculate_score(self, validation_result: Dict, problem: Dict) -> float:
"""Calculate score based on test results"""
if validation_result["all_passed"]:
return problem.get("max_score", 100)
# Partial credit based on passed tests
passed = validation_result["passed_tests"]
total = validation_result["total_tests"]
max_score = problem.get("max_score", 100)
return (passed / total) * max_score
def _generate_feedback(self, validation_result: Dict, problem: Dict) -> str:
"""Generate feedback for student"""
if validation_result["all_passed"]:
return "Excellent! All test cases passed."
failed_tests = [r for r in validation_result["results"] if not r["passed"]]
feedback = f"Some test cases failed ({len(failed_tests)}/{validation_result['total_tests']}).\n\n"
for test in failed_tests[:3]: # Show first 3 failures
feedback += f"Test {test['test_case']}: Expected {test['expected']}, got {test['actual']}\n"
if test.get("error"):
feedback += f" Error: {test['error']}\n"
return feedback
def _get_timestamp(self) -> str:
from datetime import datetime
return datetime.now().isoformat()
# Usage
platform = CodingPlatform(api_key=os.getenv("HOPX_API_KEY"))
grader = GradingSystem(platform)
problem = {
"title": "Sum of Array",
"description": "Write a function that returns the sum of all elements in an array",
"max_score": 100,
"test_cases": [
{"input": "[1, 2, 3]", "expected": 6},
{"input": "[10, 20, 30]", "expected": 60},
{"input": "[]", "expected": 0}
]
}
student_code = """
def solution(nums):
return sum(nums)
"""
grade = grader.grade_submission(student_code, problem)
print(json.dumps(grade, indent=2))
```
```javascript JavaScript theme={null}
class GradingSystem {
constructor(platform) {
this.platform = platform;
}
async gradeSubmission(code, problem, language = 'python') {
// Validate solution
const validationResult = await this.platform.validateSolution(
code,
problem.testCases || [],
language
);
// Calculate score
const score = this.calculateScore(validationResult, problem);
// Generate feedback
const feedback = this.generateFeedback(validationResult, problem);
return {
score,
maxScore: problem.maxScore || 100,
percentage: (score / (problem.maxScore || 100)) * 100,
allTestsPassed: validationResult.allPassed,
testResults: validationResult.results,
feedback,
submissionTime: new Date().toISOString()
};
}
calculateScore(validationResult, problem) {
if (validationResult.allPassed) {
return problem.maxScore || 100;
}
// Partial credit based on passed tests
const passed = validationResult.passedTests;
const total = validationResult.totalTests;
const maxScore = problem.maxScore || 100;
return (passed / total) * maxScore;
}
generateFeedback(validationResult, problem) {
if (validationResult.allPassed) {
return 'Excellent! All test cases passed.';
}
const failedTests = validationResult.results.filter(r => !r.passed);
let feedback = `Some test cases failed (${failedTests.length}/${validationResult.totalTests}).\n\n`;
for (const test of failedTests.slice(0, 3)) { // Show first 3 failures
feedback += `Test ${test.testCase}: Expected ${test.expected}, got ${test.actual}\n`;
if (test.error) {
feedback += ` Error: ${test.error}\n`;
}
}
return feedback;
}
}
// Usage
const platform = new CodingPlatform(process.env.HOPX_API_KEY);
const grader = new GradingSystem(platform);
const problem = {
title: 'Sum of Array',
description: 'Write a function that returns the sum of all elements in an array',
maxScore: 100,
testCases: [
{ input: '[1, 2, 3]', expected: 6 },
{ input: '[10, 20, 30]', expected: 60 },
{ input: '[]', expected: 0 }
]
};
const studentCode = `
def solution(nums):
return sum(nums)
`;
const grade = await grader.gradeSubmission(studentCode, problem);
console.log(JSON.stringify(grade, null, 2));
```
## Best Practices
### Security
Always create a fresh sandbox for each student submission to ensure complete isolation between submissions.
1. **Sandbox Isolation**: Never reuse sandboxes between different students
2. **Code Validation**: Check for dangerous patterns before execution
3. **Resource Limits**: Enforce strict timeouts and memory limits
4. **Input Sanitization**: Validate all inputs before processing
### Performance
Use parallel execution for multiple test cases when possible, but ensure each test case runs in isolation.
1. **Sandbox Pooling**: Consider sandbox pooling for high-volume platforms
2. **Caching**: Cache problem definitions and test cases
3. **Async Processing**: Process submissions asynchronously for better scalability
4. **Resource Monitoring**: Monitor sandbox usage and optimize accordingly
### Educational Value
1. **Clear Feedback**: Provide detailed, actionable feedback
2. **Progressive Difficulty**: Structure problems from easy to hard
3. **Hints System**: Offer hints without revealing solutions
4. **Performance Metrics**: Track execution time and memory usage
## Real-World Examples
This pattern is used by:
* **LeetCode**: Online coding interview platform
* **HackerRank**: Competitive programming platform
* **Codecademy**: Interactive coding lessons
* **Educational Platforms**: Various platforms that provide secure code execution for students
## Related Cookbooks
* [Interactive Programming Tutorials](/cookbooks/educational/interactive-tutorials) - Step-by-step learning
* [Coding Interview Platform](/cookbooks/educational/coding-interviews) - Interview preparation
* [Isolated Test Execution](/cookbooks/testing/isolated-test-execution) - Test isolation strategies
## Next Steps
1. Implement your problem database
2. Add user authentication and submission tracking
3. Create a web interface for code submission
4. Implement leaderboards and progress tracking
5. Add support for more programming languages
# Low-Code Platform Backend
Source: https://docs.hopx.ai/cookbooks/enterprise/low-code-backend
Build a low-code/no-code platform backend with visual to code translation, script execution, integration patterns, and custom logic execution
Build a production-ready low-code platform backend that translates visual workflows to code and executes them. This cookbook demonstrates how to create a platform similar to Zapier or Microsoft Power Automate using HopX.
## Overview
Low-code platforms allow users to build applications visually without writing code. The backend translates visual workflows to executable code, executes scripts, handles integrations, and runs custom logic.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of workflow engines
* Basic knowledge of code generation
## Architecture
```
┌──────────────┐
│ Visual │ Workflow definition
│ Workflow │
└──────┬───────┘
│
▼
┌─────────────────┐
│ Code │ Translate to code
│ Generator │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandbox │ Execute generated code
└─────────────────┘
```
## Implementation
### Step 1: Visual to Code Translation
Translate visual workflows to executable code:
```python Python theme={null}
from hopx_ai import Sandbox
import os
from typing import Dict, Any, List
class WorkflowNode:
def __init__(self, node_id: str, node_type: str, config: Dict[str, Any]):
self.node_id = node_id
self.node_type = node_type
self.config = config
class LowCodeBackend:
def __init__(self, api_key: str):
self.api_key = api_key
self.sandbox = None
def initialize(self):
"""Initialize backend"""
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=3600
)
def translate_workflow(self, nodes: List[WorkflowNode]) -> str:
"""Translate visual workflow to code"""
code_parts = []
for node in nodes:
if node.node_type == "trigger":
code_parts.append(f"# Trigger: {node.config.get('name', '')}")
elif node.node_type == "action":
action_code = self._generate_action_code(node)
code_parts.append(action_code)
elif node.node_type == "condition":
condition_code = self._generate_condition_code(node)
code_parts.append(condition_code)
return "\n".join(code_parts)
def _generate_action_code(self, node: WorkflowNode) -> str:
"""Generate code for action node"""
action_type = node.config.get("action_type", "")
if action_type == "http_request":
return f"""
import requests
response = requests.{node.config.get('method', 'get').lower()}('{node.config.get('url', '')}')
print(response.text)
"""
elif action_type == "data_transform":
return f"""
data = {node.config.get('data', '{}')}
# Transform data
result = data
print(result)
"""
else:
return f"# Action: {action_type}"
def _generate_condition_code(self, node: WorkflowNode) -> str:
"""Generate code for condition node"""
condition = node.config.get("condition", "")
return f"""
if {condition}:
# Condition met
pass
else:
# Condition not met
pass
"""
def execute_workflow(self, nodes: List[WorkflowNode]) -> Dict[str, Any]:
"""Execute visual workflow"""
try:
# Translate to code
code = self.translate_workflow(nodes)
# Execute
result = self.sandbox.run_code(code, timeout=60)
return {
"success": result.success,
"stdout": result.stdout,
"stderr": result.stderr,
"generated_code": code
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def cleanup(self):
"""Clean up backend resources"""
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
# Usage
backend = LowCodeBackend(api_key=os.getenv("HOPX_API_KEY"))
backend.initialize()
# Define workflow
nodes = [
WorkflowNode("node_1", "trigger", {"name": "webhook"}),
WorkflowNode("node_2", "action", {
"action_type": "http_request",
"method": "GET",
"url": "https://api.example.com/data"
})
]
result = backend.execute_workflow(nodes)
print(result)
backend.cleanup()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class WorkflowNode {
constructor(nodeId, nodeType, config) {
this.nodeId = nodeId;
this.nodeType = nodeType;
this.config = config;
}
}
class LowCodeBackend {
constructor(apiKey) {
this.apiKey = apiKey;
this.sandbox = null;
}
async initialize() {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: 3600
});
}
translateWorkflow(nodes) {
const codeParts = [];
for (const node of nodes) {
if (node.nodeType === 'trigger') {
codeParts.push(`# Trigger: ${node.config.name || ''}`);
} else if (node.nodeType === 'action') {
codeParts.push(this.generateActionCode(node));
} else if (node.nodeType === 'condition') {
codeParts.push(this.generateConditionCode(node));
}
}
return codeParts.join('\n');
}
generateActionCode(node) {
const actionType = node.config.actionType || '';
if (actionType === 'http_request') {
return `
import requests
response = requests.${(node.config.method || 'get').toLowerCase()}('${node.config.url || ''}')
print(response.text)
`;
} else if (actionType === 'data_transform') {
return `
data = ${JSON.stringify(node.config.data || {})}
# Transform data
result = data
print(result)
`;
} else {
return `# Action: ${actionType}`;
}
}
generateConditionCode(node) {
const condition = node.config.condition || '';
return `
if ${condition}:
# Condition met
pass
else:
# Condition not met
pass
`;
}
async executeWorkflow(nodes) {
try {
// Translate to code
const code = this.translateWorkflow(nodes);
// Execute
const result = await this.sandbox.runCode(code, { timeout: 60 });
return {
success: result.success,
stdout: result.stdout,
stderr: result.stderr,
generatedCode: code
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
// Usage
const backend = new LowCodeBackend(process.env.HOPX_API_KEY);
await backend.initialize();
// Define workflow
const nodes = [
new WorkflowNode('node_1', 'trigger', { name: 'webhook' }),
new WorkflowNode('node_2', 'action', {
actionType: 'http_request',
method: 'GET',
url: 'https://api.example.com/data'
})
];
const result = await backend.executeWorkflow(nodes);
console.log(result);
await backend.cleanup();
```
## Best Practices
1. **Code Generation**: Generate clean, maintainable code
2. **Error Handling**: Handle translation errors gracefully
3. **Integration Patterns**: Support common integration patterns
4. **Custom Logic**: Allow custom code injection
## Related Cookbooks
* [User-Defined Functions](/cookbooks/marketplace/user-functions) - Custom functions
* [Multi-Tenant Execution](/cookbooks/enterprise/multi-tenant-execution) - Multi-tenant patterns
## Next Steps
1. Implement visual workflow builder
2. Add more node types
3. Create integration library
4. Implement workflow versioning
5. Add workflow monitoring
# Multi-Tenant Code Execution Platform
Source: https://docs.hopx.ai/cookbooks/enterprise/multi-tenant-execution
Build a SaaS platform with custom code execution featuring tenant isolation, resource quotas, security boundaries, and billing integration
Build a production-ready multi-tenant code execution platform for SaaS applications. This cookbook demonstrates how to create a platform with tenant isolation, resource quotas, and security boundaries using HopX.
## Overview
Multi-tenant platforms serve multiple customers (tenants) on shared infrastructure. Each tenant's code must be completely isolated, resources must be quota-limited, and security boundaries must be enforced.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of multi-tenant architecture
* Basic knowledge of resource quotas
## Architecture
```
┌──────────────┐
│ Tenant A │ Code execution
└──────┬───────┘
│
▼
┌─────────────────┐
│ Tenant │ Isolate, quota
│ Manager │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Tenant │ Isolated sandbox
│ Sandbox A │
└─────────────────┘
```
## Implementation
### Step 1: Tenant Isolation
Ensure complete tenant isolation:
```python Python theme={null}
from hopx_ai import Sandbox
import os
from typing import Dict, Any
class Tenant:
def __init__(self, tenant_id: str, quota: Dict[str, int]):
self.tenant_id = tenant_id
self.quota = quota # {"executions_per_hour": 100, "max_execution_time": 60}
class MultiTenantPlatform:
def __init__(self, api_key: str):
self.api_key = api_key
self.tenants = {}
self.tenant_sandboxes = {}
self.usage_tracking = {}
def register_tenant(self, tenant: Tenant):
"""Register a tenant"""
self.tenants[tenant.tenant_id] = tenant
self.usage_tracking[tenant.tenant_id] = {
"executions": 0,
"execution_time": 0
}
def execute_for_tenant(self, tenant_id: str, code: str) -> Dict[str, Any]:
"""Execute code for specific tenant"""
if tenant_id not in self.tenants:
return {
"success": False,
"error": f"Tenant {tenant_id} not found"
}
tenant = self.tenants[tenant_id]
usage = self.usage_tracking[tenant_id]
# Check quota
if usage["executions"] >= tenant.quota.get("executions_per_hour", 100):
return {
"success": False,
"error": "Execution quota exceeded"
}
sandbox = None
try:
# Create or get tenant sandbox (isolated per tenant)
if tenant_id not in self.tenant_sandboxes:
self.tenant_sandboxes[tenant_id] = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=tenant.quota.get("max_execution_time", 60)
)
sandbox = self.tenant_sandboxes[tenant_id]
# Set tenant context
sandbox.env.set("TENANT_ID", tenant_id)
# Execute code
result = sandbox.run_code(code, timeout=tenant.quota.get("max_execution_time", 60))
# Update usage
usage["executions"] += 1
usage["execution_time"] += result.execution_time
return {
"success": result.success,
"stdout": result.stdout,
"stderr": result.stderr,
"tenant_id": tenant_id,
"usage": usage
}
except Exception as e:
return {
"success": False,
"error": str(e),
"tenant_id": tenant_id
}
def get_tenant_usage(self, tenant_id: str) -> Dict[str, Any]:
"""Get tenant usage statistics"""
if tenant_id not in self.usage_tracking:
return {"error": "Tenant not found"}
return self.usage_tracking[tenant_id]
def cleanup_tenant(self, tenant_id: str):
"""Clean up tenant resources"""
if tenant_id in self.tenant_sandboxes:
self.tenant_sandboxes[tenant_id].kill()
del self.tenant_sandboxes[tenant_id]
# Usage
platform = MultiTenantPlatform(api_key=os.getenv("HOPX_API_KEY"))
# Register tenants
platform.register_tenant(Tenant("tenant_1", {"executions_per_hour": 100, "max_execution_time": 60}))
platform.register_tenant(Tenant("tenant_2", {"executions_per_hour": 200, "max_execution_time": 120}))
# Execute for tenant
result = platform.execute_for_tenant("tenant_1", "print('Hello from tenant 1')")
print(result)
usage = platform.get_tenant_usage("tenant_1")
print(usage)
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class Tenant {
constructor(tenantId, quota) {
this.tenantId = tenantId;
this.quota = quota; // {executionsPerHour: 100, maxExecutionTime: 60}
}
}
class MultiTenantPlatform {
constructor(apiKey) {
this.apiKey = apiKey;
this.tenants = {};
this.tenantSandboxes = {};
this.usageTracking = {};
}
registerTenant(tenant) {
this.tenants[tenant.tenantId] = tenant;
this.usageTracking[tenant.tenantId] = {
executions: 0,
executionTime: 0
};
}
async executeForTenant(tenantId, code) {
if (!this.tenants[tenantId]) {
return {
success: false,
error: `Tenant ${tenantId} not found`
};
}
const tenant = this.tenants[tenantId];
const usage = this.usageTracking[tenantId];
// Check quota
if (usage.executions >= (tenant.quota.executionsPerHour || 100)) {
return {
success: false,
error: 'Execution quota exceeded'
};
}
try {
// Create or get tenant sandbox (isolated per tenant)
if (!this.tenantSandboxes[tenantId]) {
this.tenantSandboxes[tenantId] = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: tenant.quota.maxExecutionTime || 60
});
}
const sandbox = this.tenantSandboxes[tenantId];
// Set tenant context
await sandbox.env.set('TENANT_ID', tenantId);
// Execute code
const result = await sandbox.runCode(code, {
timeout: tenant.quota.maxExecutionTime || 60
});
// Update usage
usage.executions += 1;
usage.executionTime += result.execution_time || 0;
return {
success: result.success,
stdout: result.stdout,
stderr: result.stderr,
tenantId,
usage
};
} catch (error) {
return {
success: false,
error: error.message,
tenantId
};
}
}
getTenantUsage(tenantId) {
if (!this.usageTracking[tenantId]) {
return { error: 'Tenant not found' };
}
return this.usageTracking[tenantId];
}
async cleanupTenant(tenantId) {
if (this.tenantSandboxes[tenantId]) {
await this.tenantSandboxes[tenantId].kill();
delete this.tenantSandboxes[tenantId];
}
}
}
// Usage
const platform = new MultiTenantPlatform(process.env.HOPX_API_KEY);
// Register tenants
platform.registerTenant(new Tenant('tenant_1', { executionsPerHour: 100, maxExecutionTime: 60 }));
platform.registerTenant(new Tenant('tenant_2', { executionsPerHour: 200, maxExecutionTime: 120 }));
// Execute for tenant
const result = await platform.executeForTenant('tenant_1', "print('Hello from tenant 1')");
console.log(result);
const usage = platform.getTenantUsage('tenant_1');
console.log(usage);
```
## Best Practices
1. **Complete Isolation**: One sandbox per tenant
2. **Resource Quotas**: Enforce strict quotas
3. **Security Boundaries**: Maintain security between tenants
4. **Usage Tracking**: Track usage for billing
## Related Cookbooks
* [Plugin System](/cookbooks/marketplace/plugin-system) - Plugin isolation
* [Low-Code Platform Backend](/cookbooks/enterprise/low-code-backend) - Enterprise platforms
## Next Steps
1. Implement billing integration
2. Add tenant management UI
3. Create usage analytics
4. Implement quota enforcement
5. Add tenant onboarding
# Plugin System with Code Execution
Source: https://docs.hopx.ai/cookbooks/marketplace/plugin-system
Build a WordPress/Shopify-style plugin marketplace with untrusted code execution, permission systems, API access control, and sandbox isolation
Build a production-ready plugin system that safely executes untrusted code from third-party developers. This cookbook demonstrates how to create a plugin marketplace with security isolation using HopX.
## Overview
Plugin systems allow third-party developers to extend platform functionality. The system must execute untrusted code safely, enforce permissions, control API access, and maintain complete isolation between plugins.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of security isolation
* Basic knowledge of permission systems
## Architecture
```
┌──────────────┐
│ Plugin │ Untrusted code
└──────┬───────┘
│
▼
┌─────────────────┐
│ Plugin │ Validate, isolate
│ Manager │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Isolated │ One per plugin
│ Sandbox │
└─────────────────┘
```
## Implementation
### Step 1: Plugin Execution with Isolation
Execute plugins in isolated sandboxes:
```python Python theme={null}
from hopx_ai import Sandbox
import os
from typing import Dict, Any, List
class Plugin:
def __init__(self, plugin_id: str, code: str, permissions: List[str]):
self.plugin_id = plugin_id
self.code = code
self.permissions = permissions
class PluginSystem:
def __init__(self, api_key: str):
self.api_key = api_key
self.plugins = {}
self.plugin_sandboxes = {}
def register_plugin(self, plugin: Plugin):
"""Register a plugin"""
self.plugins[plugin.plugin_id] = plugin
def execute_plugin(self, plugin_id: str, context: Dict[str, Any] = None) -> Dict[str, Any]:
"""Execute plugin in isolated sandbox"""
if plugin_id not in self.plugins:
return {
"success": False,
"error": f"Plugin {plugin_id} not found"
}
plugin = self.plugins[plugin_id]
sandbox = None
try:
# Create fresh sandbox for each execution
sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=60
)
# Set up plugin environment with limited permissions
env_vars = {
"PLUGIN_ID": plugin_id,
"PERMISSIONS": ",".join(plugin.permissions)
}
sandbox.env.set_all(env_vars)
# Add context if provided
if context:
for key, value in context.items():
sandbox.env.set(f"CONTEXT_{key}", str(value))
# Execute plugin code
result = sandbox.run_code(plugin.code, timeout=30)
return {
"success": result.success,
"stdout": result.stdout,
"stderr": result.stderr,
"plugin_id": plugin_id
}
except Exception as e:
return {
"success": False,
"error": str(e),
"plugin_id": plugin_id
}
finally:
if sandbox:
sandbox.kill() # Always cleanup
def cleanup_all(self):
"""Clean up all plugin resources"""
for sandbox in self.plugin_sandboxes.values():
sandbox.kill()
self.plugin_sandboxes.clear()
# Usage
system = PluginSystem(api_key=os.getenv("HOPX_API_KEY"))
# Register plugin
system.register_plugin(Plugin(
plugin_id="calculator",
code="result = 2 + 2\nprint(f'Result: {result}')",
permissions=["compute"]
))
# Execute
result = system.execute_plugin("calculator")
print(result)
system.cleanup_all()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class Plugin {
constructor(pluginId, code, permissions) {
this.pluginId = pluginId;
this.code = code;
this.permissions = permissions;
}
}
class PluginSystem {
constructor(apiKey) {
this.apiKey = apiKey;
this.plugins = {};
this.pluginSandboxes = {};
}
registerPlugin(plugin) {
this.plugins[plugin.pluginId] = plugin;
}
async executePlugin(pluginId, context = null) {
if (!this.plugins[pluginId]) {
return {
success: false,
error: `Plugin ${pluginId} not found`
};
}
const plugin = this.plugins[pluginId];
let sandbox = null;
try {
// Create fresh sandbox for each execution
sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: 60
});
// Set up plugin environment with limited permissions
const envVars = {
PLUGIN_ID: pluginId,
PERMISSIONS: plugin.permissions.join(',')
};
await sandbox.env.setAll(envVars);
// Add context if provided
if (context) {
for (const [key, value] of Object.entries(context)) {
await sandbox.env.set(`CONTEXT_${key}`, String(value));
}
}
// Execute plugin code
const result = await sandbox.runCode(plugin.code, { timeout: 30 });
return {
success: result.success,
stdout: result.stdout,
stderr: result.stderr,
pluginId
};
} catch (error) {
return {
success: false,
error: error.message,
pluginId
};
} finally {
if (sandbox) {
await sandbox.kill(); // Always cleanup
}
}
}
async cleanupAll() {
await Promise.all(
Object.values(this.pluginSandboxes).map(sandbox => sandbox.kill())
);
this.pluginSandboxes = {};
}
}
// Usage
const system = new PluginSystem(process.env.HOPX_API_KEY);
// Register plugin
system.registerPlugin(new Plugin(
'calculator',
"result = 2 + 2\nprint(f'Result: {result}')",
['compute']
));
// Execute
const result = await system.executePlugin('calculator');
console.log(result);
await system.cleanupAll();
```
## Best Practices
Always execute plugins in fresh, isolated sandboxes. Never trust plugin code or allow plugins to access system resources.
1. **Complete Isolation**: One sandbox per plugin execution
2. **Permission System**: Enforce permissions strictly
3. **Code Validation**: Validate plugin code before execution
4. **Resource Limits**: Set strict resource limits
## Related Cookbooks
* [Multi-Tenant Execution](/cookbooks/enterprise/multi-tenant-execution) - Multi-tenant patterns
* [User-Defined Functions](/cookbooks/marketplace/user-functions) - Custom functions
## Next Steps
1. Implement permission system
2. Add plugin marketplace features
3. Create plugin validation
4. Implement plugin versioning
5. Add plugin monitoring
# User-Defined Functions Platform
Source: https://docs.hopx.ai/cookbooks/marketplace/user-functions
Build a Zapier/Make.com-style workflow automation platform with custom function execution, workflow orchestration, data transformation, and error handling
Build a production-ready user-defined functions platform where users can create custom functions for workflow automation. This cookbook demonstrates how to create a platform similar to Zapier or Make.com using HopX.
## Overview
User-defined functions platforms allow users to create custom functions for workflow automation. Users write functions, the platform executes them in workflows, transforms data, and handles errors gracefully.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of workflow automation
* Basic knowledge of data transformation
## Architecture
```
┌──────────────┐
│ User │ Define function
└──────┬───────┘
│
▼
┌─────────────────┐
│ Workflow │ Orchestrate steps
│ Engine │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandbox │ Execute function
└─────────────────┘
```
## Implementation
### Step 1: User Function Execution
Execute user-defined functions:
```python Python theme={null}
from hopx_ai import Sandbox
import os
from typing import Dict, Any, List
class UserFunction:
def __init__(self, function_id: str, code: str, inputs: List[str], outputs: List[str]):
self.function_id = function_id
self.code = code
self.inputs = inputs
self.outputs = outputs
class UserFunctionPlatform:
def __init__(self, api_key: str):
self.api_key = api_key
self.functions = {}
self.sandbox = None
def initialize(self):
"""Initialize platform"""
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=3600
)
def register_function(self, function: UserFunction):
"""Register user function"""
self.functions[function.function_id] = function
def execute_function(self, function_id: str, inputs: Dict[str, Any]) -> Dict[str, Any]:
"""Execute user function with inputs"""
if function_id not in self.functions:
return {
"success": False,
"error": f"Function {function_id} not found"
}
function = self.functions[function_id]
try:
# Prepare function code with inputs
import json
function_code = f"""
import json
# Inputs
inputs = {json.dumps(inputs)}
# User function
{function.code}
"""
result = self.sandbox.run_code(function_code, timeout=30)
return {
"success": result.success,
"output": result.stdout,
"error": result.stderr if not result.success else None
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def cleanup(self):
"""Clean up platform resources"""
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
# Usage
platform = UserFunctionPlatform(api_key=os.getenv("HOPX_API_KEY"))
platform.initialize()
# Register function
platform.register_function(UserFunction(
function_id="add_numbers",
code="result = inputs['a'] + inputs['b']\nprint(result)",
inputs=["a", "b"],
outputs=["result"]
))
# Execute
result = platform.execute_function("add_numbers", {"a": 5, "b": 3})
print(result)
platform.cleanup()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class UserFunction {
constructor(functionId, code, inputs, outputs) {
this.functionId = functionId;
this.code = code;
this.inputs = inputs;
this.outputs = outputs;
}
}
class UserFunctionPlatform {
constructor(apiKey) {
this.apiKey = apiKey;
this.functions = {};
this.sandbox = null;
}
async initialize() {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: 3600
});
}
registerFunction(func) {
this.functions[func.functionId] = func;
}
async executeFunction(functionId, inputs) {
if (!this.functions[functionId]) {
return {
success: false,
error: `Function ${functionId} not found`
};
}
const func = this.functions[functionId];
try {
// Prepare function code with inputs
const functionCode = `
// Inputs
const inputs = ${JSON.stringify(inputs)};
// User function
${func.code}
`;
const result = await this.sandbox.runCode(functionCode, { timeout: 30 });
return {
success: result.success,
output: result.stdout,
error: !result.success ? result.stderr : null
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
// Usage
const platform = new UserFunctionPlatform(process.env.HOPX_API_KEY);
await platform.initialize();
// Register function
platform.registerFunction(new UserFunction(
'add_numbers',
"const result = inputs.a + inputs.b;\nconsole.log(result);",
['a', 'b'],
['result']
));
// Execute
const result = await platform.executeFunction('add_numbers', { a: 5, b: 3 });
console.log(result);
await platform.cleanup();
```
## Best Practices
1. **Function Validation**: Validate function code before execution
2. **Input Validation**: Validate inputs before passing to functions
3. **Error Handling**: Handle errors gracefully
4. **Workflow Orchestration**: Chain functions efficiently
## Related Cookbooks
* [Plugin System](/cookbooks/marketplace/plugin-system) - Plugin architecture
* [Low-Code Platform Backend](/cookbooks/enterprise/low-code-backend) - Enterprise platforms
## Next Steps
1. Implement workflow builder
2. Add function marketplace
3. Create workflow execution engine
4. Implement data transformation
5. Add workflow monitoring
# Custom Serverless Platform
Source: https://docs.hopx.ai/cookbooks/serverless/custom-functions
Build an AWS Lambda-style serverless platform with function execution, cold start optimization, event-driven execution, and resource allocation
Build a production-ready serverless platform that executes functions on-demand, optimizes cold starts, handles events, and manages resources. This cookbook demonstrates how to create a serverless platform similar to AWS Lambda using HopX.
## Overview
Serverless platforms execute functions in response to events without managing servers. The platform handles function execution, optimizes cold starts, routes events, and allocates resources dynamically. This pattern is used by platforms like AWS Lambda, Vercel Functions, and Netlify Functions.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of serverless architecture
* Basic knowledge of event-driven systems
## Architecture
```
┌──────────────┐
│ Event │ Trigger function
└──────┬───────┘
│
▼
┌─────────────────┐
│ Function │ Route & execute
│ Router │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandbox │ Function execution
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Response │ Return result
└─────────────────┘
```
## Implementation
### Step 1: Function Execution
Execute serverless functions:
```python Python theme={null}
from hopx_ai import Sandbox
import os
import json
from typing import Dict, Any, Callable
class ServerlessFunction:
def __init__(self, function_id: str, code: str, runtime: str = "python"):
self.function_id = function_id
self.code = code
self.runtime = runtime
self.sandbox = None
def initialize(self, api_key: str):
"""Initialize function sandbox"""
self.sandbox = Sandbox.create(
template="code-interpreter",
api_key=api_key,
timeout_seconds=300 # 5 minute timeout
)
def invoke(self, event: Dict[str, Any], context: Dict[str, Any] = None) -> Dict[str, Any]:
"""Invoke function with event"""
try:
# Prepare function code with event
function_code = f"""
import json
# Event data
event = {json.dumps(event)}
# Context data
context = {json.dumps(context or {})}
# User function
{self.code}
"""
# Execute function
result = self.sandbox.run_code(function_code, timeout=30)
return {
"success": result.success,
"result": result.stdout,
"error": result.stderr if not result.success else None,
"execution_time": result.execution_time
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
def cleanup(self):
"""Clean up function resources"""
if self.sandbox:
self.sandbox.kill()
self.sandbox = None
class ServerlessPlatform:
def __init__(self, api_key: str):
self.api_key = api_key
self.functions = {}
def register_function(self, function_id: str, code: str, runtime: str = "python"):
"""Register a serverless function"""
func = ServerlessFunction(function_id, code, runtime)
func.initialize(self.api_key)
self.functions[function_id] = func
def invoke_function(self, function_id: str, event: Dict[str, Any]) -> Dict[str, Any]:
"""Invoke registered function"""
if function_id not in self.functions:
return {
"success": False,
"error": f"Function {function_id} not found"
}
return self.functions[function_id].invoke(event)
def cleanup_all(self):
"""Clean up all functions"""
for func in self.functions.values():
func.cleanup()
# Usage
platform = ServerlessPlatform(api_key=os.getenv("HOPX_API_KEY"))
# Register function
platform.register_function(
"hello_world",
"""
def handler(event, context):
name = event.get('name', 'World')
return f"Hello, {name}!"
""",
"python"
)
# Invoke function
result = platform.invoke_function("hello_world", {"name": "HopX"})
print(result)
platform.cleanup_all()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class ServerlessFunction {
constructor(functionId, code, runtime = 'javascript') {
this.functionId = functionId;
this.code = code;
this.runtime = runtime;
this.sandbox = null;
}
async initialize(apiKey) {
this.sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey,
timeoutSeconds: 300 // 5 minute timeout
});
}
async invoke(event, context = null) {
try {
// Prepare function code with event
const functionCode = `
// Event data
const event = ${JSON.stringify(event)};
// Context data
const context = ${JSON.stringify(context || {})};
// User function
${this.code}
`;
// Execute function
const result = await this.sandbox.runCode(functionCode, {
language: this.runtime,
timeout: 30
});
return {
success: result.success,
result: result.stdout,
error: !result.success ? result.stderr : null,
executionTime: result.execution_time
};
} catch (error) {
return {
success: false,
error: error.message
};
}
}
async cleanup() {
if (this.sandbox) {
await this.sandbox.kill();
this.sandbox = null;
}
}
}
class ServerlessPlatform {
constructor(apiKey) {
this.apiKey = apiKey;
this.functions = {};
}
async registerFunction(functionId, code, runtime = 'javascript') {
const func = new ServerlessFunction(functionId, code, runtime);
await func.initialize(this.apiKey);
this.functions[functionId] = func;
}
async invokeFunction(functionId, event) {
if (!this.functions[functionId]) {
return {
success: false,
error: `Function ${functionId} not found`
};
}
return await this.functions[functionId].invoke(event);
}
async cleanupAll() {
await Promise.all(
Object.values(this.functions).map(func => func.cleanup())
);
}
}
// Usage
const platform = new ServerlessPlatform(process.env.HOPX_API_KEY);
// Register function
await platform.registerFunction(
'hello_world',
`
function handler(event, context) {
const name = event.name || 'World';
return \`Hello, \${name}!\`;
}
`,
'javascript'
);
// Invoke function
const result = await platform.invokeFunction('hello_world', { name: 'HopX' });
console.log(result);
await platform.cleanupAll();
```
### Step 2: Cold Start Optimization
Optimize function cold starts:
```python Python theme={null}
class OptimizedServerlessPlatform(ServerlessPlatform):
def __init__(self, api_key: str):
super().__init__(api_key)
self.warm_pool = {} # Keep sandboxes warm
def _warm_function(self, function_id: str):
"""Warm up function sandbox"""
if function_id not in self.warm_pool:
func = self.functions[function_id]
# Keep sandbox alive
self.warm_pool[function_id] = func.sandbox
def invoke_function_optimized(self, function_id: str, event: Dict[str, Any]) -> Dict[str, Any]:
"""Invoke with cold start optimization"""
# Warm function if not already warm
if function_id not in self.warm_pool:
self._warm_function(function_id)
return self.invoke_function(function_id, event)
# Usage
platform = OptimizedServerlessPlatform(api_key=os.getenv("HOPX_API_KEY"))
platform.register_function("my_function", "def handler(e, c): return 'OK'")
platform._warm_function("my_function") # Pre-warm
result = platform.invoke_function_optimized("my_function", {})
print(result)
```
```javascript JavaScript theme={null}
class OptimizedServerlessPlatform extends ServerlessPlatform {
constructor(apiKey) {
super(apiKey);
this.warmPool = {}; // Keep sandboxes warm
}
async warmFunction(functionId) {
if (!this.warmPool[functionId]) {
const func = this.functions[functionId];
// Keep sandbox alive
this.warmPool[functionId] = func.sandbox;
}
}
async invokeFunctionOptimized(functionId, event) {
// Warm function if not already warm
if (!this.warmPool[functionId]) {
await this.warmFunction(functionId);
}
return await this.invokeFunction(functionId, event);
}
}
// Usage
const platform = new OptimizedServerlessPlatform(process.env.HOPX_API_KEY);
await platform.registerFunction('my_function', "function handler(e, c) { return 'OK'; }");
await platform.warmFunction('my_function'); // Pre-warm
const result = await platform.invokeFunctionOptimized('my_function', {});
console.log(result);
```
## Best Practices
1. **Cold Start Optimization**: Pre-warm frequently used functions
2. **Resource Limits**: Set appropriate timeouts and memory limits
3. **Error Handling**: Handle errors gracefully
4. **Event Routing**: Route events efficiently
## Real-World Examples
This pattern is used by:
* **AWS Lambda**: Serverless compute service
* **Vercel Functions**: Serverless functions for web apps
* **Netlify Functions**: Serverless functions platform
## Related Cookbooks
* [Edge Function Execution](/cookbooks/serverless/edge-functions) - Edge computing
## Next Steps
1. Implement function versioning
2. Add event source integrations
3. Create function monitoring dashboard
4. Implement auto-scaling
5. Add function deployment pipeline
# Edge Function Execution
Source: https://docs.hopx.ai/cookbooks/serverless/edge-functions
Build edge computing functions with geographic distribution, low-latency execution, resource constraints, and request routing
Build a production-ready edge function execution platform that runs code close to users for low latency. This cookbook demonstrates how to create an edge computing platform using HopX.
## Overview
Edge functions execute code at geographic locations close to users, reducing latency. The platform routes requests to appropriate edge locations, executes functions with resource constraints, and returns results quickly.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of edge computing
* Basic knowledge of request routing
## Architecture
```
┌──────────────┐
│ User │ Request
└──────┬───────┘
│
▼
┌─────────────────┐
│ Edge Router │ Route to nearest
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Edge Sandbox │ Execute function
│ (Region-based) │
└─────────────────┘
```
## Implementation
### Step 1: Edge Function Execution
Execute functions at edge locations:
```python Python theme={null}
from hopx_ai import Sandbox
import os
from typing import Dict, Any
class EdgeFunctionPlatform:
def __init__(self, api_key: str):
self.api_key = api_key
self.edge_sandboxes = {} # Region -> sandbox mapping
def get_edge_sandbox(self, region: str) -> Sandbox:
"""Get or create edge sandbox for region"""
if region not in self.edge_sandboxes:
self.edge_sandboxes[region] = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=300,
region=region # Specify region if supported
)
return self.edge_sandboxes[region]
def execute_at_edge(self, function_code: str, region: str, event: Dict[str, Any]) -> Dict[str, Any]:
"""Execute function at edge location"""
try:
sandbox = self.get_edge_sandbox(region)
# Prepare function with event
import json
full_code = f"""
import json
event = {json.dumps(event)}
{function_code}
"""
result = sandbox.run_code(full_code, timeout=10) # Fast execution for edge
return {
"success": result.success,
"result": result.stdout,
"region": region,
"execution_time": result.execution_time
}
except Exception as e:
return {
"success": False,
"error": str(e),
"region": region
}
def route_to_nearest(self, user_location: str, function_code: str, event: Dict[str, Any]) -> Dict[str, Any]:
"""Route request to nearest edge location"""
# Simple routing logic (in production, use geolocation)
region_map = {
"us": "us-east-1",
"eu": "eu-west-1",
"asia": "ap-southeast-1"
}
region = region_map.get(user_location, "us-east-1")
return self.execute_at_edge(function_code, region, event)
def cleanup_all(self):
"""Clean up all edge sandboxes"""
for sandbox in self.edge_sandboxes.values():
sandbox.kill()
self.edge_sandboxes.clear()
# Usage
platform = EdgeFunctionPlatform(api_key=os.getenv("HOPX_API_KEY"))
result = platform.route_to_nearest(
user_location="us",
function_code="print('Hello from edge!')",
event={}
)
print(result)
platform.cleanup_all()
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class EdgeFunctionPlatform {
constructor(apiKey) {
this.apiKey = apiKey;
this.edgeSandboxes = {}; // Region -> sandbox mapping
}
async getEdgeSandbox(region) {
if (!this.edgeSandboxes[region]) {
this.edgeSandboxes[region] = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: 300,
region // Specify region if supported
});
}
return this.edgeSandboxes[region];
}
async executeAtEdge(functionCode, region, event) {
try {
const sandbox = await this.getEdgeSandbox(region);
// Prepare function with event
const fullCode = `
const event = ${JSON.stringify(event)};
${functionCode}
`;
const result = await sandbox.runCode(fullCode, { timeout: 10 }); // Fast execution for edge
return {
success: result.success,
result: result.stdout,
region,
executionTime: result.execution_time
};
} catch (error) {
return {
success: false,
error: error.message,
region
};
}
}
async routeToNearest(userLocation, functionCode, event) {
// Simple routing logic (in production, use geolocation)
const regionMap = {
us: 'us-east-1',
eu: 'eu-west-1',
asia: 'ap-southeast-1'
};
const region = regionMap[userLocation] || 'us-east-1';
return await this.executeAtEdge(functionCode, region, event);
}
async cleanupAll() {
await Promise.all(
Object.values(this.edgeSandboxes).map(sandbox => sandbox.kill())
);
this.edgeSandboxes = {};
}
}
// Usage
const platform = new EdgeFunctionPlatform(process.env.HOPX_API_KEY);
const result = await platform.routeToNearest(
'us',
"print('Hello from edge!')",
{}
);
console.log(result);
await platform.cleanupAll();
```
## Best Practices
1. **Low Latency**: Optimize for fast execution
2. **Resource Constraints**: Use minimal resources at edge
3. **Geographic Distribution**: Deploy to multiple regions
4. **Request Routing**: Route to nearest edge location
## Related Cookbooks
* [Custom Serverless Platform](/cookbooks/serverless/custom-functions) - Serverless functions
## Next Steps
1. Implement geolocation-based routing
2. Add edge location management
3. Create request routing logic
4. Implement resource optimization
5. Add edge monitoring
# Isolated Test Execution Service
Source: https://docs.hopx.ai/cookbooks/testing/isolated-test-execution
Build a CI/CD test execution platform with parallel test execution, test isolation strategies, and result aggregation
Build a production-ready isolated test execution service for CI/CD pipelines. This cookbook demonstrates how to create a test execution platform that runs tests in isolated sandboxes, supports parallel execution, and aggregates results.
## Overview
Isolated test execution services run tests in completely isolated environments, ensuring test reliability and preventing interference between test runs. This pattern is essential for CI/CD pipelines, test automation platforms, and quality assurance systems. HopX provides the secure isolation needed for this use case.
## Prerequisites
* HopX API key ([Get one here](https://console.hopx.dev/api-keys))
* Python 3.8+ or Node.js 16+
* Understanding of test frameworks (pytest, jest, etc.)
* Basic knowledge of CI/CD concepts
## Architecture
```
┌──────────────┐
│ CI/CD │ Test execution requests
│ Pipeline │
└──────┬───────┘
│
▼
┌─────────────────┐
│ Test Runner │ Parallel execution
└──────┬──────────┘
│
▼
┌─────────────────┐
│ HopX Sandboxes │ Isolated execution
│ (One per test) │
└──────┬──────────┘
│
▼
┌─────────────────┐
│ Result │ Aggregate & report
│ Aggregator │
└─────────────────┘
```
## Implementation
### Step 1: Basic Isolated Test Execution
Execute tests in isolated sandboxes:
```python Python theme={null}
from hopx_ai import Sandbox
import os
import json
from typing import Dict, List, Any
from concurrent.futures import ThreadPoolExecutor, as_completed
class IsolatedTestExecutor:
def __init__(self, api_key: str):
self.api_key = api_key
def execute_test(self, test_code: str, test_framework: str = "pytest", timeout: int = 60) -> Dict[str, Any]:
"""Execute a single test in isolated sandbox"""
sandbox = None
try:
# Create fresh sandbox for each test
sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=timeout + 10
)
# Write test file
test_file = "/workspace/test_file.py"
sandbox.files.write(test_file, test_code)
# Install test framework if needed
if test_framework == "pytest":
sandbox.commands.run("pip install pytest", timeout=30)
# Execute test
result = sandbox.commands.run(f"pytest {test_file} -v", timeout=timeout)
elif test_framework == "unittest":
result = sandbox.commands.run(f"python -m unittest {test_file}", timeout=timeout)
else:
result = sandbox.run_code(test_code, timeout=timeout)
# Parse test results
test_results = self._parse_test_results(result.stdout, test_framework)
return {
"success": result.exit_code == 0,
"exit_code": result.exit_code,
"stdout": result.stdout,
"stderr": result.stderr,
"test_results": test_results,
"execution_time": getattr(result, 'execution_time', 0)
}
except Exception as e:
return {
"success": False,
"error": str(e),
"stderr": str(e)
}
finally:
if sandbox:
sandbox.kill()
def _parse_test_results(self, output: str, framework: str) -> Dict[str, Any]:
"""Parse test framework output"""
if framework == "pytest":
# Parse pytest output
passed = output.count("PASSED")
failed = output.count("FAILED")
return {
"passed": passed,
"failed": failed,
"total": passed + failed
}
else:
return {
"passed": 0,
"failed": 0,
"total": 0
}
# Usage
executor = IsolatedTestExecutor(api_key=os.getenv("HOPX_API_KEY"))
test_code = """
def test_addition():
assert 1 + 1 == 2
def test_subtraction():
assert 5 - 3 == 2
"""
result = executor.execute_test(test_code, test_framework="pytest")
print(json.dumps(result, indent=2))
```
```javascript JavaScript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
class IsolatedTestExecutor {
constructor(apiKey) {
this.apiKey = apiKey;
}
async executeTest(testCode, testFramework = 'jest', timeout = 60) {
let sandbox = null;
try {
// Create fresh sandbox for each test
sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: timeout + 10
});
// Write test file
const testFile = '/workspace/test_file.js';
await sandbox.files.write(testFile, testCode);
// Install test framework if needed
if (testFramework === 'jest') {
await sandbox.commands.run('npm install jest', { timeout: 30 });
// Execute test
const result = await sandbox.commands.run(`npx jest ${testFile}`, { timeout });
// Parse test results
const testResults = this.parseTestResults(result.stdout, testFramework);
return {
success: result.exit_code === 0,
exitCode: result.exit_code,
stdout: result.stdout,
stderr: result.stderr,
testResults,
executionTime: result.execution_time || 0
};
} else {
const result = await sandbox.runCode(testCode, { timeout });
return {
success: result.success,
stdout: result.stdout,
stderr: result.stderr
};
}
} catch (error) {
return {
success: false,
error: error.message,
stderr: error.toString()
};
} finally {
if (sandbox) {
await sandbox.kill();
}
}
}
parseTestResults(output, framework) {
if (framework === 'jest') {
// Parse jest output
const passed = (output.match(/PASS/g) || []).length;
const failed = (output.match(/FAIL/g) || []).length;
return {
passed,
failed,
total: passed + failed
};
} else {
return {
passed: 0,
failed: 0,
total: 0
};
}
}
}
// Usage
const executor = new IsolatedTestExecutor(process.env.HOPX_API_KEY);
const testCode = `
test('addition', () => {
expect(1 + 1).toBe(2);
});
test('subtraction', () => {
expect(5 - 3).toBe(2);
});
`;
const result = await executor.executeTest(testCode, 'jest');
console.log(JSON.stringify(result, null, 2));
```
### Step 2: Parallel Test Execution
Execute multiple tests in parallel:
```python Python theme={null}
class ParallelTestExecutor(IsolatedTestExecutor):
def execute_test_suite(self, test_suite: List[Dict], max_workers: int = 5) -> Dict[str, Any]:
"""Execute multiple tests in parallel"""
results = []
with ThreadPoolExecutor(max_workers=max_workers) as executor:
# Submit all tests
future_to_test = {
executor.submit(
self.execute_test,
test["code"],
test.get("framework", "pytest"),
test.get("timeout", 60)
): test
for test in test_suite
}
# Collect results as they complete
for future in as_completed(future_to_test):
test = future_to_test[future]
try:
result = future.result()
results.append({
"test_name": test.get("name", "unknown"),
"result": result
})
except Exception as e:
results.append({
"test_name": test.get("name", "unknown"),
"result": {
"success": False,
"error": str(e)
}
})
# Aggregate results
total_tests = len(results)
passed_tests = sum(1 for r in results if r["result"].get("success", False))
failed_tests = total_tests - passed_tests
return {
"total_tests": total_tests,
"passed": passed_tests,
"failed": failed_tests,
"success_rate": (passed_tests / total_tests * 100) if total_tests > 0 else 0,
"results": results
}
# Usage
executor = ParallelTestExecutor(api_key=os.getenv("HOPX_API_KEY"))
test_suite = [
{
"name": "test_math",
"code": """
def test_addition():
assert 1 + 1 == 2
""",
"framework": "pytest",
"timeout": 30
},
{
"name": "test_strings",
"code": """
def test_concatenation():
assert "hello" + " " + "world" == "hello world"
""",
"framework": "pytest",
"timeout": 30
}
]
results = executor.execute_test_suite(test_suite, max_workers=2)
print(json.dumps(results, indent=2))
```
```javascript JavaScript theme={null}
class ParallelTestExecutor extends IsolatedTestExecutor {
async executeTestSuite(testSuite, maxWorkers = 5) {
const results = [];
// Execute tests in parallel (limited by maxWorkers)
const chunks = [];
for (let i = 0; i < testSuite.length; i += maxWorkers) {
chunks.push(testSuite.slice(i, i + maxWorkers));
}
for (const chunk of chunks) {
const chunkResults = await Promise.all(
chunk.map(async (test) => {
try {
const result = await this.executeTest(
test.code,
test.framework || 'jest',
test.timeout || 60
);
return {
testName: test.name || 'unknown',
result
};
} catch (error) {
return {
testName: test.name || 'unknown',
result: {
success: false,
error: error.message
}
};
}
})
);
results.push(...chunkResults);
}
// Aggregate results
const totalTests = results.length;
const passedTests = results.filter(r => r.result.success).length;
const failedTests = totalTests - passedTests;
return {
totalTests,
passed: passedTests,
failed: failedTests,
successRate: totalTests > 0 ? (passedTests / totalTests * 100) : 0,
results
};
}
}
// Usage
const executor = new ParallelTestExecutor(process.env.HOPX_API_KEY);
const testSuite = [
{
name: 'test_math',
code: `
test('addition', () => {
expect(1 + 1).toBe(2);
});
`,
framework: 'jest',
timeout: 30
},
{
name: 'test_strings',
code: `
test('concatenation', () => {
expect('hello' + ' ' + 'world').toBe('hello world');
});
`,
framework: 'jest',
timeout: 30
}
];
const results = await executor.executeTestSuite(testSuite, 2);
console.log(JSON.stringify(results, null, 2));
```
### Step 3: Test Isolation Strategies
Ensure complete test isolation:
```python Python theme={null}
class IsolatedTestRunner:
def __init__(self, api_key: str):
self.api_key = api_key
def run_isolated_test(self, test_config: Dict) -> Dict[str, Any]:
"""Run test with complete isolation"""
sandbox = None
try:
# Create sandbox with clean environment
sandbox = Sandbox.create(
template="code-interpreter",
api_key=self.api_key,
timeout_seconds=test_config.get("timeout", 60) + 10,
env_vars=test_config.get("env_vars", {})
)
# Set up test environment
setup_code = test_config.get("setup", "")
if setup_code:
setup_result = sandbox.run_code(setup_code, timeout=30)
if not setup_result.success:
return {
"success": False,
"error": f"Setup failed: {setup_result.stderr}",
"stage": "setup"
}
# Write test files
for file_config in test_config.get("files", []):
sandbox.files.write(
file_config["path"],
file_config["content"]
)
# Execute test
test_result = sandbox.run_code(
test_config["test_code"],
language=test_config.get("language", "python"),
timeout=test_config.get("timeout", 60)
)
# Cleanup (teardown)
teardown_code = test_config.get("teardown", "")
if teardown_code:
sandbox.run_code(teardown_code, timeout=30)
return {
"success": test_result.success,
"stdout": test_result.stdout,
"stderr": test_result.stderr,
"exit_code": test_result.exit_code,
"execution_time": test_result.execution_time
}
except Exception as e:
return {
"success": False,
"error": str(e)
}
finally:
# Always cleanup - fresh sandbox for next test
if sandbox:
sandbox.kill()
# Usage
runner = IsolatedTestRunner(api_key=os.getenv("HOPX_API_KEY"))
test_config = {
"test_code": """
import unittest
class TestMath(unittest.TestCase):
def test_addition(self):
self.assertEqual(1 + 1, 2)
def test_multiplication(self):
self.assertEqual(2 * 3, 6)
if __name__ == '__main__':
unittest.main()
""",
"setup": "import unittest",
"timeout": 30,
"env_vars": {
"TEST_MODE": "true"
},
"files": [
{
"path": "/workspace/test_utils.py",
"content": "def helper(): return 'helper'"
}
]
}
result = runner.run_isolated_test(test_config)
print(json.dumps(result, indent=2))
```
```javascript JavaScript theme={null}
class IsolatedTestRunner {
constructor(apiKey) {
this.apiKey = apiKey;
}
async runIsolatedTest(testConfig) {
let sandbox = null;
try {
// Create sandbox with clean environment
sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: this.apiKey,
timeoutSeconds: (testConfig.timeout || 60) + 10,
envVars: testConfig.envVars || {}
});
// Set up test environment
const setupCode = testConfig.setup || '';
if (setupCode) {
const setupResult = await sandbox.runCode(setupCode, { timeout: 30 });
if (!setupResult.success) {
return {
success: false,
error: `Setup failed: ${setupResult.stderr}`,
stage: 'setup'
};
}
}
// Write test files
for (const fileConfig of testConfig.files || []) {
await sandbox.files.write(
fileConfig.path,
fileConfig.content
);
}
// Execute test
const testResult = await sandbox.runCode(
testConfig.testCode,
{
language: testConfig.language || 'python',
timeout: testConfig.timeout || 60
}
);
// Cleanup (teardown)
const teardownCode = testConfig.teardown || '';
if (teardownCode) {
await sandbox.runCode(teardownCode, { timeout: 30 });
}
return {
success: testResult.success,
stdout: testResult.stdout,
stderr: testResult.stderr,
exitCode: testResult.exit_code,
executionTime: testResult.execution_time
};
} catch (error) {
return {
success: false,
error: error.message
};
} finally {
// Always cleanup - fresh sandbox for next test
if (sandbox) {
await sandbox.kill();
}
}
}
}
// Usage
const runner = new IsolatedTestRunner(process.env.HOPX_API_KEY);
const testConfig = {
testCode: `
const assert = require('assert');
describe('Math Tests', () => {
it('should add numbers', () => {
assert.strictEqual(1 + 1, 2);
});
it('should multiply numbers', () => {
assert.strictEqual(2 * 3, 6);
});
});
`,
setup: 'const assert = require("assert");',
timeout: 30,
envVars: {
TEST_MODE: 'true'
},
files: [
{
path: '/workspace/test_utils.js',
content: "function helper() { return 'helper'; }"
}
]
};
const result = await runner.runIsolatedTest(testConfig);
console.log(JSON.stringify(result, null, 2));
```
### Step 4: Result Aggregation and Reporting
Aggregate test results and generate reports:
```python Python theme={null}
class TestResultAggregator:
def __init__(self):
self.results = []
def add_result(self, test_name: str, result: Dict[str, Any]):
"""Add test result to aggregation"""
self.results.append({
"test_name": test_name,
"result": result,
"timestamp": self._get_timestamp()
})
def generate_report(self) -> Dict[str, Any]:
"""Generate aggregated test report"""
total = len(self.results)
passed = sum(1 for r in self.results if r["result"].get("success", False))
failed = total - passed
# Calculate execution times
execution_times = [
r["result"].get("execution_time", 0)
for r in self.results
if "execution_time" in r["result"]
]
avg_time = sum(execution_times) / len(execution_times) if execution_times else 0
total_time = sum(execution_times)
# Group by status
passed_tests = [r for r in self.results if r["result"].get("success", False)]
failed_tests = [r for r in self.results if not r["result"].get("success", False)]
return {
"summary": {
"total": total,
"passed": passed,
"failed": failed,
"success_rate": (passed / total * 100) if total > 0 else 0,
"average_execution_time": avg_time,
"total_execution_time": total_time
},
"passed_tests": [
{
"name": r["test_name"],
"execution_time": r["result"].get("execution_time", 0)
}
for r in passed_tests
],
"failed_tests": [
{
"name": r["test_name"],
"error": r["result"].get("error") or r["result"].get("stderr", ""),
"execution_time": r["result"].get("execution_time", 0)
}
for r in failed_tests
],
"all_results": self.results
}
def _get_timestamp(self) -> str:
from datetime import datetime
return datetime.now().isoformat()
# Usage
aggregator = TestResultAggregator()
# Add results
aggregator.add_result("test_1", {"success": True, "execution_time": 1.5})
aggregator.add_result("test_2", {"success": False, "error": "Assertion failed"})
aggregator.add_result("test_3", {"success": True, "execution_time": 2.1})
# Generate report
report = aggregator.generate_report()
print(json.dumps(report, indent=2))
```
```javascript JavaScript theme={null}
class TestResultAggregator {
constructor() {
this.results = [];
}
addResult(testName, result) {
this.results.push({
testName,
result,
timestamp: new Date().toISOString()
});
}
generateReport() {
const total = this.results.length;
const passed = this.results.filter(r => r.result.success).length;
const failed = total - passed;
// Calculate execution times
const executionTimes = this.results
.map(r => r.result.executionTime || 0)
.filter(t => t > 0);
const avgTime = executionTimes.length > 0
? executionTimes.reduce((a, b) => a + b, 0) / executionTimes.length
: 0;
const totalTime = executionTimes.reduce((a, b) => a + b, 0);
// Group by status
const passedTests = this.results.filter(r => r.result.success);
const failedTests = this.results.filter(r => !r.result.success);
return {
summary: {
total,
passed,
failed,
successRate: total > 0 ? (passed / total * 100) : 0,
averageExecutionTime: avgTime,
totalExecutionTime: totalTime
},
passedTests: passedTests.map(r => ({
name: r.testName,
executionTime: r.result.executionTime || 0
})),
failedTests: failedTests.map(r => ({
name: r.testName,
error: r.result.error || r.result.stderr || '',
executionTime: r.result.executionTime || 0
})),
allResults: this.results
};
}
}
// Usage
const aggregator = new TestResultAggregator();
// Add results
aggregator.addResult('test_1', { success: true, executionTime: 1.5 });
aggregator.addResult('test_2', { success: false, error: 'Assertion failed' });
aggregator.addResult('test_3', { success: true, executionTime: 2.1 });
// Generate report
const report = aggregator.generateReport();
console.log(JSON.stringify(report, null, 2));
```
## Best Practices
### Isolation
Always create a fresh sandbox for each test to ensure complete isolation. Never reuse sandboxes between tests.
1. **Fresh Sandboxes**: One sandbox per test execution
2. **Clean Environment**: Start with clean environment variables
3. **No Shared State**: Tests should not depend on each other
4. **Resource Cleanup**: Always cleanup sandboxes after tests
### Performance
Use parallel execution for independent tests, but ensure each test runs in its own isolated sandbox.
1. **Parallel Execution**: Run independent tests in parallel
2. **Resource Limits**: Set appropriate timeouts per test
3. **Result Caching**: Cache test results when possible
4. **Efficient Cleanup**: Clean up sandboxes efficiently
### Reliability
1. **Error Handling**: Handle all error cases gracefully
2. **Timeout Management**: Set appropriate timeouts
3. **Retry Logic**: Implement retry for transient failures
4. **Logging**: Log all test executions for debugging
## Real-World Examples
This pattern is used by:
* **GitHub Actions**: CI/CD test execution
* **Jenkins**: Continuous integration platform
* **CircleCI**: Cloud-based CI/CD
* **Travis CI**: Continuous integration service
## Related Cookbooks
* [API Testing Platform](/cookbooks/automation/api-testing-platform) - API testing automation
## Next Steps
1. Integrate with CI/CD platforms (GitHub Actions, GitLab CI, etc.)
2. Add test result persistence and history
3. Implement test result notifications
4. Create test execution dashboard
5. Add support for more test frameworks
# Clearing
Source: https://docs.hopx.ai/core-concepts/cache/clearing
Clear sandbox execution result cache to free memory and reset cache statistics in HopX sandboxes. Remove cached execution results to free resources, force re-execution of code, or reset cache performance metrics. Essential for memory management and debugging. Includes Python and JavaScript SDK examples and REST API endpoints.
Clear the execution result cache to free memory, reset cache statistics, and ensure fresh executions for testing or debugging.
## Overview
Clearing the cache is useful when:
* Cache has grown too large and you need to free memory
* You want to reset cache statistics
* Testing code changes that should bypass cache
* Debugging cache-related issues
* Starting fresh after code modifications
Clearing the cache will remove all cached execution results. Subsequent executions will be cache misses until new entries are created.
## Clearing Cache
Clear all cached execution results:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Get cache stats before clearing
before = sandbox.cache.stats()
before_cache = before['cache']
print(f"Before clearing: Size={before_cache['size']}, Hits={before_cache['total_hits']}")
# Clear the cache
result = sandbox.cache.clear()
print(f"Result: {result['message']}")
# Get cache stats after clearing
after = sandbox.cache.stats()
after_cache = after['cache']
print(f"After clearing: Size={after_cache['size']}, Hits={after_cache['total_hits']}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Get cache stats before clearing
const before = await sandbox.cache.stats();
const beforeCache = before.cache;
console.log(`Before clearing: Size=${beforeCache.size}, Hits=${beforeCache.total_hits}`);
// Clear the cache
const result = await sandbox.cache.clear();
console.log(`Result: ${result.message}`);
// Get cache stats after clearing
const after = await sandbox.cache.stats();
const afterCache = after.cache;
console.log(`After clearing: Size=${afterCache.size}, Hits=${afterCache.total_hits}`);
await sandbox.kill();
```
## Cache Clear Response
The cache clear operation returns a confirmation:
```json theme={null}
{
"message": "Cache cleared successfully",
"timestamp": "2025-01-27T19:49:28Z"
}
```
### Field Descriptions
* **`message`**: Confirmation message
* **`timestamp`**: Timestamp when the cache was cleared
## Use Cases
### Freeing Memory
Clear cache when it consumes too much memory:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Check cache size
stats = sandbox.cache.stats()
cache_data = stats['cache']
cache_size = cache_data['size']
max_size = cache_data['max_size']
# Clear if cache is too large (80% of max)
CACHE_SIZE_THRESHOLD = max_size * 0.8
if cache_size > CACHE_SIZE_THRESHOLD:
print(f"Cache size ({cache_size}) exceeds threshold ({CACHE_SIZE_THRESHOLD})")
result = sandbox.cache.clear()
print(f"Cache cleared: {result['message']}")
else:
print(f"Cache size ({cache_size}) is within acceptable range")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Check cache size
const stats = await sandbox.cache.stats();
const cacheData = stats.cache;
const cacheSize = cacheData.size;
const maxSize = cacheData.max_size;
// Clear if cache is too large (80% of max)
const CACHE_SIZE_THRESHOLD = maxSize * 0.8;
if (cacheSize > CACHE_SIZE_THRESHOLD) {
console.log(`Cache size (${cacheSize}) exceeds threshold (${CACHE_SIZE_THRESHOLD})`);
const result = await sandbox.cache.clear();
console.log(`Cache cleared: ${result.message}`);
} else {
console.log(`Cache size (${cacheSize}) is within acceptable range`);
}
await sandbox.kill();
```
### Resetting for Testing
Clear cache before running tests to ensure fresh executions:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Clear cache before testing
print("Clearing cache for fresh test execution...")
sandbox.cache.clear()
# Run test code (will be cache miss)
result = sandbox.run_code("""
import time
start = time.time()
# Simulate some computation
sum(range(100000))
end = time.time()
print(f"Execution time: {end - start:.3f}s")
""")
print("Test completed with fresh execution")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Clear cache before testing
console.log('Clearing cache for fresh test execution...');
await sandbox.cache.clear();
// Run test code (will be cache miss)
const result = await sandbox.runCode(`
import time
start = time.time()
# Simulate some computation
sum(range(100000))
end = time.time()
print(f"Execution time: {end - start:.3f}s")
`);
console.log('Test completed with fresh execution');
await sandbox.kill();
```
### Periodic Cache Maintenance
Clear cache periodically to prevent unbounded growth:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Run some code to generate cache entries
for i in range(20):
sandbox.run_code(f"print('Execution {i}')")
time.sleep(0.1)
# Check cache stats
stats = sandbox.cache.stats()
cache_data = stats['cache']
print(f"Cache size: {cache_data['size']}")
print(f"Cache hits: {cache_data['total_hits']}")
# Clear cache periodically (e.g., if size > 80% of max)
if cache_data['size'] > cache_data['max_size'] * 0.8:
print("Clearing cache due to high size...")
result = sandbox.cache.clear()
print(f"Cleared: {result['message']}")
# Verify cache is cleared
after_stats = sandbox.cache.stats()
after_cache = after_stats['cache']
print(f"Cache size after clear: {after_cache['size']}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Run some code to generate cache entries
for (let i = 0; i < 20; i++) {
await sandbox.runCode(`print('Execution ${i}')`);
await new Promise(resolve => setTimeout(resolve, 100));
}
// Check cache stats
const stats = await sandbox.cache.stats();
const cacheData = stats.cache;
console.log(`Cache size: ${cacheData.size}`);
console.log(`Cache hits: ${cacheData.total_hits}`);
// Clear cache periodically (e.g., if size > 80% of max)
if (cacheData.size > cacheData.max_size * 0.8) {
console.log('Clearing cache due to high size...');
const result = await sandbox.cache.clear();
console.log(`Cleared: ${result.message}`);
// Verify cache is cleared
const afterStats = await sandbox.cache.stats();
const afterCache = afterStats.cache;
console.log(`Cache size after clear: ${afterCache.size}`);
}
await sandbox.kill();
```
## Best Practices
**Monitor cache size** before clearing. Only clear when necessary to avoid losing beneficial cached results.
**Clear cache before testing** to ensure code changes are properly tested without cache interference.
**Clearing cache affects performance**. After clearing, all executions will be cache misses until new entries are created.
**Set up periodic cache maintenance** if you have long-running sandboxes with many executions.
## API Reference
### Python SDK
* `sandbox.cache.clear(*, timeout=None)` - Clear execution cache
### JavaScript SDK
* `sandbox.cache.clear()` - Clear execution cache
### API Endpoint
* **POST** `/cache/clear` - Clear execution result cache
## Related
* **[Cache Statistics](/core-concepts/cache/statistics)** - Monitor cache performance
* **SDK**: [sandbox.cache.clear()](/sdk/python/cache#clear) - Python SDK method
* **API**: [POST /cache/clear](/api/vm-agent/clear-cache) - VM Agent API endpoint
## Next Steps
* Learn about [Cache Statistics](/core-concepts/cache/statistics) to monitor cache
* Review [Code Execution](/core-concepts/code-execution/synchronous) for execution results
* [Cache Statistics](/core-concepts/cache/statistics) - Monitor cache performance
* **[CLI System Commands](/cli/commands/system)** - View cache statistics from CLI
# Cache
Source: https://docs.hopx.ai/core-concepts/cache/index
Complete guide to cache management in HopX sandboxes - statistics, clearing, and optimization. Learn how to view cache statistics, clear execution cache, optimize cache usage, and monitor cache performance. Manage cache for improved execution speed and resource efficiency. Includes Python and JavaScript SDK examples and REST API endpoints.
Manage execution cache in HopX sandboxes for performance optimization. This hub covers cache statistics, clearing, and best practices.
## Related
* [CLI System Commands](/cli/commands/system) - System operations from CLI
## What You'll Learn
* How to view cache statistics
* How to clear execution cache
* How to optimize cache usage
* How to monitor cache performance
* Best practices for cache management
## Cache Management Overview
| Operation | SDK Method | API Endpoint |
| ------------------------------------------------- | ----------------------- | ------------------- |
| **[Statistics](/core-concepts/cache/statistics)** | `sandbox.cache.stats()` | `GET /cache/stats` |
| **[Clearing](/core-concepts/cache/clearing)** | `sandbox.cache.clear()` | `POST /cache/clear` |
## Core Concepts
### Cache Statistics
View cache statistics including hit rate and cached items.
* **[Cache Statistics](/core-concepts/cache/statistics)** - View cache statistics
* **SDK**: [Python: sandbox.cache.stats()](/sdk/python/cache#stats) | [JavaScript: sandbox.cache.stats()](/sdk/javascript/cache#stats)
* **API**: [GET /cache/stats](/api/vm-agent/get-cache-stats)
### Clearing Cache
Clear execution cache to free memory or force re-execution.
* **[Clearing Cache](/core-concepts/cache/clearing)** - Clear execution cache
* **SDK**: [Python: sandbox.cache.clear()](/sdk/python/cache#clear) | [JavaScript: sandbox.cache.clear()](/sdk/javascript/cache#clear)
* **API**: [POST /cache/clear](/api/vm-agent/clear-cache)
## SDK Reference
### Python SDK
Complete reference for Python cache operations.
* **[Cache Module](/sdk/python/cache)** - Complete cache API
* `cache.stats()` - Get cache statistics
* `cache.clear()` - Clear cache
### JavaScript SDK
Complete reference for JavaScript/TypeScript cache operations.
* **[Cache Module](/sdk/javascript/cache)** - Complete cache API
* `cache.stats()` - Get cache statistics
* `cache.clear()` - Clear cache
## API Reference
### VM Agent API
REST API endpoints for cache management.
* **[VM Agent API Overview](/api/vm-agent/overview)** - API overview
* **[Get Cache Statistics](/api/vm-agent/get-cache-stats)** - `GET /cache/stats` - Get cache stats
* **[Clear Cache](/api/vm-agent/clear-cache)** - `POST /cache/clear` - Clear cache
## Quick Start
If you're new to cache management, start here:
1. **[Cache Statistics](/core-concepts/cache/statistics)** - View cache performance
2. **[Clearing Cache](/core-concepts/cache/clearing)** - Clear cache when needed
## Related Topics
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Cache affects code execution
* **[Observability](/core-concepts/observability/metrics)** - Monitor cache metrics
* **[Sandboxes](/core-concepts/sandboxes/managing-state)** - Cache persists across state changes
## Next Steps
* Learn about [Cache Statistics](/core-concepts/cache/statistics) for monitoring
* Explore [Clearing Cache](/core-concepts/cache/clearing) for optimization
* Review [Code Execution](/core-concepts/code-execution/synchronous) to understand cache impact
* Check out [Observability](/core-concepts/observability/metrics) for performance monitoring
# Statistics
Source: https://docs.hopx.ai/core-concepts/cache/statistics
Get cache hit rate and usage statistics for sandbox code execution results in HopX sandboxes. Monitor cache performance, view hit rates, track cached items, and optimize execution speed. Essential for understanding cache effectiveness and performance tuning. Includes Python and JavaScript SDK examples and REST API endpoints.
Monitor the execution result cache to understand cache performance, optimize your code patterns, and track cache usage over time.
## Overview
HopX caches execution results to improve performance for repeated code executions. Cache statistics help you:
* Monitor cache hit rates
* Track cache size and entry counts
* Optimize code patterns for better caching
* Understand cache effectiveness
The cache stores execution results based on code content and environment. Identical code executions with the same environment variables will hit the cache.
## Getting Cache Statistics
Retrieve current cache statistics:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Get cache statistics
stats = sandbox.cache.stats()
# Cache data is nested under 'cache' key
cache_data = stats['cache']
print(f"Total Hits: {cache_data['total_hits']}")
print(f"Cache Size: {cache_data['size']}")
print(f"Max Size: {cache_data['max_size']}")
print(f"TTL: {cache_data['ttl']}")
print(f"Timestamp: {stats['timestamp']}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Get cache statistics
const stats = await sandbox.cache.stats();
// Cache data is nested under 'cache' key
const cacheData = stats.cache;
console.log(`Total Hits: ${cacheData.total_hits}`);
console.log(`Cache Size: ${cacheData.size}`);
console.log(`Max Size: ${cacheData.max_size}`);
console.log(`TTL: ${cacheData.ttl}`);
console.log(`Timestamp: ${stats.timestamp}`);
await sandbox.kill();
```
## Understanding Cache Metrics
### Cache Size and Hits
Monitor cache usage and performance:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
stats = sandbox.cache.stats()
cache_data = stats['cache']
print(f"Total Cache Hits: {cache_data['total_hits']}")
print(f"Current Cache Size: {cache_data['size']}")
print(f"Max Cache Size: {cache_data['max_size']}")
print(f"Cache TTL: {cache_data['ttl']}")
if cache_data['total_hits'] > 100:
print("✅ Cache is being utilized effectively")
else:
print("💡 Consider optimizing code patterns for better caching")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
const stats = await sandbox.cache.stats();
const cacheData = stats.cache;
console.log(`Total Cache Hits: ${cacheData.total_hits}`);
console.log(`Current Cache Size: ${cacheData.size}`);
console.log(`Max Cache Size: ${cacheData.max_size}`);
console.log(`Cache TTL: ${cacheData.ttl}`);
if (cacheData.total_hits > 100) {
console.log('✅ Cache is being utilized effectively');
} else {
console.log('💡 Consider optimizing code patterns for better caching');
}
await sandbox.kill();
```
### Cache Size
Monitor cache size to ensure it's not consuming excessive resources:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
stats = sandbox.cache.stats()
cache_data = stats['cache']
cache_size = cache_data['size']
max_size = cache_data['max_size']
print(f"Cache Size: {cache_size}")
print(f"Max Cache Size: {max_size}")
print(f"Cache TTL: {cache_data['ttl']}")
if cache_size > max_size * 0.8:
print("⚠️ Cache size is approaching maximum. Consider clearing if needed.")
elif cache_size > max_size * 0.5:
print("Cache size is moderate.")
else:
print("Cache size is small.")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
const stats = await sandbox.cache.stats();
const cacheData = stats.cache;
const cacheSize = cacheData.size;
const maxSize = cacheData.max_size;
console.log(`Cache Size: ${cacheSize}`);
console.log(`Max Cache Size: ${maxSize}`);
console.log(`Cache TTL: ${cacheData.ttl}`);
if (cacheSize > maxSize * 0.8) {
console.log('⚠️ Cache size is approaching maximum. Consider clearing if needed.');
} else if (cacheSize > maxSize * 0.5) {
console.log('Cache size is moderate.');
} else {
console.log('Cache size is small.');
}
await sandbox.kill();
```
## Monitoring Cache Performance
Track cache performance over time:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Run some code to generate cache entries
for i in range(5):
sandbox.run_code(f"print('Execution {i}')")
time.sleep(1)
# Check cache statistics
stats = sandbox.cache.stats()
cache_data = stats['cache']
print("Cache Performance:")
print(f" Total Cache Hits: {cache_data['total_hits']}")
print(f" Current Cache Size: {cache_data['size']}")
print(f" Max Cache Size: {cache_data['max_size']}")
print(f" Cache TTL: {cache_data['ttl']}")
print(f" Timestamp: {stats['timestamp']}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Run some code to generate cache entries
for (let i = 0; i < 5; i++) {
await sandbox.runCode(`print('Execution ${i}')`);
await new Promise(resolve => setTimeout(resolve, 1000));
}
// Check cache statistics
const stats = await sandbox.cache.stats();
const cacheData = stats.cache;
console.log('Cache Performance:');
console.log(` Total Cache Hits: ${cacheData.total_hits}`);
console.log(` Current Cache Size: ${cacheData.size}`);
console.log(` Max Cache Size: ${cacheData.max_size}`);
console.log(` Cache TTL: ${cacheData.ttl}`);
console.log(` Timestamp: ${stats.timestamp}`);
await sandbox.kill();
```
## Cache Statistics Response
The cache statistics response includes:
```json theme={null}
{
"cache": {
"max_size": 1000,
"size": 0,
"total_hits": 0,
"ttl": "5m0s"
},
"timestamp": "2025-01-27T19:43:55Z"
}
```
### Field Descriptions
* **`cache.max_size`**: Maximum cache size limit
* **`cache.size`**: Current cache size
* **`cache.total_hits`**: Total number of cache hits (cached results reused)
* **`cache.ttl`**: Time-to-live for cache entries
* **`timestamp`**: Timestamp when the statistics were retrieved
## Use Cases
### Optimizing for Cache
Test cache effectiveness with repeated executions:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Initial execution (cache miss)
code = "result = sum(range(1000000)); print(f'Sum: {result}')"
sandbox.run_code(code)
# Get initial stats
initial_stats = sandbox.cache.stats()
initial_hits = initial_stats['cache']['total_hits']
print(f"After first execution - Total Hits: {initial_hits}")
# Repeat same code (should hit cache)
sandbox.run_code(code)
# Check stats after repeat
final_stats = sandbox.cache.stats()
final_hits = final_stats['cache']['total_hits']
print(f"After repeat execution - Total Hits: {final_hits}")
if final_hits > initial_hits:
print("✅ Cache hit confirmed - repeated execution used cached result")
else:
print("⚠️ No cache hit - execution may have been different")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Initial execution (cache miss)
const code = "result = sum(range(1000000)); print(f'Sum: {result}')";
await sandbox.runCode(code);
// Get initial stats
const initialStats = await sandbox.cache.stats();
const initialHits = initialStats.cache.total_hits;
console.log(`After first execution - Total Hits: ${initialHits}`);
// Repeat same code (should hit cache)
await sandbox.runCode(code);
// Check stats after repeat
const finalStats = await sandbox.cache.stats();
const finalHits = finalStats.cache.total_hits;
console.log(`After repeat execution - Total Hits: ${finalHits}`);
if (finalHits > initialHits) {
console.log('✅ Cache hit confirmed - repeated execution used cached result');
} else {
console.log('⚠️ No cache hit - execution may have been different');
}
await sandbox.kill();
```
### Monitoring Cache Growth
Track how cache grows over time:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Monitor cache growth
for i in range(10):
# Execute different code each time
sandbox.run_code(f"print('Execution {i}: {i * 10}')")
stats = sandbox.cache.stats()
cache_data = stats['cache']
print(f"After execution {i+1}: Size={cache_data['size']}, Hits={cache_data['total_hits']}")
time.sleep(0.5)
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Monitor cache growth
for (let i = 0; i < 10; i++) {
// Execute different code each time
await sandbox.runCode(`print('Execution ${i}: ${i * 10}')`);
const stats = await sandbox.cache.stats();
const cacheData = stats.cache;
console.log(`After execution ${i+1}: Size=${cacheData.size}, Hits=${cacheData.total_hits}`);
await new Promise(resolve => setTimeout(resolve, 500));
}
await sandbox.kill();
```
## Best Practices
**Monitor total hits** to understand cache effectiveness. A high number of total hits indicates good cache utilization.
**Cache works best with deterministic code**. Code that produces the same output for the same input will benefit most from caching.
**Cache size can grow over time**. Monitor cache size and clear it periodically if it becomes too large.
**Environment variables affect caching**. Code with different environment variables will have separate cache entries.
## API Reference
### Python SDK
* `sandbox.cache.stats(*, timeout=None)` - Get cache statistics
### JavaScript SDK
* `sandbox.cache.stats()` - Get cache statistics
### API Endpoint
* **GET** `/cache/stats` - Get execution cache statistics
## Related
* **[Clearing Cache](/core-concepts/cache/clearing)** - Clear cache to free memory
* **SDK**: [sandbox.cache.stats()](/sdk/python/cache#stats) - Python SDK method
* **API**: [GET /cache/stats](/api/vm-agent/get-cache-stats) - VM Agent API endpoint
## Next Steps
* Learn about [Clearing Cache](/core-concepts/cache/clearing) to free memory
* Review [Code Execution](/core-concepts/code-execution/synchronous) to see cached results
* [Clearing Cache](/core-concepts/cache/clearing) - Clear the execution cache
* **[CLI System Commands](/cli/commands/system)** - View cache statistics from CLI
# Async Webhooks
Source: https://docs.hopx.ai/core-concepts/code-execution/async-webhooks
Execute very long-running code with webhook callbacks in HopX sandboxes. Run code asynchronously and receive results via webhook callbacks when execution completes. Perfect for long-running tasks, batch processing, and async workflows. Learn how to configure webhooks and handle callback responses. Includes examples and webhook setup.
Async execution with webhooks is designed for very long-running tasks (>30 minutes) that would otherwise timeout. The execution happens asynchronously, and results are delivered to your webhook endpoint when complete.
## Overview
Async webhook execution is perfect for:
* ML model training (30+ minutes)
* Large dataset processing
* Video encoding/processing
* Long-running simulations
* Any task that exceeds normal timeout limits
Async webhook execution returns immediately with an `execution_id`. The agent executes code in the background and POSTs results to your callback URL when complete.
## Basic Usage
Start async execution with a webhook callback:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Start async execution
response = sandbox.run_code_async(
code='''
import time
print("Starting long task...")
time.sleep(600) # 10 minutes
print("Task completed!")
''',
callback_url='https://your-app.com/webhooks/HopX-complete',
language='python',
timeout=1800 # 30 minutes max
)
print(f"Execution ID: {response['execution_id']}")
print(f"Status: {response['status']}")
print(f"Callback URL: {response['callback_url']}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start async execution
const response = await sandbox.runCodeAsync(
`
import time
print("Starting long task...")
time.sleep(600) # 10 minutes
print("Task completed!")
`,
{
callbackUrl: 'https://your-app.com/webhooks/HopX-complete',
language: 'python',
timeout: 1800 // 30 minutes max
}
);
console.log(`Execution ID: ${response.executionId}`);
console.log(`Status: ${response.status}`);
console.log(`Callback URL: ${response.callbackUrl}`);
await sandbox.kill();
```
## Webhook Callback
Your webhook endpoint will receive a POST request when execution completes:
```python theme={null}
from flask import Flask, request
import hmac
import hashlib
app = Flask(__name__)
@app.route('/webhooks/HopX-complete', methods=['POST'])
def hopx_webhook():
# Verify signature (if secret provided)
signature = request.headers.get('X-HopX-Signature')
timestamp = request.headers.get('X-HopX-Timestamp')
# Verify signature if secret was provided
# secret = 'your-webhook-secret'
# expected_sig = hmac.new(
# secret.encode(),
# f"{timestamp}{request.data}".encode(),
# hashlib.sha256
# ).hexdigest()
# if signature != f"sha256={expected_sig}":
# return "Invalid signature", 401
# Process webhook payload
data = request.json
execution_id = data['execution_id']
status = data['status']
stdout = data.get('stdout', '')
stderr = data.get('stderr', '')
exit_code = data.get('exit_code', 0)
execution_time = data.get('execution_time', 0)
print(f"Execution {execution_id} completed with status: {status}")
print(f"Output: {stdout}")
if status == 'completed':
# Handle successful completion
process_results(execution_id, stdout)
else:
# Handle failure
handle_error(execution_id, stderr)
return "OK", 200
```
```javascript theme={null}
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
app.post('/webhooks/HopX-complete', (req, res) => {
// Verify signature (if secret provided)
const signature = req.headers['x-HopX-signature'];
const timestamp = req.headers['x-HopX-timestamp'];
// Verify signature if secret was provided
// const secret = 'your-webhook-secret';
// const expectedSig = crypto
// .createHmac('sha256', secret)
// .update(`${timestamp}${JSON.stringify(req.body)}`)
// .digest('hex');
// if (signature !== `sha256=${expectedSig}`) {
// return res.status(401).send('Invalid signature');
// }
// Process webhook payload
const { executionId, status, stdout, stderr, exitCode, executionTime } = req.body;
console.log(`Execution ${executionId} completed with status: ${status}`);
console.log(`Output: ${stdout}`);
if (status === 'completed') {
// Handle successful completion
processResults(executionId, stdout);
} else {
// Handle failure
handleError(executionId, stderr);
}
res.status(200).send('OK');
});
```
## Signature Verification
Verify webhook signatures for security:
```python theme={null}
from hopx_ai import Sandbox
import hmac
import hashlib
sandbox = Sandbox.create(template="code-interpreter")
# Start async execution with signature secret
response = sandbox.run_code_async(
code='import time; time.sleep(600); print("Done")',
callback_url='https://your-app.com/webhooks/HopX-complete',
callback_signature_secret='your-webhook-secret-123',
language='python'
)
print(f"Execution ID: {response['execution_id']}")
# In your webhook handler:
# signature = request.headers.get('X-HopX-Signature')
# timestamp = request.headers.get('X-HopX-Timestamp')
# body = request.data
#
# expected = hmac.new(
# 'your-webhook-secret-123'.encode(),
# f"{timestamp}{body}".encode(),
# hashlib.sha256
# ).hexdigest()
#
# if signature == f"sha256={expected}":
# # Valid signature
# pass
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import crypto from 'crypto';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start async execution with signature secret
const response = await sandbox.runCodeAsync(
'import time; time.sleep(600); print("Done")',
{
callbackUrl: 'https://your-app.com/webhooks/HopX-complete',
callbackSignatureSecret: 'your-webhook-secret-123',
language: 'python'
}
);
console.log(`Execution ID: ${response.executionId}`);
// In your webhook handler:
// const signature = req.headers['x-HopX-signature'];
// const timestamp = req.headers['x-HopX-timestamp'];
// const body = JSON.stringify(req.body);
//
// const expected = crypto
// .createHmac('sha256', 'your-webhook-secret-123')
// .update(`${timestamp}${body}`)
// .digest('hex');
//
// if (signature === `sha256=${expected}`) {
// // Valid signature
// }
```
## Custom Headers
Include custom headers in webhook callbacks:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Start async execution with custom headers
response = sandbox.run_code_async(
code='import time; time.sleep(600); print("Done")',
callback_url='https://your-app.com/webhooks/HopX-complete',
callback_headers={
'Authorization': 'Bearer your-api-token',
'X-Custom-Header': 'custom-value'
},
language='python'
)
print(f"Execution ID: {response['execution_id']}")
# Your webhook will receive:
# POST https://your-app.com/webhooks/HopX-complete
# Authorization: Bearer your-api-token
# X-Custom-Header: custom-value
# X-HopX-Signature: sha256=...
# X-HopX-Timestamp: 1698765432
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start async execution with custom headers
const response = await sandbox.runCodeAsync(
'import time; time.sleep(600); print("Done")',
{
callbackUrl: 'https://your-app.com/webhooks/HopX-complete',
callbackHeaders: {
'Authorization': 'Bearer your-api-token',
'X-Custom-Header': 'custom-value'
},
language: 'python'
}
);
console.log(`Execution ID: ${response.executionId}`);
// Your webhook will receive:
// POST https://your-app.com/webhooks/HopX-complete
// Authorization: Bearer your-api-token
// X-Custom-Header: custom-value
// X-HopX-Signature: sha256=...
// X-HopX-Timestamp: 1698765432
```
## Complete Example
Here's a complete example with ML model training:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Start ML training with async webhook
response = sandbox.run_code_async(
code='''
import time
import random
print("Starting ML model training...")
print("Epoch 1/10...")
time.sleep(60)
for epoch in range(2, 11):
loss = random.uniform(0.1, 0.5)
accuracy = random.uniform(0.8, 0.95)
print(f"Epoch {epoch}/10 - Loss: {loss:.4f}, Accuracy: {accuracy:.4f}")
time.sleep(60)
print("Training completed!")
print("Model saved to /workspace/model.pkl")
''',
callback_url='https://your-app.com/webhooks/ml-training-complete',
callback_headers={
'Authorization': 'Bearer ml-api-token',
'X-Training-ID': 'training-123'
},
callback_signature_secret='ml-webhook-secret',
language='python',
timeout=3600, # 1 hour
env={
'WANDB_API_KEY': 'your-wandb-key',
'HF_TOKEN': 'your-huggingface-token'
}
)
print(f"✅ Training started")
print(f"Execution ID: {response['execution_id']}")
print(f"Status: {response['status']}")
print(f"Results will be posted to: {response['callback_url']}")
# Your webhook will receive results when training completes
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start ML training with async webhook
const response = await sandbox.runCodeAsync(
`
import time
import random
print("Starting ML model training...")
print("Epoch 1/10...")
time.sleep(60)
for epoch in range(2, 11):
loss = random.uniform(0.1, 0.5)
accuracy = random.uniform(0.8, 0.95)
print(f"Epoch {epoch}/10 - Loss: {loss:.4f}, Accuracy: {accuracy:.4f}")
time.sleep(60)
print("Training completed!")
print("Model saved to /workspace/model.pkl")
`,
{
callbackUrl: 'https://your-app.com/webhooks/ml-training-complete',
callbackHeaders: {
'Authorization': 'Bearer ml-api-token',
'X-Training-ID': 'training-123'
},
callbackSignatureSecret: 'ml-webhook-secret',
language: 'python',
timeout: 3600, // 1 hour
env: {
WANDB_API_KEY: 'your-wandb-key',
HF_TOKEN: 'your-huggingface-token'
}
}
);
console.log('✅ Training started');
console.log(`Execution ID: ${response.executionId}`);
console.log(`Status: ${response.status}`);
console.log(`Results will be posted to: ${response.callbackUrl}`);
// Your webhook will receive results when training completes
await sandbox.kill();
```
## Webhook Payload
The webhook payload structure:
```json theme={null}
{
"execution_id": "abc123",
"status": "completed",
"stdout": "Task output...",
"stderr": "",
"exit_code": 0,
"execution_time": 600.123
}
```
**Headers:**
* `X-HopX-Signature`: HMAC-SHA256 signature (if secret provided)
* `X-HopX-Timestamp`: Unix timestamp
* Custom headers from `callback_headers`
## Best Practices
Use `callback_signature_secret` and verify signatures in your webhook handler to ensure requests are authentic.
Set appropriate timeouts based on expected execution time. Default is 30 minutes, max is typically 1 hour.
Include authentication tokens or identifiers in `callback_headers` for secure webhook processing.
Check the `status` field in webhook payloads to handle both successful completions and failures.
Store `execution_id` when starting async execution to correlate webhook callbacks with your records.
## Related
* **[Synchronous Execution](/core-concepts/code-execution/synchronous)** - Basic code execution
* **[Background Execution](/core-concepts/code-execution/background)** - Long-running tasks
* **[Streaming Execution](/core-concepts/code-execution/streaming)** - Real-time output streaming
* **SDK**: [sandbox.run\_code\_async()](/sdk/python/sandbox#run_code_async) - Python SDK method
* **API**: [POST /execute/async](/api/vm-agent/execute-async) - VM Agent API endpoint
* [CLI Code Execution](/cli/commands/run) - Execute code from CLI
## Next Steps
* Learn about [Background Execution](/core-concepts/code-execution/background) for shorter tasks
* Explore [Process Management](/core-concepts/code-execution/process-management) for monitoring
* Review [Synchronous Execution](/core-concepts/code-execution/synchronous) for immediate results
# Background
Source: https://docs.hopx.ai/core-concepts/code-execution/background
Execute code in the background without blocking. Learn how to run long-running code in HopX sandboxes asynchronously, monitor background processes, retrieve results when complete, and manage process lifecycle. Perfect for training models, processing large datasets, or running time-consuming operations. Includes Python and JavaScript SDK examples.
Background execution allows you to start code execution and return immediately, without waiting for completion. This is ideal for long-running tasks that you want to monitor and manage separately.
## Prerequisites
Before you begin, make sure you have:
* **Active sandbox** - A running sandbox (see [Creating Sandboxes](/core-concepts/sandboxes/creating))
* **Understanding of synchronous execution** - Familiarity with [Synchronous Execution](/core-concepts/code-execution/synchronous) is helpful
* **Long-running task** - Code that takes more than a few minutes to complete
## Overview
Background execution is perfect for:
* Long-running computations (>5 minutes)
* Tasks that don't need immediate results
* Parallel processing of multiple tasks
* Workflows where you want to check status periodically
Background execution returns immediately with a `process_id`. Use [Process Management](/core-concepts/code-execution/process-management) to check status and manage background processes.
## Starting Background Execution
Start code execution in the background:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Start background execution
result = sandbox.run_code_background(
code='''
import time
for i in range(10):
print(f"Step {i+1}/10")
time.sleep(2)
print("Done!")
''',
language='python',
name='long-task'
)
process_id = result['process_id']
print(f"Process started: {process_id}")
print(f"Status: {result['status']}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start background execution
const result = await sandbox.runCodeBackground(
`
import time
for i in range(10):
print(f"Step {i+1}/10")
time.sleep(2)
print("Done!")
`,
{
language: 'python',
name: 'long-task'
}
);
const processId = result.processId;
console.log(`Process started: ${processId}`);
console.log(`Status: ${result.status}`);
await sandbox.kill();
```
## Checking Process Status
Check the status of background processes:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Start background task
result = sandbox.run_code_background(
code='import time; time.sleep(30); print("Done")',
language='python',
name='check-status-demo'
)
process_id = result['process_id']
# Check status periodically
for i in range(5):
processes = sandbox.list_processes()
for proc in processes:
if proc['process_id'] == process_id:
print(f"Status: {proc['status']}")
if proc['status'] == 'completed':
print(f"Output: {proc.get('stdout', '')}")
break
time.sleep(2)
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start background task
const result = await sandbox.runCodeBackground(
'import time; time.sleep(30); print("Done")',
{
language: 'python',
name: 'check-status-demo'
}
);
const processId = result.processId;
// Check status periodically
for (let i = 0; i < 5; i++) {
const processes = await sandbox.listProcesses();
const proc = processes.find(p => p.processId === processId);
if (proc) {
console.log(`Status: ${proc.status}`);
if (proc.status === 'completed') {
console.log(`Output: ${proc.stdout || ''}`);
break;
}
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
await sandbox.kill();
```
## Process Naming
Name your processes for easier identification:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Start multiple named processes
proc1 = sandbox.run_code_background(
code='import time; time.sleep(60)',
language='python',
name='data-processing'
)
proc2 = sandbox.run_code_background(
code='import time; time.sleep(60)',
language='python',
name='ml-training'
)
# List processes by name
processes = sandbox.list_processes()
for proc in processes:
print(f"{proc.get('name', 'unnamed')}: {proc['status']}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start multiple named processes
const proc1 = await sandbox.runCodeBackground(
'import time; time.sleep(60)',
{
language: 'python',
name: 'data-processing'
}
);
const proc2 = await sandbox.runCodeBackground(
'import time; time.sleep(60)',
{
language: 'python',
name: 'ml-training'
}
);
// List processes by name
const processes = await sandbox.listProcesses();
for (const proc of processes) {
console.log(`${proc.name || 'unnamed'}: ${proc.status}`);
}
await sandbox.kill();
```
## Environment Variables
Pass environment variables to background execution:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Start background task with environment variables
result = sandbox.run_code_background(
code='''
import os
import time
api_key = os.getenv("API_KEY")
print(f"Using API key: {api_key[:10]}...")
time.sleep(30)
print("Task completed")
''',
language='python',
env={
"API_KEY": "sk-123456",
"DEBUG": "true"
},
name='env-demo'
)
print(f"Process ID: {result['process_id']}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start background task with environment variables
const result = await sandbox.runCodeBackground(
`
import os
import time
api_key = os.getenv("API_KEY")
print(f"Using API key: {api_key[:10]}...")
time.sleep(30)
print("Task completed")
`,
{
language: 'python',
env: {
API_KEY: 'sk-123456',
DEBUG: 'true'
},
name: 'env-demo'
}
);
console.log(`Process ID: ${result.processId}`);
await sandbox.kill();
```
## Timeout Configuration
Set timeout for background execution:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Start background task with 10 minute timeout
result = sandbox.run_code_background(
code='import time; time.sleep(300)',
language='python',
timeout=600, # 10 minutes
name='long-task'
)
print(f"Process started with {result.get('timeout', 'default')}s timeout")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start background task with 10 minute timeout
const result = await sandbox.runCodeBackground(
'import time; time.sleep(300)',
{
language: 'python',
timeout: 600, // 10 minutes
name: 'long-task'
}
);
console.log(`Process started with ${result.timeout || 'default'}s timeout`);
await sandbox.kill();
```
## Complete Example
Here's a complete example showing background execution workflow:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Start background task
result = sandbox.run_code_background(
code='''
import time
import random
for i in range(20):
value = random.randint(1, 100)
print(f"Step {i+1}: Generated {value}")
time.sleep(1)
print("All done!")
''',
language='python',
timeout=300,
name='random-generator',
env={"SEED": "42"}
)
process_id = result['process_id']
print(f"✅ Background task started: {process_id}")
# Monitor progress
while True:
processes = sandbox.list_processes()
proc = next((p for p in processes if p['process_id'] == process_id), None)
if not proc:
print("Process not found")
break
status = proc['status']
print(f"Status: {status}")
if status == 'completed':
print(f"✅ Task completed!")
print(f"Output:\n{proc.get('stdout', '')}")
break
elif status == 'failed':
print(f"❌ Task failed!")
print(f"Error: {proc.get('stderr', '')}")
break
time.sleep(2)
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start background task
const result = await sandbox.runCodeBackground(
`
import time
import random
for i in range(20):
value = random.randint(1, 100)
print(f"Step {i+1}: Generated {value}")
time.sleep(1)
print("All done!")
`,
{
language: 'python',
timeout: 300,
name: 'random-generator',
env: { SEED: '42' }
}
);
const processId = result.processId;
console.log(`✅ Background task started: ${processId}`);
// Monitor progress
while (true) {
const processes = await sandbox.listProcesses();
const proc = processes.find(p => p.processId === processId);
if (!proc) {
console.log('Process not found');
break;
}
const status = proc.status;
console.log(`Status: ${status}`);
if (status === 'completed') {
console.log('✅ Task completed!');
console.log(`Output:\n${proc.stdout || ''}`);
break;
} else if (status === 'failed') {
console.log('❌ Task failed!');
console.log(`Error: ${proc.stderr || ''}`);
break;
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
await sandbox.kill();
```
## Best Practices
Always name your background processes for easier identification when listing and managing them.
Set timeouts based on expected execution time. Default is 5 minutes, but you can extend for longer tasks.
Check process status periodically to track progress and handle completion or failures.
Remove completed processes to keep your process list manageable. Use [Process Management](/core-concepts/code-execution/process-management) for cleanup.
Always check for failed status and handle errors appropriately. Access `stderr` for error details.
## Implementation
* **SDK**: [sandbox.run\_code\_background()](/sdk/python/sandbox#run_code_background) - Python SDK method
* **[CLI](/cli/introduction)** - Command-line interface
* **API**: [POST /execute/background](/api/vm-agent/execute-background) - VM Agent API endpoint
## Related
* **[Process Management](/core-concepts/code-execution/process-management)** - Monitor and manage background processes
* **[Synchronous Execution](/core-concepts/code-execution/synchronous)** - Execute code synchronously
* **[Streaming Execution](/core-concepts/code-execution/streaming)** - Real-time output streaming
* **[Async Execution with Webhooks](/core-concepts/code-execution/async-webhooks)** - Very long-running tasks
## Next Steps
* Learn about [Process Management](/core-concepts/code-execution/process-management) to monitor and control background processes
* Explore [Async Webhooks](/core-concepts/code-execution/async-webhooks) for very long-running tasks (>30 minutes)
* Review [Synchronous Execution](/core-concepts/code-execution/synchronous) for immediate results
# Code Execution
Source: https://docs.hopx.ai/core-concepts/code-execution/index
Complete guide to executing code in HopX sandboxes - synchronous, asynchronous, background, and streaming execution modes. Learn how to run Python, JavaScript, Bash, and Go code, capture rich outputs like plots and DataFrames, manage background processes, and stream execution results in real-time using SDK methods or REST API endpoints.
Execute code in HopX sandboxes using multiple execution modes. This hub covers all code execution methods, from simple synchronous runs to advanced background and streaming execution.
## Related
* [CLI Code Execution](/cli/commands/run) - Execute code from CLI
## What You'll Learn
* How to execute code synchronously and asynchronously
* How to capture rich outputs (plots, DataFrames, visualizations)
* How to run code in the background for long-running tasks
* How to stream execution results in real-time
* How to manage processes and handle async webhooks
## Code Execution Overview
| Execution Mode | SDK Method | API Endpoint |
| -------------------------------------------------------------------------- | --------------------------------------- | -------------------------- |
| **[Synchronous](/core-concepts/code-execution/synchronous)** | `sandbox.run_code()` | `POST /execute` |
| **[Rich Output](/core-concepts/code-execution/rich-output)** | `sandbox.run_code()` with `rich_output` | `POST /execute` |
| **[Background](/core-concepts/code-execution/background)** | `sandbox.run_code_background()` | `POST /execute/background` |
| **[Streaming](/core-concepts/code-execution/streaming)** | `sandbox.run_code_stream()` | `POST /execute/stream` |
| **[Process Management](/core-concepts/code-execution/process-management)** | `sandbox.list_processes()` | `GET /processes` |
| **[Async Webhooks](/core-concepts/code-execution/async-webhooks)** | Webhook configuration | Webhook endpoints |
## Core Concepts
### Synchronous Execution
Execute code and wait for results. Perfect for quick scripts and data analysis.
* **[Synchronous Execution](/core-concepts/code-execution/synchronous)** - Execute code and get results immediately
* **SDK**: [Python: sandbox.run\_code()](/sdk/python/sandbox#run_code) | [JavaScript: sandbox.runCode()](/sdk/javascript/sandbox#runcode)
* **API**: [POST /execute](/api/vm-agent/execute)
### Rich Output Capture
Capture matplotlib plots, pandas DataFrames, and other rich outputs automatically.
* **[Rich Output](/core-concepts/code-execution/rich-output)** - Capture plots, DataFrames, and visualizations
* **SDK**: [Python: sandbox.run\_code() with rich\_output](/sdk/python/sandbox#run_code) | [JavaScript: sandbox.runCode() with richOutput](/sdk/javascript/sandbox#runcode)
* **API**: [POST /execute](/api/vm-agent/execute) with `rich_output` parameter
### Background Execution
Run long-running code without blocking. Perfect for training models or processing large datasets.
* **[Background Execution](/core-concepts/code-execution/background)** - Run code asynchronously
* **SDK**: [Python: sandbox.run\_code\_background()](/sdk/python/sandbox#run_code_background) | [JavaScript: sandbox.runCodeBackground()](/sdk/javascript/sandbox#runcodebackground)
* **API**: [POST /execute/background](/api/vm-agent/execute-background)
### Streaming Execution
Stream execution results in real-time as code runs.
* **[Streaming Execution](/core-concepts/code-execution/streaming)** - Stream results in real-time
* **SDK**: [Python: sandbox.run\_code\_stream()](/sdk/python/sandbox#run_code_stream) | [JavaScript: sandbox.runCodeStream()](/sdk/javascript/sandbox#runcodestream)
* **API**: [POST /execute/stream](/api/vm-agent/execute-async)
### Process Management
List, monitor, and manage background processes.
* **[Process Management](/core-concepts/code-execution/process-management)** - Manage background processes
* **SDK**: [Python: sandbox.list\_processes()](/sdk/python/sandbox#list_processes) | [JavaScript: sandbox.listProcesses()](/sdk/javascript/sandbox#listprocesses)
* **API**: [GET /processes](/api/vm-agent/list-processes) | [DELETE /execute/kill](/api/vm-agent/kill-process)
### Async Webhooks
Handle code execution results via webhooks for async workflows.
* **[Async Webhooks](/core-concepts/code-execution/async-webhooks)** - Handle results via webhooks
* **SDK**: Webhook configuration in SDK | **API**: Webhook endpoints
## SDK Reference
### Python SDK
Complete reference for Python code execution.
* **[Sandbox.run\_code()](/sdk/python/sandbox#run_code)** - Synchronous execution
* **[Sandbox.run\_code\_background()](/sdk/python/sandbox#run_code_background)** - Background execution
* **[Sandbox.run\_code\_stream()](/sdk/python/sandbox#run_code_stream)** - Streaming execution
* **[Sandbox.list\_processes()](/sdk/python/sandbox#list_processes)** - Process management
### JavaScript SDK
Complete reference for JavaScript/TypeScript code execution.
* **[Sandbox.runCode()](/sdk/javascript/sandbox#runcode)** - Synchronous execution
* **[Sandbox.runCodeBackground()](/sdk/javascript/sandbox#runcodebackground)** - Background execution
* **[Sandbox.runCodeStream()](/sdk/javascript/sandbox#runcodestream)** - Streaming execution
* **[Sandbox.listProcesses()](/sdk/javascript/sandbox#listprocesses)** - Process management
## API Reference
### VM Agent API
REST API endpoints for code execution.
* **[VM Agent API Overview](/api/vm-agent/overview)** - API overview
* **[Execute Code](/api/vm-agent/execute)** - `POST /execute` - Synchronous execution
* **[Execute Background](/api/vm-agent/execute-background)** - `POST /execute/background` - Background execution
* **[Execute Async](/api/vm-agent/execute-async)** - `POST /execute/async` - Async execution
* **[List Processes](/api/vm-agent/list-processes)** - `GET /processes` - List background processes
* **[Kill Process](/api/vm-agent/kill-process)** - `DELETE /execute/kill` - Terminate process
## Quick Start
If you're new to code execution, start here:
1. **[Synchronous Execution](/core-concepts/code-execution/synchronous)** - Execute your first code
2. **[Rich Output](/core-concepts/code-execution/rich-output)** - Capture plots and DataFrames
3. **[Background Execution](/core-concepts/code-execution/background)** - Run long-running tasks
## Related Topics
* **[Sandboxes](/core-concepts/sandboxes/creating)** - Create and manage sandboxes
* **[File Operations](/core-concepts/filesystem/reading)** - Work with files during execution
* **[Environment Variables](/core-concepts/environment/getting)** - Configure execution environment
* **[Observability](/core-concepts/observability/metrics)** - Monitor execution metrics
## Next Steps
* Learn about [File Operations](/core-concepts/filesystem/reading) for working with files
* Explore [Environment Variables](/core-concepts/environment/getting) for configuration
* Review [Process Management](/core-concepts/code-execution/process-management) for advanced workflows
* Check out [Observability](/core-concepts/observability/metrics) for monitoring
# Process Management
Source: https://docs.hopx.ai/core-concepts/code-execution/process-management
List, monitor, and manage background execution processes in HopX sandboxes. Track running processes, check execution status, terminate stuck processes, and manage process lifecycle. Essential for managing long-running code execution and debugging. Includes Python and JavaScript SDK examples and REST API endpoints.
Process management allows you to monitor and control background execution processes. You can list running processes, check their status, and terminate them when needed.
## Overview
Process management is essential for:
* Monitoring background execution progress
* Checking process status and output
* Terminating long-running or stuck processes
* Managing multiple concurrent executions
Process management works with processes started via `run_code_background()`. For system processes, see system process listing in the Observability section.
## Listing Processes
List all background execution processes:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# List all processes
processes = sandbox.list_processes()
print(f"Found {len(processes)} processes")
for proc in processes:
print(f" {proc.get('name', 'unnamed')}: {proc['status']} (ID: {proc['process_id']})")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// List all processes
const processes = await sandbox.listProcesses();
console.log(`Found ${processes.length} processes`);
for (const proc of processes) {
console.log(` ${proc.name || 'unnamed'}: ${proc.status} (ID: ${proc.processId})`);
}
await sandbox.kill();
```
## Process Status
Check detailed status of processes:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Start a background process
result = sandbox.run_code_background(
code='import time; time.sleep(30)',
language='python',
name='status-demo'
)
process_id = result['process_id']
# Check status
processes = sandbox.list_processes()
proc = next((p for p in processes if p['process_id'] == process_id), None)
if proc:
print(f"Process: {proc.get('name', 'unnamed')}")
print(f"Status: {proc['status']}")
print(f"Process ID: {proc['process_id']}")
print(f"Execution ID: {proc.get('execution_id', 'N/A')}")
if proc['status'] == 'completed':
print(f"Output: {proc.get('stdout', '')}")
elif proc['status'] == 'failed':
print(f"Error: {proc.get('stderr', '')}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start a background process
const result = await sandbox.runCodeBackground(
'import time; time.sleep(30)',
{
language: 'python',
name: 'status-demo'
}
);
const processId = result.processId;
// Check status
const processes = await sandbox.listProcesses();
const proc = processes.find(p => p.processId === processId);
if (proc) {
console.log(`Process: ${proc.name || 'unnamed'}`);
console.log(`Status: ${proc.status}`);
console.log(`Process ID: ${proc.processId}`);
console.log(`Execution ID: ${proc.executionId || 'N/A'}`);
if (proc.status === 'completed') {
console.log(`Output: ${proc.stdout || ''}`);
} else if (proc.status === 'failed') {
console.log(`Error: ${proc.stderr || ''}`);
}
}
await sandbox.kill();
```
## Process States
Processes can be in different states:
* **`queued`** - Waiting to start
* **`running`** - Currently executing
* **`completed`** - Finished successfully
* **`failed`** - Execution failed
* **`killed`** - Terminated by user
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Start multiple processes
proc1 = sandbox.run_code_background('import time; time.sleep(10)', name='task-1')
proc2 = sandbox.run_code_background('import time; time.sleep(20)', name='task-2')
# Check states
processes = sandbox.list_processes()
for proc in processes:
status = proc['status']
name = proc.get('name', 'unnamed')
if status == 'running':
print(f"🟢 {name} is running")
elif status == 'completed':
print(f"✅ {name} completed")
elif status == 'failed':
print(f"❌ {name} failed")
elif status == 'queued':
print(f"⏳ {name} is queued")
elif status == 'killed':
print(f"🛑 {name} was killed")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start multiple processes
const proc1 = await sandbox.runCodeBackground('import time; time.sleep(10)', { name: 'task-1' });
const proc2 = await sandbox.runCodeBackground('import time; time.sleep(20)', { name: 'task-2' });
// Check states
const processes = await sandbox.listProcesses();
for (const proc of processes) {
const status = proc.status;
const name = proc.name || 'unnamed';
if (status === 'running') {
console.log(`🟢 ${name} is running`);
} else if (status === 'completed') {
console.log(`✅ ${name} completed`);
} else if (status === 'failed') {
console.log(`❌ ${name} failed`);
} else if (status === 'queued') {
console.log(`⏳ ${name} is queued`);
} else if (status === 'killed') {
console.log(`🛑 ${name} was killed`);
}
}
await sandbox.kill();
```
## Killing Processes
Terminate running processes:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Start a long-running process
result = sandbox.run_code_background(
code='import time; time.sleep(300)',
language='python',
name='long-task'
)
process_id = result['process_id']
print(f"Started process: {process_id}")
# Kill the process
sandbox.kill_process(process_id)
print("Process killed")
# Verify it's killed
processes = sandbox.list_processes()
proc = next((p for p in processes if p['process_id'] == process_id), None)
if proc:
print(f"Status: {proc['status']}") # Should be 'killed'
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start a long-running process
const result = await sandbox.runCodeBackground(
'import time; time.sleep(300)',
{
language: 'python',
name: 'long-task'
}
);
const processId = result.processId;
console.log(`Started process: ${processId}`);
// Kill the process
await sandbox.killProcess(processId);
console.log('Process killed');
// Verify it's killed
const processes = await sandbox.listProcesses();
const proc = processes.find(p => p.processId === processId);
if (proc) {
console.log(`Status: ${proc.status}`); // Should be 'killed'
}
await sandbox.kill();
```
## Monitoring Multiple Processes
Monitor multiple processes simultaneously:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Start multiple processes
processes = []
for i in range(3):
result = sandbox.run_code_background(
code=f'import time; time.sleep({10 + i*5})',
language='python',
name=f'task-{i+1}'
)
processes.append(result['process_id'])
print(f"Started {len(processes)} processes")
# Monitor all processes
while True:
all_processes = sandbox.list_processes()
active = [p for p in all_processes if p['process_id'] in processes and p['status'] in ['queued', 'running']]
if not active:
print("All processes completed")
break
print(f"\nActive processes: {len(active)}")
for proc in active:
print(f" {proc.get('name')}: {proc['status']}")
time.sleep(2)
# Show final status
all_processes = sandbox.list_processes()
for proc in all_processes:
if proc['process_id'] in processes:
print(f"{proc.get('name')}: {proc['status']}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start multiple processes
const processIds = [];
for (let i = 0; i < 3; i++) {
const result = await sandbox.runCodeBackground(
`import time; time.sleep(${10 + i * 5})`,
{
language: 'python',
name: `task-${i + 1}`
}
);
processIds.push(result.processId);
}
console.log(`Started ${processIds.length} processes`);
// Monitor all processes
while (true) {
const allProcesses = await sandbox.listProcesses();
const active = allProcesses.filter(
p => processIds.includes(p.processId) &&
['queued', 'running'].includes(p.status)
);
if (active.length === 0) {
console.log('All processes completed');
break;
}
console.log(`\nActive processes: ${active.length}`);
for (const proc of active) {
console.log(` ${proc.name}: ${proc.status}`);
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
// Show final status
const finalProcesses = await sandbox.listProcesses();
for (const proc of finalProcesses) {
if (processIds.includes(proc.processId)) {
console.log(`${proc.name}: ${proc.status}`);
}
}
await sandbox.kill();
```
## Complete Example
Here's a complete process management workflow:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Start multiple background tasks
tasks = {
'data-processing': 'import time; time.sleep(20); print("Data processed")',
'ml-training': 'import time; time.sleep(30); print("Model trained")',
'report-generation': 'import time; time.sleep(15); print("Report generated")'
}
process_ids = {}
for name, code in tasks.items():
result = sandbox.run_code_background(code, language='python', name=name)
process_ids[name] = result['process_id']
print(f"✅ Started: {name} (ID: {result['process_id']})")
# Monitor all processes
print("\n📊 Monitoring processes...")
while True:
all_processes = sandbox.list_processes()
active = [
p for p in all_processes
if p['process_id'] in process_ids.values()
and p['status'] in ['queued', 'running']
]
if not active:
break
print(f"\nActive: {len(active)}/{len(tasks)}")
for proc in active:
name = proc.get('name', 'unknown')
status = proc['status']
print(f" {name}: {status}")
time.sleep(3)
# Show final results
print("\n📋 Final Status:")
all_processes = sandbox.list_processes()
for name, proc_id in process_ids.items():
proc = next((p for p in all_processes if p['process_id'] == proc_id), None)
if proc:
status_icon = {
'completed': '✅',
'failed': '❌',
'killed': '🛑'
}.get(proc['status'], '⏳')
print(f"{status_icon} {name}: {proc['status']}")
if proc['status'] == 'completed' and proc.get('stdout'):
print(f" Output: {proc['stdout'].strip()}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start multiple background tasks
const tasks = {
'data-processing': 'import time; time.sleep(20); print("Data processed")',
'ml-training': 'import time; time.sleep(30); print("Model trained")',
'report-generation': 'import time; time.sleep(15); print("Report generated")'
};
const processIds = {};
for (const [name, code] of Object.entries(tasks)) {
const result = await sandbox.runCodeBackground(code, {
language: 'python',
name: name
});
processIds[name] = result.processId;
console.log(`✅ Started: ${name} (ID: ${result.processId})`);
}
// Monitor all processes
console.log('\n📊 Monitoring processes...');
while (true) {
const allProcesses = await sandbox.listProcesses();
const active = allProcesses.filter(
p => Object.values(processIds).includes(p.processId) &&
['queued', 'running'].includes(p.status)
);
if (active.length === 0) {
break;
}
console.log(`\nActive: ${active.length}/${Object.keys(tasks).length}`);
for (const proc of active) {
console.log(` ${proc.name}: ${proc.status}`);
}
await new Promise(resolve => setTimeout(resolve, 3000));
}
// Show final results
console.log('\n📋 Final Status:');
const finalProcesses = await sandbox.listProcesses();
for (const [name, procId] of Object.entries(processIds)) {
const proc = finalProcesses.find(p => p.processId === procId);
if (proc) {
const statusIcon = {
'completed': '✅',
'failed': '❌',
'killed': '🛑'
}[proc.status] || '⏳';
console.log(`${statusIcon} ${name}: ${proc.status}`);
if (proc.status === 'completed' && proc.stdout) {
console.log(` Output: ${proc.stdout.trim()}`);
}
}
}
await sandbox.kill();
```
## Best Practices
Always name processes when starting them for easier identification in process lists.
Check process status periodically to track progress and detect failures early.
Remove or archive completed processes to keep your process list manageable.
Check for failed status and access stderr for error details when processes fail.
Use `kill_process()` to terminate processes that are stuck or taking too long.
## Related
* **[Background Execution](/core-concepts/code-execution/background)** - Start background processes
* **[Process Monitoring](/core-concepts/observability/processes)** - Monitor system processes
* **SDK**: [sandbox.list\_processes()](/sdk/python/sandbox#list_processes) - Python SDK method
* **SDK**: [sandbox.kill\_process()](/sdk/python/sandbox#kill_process) - Python SDK method
* **API**: [GET /execute/processes](/api/vm-agent/list-processes) - VM Agent API endpoint
* **API**: [DELETE /execute/kill](/api/vm-agent/kill-process) - VM Agent API endpoint
* [CLI Code Execution](/cli/commands/run) - Execute code from CLI
## Next Steps
* Learn about [Background Execution](/core-concepts/code-execution/background) to start processes
* Explore [Synchronous Execution](/core-concepts/code-execution/synchronous) for immediate results
* Review [Streaming Execution](/core-concepts/code-execution/streaming) for real-time monitoring
# Rich Output
Source: https://docs.hopx.ai/core-concepts/code-execution/rich-output
Automatically capture plots, DataFrames, and visualizations from code execution in HopX sandboxes. Capture matplotlib plots, pandas DataFrames, plotly charts, and other rich outputs automatically without manual file handling. Perfect for data science workflows and visualization. Includes Python and JavaScript SDK examples and REST API endpoints.
Rich output capture automatically detects and captures visual outputs like matplotlib plots, pandas DataFrames, and plotly charts from your code execution.
## Prerequisites
Before you begin, make sure you have:
* **Active sandbox** - A running sandbox (see [Creating Sandboxes](/core-concepts/sandboxes/creating))
* **Understanding of code execution** - Familiarity with [Synchronous Execution](/core-concepts/code-execution/synchronous) is helpful
* **Code that generates visualizations** - Code that creates plots, DataFrames, or charts
## Overview
When you execute code with `run_code()`, HopX automatically captures:
* **Matplotlib plots** → PNG images (base64-encoded)
* **Pandas DataFrames** → HTML tables
* **Plotly charts** → HTML interactive visualizations
* **JSON outputs** → Structured data
Rich output capture is enabled by default in `run_code()`. All visual outputs are automatically detected and included in the `ExecutionResult.rich_outputs` array.
## Automatic Capture
Rich outputs are captured automatically:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Execute code that generates a plot
result = sandbox.run_code('''
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.plot(x, y)
plt.title("Sine Wave")
plt.savefig('/workspace/plot.png')
''')
# Check for rich outputs
print(f"Rich outputs captured: {len(result.rich_outputs)}")
for output in result.rich_outputs:
print(f"Type: {output.type}")
print(f"Data keys: {list(output.data.keys())}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Execute code that generates a plot
const result = await sandbox.runCode(`
import matplotlib.pyplot as plt
import numpy as np
x = np.linspace(0, 10, 100)
y = np.sin(x)
plt.plot(x, y)
plt.title("Sine Wave")
plt.savefig('/workspace/plot.png')
`);
// Check for rich outputs
console.log(`Rich outputs captured: ${result.richOutputs?.length || 0}`);
for (const output of result.richOutputs || []) {
console.log(`Type: ${output.type}`);
console.log(`Data keys: ${Object.keys(output.data)}`);
}
await sandbox.kill();
```
## Matplotlib Plots
Capture matplotlib plots as PNG images:
```python theme={null}
from hopx_ai import Sandbox
import base64
sandbox = Sandbox.create(template="code-interpreter")
result = sandbox.run_code('''
import matplotlib.pyplot as plt
import numpy as np
# Create a simple plot
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
plt.figure(figsize=(10, 6))
plt.plot(x, y, 'b-', linewidth=2, label='sin(x)')
plt.plot(x, np.cos(x), 'r--', linewidth=2, label='cos(x)')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Trigonometric Functions')
plt.legend()
plt.grid(True)
plt.savefig('/workspace/trig_plot.png')
''')
# Access captured plot
for output in result.rich_outputs:
if 'image/png' in output.data:
png_data = output.data['image/png']
print(f"Plot captured: {len(png_data)} bytes")
# png_data is base64-encoded PNG image
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const result = await sandbox.runCode(`
import matplotlib.pyplot as plt
import numpy as np
# Create a simple plot
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)
plt.figure(figsize=(10, 6))
plt.plot(x, y, 'b-', linewidth=2, label='sin(x)')
plt.plot(x, np.cos(x), 'r--', linewidth=2, label='cos(x)')
plt.xlabel('x')
plt.ylabel('y')
plt.title('Trigonometric Functions')
plt.legend()
plt.grid(True)
plt.savefig('/workspace/trig_plot.png')
`);
// Access captured plot
for (const output of result.richOutputs || []) {
if (output.data['image/png']) {
const pngData = output.data['image/png'];
console.log(`Plot captured: ${pngData.length} bytes`);
// pngData is base64-encoded PNG image
}
}
await sandbox.kill();
```
## Pandas DataFrames
Capture pandas DataFrames as HTML tables:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
result = sandbox.run_code('''
import pandas as pd
import numpy as np
# Create a DataFrame
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'Age': [25, 30, 35, 28],
'Score': [85, 92, 78, 95]
}
df = pd.DataFrame(data)
print(df) # DataFrame is automatically captured as HTML
''')
# Access captured DataFrame
for output in result.rich_outputs:
if 'text/html' in output.data:
html_data = output.data['text/html']
print(f"DataFrame captured as HTML: {len(html_data)} chars")
# html_data contains HTML table representation
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const result = await sandbox.runCode(`
import pandas as pd
import numpy as np
# Create a DataFrame
data = {
'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'Age': [25, 30, 35, 28],
'Score': [85, 92, 78, 95]
}
df = pd.DataFrame(data)
print(df) # DataFrame is automatically captured as HTML
`);
// Access captured DataFrame
for (const output of result.richOutputs || []) {
if (output.data['text/html']) {
const htmlData = output.data['text/html'];
console.log(`DataFrame captured as HTML: ${htmlData.length} chars`);
// htmlData contains HTML table representation
}
}
await sandbox.kill();
```
## Plotly Charts
Capture interactive Plotly charts as HTML:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
result = sandbox.run_code('''
import plotly.graph_objects as go
import numpy as np
# Create interactive plot
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=y, mode='lines', name='sin(x)'))
fig.update_layout(title='Interactive Plot', xaxis_title='x', yaxis_title='y')
fig.write_html('/workspace/plot.html')
''')
# Access captured Plotly chart
for output in result.rich_outputs:
if 'text/html' in output.data:
html_data = output.data['text/html']
print(f"Plotly chart captured: {len(html_data)} chars")
# html_data contains interactive HTML chart
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const result = await sandbox.runCode(`
import plotly.graph_objects as go
import numpy as np
# Create interactive plot
x = np.linspace(0, 10, 100)
y = np.sin(x)
fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=y, mode='lines', name='sin(x)'))
fig.update_layout(title='Interactive Plot', xaxis_title='x', yaxis_title='y')
fig.write_html('/workspace/plot.html')
`);
// Access captured Plotly chart
for (const output of result.richOutputs || []) {
if (output.data['text/html']) {
const htmlData = output.data['text/html'];
console.log(`Plotly chart captured: ${htmlData.length} chars`);
// htmlData contains interactive HTML chart
}
}
await sandbox.kill();
```
## Multiple Rich Outputs
Capture multiple outputs in a single execution:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
result = sandbox.run_code('''
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# Create a plot
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
plt.savefig('/workspace/plot1.png')
# Create a DataFrame
df = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]})
print(df)
# Create another plot
plt.figure()
plt.scatter([1, 2, 3], [4, 5, 6])
plt.savefig('/workspace/plot2.png')
''')
# Access all captured outputs
print(f"Total rich outputs: {len(result.rich_outputs)}")
for i, output in enumerate(result.rich_outputs):
print(f"Output {i+1}: {output.type}")
print(f" Data types: {list(output.data.keys())}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const result = await sandbox.runCode(`
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# Create a plot
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
plt.savefig('/workspace/plot1.png')
# Create a DataFrame
df = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]})
print(df)
# Create another plot
plt.figure()
plt.scatter([1, 2, 3], [4, 5, 6])
plt.savefig('/workspace/plot2.png')
`);
// Access all captured outputs
console.log(`Total rich outputs: ${result.richOutputs?.length || 0}`);
for (let i = 0; i < (result.richOutputs?.length || 0); i++) {
const output = result.richOutputs[i];
console.log(`Output ${i + 1}: ${output.type}`);
console.log(` Data types: ${Object.keys(output.data)}`);
}
await sandbox.kill();
```
## Rich Output Structure
Each rich output has the following structure:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
result = sandbox.run_code('''
import matplotlib.pyplot as plt
plt.plot([1, 2, 3])
plt.savefig('/workspace/plot.png')
''')
# Inspect rich output structure
for output in result.rich_outputs:
print(f"Type: {output.type}") # e.g., "image/png", "text/html"
print(f"Data: {type(output.data)}") # Dict[str, str]
# Access specific data format
if 'image/png' in output.data:
png_base64 = output.data['image/png']
# Decode if needed: import base64; image_bytes = base64.b64decode(png_base64)
if 'text/html' in output.data:
html_content = output.data['text/html']
# Use HTML content directly
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const result = await sandbox.runCode(`
import matplotlib.pyplot as plt
plt.plot([1, 2, 3])
plt.savefig('/workspace/plot.png')
`);
// Inspect rich output structure
for (const output of result.richOutputs || []) {
console.log(`Type: ${output.type}`); // e.g., "image/png", "text/html"
console.log(`Data: ${typeof output.data}`); // object
// Access specific data format
if (output.data['image/png']) {
const pngBase64 = output.data['image/png'];
// Decode if needed: const imageBytes = Buffer.from(pngBase64, 'base64');
}
if (output.data['text/html']) {
const htmlContent = output.data['text/html'];
// Use HTML content directly
}
}
await sandbox.kill();
```
## Complete Example
Here's a complete example with all rich output types:
```python theme={null}
from hopx_ai import Sandbox
import base64
sandbox = Sandbox.create(template="code-interpreter")
result = sandbox.run_code('''
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# 1. Matplotlib plot
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x))
plt.title("Sine Wave")
plt.savefig('/workspace/sine.png')
# 2. Pandas DataFrame
df = pd.DataFrame({
'x': x[::10],
'sin(x)': np.sin(x[::10])
})
print(df)
# 3. Multiple plots
plt.figure()
plt.subplot(2, 1, 1)
plt.plot(x, np.sin(x))
plt.title("Sin")
plt.subplot(2, 1, 2)
plt.plot(x, np.cos(x))
plt.title("Cos")
plt.savefig('/workspace/multiplot.png')
''')
# Process all rich outputs
print(f"Captured {len(result.rich_outputs)} rich outputs\n")
for i, output in enumerate(result.rich_outputs, 1):
print(f"Output {i}:")
print(f" Type: {output.type}")
if 'image/png' in output.data:
png_data = output.data['image/png']
print(f" PNG size: {len(png_data)} bytes (base64)")
if 'text/html' in output.data:
html_data = output.data['text/html']
print(f" HTML size: {len(html_data)} chars")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const result = await sandbox.runCode(`
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
# 1. Matplotlib plot
x = np.linspace(0, 10, 100)
plt.plot(x, np.sin(x))
plt.title("Sine Wave")
plt.savefig('/workspace/sine.png')
# 2. Pandas DataFrame
df = pd.DataFrame({
'x': x[::10],
'sin(x)': np.sin(x[::10])
})
print(df)
# 3. Multiple plots
plt.figure()
plt.subplot(2, 1, 1)
plt.plot(x, np.sin(x))
plt.title("Sin")
plt.subplot(2, 1, 2)
plt.plot(x, np.cos(x))
plt.title("Cos")
plt.savefig('/workspace/multiplot.png')
`);
// Process all rich outputs
console.log(`Captured ${result.richOutputs?.length || 0} rich outputs\n`);
for (let i = 0; i < (result.richOutputs?.length || 0); i++) {
const output = result.richOutputs[i];
console.log(`Output ${i + 1}:`);
console.log(` Type: ${output.type}`);
if (output.data['image/png']) {
const pngData = output.data['image/png'];
console.log(` PNG size: ${pngData.length} bytes (base64)`);
}
if (output.data['text/html']) {
const htmlData = output.data['text/html'];
console.log(` HTML size: ${htmlData.length} chars`);
}
}
await sandbox.kill();
```
## Best Practices
Always save plots to files (e.g., `plt.savefig()`) to ensure they're captured. Rich output capture works best when files are explicitly saved.
* Matplotlib: Save as PNG for best compatibility
* Pandas: Print DataFrames to trigger HTML capture
* Plotly: Use `write_html()` for interactive charts
Use `len(result.rich_outputs)` to verify all expected outputs were captured.
PNG images are base64-encoded. Decode them before displaying or saving locally.
You can capture multiple plots/DataFrames in a single execution. All will be included in `rich_outputs`.
## Related
* **[Synchronous Execution](/core-concepts/code-execution/synchronous)** - Basic code execution
* **[Background Execution](/core-concepts/code-execution/background)** - Long-running tasks
* **SDK**: [sandbox.run\_code()](/sdk/python/sandbox#run_code) - Python SDK method (rich output enabled by default)
* **API**: [POST /execute](/api/vm-agent/execute) - VM Agent API endpoint
* [CLI Code Execution](/cli/commands/run) - Execute code from CLI
## Next Steps
* Learn about [Synchronous Execution](/core-concepts/code-execution/synchronous) basics
* Explore [Background Execution](/core-concepts/code-execution/background) for long-running visualizations
* Review [Streaming Execution](/core-concepts/code-execution/streaming) for real-time output
# Streaming
Source: https://docs.hopx.ai/core-concepts/code-execution/streaming
Execute code with real-time output streaming via WebSocket in HopX sandboxes. Stream execution results in real-time as code runs, monitor progress, and handle long-running operations with live updates. Perfect for interactive development and progress monitoring. Includes Python and JavaScript SDK examples and WebSocket API endpoints.
Streaming execution provides real-time output as your code runs. Instead of waiting for completion, you receive stdout and stderr messages as they're generated, perfect for monitoring long-running tasks.
## Overview
Streaming execution is ideal for:
* Long-running tasks where you want real-time progress
* Interactive code that produces output over time
* Monitoring execution progress
* Building real-time dashboards or UIs
Streaming execution uses WebSocket connections for real-time communication. It requires async/await support in your code.
## Basic Streaming
Stream execution output in real-time:
```python theme={null}
from hopx_ai import Sandbox
import asyncio
async def stream_execution():
sandbox = Sandbox.create(template="code-interpreter")
code = '''
import time
for i in range(5):
print(f"Step {i+1}/5")
time.sleep(1)
print("Done!")
'''
async for message in sandbox.run_code_stream(code):
if message['type'] == 'stdout':
print(message['data'], end='')
elif message['type'] == 'stderr':
print(f"ERROR: {message['data']}", end='', file=sys.stderr)
elif message['type'] == 'result':
print(f"\nExit code: {message['exit_code']}")
print(f"Execution time: {message['execution_time']}s")
elif message['type'] == 'complete':
print("\n✅ Execution completed")
break
sandbox.kill()
asyncio.run(stream_execution())
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function streamExecution() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const code = `
import time
for i in range(5):
print(f"Step {i+1}/5")
time.sleep(1)
print("Done!")
`;
for await (const message of sandbox.runCodeStream(code)) {
if (message.type === 'stdout') {
process.stdout.write(message.data);
} else if (message.type === 'stderr') {
process.stderr.write(`ERROR: ${message.data}`);
} else if (message.type === 'result') {
console.log(`\nExit code: ${message.exit_code}`);
console.log(`Execution time: ${message.execution_time}s`);
} else if (message.type === 'complete') {
console.log('\n✅ Execution completed');
break;
}
}
await sandbox.kill();
}
streamExecution();
```
## Message Types
Stream messages have different types:
```python theme={null}
from hopx_ai import Sandbox
import asyncio
async def handle_all_message_types():
sandbox = Sandbox.create(template="code-interpreter")
code = '''
import sys
print("This is stdout")
print("This is also stdout", file=sys.stdout)
print("This is stderr", file=sys.stderr)
'''
async for message in sandbox.run_code_stream(code):
msg_type = message['type']
if msg_type == 'stdout':
print(f"[STDOUT] {message['data']}", end='')
elif msg_type == 'stderr':
print(f"[STDERR] {message['data']}", end='')
elif msg_type == 'result':
print(f"\n[RESULT] Exit: {message['exit_code']}, Time: {message['execution_time']}s")
elif msg_type == 'complete':
print("[COMPLETE] Execution finished")
break
sandbox.kill()
asyncio.run(handle_all_message_types())
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function handleAllMessageTypes() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const code = `
import sys
print("This is stdout")
print("This is also stdout", file=sys.stdout)
print("This is stderr", file=sys.stderr)
`;
for await (const message of sandbox.runCodeStream(code)) {
const msgType = message.type;
if (msgType === 'stdout') {
process.stdout.write(`[STDOUT] ${message.data}`);
} else if (msgType === 'stderr') {
process.stderr.write(`[STDERR] ${message.data}`);
} else if (msgType === 'result') {
console.log(`\n[RESULT] Exit: ${message.exit_code}, Time: ${message.execution_time}s`);
} else if (msgType === 'complete') {
console.log('[COMPLETE] Execution finished');
break;
}
}
await sandbox.kill();
}
handleAllMessageTypes();
```
## Progress Monitoring
Monitor progress of long-running tasks:
```python theme={null}
from hopx_ai import Sandbox
import asyncio
async def monitor_progress():
sandbox = Sandbox.create(template="code-interpreter")
code = '''
import time
total_steps = 20
for i in range(total_steps):
progress = (i + 1) / total_steps * 100
print(f"Progress: {progress:.1f}% ({i+1}/{total_steps})")
time.sleep(0.5)
print("All steps completed!")
'''
async for message in sandbox.run_code_stream(code):
if message['type'] == 'stdout':
# Display progress in real-time
print(message['data'], end='')
elif message['type'] == 'complete':
print("\n✅ Task completed successfully")
break
sandbox.kill()
asyncio.run(monitor_progress())
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function monitorProgress() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const code = `
import time
total_steps = 20
for i in range(total_steps):
progress = (i + 1) / total_steps * 100
print(f"Progress: {progress:.1f}% ({i+1}/{total_steps})")
time.sleep(0.5)
print("All steps completed!")
`;
for await (const message of sandbox.runCodeStream(code)) {
if (message.type === 'stdout') {
// Display progress in real-time
process.stdout.write(message.data);
} else if (message.type === 'complete') {
console.log('\n✅ Task completed successfully');
break;
}
}
await sandbox.kill();
}
monitorProgress();
```
## Environment Variables
Pass environment variables to streaming execution:
```python theme={null}
from hopx_ai import Sandbox
import asyncio
async def stream_with_env():
sandbox = Sandbox.create(template="code-interpreter")
code = '''
import os
print(f"API key: {os.getenv('API_KEY', 'not set')}")
print(f"Debug mode: {os.getenv('DEBUG', 'false')}")
'''
async for message in sandbox.run_code_stream(
code,
env={"API_KEY": "sk-123", "DEBUG": "true"}
):
if message['type'] == 'stdout':
print(message['data'], end='')
elif message['type'] == 'complete':
break
sandbox.kill()
asyncio.run(stream_with_env())
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function streamWithEnv() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const code = `
import os
print(f"API key: {os.getenv('API_KEY', 'not set')}")
print(f"Debug mode: {os.getenv('DEBUG', 'false')}")
`;
for await (const message of sandbox.runCodeStream(code, {
env: { API_KEY: 'sk-123', DEBUG: 'true' }
})) {
if (message.type === 'stdout') {
process.stdout.write(message.data);
} else if (message.type === 'complete') {
break;
}
}
await sandbox.kill();
}
streamWithEnv();
```
## Error Handling
Handle errors in streaming execution:
```python theme={null}
from hopx_ai import Sandbox
import asyncio
async def handle_streaming_errors():
sandbox = Sandbox.create(template="code-interpreter")
code = '''
print("Starting...")
print(undefined_variable) # This will cause an error
print("This won't be reached")
'''
try:
async for message in sandbox.run_code_stream(code):
if message['type'] == 'stdout':
print(message['data'], end='')
elif message['type'] == 'stderr':
print(f"ERROR: {message['data']}", end='')
elif message['type'] == 'result':
if message['exit_code'] != 0:
print(f"\n❌ Execution failed with exit code: {message['exit_code']}")
elif message['type'] == 'complete':
if not message.get('success', False):
print("\n❌ Execution completed with errors")
break
except Exception as e:
print(f"Streaming error: {e}")
finally:
sandbox.kill()
asyncio.run(handle_streaming_errors())
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function handleStreamingErrors() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const code = `
print("Starting...")
print(undefined_variable) # This will cause an error
print("This won't be reached")
`;
try {
for await (const message of sandbox.runCodeStream(code)) {
if (message.type === 'stdout') {
process.stdout.write(message.data);
} else if (message.type === 'stderr') {
process.stderr.write(`ERROR: ${message.data}`);
} else if (message.type === 'result') {
if (message.exit_code !== 0) {
console.log(`\n❌ Execution failed with exit code: ${message.exit_code}`);
}
} else if (message.type === 'complete') {
if (!message.success) {
console.log('\n❌ Execution completed with errors');
}
break;
}
}
} catch (error) {
console.error(`Streaming error: ${error.message}`);
} finally {
await sandbox.kill();
}
}
handleStreamingErrors();
```
## Complete Example
Here's a complete example with real-time progress:
```python theme={null}
from hopx_ai import Sandbox
import asyncio
async def complete_streaming_example():
sandbox = Sandbox.create(template="code-interpreter")
code = '''
import time
import random
print("Starting data processing...")
total_items = 100
for i in range(total_items):
# Simulate processing
time.sleep(0.1)
# Generate some output
if i % 10 == 0:
print(f"Processed {i}/{total_items} items")
# Simulate occasional errors
if random.random() < 0.05:
print(f"Warning: Issue with item {i}", file=sys.stderr)
print("Processing complete!")
print(f"Total items processed: {total_items}")
'''
print("🔄 Starting streaming execution...\n")
async for message in sandbox.run_code_stream(
code,
language='python',
timeout=120,
env={"BATCH_SIZE": "10"}
):
if message['type'] == 'stdout':
print(message['data'], end='')
elif message['type'] == 'stderr':
print(f"⚠️ {message['data']}", end='')
elif message['type'] == 'result':
print(f"\n\n📊 Execution Summary:")
print(f" Exit code: {message['exit_code']}")
print(f" Execution time: {message['execution_time']:.2f}s")
elif message['type'] == 'complete':
print("\n✅ Streaming completed")
break
sandbox.kill()
asyncio.run(complete_streaming_example())
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function completeStreamingExample() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const code = `
import time
import random
print("Starting data processing...")
total_items = 100
for i in range(total_items):
# Simulate processing
time.sleep(0.1)
# Generate some output
if i % 10 == 0:
print(f"Processed {i}/{total_items} items")
# Simulate occasional errors
if random.random() < 0.05:
print(f"Warning: Issue with item {i}", file=sys.stderr)
print("Processing complete!")
print(f"Total items processed: {total_items}")
`;
console.log('🔄 Starting streaming execution...\n');
for await (const message of sandbox.runCodeStream(code, {
language: 'python',
timeout: 120,
env: { BATCH_SIZE: '10' }
})) {
if (message.type === 'stdout') {
process.stdout.write(message.data);
} else if (message.type === 'stderr') {
process.stderr.write(`⚠️ ${message.data}`);
} else if (message.type === 'result') {
console.log(`\n\n📊 Execution Summary:`);
console.log(` Exit code: ${message.exit_code}`);
console.log(` Execution time: ${message.execution_time.toFixed(2)}s`);
} else if (message.type === 'complete') {
console.log('\n✅ Streaming completed');
break;
}
}
await sandbox.kill();
}
completeStreamingExample();
```
## Best Practices
Streaming execution requires async/await. Make sure your code uses async functions and `async for` loops.
Process stdout, stderr, result, and complete messages appropriately for a complete streaming experience.
Always break the loop when you receive a 'complete' message to avoid unnecessary processing.
Check exit codes and success flags to handle execution failures gracefully.
Streaming is best for tasks where real-time output is valuable. For simple scripts, synchronous execution may be simpler.
## Related
* **[Synchronous Execution](/core-concepts/code-execution/synchronous)** - Basic code execution
* **[Background Execution](/core-concepts/code-execution/background)** - Long-running tasks
* **[Rich Output Capture](/core-concepts/code-execution/rich-output)** - Capture plots and visualizations
* **SDK**: [sandbox.run\_code\_stream()](/sdk/python/sandbox#run_code_stream) - Python SDK method
* [CLI Code Execution](/cli/commands/run) - Execute code from CLI
## Next Steps
* Learn about [Synchronous Execution](/core-concepts/code-execution/synchronous) for immediate results
* Explore [Background Execution](/core-concepts/code-execution/background) for non-blocking tasks
* Review [Process Management](/core-concepts/code-execution/process-management) for monitoring
# Synchronous
Source: https://docs.hopx.ai/core-concepts/code-execution/synchronous
Execute code synchronously and wait for results. Learn how to run Python, JavaScript, Bash, and Go code in HopX sandboxes, handle execution results, manage timeouts, and process outputs. Includes SDK examples and REST API endpoints for synchronous code execution.
Synchronous execution is the simplest way to run code in a sandbox. The execution blocks until the code completes, then returns the results immediately.
## Prerequisites
Before you begin, make sure you have:
* **Active sandbox** - A running sandbox (see [Creating Sandboxes](/core-concepts/sandboxes/creating))
* **Sandbox object** - A `Sandbox` instance connected to your sandbox
* **Code to execute** - The code you want to run in the sandbox
## Overview
Synchronous execution is ideal for:
* Quick scripts and computations
* Code that completes in seconds or minutes
* When you need immediate results
* Simple workflows without complex state management
Synchronous execution automatically captures rich outputs (plots, DataFrames) when available. For more control over rich output capture, see [Rich Output](/core-concepts/code-execution/rich-output).
## Basic Execution
Execute code and wait for results:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Execute simple code
result = sandbox.run_code('print("Hello, World!")')
print(result.stdout) # "Hello, World!\n"
print(f"Success: {result.success}")
print(f"Exit code: {result.exit_code}")
print(f"Execution time: {result.execution_time}s")
sandbox.kill()
```
**Expected Output:**
```
Hello, World!
Success: True
Exit code: 0
Execution time: 1.23s
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Execute simple code
const result = await sandbox.runCode('print("Hello, World!")');
console.log(result.stdout); // "Hello, World!\n"
console.log(`Success: ${result.success}`);
console.log(`Exit code: ${result.exitCode}`);
console.log(`Execution time: ${result.executionTime}s`);
await sandbox.kill();
```
**Expected Output:**
```
Hello, World!
Success: true
Exit code: 0
Execution time: 1.23s
```
## Execution Result
The `ExecutionResult` object contains:
* **`stdout`** - Standard output from code execution
* **`stderr`** - Standard error output (if any)
* **`exit_code`** - Exit code (0 = success, non-zero = error)
* **`success`** - Boolean indicating if execution succeeded
* **`execution_time`** - Time taken in seconds
* **`rich_outputs`** - Array of captured rich outputs (plots, DataFrames)
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
result = sandbox.run_code('''
import sys
print("Python version:", sys.version)
print("Platform:", sys.platform)
''')
# Access all result fields
print(f"Output: {result.stdout}")
print(f"Errors: {result.stderr}")
print(f"Success: {result.success}")
print(f"Exit code: {result.exit_code}")
print(f"Time: {result.execution_time}s")
print(f"Rich outputs: {len(result.rich_outputs)}")
sandbox.kill()
```
**Expected Output:**
```
Output: Python version: 3.11.0 (main, Oct 24 2023, 00:00:00) [GCC 11.3.0]
Platform: linux
Errors:
Success: True
Exit code: 0
Time: 1.45s
Rich outputs: 0
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const result = await sandbox.runCode(`
import sys
print("Python version:", sys.version)
print("Platform:", sys.platform)
`);
// Access all result fields
console.log(`Output: ${result.stdout}`);
console.log(`Errors: ${result.stderr}`);
console.log(`Success: ${result.success}`);
console.log(`Exit code: ${result.exitCode}`);
console.log(`Time: ${result.executionTime}s`);
console.log(`Rich outputs: ${result.richOutputs?.length || 0}`);
await sandbox.kill();
```
**Expected Output:**
```
Output: Python version: 3.11.0 (main, Oct 24 2023, 00:00:00) [GCC 11.3.0]
Platform: linux
Errors:
Success: true
Exit code: 0
Time: 1.45s
Rich outputs: 0
```
## Language Support
Execute code in different languages:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Python
result = sandbox.run_code('print("Hello from Python!")', language='python')
print(result.stdout)
# JavaScript
result = sandbox.run_code('console.log("Hello from JavaScript!")', language='javascript')
print(result.stdout)
# Bash
result = sandbox.run_code('echo "Hello from Bash!"', language='bash')
print(result.stdout)
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Python
let result = await sandbox.runCode('print("Hello from Python!")', { language: 'python' });
console.log(result.stdout);
// JavaScript
result = await sandbox.runCode('console.log("Hello from JavaScript!")', { language: 'javascript' });
console.log(result.stdout);
// Bash
result = await sandbox.runCode('echo "Hello from Bash!"', { language: 'bash' });
console.log(result.stdout);
await sandbox.kill();
```
## Environment Variables
Pass environment variables for execution:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Execute with environment variables
result = sandbox.run_code(
'import os; print(os.getenv("API_KEY"))',
language='python',
env={"API_KEY": "sk-123", "DEBUG": "true"}
)
print(result.stdout) # "sk-123"
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Execute with environment variables
const result = await sandbox.runCode(
'import os; print(os.getenv("API_KEY"))',
{
language: 'python',
env: { API_KEY: 'sk-123', DEBUG: 'true' }
}
);
console.log(result.stdout); // "sk-123"
await sandbox.kill();
```
Environment variables passed to `run_code()` have priority over global environment variables set via `sandbox.env.set()`. Priority: Request env > Global env > Agent env.
## Working Directory
Specify a custom working directory:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Execute in custom directory
result = sandbox.run_code(
'import os; print(os.getcwd())',
language='python',
working_dir='/tmp/myproject'
)
print(result.stdout) # "/tmp/myproject"
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Execute in custom directory
const result = await sandbox.runCode(
'import os; print(os.getcwd())',
{
language: 'python',
workingDir: '/tmp/myproject'
}
);
console.log(result.stdout); // "/tmp/myproject"
await sandbox.kill();
```
## Timeout Configuration
Set execution timeout for long-running code:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Execute with custom timeout (5 minutes)
result = sandbox.run_code(
'import time; time.sleep(10); print("Done")',
language='python',
timeout=300 # 5 minutes
)
print(result.stdout)
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Execute with custom timeout (5 minutes)
const result = await sandbox.runCode(
'import time; time.sleep(10); print("Done")',
{
language: 'python',
timeout: 300 // 5 minutes
}
);
console.log(result.stdout);
await sandbox.kill();
```
Default timeout is 60 seconds. Maximum timeout is 300 seconds (5 minutes) for synchronous execution. For longer-running code, use [Background Execution](/core-concepts/code-execution/background) or [Async Webhooks](/core-concepts/code-execution/async-webhooks).
## Error Handling
Handle execution errors:
```python theme={null}
from hopx_ai import Sandbox
from hopx_ai.errors import CodeExecutionError, TimeoutError
sandbox = Sandbox.create(template="code-interpreter")
try:
result = sandbox.run_code('print(undefined_var)', language='python')
if not result.success:
print(f"Execution failed with exit code: {result.exit_code}")
print(f"Error output: {result.stderr}")
else:
print(f"Output: {result.stdout}")
except TimeoutError:
print("Execution timed out")
except CodeExecutionError as e:
print(f"Execution error: {e}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import { CodeExecutionError, TimeoutError } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
try {
const result = await sandbox.runCode('print(undefined_var)', { language: 'python' });
if (!result.success) {
console.error(`Execution failed with exit code: ${result.exitCode}`);
console.error(`Error output: ${result.stderr}`);
} else {
console.log(`Output: ${result.stdout}`);
}
} catch (error) {
if (error instanceof TimeoutError) {
console.error('Execution timed out');
} else if (error instanceof CodeExecutionError) {
console.error(`Execution error: ${error.message}`);
}
}
await sandbox.kill();
```
## Complete Example
Here's a complete example showing all features:
```python theme={null}
from hopx_ai import Sandbox
# Create sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Execute code with all options
result = sandbox.run_code(
'''
import os
import sys
print(f"Python: {sys.version}")
print(f"Working directory: {os.getcwd()}")
print(f"API key: {os.getenv('API_KEY', 'not set')}")
print(f"Debug mode: {os.getenv('DEBUG', 'false')}")
''',
language='python',
timeout=120,
env={
"API_KEY": "sk-123",
"DEBUG": "true"
},
working_dir='/workspace'
)
# Check results
if result.success:
print("✅ Execution successful")
print(f"Output:\n{result.stdout}")
else:
print("❌ Execution failed")
print(f"Error: {result.stderr}")
print(f"Exit code: {result.exit_code}")
print(f"Execution time: {result.execution_time}s")
# Cleanup
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Create sandbox
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Execute code with all options
const result = await sandbox.runCode(
`
import os
import sys
print(f"Python: {sys.version}")
print(f"Working directory: {os.getcwd()}")
print(f"API key: {os.getenv('API_KEY', 'not set')}")
print(f"Debug mode: {os.getenv('DEBUG', 'false')}")
`,
{
language: 'python',
timeout: 120,
env: {
API_KEY: 'sk-123',
DEBUG: 'true'
},
workingDir: '/workspace'
}
);
// Check results
if (result.success) {
console.log('✅ Execution successful');
console.log(`Output:\n${result.stdout}`);
} else {
console.error('❌ Execution failed');
console.error(`Error: ${result.stderr}`);
console.error(`Exit code: ${result.exitCode}`);
}
console.log(`Execution time: ${result.executionTime}s`);
// Cleanup
await sandbox.kill();
```
## Best Practices
Set timeouts based on expected execution time. Default 60 seconds is good for quick scripts, but increase for longer operations.
Always check `result.success` and handle `stderr` appropriately. Use try/catch for exception handling.
Pass environment variables via `env` parameter rather than hardcoding values in code.
Monitor `execution_time` to optimize code performance and identify slow operations.
For code that runs longer than 5 minutes, use [Background Execution](/core-concepts/code-execution/background) instead.
## Implementation
* **SDK**: [sandbox.run\_code()](/sdk/python/sandbox#run_code) - Python SDK method
* **[CLI](/cli/introduction)** - Command-line interface
* **API**: [POST /execute](/api/vm-agent/execute) - VM Agent API endpoint
## Related
* **[Background Execution](/core-concepts/code-execution/background)** - Long-running tasks
* **[Rich Output Capture](/core-concepts/code-execution/rich-output)** - Capture plots and visualizations
* **[Streaming Execution](/core-concepts/code-execution/streaming)** - Real-time output streaming
* **[Async Execution with Webhooks](/core-concepts/code-execution/async-webhooks)** - Very long-running tasks
## Next Steps
* Learn about [Rich Output](/core-concepts/code-execution/rich-output) capture for plots and DataFrames
* Explore [Background Execution](/core-concepts/code-execution/background) for non-blocking operations
* Discover [Streaming Execution](/core-concepts/code-execution/streaming) for real-time output
* Review [Process Management](/core-concepts/code-execution/process-management) for background processes
# Background
Source: https://docs.hopx.ai/core-concepts/commands/background
Execute shell commands in the background without blocking in HopX sandboxes. Run long-running shell commands asynchronously, monitor process status, and retrieve results when complete. Perfect for package installations, data processing, and time-consuming operations. Includes Python and JavaScript SDK examples and REST API endpoints.
Run shell commands in the background and return immediately. This is ideal for long-running commands that you want to monitor and manage separately.
## Overview
Background command execution is perfect for:
* Long-running commands (>5 minutes)
* Server processes that need to keep running
* Commands that don't need immediate results
* Parallel execution of multiple commands
Background commands return immediately with a `process_id`. Use process management to check status and manage background processes.
## Starting Background Commands
Start a command in the background:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Start background command
result = sandbox.commands.run(
'sleep 30 && echo "Done!"',
background=True
)
# Extract process ID from output
process_id = result.stdout.split('cmd_')[-1].strip() if 'cmd_' in result.stdout else None
print(f"Process started: {process_id}")
print(f"Status: {result.stdout}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start background command
const result = await sandbox.commands.runBackground(
'sleep 30 && echo "Done!"'
);
console.log(`Process started: ${result.processId}`);
console.log(`Status: ${result.status || 'running'}`);
await sandbox.kill();
```
## Checking Process Status
Check the status of background commands:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Start background command
result = sandbox.commands.run(
'sleep 30 && echo "Task completed"',
background=True
)
# Extract process ID
process_id = result.stdout.split('cmd_')[-1].strip() if 'cmd_' in result.stdout else None
# Check status using list_processes
for i in range(5):
processes = sandbox.list_processes()
for proc in processes:
if proc.get('process_id') == process_id:
print(f"Status: {proc['status']}")
if proc['status'] == 'completed':
print(f"Output: {proc.get('stdout', '')}")
break
time.sleep(2)
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start background command
const result = await sandbox.commands.runBackground(
'sleep 30 && echo "Task completed"'
);
const processId = result.processId;
// Check status using listProcesses
for (let i = 0; i < 5; i++) {
const processes = await sandbox.listProcesses();
const proc = processes.find(p => p.processId === processId);
if (proc) {
console.log(`Status: ${proc.status}`);
if (proc.status === 'completed') {
console.log(`Output: ${proc.stdout || ''}`);
break;
}
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
await sandbox.kill();
```
## Long-Running Servers
Start long-running server processes:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Start a web server in background
result = sandbox.commands.run(
'python -m http.server 8000',
background=True,
timeout=3600, # 1 hour
env={"PORT": "8000"}
)
process_id = result.stdout.split('cmd_')[-1].strip() if 'cmd_' in result.stdout else None
print(f"Server started: {process_id}")
# Check if server is running
time.sleep(2)
processes = sandbox.list_processes()
for proc in processes:
if proc.get('process_id') == process_id:
print(f"Server status: {proc['status']}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start a web server in background
const result = await sandbox.commands.runBackground(
'python -m http.server 8000',
{
timeout: 3600, // 1 hour
env: { PORT: '8000' }
}
);
console.log(`Server started: ${result.processId}`);
// Check if server is running
await new Promise(resolve => setTimeout(resolve, 2000));
const processes = await sandbox.listProcesses();
const serverProc = processes.find(p => p.processId === result.processId);
if (serverProc) {
console.log(`Server status: ${serverProc.status}`);
}
await sandbox.kill();
```
## Environment Variables
Pass environment variables to background commands:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Start background command with environment variables
result = sandbox.commands.run(
'python -c "import os, time; print(os.getenv(\'API_KEY\')); time.sleep(60)"',
background=True,
env={
"API_KEY": "sk-123456",
"DEBUG": "true"
}
)
print(f"Process started: {result.stdout}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start background command with environment variables
const result = await sandbox.commands.runBackground(
'python -c "import os, time; print(os.getenv(\'API_KEY\')); time.sleep(60)"',
{
env: {
API_KEY: 'sk-123456',
DEBUG: 'true'
}
}
);
console.log(`Process started: ${result.processId}`);
await sandbox.kill();
```
## Timeout Configuration
Set timeout for background commands:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Start background command with 10 minute timeout
result = sandbox.commands.run(
'long_running_task.sh',
background=True,
timeout=600 # 10 minutes
)
print(f"Process started with {600}s timeout")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start background command with 10 minute timeout
const result = await sandbox.commands.runBackground(
'long_running_task.sh',
{
timeout: 600 // 10 minutes
}
);
console.log(`Process started with 600s timeout`);
await sandbox.kill();
```
## Complete Example
Here's a complete example showing background command workflow:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Start multiple background tasks
tasks = {
'data-processing': 'python process_data.py',
'ml-training': 'python train_model.py',
'report-generation': 'python generate_report.py'
}
process_ids = {}
print("🚀 Starting background tasks...\n")
for name, command in tasks.items():
result = sandbox.commands.run(
command,
background=True,
timeout=600,
env={"TASK_NAME": name}
)
process_id = result.stdout.split('cmd_')[-1].strip() if 'cmd_' in result.stdout else None
process_ids[name] = process_id
print(f"✅ Started: {name} (ID: {process_id})")
# Monitor all processes
print("\n📊 Monitoring processes...")
while True:
all_processes = sandbox.list_processes()
active = [
p for p in all_processes
if p.get('process_id') in process_ids.values()
and p.get('status') in ['queued', 'running']
]
if not active:
break
print(f"\nActive: {len(active)}/{len(tasks)}")
for proc in active:
name = next(k for k, v in process_ids.items() if v == proc.get('process_id'))
print(f" {name}: {proc['status']}")
time.sleep(3)
# Show final results
print("\n📋 Final Status:")
all_processes = sandbox.list_processes()
for name, proc_id in process_ids.items():
proc = next((p for p in all_processes if p.get('process_id') == proc_id), None)
if proc:
status_icon = {
'completed': '✅',
'failed': '❌',
'killed': '🛑'
}.get(proc['status'], '⏳')
print(f"{status_icon} {name}: {proc['status']}")
if proc['status'] == 'completed' and proc.get('stdout'):
print(f" Output: {proc['stdout'].strip()[:50]}...")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start multiple background tasks
const tasks = {
'data-processing': 'python process_data.py',
'ml-training': 'python train_model.py',
'report-generation': 'python generate_report.py'
};
const processIds = {};
console.log('🚀 Starting background tasks...\n');
for (const [name, command] of Object.entries(tasks)) {
const result = await sandbox.commands.runBackground(command, {
timeout: 600,
env: { TASK_NAME: name }
});
processIds[name] = result.processId;
console.log(`✅ Started: ${name} (ID: ${result.processId})`);
}
// Monitor all processes
console.log('\n📊 Monitoring processes...');
while (true) {
const allProcesses = await sandbox.listProcesses();
const active = allProcesses.filter(
p => Object.values(processIds).includes(p.processId) &&
['queued', 'running'].includes(p.status)
);
if (active.length === 0) {
break;
}
console.log(`\nActive: ${active.length}/${Object.keys(tasks).length}`);
for (const proc of active) {
const name = Object.keys(processIds).find(k => processIds[k] === proc.processId);
console.log(` ${name}: ${proc.status}`);
}
await new Promise(resolve => setTimeout(resolve, 3000));
}
// Show final results
console.log('\n📋 Final Status:');
const finalProcesses = await sandbox.listProcesses();
for (const [name, procId] of Object.entries(processIds)) {
const proc = finalProcesses.find(p => p.processId === procId);
if (proc) {
const statusIcon = {
'completed': '✅',
'failed': '❌',
'killed': '🛑'
}[proc.status] || '⏳';
console.log(`${statusIcon} ${name}: ${proc.status}`);
if (proc.status === 'completed' && proc.stdout) {
console.log(` Output: ${proc.stdout.trim().substring(0, 50)}...`);
}
}
}
await sandbox.kill();
```
## Best Practices
Extract process IDs from the result to track and manage background commands.
Set timeouts based on expected execution time. Default is 30 seconds, but increase for longer tasks.
Check process status periodically to track progress and detect failures early.
Use `list_processes()` and `kill_process()` to monitor and control background commands.
Check for failed status and access stderr for error details when commands fail.
## Related
* **[Running Commands](/core-concepts/commands/running)** - Execute commands synchronously
* **[Process Monitoring](/core-concepts/observability/processes)** - Monitor background processes
* **SDK**: [sandbox.commands.run\_background()](/sdk/python/commands#run_background) - Python SDK method
* **API**: [POST /commands/background](/api/vm-agent/run-command-background) - VM Agent API endpoint
## Next Steps
* Learn about [Running Commands](/core-concepts/commands/running) for synchronous execution
* Explore [Process Management](/core-concepts/code-execution/process-management) to monitor background processes
* Review [Code Execution](/core-concepts/code-execution/background) for background code execution
## Related
* [CLI Commands](/cli/commands/cmd) - Shell commands from CLI
# Commands
Source: https://docs.hopx.ai/core-concepts/commands/index
Complete guide to running shell commands in HopX sandboxes - synchronous and background command execution. Learn how to execute shell commands, run system administration tasks, install packages, and automate workflows using Python and JavaScript SDKs or REST API. Includes examples for synchronous and background command execution.
Run shell commands in HopX sandboxes for system administration, package installation, and automation. This hub covers all command execution methods.
## Related
* [CLI Commands](/cli/commands/cmd) - Shell commands from CLI
## What You'll Learn
* How to run shell commands synchronously
* How to run commands in the background
* How to handle command output and errors
* How to use commands for system administration
* How to integrate commands with code execution
## Command Execution Overview
| Execution Mode | SDK Method | API Endpoint |
| ------------------------------------------------------------- | ----------------------------------- | --------------------------- |
| **[Running Commands](/core-concepts/commands/running)** | `sandbox.commands.run()` | `POST /commands/run` |
| **[Background Commands](/core-concepts/commands/background)** | `sandbox.commands.run_background()` | `POST /commands/background` |
## Core Concepts
### Running Commands
Execute shell commands synchronously and wait for results.
* **[Running Commands](/core-concepts/commands/running)** - Run shell commands
* **SDK**: [Python: sandbox.commands.run()](/sdk/python/commands#run) | [JavaScript: sandbox.commands.run()](/sdk/javascript/commands#run)
* **API**: [POST /commands/run](/api/vm-agent/run-command)
### Background Commands
Run long-running commands in the background without blocking.
* **[Background Commands](/core-concepts/commands/background)** - Run commands in background
* **SDK**: [Python: sandbox.commands.run\_background()](/sdk/python/commands#run_background) | [JavaScript: sandbox.commands.runBackground()](/sdk/javascript/commands#runbackground)
* **API**: [POST /commands/background](/api/vm-agent/run-command-background)
## SDK Reference
### Python SDK
Complete reference for Python command execution.
* **[Commands Module](/sdk/python/commands)** - Complete command API
* `commands.run()` - Run commands synchronously
* `commands.run_background()` - Run commands in background
### JavaScript SDK
Complete reference for JavaScript/TypeScript command execution.
* **[Commands Module](/sdk/javascript/commands)** - Complete command API
* `commands.run()` - Run commands synchronously
* `commands.runBackground()` - Run commands in background
## API Reference
### VM Agent API
REST API endpoints for command execution.
* **[VM Agent API Overview](/api/vm-agent/overview)** - API overview
* **[Run Command](/api/vm-agent/run-command)** - `POST /commands/run` - Run commands synchronously
* **[Run Command Background](/api/vm-agent/run-command-background)** - `POST /commands/background` - Run commands in background
## Quick Start
If you're new to command execution, start here:
1. **[Running Commands](/core-concepts/commands/running)** - Run your first command
2. **[Background Commands](/core-concepts/commands/background)** - Run long-running commands
## Related Topics
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Execute code alongside commands
* **[File Operations](/core-concepts/filesystem/reading)** - Work with files via commands
* **[Environment Variables](/core-concepts/environment/getting)** - Use variables in commands
* **[Process Management](/core-concepts/code-execution/process-management)** - Manage command processes
## Next Steps
* Learn about [Running Commands](/core-concepts/commands/running) for system administration
* Explore [Background Commands](/core-concepts/commands/background) for long-running tasks
* Review [Code Execution](/core-concepts/code-execution/synchronous) to combine with commands
* Check out [Process Management](/core-concepts/code-execution/process-management) for advanced workflows
# Running
Source: https://docs.hopx.ai/core-concepts/commands/running
Execute shell commands synchronously in HopX sandboxes. Run shell commands for system administration, package installation, file operations, and automation tasks. Learn how to execute commands, capture output, handle errors, and process command results using Python and JavaScript SDKs or REST API. Includes examples for common use cases.
Run shell commands synchronously in your sandbox. Commands execute and return results immediately, making them perfect for quick operations, package installation, and system tasks.
## Overview
Synchronous command execution is ideal for:
* Quick shell commands and system operations
* Package installation (pip, npm, apt, etc.)
* File system operations
* Environment setup and configuration
* Commands that complete in seconds or minutes
Commands run in `/bin/sh` by default. For commands that complete quickly, synchronous execution is simpler than background execution.
## Basic Command Execution
Run a simple shell command:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Run a simple command
result = sandbox.commands.run('ls -la /workspace')
print(result.stdout)
print(f"Exit code: {result.exit_code}")
sandbox.kill()
```
**Expected Output:**
```
total 8
drwxr-xr-x 2 root root 4096 Jan 27 10:30 .
drwxr-xr-x 3 root root 4096 Jan 27 10:30 ..
Exit code: 0
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Run a simple command
const result = await sandbox.commands.run('ls -la /workspace');
console.log(result.stdout);
console.log(`Exit code: ${result.exitCode}`);
await sandbox.kill();
```
**Expected Output:**
```
total 8
drwxr-xr-x 2 root root 4096 Jan 27 10:30 .
drwxr-xr-x 3 root root 4096 Jan 27 10:30 ..
Exit code: 0
```
## Command Result
The `CommandResult` object contains:
* **`stdout`** - Standard output from command
* **`stderr`** - Standard error output (if any)
* **`exit_code`** - Exit code (0 = success, non-zero = error)
* **`success`** - Boolean indicating if command succeeded
* **`execution_time`** - Time taken in seconds
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
result = sandbox.commands.run('echo "Hello, World!"')
# Access all result fields
print(f"Output: {result.stdout}")
print(f"Errors: {result.stderr}")
print(f"Success: {result.success}")
print(f"Exit code: {result.exit_code}")
print(f"Execution time: {result.execution_time}s")
sandbox.kill()
```
**Expected Output:**
```
Output: Hello, World!
Errors:
Success: True
Exit code: 0
Execution time: 0.15s
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const result = await sandbox.commands.run('echo "Hello, World!"');
// Access all result fields
console.log(`Output: ${result.stdout}`);
console.log(`Errors: ${result.stderr}`);
console.log(`Success: ${result.success}`);
console.log(`Exit code: ${result.exitCode}`);
console.log(`Execution time: ${result.executionTime}s`);
await sandbox.kill();
```
**Expected Output:**
```
Output: Hello, World!
Errors:
Success: true
Exit code: 0
Execution time: 0.15
```
## Package Installation
Install packages using package managers:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Install Python packages
result = sandbox.commands.run('pip install requests pandas numpy', timeout=300)
if result.success:
print("Packages installed successfully")
print(result.stdout)
else:
print(f"Installation failed: {result.stderr}")
# Install Node.js packages
result = sandbox.commands.run('npm install express lodash', timeout=300)
print(f"npm install exit code: {result.exit_code}")
sandbox.kill()
```
**Expected Output:**
```
Packages installed successfully
Successfully installed requests-2.31.0 pandas-2.1.0 numpy-1.24.3
npm install exit code: 0
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Install Python packages
const result = await sandbox.commands.run('pip install requests pandas numpy', {
timeout: 300
});
if (result.success) {
console.log('Packages installed successfully');
console.log(result.stdout);
} else {
console.error(`Installation failed: ${result.stderr}`);
}
// Install Node.js packages
const npmResult = await sandbox.commands.run('npm install express lodash', {
timeout: 300
});
console.log(`npm install exit code: ${npmResult.exitCode}`);
await sandbox.kill();
```
**Expected Output:**
```
Packages installed successfully
Successfully installed requests-2.31.0 pandas-2.1.0 numpy-1.24.3
npm install exit code: 0
```
## Environment Variables
Pass environment variables to commands:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Run command with environment variables
result = sandbox.commands.run(
'echo $API_KEY',
env={"API_KEY": "sk-123", "DEBUG": "true"}
)
print(result.stdout) # "sk-123"
# Use environment variables in commands
result = sandbox.commands.run(
'python -c "import os; print(os.getenv(\'API_KEY\'))"',
env={"API_KEY": "sk-456"}
)
print(result.stdout) # "sk-456"
sandbox.kill()
```
**Expected Output:**
```
sk-123
sk-456
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Run command with environment variables
const result = await sandbox.commands.run('echo $API_KEY', {
env: { API_KEY: 'sk-123', DEBUG: 'true' }
});
console.log(result.stdout); // "sk-123"
// Use environment variables in commands
const pythonResult = await sandbox.commands.run(
'python -c "import os; print(os.getenv(\'API_KEY\'))"',
{ env: { API_KEY: 'sk-456' } }
);
console.log(pythonResult.stdout); // "sk-456"
await sandbox.kill();
```
**Expected Output:**
```
sk-123
sk-456
```
Environment variables passed to `commands.run()` have priority over global environment variables set via `sandbox.env.set()`. Priority: Request env > Global env > Agent env.
## Working Directory
Specify a custom working directory:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Create directory
sandbox.files.mkdir('/workspace/myproject')
# Run command in specific directory
result = sandbox.commands.run(
'pwd',
working_dir='/workspace/myproject'
)
print(result.stdout) # "/workspace/myproject"
# Run multiple commands in same directory
result = sandbox.commands.run(
'touch file.txt && ls -la',
working_dir='/workspace/myproject'
)
print(result.stdout)
sandbox.kill()
```
**Expected Output:**
```
/workspace/myproject
total 8
drwxr-xr-x 2 root root 4096 Jan 27 10:30 .
drwxr-xr-x 3 root root 4096 Jan 27 10:30 ..
-rw-r--r-- 1 root root 0 Jan 27 10:30 file.txt
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Create directory
await sandbox.files.mkdir('/workspace/myproject');
// Run command in specific directory
const result = await sandbox.commands.run('pwd', {
workingDir: '/workspace/myproject'
});
console.log(result.stdout); // "/workspace/myproject"
// Run multiple commands in same directory
const multiResult = await sandbox.commands.run('touch file.txt && ls -la', {
workingDir: '/workspace/myproject'
});
console.log(multiResult.stdout);
await sandbox.kill();
```
**Expected Output:**
```
/workspace/myproject
total 8
drwxr-xr-x 2 root root 4096 Jan 27 10:30 .
drwxr-xr-x 3 root root 4096 Jan 27 10:30 ..
-rw-r--r-- 1 root root 0 Jan 27 10:30 file.txt
```
## Timeout Configuration
Set timeout for long-running commands:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Run command with custom timeout (5 minutes)
result = sandbox.commands.run(
'npm install',
timeout=300
)
print(f"Installation completed: {result.success}")
# For very long operations, use background execution instead
sandbox.kill()
```
**Expected Output:**
```
Installation completed: True
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Run command with custom timeout (5 minutes)
const result = await sandbox.commands.run('npm install', {
timeout: 300
});
console.log(`Installation completed: ${result.success}`);
// For very long operations, use background execution instead
await sandbox.kill();
```
**Expected Output:**
```
Installation completed: true
```
Default timeout is 30 seconds. Maximum timeout is typically 300 seconds (5 minutes) for synchronous execution. For longer-running commands, use [Background Commands](/core-concepts/commands/background) instead.
## Error Handling
Handle command execution errors:
```python theme={null}
from hopx_ai import Sandbox
from hopx_ai.errors import CommandExecutionError, TimeoutError
sandbox = Sandbox.create(template="code-interpreter")
try:
result = sandbox.commands.run('nonexistent-command')
if not result.success:
print(f"Command failed with exit code: {result.exit_code}")
print(f"Error output: {result.stderr}")
else:
print(f"Output: {result.stdout}")
except TimeoutError:
print("Command timed out")
except CommandExecutionError as e:
print(f"Command execution error: {e}")
sandbox.kill()
```
**Expected Output:**
```
Command failed with exit code: 127
Error output: /bin/sh: nonexistent-command: command not found
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import { CommandExecutionError, TimeoutError } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
try {
const result = await sandbox.commands.run('nonexistent-command');
if (!result.success) {
console.error(`Command failed with exit code: ${result.exitCode}`);
console.error(`Error output: ${result.stderr}`);
} else {
console.log(`Output: ${result.stdout}`);
}
} catch (error) {
if (error instanceof TimeoutError) {
console.error('Command timed out');
} else if (error instanceof CommandExecutionError) {
console.error(`Command execution error: ${error.message}`);
}
}
await sandbox.kill();
```
**Expected Output:**
```
Command failed with exit code: 127
Error output: /bin/sh: nonexistent-command: command not found
```
## Chaining Commands
Chain multiple commands together:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Chain commands with &&
result = sandbox.commands.run('cd /workspace && mkdir test && ls -la')
print(result.stdout)
# Chain with pipes
result = sandbox.commands.run('ls -la /workspace | grep .txt')
print(result.stdout)
# Multiple commands with semicolon
result = sandbox.commands.run('echo "Step 1"; echo "Step 2"; echo "Step 3"')
print(result.stdout)
sandbox.kill()
```
**Expected Output:**
```
total 12
drwxr-xr-x 3 root root 4096 Jan 27 10:30 .
drwxr-xr-x 3 root root 4096 Jan 27 10:30 ..
drwxr-xr-x 2 root root 4096 Jan 27 10:30 test
Step 1
Step 2
Step 3
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Chain commands with &&
const result = await sandbox.commands.run('cd /workspace && mkdir test && ls -la');
console.log(result.stdout);
// Chain with pipes
const pipeResult = await sandbox.commands.run('ls -la /workspace | grep .txt');
console.log(pipeResult.stdout);
// Multiple commands with semicolon
const multiResult = await sandbox.commands.run('echo "Step 1"; echo "Step 2"; echo "Step 3"');
console.log(multiResult.stdout);
await sandbox.kill();
```
**Expected Output:**
```
total 12
drwxr-xr-x 3 root root 4096 Jan 27 10:30 .
drwxr-xr-x 3 root root 4096 Jan 27 10:30 ..
drwxr-xr-x 2 root root 4096 Jan 27 10:30 test
Step 1
Step 2
Step 3
```
## Complete Example
Here's a complete example showing command execution workflow:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Setup project
print("📦 Setting up project...")
result = sandbox.commands.run('mkdir -p /workspace/myproject', timeout=10)
print(f" Create directory: {'✅' if result.success else '❌'}")
# Install dependencies
print("\n📥 Installing dependencies...")
result = sandbox.commands.run(
'pip install requests pandas',
timeout=300,
working_dir='/workspace/myproject'
)
if result.success:
print(" ✅ Dependencies installed")
print(f" Output: {result.stdout[:100]}...")
else:
print(f" ❌ Installation failed: {result.stderr}")
# Create project files
print("\n📝 Creating project files...")
result = sandbox.commands.run(
'echo "import requests" > main.py && echo "import pandas" >> main.py',
working_dir='/workspace/myproject'
)
print(f" Create files: {'✅' if result.success else '❌'}")
# Verify setup
print("\n🔍 Verifying setup...")
result = sandbox.commands.run(
'ls -la && python -c "import requests, pandas; print(\'All imports OK\')"',
working_dir='/workspace/myproject'
)
if result.success:
print(" ✅ Setup complete")
print(f" Output:\n{result.stdout}")
else:
print(f" ❌ Verification failed: {result.stderr}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Setup project
console.log('📦 Setting up project...');
let result = await sandbox.commands.run('mkdir -p /workspace/myproject', { timeout: 10 });
console.log(` Create directory: ${result.success ? '✅' : '❌'}`);
// Install dependencies
console.log('\n📥 Installing dependencies...');
result = await sandbox.commands.run('pip install requests pandas', {
timeout: 300,
workingDir: '/workspace/myproject'
});
if (result.success) {
console.log(' ✅ Dependencies installed');
console.log(` Output: ${result.stdout.substring(0, 100)}...`);
} else {
console.error(` ❌ Installation failed: ${result.stderr}`);
}
// Create project files
console.log('\n📝 Creating project files...');
result = await sandbox.commands.run(
'echo "import requests" > main.py && echo "import pandas" >> main.py',
{ workingDir: '/workspace/myproject' }
);
console.log(` Create files: ${result.success ? '✅' : '❌'}`);
// Verify setup
console.log('\n🔍 Verifying setup...');
result = await sandbox.commands.run(
'ls -la && python -c "import requests, pandas; print(\'All imports OK\')"',
{ workingDir: '/workspace/myproject' }
);
if (result.success) {
console.log(' ✅ Setup complete');
console.log(` Output:\n${result.stdout}`);
} else {
console.error(` ❌ Verification failed: ${result.stderr}`);
}
await sandbox.kill();
```
## Best Practices
Set timeouts based on expected execution time. Default 30 seconds is good for quick commands, but increase for package installations or long operations.
Always check `result.success` and handle `stderr` appropriately. Use try/catch for exception handling.
Pass environment variables via `env` parameter rather than hardcoding values in commands.
Use `working_dir` to run commands in the correct directory context.
For commands that run longer than 5 minutes, use [Background Commands](/core-concepts/commands/background) instead.
## Related
* **[Background Commands](/core-concepts/commands/background)** - Run commands in background
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Execute code directly
* **SDK**: [sandbox.commands.run()](/sdk/python/commands#run) - Python SDK method
* **API**: [POST /commands/run](/api/vm-agent/run-command) - VM Agent API endpoint
## Next Steps
* Learn about [Background Commands](/core-concepts/commands/background) for non-blocking execution
* Explore [Code Execution](/core-concepts/code-execution/synchronous) for running code instead of shell commands
* Review [Filesystem Operations](/core-concepts/filesystem/reading) for file management
## Related
* [CLI Commands](/cli/commands/cmd) - Shell commands from CLI
# Clipboard Operations
Source: https://docs.hopx.ai/core-concepts/desktop/clipboard
Read and write clipboard content in sandbox desktop environments in HopX. Access and manipulate clipboard contents for data transfer, copy-paste operations, and desktop automation workflows. Learn how to read and write clipboard data using Python and JavaScript SDKs or REST API. Includes examples for clipboard automation.
Read and write clipboard content for desktop automation. Clipboard operations enable copying and pasting data between applications.
## Overview
Clipboard operations enable:
* Reading clipboard content
* Setting clipboard content
* Accessing clipboard history
* Copying data between applications
Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled.
## Getting Clipboard Content
Read the current clipboard content:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop")
# Get clipboard content
text = sandbox.desktop.get_clipboard()
print(f"Clipboard: {text}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'desktop' });
// Get clipboard content
const text = await sandbox.desktop.getClipboard();
console.log(`Clipboard: ${text}`);
```
## Setting Clipboard Content
Set clipboard content:
```python theme={null}
# Set clipboard content
sandbox.desktop.set_clipboard("Hello from clipboard!")
# Verify
text = sandbox.desktop.get_clipboard()
print(text) # "Hello from clipboard!"
```
```javascript theme={null}
// Set clipboard content
await sandbox.desktop.setClipboard('Hello from clipboard!');
// Verify
const text = await sandbox.desktop.getClipboard();
console.log(text); // "Hello from clipboard!"
```
## Clipboard History
Get clipboard history (if supported):
```python theme={null}
# Get clipboard history
history = sandbox.desktop.get_clipboard_history()
for item in history:
print(f"History item: {item}")
```
```javascript theme={null}
// Get clipboard history
const history = await sandbox.desktop.getClipboardHistory();
history.forEach(item => {
console.log(`History item: ${item}`);
});
```
## Copy-Paste Workflow
Complete copy-paste automation:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop")
try:
# Select text (using mouse/keyboard)
sandbox.desktop.click(100, 100)
sandbox.desktop.drag(100, 100, 300, 100)
# Copy (Ctrl+C)
sandbox.desktop.combination(['ctrl'], 'c')
# Get copied text
copied_text = sandbox.desktop.get_clipboard()
print(f"Copied: {copied_text}")
# Click elsewhere
sandbox.desktop.click(500, 300)
# Paste (Ctrl+V)
sandbox.desktop.combination(['ctrl'], 'v')
finally:
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'desktop' });
try {
// Select text (using mouse/keyboard)
await sandbox.desktop.mouseClick(100, 100);
await sandbox.desktop.mouseDrag(100, 100, 300, 100);
// Copy (Ctrl+C)
await sandbox.desktop.keyboardCombination(['ctrl', 'c']);
// Get copied text
const copiedText = await sandbox.desktop.getClipboard();
console.log(`Copied: ${copiedText}`);
// Click elsewhere
await sandbox.desktop.mouseClick(500, 300);
// Paste (Ctrl+V)
await sandbox.desktop.keyboardCombination(['ctrl', 'v']);
} finally {
await sandbox.kill();
}
```
## Programmatic Copy-Paste
Set clipboard programmatically and paste:
```python theme={null}
# Set clipboard programmatically
sandbox.desktop.set_clipboard("Programmatic clipboard content")
# Click in target application
sandbox.desktop.click(400, 300)
# Paste
sandbox.desktop.combination(['ctrl'], 'v')
```
```javascript theme={null}
// Set clipboard programmatically
await sandbox.desktop.setClipboard('Programmatic clipboard content');
// Click in target application
await sandbox.desktop.mouseClick(400, 300);
// Paste
await sandbox.desktop.keyboardCombination(['ctrl', 'v']);
```
## Related
* [Keyboard Control](/core-concepts/desktop/keyboard-control) - Keyboard shortcuts for copy/paste
* [CLI Reference](/cli/introduction) - Command-line interface for HopX
* [Mouse Control](/core-concepts/desktop/mouse-control) - Mouse operations for selection
* **SDK**: [sandbox.desktop.get\_clipboard()](/sdk/python/desktop#get_clipboard) - Python SDK method
## Next Steps
* Learn about [Keyboard Control](/core-concepts/desktop/keyboard-control) for copy/paste shortcuts
* Explore [Mouse Control](/core-concepts/desktop/mouse-control) for selection operations
* Review [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access
# Display Management
Source: https://docs.hopx.ai/core-concepts/desktop/display-management
Configure sandbox display resolution and settings for desktop environments in HopX sandboxes. Set display resolution, configure display settings, and manage multiple displays for desktop automation and GUI testing. Learn how to configure displays using Python and JavaScript SDKs or REST API. Includes examples for display configuration.
Configure display resolution and settings for the desktop environment.
## Overview
Display management enables:
* Getting current display resolution
* Setting display resolution
* Listing available resolutions
* Configuring display settings
Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled.
## Getting Display Information
Get current display resolution and settings:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop")
# Get display info
display = sandbox.desktop.get_display()
print(f"Resolution: {display.width}x{display.height}")
print(f"Color depth: {display.depth} bits")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'desktop' });
// Get display info
const display = await sandbox.desktop.getDisplayInfo();
console.log(`Resolution: ${display.width}x${display.height}`);
console.log(`Color depth: ${display.depth} bits`);
```
## Setting Resolution
Set display resolution:
```python theme={null}
# Set resolution to 1920x1080
display = sandbox.desktop.set_resolution(1920, 1080)
print(f"New resolution: {display.width}x{display.height}")
# Set to 1280x720
display = sandbox.desktop.set_resolution(1280, 720)
print(f"Resolution: {display.width}x{display.height}")
```
```javascript theme={null}
// Set resolution to 1920x1080
await sandbox.desktop.setResolution(1920, 1080);
// Verify
const display = await sandbox.desktop.getDisplayInfo();
console.log(`Resolution: ${display.width}x${display.height}`);
// Set to 1280x720
await sandbox.desktop.setResolution(1280, 720);
```
## Available Resolutions
List available display resolutions:
```python theme={null}
# Get available resolutions
resolutions = sandbox.desktop.get_available_resolutions()
print("Available resolutions:")
for width, height in resolutions:
print(f" {width}x{height}")
# Find highest resolution
if resolutions:
highest = max(resolutions, key=lambda r: r[0] * r[1])
print(f"Highest: {highest[0]}x{highest[1]}")
```
```javascript theme={null}
// Get available resolutions
const resolutions = await sandbox.desktop.getAvailableResolutions();
console.log('Available resolutions:');
resolutions.forEach(([width, height]) => {
console.log(` ${width}x${height}`);
});
// Find highest resolution
if (resolutions.length > 0) {
const highest = resolutions.reduce((a, b) =>
(a[0] * a[1] > b[0] * b[1]) ? a : b
);
console.log(`Highest: ${highest[0]}x${highest[1]}`);
}
```
## Common Resolutions
Common display resolutions:
* **1920x1080**: Full HD (1080p) - Recommended
* **1280x720**: HD (720p)
* **2560x1440**: 2K (1440p)
* **3840x2160**: 4K (2160p)
## Complete Example
Complete display management workflow:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop")
try:
# Get current display
current = sandbox.desktop.get_display()
print(f"Current: {current.width}x{current.height}")
# List available resolutions
resolutions = sandbox.desktop.get_available_resolutions()
print(f"Available: {len(resolutions)} resolutions")
# Set to Full HD
display = sandbox.desktop.set_resolution(1920, 1080)
print(f"Set to: {display.width}x{display.height}")
# Verify
verify = sandbox.desktop.get_display()
assert verify.width == 1920 and verify.height == 1080
print("✅ Resolution verified")
finally:
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'desktop' });
try {
// Get current display
const current = await sandbox.desktop.getDisplayInfo();
console.log(`Current: ${current.width}x${current.height}`);
// List available resolutions
const resolutions = await sandbox.desktop.getAvailableResolutions();
console.log(`Available: ${resolutions.length} resolutions`);
// Set to Full HD
await sandbox.desktop.setResolution(1920, 1080);
// Verify
const verify = await sandbox.desktop.getDisplayInfo();
if (verify.width === 1920 && verify.height === 1080) {
console.log('✅ Resolution verified');
}
} finally {
await sandbox.kill();
}
```
## Resolution Best Practices
Set display resolution before starting VNC server for optimal remote desktop experience.
* **Before VNC**: Set resolution before starting VNC for best results
* **Standard sizes**: Use common resolutions (1920x1080, 1280x720) for compatibility
* **Testing**: Test different resolutions for your use case
## Related
* [VNC Server](/core-concepts/desktop/vnc-server) - Remote desktop access
* [CLI Reference](/cli/introduction) - Command-line interface for HopX
* [Window Management](/core-concepts/desktop/window-management) - Manage windows
* **SDK**: [sandbox.desktop.get\_display()](/sdk/python/desktop#get_display) - Python SDK method
## Next Steps
* Learn about [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access
* Explore [Window Management](/core-concepts/desktop/window-management) to manage windows
* Review [Screenshots](/core-concepts/desktop/screenshots) for visual verification
# Desktop Automation
Source: https://docs.hopx.ai/core-concepts/desktop/index
Complete guide to desktop automation in HopX sandboxes - VNC, screenshots, mouse, keyboard, and window management. Automate desktop interactions with VNC servers, capture screenshots and screen recordings, control mouse and keyboard, manage windows and displays, and use clipboard operations. Includes Python and JavaScript SDK examples.
Automate desktop interactions in HopX sandboxes with VNC, screenshots, mouse and keyboard control, and window management. This hub covers all desktop automation features.
## Related
* [CLI Reference](/cli/introduction) - Command-line interface
## What You'll Learn
* How to set up and use VNC servers
* How to capture screenshots and screen recordings
* How to control mouse and keyboard
* How to manage windows and displays
* How to use clipboard and advanced X11 features
## Desktop Automation Overview
| Feature | SDK Method | API Endpoint |
| ----------------------------------------------------------------- | ------------------------------ | -------------------- |
| **[VNC Server](/core-concepts/desktop/vnc-server)** | `sandbox.desktop.vnc` | VNC endpoints |
| **[Screenshots](/core-concepts/desktop/screenshots)** | `sandbox.desktop.screenshot()` | Screenshot endpoints |
| **[Mouse Control](/core-concepts/desktop/mouse-control)** | `sandbox.desktop.mouse` | Mouse endpoints |
| **[Keyboard Control](/core-concepts/desktop/keyboard-control)** | `sandbox.desktop.keyboard` | Keyboard endpoints |
| **[Window Management](/core-concepts/desktop/window-management)** | `sandbox.desktop.windows` | Window endpoints |
| **[Advanced X11](/core-concepts/desktop/x11-advanced)** | Advanced X11 | X11 endpoints |
## Core Concepts
### VNC Server
Set up and connect to VNC servers for remote desktop access.
* **[VNC Server](/core-concepts/desktop/vnc-server)** - Set up VNC servers
* **SDK**: [Python: sandbox.desktop.vnc](/sdk/python/desktop#vnc) | [JavaScript: sandbox.desktop.vnc](/sdk/javascript/desktop#vnc)
* **API**: VNC server endpoints
### Screenshots
Capture screenshots and screen recordings from sandboxes.
* **[Screenshots](/core-concepts/desktop/screenshots)** - Capture screenshots
* **[Screen Recording](/core-concepts/desktop/screen-recording)** - Record screen activity
* **SDK**: [Python: sandbox.desktop.screenshot()](/sdk/python/desktop#screenshot) | [JavaScript: sandbox.desktop.screenshot()](/sdk/javascript/desktop#screenshot)
* **API**: Screenshot endpoints
### Mouse Control
Control mouse movements, clicks, and gestures.
* **[Mouse Control](/core-concepts/desktop/mouse-control)** - Control mouse interactions
* **SDK**: [Python: sandbox.desktop.mouse](/sdk/python/desktop#mouse) | [JavaScript: sandbox.desktop.mouse](/sdk/javascript/desktop#mouse)
* **API**: Mouse control endpoints
### Keyboard Control
Send keyboard input and key combinations.
* **[Keyboard Control](/core-concepts/desktop/keyboard-control)** - Control keyboard input
* **SDK**: [Python: sandbox.desktop.keyboard](/sdk/python/desktop#keyboard) | [JavaScript: sandbox.desktop.keyboard](/sdk/javascript/desktop#keyboard)
* **API**: Keyboard control endpoints
### Window Management
Manage windows, displays, and desktop layout.
* **[Window Management](/core-concepts/desktop/window-management)** - Manage windows
* **[Display Management](/core-concepts/desktop/display-management)** - Manage displays
* **SDK**: [Python: sandbox.desktop.windows](/sdk/python/desktop#windows) | [JavaScript: sandbox.desktop.windows](/sdk/javascript/desktop#windows)
* **API**: Window management endpoints
### Advanced X11
Advanced X11 features for desktop automation.
* **[Advanced X11](/core-concepts/desktop/x11-advanced)** - Advanced X11 features
* **SDK**: [Python: sandbox.desktop.x11](/sdk/python/desktop#x11) | [JavaScript: sandbox.desktop.x11](/sdk/javascript/desktop#x11)
* **API**: X11 endpoints
### Clipboard
Access and manipulate clipboard contents.
* **[Clipboard](/core-concepts/desktop/clipboard)** - Clipboard operations
* **SDK**: [Python: sandbox.desktop.clipboard](/sdk/python/desktop#clipboard) | [JavaScript: sandbox.desktop.clipboard](/sdk/javascript/desktop#clipboard)
* **API**: Clipboard endpoints
## SDK Reference
### Python SDK
Complete reference for Python desktop automation.
* **[Desktop Module](/sdk/python/desktop)** - Complete desktop automation API
* `desktop.vnc` - VNC server
* `desktop.screenshot()` - Screenshots
* `desktop.mouse` - Mouse control
* `desktop.keyboard` - Keyboard control
* `desktop.windows` - Window management
* `desktop.clipboard` - Clipboard
* `desktop.x11` - Advanced X11
### JavaScript SDK
Complete reference for JavaScript/TypeScript desktop automation.
* **[Desktop Module](/sdk/javascript/desktop)** - Complete desktop automation API
* `desktop.vnc` - VNC server
* `desktop.screenshot()` - Screenshots
* `desktop.mouse` - Mouse control
* `desktop.keyboard` - Keyboard control
* `desktop.windows` - Window management
* `desktop.clipboard` - Clipboard
* `desktop.x11` - Advanced X11
## API Reference
### VM Agent API
REST API endpoints for desktop automation.
* **[VM Agent API Overview](/api/vm-agent/overview)** - API overview
* Desktop automation endpoints (VNC, screenshots, mouse, keyboard, windows)
## Quick Start
If you're new to desktop automation, start here:
1. **[VNC Server](/core-concepts/desktop/vnc-server)** - Set up VNC access
2. **[Screenshots](/core-concepts/desktop/screenshots)** - Capture your first screenshot
3. **[Mouse Control](/core-concepts/desktop/mouse-control)** - Control mouse interactions
## Related Topics
* **[Sandboxes](/core-concepts/sandboxes/creating)** - Create sandboxes for desktop automation
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Execute code with desktop access
* **[Terminal](/core-concepts/terminal/websocket)** - Terminal access alongside desktop
* **[Observability](/core-concepts/observability/metrics)** - Monitor desktop performance
## Next Steps
* Learn about [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access
* Explore [Screenshots](/core-concepts/desktop/screenshots) for visual capture
* Review [Mouse Control](/core-concepts/desktop/mouse-control) and [Keyboard Control](/core-concepts/desktop/keyboard-control) for automation
* Check out [Advanced X11](/core-concepts/desktop/x11-advanced) for advanced features
# Keyboard Control
Source: https://docs.hopx.ai/core-concepts/desktop/keyboard-control
Control keyboard input for sandbox desktop automation in HopX sandboxes. Send keyboard input, simulate key presses, type text, and handle keyboard shortcuts for desktop automation. Learn how to control keyboard interactions using Python and JavaScript SDKs or REST API. Includes examples for common keyboard operations.
Control keyboard input to type text, press keys, and execute key combinations for desktop automation.
## Overview
Keyboard control enables:
* Typing text into applications
* Pressing individual keys
* Executing key combinations (Ctrl+C, Alt+Tab, etc.)
* Simulating keyboard shortcuts
Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled.
## Typing Text
Type text as if typed on a keyboard:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop")
# Type text
sandbox.desktop.type("Hello, World!")
# Type with custom delay between keystrokes
sandbox.desktop.type("Slow typing", delay_ms=50)
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'desktop' });
// Type text
await sandbox.desktop.keyboardType('Hello, World!');
```
## Pressing Keys
Press individual keys:
```python theme={null}
# Press Enter
sandbox.desktop.press("Return")
# Press Escape
sandbox.desktop.press("Escape")
# Press Tab
sandbox.desktop.press("Tab")
# Press function keys
sandbox.desktop.press("F1")
sandbox.desktop.press("F5")
```
```javascript theme={null}
// Press Enter
await sandbox.desktop.keyboardPress('Return');
// Press Escape
await sandbox.desktop.keyboardPress('Escape');
// Press Tab
await sandbox.desktop.keyboardPress('Tab');
```
## Key Combinations
Execute key combinations (modifier keys + main key):
```python theme={null}
# Ctrl+C (copy)
sandbox.desktop.combination(['ctrl'], 'c')
# Ctrl+V (paste)
sandbox.desktop.combination(['ctrl'], 'v')
# Ctrl+Shift+T (new tab)
sandbox.desktop.combination(['ctrl', 'shift'], 't')
# Alt+F4 (close window)
sandbox.desktop.combination(['alt'], 'F4')
# Ctrl+Alt+Delete
sandbox.desktop.combination(['ctrl', 'alt'], 'Delete')
```
```javascript theme={null}
// Ctrl+C (copy)
await sandbox.desktop.keyboardCombination(['ctrl', 'c']);
// Ctrl+V (paste)
await sandbox.desktop.keyboardCombination(['ctrl', 'v']);
// Ctrl+Shift+T (new tab)
await sandbox.desktop.keyboardCombination(['ctrl', 'shift', 't']);
```
## Available Keys
Common key names:
* **Modifiers**: `'ctrl'`, `'shift'`, `'alt'`, `'meta'` (Command on macOS)
* **Function keys**: `'F1'` through `'F12'`
* **Special keys**: `'Return'` (Enter), `'Escape'`, `'Tab'`, `'Backspace'`, `'Delete'`
* **Arrow keys**: `'Up'`, `'Down'`, `'Left'`, `'Right'`
* **Letters and numbers**: `'a'`, `'b'`, `'1'`, `'2'`, etc.
## Typing Speed
Control typing speed with delay:
```python theme={null}
# Fast typing (default: 10ms delay)
sandbox.desktop.type("Fast text", delay_ms=10)
# Normal typing
sandbox.desktop.type("Normal text", delay_ms=50)
# Slow typing (for debugging)
sandbox.desktop.type("Slow text", delay_ms=100)
```
```javascript theme={null}
// Note: JavaScript SDK may have different delay parameter
await sandbox.desktop.keyboardType('Text to type');
```
## Complete Example
Automate a form filling workflow:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop")
try:
# Click on input field (assuming coordinates)
sandbox.desktop.click(400, 300)
# Type username
sandbox.desktop.type("myusername")
# Press Tab to move to next field
sandbox.desktop.press("Tab")
# Type password
sandbox.desktop.type("mypassword")
# Press Enter to submit
sandbox.desktop.press("Return")
finally:
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'desktop' });
try {
// Click on input field (assuming coordinates)
await sandbox.desktop.mouseClick(400, 300);
// Type username
await sandbox.desktop.keyboardType('myusername');
// Press Tab to move to next field
await sandbox.desktop.keyboardPress('Tab');
// Type password
await sandbox.desktop.keyboardType('mypassword');
// Press Enter to submit
await sandbox.desktop.keyboardPress('Return');
} finally {
await sandbox.kill();
}
```
## Common Shortcuts
Common keyboard shortcuts for automation:
* **Copy**: `Ctrl+C` (or `Cmd+C` on macOS)
* **Paste**: `Ctrl+V` (or `Cmd+V` on macOS)
* **Cut**: `Ctrl+X` (or `Cmd+X` on macOS)
* **Select All**: `Ctrl+A` (or `Cmd+A` on macOS)
* **Undo**: `Ctrl+Z` (or `Cmd+Z` on macOS)
* **Redo**: `Ctrl+Y` (or `Cmd+Shift+Z` on macOS)
* **Save**: `Ctrl+S` (or `Cmd+S` on macOS)
* **Close Tab**: `Ctrl+W` (or `Cmd+W` on macOS)
* **New Tab**: `Ctrl+T` (or `Cmd+T` on macOS)
## Related
* [Mouse Control](/core-concepts/desktop/mouse-control) - Control mouse input
* [CLI Reference](/cli/introduction) - Command-line interface for HopX
* [Clipboard](/core-concepts/desktop/clipboard) - Clipboard operations
* [X11 Advanced](/core-concepts/desktop/x11-advanced) - Advanced keyboard features
* **SDK**: [sandbox.desktop.type()](/sdk/python/desktop#type) - Python SDK method
## Next Steps
* Learn about [Mouse Control](/core-concepts/desktop/mouse-control) for clicking and dragging
* Explore [Clipboard](/core-concepts/desktop/clipboard) for copy/paste operations
* Review [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access
# Mouse Control
Source: https://docs.hopx.ai/core-concepts/desktop/mouse-control
Control mouse input for sandbox desktop automation in HopX sandboxes. Move mouse cursor, click buttons, perform drag operations, and simulate mouse gestures for desktop automation. Learn how to control mouse interactions using Python and JavaScript SDKs or REST API. Includes examples for common mouse operations.
Control mouse input to interact with GUI applications. Mouse control enables clicking, moving, dragging, and scrolling operations.
## Overview
Mouse control enables:
* Clicking buttons and UI elements
* Moving cursor to specific positions
* Dragging and dropping elements
* Scrolling windows and content
Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled.
## Clicking
Click at a specific position on the screen:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop")
# Single left click
sandbox.desktop.click(100, 100)
# Right click
sandbox.desktop.click(200, 200, button="right")
# Middle click
sandbox.desktop.click(300, 300, button="middle")
# Double click
sandbox.desktop.click(150, 150, clicks=2)
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'desktop' });
// Single left click
await sandbox.desktop.mouseClick(100, 100);
// Right click
await sandbox.desktop.mouseClick(200, 200, { button: 'right' });
// Middle click
await sandbox.desktop.mouseClick(300, 300, { button: 'middle' });
// Double click
await sandbox.desktop.mouseClick(150, 150, { clicks: 2 });
```
## Moving Cursor
Move the mouse cursor to a specific position:
```python theme={null}
# Move cursor to position
sandbox.desktop.move(500, 300)
```
```javascript theme={null}
// Move cursor to position
await sandbox.desktop.mouseMove(500, 300);
```
## Dragging
Drag from one position to another:
```python theme={null}
# Drag from (100, 100) to (200, 200)
sandbox.desktop.drag(100, 100, 200, 200)
# Drag with right button
sandbox.desktop.drag(100, 100, 200, 200, button="right")
```
```javascript theme={null}
// Drag from (100, 100) to (200, 200)
await sandbox.desktop.mouseDrag(100, 100, 200, 200);
```
## Scrolling
Scroll the mouse wheel:
```python theme={null}
# Scroll down 5 clicks
sandbox.desktop.scroll(5, "down")
# Scroll up 3 clicks
sandbox.desktop.scroll(3, "up")
# Scroll left
sandbox.desktop.scroll(2, "left")
# Scroll right
sandbox.desktop.scroll(2, "right")
```
```javascript theme={null}
// Scroll (JavaScript SDK may have different API)
// Note: Check SDK documentation for exact scroll method signature
await sandbox.desktop.mouseScroll(500, 300, 5); // x, y, deltaY
```
## Mouse Buttons
Available mouse buttons:
* `"left"` - Left mouse button (default)
* `"right"` - Right mouse button
* `"middle"` - Middle mouse button (scroll wheel)
## Complete Example
Automate a simple GUI interaction:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop")
try:
# Move to button
sandbox.desktop.move(400, 300)
# Click button
sandbox.desktop.click(400, 300)
# Wait a moment (you might use time.sleep in real scenarios)
# Drag a slider
sandbox.desktop.drag(100, 200, 300, 200)
# Scroll to see more content
sandbox.desktop.scroll(10, "down")
finally:
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'desktop' });
try {
// Move to button
await sandbox.desktop.mouseMove(400, 300);
// Click button
await sandbox.desktop.mouseClick(400, 300);
// Wait a moment (you might use setTimeout in real scenarios)
// Drag a slider
await sandbox.desktop.mouseDrag(100, 200, 300, 200);
// Scroll to see more content
await sandbox.desktop.mouseScroll(500, 300, 10);
} finally {
await sandbox.kill();
}
```
## Coordinate System
Mouse coordinates use screen pixels:
* **Origin (0, 0)**: Top-left corner of the screen
* **X-axis**: Increases from left to right
* **Y-axis**: Increases from top to bottom
Use screenshots to identify exact coordinates of UI elements before automating interactions.
## Related
* [Keyboard Control](/core-concepts/desktop/keyboard-control) - Control keyboard input
* [CLI Reference](/cli/introduction) - Command-line interface for HopX
* [Screenshots](/core-concepts/desktop/screenshots) - Capture screenshots to find coordinates
* [X11 Advanced](/core-concepts/desktop/x11-advanced) - Find elements by text
* **SDK**: [sandbox.desktop.click()](/sdk/python/desktop#click) - Python SDK method
## Next Steps
* Learn about [Keyboard Control](/core-concepts/desktop/keyboard-control) for text input
* Explore [Screenshots](/core-concepts/desktop/screenshots) to find element coordinates
* Review [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access
# Screen Recording
Source: https://docs.hopx.ai/core-concepts/desktop/screen-recording
Record sandbox screen activity as video for desktop automation in HopX sandboxes. Capture screen recordings of desktop interactions, GUI workflows, and visual demonstrations. Learn how to start and stop recordings, download video files, and use recordings for documentation or testing. Includes Python and JavaScript SDK examples.
Record screen activity as video files for documentation, testing, and debugging.
## Overview
Screen recording enables:
* Recording desktop activity as video
* Configurable frame rate and quality
* Downloading recorded videos
* Monitoring recording status
Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled.
## Starting Recording
Start a screen recording:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop")
# Start recording with default settings
recording = sandbox.desktop.start_recording()
# Start with custom settings
recording = sandbox.desktop.start_recording(
fps=30, # 30 frames per second
format="mp4", # MP4 format
quality="high" # High quality
)
print(f"Recording ID: {recording.recording_id}")
print(f"Status: {recording.status}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'desktop' });
// Start recording
await sandbox.desktop.startRecording();
// Note: JavaScript SDK may have different parameters
// Check SDK documentation for exact API
```
## Recording Options
Configure recording settings:
```python theme={null}
# Low quality, low FPS (smaller file)
recording = sandbox.desktop.start_recording(
fps=10,
format="mp4",
quality="low"
)
# Medium quality (balanced)
recording = sandbox.desktop.start_recording(
fps=15,
format="mp4",
quality="medium"
)
# High quality, high FPS (larger file)
recording = sandbox.desktop.start_recording(
fps=30,
format="mp4",
quality="high"
)
```
```javascript theme={null}
// Note: JavaScript SDK may have different parameters
await sandbox.desktop.startRecording('output.mp4');
```
## Stopping Recording
Stop a recording and get final information:
```python theme={null}
# Start recording
recording = sandbox.desktop.start_recording()
# ... perform actions ...
# Stop recording
final_recording = sandbox.desktop.stop_recording(recording.recording_id)
print(f"Duration: {final_recording.duration}s")
print(f"File size: {final_recording.file_size} bytes")
print(f"Format: {final_recording.format}")
```
```javascript theme={null}
// Start recording
await sandbox.desktop.startRecording();
// ... perform actions ...
// Stop recording
await sandbox.desktop.stopRecording();
// Get status
const status = await sandbox.desktop.getRecordingStatus();
console.log(`Duration: ${status.duration}s`);
console.log(`File size: ${status.fileSize} bytes`);
```
## Recording Status
Check recording status:
```python theme={null}
# Get recording status
status = sandbox.desktop.get_recording_status(recording.recording_id)
print(f"Status: {status.status}")
print(f"Duration: {status.duration}s")
print(f"File size: {status.file_size} bytes")
# Check if ready
if status.status == "stopped":
video = sandbox.desktop.download_recording(recording.recording_id)
```
```javascript theme={null}
// Get recording status
const status = await sandbox.desktop.getRecordingStatus();
console.log(`Status: ${status.status}`);
console.log(`Duration: ${status.duration}s`);
console.log(`File size: ${status.fileSize} bytes`);
```
## Downloading Recording
Download the recorded video:
```python theme={null}
# Download recording
video_bytes = sandbox.desktop.download_recording(recording.recording_id)
# Save to file
with open('recording.mp4', 'wb') as f:
f.write(video_bytes)
print(f"Video saved: {len(video_bytes)} bytes")
```
```javascript theme={null}
// Download recording
const video = await sandbox.desktop.downloadRecording(recordingId);
// Save to file
fs.writeFileSync('recording.mp4', video);
console.log(`Video saved: ${video.length} bytes`);
```
## Complete Example
Complete recording workflow:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="desktop")
try:
# Start recording
recording = sandbox.desktop.start_recording(
fps=30,
format="mp4",
quality="high"
)
print(f"Recording started: {recording.recording_id}")
# Perform actions to record
sandbox.desktop.click(400, 300)
time.sleep(1)
sandbox.desktop.type("Hello, World!")
time.sleep(2)
# Stop recording
final = sandbox.desktop.stop_recording(recording.recording_id)
print(f"Recording stopped: {final.duration}s")
# Wait for processing
time.sleep(2)
# Download video
video = sandbox.desktop.download_recording(recording.recording_id)
with open('demo.mp4', 'wb') as f:
f.write(video)
print(f"Video saved: {len(video)} bytes")
finally:
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import fs from 'fs';
const sandbox = await Sandbox.create({ template: 'desktop' });
try {
// Start recording
await sandbox.desktop.startRecording();
console.log('Recording started');
// Perform actions to record
await sandbox.desktop.mouseClick(400, 300);
await new Promise(resolve => setTimeout(resolve, 1000));
await sandbox.desktop.keyboardType('Hello, World!');
await new Promise(resolve => setTimeout(resolve, 2000));
// Stop recording
await sandbox.desktop.stopRecording();
console.log('Recording stopped');
// Wait for processing
await new Promise(resolve => setTimeout(resolve, 2000));
// Get status and download
const status = await sandbox.desktop.getRecordingStatus();
if (status.recordingId) {
const video = await sandbox.desktop.downloadRecording(status.recordingId);
fs.writeFileSync('demo.mp4', video);
console.log(`Video saved: ${video.length} bytes`);
}
} finally {
await sandbox.kill();
}
```
## Recording Formats
Supported video formats:
* **MP4**: H.264 encoded MP4 (recommended)
* **WebM**: WebM format (if supported)
## Quality Settings
Quality options:
* **low**: Lower file size, lower quality
* **medium**: Balanced quality and file size (default)
* **high**: Higher quality, larger file size
## Frame Rate
Frame rate options:
* **10 fps**: Lower file size, choppier video
* **15 fps**: Balanced (default)
* **30 fps**: Smooth video, larger file size
Use lower FPS and quality for longer recordings to reduce file size. Use higher settings for short, high-quality demos.
## Related
* [Screenshots](/core-concepts/desktop/screenshots) - Capture static screenshots
* [VNC Server](/core-concepts/desktop/vnc-server) - Remote desktop access
* **SDK**: [sandbox.desktop.start\_recording()](/sdk/python/desktop#start_recording) - Python SDK method
## Next Steps
* Learn about [Screenshots](/core-concepts/desktop/screenshots) for static image capture
* Explore [VNC Server](/core-concepts/desktop/vnc-server) for live remote access
* Review [Mouse Control](/core-concepts/desktop/mouse-control) and [Keyboard Control](/core-concepts/desktop/keyboard-control) for automation
* [Screenshots](/core-concepts/desktop/screenshots) - Capture static screenshots
* [Window Management](/core-concepts/desktop/window-management) - Manage windows during recording
* **[CLI System Commands](/cli/commands/system)** - System operations from CLI
# Screenshots
Source: https://docs.hopx.ai/core-concepts/desktop/screenshots
Capture screenshots of the sandbox desktop environment in HopX sandboxes. Take screenshots of desktop applications, GUIs, and visual outputs for documentation, testing, or monitoring. Learn how to capture screenshots using Python and JavaScript SDKs or REST API. Includes examples for screenshot capture and image processing.
Capture screenshots of the desktop for visual verification, debugging, and documentation.
## Overview
Screenshot capture enables:
* Full screen screenshots
* Region-specific screenshots
* Visual verification of GUI state
* Documentation and debugging
Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled.
## Full Screen Screenshot
Capture the entire screen:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop")
# Capture full screen
img_bytes = sandbox.desktop.screenshot()
# Save to file
with open('screenshot.png', 'wb') as f:
f.write(img_bytes)
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import fs from 'fs';
const sandbox = await Sandbox.create({ template: 'desktop' });
// Capture full screen
const screenshot = await sandbox.desktop.screenshot();
// Save to file (screenshot may be Buffer or object with data property)
if (screenshot instanceof Buffer) {
fs.writeFileSync('screenshot.png', screenshot);
} else {
fs.writeFileSync('screenshot.png', Buffer.from(screenshot.data, 'base64'));
}
```
## Region Screenshot
Capture a specific region of the screen:
```python theme={null}
# Capture region: x=100, y=100, width=500, height=300
img_bytes = sandbox.desktop.screenshot_region(100, 100, 500, 300)
# Save to file
with open('region.png', 'wb') as f:
f.write(img_bytes)
```
```javascript theme={null}
// Capture region: x=100, y=100, width=500, height=300
const region = await sandbox.desktop.screenshotRegion(100, 100, 500, 300);
// Save to file
fs.writeFileSync('region.png', region);
```
## Window Screenshot
Capture a specific window (X11 advanced feature):
```python theme={null}
# Capture active window
img_bytes = sandbox.desktop.capture_window()
# Capture specific window
windows = sandbox.desktop.get_windows()
if windows:
window_id = windows[0].id
img_bytes = sandbox.desktop.capture_window(window_id)
# Save to file
with open('window.png', 'wb') as f:
f.write(img_bytes)
```
```javascript theme={null}
// Capture active window
const windowImg = await sandbox.desktop.captureWindow();
// Capture specific window
const windows = await sandbox.desktop.listWindows();
if (windows.length > 0) {
const windowId = windows[0].id;
const windowImg = await sandbox.desktop.captureWindow(windowId);
}
// Save to file
fs.writeFileSync('window.png', windowImg);
```
## Screenshot Workflow
Complete screenshot workflow:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="desktop")
try:
# Start application (example)
# ... application setup ...
# Wait for application to load
time.sleep(2)
# Capture initial state
initial = sandbox.desktop.screenshot()
with open('initial.png', 'wb') as f:
f.write(initial)
# Perform actions
sandbox.desktop.click(400, 300)
time.sleep(1)
# Capture after action
after = sandbox.desktop.screenshot()
with open('after.png', 'wb') as f:
f.write(after)
# Capture specific region
region = sandbox.desktop.screenshot_region(100, 100, 400, 300)
with open('region.png', 'wb') as f:
f.write(region)
finally:
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import fs from 'fs';
const sandbox = await Sandbox.create({ template: 'desktop' });
try {
// Start application (example)
// ... application setup ...
// Wait for application to load
await new Promise(resolve => setTimeout(resolve, 2000));
// Capture initial state
const initial = await sandbox.desktop.screenshot();
fs.writeFileSync('initial.png', Buffer.from(initial.data, 'base64'));
// Perform actions
await sandbox.desktop.mouseClick(400, 300);
await new Promise(resolve => setTimeout(resolve, 1000));
// Capture after action
const after = await sandbox.desktop.screenshot();
fs.writeFileSync('after.png', Buffer.from(after.data, 'base64'));
// Capture specific region
const region = await sandbox.desktop.screenshotRegion(100, 100, 400, 300);
fs.writeFileSync('region.png', region);
} finally {
await sandbox.kill();
}
```
## Image Format
Screenshots are returned as PNG image bytes:
* **Format**: PNG
* **Color depth**: 24-bit RGB
* **Compression**: PNG compression
## Finding Coordinates
Use screenshots to find coordinates for mouse operations:
```python theme={null}
# Take screenshot
img_bytes = sandbox.desktop.screenshot()
# Save and inspect in image viewer
with open('reference.png', 'wb') as f:
f.write(img_bytes)
# Use coordinates from image viewer
sandbox.desktop.click(400, 300) # Coordinates from reference.png
```
```javascript theme={null}
// Take screenshot
const screenshot = await sandbox.desktop.screenshot();
// Save and inspect in image viewer
fs.writeFileSync('reference.png', Buffer.from(screenshot.data, 'base64'));
// Use coordinates from image viewer
await sandbox.desktop.mouseClick(400, 300); // Coordinates from reference.png
```
## Related
* [Screen Recording](/core-concepts/desktop/screen-recording) - Record screen activity
* [CLI Reference](/cli/introduction) - Command-line interface for HopX
* [Window Management](/core-concepts/desktop/window-management) - Manage windows
* [X11 Advanced](/core-concepts/desktop/x11-advanced) - Advanced screenshot features
* **SDK**: [sandbox.desktop.screenshot()](/sdk/python/desktop#screenshot) - Python SDK method
## Next Steps
* Learn about [Screen Recording](/core-concepts/desktop/screen-recording) for video capture
* Explore [Mouse Control](/core-concepts/desktop/mouse-control) to interact with GUI elements
* Review [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access
# VNC Server
Source: https://docs.hopx.ai/core-concepts/desktop/vnc-server
Start and manage VNC server for remote desktop access in HopX sandboxes. Set up VNC servers for graphical desktop environments, connect via VNC clients, and manage remote desktop sessions. Learn how to configure VNC settings, access desktop environments, and use VNC for desktop automation. Includes Python and JavaScript SDK examples.
Access and control the graphical desktop environment through VNC (Virtual Network Computing). VNC provides remote desktop access to your sandbox, allowing you to see and interact with GUI applications.
## Prerequisites
Before you begin, make sure you have:
* **Desktop template** - A sandbox created from a template with desktop support (e.g., `desktop` template)
* **Active sandbox** - A running sandbox (see [Creating Sandboxes](/core-concepts/sandboxes/creating))
* **VNC client** - A VNC viewer application (optional, for manual access)
## Overview
VNC server enables:
* Remote desktop access to sandbox GUI
* Visual debugging of GUI applications
* Interactive testing of desktop software
* Screen sharing and collaboration
Desktop automation requires a template with desktop support. Templates like `desktop` or custom templates with X11/VNC dependencies are required.
## Starting VNC Server
Start a VNC server to enable remote desktop access:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop")
# Start VNC server
vnc_info = sandbox.desktop.start_vnc()
print(f"VNC URL: {vnc_info.url}")
print(f"Display: {vnc_info.display}")
print(f"Port: {vnc_info.port}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'desktop' });
// Start VNC server
const vncInfo = await sandbox.desktop.startVnc();
console.log(`VNC URL: ${vncInfo.url}`);
console.log(`Display: ${vncInfo.display}`);
console.log(`Port: ${vncInfo.port}`);
```
## VNC Server with Password
Start VNC server with a password for security:
```python theme={null}
# Start VNC with password
vnc_info = sandbox.desktop.start_vnc(display=1, password="my-secure-password")
print(f"Connect to: {vnc_info.url}")
```
```javascript theme={null}
// Note: JavaScript SDK may have different password parameter
const vncInfo = await sandbox.desktop.startVnc();
console.log(`Connect to: ${vncInfo.url}`);
```
## Getting VNC Status
Check if VNC server is running and get connection details:
```python theme={null}
# Get VNC status
vnc_info = sandbox.desktop.get_vnc_status()
if vnc_info.running:
print(f"VNC is running at {vnc_info.url}")
print(f"Display: {vnc_info.display}")
else:
print("VNC server is not running")
```
```javascript theme={null}
// Get VNC info
const vncInfo = await sandbox.desktop.getVncInfo();
if (vncInfo.running) {
console.log(`VNC is running at ${vncInfo.url}`);
console.log(`Display: ${vncInfo.display}`);
} else {
console.log('VNC server is not running');
}
```
## Getting VNC URL
Get just the VNC URL string (convenience method):
```python theme={null}
# Get VNC URL
url = sandbox.desktop.get_vnc_url()
print(f"Connect to: {url}")
```
```javascript theme={null}
// Get VNC URL
const url = await sandbox.desktop.getVncUrl();
console.log(`Connect to: ${url}`);
```
## Stopping VNC Server
Stop the VNC server:
```python theme={null}
# Stop VNC server
sandbox.desktop.stop_vnc()
print("VNC server stopped")
```
```javascript theme={null}
// Stop VNC server
await sandbox.desktop.stopVnc();
console.log('VNC server stopped');
```
## Connecting to VNC
Once VNC is started, connect using a VNC client:
1. **Get the VNC URL** from `vnc_info.url` or `get_vnc_url()`
2. **Use a VNC client** such as:
* **TigerVNC Viewer** (Windows, macOS, Linux)
* **RealVNC Viewer** (Windows, macOS, Linux)
* **Remmina** (Linux)
* **Built-in Screen Sharing** (macOS)
3. **Connect** using the URL (e.g., `vnc://sandbox-id.region.hopx.dev:5901`)
For web-based access, some VNC clients support WebSocket connections. Check your VNC client documentation for WebSocket support.
## VNC Display Numbers
VNC servers use display numbers (e.g., `:1`, `:2`). The default is display `1`:
```python theme={null}
# Start VNC on display 2
vnc_info = sandbox.desktop.start_vnc(display=2)
print(f"Display: {vnc_info.display}") # :2
```
```javascript theme={null}
// Note: JavaScript SDK may use different parameter
const vncInfo = await sandbox.desktop.startVnc();
console.log(`Display: ${vncInfo.display}`);
```
## Complete Example
Complete workflow for VNC access:
```python theme={null}
from hopx_ai import Sandbox
# Create sandbox with desktop support
sandbox = Sandbox.create(template="desktop")
try:
# Start VNC
vnc_info = sandbox.desktop.start_vnc(password="secure-password")
print(f"✅ VNC started: {vnc_info.url}")
print(f" Display: {vnc_info.display}")
print(f" Port: {vnc_info.port}")
# Check status
status = sandbox.desktop.get_vnc_status()
if status.running:
print("✅ VNC is running")
# Use VNC URL to connect with VNC client
print(f"\nConnect using: {vnc_info.url}")
finally:
# Cleanup
sandbox.desktop.stop_vnc()
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Create sandbox with desktop support
const sandbox = await Sandbox.create({ template: 'desktop' });
try {
// Start VNC
const vncInfo = await sandbox.desktop.startVnc();
console.log(`✅ VNC started: ${vncInfo.url}`);
console.log(` Display: ${vncInfo.display}`);
console.log(` Port: ${vncInfo.port}`);
// Check status
const status = await sandbox.desktop.getVncInfo();
if (status.running) {
console.log('✅ VNC is running');
}
// Use VNC URL to connect with VNC client
console.log(`\nConnect using: ${vncInfo.url}`);
} finally {
// Cleanup
await sandbox.desktop.stopVnc();
await sandbox.kill();
}
```
## Troubleshooting
### VNC Not Available
If VNC methods raise `DesktopNotAvailableError`, your template may be missing required dependencies:
Desktop automation requires specific dependencies. Ensure your template includes:
* `tigervnc-standalone-server`
* `xvfb`
* `xdotool`
* `wmctrl`
### Connection Issues
* **Check VNC status**: Verify server is running with `get_vnc_status()`
* **Verify URL**: Ensure you're using the correct VNC URL
* **Firewall**: Check if ports are accessible
* **Password**: If using password, ensure it's correct
### Display Issues
* **Multiple displays**: Use different display numbers for multiple VNC sessions
* **Resolution**: Set display resolution before starting VNC (see Display Management)
## Related
* [Mouse Control](/core-concepts/desktop/mouse-control) - Control mouse input
* [CLI Reference](/cli/introduction) - Command-line interface for HopX
* [Keyboard Control](/core-concepts/desktop/keyboard-control) - Control keyboard input
* [Screenshots](/core-concepts/desktop/screenshots) - Capture screenshots
* [Display Management](/core-concepts/desktop/display-management) - Configure display settings
* **SDK**: [sandbox.desktop.start\_vnc()](/sdk/python/desktop#start_vnc) - Python SDK method
## Next Steps
* Learn about [Mouse Control](/core-concepts/desktop/mouse-control) to interact with GUI
* Explore [Keyboard Control](/core-concepts/desktop/keyboard-control) for text input
* Review [Screenshots](/core-concepts/desktop/screenshots) for visual verification
# Window Management
Source: https://docs.hopx.ai/core-concepts/desktop/window-management
Manage windows on the sandbox desktop including resizing, moving, and focusing windows in HopX sandboxes. Control window positions, sizes, focus, and visibility for desktop automation workflows. Learn how to manage windows using Python and JavaScript SDKs or REST API. Includes examples for window automation and GUI testing.
Manage windows on the desktop: list, focus, resize, minimize, and close windows.
## Overview
Window management enables:
* Listing all windows
* Focusing (activating) windows
* Resizing windows
* Minimizing windows
* Closing windows
Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled.
## Listing Windows
Get list of all windows:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop")
# Get all windows
windows = sandbox.desktop.get_windows()
for window in windows:
print(f"Window: {window.title}")
print(f" ID: {window.id}")
print(f" Position: ({window.x}, {window.y})")
print(f" Size: {window.width}x{window.height}")
print(f" PID: {window.pid}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'desktop' });
// Get all windows
const windows = await sandbox.desktop.listWindows();
windows.forEach(window => {
console.log(`Window: ${window.title}`);
console.log(` ID: ${window.id}`);
console.log(` Position: (${window.x}, ${window.y})`);
console.log(` Size: ${window.width}x${window.height}`);
console.log(` PID: ${window.pid}`);
});
```
## Focusing Windows
Focus (activate) a window:
```python theme={null}
# Get windows
windows = sandbox.desktop.get_windows()
# Focus first window
if windows:
sandbox.desktop.focus_window(windows[0].id)
# Find and focus window by title
for window in windows:
if "Firefox" in window.title:
sandbox.desktop.focus_window(window.id)
break
```
```javascript theme={null}
// Get windows
const windows = await sandbox.desktop.listWindows();
// Focus first window
if (windows.length > 0) {
await sandbox.desktop.focusWindow(windows[0].id);
}
// Find and focus window by title
for (const window of windows) {
if (window.title.includes('Firefox')) {
await sandbox.desktop.focusWindow(window.id);
break;
}
}
```
## Resizing Windows
Resize a window:
```python theme={null}
# Get windows
windows = sandbox.desktop.get_windows()
# Resize first window to 800x600
if windows:
sandbox.desktop.resize_window(windows[0].id, 800, 600)
# Resize window by title
for window in windows:
if "My App" in window.title:
sandbox.desktop.resize_window(window.id, 1024, 768)
break
```
```javascript theme={null}
// Get windows
const windows = await sandbox.desktop.listWindows();
// Resize first window to 800x600
if (windows.length > 0) {
await sandbox.desktop.resizeWindow(windows[0].id, 800, 600);
}
// Resize window by title
for (const window of windows) {
if (window.title.includes('My App')) {
await sandbox.desktop.resizeWindow(window.id, 1024, 768);
break;
}
}
```
## Minimizing Windows
Minimize a window:
```python theme={null}
# Minimize first window
windows = sandbox.desktop.get_windows()
if windows:
sandbox.desktop.minimize_window(windows[0].id)
```
```javascript theme={null}
// Minimize first window
const windows = await sandbox.desktop.listWindows();
if (windows.length > 0) {
await sandbox.desktop.minimizeWindow(windows[0].id);
}
```
## Closing Windows
Close a window:
```python theme={null}
# Close window by title
windows = sandbox.desktop.get_windows()
for window in windows:
if "Firefox" in window.title:
sandbox.desktop.close_window(window.id)
break
```
```javascript theme={null}
// Close window by title
const windows = await sandbox.desktop.listWindows();
for (const window of windows) {
if (window.title.includes('Firefox')) {
await sandbox.desktop.closeWindow(window.id);
break;
}
}
```
## Window Information
Window objects contain:
* **id**: Unique window identifier
* **title**: Window title/name
* **x, y**: Window position (top-left corner)
* **width, height**: Window size
* **desktop**: Desktop number (for multi-desktop)
* **pid**: Process ID of the window
## Complete Example
Complete window management workflow:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop")
try:
# List all windows
windows = sandbox.desktop.get_windows()
print(f"Found {len(windows)} windows")
# Find specific window
target_window = None
for window in windows:
if "My Application" in window.title:
target_window = window
break
if target_window:
# Focus window
sandbox.desktop.focus_window(target_window.id)
print(f"Focused: {target_window.title}")
# Resize window
sandbox.desktop.resize_window(target_window.id, 1024, 768)
print("Resized to 1024x768")
# Minimize
sandbox.desktop.minimize_window(target_window.id)
print("Minimized")
# Close
sandbox.desktop.close_window(target_window.id)
print("Closed")
finally:
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'desktop' });
try {
// List all windows
const windows = await sandbox.desktop.listWindows();
console.log(`Found ${windows.length} windows`);
// Find specific window
const targetWindow = windows.find(w => w.title.includes('My Application'));
if (targetWindow) {
// Focus window
await sandbox.desktop.focusWindow(targetWindow.id);
console.log(`Focused: ${targetWindow.title}`);
// Resize window
await sandbox.desktop.resizeWindow(targetWindow.id, 1024, 768);
console.log('Resized to 1024x768');
// Minimize
await sandbox.desktop.minimizeWindow(targetWindow.id);
console.log('Minimized');
// Close
await sandbox.desktop.closeWindow(targetWindow.id);
console.log('Closed');
}
} finally {
await sandbox.kill();
}
```
## Related
* [Display Management](/core-concepts/desktop/display-management) - Configure display settings
* [VNC Server](/core-concepts/desktop/vnc-server) - Remote desktop access
* **SDK**: [sandbox.desktop.get\_windows()](/sdk/python/desktop#get_windows) - Python SDK method
## Next Steps
* Learn about [Display Management](/core-concepts/desktop/display-management) to configure display
* Explore [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access
* Review [Screenshots](/core-concepts/desktop/screenshots) for visual verification
* [Display Management](/core-concepts/desktop/display-management) - Configure display settings
* [Screenshots](/core-concepts/desktop/screenshots) - Capture window screenshots
* **[CLI System Commands](/cli/commands/system)** - System operations from CLI
# X11 Advanced Features
Source: https://docs.hopx.ai/core-concepts/desktop/x11-advanced
Advanced X11 desktop automation features for sandbox environments in HopX. Access advanced X11 capabilities for complex desktop automation, window management, and GUI interactions. Learn about X11-specific features, advanced automation techniques, and low-level desktop control. Includes Python and JavaScript SDK examples and X11 API endpoints.
Advanced X11 desktop automation features including OCR, element finding, and advanced interactions.
## Prerequisites
Before you begin, make sure you have:
* **VNC server running** - A VNC server must be started (see [VNC Server](/core-concepts/desktop/vnc-server))
* **Desktop template** - A sandbox with desktop support enabled
* **Active sandbox** - A running sandbox with desktop capabilities
* **Basic desktop automation** - Familiarity with basic desktop operations is helpful
## Overview
X11 advanced features enable:
* OCR (Optical Character Recognition) text extraction
* Finding UI elements by text
* Waiting for elements to appear
* Advanced drag and drop
* Window capture
* Hotkey execution
Desktop automation requires a template with desktop support. Ensure your sandbox has desktop capabilities enabled.
## OCR (Optical Character Recognition)
Extract text from screen regions using OCR:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop")
# Extract text from region
text = sandbox.desktop.ocr(100, 100, 400, 200)
print(f"Extracted text: {text}")
# OCR with custom language
text = sandbox.desktop.ocr(100, 100, 400, 200, language="eng")
print(f"Text: {text}")
```
**Expected Output:**
```
Extracted text: Hello World
Text: Hello World
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'desktop' });
// Extract text from region
const text = await sandbox.desktop.ocr(100, 100, 400, 200);
console.log(`Extracted text: ${text}`);
// OCR with custom language
const text2 = await sandbox.desktop.ocr(100, 100, 400, 200, { language: 'eng' });
console.log(`Text: ${text2}`);
```
**Expected Output:**
```
Extracted text: Hello World
Text: Hello World
```
## Finding Elements
Find UI elements by text:
```python theme={null}
# Find element by text
element = sandbox.desktop.find_element("Submit")
if element:
print(f"Found at: ({element['x']}, {element['y']})")
print(f"Size: {element['width']}x{element['height']}")
# Click the element
sandbox.desktop.click(element['x'], element['y'])
else:
print("Element not found")
```
**Expected Output:**
```
Found at: (150, 200)
Size: 100x30
```
```javascript theme={null}
// Find element by text
const element = await sandbox.desktop.findElement('Submit');
if (element) {
console.log(`Found at: (${element.x}, ${element.y})`);
console.log(`Size: ${element.width}x${element.height}`);
// Click the element
await sandbox.desktop.mouseClick(element.x, element.y);
} else {
console.log('Element not found');
}
```
**Expected Output:**
```
Found at: (150, 200)
Size: 100x30
```
## Waiting for Elements
Wait for an element to appear:
```python theme={null}
# Wait for element to appear (default: 30 seconds)
element = sandbox.desktop.wait_for("Loading complete", timeout=60)
print(f"Element found at: ({element['x']}, {element['y']})")
# Click when found
sandbox.desktop.click(element['x'], element['y'])
```
**Expected Output:**
```
Element found at: (200, 300)
```
```javascript theme={null}
// Wait for element to appear (default: 30 seconds)
const element = await sandbox.desktop.waitFor('Loading complete', 60);
console.log(`Element found at: (${element.x}, ${element.y})`);
// Click when found
await sandbox.desktop.mouseClick(element.x, element.y);
```
**Expected Output:**
```
Element found at: (200, 300)
```
## Getting Element Bounds
Get bounding box of an element:
```python theme={null}
# Get element bounds
bounds = sandbox.desktop.get_bounds("OK Button")
print(f"Button at: {bounds['x']}, {bounds['y']}")
print(f"Size: {bounds['width']}x{bounds['height']}")
# Click center of button
center_x = bounds['x'] + bounds['width'] // 2
center_y = bounds['y'] + bounds['height'] // 2
sandbox.desktop.click(center_x, center_y)
```
**Expected Output:**
```
Button at: 300, 400
Size: 80x25
```
```javascript theme={null}
// Get element bounds
const bounds = await sandbox.desktop.getBounds('OK Button');
console.log(`Button at: ${bounds.x}, ${bounds.y}`);
console.log(`Size: ${bounds.width}x${bounds.height}`);
// Click center of button
const centerX = bounds.x + bounds.width / 2;
const centerY = bounds.y + bounds.height / 2;
await sandbox.desktop.mouseClick(centerX, centerY);
```
**Expected Output:**
```
Button at: 300, 400
Size: 80x25
```
## Advanced Drag and Drop
Drag and drop operations:
```python theme={null}
# Drag and drop
sandbox.desktop.drag_drop(100, 200, 500, 300)
# Drag file to folder
sandbox.desktop.drag_drop(50, 50, 400, 300)
```
**Expected Output:**
```
(Drag and drop operation completed)
```
```javascript theme={null}
// Drag and drop
await sandbox.desktop.dragDrop(100, 200, 500, 300);
// Drag file to folder
await sandbox.desktop.dragDrop(50, 50, 400, 300);
```
**Expected Output:**
```
(Drag and drop operation completed)
```
## Window Capture
Capture specific window:
```python theme={null}
# Capture active window
img_bytes = sandbox.desktop.capture_window()
# Capture specific window
windows = sandbox.desktop.get_windows()
if windows:
window_id = windows[0].id
img_bytes = sandbox.desktop.capture_window(window_id)
# Save to file
with open('window.png', 'wb') as f:
f.write(img_bytes)
```
**Expected Output:**
```
(Window captured and saved to window.png)
```
```javascript theme={null}
// Capture active window
const windowImg = await sandbox.desktop.captureWindow();
// Capture specific window
const windows = await sandbox.desktop.listWindows();
if (windows.length > 0) {
const windowId = windows[0].id;
const windowImg = await sandbox.desktop.captureWindow(windowId);
}
// Save to file
fs.writeFileSync('window.png', windowImg);
```
**Expected Output:**
```
(Window captured and saved to window.png)
```
## Hotkeys
Execute hotkey combinations:
```python theme={null}
# Copy: Ctrl+C
sandbox.desktop.hotkey(['ctrl'], 'c')
# Paste: Ctrl+V
sandbox.desktop.hotkey(['ctrl'], 'v')
# Switch window: Alt+Tab
sandbox.desktop.hotkey(['alt'], 'tab')
# Screenshot: Ctrl+Shift+P
sandbox.desktop.hotkey(['ctrl', 'shift'], 'p')
```
**Expected Output:**
```
(Hotkey combinations executed)
```
```javascript theme={null}
// Note: JavaScript SDK may use keyboardCombination
// Copy: Ctrl+C
await sandbox.desktop.keyboardCombination(['ctrl', 'c']);
// Paste: Ctrl+V
await sandbox.desktop.keyboardCombination(['ctrl', 'v']);
```
**Expected Output:**
```
(Hotkey combinations executed)
```
## Complete Example
Complete workflow using advanced features:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="desktop")
try:
# Wait for application to load
element = sandbox.desktop.wait_for("Application Ready", timeout=30)
print("Application loaded")
# Find and click button
button = sandbox.desktop.find_element("Start")
if button:
sandbox.desktop.click(button['x'], button['y'])
# Wait for dialog
dialog = sandbox.desktop.wait_for("Confirm", timeout=10)
# Extract text from dialog using OCR
dialog_text = sandbox.desktop.ocr(
dialog['x'], dialog['y'],
dialog['width'], dialog['height']
)
print(f"Dialog text: {dialog_text}")
# Find OK button
ok_bounds = sandbox.desktop.get_bounds("OK")
center_x = ok_bounds['x'] + ok_bounds['width'] // 2
center_y = ok_bounds['y'] + ok_bounds['height'] // 2
sandbox.desktop.click(center_x, center_y)
finally:
sandbox.kill()
```
**Expected Output:**
```
Application loaded
Dialog text: Please confirm this action
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'desktop' });
try {
// Wait for application to load
const element = await sandbox.desktop.waitFor('Application Ready', 30);
console.log('Application loaded');
// Find and click button
const button = await sandbox.desktop.findElement('Start');
if (button) {
await sandbox.desktop.mouseClick(button.x, button.y);
}
// Wait for dialog
const dialog = await sandbox.desktop.waitFor('Confirm', 10);
// Extract text from dialog using OCR
const dialogText = await sandbox.desktop.ocr(
dialog.x, dialog.y,
dialog.width, dialog.height
);
console.log(`Dialog text: ${dialogText}`);
// Find OK button
const okBounds = await sandbox.desktop.getBounds('OK');
const centerX = okBounds.x + okBounds.width / 2;
const centerY = okBounds.y + okBounds.height / 2;
await sandbox.desktop.mouseClick(centerX, centerY);
} finally {
await sandbox.kill();
}
```
**Expected Output:**
```
Application loaded
Dialog text: Please confirm this action
```
## OCR Languages
Supported OCR languages:
* **eng**: English (default)
* **spa**: Spanish
* **fra**: French
* **deu**: German
* And more (check Tesseract language support)
## Related
* [Screenshots](/core-concepts/desktop/screenshots) - Basic screenshot capture
* [Mouse Control](/core-concepts/desktop/mouse-control) - Mouse operations
* [Keyboard Control](/core-concepts/desktop/keyboard-control) - Keyboard operations
* **SDK**: [sandbox.desktop.ocr()](/sdk/python/desktop#ocr) - Python SDK method
## Next Steps
* Learn about [Screenshots](/core-concepts/desktop/screenshots) for basic image capture
* Explore [Mouse Control](/core-concepts/desktop/mouse-control) and [Keyboard Control](/core-concepts/desktop/keyboard-control) for interactions
* Review [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access
* [Mouse Control](/core-concepts/desktop/mouse-control) - Basic mouse operations
* [Keyboard Control](/core-concepts/desktop/keyboard-control) - Basic keyboard operations
* [Screenshots](/core-concepts/desktop/screenshots) - Screenshot capture
* **[CLI System Commands](/cli/commands/system)** - System operations from CLI
# Clearing
Source: https://docs.hopx.ai/core-concepts/environment/clearing
Remove environment variables from sandboxes. Clear all environment variables to reset configuration, remove sensitive data, or start with a clean environment. Learn how to clear variables using Python and JavaScript SDKs or REST API. Includes examples for cleanup and security best practices.
Remove environment variables from your sandbox. You can delete individual variables or clear all custom variables at once.
## Overview
Clearing environment variables is useful for:
* Removing sensitive data
* Resetting configuration
* Cleaning up temporary variables
* Preparing sandbox for reuse
Deleting individual variables preserves other variables. System variables (like `PATH`, `HOME`) are typically preserved and cannot be deleted.
## Delete Single Variable
Delete a specific environment variable:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set some variables
sandbox.env.set_all({
"API_KEY": "sk-123",
"DEBUG": "true",
"TEMP_TOKEN": "temp-xyz"
})
# Delete a single variable
sandbox.env.delete("TEMP_TOKEN")
print("TEMP_TOKEN deleted")
# Verify deletion
env = sandbox.env.get_all()
print(f"TEMP_TOKEN exists: {'TEMP_TOKEN' in env}")
print(f"API_KEY still exists: {'API_KEY' in env}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set some variables
await sandbox.env.setAll({
API_KEY: 'sk-123',
DEBUG: 'true',
TEMP_TOKEN: 'temp-xyz'
});
// Delete a single variable
await sandbox.env.delete('TEMP_TOKEN');
console.log('TEMP_TOKEN deleted');
// Verify deletion
const env = await sandbox.env.getAll();
console.log(`TEMP_TOKEN exists: ${'TEMP_TOKEN' in env}`);
console.log(`API_KEY still exists: ${'API_KEY' in env}`);
await sandbox.kill();
```
## Delete Multiple Variables
Delete multiple variables one by one:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set multiple variables
sandbox.env.set_all({
"API_KEY": "sk-123",
"DATABASE_URL": "postgres://localhost/db",
"DEBUG": "true",
"TEMP_TOKEN": "temp-xyz",
"OLD_CONFIG": "deprecated"
})
# Delete multiple variables
variables_to_delete = ["TEMP_TOKEN", "OLD_CONFIG", "DEBUG"]
for var in variables_to_delete:
sandbox.env.delete(var)
print(f"Deleted: {var}")
# Verify remaining variables
env = sandbox.env.get_all()
print(f"\nRemaining variables: {list(env.keys())}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set multiple variables
await sandbox.env.setAll({
API_KEY: 'sk-123',
DATABASE_URL: 'postgres://localhost/db',
DEBUG: 'true',
TEMP_TOKEN: 'temp-xyz',
OLD_CONFIG: 'deprecated'
});
// Delete multiple variables
const variablesToDelete = ['TEMP_TOKEN', 'OLD_CONFIG', 'DEBUG'];
for (const varName of variablesToDelete) {
await sandbox.env.delete(varName);
console.log(`Deleted: ${varName}`);
}
// Verify remaining variables
const env = await sandbox.env.getAll();
console.log(`\nRemaining variables: ${Object.keys(env)}`);
await sandbox.kill();
```
## Clear All Custom Variables
Clear all custom environment variables:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set custom variables
sandbox.env.set_all({
"API_KEY": "sk-123",
"DATABASE_URL": "postgres://localhost/db",
"DEBUG": "true"
})
# Get current variables
before = sandbox.env.get_all()
print(f"Variables before: {len(before)}")
# Clear all custom variables (set empty dict)
sandbox.env.set_all({})
# Get variables after clearing
after = sandbox.env.get_all()
print(f"Variables after: {len(after)}")
# System variables may still exist
system_vars = ['PATH', 'HOME', 'USER', 'SHELL']
remaining = [v for v in after.keys() if v in system_vars]
print(f"System variables preserved: {remaining}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set custom variables
await sandbox.env.setAll({
API_KEY: 'sk-123',
DATABASE_URL: 'postgres://localhost/db',
DEBUG: 'true'
});
// Get current variables
const before = await sandbox.env.getAll();
console.log(`Variables before: ${Object.keys(before).length}`);
// Clear all custom variables (set empty dict)
await sandbox.env.setAll({});
// Get variables after clearing
const after = await sandbox.env.getAll();
console.log(`Variables after: ${Object.keys(after).length}`);
// System variables may still exist
const systemVars = ['PATH', 'HOME', 'USER', 'SHELL'];
const remaining = Object.keys(after).filter(v => systemVars.includes(v));
console.log(`System variables preserved: ${remaining}`);
await sandbox.kill();
```
## Clean Up Temporary Variables
Remove temporary or sensitive variables:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set up environment with temporary variables
sandbox.env.set_all({
"API_KEY": "sk-prod-xyz",
"DATABASE_URL": "postgres://localhost/db",
"TEMP_TOKEN": "temp-abc123",
"SESSION_ID": "session-xyz",
"DEBUG": "true"
})
# Clean up temporary variables
temp_vars = ["TEMP_TOKEN", "SESSION_ID"]
for var in temp_vars:
sandbox.env.delete(var)
print(f"Cleaned up: {var}")
# Verify cleanup
env = sandbox.env.get_all()
print(f"\nRemaining variables: {list(env.keys())}")
# Production variables should still exist
print(f"API_KEY exists: {'API_KEY' in env}")
print(f"DATABASE_URL exists: {'DATABASE_URL' in env}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set up environment with temporary variables
await sandbox.env.setAll({
API_KEY: 'sk-prod-xyz',
DATABASE_URL: 'postgres://localhost/db',
TEMP_TOKEN: 'temp-abc123',
SESSION_ID: 'session-xyz',
DEBUG: 'true'
});
// Clean up temporary variables
const tempVars = ['TEMP_TOKEN', 'SESSION_ID'];
for (const varName of tempVars) {
await sandbox.env.delete(varName);
console.log(`Cleaned up: ${varName}`);
}
// Verify cleanup
const env = await sandbox.env.getAll();
console.log(`\nRemaining variables: ${Object.keys(env)}`);
// Production variables should still exist
console.log(`API_KEY exists: ${'API_KEY' in env}`);
console.log(`DATABASE_URL exists: ${'DATABASE_URL' in env}`);
await sandbox.kill();
```
## Complete Example
Here's a complete example showing environment variable cleanup:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set up complete environment
print("🔧 Setting up environment...")
sandbox.env.set_all({
"API_KEY": "sk-prod-xyz",
"DATABASE_URL": "postgres://localhost/prod",
"REDIS_URL": "redis://localhost:6379",
"TEMP_TOKEN": "temp-abc123",
"SESSION_ID": "session-xyz",
"DEBUG": "true",
"LOG_LEVEL": "info"
})
env = sandbox.env.get_all()
print(f"✅ Environment set up with {len(env)} variables\n")
# Use environment in code
print("💻 Using environment in code...")
result = sandbox.run_code('''
import os
print(f"API key: {os.getenv('API_KEY', 'not set')[:10]}...")
print(f"Database: {os.getenv('DATABASE_URL', 'not set')}")
print(f"Temp Token: {os.getenv('TEMP_TOKEN', 'not set')}")
''')
print(result.stdout)
# Clean up temporary variables
print("\n🧹 Cleaning up temporary variables...")
temp_vars = ["TEMP_TOKEN", "SESSION_ID"]
for var in temp_vars:
sandbox.env.delete(var)
print(f" ✅ Deleted: {var}")
# Verify cleanup
print("\n📋 Final environment:")
final_env = sandbox.env.get_all()
for key in sorted(final_env.keys()):
if key not in ['PATH', 'HOME', 'USER', 'SHELL', 'PWD']:
if any(sensitive in key.upper() for sensitive in ['KEY', 'SECRET', 'PASSWORD']):
print(f" {key}=***MASKED***")
else:
print(f" {key}={final_env[key]}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set up complete environment
console.log('🔧 Setting up environment...');
await sandbox.env.setAll({
API_KEY: 'sk-prod-xyz',
DATABASE_URL: 'postgres://localhost/prod',
REDIS_URL: 'redis://localhost:6379',
TEMP_TOKEN: 'temp-abc123',
SESSION_ID: 'session-xyz',
DEBUG: 'true',
LOG_LEVEL: 'info'
});
const env = await sandbox.env.getAll();
console.log(`✅ Environment set up with ${Object.keys(env).length} variables\n`);
// Use environment in code
console.log('💻 Using environment in code...');
const result = await sandbox.runCode(`
import os
print(f"API key: {os.getenv('API_KEY', 'not set')[:10]}...")
print(f"Database: {os.getenv('DATABASE_URL', 'not set')}")
print(f"Temp Token: {os.getenv('TEMP_TOKEN', 'not set')}")
`);
console.log(result.stdout);
// Clean up temporary variables
console.log('\n🧹 Cleaning up temporary variables...');
const tempVars = ['TEMP_TOKEN', 'SESSION_ID'];
for (const varName of tempVars) {
await sandbox.env.delete(varName);
console.log(` ✅ Deleted: ${varName}`);
}
// Verify cleanup
console.log('\n📋 Final environment:');
const finalEnv = await sandbox.env.getAll();
for (const key of Object.keys(finalEnv).sort()) {
if (!['PATH', 'HOME', 'USER', 'SHELL', 'PWD'].includes(key)) {
const isSensitive = ['KEY', 'SECRET', 'PASSWORD'].some(
s => key.toUpperCase().includes(s)
);
if (isSensitive) {
console.log(` ${key}=***MASKED***`);
} else {
console.log(` ${key}=${finalEnv[key]}`);
}
}
}
await sandbox.kill();
```
## Best Practices
Use `delete(key)` to remove specific variables while preserving others.
Regularly delete temporary variables (tokens, session IDs) to reduce security risk.
Clear all custom variables before reusing a sandbox for a different purpose.
Always verify variables are deleted using `get_all()` or `get()` after deletion.
System variables (PATH, HOME, etc.) are typically preserved and cannot be deleted.
## Related
* **[Getting Environment Variables](/core-concepts/environment/getting)** - Retrieve environment variables
* **[Setting Environment Variables](/core-concepts/environment/setting)** - Set or replace variables
* **[Updating Environment Variables](/core-concepts/environment/updating)** - Update variables without replacing
* **SDK**: [sandbox.env.clear()](/sdk/python/environment-variables#clear) - Python SDK method
* **API**: [DELETE /env](/api/vm-agent/clear-env) - VM Agent API endpoint
* [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI
## Next Steps
* Learn about [Getting Environment Variables](/core-concepts/environment/getting) to retrieve variables
* Explore [Setting Environment Variables](/core-concepts/environment/setting) to configure your sandbox
* Review [Updating Environment Variables](/core-concepts/environment/updating) to modify existing variables
# Getting
Source: https://docs.hopx.ai/core-concepts/environment/getting
Retrieve environment variables from sandboxes. Learn how to get single or all environment variables from HopX sandboxes using Python and JavaScript SDKs or REST API. Includes examples for reading variables, handling missing variables, and processing environment data. Essential for configuring code execution environments.
Retrieve environment variables from your sandbox. You can get all variables at once or fetch specific variables by name.
## Overview
Getting environment variables is useful for:
* Inspecting current environment configuration
* Verifying variables are set correctly
* Accessing system and custom variables
* Debugging environment-related issues
Environment variables include both system variables (like `PATH`, `HOME`) and custom variables you've set. Sensitive values may be masked in responses.
## Get All Environment Variables
Retrieve all environment variables:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Get all environment variables
env = sandbox.env.get_all()
print(f"Total variables: {len(env)}")
# Access specific variables
print(f"PATH: {env.get('PATH', 'not set')}")
print(f"HOME: {env.get('HOME', 'not set')}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Get all environment variables
const env = await sandbox.env.getAll();
console.log(`Total variables: ${Object.keys(env).length}`);
// Access specific variables
console.log(`PATH: ${env.PATH || 'not set'}`);
console.log(`HOME: ${env.HOME || 'not set'}`);
await sandbox.kill();
```
## Get Specific Variable
Get a single environment variable:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Get a specific variable
api_key = sandbox.env.get("API_KEY")
if api_key:
print(f"API key: {api_key[:10]}...")
else:
print("API_KEY not set")
# Get with default value
db_url = sandbox.env.get("DATABASE_URL", "postgres://localhost/db")
print(f"Database URL: {db_url}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Get a specific variable
const apiKey = await sandbox.env.get('API_KEY');
if (apiKey) {
console.log(`API key: ${apiKey.substring(0, 10)}...`);
} else {
console.log('API_KEY not set');
}
// Get with default value
const dbUrl = await sandbox.env.get('DATABASE_URL', 'postgres://localhost/db');
console.log(`Database URL: ${dbUrl}`);
await sandbox.kill();
```
## List All Variables
Iterate through all environment variables:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Get all variables
env = sandbox.env.get_all()
# List all variables
print("Environment Variables:")
for key, value in sorted(env.items()):
# Mask sensitive values
if any(sensitive in key.upper() for sensitive in ['KEY', 'SECRET', 'PASSWORD', 'TOKEN']):
print(f" {key}=***MASKED***")
else:
print(f" {key}={value}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Get all variables
const env = await sandbox.env.getAll();
// List all variables
console.log('Environment Variables:');
for (const [key, value] of Object.entries(env).sort()) {
// Mask sensitive values
const isSensitive = ['KEY', 'SECRET', 'PASSWORD', 'TOKEN'].some(
s => key.toUpperCase().includes(s)
);
if (isSensitive) {
console.log(` ${key}=***MASKED***`);
} else {
console.log(` ${key}=${value}`);
}
}
await sandbox.kill();
```
## Filter Variables
Filter environment variables by prefix or pattern:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Get all variables
env = sandbox.env.get_all()
# Filter by prefix
api_vars = {k: v for k, v in env.items() if k.startswith('API_')}
print(f"API variables: {list(api_vars.keys())}")
# Filter by pattern
debug_vars = {k: v for k, v in env.items() if 'DEBUG' in k.upper()}
print(f"Debug variables: {list(debug_vars.keys())}")
# Filter custom variables (exclude system vars)
system_vars = {'PATH', 'HOME', 'USER', 'SHELL', 'PWD'}
custom_vars = {k: v for k, v in env.items() if k not in system_vars}
print(f"Custom variables: {list(custom_vars.keys())}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Get all variables
const env = await sandbox.env.getAll();
// Filter by prefix
const apiVars = Object.fromEntries(
Object.entries(env).filter(([k]) => k.startsWith('API_'))
);
console.log(`API variables: ${Object.keys(apiVars)}`);
// Filter by pattern
const debugVars = Object.fromEntries(
Object.entries(env).filter(([k]) => k.toUpperCase().includes('DEBUG'))
);
console.log(`Debug variables: ${Object.keys(debugVars)}`);
// Filter custom variables (exclude system vars)
const systemVars = new Set(['PATH', 'HOME', 'USER', 'SHELL', 'PWD']);
const customVars = Object.fromEntries(
Object.entries(env).filter(([k]) => !systemVars.has(k))
);
console.log(`Custom variables: ${Object.keys(customVars)}`);
await sandbox.kill();
```
## Check Variable Existence
Check if a variable exists:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Check if variable exists
api_key = sandbox.env.get("API_KEY")
if api_key:
print("API_KEY is set")
else:
print("API_KEY is not set")
# Check multiple variables
required_vars = ["API_KEY", "DATABASE_URL", "NODE_ENV"]
env = sandbox.env.get_all()
missing = [var for var in required_vars if var not in env]
if missing:
print(f"Missing variables: {missing}")
else:
print("All required variables are set")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Check if variable exists
const apiKey = await sandbox.env.get('API_KEY');
if (apiKey) {
console.log('API_KEY is set');
} else {
console.log('API_KEY is not set');
}
// Check multiple variables
const requiredVars = ['API_KEY', 'DATABASE_URL', 'NODE_ENV'];
const env = await sandbox.env.getAll();
const missing = requiredVars.filter(v => !(v in env));
if (missing.length > 0) {
console.log(`Missing variables: ${missing}`);
} else {
console.log('All required variables are set');
}
await sandbox.kill();
```
## Verify Variables in Code
Verify environment variables are accessible in code execution:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set some variables
sandbox.env.set("API_KEY", "sk-123")
sandbox.env.set("DEBUG", "true")
# Verify they're accessible in code
result = sandbox.run_code('''
import os
print(f"API_KEY: {os.getenv('API_KEY')}")
print(f"DEBUG: {os.getenv('DEBUG')}")
''')
print(result.stdout)
# Get variables via env API
env = sandbox.env.get_all()
print(f"\nVia API - API_KEY: {env.get('API_KEY')}")
print(f"Via API - DEBUG: {env.get('DEBUG')}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set some variables
await sandbox.env.set('API_KEY', 'sk-123');
await sandbox.env.set('DEBUG', 'true');
// Verify they're accessible in code
const result = await sandbox.runCode(`
import os
print(f"API_KEY: {os.getenv('API_KEY')}")
print(f"DEBUG: {os.getenv('DEBUG')}")
`);
console.log(result.stdout);
// Get variables via env API
const env = await sandbox.env.getAll();
console.log(`\nVia API - API_KEY: ${env.API_KEY}`);
console.log(`Via API - DEBUG: ${env.DEBUG}`);
await sandbox.kill();
```
## Complete Example
Here's a complete example showing environment variable retrieval:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set up environment
sandbox.env.set_all({
"API_KEY": "sk-prod-xyz",
"DATABASE_URL": "postgres://localhost/db",
"NODE_ENV": "production",
"DEBUG": "false"
})
# Get all variables
print("📋 All Environment Variables:")
env = sandbox.env.get_all()
for key, value in sorted(env.items()):
if any(sensitive in key.upper() for sensitive in ['KEY', 'SECRET', 'PASSWORD']):
print(f" {key}=***MASKED***")
else:
print(f" {key}={value}")
# Get specific variables
print("\n🔍 Specific Variables:")
api_key = sandbox.env.get("API_KEY")
print(f" API_KEY: {'Set' if api_key else 'Not set'}")
db_url = sandbox.env.get("DATABASE_URL")
print(f" DATABASE_URL: {db_url}")
node_env = sandbox.env.get("NODE_ENV", "development")
print(f" NODE_ENV: {node_env}")
# Verify in code execution
print("\n✅ Verification in Code:")
result = sandbox.run_code('''
import os
print(f"API_KEY: {os.getenv('API_KEY', 'not set')[:10]}...")
print(f"DATABASE_URL: {os.getenv('DATABASE_URL', 'not set')}")
print(f"NODE_ENV: {os.getenv('NODE_ENV', 'not set')}")
''')
print(result.stdout)
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set up environment
await sandbox.env.setAll({
API_KEY: 'sk-prod-xyz',
DATABASE_URL: 'postgres://localhost/db',
NODE_ENV: 'production',
DEBUG: 'false'
});
// Get all variables
console.log('📋 All Environment Variables:');
const env = await sandbox.env.getAll();
for (const [key, value] of Object.entries(env).sort()) {
const isSensitive = ['KEY', 'SECRET', 'PASSWORD'].some(
s => key.toUpperCase().includes(s)
);
if (isSensitive) {
console.log(` ${key}=***MASKED***`);
} else {
console.log(` ${key}=${value}`);
}
}
// Get specific variables
console.log('\n🔍 Specific Variables:');
const apiKey = await sandbox.env.get('API_KEY');
console.log(` API_KEY: ${apiKey ? 'Set' : 'Not set'}`);
const dbUrl = await sandbox.env.get('DATABASE_URL');
console.log(` DATABASE_URL: ${dbUrl}`);
const nodeEnv = await sandbox.env.get('NODE_ENV', 'development');
console.log(` NODE_ENV: ${nodeEnv}`);
// Verify in code execution
console.log('\n✅ Verification in Code:');
const result = await sandbox.runCode(`
import os
print(f"API_KEY: {os.getenv('API_KEY', 'not set')[:10]}...")
print(f"DATABASE_URL: {os.getenv('DATABASE_URL', 'not set')}")
print(f"NODE_ENV: {os.getenv('NODE_ENV', 'not set')}")
`);
console.log(result.stdout);
await sandbox.kill();
```
## Best Practices
Use `env.get(key)` for retrieving individual variables with optional defaults.
Use `env.get_all()` when you need to access multiple variables or iterate through all.
Always check if variables exist or provide defaults when retrieving.
When displaying environment variables, mask sensitive values (keys, secrets, passwords, tokens).
Test that environment variables are accessible in code execution to ensure they're set correctly.
## Related
* **[Setting Environment Variables](/core-concepts/environment/setting)** - Set environment variables
* **[Updating Environment Variables](/core-concepts/environment/updating)** - Update variables
* **SDK**: [sandbox.env.get()](/sdk/python/environment-variables#get) - Python SDK method
* **API**: [GET /env](/api/vm-agent/get-env) - VM Agent API endpoint
* [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI
## Next Steps
* Learn about [Setting Environment Variables](/core-concepts/environment/setting) to configure your sandbox
* Explore [Updating Environment Variables](/core-concepts/environment/updating) to modify existing variables
* Review [Clearing Environment Variables](/core-concepts/environment/clearing) to remove variables
# Environment Variables
Source: https://docs.hopx.ai/core-concepts/environment/index
Complete guide to managing environment variables in HopX sandboxes - getting, setting, updating, and clearing environment variables. Learn how to configure execution environments, set variables for code execution, manage variables across sandbox sessions, and use environment variables in Python and JavaScript SDKs or REST API.
Manage environment variables in HopX sandboxes to configure execution environments. This hub covers all environment variable operations, from basic get/set to advanced bulk updates.
## Related
* [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI
## What You'll Learn
* How to get and set environment variables
* How to update existing variables
* How to clear all environment variables
* How to use environment variables in code execution
* How to manage variables across sandbox sessions
## Environment Variables Overview
| Operation | SDK Method | API Endpoint |
| --------------------------------------------------- | ------------------------------------- | ------------- |
| **[Getting](/core-concepts/environment/getting)** | `sandbox.env.get()` / `env.get_all()` | `GET /env` |
| **[Setting](/core-concepts/environment/setting)** | `sandbox.env.set()` / `env.set_all()` | `PUT /env` |
| **[Updating](/core-concepts/environment/updating)** | `sandbox.env.update()` | `PATCH /env` |
| **[Clearing](/core-concepts/environment/clearing)** | `sandbox.env.clear()` | `DELETE /env` |
## Core Concepts
### Getting Environment Variables
Retrieve environment variables from sandboxes.
* **[Getting Environment Variables](/core-concepts/environment/getting)** - Get environment variables
* **SDK**: [Python: sandbox.env.get()](/sdk/python/environment-variables#get) | [Python: sandbox.env.get\_all()](/sdk/python/environment-variables#get_all) | [JavaScript: sandbox.env.get()](/sdk/javascript/environment-variables#get) | [JavaScript: sandbox.env.getAll()](/sdk/javascript/environment-variables#getall)
* **API**: [GET /env](/api/vm-agent/get-env)
### Setting Environment Variables
Set environment variables in sandboxes.
* **[Setting Environment Variables](/core-concepts/environment/setting)** - Set environment variables
* **SDK**: [Python: sandbox.env.set()](/sdk/python/environment-variables#set) | [Python: sandbox.env.set\_all()](/sdk/python/environment-variables#set_all) | [JavaScript: sandbox.env.set()](/sdk/javascript/environment-variables#set) | [JavaScript: sandbox.env.setAll()](/sdk/javascript/environment-variables#setall)
* **API**: [PUT /env](/api/vm-agent/set-env) | [POST /env](/api/vm-agent/set-env)
### Updating Environment Variables
Update existing environment variables without clearing others.
* **[Updating Environment Variables](/core-concepts/environment/updating)** - Update environment variables
* **SDK**: [Python: sandbox.env.update()](/sdk/python/environment-variables#update) | [JavaScript: sandbox.env.update()](/sdk/javascript/environment-variables#update)
* **API**: [PATCH /env](/api/vm-agent/update-env)
### Clearing Environment Variables
Remove all environment variables from sandboxes.
* **[Clearing Environment Variables](/core-concepts/environment/clearing)** - Clear all environment variables
* **SDK**: [Python: sandbox.env.clear()](/sdk/python/environment-variables#clear) | [JavaScript: sandbox.env.clear()](/sdk/javascript/environment-variables#clear)
* **API**: [DELETE /env](/api/vm-agent/clear-env)
## SDK Reference
### Python SDK
Complete reference for Python environment variable operations.
* **[Environment Variables Module](/sdk/python/environment-variables)** - Complete environment API
* `env.get()` - Get single variable
* `env.get_all()` - Get all variables
* `env.set()` - Set single variable
* `env.set_all()` - Set all variables
* `env.update()` - Update variables
* `env.clear()` - Clear all variables
### JavaScript SDK
Complete reference for JavaScript/TypeScript environment variable operations.
* **[Environment Variables Module](/sdk/javascript/environment-variables)** - Complete environment API
* `env.get()` - Get single variable
* `env.getAll()` - Get all variables
* `env.set()` - Set single variable
* `env.setAll()` - Set all variables
* `env.update()` - Update variables
* `env.clear()` - Clear all variables
## API Reference
### VM Agent API
REST API endpoints for environment variable operations.
* **[VM Agent API Overview](/api/vm-agent/overview)** - API overview
* **[Get Environment Variables](/api/vm-agent/get-env)** - `GET /env` - Get all variables
* **[Set Environment Variables](/api/vm-agent/set-env)** - `PUT /env` - Set all variables
* **[Update Environment Variables](/api/vm-agent/update-env)** - `PATCH /env` - Update variables
* **[Clear Environment Variables](/api/vm-agent/clear-env)** - `DELETE /env` - Clear all variables
## Quick Start
If you're new to environment variables, start here:
1. **[Getting Environment Variables](/core-concepts/environment/getting)** - Read environment variables
2. **[Setting Environment Variables](/core-concepts/environment/setting)** - Set your first variable
3. **[Updating Environment Variables](/core-concepts/environment/updating)** - Update existing variables
## Related Topics
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Use environment variables in code
* **[Sandboxes](/core-concepts/sandboxes/creating)** - Set variables when creating sandboxes
* **[File Operations](/core-concepts/filesystem/reading)** - Configure file paths with variables
* **[Commands](/core-concepts/commands/running)** - Use variables in shell commands
## Next Steps
* Learn about [Code Execution](/core-concepts/code-execution/synchronous) to use variables in code
* Explore [Setting Environment Variables](/core-concepts/environment/setting) for configuration
* Review [Updating Environment Variables](/core-concepts/environment/updating) for incremental changes
* Check out [Sandboxes](/core-concepts/sandboxes/creating) for initial configuration
# Setting
Source: https://docs.hopx.ai/core-concepts/environment/setting
Set and replace environment variables in sandboxes. Configure execution environments by setting environment variables for code execution, API keys, database connections, and other configuration values. Learn how to set single or multiple variables using Python and JavaScript SDKs or REST API. Includes examples for common use cases.
Set environment variables in your sandbox. You can set individual variables or replace all variables at once.
## Overview
Setting environment variables is essential for:
* Configuring application settings
* Providing API keys and secrets
* Setting up database connections
* Configuring runtime behavior
`set_all()` replaces ALL existing environment variables. Use [Updating Environment Variables](/core-concepts/environment/updating) if you want to merge with existing variables instead.
## Set Single Variable
Set a single environment variable:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set a single variable
sandbox.env.set("API_KEY", "sk-prod-xyz")
print("API_KEY set")
# Verify it's set
api_key = sandbox.env.get("API_KEY")
print(f"API_KEY value: {api_key}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set a single variable
await sandbox.env.set('API_KEY', 'sk-prod-xyz');
console.log('API_KEY set');
// Verify it's set
const apiKey = await sandbox.env.get('API_KEY');
console.log(`API_KEY value: ${apiKey}`);
await sandbox.kill();
```
## Set Multiple Variables
Set multiple environment variables at once:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set multiple variables (replaces all existing)
sandbox.env.set_all({
"API_KEY": "sk-prod-xyz",
"DATABASE_URL": "postgres://localhost/db",
"NODE_ENV": "production",
"DEBUG": "false"
})
# Verify all are set
env = sandbox.env.get_all()
print(f"Set {len(env)} variables")
for key in ["API_KEY", "DATABASE_URL", "NODE_ENV", "DEBUG"]:
print(f" {key}: {env.get(key, 'not set')}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set multiple variables (replaces all existing)
await sandbox.env.setAll({
API_KEY: 'sk-prod-xyz',
DATABASE_URL: 'postgres://localhost/db',
NODE_ENV: 'production',
DEBUG: 'false'
});
// Verify all are set
const env = await sandbox.env.getAll();
console.log(`Set ${Object.keys(env).length} variables`);
for (const key of ['API_KEY', 'DATABASE_URL', 'NODE_ENV', 'DEBUG']) {
console.log(` ${key}: ${env[key] || 'not set'}`);
}
await sandbox.kill();
```
## Replace All Variables
Replace all environment variables (removes existing ones):
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Get current variables
current_env = sandbox.env.get_all()
print(f"Current variables: {len(current_env)}")
# Replace all with new set
sandbox.env.set_all({
"API_KEY": "sk-new-key",
"DATABASE_URL": "postgres://new-host/db"
})
# Verify replacement
new_env = sandbox.env.get_all()
print(f"New variables: {len(new_env)}")
print(f"Variables: {list(new_env.keys())}")
# Note: System variables like PATH may still exist
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Get current variables
const currentEnv = await sandbox.env.getAll();
console.log(`Current variables: ${Object.keys(currentEnv).length}`);
// Replace all with new set
await sandbox.env.setAll({
API_KEY: 'sk-new-key',
DATABASE_URL: 'postgres://new-host/db'
});
// Verify replacement
const newEnv = await sandbox.env.getAll();
console.log(`New variables: ${Object.keys(newEnv).length}`);
console.log(`Variables: ${Object.keys(newEnv)}`);
// Note: System variables like PATH may still exist
await sandbox.kill();
```
## Use in Code Execution
Set variables and use them in code:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set environment variables
sandbox.env.set_all({
"API_KEY": "sk-123",
"DATABASE_URL": "postgres://localhost/mydb",
"DEBUG": "true"
})
# Use in code execution
result = sandbox.run_code('''
import os
print(f"API key: {os.getenv('API_KEY')}")
print(f"Database: {os.getenv('DATABASE_URL')}")
print(f"Debug mode: {os.getenv('DEBUG')}")
''')
print(result.stdout)
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set environment variables
await sandbox.env.setAll({
API_KEY: 'sk-123',
DATABASE_URL: 'postgres://localhost/mydb',
DEBUG: 'true'
});
// Use in code execution
const result = await sandbox.runCode(`
import os
print(f"API key: {os.getenv('API_KEY')}")
print(f"Database: {os.getenv('DATABASE_URL')}")
print(f"Debug mode: {os.getenv('DEBUG')}")
`);
console.log(result.stdout);
await sandbox.kill();
```
## Use in Commands
Set variables and use them in shell commands:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set environment variables
sandbox.env.set_all({
"API_KEY": "sk-123",
"NODE_ENV": "production"
})
# Use in commands
result = sandbox.commands.run('echo $API_KEY')
print(f"Command output: {result.stdout}")
result = sandbox.commands.run('echo $NODE_ENV')
print(f"Command output: {result.stdout}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set environment variables
await sandbox.env.setAll({
API_KEY: 'sk-123',
NODE_ENV: 'production'
});
// Use in commands
let result = await sandbox.commands.run('echo $API_KEY');
console.log(`Command output: ${result.stdout}`);
result = await sandbox.commands.run('echo $NODE_ENV');
console.log(`Command output: ${result.stdout}`);
await sandbox.kill();
```
## Complete Example
Here's a complete example showing environment variable setup:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Configure application environment
print("🔧 Setting up environment...")
sandbox.env.set_all({
"API_KEY": "sk-prod-xyz123",
"DATABASE_URL": "postgres://localhost/production",
"REDIS_URL": "redis://localhost:6379",
"NODE_ENV": "production",
"DEBUG": "false",
"LOG_LEVEL": "info"
})
# Verify setup
env = sandbox.env.get_all()
print(f"\n✅ Environment configured with {len(env)} variables")
# Use in application code
print("\n💻 Testing in code execution...")
result = sandbox.run_code('''
import os
config = {
"api_key": os.getenv("API_KEY", "not set"),
"database": os.getenv("DATABASE_URL", "not set"),
"redis": os.getenv("REDIS_URL", "not set"),
"node_env": os.getenv("NODE_ENV", "development"),
"debug": os.getenv("DEBUG", "false"),
"log_level": os.getenv("LOG_LEVEL", "debug")
}
for key, value in config.items():
if 'key' in key.lower():
print(f"{key}: {value[:10]}...")
else:
print(f"{key}: {value}")
''')
print(result.stdout)
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Configure application environment
console.log('🔧 Setting up environment...');
await sandbox.env.setAll({
API_KEY: 'sk-prod-xyz123',
DATABASE_URL: 'postgres://localhost/production',
REDIS_URL: 'redis://localhost:6379',
NODE_ENV: 'production',
DEBUG: 'false',
LOG_LEVEL: 'info'
});
// Verify setup
const env = await sandbox.env.getAll();
console.log(`\n✅ Environment configured with ${Object.keys(env).length} variables`);
// Use in application code
console.log('\n💻 Testing in code execution...');
const result = await sandbox.runCode(`
import os
config = {
"api_key": os.getenv("API_KEY", "not set"),
"database": os.getenv("DATABASE_URL", "not set"),
"redis": os.getenv("REDIS_URL", "not set"),
"node_env": os.getenv("NODE_ENV", "development"),
"debug": os.getenv("DEBUG", "false"),
"log_level": os.getenv("LOG_LEVEL", "debug")
}
for key, value in config.items():
if 'key' in key.lower():
print(f"{key}: {value[:10]}...")
else:
print(f"{key}: {value}")
`);
console.log(result.stdout);
await sandbox.kill();
```
## Best Practices
Use `env.set(key, value)` for setting individual variables. This merges with existing variables.
`set_all()` replaces ALL variables. Only use when you want to completely replace the environment.
For setting multiple variables while preserving existing ones, use [Updating Environment Variables](/core-concepts/environment/updating) instead.
Set environment variables before running code or commands that need them.
Always verify variables are set correctly using `get()` or `get_all()` after setting.
## Related
* **[Getting Environment Variables](/core-concepts/environment/getting)** - Retrieve environment variables
* **[Updating Environment Variables](/core-concepts/environment/updating)** - Update variables without replacing
* **SDK**: [sandbox.env.set()](/sdk/python/environment-variables#set) - Python SDK method
* **API**: [PUT /env](/api/vm-agent/set-env) - VM Agent API endpoint
* [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI
## Next Steps
* Learn about [Getting Environment Variables](/core-concepts/environment/getting) to retrieve variables
* Explore [Updating Environment Variables](/core-concepts/environment/updating) to merge with existing variables
* Review [Clearing Environment Variables](/core-concepts/environment/clearing) to remove variables
# Updating
Source: https://docs.hopx.ai/core-concepts/environment/updating
Update and merge environment variables without replacing existing ones in HopX sandboxes. Incrementally update environment configuration, add new variables, or modify existing ones without clearing the entire environment. Essential for dynamic configuration management. Includes Python and JavaScript SDK examples and REST API endpoints.
Update environment variables by merging new values with existing ones. This preserves existing variables while adding or updating specific ones.
## Overview
Updating environment variables is ideal for:
* Adding new variables without removing existing ones
* Updating specific variables while preserving others
* Incrementally building environment configuration
* Modifying configuration without full replacement
`update()` merges new variables with existing ones. Existing variables not specified in the update are preserved. This is safer than `set_all()` which replaces everything.
## Update Single Variable
Update a single environment variable:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set initial variables
sandbox.env.set_all({
"API_KEY": "sk-123",
"DEBUG": "true"
})
# Update a single variable
sandbox.env.update({"DEBUG": "false"})
# Verify update
env = sandbox.env.get_all()
print(f"API_KEY: {env.get('API_KEY')}") # Still "sk-123"
print(f"DEBUG: {env.get('DEBUG')}") # Now "false"
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set initial variables
await sandbox.env.setAll({
API_KEY: 'sk-123',
DEBUG: 'true'
});
// Update a single variable
await sandbox.env.update({ DEBUG: 'false' });
// Verify update
const env = await sandbox.env.getAll();
console.log(`API_KEY: ${env.API_KEY}`); // Still "sk-123"
console.log(`DEBUG: ${env.DEBUG}`); // Now "false"
await sandbox.kill();
```
## Update Multiple Variables
Update multiple variables at once:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set initial configuration
sandbox.env.set_all({
"API_KEY": "sk-123",
"DATABASE_URL": "postgres://localhost/db"
})
# Update multiple variables
sandbox.env.update({
"NODE_ENV": "production",
"DEBUG": "false",
"LOG_LEVEL": "info"
})
# Verify all variables
env = sandbox.env.get_all()
print("All environment variables:")
for key in ["API_KEY", "DATABASE_URL", "NODE_ENV", "DEBUG", "LOG_LEVEL"]:
print(f" {key}: {env.get(key, 'not set')}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set initial configuration
await sandbox.env.setAll({
API_KEY: 'sk-123',
DATABASE_URL: 'postgres://localhost/db'
});
// Update multiple variables
await sandbox.env.update({
NODE_ENV: 'production',
DEBUG: 'false',
LOG_LEVEL: 'info'
});
// Verify all variables
const env = await sandbox.env.getAll();
console.log('All environment variables:');
for (const key of ['API_KEY', 'DATABASE_URL', 'NODE_ENV', 'DEBUG', 'LOG_LEVEL']) {
console.log(` ${key}: ${env[key] || 'not set'}`);
}
await sandbox.kill();
```
## Incremental Configuration
Build environment configuration incrementally:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Step 1: Set base configuration
sandbox.env.set_all({
"NODE_ENV": "production"
})
# Step 2: Add API configuration
sandbox.env.update({
"API_KEY": "sk-prod-xyz",
"API_URL": "https://api.example.com"
})
# Step 3: Add database configuration
sandbox.env.update({
"DATABASE_URL": "postgres://localhost/prod",
"DB_POOL_SIZE": "10"
})
# Step 4: Add logging configuration
sandbox.env.update({
"LOG_LEVEL": "info",
"LOG_FORMAT": "json"
})
# Verify final configuration
env = sandbox.env.get_all()
print(f"Final configuration: {len(env)} variables")
for key in sorted(env.keys()):
if key not in ['PATH', 'HOME', 'USER', 'SHELL']: # Skip system vars
print(f" {key}: {env[key]}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Step 1: Set base configuration
await sandbox.env.setAll({
NODE_ENV: 'production'
});
// Step 2: Add API configuration
await sandbox.env.update({
API_KEY: 'sk-prod-xyz',
API_URL: 'https://api.example.com'
});
// Step 3: Add database configuration
await sandbox.env.update({
DATABASE_URL: 'postgres://localhost/prod',
DB_POOL_SIZE: '10'
});
// Step 4: Add logging configuration
await sandbox.env.update({
LOG_LEVEL: 'info',
LOG_FORMAT: 'json'
});
// Verify final configuration
const env = await sandbox.env.getAll();
console.log(`Final configuration: ${Object.keys(env).length} variables`);
for (const key of Object.keys(env).sort()) {
if (!['PATH', 'HOME', 'USER', 'SHELL'].includes(key)) { // Skip system vars
console.log(` ${key}: ${env[key]}`);
}
}
await sandbox.kill();
```
## Override Existing Variables
Update existing variables with new values:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set initial values
sandbox.env.set_all({
"API_KEY": "sk-dev-123",
"DEBUG": "true",
"LOG_LEVEL": "debug"
})
# Override with production values
sandbox.env.update({
"API_KEY": "sk-prod-xyz",
"DEBUG": "false",
"LOG_LEVEL": "info"
})
# Verify overrides
env = sandbox.env.get_all()
print(f"API_KEY: {env.get('API_KEY')}") # "sk-prod-xyz"
print(f"DEBUG: {env.get('DEBUG')}") # "false"
print(f"LOG_LEVEL: {env.get('LOG_LEVEL')}") # "info"
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set initial values
await sandbox.env.setAll({
API_KEY: 'sk-dev-123',
DEBUG: 'true',
LOG_LEVEL: 'debug'
});
// Override with production values
await sandbox.env.update({
API_KEY: 'sk-prod-xyz',
DEBUG: 'false',
LOG_LEVEL: 'info'
});
// Verify overrides
const env = await sandbox.env.getAll();
console.log(`API_KEY: ${env.API_KEY}`); // "sk-prod-xyz"
console.log(`DEBUG: ${env.DEBUG}`); // "false"
console.log(`LOG_LEVEL: ${env.LOG_LEVEL}`); // "info"
await sandbox.kill();
```
## Complete Example
Here's a complete example showing incremental environment setup:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Start with base configuration
print("🔧 Setting up environment incrementally...\n")
# Step 1: Base environment
sandbox.env.set_all({"NODE_ENV": "production"})
print("✅ Step 1: Base environment set")
# Step 2: API configuration
sandbox.env.update({
"API_KEY": "sk-prod-xyz",
"API_URL": "https://api.example.com",
"API_TIMEOUT": "30"
})
print("✅ Step 2: API configuration added")
# Step 3: Database configuration
sandbox.env.update({
"DATABASE_URL": "postgres://localhost/prod",
"DB_POOL_SIZE": "10",
"DB_TIMEOUT": "5"
})
print("✅ Step 3: Database configuration added")
# Step 4: Feature flags
sandbox.env.update({
"FEATURE_NEW_UI": "true",
"FEATURE_ANALYTICS": "true",
"FEATURE_BETA": "false"
})
print("✅ Step 4: Feature flags added")
# Step 5: Update existing variable
sandbox.env.update({"NODE_ENV": "staging"})
print("✅ Step 5: NODE_ENV updated to staging")
# Final verification
env = sandbox.env.get_all()
custom_vars = {k: v for k, v in env.items()
if k not in ['PATH', 'HOME', 'USER', 'SHELL', 'PWD']}
print(f"\n📋 Final environment ({len(custom_vars)} custom variables):")
for key, value in sorted(custom_vars.items()):
if any(sensitive in key.upper() for sensitive in ['KEY', 'SECRET', 'PASSWORD']):
print(f" {key}=***MASKED***")
else:
print(f" {key}={value}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start with base configuration
console.log('🔧 Setting up environment incrementally...\n');
// Step 1: Base environment
await sandbox.env.setAll({ NODE_ENV: 'production' });
console.log('✅ Step 1: Base environment set');
// Step 2: API configuration
await sandbox.env.update({
API_KEY: 'sk-prod-xyz',
API_URL: 'https://api.example.com',
API_TIMEOUT: '30'
});
console.log('✅ Step 2: API configuration added');
// Step 3: Database configuration
await sandbox.env.update({
DATABASE_URL: 'postgres://localhost/prod',
DB_POOL_SIZE: '10',
DB_TIMEOUT: '5'
});
console.log('✅ Step 3: Database configuration added');
// Step 4: Feature flags
await sandbox.env.update({
FEATURE_NEW_UI: 'true',
FEATURE_ANALYTICS: 'true',
FEATURE_BETA: 'false'
});
console.log('✅ Step 4: Feature flags added');
// Step 5: Update existing variable
await sandbox.env.update({ NODE_ENV: 'staging' });
console.log('✅ Step 5: NODE_ENV updated to staging');
// Final verification
const env = await sandbox.env.getAll();
const systemVars = new Set(['PATH', 'HOME', 'USER', 'SHELL', 'PWD']);
const customVars = Object.fromEntries(
Object.entries(env).filter(([k]) => !systemVars.has(k))
);
console.log(`\n📋 Final environment (${Object.keys(customVars).length} custom variables):`);
for (const [key, value] of Object.entries(customVars).sort()) {
const isSensitive = ['KEY', 'SECRET', 'PASSWORD'].some(
s => key.toUpperCase().includes(s)
);
if (isSensitive) {
console.log(` ${key}=***MASKED***`);
} else {
console.log(` ${key}=${value}`);
}
}
await sandbox.kill();
```
## Best Practices
Prefer `update()` over `set_all()` to preserve existing variables unless you want to replace everything.
Build environment configuration incrementally by updating variables in logical groups.
Use `update()` to override existing variables with new values without affecting others.
Update related variables together (e.g., all API config, all database config) for better organization.
Always verify variables are updated correctly using `get_all()` after updates.
## Related
* **[Getting Environment Variables](/core-concepts/environment/getting)** - Retrieve environment variables
* **[Setting Environment Variables](/core-concepts/environment/setting)** - Set or replace variables
* **SDK**: [sandbox.env.update()](/sdk/python/environment-variables#update) - Python SDK method
* **API**: [PATCH /env](/api/vm-agent/update-env) - VM Agent API endpoint
* [CLI Environment Variables](/cli/commands/env) - Environment variables from CLI
## Next Steps
* Learn about [Getting Environment Variables](/core-concepts/environment/getting) to retrieve variables
* Explore [Setting Environment Variables](/core-concepts/environment/setting) to replace all variables
* Review [Clearing Environment Variables](/core-concepts/environment/clearing) to remove variables
# Downloading
Source: https://docs.hopx.ai/core-concepts/filesystem/downloading
Download files from sandboxes to your local filesystem. Retrieve files from HopX sandboxes to your local machine for further processing, analysis, or storage. Learn how to download single files or bulk download multiple files using Python and JavaScript SDKs or REST API. Includes examples for file downloads and progress tracking.
Download files from sandboxes to your local filesystem. This is useful for retrieving generated outputs, results, plots, or any files created in your sandbox.
## Overview
File downloading is essential for:
* Retrieving generated outputs and results
* Saving plots and visualizations
* Downloading processed data files
* Archiving sandbox contents
Download supports both text and binary files. Large files may take longer to download - set appropriate timeouts for large transfers.
## Basic Download
Download a file from sandbox to local:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Create a file in sandbox
sandbox.files.write('/workspace/output.txt', 'Hello from sandbox!')
# Download to local filesystem
sandbox.files.download('/workspace/output.txt', './downloaded_output.txt')
print("File downloaded successfully")
# Verify download
with open('./downloaded_output.txt', 'r') as f:
content = f.read()
print(f"Downloaded content: {content}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import * as fs from 'fs';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Create a file in sandbox
await sandbox.files.write('/workspace/output.txt', 'Hello from sandbox!');
// Download to local filesystem
const content = await sandbox.files.download('/workspace/output.txt');
fs.writeFileSync('./downloaded_output.txt', content);
console.log('File downloaded successfully');
// Verify download
const downloadedContent = fs.readFileSync('./downloaded_output.txt', 'utf-8');
console.log(`Downloaded content: ${downloadedContent}`);
await sandbox.kill();
```
## Download with Timeout
Set timeout for large file downloads:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Generate a large file
sandbox.run_code('''
with open('/workspace/large_data.txt', 'w') as f:
f.write('x' * 1000000) # 1MB
''')
# Download with extended timeout
sandbox.files.download('/workspace/large_data.txt', './large_data.txt', timeout=300)
print("Large file downloaded")
# Verify
import os
file_size = os.path.getsize('./large_data.txt') / 1024 / 1024
print(f"Downloaded file size: {file_size:.2f} MB")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import * as fs from 'fs';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Generate a large file
await sandbox.runCode(`
with open('/workspace/large_data.txt', 'w') as f:
f.write('x' * 1000000) # 1MB
`);
// Download
const content = await sandbox.files.download('/workspace/large_data.txt');
fs.writeFileSync('./large_data.txt', content);
console.log('Large file downloaded');
// Verify
const stats = fs.statSync('./large_data.txt');
const fileSize = stats.size / 1024 / 1024;
console.log(`Downloaded file size: ${fileSize.toFixed(2)} MB`);
await sandbox.kill();
```
## Download Binary Files
Download binary files (images, PDFs, etc.):
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Generate a plot
sandbox.run_code('''
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.savefig('/workspace/plot.png')
''')
# Download the image
sandbox.files.download('/workspace/plot.png', './local_plot.png')
print("Plot downloaded")
# Verify it's a valid image
with open('./local_plot.png', 'rb') as f:
header = f.read(8)
print(f"PNG header: {header[:8]}") # Should start with PNG signature
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import * as fs from 'fs';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Generate a plot
await sandbox.runCode(`
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.savefig('/workspace/plot.png')
`);
// Download the image
const imageData = await sandbox.files.download('/workspace/plot.png');
fs.writeFileSync('./local_plot.png', imageData);
console.log('Plot downloaded');
// Verify it's a valid image
const buffer = fs.readFileSync('./local_plot.png');
console.log(`PNG header: ${buffer.slice(0, 8)}`); // Should start with PNG signature
await sandbox.kill();
```
## Download Multiple Files
Download multiple files:
```python theme={null}
from hopx_ai import Sandbox
import os
sandbox = Sandbox.create(template="code-interpreter")
# Generate multiple files
sandbox.run_code('''
import json
import matplotlib.pyplot as plt
# Create data file
with open('/workspace/data.json', 'w') as f:
json.dump({"values": [1, 2, 3]}, f)
# Create plot
plt.plot([1, 2, 3])
plt.savefig('/workspace/plot.png')
# Create text file
with open('/workspace/readme.txt', 'w') as f:
f.write("Generated files")
''')
# Download all files
files_to_download = [
('/workspace/data.json', './downloaded_data.json'),
('/workspace/plot.png', './downloaded_plot.png'),
('/workspace/readme.txt', './downloaded_readme.txt')
]
print("📥 Downloading files...")
for remote_path, local_path in files_to_download:
try:
sandbox.files.download(remote_path, local_path)
file_size = os.path.getsize(local_path) / 1024
print(f" ✅ {remote_path} → {local_path} ({file_size:.2f} KB)")
except Exception as e:
print(f" ❌ Failed to download {remote_path}: {e}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import * as fs from 'fs';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Generate multiple files
await sandbox.runCode(`
import json
import matplotlib.pyplot as plt
# Create data file
with open('/workspace/data.json', 'w') as f:
json.dump({"values": [1, 2, 3]}, f)
# Create plot
plt.plot([1, 2, 3])
plt.savefig('/workspace/plot.png')
# Create text file
with open('/workspace/readme.txt', 'w') as f:
f.write("Generated files")
`);
// Download all files
const filesToDownload = [
['/workspace/data.json', './downloaded_data.json'],
['/workspace/plot.png', './downloaded_plot.png'],
['/workspace/readme.txt', './downloaded_readme.txt']
];
console.log('📥 Downloading files...');
for (const [remotePath, localPath] of filesToDownload) {
try {
const content = await sandbox.files.download(remotePath);
fs.writeFileSync(localPath, content);
const stats = fs.statSync(localPath);
const fileSize = stats.size / 1024;
console.log(` ✅ ${remotePath} → ${localPath} (${fileSize.toFixed(2)} KB)`);
} catch (error) {
console.error(` ❌ Failed to download ${remotePath}: ${error.message}`);
}
}
await sandbox.kill();
```
## Download All Files in Directory
Download all files from a directory:
```python theme={null}
from hopx_ai import Sandbox
import os
sandbox = Sandbox.create(template="code-interpreter")
# Create multiple files
for i in range(3):
sandbox.files.write(f'/workspace/file_{i}.txt', f'Content {i}')
# Create local directory
os.makedirs('./downloads', exist_ok=True)
# Download all files
files = sandbox.files.list('/workspace')
print("📥 Downloading all files...")
for file in files:
if file.is_file:
local_path = f'./downloads/{file.name}'
try:
sandbox.files.download(file.path, local_path)
print(f" ✅ {file.name} ({file.size_kb:.2f} KB)")
except Exception as e:
print(f" ❌ Failed to download {file.name}: {e}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import * as fs from 'fs';
import * as path from 'path';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Create multiple files
for (let i = 0; i < 3; i++) {
await sandbox.files.write(`/workspace/file_${i}.txt`, `Content ${i}`);
}
// Create local directory
if (!fs.existsSync('./downloads')) {
fs.mkdirSync('./downloads');
}
// Download all files
const files = await sandbox.files.list('/workspace');
console.log('📥 Downloading all files...');
for (const file of files) {
if (file.isFile) {
const localPath = `./downloads/${file.name}`;
try {
const content = await sandbox.files.download(file.path);
fs.writeFileSync(localPath, content);
console.log(` ✅ ${file.name} (${(file.size / 1024).toFixed(2)} KB)`);
} catch (error) {
console.error(` ❌ Failed to download ${file.name}: ${error.message}`);
}
}
}
await sandbox.kill();
```
## Error Handling
Handle download errors:
```python theme={null}
from hopx_ai import Sandbox
from hopx_ai.errors import FileNotFoundError, FileOperationError
sandbox = Sandbox.create(template="code-interpreter")
try:
# Try to download non-existent file
sandbox.files.download('/workspace/nonexistent.txt', './downloaded.txt')
except FileNotFoundError:
print("File not found in sandbox")
except FileOperationError as e:
print(f"Download failed: {e}")
# Check if file exists first
if sandbox.files.exists('/workspace/data.txt'):
sandbox.files.download('/workspace/data.txt', './data.txt')
print("Download successful")
else:
print("File does not exist")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import { FileNotFoundError, FileOperationError } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
try {
// Try to download non-existent file
await sandbox.files.download('/workspace/nonexistent.txt');
} catch (error) {
if (error instanceof FileNotFoundError) {
console.error('File not found in sandbox');
} else if (error instanceof FileOperationError) {
console.error(`Download failed: ${error.message}`);
}
}
// Check if file exists first
const exists = await sandbox.files.exists('/workspace/data.txt');
if (exists) {
const content = await sandbox.files.download('/workspace/data.txt');
fs.writeFileSync('./data.txt', content);
console.log('Download successful');
} else {
console.log('File does not exist');
}
await sandbox.kill();
```
## Complete Example
Here's a complete download workflow:
```python theme={null}
from hopx_ai import Sandbox
import os
sandbox = Sandbox.create(template="code-interpreter")
# Generate outputs
sandbox.run_code('''
import json
import matplotlib.pyplot as plt
import pandas as pd
# Generate JSON data
data = {"results": [1, 2, 3, 4, 5]}
with open('/workspace/results.json', 'w') as f:
json.dump(data, f, indent=2)
# Generate plot
plt.figure(figsize=(10, 6))
plt.plot([1, 2, 3, 4, 5], [1, 4, 9, 16, 25])
plt.title("Results Visualization")
plt.savefig('/workspace/results.png')
# Generate CSV
df = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
df.to_csv('/workspace/data.csv', index=False)
''')
# Create local output directory
os.makedirs('./outputs', exist_ok=True)
# Download all generated files
print("📥 Downloading generated outputs...")
files = sandbox.files.list('/workspace')
total_size = 0
for file in files:
if file.is_file and file.name in ['results.json', 'results.png', 'data.csv']:
local_path = f'./outputs/{file.name}'
try:
sandbox.files.download(file.path, local_path, timeout=120)
total_size += file.size
print(f" ✅ {file.name} ({file.size_kb:.2f} KB)")
except Exception as e:
print(f" ❌ Failed to download {file.name}: {e}")
print(f"\n✅ Total downloaded: {total_size / 1024:.2f} KB")
print(f"📁 Files saved to: ./outputs/")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import * as fs from 'fs';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Generate outputs
await sandbox.runCode(`
import json
import matplotlib.pyplot as plt
import pandas as pd
# Generate JSON data
data = {"results": [1, 2, 3, 4, 5]}
with open('/workspace/results.json', 'w') as f:
json.dump(data, f, indent=2)
# Generate plot
plt.figure(figsize=(10, 6))
plt.plot([1, 2, 3, 4, 5], [1, 4, 9, 16, 25])
plt.title("Results Visualization")
plt.savefig('/workspace/results.png')
# Generate CSV
df = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
df.to_csv('/workspace/data.csv', index=False)
`);
// Create local output directory
if (!fs.existsSync('./outputs')) {
fs.mkdirSync('./outputs');
}
// Download all generated files
console.log('📥 Downloading generated outputs...');
const files = await sandbox.files.list('/workspace');
let totalSize = 0;
for (const file of files) {
if (file.isFile && ['results.json', 'results.png', 'data.csv'].includes(file.name)) {
const localPath = `./outputs/${file.name}`;
try {
const content = await sandbox.files.download(file.path);
fs.writeFileSync(localPath, content);
totalSize += file.size;
console.log(` ✅ ${file.name} (${(file.size / 1024).toFixed(2)} KB)`);
} catch (error) {
console.error(` ❌ Failed to download ${file.name}: ${error.message}`);
}
}
}
console.log(`\n✅ Total downloaded: ${(totalSize / 1024).toFixed(2)} KB`);
console.log('📁 Files saved to: ./outputs/');
await sandbox.kill();
```
## Best Practices
Use `files.exists()` before downloading to avoid errors, or handle `FileNotFoundError` appropriately.
For large files, set extended timeouts (60+ seconds) to avoid connection timeouts.
Create local directories before downloading to ensure files are saved correctly.
Wrap downloads in try/catch blocks to handle network errors, file not found, etc.
After downloading, verify files exist locally and check their sizes to ensure successful transfer.
## Related
* **[Reading Files](/core-concepts/filesystem/reading)** - Read file contents
* **[Uploading Files](/core-concepts/filesystem/uploading)** - Upload files to sandboxes
* **[Listing Files](/core-concepts/filesystem/listing)** - List directory contents
* **SDK**: [sandbox.files.download()](/sdk/python/files#download) - Python SDK method
* [CLI File Operations](/cli/commands/files) - File operations from CLI
## Next Steps
* Learn about [Uploading Files](/core-concepts/filesystem/uploading) to transfer files to sandboxes
* Explore [Reading Files](/core-concepts/filesystem/reading) to access file contents
* Review [Watching Files](/core-concepts/filesystem/watching) for real-time file monitoring
# Filesystem
Source: https://docs.hopx.ai/core-concepts/filesystem/index
Complete guide to file operations in HopX sandboxes - reading, writing, listing, uploading, downloading, and watching files. Work with files in sandboxes using comprehensive file operations, from basic read/write to advanced file watching and bulk transfers. Includes Python and JavaScript SDK examples and REST API endpoints for all file operations.
Work with files in HopX sandboxes using comprehensive file operations. This hub covers all filesystem operations, from basic read/write to advanced file watching and bulk transfers.
## Related
* [CLI File Operations](/cli/commands/files) - File operations from CLI
## What You'll Learn
* How to read and write files in sandboxes
* How to list directories and navigate the filesystem
* How to upload and download files to/from sandboxes
* How to watch files for changes
* How to manage file permissions and metadata
## File Operations Overview
| Operation | SDK Method | API Endpoint |
| -------------------------------------------------------- | -------------------------- | ------------------------ |
| **[Reading](/core-concepts/filesystem/reading)** | `sandbox.files.read()` | `GET /files/read` |
| **[Writing](/core-concepts/filesystem/writing)** | `sandbox.files.write()` | `POST /files/write` |
| **[Listing](/core-concepts/filesystem/listing)** | `sandbox.files.list()` | `GET /files/list` |
| **[Uploading](/core-concepts/filesystem/uploading)** | `sandbox.files.upload()` | `POST /files/upload` |
| **[Downloading](/core-concepts/filesystem/downloading)** | `sandbox.files.download()` | `GET /files/download` |
| **[Watching](/core-concepts/filesystem/watching)** | `sandbox.files.watch()` | `WebSocket /files/watch` |
## Core Concepts
### Reading Files
Read file contents from sandboxes as text or binary data.
* **[Reading Files](/core-concepts/filesystem/reading)** - Read file contents
* **SDK**: [Python: sandbox.files.read()](/sdk/python/files#read) | [JavaScript: sandbox.files.read()](/sdk/javascript/files#read)
* **API**: [GET /files/read](/api/vm-agent/read-file)
### Writing Files
Write text or binary data to files in sandboxes.
* **[Writing Files](/core-concepts/filesystem/writing)** - Write file contents
* **SDK**: [Python: sandbox.files.write()](/sdk/python/files#write) | [JavaScript: sandbox.files.write()](/sdk/javascript/files#write)
* **API**: [POST /files/write](/api/vm-agent/write-file)
### Listing Files
List directory contents and navigate the filesystem.
* **[Listing Files](/core-concepts/filesystem/listing)** - List directories and files
* **SDK**: [Python: sandbox.files.list()](/sdk/python/files#list) | [JavaScript: sandbox.files.list()](/sdk/javascript/files#list)
* **API**: [GET /files/list](/api/vm-agent/list-files)
### Uploading Files
Upload files from your local machine to sandboxes.
* **[Uploading Files](/core-concepts/filesystem/uploading)** - Upload files to sandboxes
* **SDK**: [Python: sandbox.files.upload()](/sdk/python/files#upload) | [JavaScript: sandbox.files.upload()](/sdk/javascript/files#upload)
* **API**: [POST /files/upload](/api/vm-agent/upload-file)
### Downloading Files
Download files from sandboxes to your local machine.
* **[Downloading Files](/core-concepts/filesystem/downloading)** - Download files from sandboxes
* **SDK**: [Python: sandbox.files.download()](/sdk/python/files#download) | [JavaScript: sandbox.files.download()](/sdk/javascript/files#download)
* **API**: [GET /files/download](/api/vm-agent/download-file)
### Watching Files
Watch files and directories for changes in real-time.
* **[Watching Files](/core-concepts/filesystem/watching)** - Monitor file changes
* **SDK**: [Python: sandbox.files.watch()](/sdk/python/files#watch) | [JavaScript: sandbox.files.watch()](/sdk/javascript/files#watch)
* **API**: [WebSocket /files/watch](/api/vm-agent/watch-file)
## SDK Reference
### Python SDK
Complete reference for Python file operations.
* **[Files Module](/sdk/python/files)** - Complete filesystem API
* `files.read()` - Read files
* `files.write()` - Write files
* `files.list()` - List directories
* `files.upload()` - Upload files
* `files.download()` - Download files
* `files.watch()` - Watch files
* `files.exists()` - Check existence
* `files.remove()` - Delete files
* `files.mkdir()` - Create directories
### JavaScript SDK
Complete reference for JavaScript/TypeScript file operations.
* **[Files Module](/sdk/javascript/files)** - Complete filesystem API
* `files.read()` - Read files
* `files.write()` - Write files
* `files.list()` - List directories
* `files.upload()` - Upload files
* `files.download()` - Download files
* `files.watch()` - Watch files
* `files.exists()` - Check existence
* `files.remove()` - Delete files
* `files.mkdir()` - Create directories
## API Reference
### VM Agent API
REST API endpoints for file operations.
* **[VM Agent API Overview](/api/vm-agent/overview)** - API overview
* **[Read File](/api/vm-agent/read-file)** - `GET /files/read` - Read file contents
* **[Write File](/api/vm-agent/write-file)** - `POST /files/write` - Write file contents
* **[List Files](/api/vm-agent/list-files)** - `GET /files/list` - List directory contents
* **[File Exists](/api/vm-agent/file-exists)** - `GET /files/exists` - Check file existence
* **[Remove File](/api/vm-agent/remove-file)** - `DELETE /files/remove` - Delete files
* **[Create Directory](/api/vm-agent/mkdir)** - `POST /files/mkdir` - Create directories
## Quick Start
If you're new to file operations, start here:
1. **[Reading Files](/core-concepts/filesystem/reading)** - Read your first file
2. **[Writing Files](/core-concepts/filesystem/writing)** - Write files to sandboxes
3. **[Listing Files](/core-concepts/filesystem/listing)** - Navigate directories
## Related Topics
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Execute code that works with files
* **[Sandboxes](/core-concepts/sandboxes/creating)** - Create sandboxes for file operations
* **[Commands](/core-concepts/commands/running)** - Run shell commands for file operations
* **[Environment Variables](/core-concepts/environment/getting)** - Configure file paths
## Next Steps
* Learn about [Code Execution](/core-concepts/code-execution/synchronous) to process files
* Explore [Commands](/core-concepts/commands/running) for shell-based file operations
* Review [Uploading Files](/core-concepts/filesystem/uploading) for bulk transfers
* Check out [Watching Files](/core-concepts/filesystem/watching) for real-time monitoring
# Listing
Source: https://docs.hopx.ai/core-concepts/filesystem/listing
List directory contents and browse the filesystem in HopX sandboxes. Navigate directories, view file metadata, filter files by name or pattern, and discover generated outputs. Learn how to list files and directories using Python and JavaScript SDKs or REST API. Includes examples for directory navigation and file discovery.
List directory contents to browse your sandbox filesystem. Get file metadata including size, permissions, and modification times.
## Overview
Directory listing is useful for:
* Browsing sandbox filesystem structure
* Finding files by name or pattern
* Checking file sizes and metadata
* Discovering generated outputs
You can list contents of allowed paths like `/workspace` and `/tmp`. Listing system directories may be restricted for security.
## Basic Listing
List files in a directory:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Create some files
sandbox.files.write('/workspace/file1.txt', 'Content 1')
sandbox.files.write('/workspace/file2.txt', 'Content 2')
sandbox.files.mkdir('/workspace/subdir')
# List directory contents
files = sandbox.files.list('/workspace')
print(f"Found {len(files)} items")
for file in files:
if file.is_file:
print(f"📄 {file.name} ({file.size_kb:.2f} KB)")
else:
print(f"📁 {file.name}/")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Create some files
await sandbox.files.write('/workspace/file1.txt', 'Content 1');
await sandbox.files.write('/workspace/file2.txt', 'Content 2');
await sandbox.files.mkdir('/workspace/subdir');
// List directory contents
const files = await sandbox.files.list('/workspace');
console.log(`Found ${files.length} items`);
for (const file of files) {
if (file.isFile) {
console.log(`📄 ${file.name} (${(file.size / 1024).toFixed(2)} KB)`);
} else {
console.log(`📁 ${file.name}/`);
}
}
await sandbox.kill();
```
## File Information
Access detailed file information:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Create a file
sandbox.files.write('/workspace/data.txt', 'Some content')
# List and get file info
files = sandbox.files.list('/workspace')
for file in files:
if file.name == 'data.txt':
print(f"Name: {file.name}")
print(f"Path: {file.path}")
print(f"Size: {file.size} bytes")
print(f"Size (KB): {file.size_kb:.2f} KB")
print(f"Size (MB): {file.size_mb:.2f} MB")
print(f"Is file: {file.is_file}")
print(f"Is directory: {file.is_dir}")
print(f"Permissions: {file.permissions}")
print(f"Modified: {file.modified_time}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Create a file
await sandbox.files.write('/workspace/data.txt', 'Some content');
// List and get file info
const files = await sandbox.files.list('/workspace');
for (const file of files) {
if (file.name === 'data.txt') {
console.log(`Name: ${file.name}`);
console.log(`Path: ${file.path}`);
console.log(`Size: ${file.size} bytes`);
console.log(`Size (KB): ${(file.size / 1024).toFixed(2)} KB`);
console.log(`Size (MB): ${(file.size / 1024 / 1024).toFixed(2)} MB`);
console.log(`Is file: ${file.isFile}`);
console.log(`Is directory: ${file.isDirectory}`);
console.log(`Permissions: ${file.permissions}`);
console.log(`Modified: ${file.modifiedTime}`);
}
}
await sandbox.kill();
```
## Filtering Files
Filter files by type or pattern:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Create various files
sandbox.files.write('/workspace/script.py', 'print("Hello")')
sandbox.files.write('/workspace/data.json', '{"key": "value"}')
sandbox.files.write('/workspace/readme.txt', 'Documentation')
# List only Python files
files = sandbox.files.list('/workspace')
python_files = [f for f in files if f.is_file and f.name.endswith('.py')]
print(f"Python files: {len(python_files)}")
for f in python_files:
print(f" {f.name}")
# List only directories
directories = [f for f in files if f.is_dir]
print(f"\nDirectories: {len(directories)}")
for d in directories:
print(f" {d.name}/")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Create various files
await sandbox.files.write('/workspace/script.py', 'print("Hello")');
await sandbox.files.write('/workspace/data.json', '{"key": "value"}');
await sandbox.files.write('/workspace/readme.txt', 'Documentation');
// List only Python files
const files = await sandbox.files.list('/workspace');
const pythonFiles = files.filter(f => f.isFile && f.name.endsWith('.py'));
console.log(`Python files: ${pythonFiles.length}`);
for (const f of pythonFiles) {
console.log(` ${f.name}`);
}
// List only directories
const directories = files.filter(f => f.isDirectory);
console.log(`\nDirectories: ${directories.length}`);
for (const d of directories) {
console.log(` ${d.name}/`);
}
await sandbox.kill();
```
## Recursive Listing
List files recursively by traversing directories:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Create nested structure
sandbox.files.mkdir('/workspace/project')
sandbox.files.mkdir('/workspace/project/src')
sandbox.files.write('/workspace/project/src/main.py', 'print("Hello")')
sandbox.files.write('/workspace/project/README.md', '# Project')
def list_recursive(files, path='/workspace', indent=0):
"""Recursively list directory contents"""
items = sandbox.files.list(path)
for item in items:
prefix = " " * indent
if item.is_dir:
print(f"{prefix}📁 {item.name}/")
list_recursive(files, item.path, indent + 1)
else:
print(f"{prefix}📄 {item.name} ({item.size_kb:.2f} KB)")
print("Directory structure:")
list_recursive(sandbox.files.list('/workspace'))
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Create nested structure
await sandbox.files.mkdir('/workspace/project');
await sandbox.files.mkdir('/workspace/project/src');
await sandbox.files.write('/workspace/project/src/main.py', 'print("Hello")');
await sandbox.files.write('/workspace/project/README.md', '# Project');
async function listRecursive(path = '/workspace', indent = 0) {
const items = await sandbox.files.list(path);
for (const item of items) {
const prefix = ' '.repeat(indent);
if (item.isDirectory) {
console.log(`${prefix}📁 ${item.name}/`);
await listRecursive(item.path, indent + 1);
} else {
console.log(`${prefix}📄 ${item.name} (${(item.size / 1024).toFixed(2)} KB)`);
}
}
}
console.log('Directory structure:');
await listRecursive('/workspace');
await sandbox.kill();
```
## Sorting and Filtering
Sort files by size, name, or date:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Create files of different sizes
sandbox.files.write('/workspace/small.txt', 'small')
sandbox.files.write('/workspace/medium.txt', 'x' * 1000)
sandbox.files.write('/workspace/large.txt', 'x' * 10000)
# List and sort by size
files = sandbox.files.list('/workspace')
files_only = [f for f in files if f.is_file]
# Sort by size (largest first)
sorted_by_size = sorted(files_only, key=lambda f: f.size, reverse=True)
print("Files sorted by size:")
for f in sorted_by_size:
print(f" {f.name}: {f.size_kb:.2f} KB")
# Sort by name
sorted_by_name = sorted(files_only, key=lambda f: f.name)
print("\nFiles sorted by name:")
for f in sorted_by_name:
print(f" {f.name}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Create files of different sizes
await sandbox.files.write('/workspace/small.txt', 'small');
await sandbox.files.write('/workspace/medium.txt', 'x'.repeat(1000));
await sandbox.files.write('/workspace/large.txt', 'x'.repeat(10000));
// List and sort by size
const files = await sandbox.files.list('/workspace');
const filesOnly = files.filter(f => f.isFile);
// Sort by size (largest first)
const sortedBySize = filesOnly.sort((a, b) => b.size - a.size);
console.log('Files sorted by size:');
for (const f of sortedBySize) {
console.log(` ${f.name}: ${(f.size / 1024).toFixed(2)} KB`);
}
// Sort by name
const sortedByName = filesOnly.sort((a, b) => a.name.localeCompare(b.name));
console.log('\nFiles sorted by name:');
for (const f of sortedByName) {
console.log(` ${f.name}`);
}
await sandbox.kill();
```
## Complete Example
Here's a complete example showing directory listing:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Create a project structure
sandbox.files.mkdir('/workspace/myproject')
sandbox.files.mkdir('/workspace/myproject/src')
sandbox.files.mkdir('/workspace/myproject/tests')
sandbox.files.mkdir('/workspace/myproject/data')
# Create files
sandbox.files.write('/workspace/myproject/src/main.py', 'print("Hello")')
sandbox.files.write('/workspace/myproject/src/utils.py', 'def helper(): pass')
sandbox.files.write('/workspace/myproject/tests/test_main.py', 'def test(): pass')
sandbox.files.write('/workspace/myproject/data/input.csv', '1,2,3')
sandbox.files.write('/workspace/myproject/README.md', '# My Project')
# List and display structure
def display_tree(path, prefix=""):
files = sandbox.files.list(path)
files.sort(key=lambda f: (f.is_dir, f.name))
for i, file in enumerate(files):
is_last = i == len(files) - 1
current_prefix = "└── " if is_last else "├── "
print(f"{prefix}{current_prefix}{file.name}")
if file.is_dir:
next_prefix = prefix + (" " if is_last else "│ ")
display_tree(file.path, next_prefix)
print("Project structure:")
display_tree('/workspace/myproject')
# Summary
all_files = sandbox.files.list('/workspace/myproject')
total_size = sum(f.size for f in all_files if f.is_file)
print(f"\nTotal files: {len([f for f in all_files if f.is_file])}")
print(f"Total size: {total_size / 1024:.2f} KB")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Create a project structure
await sandbox.files.mkdir('/workspace/myproject');
await sandbox.files.mkdir('/workspace/myproject/src');
await sandbox.files.mkdir('/workspace/myproject/tests');
await sandbox.files.mkdir('/workspace/myproject/data');
// Create files
await sandbox.files.write('/workspace/myproject/src/main.py', 'print("Hello")');
await sandbox.files.write('/workspace/myproject/src/utils.py', 'def helper(): pass');
await sandbox.files.write('/workspace/myproject/tests/test_main.py', 'def test(): pass');
await sandbox.files.write('/workspace/myproject/data/input.csv', '1,2,3');
await sandbox.files.write('/workspace/myproject/README.md', '# My Project');
// List and display structure
async function displayTree(path, prefix = '') {
const files = await sandbox.files.list(path);
files.sort((a, b) => {
if (a.isDirectory !== b.isDirectory) {
return a.isDirectory ? -1 : 1;
}
return a.name.localeCompare(b.name);
});
for (let i = 0; i < files.length; i++) {
const file = files[i];
const isLast = i === files.length - 1;
const currentPrefix = isLast ? '└── ' : '├── ';
console.log(`${prefix}${currentPrefix}${file.name}`);
if (file.isDirectory) {
const nextPrefix = prefix + (isLast ? ' ' : '│ ');
await displayTree(file.path, nextPrefix);
}
}
}
console.log('Project structure:');
await displayTree('/workspace/myproject');
// Summary
const allFiles = await sandbox.files.list('/workspace/myproject');
const totalSize = allFiles.filter(f => f.isFile).reduce((sum, f) => sum + f.size, 0);
console.log(`\nTotal files: ${allFiles.filter(f => f.isFile).length}`);
console.log(`Total size: ${(totalSize / 1024).toFixed(2)} KB`);
await sandbox.kill();
```
## Best Practices
Use `files.exists()` before listing to avoid errors, or handle `FileNotFoundError` appropriately.
Use `is_file` and `is_dir` properties to filter files and directories.
Sort files by name, size, or date for better user experience.
For nested structures, implement recursive listing to show complete directory trees.
For directories with many files, consider pagination or filtering to avoid performance issues.
## Related
* **[Reading Files](/core-concepts/filesystem/reading)** - Read file contents
* **[Writing Files](/core-concepts/filesystem/writing)** - Write files to sandboxes
* **SDK**: [sandbox.files.list()](/sdk/python/files#list) - Python SDK method
* **API**: [GET /files/list](/api/vm-agent/list-files) - VM Agent API endpoint
* [CLI File Operations](/cli/commands/files) - File operations from CLI
## Next Steps
* Learn about [Reading Files](/core-concepts/filesystem/reading) to access file contents
* Explore [Writing Files](/core-concepts/filesystem/writing) to create files
* Review [Watching Files](/core-concepts/filesystem/watching) for real-time file monitoring
# Reading
Source: https://docs.hopx.ai/core-concepts/filesystem/reading
Read text and binary files from sandboxes. Learn how to read file contents from HopX sandboxes using Python and JavaScript SDKs or REST API. Includes examples for reading text files, binary files, handling encoding, and processing file contents in your applications.
Read files from your sandbox filesystem. HopX supports both text and binary file reading with automatic encoding handling.
## Overview
File reading is essential for:
* Accessing generated outputs from code execution
* Reading configuration files
* Processing data files
* Retrieving logs and results
Files can be read from allowed paths like `/workspace` and `/tmp`. Reading from system directories may be restricted for security.
## Reading Text Files
Read text files as strings:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Write a file first
sandbox.files.write('/workspace/data.txt', 'Hello, World!\nLine 2\nLine 3')
# Read the file
content = sandbox.files.read('/workspace/data.txt')
print(content)
# Output:
# Hello, World!
# Line 2
# Line 3
sandbox.kill()
```
**Expected Output:**
```
Hello, World!
Line 2
Line 3
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Write a file first
await sandbox.files.write('/workspace/data.txt', 'Hello, World!\nLine 2\nLine 3');
// Read the file
const content = await sandbox.files.read('/workspace/data.txt');
console.log(content);
// Output:
// Hello, World!
// Line 2
// Line 3
await sandbox.kill();
```
**Expected Output:**
```
Hello, World!
Line 2
Line 3
```
## Reading Binary Files
Read binary files (images, PDFs, etc.) as bytes:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Generate a plot and save it
sandbox.run_code('''
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.savefig('/workspace/plot.png')
''')
# Read the binary image file
image_data = sandbox.files.read_bytes('/workspace/plot.png')
print(f"Image size: {len(image_data)} bytes")
# Save to local file
with open('local_plot.png', 'wb') as f:
f.write(image_data)
sandbox.kill()
```
**Expected Output:**
```
Image size: 245760 bytes
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import * as fs from 'fs';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Generate a plot and save it
await sandbox.runCode(`
import matplotlib.pyplot as plt
plt.plot([1, 2, 3, 4])
plt.savefig('/workspace/plot.png')
`);
// Read the binary image file
const imageData = await sandbox.files.readBytes('/workspace/plot.png');
console.log(`Image size: ${imageData.length} bytes`);
// Save to local file
fs.writeFileSync('local_plot.png', imageData);
await sandbox.kill();
```
**Expected Output:**
```
Image size: 245760 bytes
```
## Reading Code Files
Read and execute code files:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Write a Python script
sandbox.files.write('/workspace/script.py', '''
def greet(name):
return f"Hello, {name}!"
print(greet("World"))
''')
# Read and execute
script_content = sandbox.files.read('/workspace/script.py')
result = sandbox.run_code(script_content, language='python')
print(result.stdout) # "Hello, World!"
sandbox.kill()
```
**Expected Output:**
```
Hello, World!
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Write a Python script
await sandbox.files.write('/workspace/script.py', `
def greet(name):
return f"Hello, {name}!"
print(greet("World"))
`);
// Read and execute
const scriptContent = await sandbox.files.read('/workspace/script.py');
const result = await sandbox.runCode(scriptContent, { language: 'python' });
console.log(result.stdout); // "Hello, World!"
await sandbox.kill();
```
**Expected Output:**
```
Hello, World!
```
## Reading Configuration Files
Read JSON, YAML, or other configuration files:
```python theme={null}
from hopx_ai import Sandbox
import json
sandbox = Sandbox.create(template="code-interpreter")
# Write a config file
sandbox.files.write('/workspace/config.json', '''
{
"api_key": "sk-123",
"debug": true,
"timeout": 30
}
''')
# Read and parse
config_content = sandbox.files.read('/workspace/config.json')
config = json.loads(config_content)
print(f"API key: {config['api_key']}")
print(f"Debug: {config['debug']}")
sandbox.kill()
```
**Expected Output:**
```
API key: sk-123
Debug: True
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Write a config file
await sandbox.files.write('/workspace/config.json', `
{
"api_key": "sk-123",
"debug": true,
"timeout": 30
}
`);
// Read and parse
const configContent = await sandbox.files.read('/workspace/config.json');
const config = JSON.parse(configContent);
console.log(`API key: ${config.api_key}`);
console.log(`Debug: ${config.debug}`);
await sandbox.kill();
```
**Expected Output:**
```
API key: sk-123
Debug: true
```
## Reading Large Files
For large files, consider using timeouts:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Read large file with custom timeout
try:
content = sandbox.files.read('/workspace/large_file.txt', timeout=120)
print(f"Read {len(content)} characters")
except Exception as e:
print(f"Error reading file: {e}")
sandbox.kill()
```
**Expected Output:**
```
Read 1000000 characters
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Read large file (timeout handled by HTTP client)
try {
const content = await sandbox.files.read('/workspace/large_file.txt');
console.log(`Read ${content.length} characters`);
} catch (error) {
console.error(`Error reading file: ${error.message}`);
}
await sandbox.kill();
```
**Expected Output:**
```
Read 1000000 characters
```
## Error Handling
Handle file reading errors:
```python theme={null}
from hopx_ai import Sandbox
from hopx_ai.errors import FileNotFoundError, FileOperationError
sandbox = Sandbox.create(template="code-interpreter")
try:
content = sandbox.files.read('/workspace/nonexistent.txt')
except FileNotFoundError:
print("File not found")
except FileOperationError as e:
print(f"File operation error: {e}")
# Check if file exists first
if sandbox.files.exists('/workspace/data.txt'):
content = sandbox.files.read('/workspace/data.txt')
print(content)
else:
print("File does not exist")
sandbox.kill()
```
**Expected Output:**
```
File not found
File does not exist
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import { FileNotFoundError, FileOperationError } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
try {
const content = await sandbox.files.read('/workspace/nonexistent.txt');
} catch (error) {
if (error instanceof FileNotFoundError) {
console.error('File not found');
} else if (error instanceof FileOperationError) {
console.error(`File operation error: ${error.message}`);
}
}
// Check if file exists first
const exists = await sandbox.files.exists('/workspace/data.txt');
if (exists) {
const content = await sandbox.files.read('/workspace/data.txt');
console.log(content);
} else {
console.log('File does not exist');
}
await sandbox.kill();
```
**Expected Output:**
```
File not found
File does not exist
```
## Reading Multiple Files
Read multiple files in a loop:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Create multiple files
for i in range(3):
sandbox.files.write(f'/workspace/file_{i}.txt', f'Content {i}')
# Read all files
files = sandbox.files.list('/workspace')
for file in files:
if file.is_file and file.name.endswith('.txt'):
content = sandbox.files.read(file.path)
print(f"{file.name}: {content}")
sandbox.kill()
```
**Expected Output:**
```
file_0.txt: Content 0
file_1.txt: Content 1
file_2.txt: Content 2
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Create multiple files
for (let i = 0; i < 3; i++) {
await sandbox.files.write(`/workspace/file_${i}.txt`, `Content ${i}`);
}
// Read all files
const files = await sandbox.files.list('/workspace');
for (const file of files) {
if (file.isFile && file.name.endsWith('.txt')) {
const content = await sandbox.files.read(file.path);
console.log(`${file.name}: ${content}`);
}
}
await sandbox.kill();
```
**Expected Output:**
```
file_0.txt: Content 0
file_1.txt: Content 1
file_2.txt: Content 2
```
## Complete Example
Here's a complete example showing file reading workflow:
```python theme={null}
from hopx_ai import Sandbox
import json
sandbox = Sandbox.create(template="code-interpreter")
# Generate some files
sandbox.run_code('''
import json
import matplotlib.pyplot as plt
# Create data file
data = {"values": [1, 2, 3, 4, 5]}
with open('/workspace/data.json', 'w') as f:
json.dump(data, f)
# Create plot
plt.plot([1, 2, 3, 4, 5])
plt.savefig('/workspace/plot.png')
# Create text file
with open('/workspace/readme.txt', 'w') as f:
f.write("Generated files:\n- data.json\n- plot.png")
''')
# Read all generated files
print("📄 Reading generated files:\n")
# Read JSON data
json_content = sandbox.files.read('/workspace/data.json')
data = json.loads(json_content)
print(f"Data: {data}")
# Read binary plot
plot_data = sandbox.files.read_bytes('/workspace/plot.png')
print(f"Plot size: {len(plot_data)} bytes")
# Read text file
readme = sandbox.files.read('/workspace/readme.txt')
print(f"\nReadme:\n{readme}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Generate some files
await sandbox.runCode(`
import json
import matplotlib.pyplot as plt
# Create data file
data = {"values": [1, 2, 3, 4, 5]}
with open('/workspace/data.json', 'w') as f:
json.dump(data, f)
# Create plot
plt.plot([1, 2, 3, 4, 5])
plt.savefig('/workspace/plot.png')
# Create text file
with open('/workspace/readme.txt', 'w') as f:
f.write("Generated files:\\n- data.json\\n- plot.png")
`);
// Read all generated files
console.log('📄 Reading generated files:\n');
// Read JSON data
const jsonContent = await sandbox.files.read('/workspace/data.json');
const data = JSON.parse(jsonContent);
console.log(`Data: ${JSON.stringify(data)}`);
// Read binary plot
const plotData = await sandbox.files.readBytes('/workspace/plot.png');
console.log(`Plot size: ${plotData.length} bytes`);
// Read text file
const readme = await sandbox.files.read('/workspace/readme.txt');
console.log(`\nReadme:\n${readme}`);
await sandbox.kill();
```
## Best Practices
Use `files.exists()` before reading to avoid errors, or handle `FileNotFoundError` appropriately.
Use `read()` for text files and `read_bytes()` for binary files (images, PDFs, etc.).
For large files, set appropriate timeouts to avoid connection timeouts.
Text files are automatically decoded. Binary files return raw bytes.
Only read from allowed paths like `/workspace` and `/tmp`. System directories may be restricted.
## Related
* **[Writing Files](/core-concepts/filesystem/writing)** - Write files to sandboxes
* **[Listing Files](/core-concepts/filesystem/listing)** - List directory contents
* **SDK**: [sandbox.files.read()](/sdk/python/files#read) - Python SDK method
* **API**: [GET /files/read](/api/vm-agent/read-file) - VM Agent API endpoint
## Next Steps
* Learn about [Writing Files](/core-concepts/filesystem/writing) to create files
* Explore [Listing Files](/core-concepts/filesystem/listing) to browse directories
* Review [Downloading Files](/core-concepts/filesystem/downloading) to save files locally
# Uploading
Source: https://docs.hopx.ai/core-concepts/filesystem/uploading
Upload files from your local filesystem to sandboxes. Transfer files from your local machine to HopX sandboxes for processing, configuration, or data input. Learn how to upload single files or bulk upload multiple files using Python and JavaScript SDKs or REST API. Includes examples for file uploads and progress tracking.
Upload files from your local filesystem to sandboxes. This is useful for transferring data files, scripts, or any local files you want to use in your sandbox.
## Overview
File uploading is ideal for:
* Transferring local data files to sandboxes
* Uploading scripts and code files
* Moving configuration files
* Transferring datasets or models
Upload supports both text and binary files. Large files may take longer to upload - set appropriate timeouts for large transfers.
## Basic Upload
Upload a file from local to sandbox:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Upload a local file
sandbox.files.upload('./local_data.csv', '/workspace/data.csv')
print("File uploaded successfully")
# Verify upload
if sandbox.files.exists('/workspace/data.csv'):
content = sandbox.files.read('/workspace/data.csv')
print(f"Uploaded content: {content[:100]}...")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Note: JavaScript SDK upload may require FormData implementation
// For now, use write() with file content
import * as fs from 'fs';
const localContent = fs.readFileSync('./local_data.csv', 'utf-8');
await sandbox.files.write('/workspace/data.csv', localContent);
console.log('File uploaded successfully');
// Verify upload
const exists = await sandbox.files.exists('/workspace/data.csv');
if (exists) {
const content = await sandbox.files.read('/workspace/data.csv');
console.log(`Uploaded content: ${content.substring(0, 100)}...`);
}
await sandbox.kill();
```
## Upload with Timeout
Set timeout for large file uploads:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Upload large file with extended timeout
sandbox.files.upload('./large_dataset.zip', '/workspace/dataset.zip', timeout=300)
print("Large file uploaded")
# Verify
files = sandbox.files.list('/workspace')
for f in files:
if f.name == 'dataset.zip':
print(f"Uploaded: {f.name} ({f.size_mb:.2f} MB)")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import * as fs from 'fs';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Upload large file (use writeBytes for binary)
const largeContent = fs.readFileSync('./large_dataset.zip');
await sandbox.files.writeBytes('/workspace/dataset.zip', largeContent);
console.log('Large file uploaded');
// Verify
const files = await sandbox.files.list('/workspace');
const datasetFile = files.find(f => f.name === 'dataset.zip');
if (datasetFile) {
console.log(`Uploaded: ${datasetFile.name} (${(datasetFile.size / 1024 / 1024).toFixed(2)} MB)`);
}
await sandbox.kill();
```
## Upload Multiple Files
Upload multiple files in a loop:
```python theme={null}
from hopx_ai import Sandbox
import os
sandbox = Sandbox.create(template="code-interpreter")
# List of files to upload
files_to_upload = [
('./config.json', '/workspace/config.json'),
('./data.csv', '/workspace/data.csv'),
('./script.py', '/workspace/script.py')
]
# Upload all files
for local_path, remote_path in files_to_upload:
if os.path.exists(local_path):
sandbox.files.upload(local_path, remote_path)
print(f"✅ Uploaded: {local_path} → {remote_path}")
else:
print(f"⚠️ File not found: {local_path}")
# Verify all uploads
files = sandbox.files.list('/workspace')
print(f"\nUploaded {len(files)} files")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import * as fs from 'fs';
import * as path from 'path';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// List of files to upload
const filesToUpload = [
['./config.json', '/workspace/config.json'],
['./data.csv', '/workspace/data.csv'],
['./script.py', '/workspace/script.py']
];
// Upload all files
for (const [localPath, remotePath] of filesToUpload) {
try {
if (fs.existsSync(localPath)) {
const content = fs.readFileSync(localPath, 'utf-8');
await sandbox.files.write(remotePath, content);
console.log(`✅ Uploaded: ${localPath} → ${remotePath}`);
} else {
console.log(`⚠️ File not found: ${localPath}`);
}
} catch (error) {
console.error(`Error uploading ${localPath}: ${error.message}`);
}
}
// Verify all uploads
const files = await sandbox.files.list('/workspace');
console.log(`\nUploaded ${files.length} files`);
await sandbox.kill();
```
## Upload Binary Files
Upload binary files (images, PDFs, etc.):
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Upload image file
sandbox.files.upload('./image.png', '/workspace/image.png', timeout=60)
print("Image uploaded")
# Upload PDF
sandbox.files.upload('./document.pdf', '/workspace/document.pdf', timeout=60)
print("PDF uploaded")
# Verify binary files
files = sandbox.files.list('/workspace')
for f in files:
if f.name.endswith(('.png', '.pdf')):
print(f"Binary file: {f.name} ({f.size_kb:.2f} KB)")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import * as fs from 'fs';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Upload image file
const imageData = fs.readFileSync('./image.png');
await sandbox.files.writeBytes('/workspace/image.png', imageData);
console.log('Image uploaded');
// Upload PDF
const pdfData = fs.readFileSync('./document.pdf');
await sandbox.files.writeBytes('/workspace/document.pdf', pdfData);
console.log('PDF uploaded');
// Verify binary files
const files = await sandbox.files.list('/workspace');
for (const f of files) {
if (f.name.endsWith('.png') || f.name.endsWith('.pdf')) {
console.log(`Binary file: ${f.name} (${(f.size / 1024).toFixed(2)} KB)`);
}
}
await sandbox.kill();
```
## Upload to Specific Directory
Upload files to specific directories:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Create directory structure
sandbox.files.mkdir('/workspace/project')
sandbox.files.mkdir('/workspace/project/data')
sandbox.files.mkdir('/workspace/project/src')
# Upload to specific directories
sandbox.files.upload('./dataset.csv', '/workspace/project/data/dataset.csv')
sandbox.files.upload('./main.py', '/workspace/project/src/main.py')
sandbox.files.upload('./config.json', '/workspace/project/config.json')
# Verify structure
print("Project structure:")
for path in ['/workspace/project', '/workspace/project/data', '/workspace/project/src']:
files = sandbox.files.list(path)
print(f"\n{path}:")
for f in files:
print(f" {f.name}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import * as fs from 'fs';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Create directory structure
await sandbox.files.mkdir('/workspace/project');
await sandbox.files.mkdir('/workspace/project/data');
await sandbox.files.mkdir('/workspace/project/src');
// Upload to specific directories
const datasetContent = fs.readFileSync('./dataset.csv', 'utf-8');
await sandbox.files.write('/workspace/project/data/dataset.csv', datasetContent);
const mainContent = fs.readFileSync('./main.py', 'utf-8');
await sandbox.files.write('/workspace/project/src/main.py', mainContent);
const configContent = fs.readFileSync('./config.json', 'utf-8');
await sandbox.files.write('/workspace/project/config.json', configContent);
// Verify structure
console.log('Project structure:');
for (const dirPath of ['/workspace/project', '/workspace/project/data', '/workspace/project/src']) {
const files = await sandbox.files.list(dirPath);
console.log(`\n${dirPath}:`);
for (const f of files) {
console.log(` ${f.name}`);
}
}
await sandbox.kill();
```
## Error Handling
Handle upload errors:
```python theme={null}
from hopx_ai import Sandbox
from hopx_ai.errors import FileOperationError
import os
sandbox = Sandbox.create(template="code-interpreter")
local_file = './data.csv'
try:
# Check if local file exists
if not os.path.exists(local_file):
print(f"Local file not found: {local_file}")
else:
# Upload with error handling
sandbox.files.upload(local_file, '/workspace/data.csv', timeout=120)
print("Upload successful")
except FileOperationError as e:
print(f"Upload failed: {e}")
except Exception as e:
print(f"Error: {e}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import * as fs from 'fs';
import { FileOperationError } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const localFile = './data.csv';
try {
// Check if local file exists
if (!fs.existsSync(localFile)) {
console.error(`Local file not found: ${localFile}`);
} else {
// Upload with error handling
const content = fs.readFileSync(localFile, 'utf-8');
await sandbox.files.write('/workspace/data.csv', content);
console.log('Upload successful');
}
} catch (error) {
if (error instanceof FileOperationError) {
console.error(`Upload failed: ${error.message}`);
} else {
console.error(`Error: ${error.message}`);
}
}
await sandbox.kill();
```
## Complete Example
Here's a complete upload workflow:
```python theme={null}
from hopx_ai import Sandbox
import os
sandbox = Sandbox.create(template="code-interpreter")
# Create project structure
sandbox.files.mkdir('/workspace/ml-project')
sandbox.files.mkdir('/workspace/ml-project/data')
sandbox.files.mkdir('/workspace/ml-project/models')
# Upload project files
files_to_upload = {
'./train.py': '/workspace/ml-project/train.py',
'./data/train.csv': '/workspace/ml-project/data/train.csv',
'./data/test.csv': '/workspace/ml-project/data/test.csv',
'./config.yaml': '/workspace/ml-project/config.yaml'
}
print("📤 Uploading files...")
for local_path, remote_path in files_to_upload.items():
if os.path.exists(local_path):
try:
sandbox.files.upload(local_path, remote_path, timeout=120)
file_size = os.path.getsize(local_path) / 1024
print(f" ✅ {local_path} → {remote_path} ({file_size:.2f} KB)")
except Exception as e:
print(f" ❌ Failed to upload {local_path}: {e}")
else:
print(f" ⚠️ File not found: {local_path}")
# Verify uploads
print("\n📋 Verifying uploads...")
files = sandbox.files.list('/workspace/ml-project')
total_size = 0
for f in files:
if f.is_file:
total_size += f.size
print(f" 📄 {f.path} ({f.size_kb:.2f} KB)")
print(f"\n✅ Total uploaded: {total_size / 1024:.2f} KB")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import * as fs from 'fs';
import * as path from 'path';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Create project structure
await sandbox.files.mkdir('/workspace/ml-project');
await sandbox.files.mkdir('/workspace/ml-project/data');
await sandbox.files.mkdir('/workspace/ml-project/models');
// Upload project files
const filesToUpload = {
'./train.py': '/workspace/ml-project/train.py',
'./data/train.csv': '/workspace/ml-project/data/train.csv',
'./data/test.csv': '/workspace/ml-project/data/test.csv',
'./config.yaml': '/workspace/ml-project/config.yaml'
};
console.log('📤 Uploading files...');
let totalSize = 0;
for (const [localPath, remotePath] of Object.entries(filesToUpload)) {
try {
if (fs.existsSync(localPath)) {
const stats = fs.statSync(localPath);
const content = fs.readFileSync(localPath, 'utf-8');
await sandbox.files.write(remotePath, content);
const fileSize = stats.size / 1024;
console.log(` ✅ ${localPath} → ${remotePath} (${fileSize.toFixed(2)} KB)`);
totalSize += stats.size;
} else {
console.log(` ⚠️ File not found: ${localPath}`);
}
} catch (error) {
console.error(` ❌ Failed to upload ${localPath}: ${error.message}`);
}
}
// Verify uploads
console.log('\n📋 Verifying uploads...');
const files = await sandbox.files.list('/workspace/ml-project');
for (const f of files) {
if (f.isFile) {
console.log(` 📄 ${f.path} (${(f.size / 1024).toFixed(2)} KB)`);
}
}
console.log(`\n✅ Total uploaded: ${(totalSize / 1024).toFixed(2)} KB`);
await sandbox.kill();
```
## Best Practices
Always verify local files exist before attempting upload to avoid errors.
For large files, set extended timeouts (60+ seconds) to avoid connection timeouts.
Use `files.mkdir()` to create target directories before uploading files.
Wrap uploads in try/catch blocks to handle network errors, file not found, etc.
After uploading, verify files exist and check their sizes to ensure successful transfer.
## Related
* **[Writing Files](/core-concepts/filesystem/writing)** - Write files directly in sandboxes
* **[Downloading Files](/core-concepts/filesystem/downloading)** - Download files from sandboxes
* **[Listing Files](/core-concepts/filesystem/listing)** - List directory contents
* **SDK**: [sandbox.files.upload()](/sdk/python/files#upload) - Python SDK method
* [CLI File Operations](/cli/commands/files) - File operations from CLI
## Next Steps
* Learn about [Downloading Files](/core-concepts/filesystem/downloading) to retrieve files from sandboxes
* Explore [Writing Files](/core-concepts/filesystem/writing) for programmatic file creation
* Review [Listing Files](/core-concepts/filesystem/listing) to browse uploaded files
# Watching
Source: https://docs.hopx.ai/core-concepts/filesystem/watching
Watch filesystem for real-time changes via WebSocket in HopX sandboxes. Monitor file and directory changes in real-time, receive notifications for file modifications, and react to filesystem events. Perfect for build systems, file processing pipelines, and real-time monitoring. Includes Python and JavaScript SDK examples and WebSocket API endpoints.
Watch filesystem for real-time changes. Get notified immediately when files are created, modified, deleted, or renamed in your sandbox.
## Overview
File watching is perfect for:
* Real-time monitoring of file changes
* Building reactive applications
* Detecting when outputs are generated
* Implementing file-based workflows
File watching uses WebSocket connections for real-time communication. It requires async/await support and the websockets library (Python).
## Basic File Watching
Watch a directory for changes:
```python theme={null}
from hopx_ai import Sandbox
import asyncio
async def watch_files():
sandbox = Sandbox.create(template="code-interpreter")
# Start watching
print("👀 Watching /workspace for changes...")
event_count = 0
async for event in sandbox.files.watch("/workspace"):
event_type = event.get('event', 'unknown')
path = event.get('path', '')
print(f"{event_type}: {path}")
event_count += 1
if event_count >= 10:
print("Stopping after 10 events")
break
sandbox.kill()
asyncio.run(watch_files())
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function watchFiles() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start watching
console.log('👀 Watching /workspace for changes...');
let eventCount = 0;
for await (const event of sandbox.files.watch('/workspace')) {
const eventType = event.event || 'unknown';
const path = event.path || '';
console.log(`${eventType}: ${path}`);
eventCount++;
if (eventCount >= 10) {
console.log('Stopping after 10 events');
break;
}
}
await sandbox.kill();
}
watchFiles();
```
## Event Types
Handle different file system events:
```python theme={null}
from hopx_ai import Sandbox
import asyncio
async def handle_all_events():
sandbox = Sandbox.create(template="code-interpreter")
async for event in sandbox.files.watch("/workspace"):
event_type = event.get('event', 'unknown')
path = event.get('path', '')
timestamp = event.get('timestamp', '')
if event_type == 'created':
print(f"📄 Created: {path}")
elif event_type == 'modified':
print(f"✏️ Modified: {path}")
elif event_type == 'deleted':
print(f"🗑️ Deleted: {path}")
elif event_type == 'renamed':
old_path = event.get('old_path', '')
print(f"📝 Renamed: {old_path} → {path}")
else:
print(f"❓ Unknown event: {event_type} - {path}")
asyncio.run(handle_all_events())
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function handleAllEvents() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
for await (const event of sandbox.files.watch('/workspace')) {
const eventType = event.event || 'unknown';
const path = event.path || '';
const timestamp = event.timestamp || '';
if (eventType === 'created') {
console.log(`📄 Created: ${path}`);
} else if (eventType === 'modified') {
console.log(`✏️ Modified: ${path}`);
} else if (eventType === 'deleted') {
console.log(`🗑️ Deleted: ${path}`);
} else if (eventType === 'renamed') {
const oldPath = event.old_path || '';
console.log(`📝 Renamed: ${oldPath} → ${path}`);
} else {
console.log(`❓ Unknown event: ${eventType} - ${path}`);
}
}
await sandbox.kill();
}
handleAllEvents();
```
## Monitoring File Generation
Watch for generated output files:
```python theme={null}
from hopx_ai import Sandbox
import asyncio
async def monitor_outputs():
sandbox = Sandbox.create(template="code-interpreter")
# Start background task that generates files
sandbox.run_code_background('''
import time
import json
for i in range(5):
data = {"step": i, "value": i * 2}
with open(f'/workspace/output_{i}.json', 'w') as f:
json.dump(data, f)
time.sleep(2)
''', name='file-generator')
# Watch for new files
print("👀 Watching for output files...")
output_files = []
async for event in sandbox.files.watch("/workspace"):
if event.get('event') == 'created':
path = event.get('path', '')
if path.startswith('/workspace/output_'):
output_files.append(path)
print(f"✅ New output: {path}")
if len(output_files) >= 5:
print("All outputs generated!")
break
print(f"\nGenerated {len(output_files)} files")
sandbox.kill()
asyncio.run(monitor_outputs())
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function monitorOutputs() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start background task that generates files
await sandbox.runCodeBackground(`
import time
import json
for i in range(5):
data = {"step": i, "value": i * 2}
with open(f'/workspace/output_{i}.json', 'w') as f:
json.dump(data, f)
time.sleep(2)
`, { name: 'file-generator' });
// Watch for new files
console.log('👀 Watching for output files...');
const outputFiles = [];
for await (const event of sandbox.files.watch('/workspace')) {
if (event.event === 'created') {
const path = event.path || '';
if (path.startsWith('/workspace/output_')) {
outputFiles.push(path);
console.log(`✅ New output: ${path}`);
if (outputFiles.length >= 5) {
console.log('All outputs generated!');
break;
}
}
}
}
console.log(`\nGenerated ${outputFiles.length} files`);
await sandbox.kill();
}
monitorOutputs();
```
## Filtering Events
Filter events by type or path:
```python theme={null}
from hopx_ai import Sandbox
import asyncio
async def filter_events():
sandbox = Sandbox.create(template="code-interpreter")
# Only watch for Python files
async for event in sandbox.files.watch("/workspace"):
event_type = event.get('event', '')
path = event.get('path', '')
# Only process Python files
if path.endswith('.py'):
if event_type == 'created':
print(f"📄 New Python file: {path}")
elif event_type == 'modified':
print(f"✏️ Python file modified: {path}")
elif event_type == 'deleted':
print(f"🗑️ Python file deleted: {path}")
asyncio.run(filter_events())
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function filterEvents() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Only watch for Python files
for await (const event of sandbox.files.watch('/workspace')) {
const eventType = event.event || '';
const path = event.path || '';
// Only process Python files
if (path.endsWith('.py')) {
if (eventType === 'created') {
console.log(`📄 New Python file: ${path}`);
} else if (eventType === 'modified') {
console.log(`✏️ Python file modified: ${path}`);
} else if (eventType === 'deleted') {
console.log(`🗑️ Python file deleted: ${path}`);
}
}
}
await sandbox.kill();
}
filterEvents();
```
## Complete Example
Here's a complete file watching workflow:
```python theme={null}
from hopx_ai import Sandbox
import asyncio
async def complete_watch_example():
sandbox = Sandbox.create(template="code-interpreter")
# Start a task that creates/modifies files
sandbox.run_code_background('''
import time
import json
# Create initial file
with open('/workspace/status.json', 'w') as f:
json.dump({"status": "starting"}, f)
time.sleep(1)
# Modify file
with open('/workspace/status.json', 'w') as f:
json.dump({"status": "processing"}, f)
time.sleep(1)
# Create output file
with open('/workspace/result.txt', 'w') as f:
f.write("Processing complete")
time.sleep(1)
# Delete status file
import os
os.remove('/workspace/status.json')
''', name='file-operations')
# Watch for all events
print("👀 Watching filesystem...\n")
events_received = []
async for event in sandbox.files.watch("/workspace"):
event_type = event.get('event', 'unknown')
path = event.get('path', '')
timestamp = event.get('timestamp', '')
events_received.append({
'type': event_type,
'path': path,
'timestamp': timestamp
})
# Display event
icons = {
'created': '📄',
'modified': '✏️',
'deleted': '🗑️',
'renamed': '📝'
}
icon = icons.get(event_type, '❓')
print(f"{icon} {event_type.upper()}: {path}")
# Stop after receiving all expected events
if len(events_received) >= 4:
print("\n✅ All events received")
break
# Summary
print(f"\n📊 Summary: Received {len(events_received)} events")
for e in events_received:
print(f" - {e['type']}: {e['path']}")
sandbox.kill()
asyncio.run(complete_watch_example())
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function completeWatchExample() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Start a task that creates/modifies files
await sandbox.runCodeBackground(`
import time
import json
# Create initial file
with open('/workspace/status.json', 'w') as f:
json.dump({"status": "starting"}, f)
time.sleep(1)
# Modify file
with open('/workspace/status.json', 'w') as f:
json.dump({"status": "processing"}, f)
time.sleep(1)
# Create output file
with open('/workspace/result.txt', 'w') as f:
f.write("Processing complete")
time.sleep(1)
# Delete status file
import os
os.remove('/workspace/status.json')
`, { name: 'file-operations' });
// Watch for all events
console.log('👀 Watching filesystem...\n');
const eventsReceived = [];
for await (const event of sandbox.files.watch('/workspace')) {
const eventType = event.event || 'unknown';
const path = event.path || '';
const timestamp = event.timestamp || '';
eventsReceived.push({
type: eventType,
path: path,
timestamp: timestamp
});
// Display event
const icons = {
'created': '📄',
'modified': '✏️',
'deleted': '🗑️',
'renamed': '📝'
};
const icon = icons[eventType] || '❓';
console.log(`${icon} ${eventType.toUpperCase()}: ${path}`);
// Stop after receiving all expected events
if (eventsReceived.length >= 4) {
console.log('\n✅ All events received');
break;
}
}
// Summary
console.log(`\n📊 Summary: Received ${eventsReceived.length} events`);
for (const e of eventsReceived) {
console.log(` - ${e.type}: ${e.path}`);
}
await sandbox.kill();
}
completeWatchExample();
```
## Best Practices
File watching requires async/await. Make sure your code uses async functions and `async for` loops.
Filter events by type or path pattern to process only relevant changes.
Process created, modified, deleted, and renamed events appropriately for your use case.
Consider setting timeouts or event count limits to avoid infinite watching.
Always break the watch loop and clean up connections when done.
## Related
* **[Listing Files](/core-concepts/filesystem/listing)** - List directory contents
* **[Reading Files](/core-concepts/filesystem/reading)** - Read file contents
* **[Writing Files](/core-concepts/filesystem/writing)** - Write files to sandboxes
* **SDK**: [sandbox.files.watch()](/sdk/python/files#watch) - Python SDK method
* [CLI File Operations](/cli/commands/files) - File operations from CLI
## Next Steps
* Learn about [Reading Files](/core-concepts/filesystem/reading) to access file contents
* Explore [Writing Files](/core-concepts/filesystem/writing) to create files
* Review [Listing Files](/core-concepts/filesystem/listing) to browse directories
# Writing
Source: https://docs.hopx.ai/core-concepts/filesystem/writing
Write text and binary files to sandboxes. Learn how to create and write files in HopX sandboxes using Python and JavaScript SDKs or REST API. Includes examples for writing text files, binary files, handling encoding, appending content, and managing file permissions. Perfect for creating configuration files, data files, and scripts.
Write files to your sandbox filesystem. HopX supports both text and binary file writing with automatic encoding and permission handling.
## Overview
File writing is essential for:
* Creating scripts and code files
* Saving generated data and results
* Writing configuration files
* Storing outputs from computations
Files can be written to allowed paths like `/workspace` and `/tmp`. Writing to system directories may be restricted for security.
## Writing Text Files
Write text files as strings:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Write a simple text file
sandbox.files.write('/workspace/hello.txt', 'Hello, World!')
print("File written successfully")
# Read it back
content = sandbox.files.read('/workspace/hello.txt')
print(f"Content: {content}")
sandbox.kill()
```
**Expected Output:**
```
File written successfully
Content: Hello, World!
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Write a simple text file
await sandbox.files.write('/workspace/hello.txt', 'Hello, World!');
console.log('File written successfully');
// Read it back
const content = await sandbox.files.read('/workspace/hello.txt');
console.log(`Content: ${content}`);
await sandbox.kill();
```
**Expected Output:**
```
File written successfully
Content: Hello, World!
```
## Writing Multi-line Files
Write files with multiple lines:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Write multi-line content
content = '''Line 1
Line 2
Line 3
'''
sandbox.files.write('/workspace/multiline.txt', content)
# Verify
read_content = sandbox.files.read('/workspace/multiline.txt')
print(read_content)
sandbox.kill()
```
**Expected Output:**
```
Line 1
Line 2
Line 3
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Write multi-line content
const content = `Line 1
Line 2
Line 3
`;
await sandbox.files.write('/workspace/multiline.txt', content);
// Verify
const readContent = await sandbox.files.read('/workspace/multiline.txt');
console.log(readContent);
await sandbox.kill();
```
**Expected Output:**
```
Line 1
Line 2
Line 3
```
## Writing Binary Files
Write binary files (images, PDFs, etc.):
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Read binary data from local file
with open('local_image.png', 'rb') as f:
image_data = f.read()
# Write to sandbox
sandbox.files.write_bytes('/workspace/image.png', image_data)
print("Binary file written")
# Verify
read_data = sandbox.files.read_bytes('/workspace/image.png')
print(f"Read back: {len(read_data)} bytes")
sandbox.kill()
```
**Expected Output:**
```
Binary file written
Read back: 245760 bytes
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import * as fs from 'fs';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Read binary data from local file
const imageData = fs.readFileSync('local_image.png');
// Write to sandbox
await sandbox.files.writeBytes('/workspace/image.png', imageData);
console.log('Binary file written');
// Verify
const readData = await sandbox.files.readBytes('/workspace/image.png');
console.log(`Read back: ${readData.length} bytes`);
await sandbox.kill();
```
**Expected Output:**
```
Binary file written
Read back: 245760 bytes
```
## Writing Code Files
Write and execute code files:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Write a Python script
script = '''
def calculate_sum(numbers):
return sum(numbers)
result = calculate_sum([1, 2, 3, 4, 5])
print(f"Sum: {result}")
'''
sandbox.files.write('/workspace/calculator.py', script)
# Execute the script
result = sandbox.run_code(
'exec(open("/workspace/calculator.py").read())',
language='python'
)
print(result.stdout) # "Sum: 15"
sandbox.kill()
```
**Expected Output:**
```
Sum: 15
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Write a Python script
const script = `
def calculate_sum(numbers):
return sum(numbers)
result = calculate_sum([1, 2, 3, 4, 5])
print(f"Sum: {result}")
`;
await sandbox.files.write('/workspace/calculator.py', script);
// Execute the script
const result = await sandbox.runCode(
'exec(open("/workspace/calculator.py").read())',
{ language: 'python' }
);
console.log(result.stdout); // "Sum: 15"
await sandbox.kill();
```
**Expected Output:**
```
Sum: 15
```
## File Permissions
Set file permissions when writing:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Write executable script with permissions
script = '#!/bin/bash\necho "Hello from bash!"'
sandbox.files.write('/workspace/script.sh', script, mode='0755')
print("Executable script created")
# Write regular file with default permissions
sandbox.files.write('/workspace/data.txt', 'Some data', mode='0644')
print("Regular file created")
sandbox.kill()
```
**Expected Output:**
```
Executable script created
Regular file created
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Write executable script (permissions handled automatically)
const script = '#!/bin/bash\necho "Hello from bash!"';
await sandbox.files.write('/workspace/script.sh', script);
console.log('Script created');
// Write regular file
await sandbox.files.write('/workspace/data.txt', 'Some data');
console.log('Regular file created');
await sandbox.kill();
```
**Expected Output:**
```
Script created
Regular file created
```
## Writing Configuration Files
Write JSON, YAML, or other configuration files:
```python theme={null}
from hopx_ai import Sandbox
import json
sandbox = Sandbox.create(template="code-interpreter")
# Write JSON config
config = {
"api_key": "sk-123",
"debug": True,
"timeout": 30
}
config_json = json.dumps(config, indent=2)
sandbox.files.write('/workspace/config.json', config_json)
# Read and verify
read_config = json.loads(sandbox.files.read('/workspace/config.json'))
print(f"Config written: {read_config}")
sandbox.kill()
```
**Expected Output:**
```
Config written: {'api_key': 'sk-123', 'debug': True, 'timeout': 30}
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Write JSON config
const config = {
api_key: 'sk-123',
debug: true,
timeout: 30
};
const configJson = JSON.stringify(config, null, 2);
await sandbox.files.write('/workspace/config.json', configJson);
// Read and verify
const readConfig = JSON.parse(await sandbox.files.read('/workspace/config.json'));
console.log(`Config written: ${JSON.stringify(readConfig)}`);
await sandbox.kill();
```
**Expected Output:**
```
Config written: {"api_key":"sk-123","debug":true,"timeout":30}
```
## Writing Large Files
For large files, consider chunking or using upload:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Write large content
large_content = "x" * 1000000 # 1MB of data
sandbox.files.write('/workspace/large.txt', large_content, timeout=120)
print("Large file written")
# Verify size
files = sandbox.files.list('/workspace')
for f in files:
if f.name == 'large.txt':
print(f"File size: {f.size_kb:.2f} KB")
sandbox.kill()
```
**Expected Output:**
```
Large file written
File size: 976.56 KB
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Write large content
const largeContent = 'x'.repeat(1000000); // 1MB of data
await sandbox.files.write('/workspace/large.txt', largeContent);
console.log('Large file written');
// Verify size
const files = await sandbox.files.list('/workspace');
const largeFile = files.find(f => f.name === 'large.txt');
if (largeFile) {
console.log(`File size: ${(largeFile.size / 1024).toFixed(2)} KB`);
}
await sandbox.kill();
```
**Expected Output:**
```
Large file written
File size: 976.56 KB
```
## Complete Example
Here's a complete example showing file writing workflow:
```python theme={null}
from hopx_ai import Sandbox
import json
sandbox = Sandbox.create(template="code-interpreter")
# Create directory structure
sandbox.files.mkdir('/workspace/project')
sandbox.files.mkdir('/workspace/project/src')
sandbox.files.mkdir('/workspace/project/data')
# Write code file
code = '''
def process_data(data):
return [x * 2 for x in data]
if __name__ == "__main__":
result = process_data([1, 2, 3])
print(result)
'''
sandbox.files.write('/workspace/project/src/main.py', code)
# Write config file
config = {"batch_size": 32, "epochs": 10}
sandbox.files.write('/workspace/project/config.json', json.dumps(config, indent=2))
# Write data file
data = "1,2,3\n4,5,6\n7,8,9\n"
sandbox.files.write('/workspace/project/data/input.csv', data)
# List all files
files = sandbox.files.list('/workspace/project')
print("Created files:")
for f in files:
if f.is_file:
print(f" 📄 {f.path} ({f.size_kb:.2f} KB)")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Create directory structure
await sandbox.files.mkdir('/workspace/project');
await sandbox.files.mkdir('/workspace/project/src');
await sandbox.files.mkdir('/workspace/project/data');
// Write code file
const code = `
def process_data(data):
return [x * 2 for x in data]
if __name__ == "__main__":
result = process_data([1, 2, 3])
print(result)
`;
await sandbox.files.write('/workspace/project/src/main.py', code);
// Write config file
const config = { batch_size: 32, epochs: 10 };
await sandbox.files.write('/workspace/project/config.json', JSON.stringify(config, null, 2));
// Write data file
const data = '1,2,3\n4,5,6\n7,8,9\n';
await sandbox.files.write('/workspace/project/data/input.csv', data);
// List all files
const files = await sandbox.files.list('/workspace/project');
console.log('Created files:');
for (const f of files) {
if (f.isFile) {
console.log(` 📄 ${f.path} (${(f.size / 1024).toFixed(2)} KB)`);
}
}
await sandbox.kill();
```
## Best Practices
Use `write()` for text files and `write_bytes()` for binary files (images, PDFs, etc.).
Set appropriate file permissions (e.g., '0755' for executables, '0644' for regular files).
Use `files.mkdir()` to create directories before writing files in them.
For very large files, consider using [Upload](/core-concepts/filesystem/uploading) instead of writing directly.
Only write to allowed paths like `/workspace` and `/tmp`. System directories may be restricted.
## Related
* **[Reading Files](/core-concepts/filesystem/reading)** - Read files from sandboxes
* **[Listing Files](/core-concepts/filesystem/listing)** - List directory contents
* **SDK**: [sandbox.files.write()](/sdk/python/files#write) - Python SDK method
* **API**: [POST /files/write](/api/vm-agent/write-file) - VM Agent API endpoint
* [CLI File Operations](/cli/commands/files) - File operations from CLI
## Next Steps
* Learn about [Reading Files](/core-concepts/filesystem/reading) to retrieve file contents
* Explore [Listing Files](/core-concepts/filesystem/listing) to browse directories
* Review [Uploading Files](/core-concepts/filesystem/uploading) for local file transfers
# Observability
Source: https://docs.hopx.ai/core-concepts/observability/index
Complete guide to monitoring HopX sandboxes - metrics, processes, and system information for observability and debugging. Monitor CPU, memory, and disk usage, list and track running processes, view system metrics, and use observability features for performance optimization and troubleshooting. Includes SDK and API examples.
Monitor and observe HopX sandboxes with comprehensive metrics, process monitoring, and system information. This hub covers all observability features for debugging and performance optimization.
## Related
* [CLI System Commands](/cli/commands/system) - System operations from CLI
## What You'll Learn
* How to monitor sandbox metrics (CPU, memory, disk)
* How to list and monitor processes
* How to track system information and health
* How to use observability for debugging
* How to optimize performance based on metrics
## Observability Overview
| Feature | SDK Method | API Endpoint |
| --------------------------------------------------------- | ----------------------------- | --------------------- |
| **[Metrics](/core-concepts/observability/metrics)** | `sandbox.get_agent_metrics()` | `GET /system/metrics` |
| **[Processes](/core-concepts/observability/processes)** | `sandbox.list_processes()` | `GET /processes` |
| **[Monitoring](/core-concepts/observability/monitoring)** | Monitoring utilities | Monitoring endpoints |
## Core Concepts
### Metrics
Monitor CPU, memory, disk, and other system metrics.
* **[Metrics](/core-concepts/observability/metrics)** - Monitor system metrics
* **SDK**: [Python: sandbox.get\_agent\_metrics()](/sdk/python/sandbox#get_agent_metrics) | [JavaScript: sandbox.getAgentMetrics()](/sdk/javascript/sandbox#getagentmetrics)
* **API**: [GET /system/metrics](/api/vm-agent/get-system-metrics)
### Processes
List and monitor running processes in sandboxes.
* **[Processes](/core-concepts/observability/processes)** - Monitor processes
* **SDK**: [Python: sandbox.list\_processes()](/sdk/python/sandbox#list_processes) | [JavaScript: sandbox.listProcesses()](/sdk/javascript/sandbox#listprocesses)
* **API**: [GET /processes](/api/vm-agent/list-processes) | [GET /processes/system](/api/vm-agent/list-system-processes)
### Monitoring
Comprehensive monitoring strategies and best practices.
* **[Monitoring](/core-concepts/observability/monitoring)** - Monitoring strategies
* **SDK**: Monitoring utilities | **API**: Monitoring endpoints
## SDK Reference
### Python SDK
Complete reference for Python observability operations.
* **[Sandbox.get\_agent\_metrics()](/sdk/python/sandbox#get_agent_metrics)** - Get system metrics
* **[Sandbox.list\_processes()](/sdk/python/sandbox#list_processes)** - List processes
* **[Sandbox.get\_metrics\_snapshot()](/sdk/python/sandbox#get_metrics_snapshot)** - Get metrics snapshot
### JavaScript SDK
Complete reference for JavaScript/TypeScript observability operations.
* **[Sandbox.getAgentMetrics()](/sdk/javascript/sandbox#getagentmetrics)** - Get system metrics
* **[Sandbox.listProcesses()](/sdk/javascript/sandbox#listprocesses)** - List processes
* **[Sandbox.getMetricsSnapshot()](/sdk/javascript/sandbox#getmetricssnapshot)** - Get metrics snapshot
## API Reference
### VM Agent API
REST API endpoints for observability.
* **[VM Agent API Overview](/api/vm-agent/overview)** - API overview
* **[Get System Metrics](/api/vm-agent/get-system-metrics)** - `GET /system/metrics` - Get metrics
* **[List Processes](/api/vm-agent/list-processes)** - `GET /processes` - List background processes
* **[List System Processes](/api/vm-agent/list-system-processes)** - `GET /processes/system` - List all processes
## Quick Start
If you're new to observability, start here:
1. **[Metrics](/core-concepts/observability/metrics)** - Monitor system metrics
2. **[Processes](/core-concepts/observability/processes)** - Monitor running processes
3. **[Monitoring](/core-concepts/observability/monitoring)** - Set up monitoring
## Related Topics
* **[Code Execution](/core-concepts/code-execution/background)** - Monitor background execution
* **[Sandboxes](/core-concepts/sandboxes/managing-state)** - Monitor sandbox state
* **[Process Management](/core-concepts/code-execution/process-management)** - Manage processes
* **[Cache Management](/core-concepts/cache/statistics)** - Monitor cache usage
## Next Steps
* Learn about [Metrics](/core-concepts/observability/metrics) for system monitoring
* Explore [Processes](/core-concepts/observability/processes) for process monitoring
* Review [Monitoring](/core-concepts/observability/monitoring) for comprehensive strategies
* Check out [Code Execution](/core-concepts/code-execution/background) for execution monitoring
# System Metrics
Source: https://docs.hopx.ai/core-concepts/observability/metrics
Get agent performance metrics including uptime, execution counts, and error rates. Monitor CPU, memory, and disk usage in HopX sandboxes to optimize performance and troubleshoot issues. Learn how to retrieve system metrics, track resource usage over time, and use metrics for capacity planning. Includes Python and JavaScript SDK examples and REST API endpoints.
Monitor your sandbox's agent performance in real-time with execution metrics. Track uptime, execution counts, error rates, and per-endpoint statistics to optimize your workloads and troubleshoot issues.
## Overview
HopX provides agent performance metrics to monitor sandbox execution performance:
* **Agent Metrics**: Agent performance metrics including uptime, execution counts, error rates, and per-endpoint statistics
Both `get_metrics_snapshot()` and `get_agent_metrics()` return agent performance metrics. They provide the same data structure.
## Agent Metrics Snapshot
Get a snapshot of current agent performance metrics:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Get agent metrics snapshot
metrics = sandbox.get_metrics_snapshot()
print(f"Uptime: {metrics['uptime_seconds']} seconds")
print(f"Total Executions: {metrics['total_executions']}")
print(f"Active Executions: {metrics['active_executions']}")
print(f"Error Count: {metrics['error_count']}")
# Per-endpoint statistics
if 'requests_total' in metrics:
print("\nRequests by Endpoint:")
for endpoint, count in metrics['requests_total'].items():
print(f" {endpoint}: {count}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Get agent metrics snapshot
const metrics = await sandbox.getMetricsSnapshot();
console.log(`Uptime: ${metrics.uptime_seconds} seconds`);
console.log(`Total Executions: ${metrics.total_executions}`);
console.log(`Active Executions: ${metrics.active_executions}`);
console.log(`Error Count: ${metrics.error_count}`);
// Per-endpoint statistics
if (metrics.requests_total) {
console.log('\nRequests by Endpoint:');
for (const [endpoint, count] of Object.entries(metrics.requests_total)) {
console.log(` ${endpoint}: ${count}`);
}
}
await sandbox.kill();
```
## Agent Performance Metrics
Get detailed agent performance metrics:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Get agent metrics
agent_metrics = sandbox.get_agent_metrics()
print(f"Agent Uptime: {agent_metrics['uptime_seconds']} seconds")
print(f"Total Executions: {agent_metrics['total_executions']}")
print(f"Active Executions: {agent_metrics['active_executions']}")
print(f"Error Count: {agent_metrics['error_count']}")
# Per-endpoint metrics
if 'requests_total' in agent_metrics:
print("\nRequests by Endpoint:")
for endpoint, count in agent_metrics['requests_total'].items():
print(f" {endpoint}: {count}")
if 'avg_duration_ms' in agent_metrics:
print("\nAverage Duration by Endpoint:")
for endpoint, duration in agent_metrics['avg_duration_ms'].items():
print(f" {endpoint}: {duration:.2f} ms")
if 'p95_duration_ms' in agent_metrics:
print("\nP95 Duration by Endpoint:")
for endpoint, duration in agent_metrics['p95_duration_ms'].items():
print(f" {endpoint}: {duration:.2f} ms")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Get agent metrics
const agentMetrics = await sandbox.getAgentMetrics();
console.log(`Agent Uptime: ${agentMetrics.uptime_seconds} seconds`);
console.log(`Total Executions: ${agentMetrics.total_executions}`);
console.log(`Active Executions: ${agentMetrics.active_executions}`);
console.log(`Error Count: ${agentMetrics.error_count}`);
// Per-endpoint metrics
if (agentMetrics.requests_total) {
console.log('\nRequests by Endpoint:');
for (const [endpoint, count] of Object.entries(agentMetrics.requests_total)) {
console.log(` ${endpoint}: ${count}`);
}
}
if (agentMetrics.avg_duration_ms) {
console.log('\nAverage Duration by Endpoint:');
for (const [endpoint, duration] of Object.entries(agentMetrics.avg_duration_ms)) {
console.log(` ${endpoint}: ${duration.toFixed(2)} ms`);
}
}
if (agentMetrics.p95_duration_ms) {
console.log('\nP95 Duration by Endpoint:');
for (const [endpoint, duration] of Object.entries(agentMetrics.p95_duration_ms)) {
console.log(` ${endpoint}: ${duration.toFixed(2)} ms`);
}
}
await sandbox.kill();
```
## Monitoring Agent Performance
Monitor agent metrics over time to track performance:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Monitor metrics every 5 seconds
for i in range(5):
metrics = sandbox.get_metrics_snapshot()
print(f"Snapshot {i+1}:")
print(f" Uptime: {metrics['uptime_seconds']}s")
print(f" Total Executions: {metrics['total_executions']}")
print(f" Active Executions: {metrics['active_executions']}")
print(f" Error Count: {metrics['error_count']}")
if i < 4: # Don't sleep after last iteration
time.sleep(5)
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Monitor metrics every 5 seconds
for (let i = 0; i < 5; i++) {
const metrics = await sandbox.getMetricsSnapshot();
console.log(`Snapshot ${i+1}:`);
console.log(` Uptime: ${metrics.uptime_seconds}s`);
console.log(` Total Executions: ${metrics.total_executions}`);
console.log(` Active Executions: ${metrics.active_executions}`);
console.log(` Error Count: ${metrics.error_count}`);
if (i < 4) { // Don't sleep after last iteration
await new Promise(resolve => setTimeout(resolve, 5000));
}
}
await sandbox.kill();
```
## Metrics Structure
### Agent Metrics Response
Both `get_metrics_snapshot()` and `get_agent_metrics()` return the same structure:
```json theme={null}
{
"uptime_seconds": 1234,
"total_executions": 1250,
"active_executions": 2,
"error_count": 3,
"requests_total": {
"/execute": 800,
"/files/read": 300,
"/files/write": 150
},
"avg_duration_ms": {
"/execute": 1250.5,
"/files/read": 45.2,
"/files/write": 78.9
},
"p95_duration_ms": {
"/execute": 2500.0,
"/files/read": 100.0,
"/files/write": 150.0
}
}
```
### Field Descriptions
* **`uptime_seconds`**: Agent uptime in seconds
* **`total_executions`**: Total number of code executions processed
* **`active_executions`**: Currently running executions
* **`error_count`**: Total number of errors encountered
* **`requests_total`**: Per-endpoint request counts
* **`avg_duration_ms`**: Average request duration by endpoint (milliseconds)
* **`p95_duration_ms`**: 95th percentile request duration by endpoint (milliseconds)
## Use Cases
### Monitoring Execution Performance
Monitor agent performance during code execution:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Get baseline metrics
baseline = sandbox.get_metrics_snapshot()
print(f"Baseline Executions: {baseline['total_executions']}")
print(f"Baseline Errors: {baseline['error_count']}")
# Run some code
sandbox.run_code("""
import time
for i in range(5):
print(f"Step {i+1}")
time.sleep(0.1)
""")
# Check metrics after execution
after = sandbox.get_metrics_snapshot()
print(f"After Execution - Total: {after['total_executions']}")
print(f"After Execution - Errors: {after['error_count']}")
print(f"Executions Added: {after['total_executions'] - baseline['total_executions']}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Get baseline metrics
const baseline = await sandbox.getMetricsSnapshot();
console.log(`Baseline Executions: ${baseline.total_executions}`);
console.log(`Baseline Errors: ${baseline.error_count}`);
// Run some code
await sandbox.runCode(`
import time
for i in range(5):
print(f"Step {i+1}")
time.sleep(0.1)
`);
// Check metrics after execution
const after = await sandbox.getMetricsSnapshot();
console.log(`After Execution - Total: ${after.total_executions}`);
console.log(`After Execution - Errors: ${after.error_count}`);
console.log(`Executions Added: ${after.total_executions - baseline.total_executions}`);
await sandbox.kill();
```
### Performance Analysis
Analyze agent performance to identify bottlenecks:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Get agent metrics
metrics = sandbox.get_agent_metrics()
# Calculate error rate
if metrics['total_executions'] > 0:
error_rate = (metrics['error_count'] / metrics['total_executions']) * 100
print(f"Error Rate: {error_rate:.2f}%")
else:
print("No executions yet")
# Find slowest endpoint
if 'avg_duration_ms' in metrics and metrics['avg_duration_ms']:
slowest = max(metrics['avg_duration_ms'].items(), key=lambda x: x[1])
print(f"Slowest Endpoint: {slowest[0]} ({slowest[1]:.2f} ms)")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Get agent metrics
const metrics = await sandbox.getAgentMetrics();
// Calculate error rate
if (metrics.total_executions > 0) {
const errorRate = (metrics.error_count / metrics.total_executions) * 100;
console.log(`Error Rate: ${errorRate.toFixed(2)}%`);
} else {
console.log('No executions yet');
}
// Find slowest endpoint
if (metrics.avg_duration_ms && Object.keys(metrics.avg_duration_ms).length > 0) {
const slowest = Object.entries(metrics.avg_duration_ms)
.reduce((a, b) => a[1] > b[1] ? a : b);
console.log(`Slowest Endpoint: ${slowest[0]} (${slowest[1].toFixed(2)} ms)`);
}
await sandbox.kill();
```
## Best Practices
**Monitor metrics before and after operations** to track execution performance and identify bottlenecks or error patterns.
**Use agent metrics** to identify frequently used endpoints and optimize your code patterns accordingly.
**Metrics are snapshots**, not continuous monitoring. For real-time streaming metrics, use the [monitoring endpoint](/core-concepts/observability/monitoring) with SSE.
**Check agent version** before using agent metrics. Use `sandbox.get_agent_info()` to verify v3.1.0+ support.
## API Reference
### Python SDK
* `sandbox.get_metrics_snapshot()` - Get agent performance metrics snapshot
* `sandbox.get_agent_metrics()` - Get agent performance metrics (same as get\_metrics\_snapshot)
### JavaScript SDK
* `sandbox.getMetricsSnapshot()` - Get agent performance metrics snapshot
* `sandbox.getAgentMetrics()` - Get agent performance metrics (same as getMetricsSnapshot)
### API Endpoints
* **GET** `/metrics/snapshot` - Get agent performance metrics snapshot
## Related
* **[Process Monitoring](/core-concepts/observability/processes)** - Monitor running processes
* **SDK**: [sandbox.get\_agent\_metrics()](/sdk/python/sandbox#get_agent_metrics) - Python SDK method
* **API**: [GET /system](/api/vm-agent/get-system-metrics) - VM Agent API endpoint
* [CLI System Commands](/cli/commands/system) - System operations from CLI
## Next Steps
* Learn about [Process Monitoring](/core-concepts/observability/processes) to track running processes
* Explore [Code Execution](/core-concepts/code-execution/synchronous) to execute code in sandboxes
* Review [Managing Sandbox State](/core-concepts/sandboxes/managing-state) for lifecycle control
# Monitoring
Source: https://docs.hopx.ai/core-concepts/observability/monitoring
Real-time monitoring and streaming metrics via Server-Sent Events (SSE) in HopX sandboxes. Stream sandbox events, monitor system metrics in real-time, track resource usage, and receive live updates via SSE. Perfect for dashboards, alerting, and real-time monitoring. Includes Python and JavaScript SDK examples and SSE endpoints.
Stream real-time metrics from your sandbox using Server-Sent Events (SSE). This provides continuous monitoring of agent performance metrics without polling.
## Overview
SSE monitoring is ideal for:
* Real-time dashboards and visualizations
* Continuous agent performance monitoring
* Alerting on threshold breaches
* Long-term performance tracking
SSE monitoring is available through the Control Plane API endpoint `/v1/sandboxes/:id/metrics/stream`. This streams metrics from the VM agent to your application.
## Basic Streaming
Connect to the metrics stream and receive real-time updates:
```python theme={null}
import requests
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
info = sandbox.get_info()
# Get API key and base URL
api_key = sandbox._api_key # Access internal API key
base_url = "https://api.hopx.dev"
# Stream metrics via SSE
headers = {
"Authorization": f"Bearer {api_key}",
"Accept": "text/event-stream"
}
stream_url = f"{base_url}/v1/sandboxes/{sandbox.sandbox_id}/metrics/stream"
with requests.get(stream_url, headers=headers, stream=True) as response:
for line in response.iter_lines():
if line and line.startswith(b"data: "):
import json
data = json.loads(line[6:]) # Skip "data: " prefix
print(f"Uptime: {data.get('uptime_seconds', 0)}s")
print(f"Total Executions: {data.get('total_executions', 0)}")
print(f"Active Executions: {data.get('active_executions', 0)}")
print(f"Error Count: {data.get('error_count', 0)}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import EventSource from 'eventsource';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
const info = await sandbox.getInfo();
// Get API key and base URL
const apiKey = sandbox.apiKey; // Access API key
const baseUrl = 'https://api.hopx.dev';
// Stream metrics via SSE
const streamUrl = `${baseUrl}/v1/sandboxes/${sandbox.sandboxId}/metrics/stream?token=${apiKey}`;
const eventSource = new EventSource(streamUrl);
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log(`Uptime: ${data.uptime_seconds || 0}s`);
console.log(`Total Executions: ${data.total_executions || 0}`);
console.log(`Active Executions: ${data.active_executions || 0}`);
console.log(`Error Count: ${data.error_count || 0}`);
};
eventSource.onerror = (error) => {
console.error('SSE error:', error);
eventSource.close();
};
// Close after 30 seconds
setTimeout(() => {
eventSource.close();
sandbox.kill();
}, 30000);
```
## Processing Stream Events
Handle different event types from the SSE stream:
```python theme={null}
import requests
import json
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
info = sandbox.get_info()
api_key = sandbox._api_key
base_url = "https://api.hopx.dev"
headers = {
"Authorization": f"Bearer {api_key}",
"Accept": "text/event-stream"
}
stream_url = f"{base_url}/v1/sandboxes/{sandbox.sandbox_id}/metrics/stream"
with requests.get(stream_url, headers=headers, stream=True) as response:
for line in response.iter_lines():
if not line:
continue
line_str = line.decode('utf-8')
# Handle different SSE event types
if line_str.startswith("event: "):
event_type = line_str[7:]
print(f"Event type: {event_type}")
elif line_str.startswith("data: "):
data = json.loads(line_str[6:])
# Process metrics data
print(f"Metrics - Uptime: {data.get('uptime_seconds', 0)}s")
print(f" Total Executions: {data.get('total_executions', 0)}")
print(f" Active Executions: {data.get('active_executions', 0)}")
print(f" Error Count: {data.get('error_count', 0)}")
elif line_str.startswith("id: "):
event_id = line_str[4:]
# Use event ID for reconnection logic if needed
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import EventSource from 'eventsource';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
const info = await sandbox.getInfo();
const apiKey = sandbox.apiKey;
const baseUrl = 'https://api.hopx.dev';
const streamUrl = `${baseUrl}/v1/sandboxes/${sandbox.sandboxId}/metrics/stream?token=${apiKey}`;
const eventSource = new EventSource(streamUrl);
// Handle different event types
eventSource.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
console.log(`Metrics - Uptime: ${data.uptime_seconds || 0}s`);
console.log(` Total Executions: ${data.total_executions || 0}`);
console.log(` Active Executions: ${data.active_executions || 0}`);
console.log(` Error Count: ${data.error_count || 0}`);
});
eventSource.addEventListener('error', (event) => {
console.error('SSE error:', event);
eventSource.close();
});
// Close after 30 seconds
setTimeout(() => {
eventSource.close();
sandbox.kill();
}, 30000);
```
## Building a Metrics Dashboard
Create a simple dashboard that displays real-time metrics:
```python theme={null}
import requests
import json
import time
from datetime import datetime
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
api_key = sandbox._api_key
base_url = "https://api.hopx.dev"
headers = {
"Authorization": f"Bearer {api_key}",
"Accept": "text/event-stream"
}
stream_url = f"{base_url}/v1/sandboxes/{sandbox.sandbox_id}/metrics/stream"
print("=== Real-Time Metrics Dashboard ===")
print("Press Ctrl+C to stop\n")
try:
with requests.get(stream_url, headers=headers, stream=True) as response:
for line in response.iter_lines():
if line and line.startswith(b"data: "):
data = json.loads(line[6:])
timestamp = datetime.now().strftime("%H:%M:%S")
uptime = data.get('uptime_seconds', 0)
total_exec = data.get('total_executions', 0)
active_exec = data.get('active_executions', 0)
errors = data.get('error_count', 0)
# Simple text-based dashboard
print(f"[{timestamp}] Uptime: {uptime:6d}s | Executions: {total_exec:4d} | Active: {active_exec:2d} | Errors: {errors:3d}")
time.sleep(0.1) # Throttle output
except KeyboardInterrupt:
print("\nStopping monitoring...")
finally:
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import EventSource from 'eventsource';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
const apiKey = sandbox.apiKey;
const baseUrl = 'https://api.hopx.dev';
const streamUrl = `${baseUrl}/v1/sandboxes/${sandbox.sandboxId}/metrics/stream?token=${apiKey}`;
console.log('=== Real-Time Metrics Dashboard ===');
console.log('Press Ctrl+C to stop\n');
const eventSource = new EventSource(streamUrl);
eventSource.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
const timestamp = new Date().toLocaleTimeString();
const uptime = data.uptime_seconds || 0;
const totalExec = data.total_executions || 0;
const activeExec = data.active_executions || 0;
const errors = data.error_count || 0;
// Simple text-based dashboard
console.log(`[${timestamp}] Uptime: ${uptime.toString().padStart(6)}s | Executions: ${totalExec.toString().padStart(4)} | Active: ${activeExec.toString().padStart(2)} | Errors: ${errors.toString().padStart(3)}`);
});
eventSource.addEventListener('error', (error) => {
console.error('Stream error:', error);
eventSource.close();
sandbox.kill();
});
// Handle graceful shutdown
process.on('SIGINT', () => {
console.log('\nStopping monitoring...');
eventSource.close();
sandbox.kill();
process.exit(0);
});
```
## Alerting on Thresholds
Set up alerts when metrics exceed thresholds:
```python theme={null}
import requests
import json
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
api_key = sandbox._api_key
base_url = "https://api.hopx.dev"
headers = {
"Authorization": f"Bearer {api_key}",
"Accept": "text/event-stream"
}
stream_url = f"{base_url}/v1/sandboxes/{sandbox.sandbox_id}/metrics/stream"
# Thresholds
ERROR_COUNT_THRESHOLD = 10
ACTIVE_EXECUTIONS_THRESHOLD = 5
print("Monitoring for threshold breaches...")
with requests.get(stream_url, headers=headers, stream=True) as response:
for line in response.iter_lines():
if line and line.startswith(b"data: "):
data = json.loads(line[6:])
error_count = data.get('error_count', 0)
active_executions = data.get('active_executions', 0)
# Check thresholds
if error_count > ERROR_COUNT_THRESHOLD:
print(f"⚠️ ALERT: Error count {error_count} exceeds threshold {ERROR_COUNT_THRESHOLD}")
if active_executions > ACTIVE_EXECUTIONS_THRESHOLD:
print(f"⚠️ ALERT: Active executions {active_executions} exceeds threshold {ACTIVE_EXECUTIONS_THRESHOLD}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import EventSource from 'eventsource';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
const apiKey = sandbox.apiKey;
const baseUrl = 'https://api.hopx.dev';
const streamUrl = `${baseUrl}/v1/sandboxes/${sandbox.sandboxId}/metrics/stream?token=${apiKey}`;
// Thresholds
const ERROR_COUNT_THRESHOLD = 10;
const ACTIVE_EXECUTIONS_THRESHOLD = 5;
console.log('Monitoring for threshold breaches...');
const eventSource = new EventSource(streamUrl);
eventSource.addEventListener('message', (event) => {
const data = JSON.parse(event.data);
const errorCount = data.error_count || 0;
const activeExecutions = data.active_executions || 0;
// Check thresholds
if (errorCount > ERROR_COUNT_THRESHOLD) {
console.log(`⚠️ ALERT: Error count ${errorCount} exceeds threshold ${ERROR_COUNT_THRESHOLD}`);
}
if (activeExecutions > ACTIVE_EXECUTIONS_THRESHOLD) {
console.log(`⚠️ ALERT: Active executions ${activeExecutions} exceeds threshold ${ACTIVE_EXECUTIONS_THRESHOLD}`);
}
});
eventSource.addEventListener('error', (error) => {
console.error('Stream error:', error);
eventSource.close();
sandbox.kill();
});
```
## Best Practices
**Use SSE for real-time monitoring** when you need continuous updates. For one-time snapshots, use `get_metrics_snapshot()` instead.
**Handle reconnection logic** in production applications. SSE connections can drop, and you should reconnect automatically.
**SSE streams consume resources**. Close connections when no longer needed to free up server resources.
**Throttle processing** if you're receiving metrics faster than you can process them. The stream sends updates frequently.
## API Reference
### Control Plane API
* **GET** `/v1/sandboxes/:id/metrics/stream` - Stream metrics via SSE
* **Headers**: `Authorization: Bearer {token}`, `Accept: text/event-stream`
* **Response**: Server-Sent Events stream with JSON metrics data
### SSE Event Format
```
event: message
data: {"system": {"cpu": {"usage_percent": 25.5}, ...}}
id: 12345
```
## Related
* [System Metrics](/core-concepts/observability/metrics) - Get snapshot metrics
* [Process Monitoring](/core-concepts/observability/processes) - Monitor processes
* **API**: [GET /v1/sandboxes/:id/metrics/stream](/api/control-plane/stream-metrics) - Control Plane API endpoint
## Next Steps
* Learn about [System Metrics](/core-concepts/observability/metrics) for snapshot metrics
* Explore [Process Monitoring](/core-concepts/observability/processes) to monitor processes
* Review [Code Execution](/core-concepts/code-execution/synchronous) to generate metrics
* [Metrics](/core-concepts/observability/metrics) - Get metrics snapshots
* [Processes](/core-concepts/observability/processes) - Monitor processes
* **[CLI Reference](/cli/introduction)** - Use HopX from the command line
# Process Monitoring
Source: https://docs.hopx.ai/core-concepts/observability/processes
List and monitor system processes and background executions in HopX sandboxes. Track running processes, monitor background code execution, check process status, and manage process lifecycle. Essential for debugging, performance monitoring, and resource management. Includes Python and JavaScript SDK examples and REST API endpoints.
Monitor all processes running in your sandbox, including system processes and background code executions. This helps you track resource usage, debug issues, and manage long-running tasks.
## Overview
HopX provides two types of process listings:
* **System Processes**: All processes running in the sandbox (requires Agent v3.2.0+)
* **Background Executions**: Processes started via `execute_code_background()` or `run_code_background()`
System process listing requires VM Agent v3.2.0 or later. Check your agent version using `sandbox.get_agent_info()`.
## System Processes
List all system processes running in the sandbox:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# List all system processes
processes = sandbox.list_system_processes()
print(f"Total Processes: {len(processes)}")
print("\nProcess List:")
for proc in processes[:10]: # Show first 10
print(f"PID {proc['pid']}: {proc['command']} (User: {proc['user']})")
sandbox.kill()
```
**Expected Output:**
```
Total Processes: 45
Process List:
PID 1: /sbin/init (User: root)
PID 2: [kthreadd] (User: root)
PID 3: [rcu_gp] (User: root)
PID 4: [rcu_par_gp] (User: root)
PID 5: [kworker/0:0] (User: root)
PID 6: [mm_percpu_wq] (User: root)
PID 7: [ksoftirqd/0] (User: root)
PID 8: [rcu_sched] (User: root)
PID 9: [migration/0] (User: root)
PID 10: [idle_inject/0] (User: root)
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// List all system processes
const processes = await sandbox.listSystemProcesses();
console.log(`Total Processes: ${processes.length}`);
console.log('\nProcess List:');
for (const proc of processes.slice(0, 10)) { // Show first 10
console.log(`PID ${proc.pid}: ${proc.command} (User: ${proc.user})`);
}
await sandbox.kill();
```
**Expected Output:**
```
Total Processes: 45
Process List:
PID 1: /sbin/init (User: root)
PID 2: [kthreadd] (User: root)
PID 3: [rcu_gp] (User: root)
PID 4: [rcu_par_gp] (User: root)
PID 5: [kworker/0:0] (User: root)
PID 6: [mm_percpu_wq] (User: root)
PID 7: [ksoftirqd/0] (User: root)
PID 8: [rcu_sched] (User: root)
PID 9: [migration/0] (User: root)
PID 10: [idle_inject/0] (User: root)
```
## Background Execution Processes
List processes started via background execution:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Start a background process
process_id = sandbox.run_code_async("""
import time
for i in range(10):
print(f"Step {i+1}")
time.sleep(2)
""")
print(f"Started background process: {process_id}")
# Wait a moment
time.sleep(3)
# List background processes
processes = sandbox.list_processes()
print(f"\nBackground Processes: {len(processes)}")
for proc in processes:
print(f"Process ID: {proc['process_id']}")
print(f"Status: {proc['status']}")
if 'stdout' in proc:
print(f"Output: {proc['stdout'][:100]}...")
sandbox.kill()
```
**Expected Output:**
```
Started background process: proc_abc123xyz
Background Processes: 1
Process ID: proc_abc123xyz
Status: running
Output: Step 1
Step 2
...
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Start a background process
const processId = await sandbox.runCodeAsync(`
import time
for i in range(10):
print(f"Step {i+1}")
time.sleep(2)
`);
console.log(`Started background process: ${processId}`);
// Wait a moment
await new Promise(resolve => setTimeout(resolve, 3000));
// List background processes
const processes = await sandbox.listProcesses();
console.log(`\nBackground Processes: ${processes.length}`);
for (const proc of processes) {
console.log(`Process ID: ${proc.process_id}`);
console.log(`Status: ${proc.status}`);
if (proc.stdout) {
console.log(`Output: ${proc.stdout.substring(0, 100)}...`);
}
}
await sandbox.kill();
```
**Expected Output:**
```
Started background process: proc_abc123xyz
Background Processes: 1
Process ID: proc_abc123xyz
Status: running
Output: Step 1
Step 2
...
```
## Process Structure
### System Process Object
```json theme={null}
{
"pid": 1234,
"name": "python3",
"command": "/usr/bin/python3 /workspace/script.py",
"user": "root",
"cpu_percent": 2.5,
"memory_mb": 45,
"status": "running",
"start_time": "2025-01-27T10:00:00Z"
}
```
### Background Process Object
```json theme={null}
{
"process_id": "proc_abc123",
"status": "running",
"stdout": "Step 1\nStep 2\n",
"stderr": "",
"exit_code": null,
"created_at": "2025-01-27T10:00:00Z"
}
```
## Filtering and Searching
Filter processes by command or user:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# List all system processes
all_processes = sandbox.list_system_processes()
# Filter Python processes
python_processes = [
p for p in all_processes
if 'python' in p['command'].lower()
]
print(f"Python Processes: {len(python_processes)}")
for proc in python_processes:
print(f"PID {proc['pid']}: {proc['command']}")
print(f" CPU: {proc.get('cpu_percent', 0):.1f}%, Memory: {proc.get('memory_mb', 0)} MB")
# Filter by user
root_processes = [
p for p in all_processes
if p['user'] == 'root'
]
print(f"\nRoot Processes: {len(root_processes)}")
sandbox.kill()
```
**Expected Output:**
```
Python Processes: 2
PID 1234: /usr/bin/python3 /workspace/script.py
CPU: 2.5%, Memory: 45 MB
PID 1235: /usr/bin/python3 -m http.server
CPU: 0.8%, Memory: 32 MB
Root Processes: 42
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// List all system processes
const allProcesses = await sandbox.listSystemProcesses();
// Filter Python processes
const pythonProcesses = allProcesses.filter(
p => p.command.toLowerCase().includes('python')
);
console.log(`Python Processes: ${pythonProcesses.length}`);
for (const proc of pythonProcesses) {
console.log(`PID ${proc.pid}: ${proc.command}`);
console.log(` CPU: ${(proc.cpu_percent || 0).toFixed(1)}%, Memory: ${proc.memory_mb || 0} MB`);
}
// Filter by user
const rootProcesses = allProcesses.filter(
p => p.user === 'root'
);
console.log(`\nRoot Processes: ${rootProcesses.length}`);
await sandbox.kill();
```
**Expected Output:**
```
Python Processes: 2
PID 1234: /usr/bin/python3 /workspace/script.py
CPU: 2.5%, Memory: 45 MB
PID 1235: /usr/bin/python3 -m http.server
CPU: 0.8%, Memory: 32 MB
Root Processes: 42
```
## Monitoring Process Status
Monitor background processes to track their progress:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Start long-running background process
process_id = sandbox.run_code_async("""
import time
for i in range(5):
print(f"Processing item {i+1}/5")
time.sleep(3)
print("Complete!")
""")
print(f"Started process: {process_id}")
# Monitor until complete
while True:
processes = sandbox.list_processes()
proc = next((p for p in processes if p['process_id'] == process_id), None)
if not proc:
print("Process not found")
break
print(f"Status: {proc['status']}")
if proc['status'] == 'completed':
print(f"Exit Code: {proc.get('exit_code', 'N/A')}")
if 'stdout' in proc:
print(f"Output:\n{proc['stdout']}")
break
elif proc['status'] == 'failed':
print(f"Error: {proc.get('stderr', 'Unknown error')}")
break
time.sleep(2)
sandbox.kill()
```
**Expected Output:**
```
Started process: proc_abc123xyz
Status: running
Status: running
Status: completed
Exit Code: 0
Output:
Processing item 1/5
Processing item 2/5
Processing item 3/5
Processing item 4/5
Processing item 5/5
Complete!
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Start long-running background process
const processId = await sandbox.runCodeAsync(`
import time
for i in range(5):
print(f"Processing item {i+1}/5")
time.sleep(3)
print("Complete!")
`);
console.log(`Started process: ${processId}`);
// Monitor until complete
while (true) {
const processes = await sandbox.listProcesses();
const proc = processes.find(p => p.process_id === processId);
if (!proc) {
console.log('Process not found');
break;
}
console.log(`Status: ${proc.status}`);
if (proc.status === 'completed') {
console.log(`Exit Code: ${proc.exit_code || 'N/A'}`);
if (proc.stdout) {
console.log(`Output:\n${proc.stdout}`);
}
break;
} else if (proc.status === 'failed') {
console.log(`Error: ${proc.stderr || 'Unknown error'}`);
break;
}
await new Promise(resolve => setTimeout(resolve, 2000));
}
await sandbox.kill();
```
**Expected Output:**
```
Started process: proc_abc123xyz
Status: running
Status: running
Status: completed
Exit Code: 0
Output:
Processing item 1/5
Processing item 2/5
Processing item 3/5
Processing item 4/5
Processing item 5/5
Complete!
```
## Process Limits
Control the number of processes returned:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# List system processes with limit
# Note: list_system_processes() doesn't support max_results parameter
# The API defaults to 200 processes
processes = sandbox.list_system_processes()
print(f"Returned {len(processes)} processes")
if len(processes) >= 200:
print("Note: Results may be truncated (max 200)")
sandbox.kill()
```
**Expected Output:**
```
Returned 45 processes
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// List system processes
// Note: listSystemProcesses() doesn't support maxResults parameter
// The API defaults to 200 processes
const processes = await sandbox.listSystemProcesses();
console.log(`Returned ${processes.length} processes`);
if (processes.length >= 200) {
console.log('Note: Results may be truncated (max 200)');
}
await sandbox.kill();
```
**Expected Output:**
```
Returned 45 processes
```
## Use Cases
### Debugging Hanging Processes
Identify processes that might be causing issues:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# List all processes
processes = sandbox.list_system_processes()
# Find processes consuming resources
print("All Running Processes:")
for proc in processes:
print(f"PID {proc['pid']}: {proc['command']}")
print(f" CPU: {proc.get('cpu_percent', 0):.1f}%, Memory: {proc.get('memory_mb', 0)} MB, Status: {proc.get('status', 'N/A')}")
# Check for specific problematic processes
zombie_processes = [p for p in processes if 'defunct' in p['command']]
if zombie_processes:
print(f"\nFound {len(zombie_processes)} zombie processes")
sandbox.kill()
```
**Expected Output:**
```
All Running Processes:
PID 1: /sbin/init
CPU: 0.0%, Memory: 0 MB, Status: running
PID 2: [kthreadd]
CPU: 0.0%, Memory: 0 MB, Status: running
...
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// List all processes
const processes = await sandbox.listSystemProcesses();
// Find processes consuming resources
console.log('All Running Processes:');
for (const proc of processes) {
console.log(`PID ${proc.pid}: ${proc.command}`);
console.log(` CPU: ${(proc.cpu_percent || 0).toFixed(1)}%, Memory: ${proc.memory_mb || 0} MB, Status: ${proc.status || 'N/A'}`);
}
// Check for specific problematic processes
const zombieProcesses = processes.filter(
p => p.command.includes('defunct')
);
if (zombieProcesses.length > 0) {
console.log(`\nFound ${zombieProcesses.length} zombie processes`);
}
await sandbox.kill();
```
**Expected Output:**
```
All Running Processes:
PID 1: /sbin/init
CPU: 0.0%, Memory: 0 MB, Status: running
PID 2: [kthreadd]
CPU: 0.0%, Memory: 0 MB, Status: running
...
```
### Tracking Background Jobs
Monitor multiple background executions:
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Start multiple background processes
process_ids = []
for i in range(3):
pid = sandbox.run_code_async(f"""
import time
print("Task {i+1} starting")
time.sleep(5)
print("Task {i+1} complete")
""")
process_ids.append(pid)
print(f"Started task {i+1}: {pid}")
# Monitor all processes
time.sleep(2)
processes = sandbox.list_processes()
print(f"\nActive Background Processes: {len(processes)}")
for proc in processes:
if proc['process_id'] in process_ids:
print(f" {proc['process_id']}: {proc['status']}")
sandbox.kill()
```
**Expected Output:**
```
Started task 1: proc_task1_xyz
Started task 2: proc_task2_abc
Started task 3: proc_task3_def
Active Background Processes: 3
proc_task1_xyz: running
proc_task2_abc: running
proc_task3_def: running
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Start multiple background processes
const processIds = [];
for (let i = 0; i < 3; i++) {
const pid = await sandbox.runCodeAsync(`
import time
print("Task ${i+1} starting")
time.sleep(5)
print("Task ${i+1} complete")
`);
processIds.push(pid);
console.log(`Started task ${i+1}: ${pid}`);
}
// Monitor all processes
await new Promise(resolve => setTimeout(resolve, 2000));
const processes = await sandbox.listProcesses();
console.log(`\nActive Background Processes: ${processes.length}`);
for (const proc of processes) {
if (processIds.includes(proc.process_id)) {
console.log(` ${proc.process_id}: ${proc.status}`);
}
}
await sandbox.kill();
```
**Expected Output:**
```
Started task 1: proc_task1_xyz
Started task 2: proc_task2_abc
Started task 3: proc_task3_def
Active Background Processes: 3
proc_task1_xyz: running
proc_task2_abc: running
proc_task3_def: running
```
## Best Practices
**Use system processes** to debug issues and understand what's running in your sandbox environment.
**Use background process listing** to monitor and manage long-running code executions started via `run_code_async()` or `execute_code_background()`.
**System process listing is limited to 200 processes** by default. If you have more processes, results may be truncated.
**Check process status regularly** for background executions to detect completion or failures early.
## API Reference
### Python SDK
* `sandbox.list_system_processes()` - List all system processes (v3.2.0+)
* `sandbox.list_processes()` - List background execution processes
### JavaScript SDK
* `sandbox.listSystemProcesses()` - List all system processes (v3.2.0+)
* `sandbox.listProcesses()` - List background execution processes
### API Endpoints
* **GET** `/processes` - List all system processes (max 200, v3.2.0+)
* **GET** `/execute/processes` - List background execution processes
## Related
* **[System Metrics](/core-concepts/observability/metrics)** - Monitor agent performance metrics
* **[Background Execution](/core-concepts/code-execution/background)** - Start background processes
* **SDK**: [sandbox.list\_processes()](/sdk/python/sandbox#list_processes) - Python SDK method
* **API**: [GET /execute/processes](/api/vm-agent/list-processes) - VM Agent API endpoint
* [CLI System Commands](/cli/commands/system) - System operations from CLI
## Next Steps
* Learn about [System Metrics](/core-concepts/observability/metrics) to monitor agent performance
* Explore [Background Execution](/core-concepts/code-execution/background) to start background processes
* Review [Process Management](/core-concepts/code-execution/process-management) for advanced process control
# Connecting
Source: https://docs.hopx.ai/core-concepts/sandboxes/connecting
Learn how to connect to running HopX sandboxes and establish communication channels. Connect to existing sandboxes by ID, retrieve sandbox information, and resume work with previously created sandboxes. Essential for managing long-running sandboxes and resuming interrupted sessions. Includes Python and JavaScript SDK examples and REST API endpoints.
Connect to sandboxes that are already running. This is useful when you need to reconnect to a sandbox after your application restarts, or when working with sandboxes created by other processes.
## Prerequisites
Before you begin, make sure you have:
* **Existing sandbox** - A sandbox that was previously created (see [Creating Sandboxes](/core-concepts/sandboxes/creating))
* **Sandbox ID** - The ID of the sandbox you want to connect to
* **API key** - Your HopX API key configured
## Overview
The `connect()` method allows you to reconnect to an existing sandbox by its ID. When connecting:
* **If sandbox is paused** → Automatically resumes it and refreshes JWT token
* **If sandbox is stopped** → Raises an error (cannot connect to stopped sandbox)
* **If sandbox is running** → Refreshes JWT token for agent authentication
* **JWT token** → Automatically refreshed and stored for agent operations
You cannot connect to a stopped sandbox. Use `sandbox.start()` first, or create a new sandbox.
## Basic Connection
Connect to an existing sandbox by ID:
```python theme={null}
from hopx_ai import Sandbox
# Connect to existing sandbox
sandbox = Sandbox.connect("1763309903rt5vs4lm")
# Get current information
info = sandbox.get_info()
print(f"Status: {info.status}")
print(f"URL: {info.public_host}")
```
**Expected Output:**
```
Status: running
URL: https://1763309903rt5vs4lm.hopx.dev
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Connect to existing sandbox
const sandbox = await Sandbox.connect('1763309903rt5vs4lm');
// Get current information
const info = await sandbox.getInfo();
console.log(`Status: ${info.status}`);
console.log(`URL: ${info.publicHost}`);
```
**Expected Output:**
```
Status: running
URL: https://1763309903rt5vs4lm.hopx.dev
```
## Finding Sandbox IDs
You can find sandbox IDs by listing your sandboxes:
```python theme={null}
from hopx_ai import Sandbox
# List sandboxes to find IDs
sandboxes = Sandbox.list(status="running")
for sandbox in sandboxes:
info = sandbox.get_info()
print(f"ID: {sandbox.sandbox_id}, Status: {info.status}")
# Connect to the first one
if sandboxes:
sandbox = Sandbox.connect(sandboxes[0].sandbox_id)
print(f"Connected to: {sandbox.sandbox_id}")
```
**Expected Output:**
```
ID: 1763309903rt5vs4lm, Status: running
ID: 1763309904rt5vs4ln, Status: running
Connected to: 1763309903rt5vs4lm
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// List sandboxes to find IDs
const sandboxes = await Sandbox.list({ status: 'running' });
for (const sandbox of sandboxes) {
const info = await sandbox.getInfo();
console.log(`ID: ${sandbox.sandboxId}, Status: ${info.status}`);
}
// Connect to the first one
if (sandboxes.length > 0) {
const sandbox = await Sandbox.connect(sandboxes[0].sandboxId);
console.log(`Connected to: ${sandbox.sandboxId}`);
}
```
## Handling Different States
The `connect()` method handles different sandbox states automatically:
```python theme={null}
from hopx_ai import Sandbox
from hopx_ai.errors import HopxError
try:
sandbox = Sandbox.connect("sandbox_id")
info = sandbox.get_info()
if info.status == "paused":
print("Sandbox was paused - automatically resumed")
elif info.status == "running":
print("Sandbox is running - ready to use")
except HopxError as e:
if "stopped" in str(e).lower():
print("Cannot connect to stopped sandbox")
print("Use sandbox.start() first, or create a new sandbox")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
try {
const sandbox = await Sandbox.connect('sandbox_id');
const info = await sandbox.getInfo();
if (info.status === 'paused') {
console.log('Sandbox was paused - automatically resumed');
} else if (info.status === 'running') {
console.log('Sandbox is running - ready to use');
}
} catch (error) {
if (error.message.includes('stopped')) {
console.error('Cannot connect to stopped sandbox');
console.error('Use sandbox.start() first, or create a new sandbox');
}
}
```
## Complete Workflow Example
Here's a complete example showing the connect workflow:
```python theme={null}
from hopx_ai import Sandbox
# Step 1: List running sandboxes
sandboxes = Sandbox.list(status="running")
print(f"Found {len(sandboxes)} running sandboxes")
# Step 2: Connect to a specific sandbox
if sandboxes:
sandbox_id = sandboxes[0].sandbox_id
print(f"\nConnecting to: {sandbox_id}")
sandbox = Sandbox.connect(sandbox_id)
info = sandbox.get_info()
print(f"✅ Connected successfully")
print(f" Status: {info.status}")
print(f" Template: {info.template_name}")
print(f" URL: {info.public_host}")
# Step 3: Use the sandbox
result = sandbox.run_code('print("Reconnected!")')
print(f" Output: {result.stdout}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Step 1: List running sandboxes
const sandboxes = await Sandbox.list({ status: 'running' });
console.log(`Found ${sandboxes.length} running sandboxes`);
// Step 2: Connect to a specific sandbox
if (sandboxes.length > 0) {
const sandboxId = sandboxes[0].sandboxId;
console.log(`\nConnecting to: ${sandboxId}`);
const sandbox = await Sandbox.connect(sandboxId);
const info = await sandbox.getInfo();
console.log('✅ Connected successfully');
console.log(` Status: ${info.status}`);
console.log(` Template: ${info.templateName}`);
console.log(` URL: ${info.publicHost}`);
// Step 3: Use the sandbox
const result = await sandbox.runCode('print("Reconnected!")');
console.log(` Output: ${result.stdout}`);
}
```
## Error Handling
Handle connection errors appropriately:
```python theme={null}
from hopx_ai import Sandbox
from hopx_ai.errors import NotFoundError, HopxError
try:
sandbox = Sandbox.connect("invalid_id")
except NotFoundError:
print("Sandbox not found")
except HopxError as e:
if "stopped" in str(e).lower():
print("Sandbox is stopped - cannot connect")
print("Start it first: sandbox.start()")
else:
print(f"Connection error: {e}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import { NotFoundError, HopxError } from '@hopx-ai/sdk';
try {
const sandbox = await Sandbox.connect('invalid_id');
} catch (error) {
if (error instanceof NotFoundError) {
console.error('Sandbox not found');
} else if (error instanceof HopxError) {
if (error.message.includes('stopped')) {
console.error('Sandbox is stopped - cannot connect');
console.error('Start it first: sandbox.start()');
} else {
console.error(`Connection error: ${error.message}`);
}
}
}
```
## Use Cases
### Reconnecting After Application Restart
```python theme={null}
from hopx_ai import Sandbox
import os
# Store sandbox ID (e.g., in environment variable or database)
sandbox_id = os.getenv("SANDBOX_ID")
if sandbox_id:
# Reconnect to existing sandbox
sandbox = Sandbox.connect(sandbox_id)
print(f"Reconnected to: {sandbox.sandbox_id}")
else:
# Create new sandbox
sandbox = Sandbox.create(template="code-interpreter")
print(f"Created new: {sandbox.sandbox_id}")
# Store ID for later
os.environ["SANDBOX_ID"] = sandbox.sandbox_id
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Store sandbox ID (e.g., in environment variable or database)
const sandboxId = process.env.SANDBOX_ID;
if (sandboxId) {
// Reconnect to existing sandbox
const sandbox = await Sandbox.connect(sandboxId);
console.log(`Reconnected to: ${sandbox.sandboxId}`);
} else {
// Create new sandbox
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
console.log(`Created new: ${sandbox.sandboxId}`);
// Store ID for later
process.env.SANDBOX_ID = sandbox.sandboxId;
}
```
### Working with Shared Sandboxes
```python theme={null}
from hopx_ai import Sandbox
# Multiple processes can connect to the same sandbox
# Process 1: Creates sandbox
sandbox1 = Sandbox.create(template="code-interpreter")
sandbox_id = sandbox1.sandbox_id
print(f"Created: {sandbox_id}")
# Process 2: Connects to same sandbox
sandbox2 = Sandbox.connect(sandbox_id)
print(f"Connected: {sandbox2.sandbox_id}")
# Both can use the same sandbox
result1 = sandbox1.run_code('x = 1')
result2 = sandbox2.run_code('print(x)') # Can access shared state
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Multiple processes can connect to the same sandbox
// Process 1: Creates sandbox
const sandbox1 = await Sandbox.create({ template: 'code-interpreter' });
const sandboxId = sandbox1.sandboxId;
console.log(`Created: ${sandboxId}`);
// Process 2: Connects to same sandbox
const sandbox2 = await Sandbox.connect(sandboxId);
console.log(`Connected: ${sandbox2.sandboxId}`);
// Both can use the same sandbox
await sandbox1.runCode('x = 1');
await sandbox2.runCode('print(x)'); // Can access shared state
```
## JWT Token Management
When you connect to a sandbox, the SDK automatically:
1. **Refreshes the JWT token** for agent authentication
2. **Stores the token** for subsequent agent operations
3. **Handles token expiration** automatically
You don't need to manage tokens manually - the SDK handles this for you.
```python theme={null}
from hopx_ai import Sandbox
# Connect - token is automatically refreshed
sandbox = Sandbox.connect("sandbox_id")
# Token is stored and used automatically for agent calls
result = sandbox.run_code('print("Hello")') # Uses stored token
# Manually refresh if needed
sandbox.refresh_token()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Connect - token is automatically refreshed
const sandbox = await Sandbox.connect('sandbox_id');
// Token is stored and used automatically for agent calls
const result = await sandbox.runCode('print("Hello")'); // Uses stored token
// Manually refresh if needed
await sandbox.refreshToken();
```
## Implementation
* **SDK**: [Sandbox.connect()](/sdk/python/sandbox#connect) - Python SDK method
* **[CLI](/cli/introduction)** - Command-line interface
* **SDK**: [sandbox.get\_info()](/sdk/python/sandbox#get_info) - Python SDK method
* **API**: [GET /v1/sandboxes/:id](/api/control-plane/get-sandbox) - Control Plane API endpoint
## Related
* **[Listing Sandboxes](/core-concepts/sandboxes/listing)** - Find sandboxes to connect to
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create new sandboxes
* **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle
## Next Steps
* Learn about [Managing State](/core-concepts/sandboxes/managing-state) to start/stop/pause/resume sandboxes
* Explore [Timeout Management](/core-concepts/sandboxes/timeout) for connected sandboxes
* Review [Creating Sandboxes](/core-concepts/sandboxes/creating) for creating new sandboxes
# Creating
Source: https://docs.hopx.ai/core-concepts/sandboxes/creating
Create new sandboxes from templates with custom configuration. Learn how to create isolated cloud environments using HopX templates, configure resources, set environment variables, and manage sandbox lifecycle. Includes Python and JavaScript SDK examples and REST API endpoints.
Sandboxes are isolated, ephemeral cloud environments where your code runs. This guide shows you how to create sandboxes from templates with custom configuration options.
## Prerequisites
Before you begin, make sure you have:
* **HopX API key** - Get one from [console.hopx.dev](https://console.hopx.dev) or see \[API key Management]\(/API key)
* **SDK installed** - Python SDK (`pip install hopx-ai`) or JavaScript SDK (`npm install @hopx-ai/sdk`)
* **Basic understanding** - Familiarity with the [Quickstart Guide](/quickstart) is helpful
## Overview
When you create a sandbox, HopX:
* Spins up a lightweight VM in seconds (\~100ms)
* Loads resources (CPU, memory, disk) from the template
* Provides a persistent filesystem during the sandbox lifecycle
* Auto-destroys the sandbox after timeout (if configured)
Resources (vcpu, memory, disk) are **always** loaded from the template. You cannot specify custom resources when creating a sandbox. To use different resources, create a custom template first.
## Basic Creation
The simplest way to create a sandbox is using a template name:
```python theme={null}
from hopx_ai import Sandbox
# Create sandbox from template name
sandbox = Sandbox.create(template="code-interpreter")
print(f"Sandbox ID: {sandbox.sandbox_id}")
info = sandbox.get_info()
print(f"Status: {info.status}")
print(f"URL: {info.public_host}")
# Clean up when done
sandbox.kill()
```
**Expected Output:**
```
Sandbox ID: sandbox_abc123xyz
Status: running
URL: https://sandbox_abc123xyz.hopx.dev
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Create sandbox from template name
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
console.log(`Sandbox ID: ${sandbox.sandboxId}`);
const info = await sandbox.getInfo();
console.log(`Status: ${info.status}`);
console.log(`URL: ${info.publicHost}`);
// Clean up when done
await sandbox.kill();
```
**Expected Output:**
```
Sandbox ID: sandbox_abc123xyz
Status: running
URL: https://sandbox_abc123xyz.hopx.dev
```
## Using Template ID
You can also create a sandbox using a template ID instead of a name:
```python theme={null}
from hopx_ai import Sandbox
# Create from template ID
sandbox = Sandbox.create(template_id="119")
# Cleanup when done
sandbox.kill()
```
**Expected Output:**
```
Sandbox created successfully
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Create from template ID
const sandbox = await Sandbox.create({
templateId: '119'
});
// Cleanup when done
await sandbox.kill();
```
**Expected Output:**
```
Sandbox created successfully
```
## Configuration Options
When creating a sandbox, you can configure several options:
### Timeout
Set an auto-kill timeout to automatically destroy the sandbox after a specified duration:
```python theme={null}
from hopx_ai import Sandbox
# Create with 1 hour timeout
sandbox = Sandbox.create(
template="code-interpreter",
timeout_seconds=3600 # 1 hour
)
info = sandbox.get_info()
if info.expires_at:
print(f"Sandbox expires at: {info.expires_at}")
```
**Expected Output:**
```
Sandbox expires at: 2025-01-27T11:30:00Z
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Create with 1 hour timeout
const sandbox = await Sandbox.create({
template: 'code-interpreter',
timeoutSeconds: 3600 // 1 hour
});
const info = await sandbox.getInfo();
if (info.expiresAt) {
console.log(`Sandbox expires at: ${info.expiresAt}`);
}
```
**Expected Output:**
```
Sandbox expires at: 2025-01-27T11:30:00Z
```
### Internet Access
Control whether the sandbox has internet access:
```python theme={null}
from hopx_ai import Sandbox
# Create without internet access (isolated)
sandbox = Sandbox.create(
template="code-interpreter",
internet_access=False
)
info = sandbox.get_info()
print(f"Internet access: {info.internet_access}")
# Try to fetch an online resource to demonstrate lack of internet connectivity
result = sandbox.run_code("""
import urllib.request
import urllib.error
try:
response = urllib.request.urlopen('https://www.hopx.ai', timeout=10)
print(f"✅ Successfully fetched hopx.ai - Status: {response.status}")
print(f"Content-Type: {response.headers.get('Content-Type')}")
except urllib.error.URLError as e:
print(f"❌ Failed to fetch URL: {e.reason}")
except Exception as e:
print(f"❌ Error: {type(e).__name__}: {e}")
""", language="python")
print("Fetch attempt output:")
print(result.stdout)
if result.stderr:
print("Errors:")
print(result.stderr)
if result.exit_code != 0:
print("\n❌ Code execution failed")
elif "Failed to fetch" in result.stdout or "Error:" in result.stdout:
print("\n❌ As expected, the fetch failed. Sandbox does not have internet access.")
else:
print("\n✅ Unexpected: fetch succeeded, internet access is enabled!")
# Clean up when done
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Create without internet access (isolated)
const sandbox = await Sandbox.create({
template: 'code-interpreter',
internetAccess: false
});
const info = await sandbox.getInfo();
console.log(`Internet access: ${info.internetAccess}`);
// Try to fetch an online resource to demonstrate lack of internet connectivity
const result = await sandbox.runCode(`
const https = require('https');
function fetchUrl(url) {
return new Promise((resolve, reject) => {
https.get(url, (res) => {
console.log(\`✅ Successfully fetched hopx.ai - Status: \${res.statusCode}\`);
console.log(\`Content-Type: \${res.headers['content-type']}\`);
resolve();
}).on('error', (err) => {
console.log(\`❌ Failed to fetch URL: \${err.message}\`);
reject(err);
});
});
}
fetchUrl('https://www.hopx.ai').catch((err) => {
console.log(\`❌ Error: \${err.name}: \${err.message}\`);
});
`, { language: 'javascript' });
console.log('Fetch attempt output:');
console.log(result.stdout);
if (result.stderr) {
console.log('Errors:');
console.log(result.stderr);
}
if (result.exitCode !== 0) {
console.log('\n❌ Code execution failed');
} else if (result.stdout.includes('Failed to fetch') || result.stdout.includes('Error:')) {
console.log('\n❌ As expected, the fetch failed. Sandbox does not have internet access.');
} else {
console.log('\n✅ Unexpected: fetch succeeded, internet access is enabled!');
}
// Clean up when done
await sandbox.kill();
```
### Environment Variables
Set initial environment variables when creating the sandbox:
```python theme={null}
from hopx_ai import Sandbox
# Create with environment variables
sandbox = Sandbox.create(
template="code-interpreter",
env_vars={
"API_KEY": "sk-123",
"DEBUG": "true",
"ENVIRONMENT": "production"
}
)
# Verify environment variables
result = sandbox.run_code(
"import os; print(dict(os.environ))",
language="python"
)
print(result.stdout)
# Clean up when done
sandbox.kill()
```
**Expected Output:**
```
{'API_KEY': 'sk-123', 'DEBUG': 'true', 'ENVIRONMENT': 'production', 'PATH': '/usr/local/bin:/usr/bin:/bin', ...}
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Create with environment variables
const sandbox = await Sandbox.create({
template: 'code-interpreter',
envVars: {
API_KEY: 'sk-123',
DEBUG: 'true',
ENVIRONMENT: 'production'
}
});
// Verify environment variables
const result = await sandbox.runCode(
"import os; print(os.getenv('API_KEY'))",
{ language: 'python' }
);
console.log(result.stdout); // sk-123
// Clean up when done
await sandbox.kill();
```
**Expected Output:**
```
sk-123
```
## Using Context Managers (Python)
Python SDK supports context managers for automatic cleanup:
```python theme={null}
from hopx_ai import Sandbox
# Automatically cleans up when exiting the context
with Sandbox.create(template="code-interpreter") as sandbox:
result = sandbox.run_code('print("Hello from HopX!")')
print(result.stdout)
# Sandbox is automatically deleted when exiting the block
```
**Expected Output:**
```
Hello from HopX!
```
The context manager automatically calls `sandbox.kill()` when exiting the `with` block, even if an error occurs. This ensures proper cleanup.
## Finding Available Templates
Before creating a sandbox, you may want to list available templates:
```python theme={null}
from hopx_ai import Sandbox
# List all templates
templates = Sandbox.list_templates()
for template in templates:
print(f"{template.name}: {template.display_name}")
# Get specific template details
template = Sandbox.get_template("code-interpreter")
print(f"Description: {template.description}")
print(f"Default resources: {template.default_resources.vcpu} vCPU")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// List all templates
const templates = await Sandbox.listTemplates();
for (const template of templates) {
console.log(`${template.name}: ${template.displayName}`);
}
// Get specific template details
const template = await Sandbox.getTemplate('code-interpreter');
console.log(`Description: ${template.description}`);
console.log(`Default resources: ${template.defaultResources.vcpu} vCPU`);
```
## Best Practices
Use context managers (Python) or try/finally blocks to ensure sandboxes are cleaned up, even if errors occur.
Set timeouts based on your use case. For quick scripts, use shorter timeouts. For long-running tasks, set longer timeouts or use timeout management.
Set environment variables at creation time rather than later for better performance and consistency.
Select templates that match your needs. Use `list_templates()` to find available options.
Always handle potential errors (template not found, resource limits, etc.) in your code.
## Implementation
* **SDK**: [Sandbox.create()](/sdk/python/sandbox#create) - Python SDK method
* **[CLI](/cli/introduction)** - Command-line interface
* **API**: [POST /v1/sandboxes](/api/control-plane/create-sandbox) - Control Plane API endpoint
## Related
* **[Listing Templates](/core-concepts/templates/listing)** - Find available templates
* **[Getting Template Details](/core-concepts/templates/getting-details)** - View template information
* **[Connecting to Sandboxes](/core-concepts/sandboxes/connecting)** - Connect to existing sandboxes
* **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle
## Next Steps
* Learn how to [List Sandboxes](/core-concepts/sandboxes/listing) to find existing sandboxes
* Understand [Connecting to Existing](/core-concepts/sandboxes/connecting) sandboxes
* Explore [Managing State](/core-concepts/sandboxes/managing-state) (start, stop, pause, resume)
* Configure [Timeout Management](/core-concepts/sandboxes/timeout) for long-running sandboxes
# Sandboxes
Source: https://docs.hopx.ai/core-concepts/sandboxes/index
Complete guide to creating, managing, and working with HopX sandboxes - isolated cloud environments for code execution. Learn how to create sandboxes from templates, list and filter existing sandboxes, connect to sandboxes, manage state, and configure timeouts using Python and JavaScript SDKs or REST API.
Sandboxes are isolated, ephemeral cloud environments where your code runs. This hub provides a complete overview of sandbox lifecycle management, from creation to cleanup.
## Related
* [CLI Sandbox Commands](/cli/commands/sandbox) - Manage sandboxes from CLI
## What You'll Learn
* How to create sandboxes from templates
* How to list and filter existing sandboxes
* How to connect to sandboxes and manage their state
* How to configure timeouts and lifecycle management
* SDK and API methods for sandbox operations
## Sandbox Lifecycle Overview
| Operation | SDK Method | API Endpoint |
| ------------------------------------------------------------- | --------------------------------------------- | -------------------------------- |
| **[Creating](/core-concepts/sandboxes/creating)** | `Sandbox.create()` | `POST /v1/sandboxes` |
| **[Listing](/core-concepts/sandboxes/listing)** | `Sandbox.list()` / `Sandbox.iter()` | `GET /v1/sandboxes` |
| **[Connecting](/core-concepts/sandboxes/connecting)** | `Sandbox.connect()` | `GET /v1/sandboxes/:id` |
| **[Managing State](/core-concepts/sandboxes/managing-state)** | `start()` / `stop()` / `pause()` / `resume()` | `POST /v1/sandboxes/:id/:action` |
| **[Timeout](/core-concepts/sandboxes/timeout)** | `set_timeout()` | `PUT /v1/sandboxes/:id/timeout` |
## Core Concepts
### Creating Sandboxes
Learn how to create new sandboxes from templates with custom configuration.
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create new sandboxes from templates
* **SDK**: [Python: Sandbox.create()](/sdk/python/sandbox#create) | [JavaScript: Sandbox.create()](/sdk/javascript/sandbox#create)
* **API**: [POST /v1/sandboxes](/api/control-plane/create-sandbox)
### Listing Sandboxes
Discover how to list, filter, and iterate through existing sandboxes.
* **[Listing Sandboxes](/core-concepts/sandboxes/listing)** - List and filter sandboxes
* **SDK**: [Python: Sandbox.list()](/sdk/python/sandbox#list) | [Python: Sandbox.iter()](/sdk/python/sandbox#iter) | [JavaScript: Sandbox.list()](/sdk/javascript/sandbox#list)
* **API**: [GET /v1/sandboxes](/api/control-plane/list-sandboxes)
### Connecting to Sandboxes
Connect to existing sandboxes by ID or from previous sessions.
* **[Connecting to Sandboxes](/core-concepts/sandboxes/connecting)** - Connect to existing sandboxes
* **SDK**: [Python: Sandbox.connect()](/sdk/python/sandbox#connect) | [JavaScript: Sandbox.connect()](/sdk/javascript/sandbox#connect)
* **API**: [GET /v1/sandboxes/:id](/api/control-plane/get-sandbox)
### Managing Sandbox State
Control sandbox lifecycle: start, stop, pause, and resume operations.
* **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle
* **SDK**: [Python: start/stop/pause/resume](/sdk/python/sandbox#start) | [JavaScript: start/stop/pause/resume](/sdk/javascript/sandbox#start)
* **API**: [POST /v1/sandboxes/:id/start](/api/control-plane/start-sandbox) | [POST /v1/sandboxes/:id/stop](/api/control-plane/stop-sandbox) | [POST /v1/sandboxes/:id/pause](/api/control-plane/pause-sandbox) | [POST /v1/sandboxes/:id/resume](/api/control-plane/resume-sandbox)
### Timeout Management
Configure and manage sandbox auto-shutdown timers.
* **[Timeout Management](/core-concepts/sandboxes/timeout)** - Set and extend sandbox timeouts
* **SDK**: [Python: set\_timeout()](/sdk/python/sandbox#set_timeout) | [JavaScript: setTimeout()](/sdk/javascript/sandbox#settimeout)
* **API**: [PUT /v1/sandboxes/:id/timeout](/api/control-plane/set-timeout)
## SDK Reference
### Python SDK
Complete reference for Python sandbox operations.
* **[Sandbox Class](/sdk/python/sandbox)** - Complete Python SDK reference
* **[AsyncSandbox Class](/sdk/python/async-sandbox)** - Async/await support
### JavaScript SDK
Complete reference for JavaScript/TypeScript sandbox operations.
* **[Sandbox Class](/sdk/javascript/sandbox)** - Complete JavaScript SDK reference
## API Reference
### Control Plane API
REST API endpoints for sandbox lifecycle management.
* **[Control Plane API Overview](/api/control-plane/overview)** - API overview
* **[Create Sandbox](/api/control-plane/create-sandbox)** - `POST /v1/sandboxes`
* **[Get Sandbox](/api/control-plane/get-sandbox)** - `GET /v1/sandboxes/:id`
* **[List Sandboxes](/api/control-plane/list-sandboxes)** - `GET /v1/sandboxes`
* **[Delete Sandbox](/api/control-plane/delete-sandbox)** - `DELETE /v1/sandboxes/:id`
* **[Pause Sandbox](/api/control-plane/pause-sandbox)** - `POST /v1/sandboxes/:id/pause`
* **[Resume Sandbox](/api/control-plane/resume-sandbox)** - `POST /v1/sandboxes/:id/resume`
* **[Set Timeout](/api/control-plane/set-timeout)** - `PUT /v1/sandboxes/:id/timeout`
## Quick Start
If you're new to sandboxes, start here:
1. **[Quickstart Guide](/quickstart)** - Get started in 5 minutes
2. **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create your first sandbox
3. **[Listing Sandboxes](/core-concepts/sandboxes/listing)** - Find existing sandboxes
4. **[Managing State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle
## Related Topics
* **[Templates](/core-concepts/templates/listing)** - Learn about sandbox templates
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Execute code in sandboxes
* **[File Operations](/core-concepts/filesystem/reading)** - Work with files in sandboxes
* **[Environment Variables](/core-concepts/environment/getting)** - Manage environment variables
## Next Steps
* Explore [Code Execution](/core-concepts/code-execution/synchronous) to run code in sandboxes
* Learn about [File Operations](/core-concepts/filesystem/reading) for working with files
* Understand [Template Management](/core-concepts/templates/listing) for custom environments
* Review [Observability](/core-concepts/observability/metrics) for monitoring sandboxes
# Listing
Source: https://docs.hopx.ai/core-concepts/sandboxes/listing
List and filter your sandboxes by status, region, template, and other criteria. Discover how to query existing sandboxes, filter by status or region, iterate through sandbox lists, and find specific sandboxes using Python and JavaScript SDKs or REST API endpoints. Includes pagination and filtering examples.
List and filter your sandboxes to find existing environments, monitor their status, and manage multiple sandboxes efficiently.
## Prerequisites
Before you begin, make sure you have:
* **HopX API key** - Get one from [console.hopx.dev](https://console.hopx.dev) or see \[API key Management]\(/API key)
* **SDK installed** - Python SDK (`pip install hopx-ai`) or JavaScript SDK (`npm install @hopx-ai/sdk`)
* **At least one sandbox** - You should have created at least one sandbox (see [Creating Sandboxes](/core-concepts/sandboxes/creating))
## Basic Listing
List all your sandboxes:
```python theme={null}
from hopx_ai import Sandbox
# List all sandboxes
sandboxes = Sandbox.list()
print(f"Found {len(sandboxes)} sandboxes")
for sandbox in sandboxes:
info = sandbox.get_info()
print(f"{sandbox.sandbox_id}: {info.status}")
```
**Expected Output:**
```
Found 3 sandboxes
sandbox_abc123xyz: running
sandbox_def456uvw: paused
sandbox_ghi789rst: running
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// List all sandboxes
const sandboxes = await Sandbox.list();
console.log(`Found ${sandboxes.length} sandboxes`);
for (const sandbox of sandboxes) {
const info = await sandbox.getInfo();
console.log(`${sandbox.sandboxId}: ${info.status}`);
}
```
**Expected Output:**
```
Found 3 sandboxes
sandbox_abc123xyz: running
sandbox_def456uvw: paused
sandbox_ghi789rst: running
```
## Filtering by Status
Filter sandboxes by their current status:
```python theme={null}
from hopx_ai import Sandbox
# List only running sandboxes
running = Sandbox.list(status="running")
print(f"Running sandboxes: {len(running)}")
# List paused sandboxes
paused = Sandbox.list(status="paused")
print(f"Paused sandboxes: {len(paused)}")
```
**Expected Output:**
```
Running sandboxes: 2
Paused sandboxes: 1
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// List only running sandboxes
const running = await Sandbox.list({ status: 'running' });
console.log(`Running sandboxes: ${running.length}`);
// List paused sandboxes
const paused = await Sandbox.list({ status: 'paused' });
console.log(`Paused sandboxes: ${paused.length}`);
```
**Expected Output:**
```
Running sandboxes: 2
Paused sandboxes: 1
```
## Combining Filters
Combine multiple filters:
```python theme={null}
from hopx_ai import Sandbox
# List running sandboxes in EU region
running_eu = Sandbox.list(status="running", region="eu-west")
print(f"Running EU sandboxes: {len(running_eu)}")
# List with limit
limited = Sandbox.list(status="running", limit=10)
print(f"First 10 running sandboxes: {len(limited)}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// List running sandboxes in EU region
const runningEu = await Sandbox.list({
status: 'running',
region: 'eu-west'
});
console.log(`Running EU sandboxes: ${runningEu.length}`);
// List with limit
const limited = await Sandbox.list({
status: 'running',
limit: 10
});
console.log(`First 10 running sandboxes: ${limited.length}`);
```
## Lazy Iteration (Python)
For better memory usage with many sandboxes, use the iterator:
```python theme={null}
from hopx_ai import Sandbox
found_it_flag = False
# Lazy loading - fetches pages as needed
for sandbox in Sandbox.iter(status="running"):
info = sandbox.get_info()
print(f"{sandbox.sandbox_id}: {info.public_host}")
# Can break early without fetching remaining pages
if found_it_flag:
break
```
The `iter()` method is more memory-efficient for large numbers of sandboxes because it fetches pages on-demand rather than loading all sandboxes into memory at once.
## Getting Detailed Information
Get detailed information for each sandbox:
```python theme={null}
from hopx_ai import Sandbox
sandboxes = Sandbox.list(status="running")
for sandbox in sandboxes:
info = sandbox.get_info()
print(f"\nSandbox: {sandbox.sandbox_id}")
print(f" Status: {info.status}")
print(f" Template: {info.template_name}")
print(f" URL: {info.public_host}")
print(f" Resources: {info.vcpu} vCPU, {info.memory_mb}MB RAM")
print(f" Internet: {info.internet_access}")
if info.expires_at:
print(f" Expires: {info.expires_at}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandboxes = await Sandbox.list({ status: 'running' });
for (const sandbox of sandboxes) {
const info = await sandbox.getInfo();
console.log(`\nSandbox: ${sandbox.sandboxId}`);
console.log(` Status: ${info.status}`);
console.log(` Template: ${info.templateName}`);
console.log(` URL: ${info.publicHost}`);
console.log(` Resources: ${info.vcpu} vCPU, ${info.memoryMb}MB RAM`);
console.log(` Internet: ${info.internetAccess}`);
if (info.expiresAt) {
console.log(` Expires: ${info.expiresAt}`);
}
}
```
## Common Use Cases
### Find a Specific Sandbox
```python theme={null}
from hopx_ai import Sandbox
# Find sandbox by ID pattern
sandboxes = Sandbox.list()
target_id = "1763309903rt5vs4lm"
for sandbox in sandboxes:
if sandbox.sandbox_id == target_id:
print(f"Found: {sandbox.sandbox_id}")
info = sandbox.get_info()
print(f"Status: {info.status}")
break
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Find sandbox by ID pattern
const sandboxes = await Sandbox.list();
const targetId = '1763309903rt5vs4lm';
for (const sandbox of sandboxes) {
if (sandbox.sandboxId === targetId) {
console.log(`Found: ${sandbox.sandboxId}`);
const info = await sandbox.getInfo();
console.log(`Status: ${info.status}`);
break;
}
}
```
### Count Sandboxes by Status
```python theme={null}
from hopx_ai import Sandbox
from collections import Counter
# Count sandboxes by status
sandboxes = Sandbox.list()
status_counts = Counter(sb.get_info().status for sb in sandboxes)
print("Sandbox status summary:")
for status, count in status_counts.items():
print(f" {status}: {count}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Count sandboxes by status
const sandboxes = await Sandbox.list();
const statusCounts = {};
for (const sandbox of sandboxes) {
const info = await sandbox.getInfo();
statusCounts[info.status] = (statusCounts[info.status] || 0) + 1;
}
console.log('Sandbox status summary:');
for (const [status, count] of Object.entries(statusCounts)) {
console.log(` ${status}: ${count}`);
}
```
### Clean Up Old Sandboxes
```python theme={null}
from hopx_ai import Sandbox
from datetime import datetime, timedelta
# Find and clean up sandboxes older than 1 hour
sandboxes = Sandbox.list()
cutoff = datetime.now() - timedelta(hours=1)
for sandbox in sandboxes:
info = sandbox.get_info()
created = datetime.fromisoformat(info.created_at.replace('Z', '+00:00'))
if created < cutoff:
print(f"Cleaning up old sandbox: {sandbox.sandbox_id}")
sandbox.kill()
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Find and clean up sandboxes older than 1 hour
const sandboxes = await Sandbox.list();
const cutoff = new Date(Date.now() - 60 * 60 * 1000); // 1 hour ago
for (const sandbox of sandboxes) {
const info = await sandbox.getInfo();
const created = new Date(info.createdAt);
if (created < cutoff) {
console.log(`Cleaning up old sandbox: ${sandbox.sandboxId}`);
await sandbox.kill();
}
}
```
## API Direct Access
You can also list sandboxes using direct API calls:
```bash theme={null}
# List all sandboxes
curl https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer your-API key"
# Filter by status
curl "https://api.hopx.dev/v1/sandboxes?status=running" \
-H "Authorization: Bearer your-API key"
# Filter by region
curl "https://api.hopx.dev/v1/sandboxes?region=eu-west" \
-H "Authorization: Bearer your-API key"
# Combine filters
curl "https://api.hopx.dev/v1/sandboxes?status=running®ion=us-east&limit=10" \
-H "Authorization: Bearer your-API key"
```
## Implementation
* **SDK**: [Sandbox.list()](/sdk/python/sandbox#list) - Python SDK method
* **[CLI](/cli/introduction)** - Command-line interface
* **SDK**: [Sandbox.iter()](/sdk/python/sandbox#iter) - Python SDK iterator method
* **API**: [GET /v1/sandboxes](/api/control-plane/list-sandboxes) - Control Plane API endpoint
## Related
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create new sandboxes
* **[Connecting to Sandboxes](/core-concepts/sandboxes/connecting)** - Connect to existing sandboxes
* **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle
* **[API Pagination](/api/concepts/pagination)** - Understand pagination in list results
## Next Steps
* Learn about [Connecting to Existing](/core-concepts/sandboxes/connecting) sandboxes from the list
* Understand [Managing State](/core-concepts/sandboxes/managing-state) operations
* Explore [Timeout Management](/core-concepts/sandboxes/timeout) for listed sandboxes
# Managing State
Source: https://docs.hopx.ai/core-concepts/sandboxes/managing-state
Start, stop, pause, and resume sandboxes to control their lifecycle. Learn how to manage sandbox state transitions, free resources when not in use, pause execution temporarily, and resume paused sandboxes. Essential for resource management and workflow control. Includes Python and JavaScript SDK examples and REST API endpoints.
Control the lifecycle of your sandboxes by starting, stopping, pausing, and resuming them. This allows you to manage resources efficiently and maintain state across sessions.
## Prerequisites
Before you begin, make sure you have:
* **Existing sandbox** - A sandbox that was created (see [Creating Sandboxes](/core-concepts/sandboxes/creating))
* **Sandbox object** - A `Sandbox` instance connected to your sandbox
* **Basic understanding** - Familiarity with sandbox states and lifecycle
## Sandbox States
Sandboxes can be in one of these states:
* **`running`** - Active and ready to execute code
* **`stopped`** - Shut down but can be restarted
* **`paused`** - Temporarily suspended, can be resumed
* **`creating`** - Currently being created
When you pause a sandbox, its state is preserved. When you resume it, everything continues from where it left off. Stopped sandboxes lose their runtime state but can be restarted.
## Getting Current State
Check the current state of a sandbox:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
info = sandbox.get_info()
print(f"Status: {info.status}")
print(f"Sandbox ID: {info.sandbox_id}")
```
**Expected Output:**
```
Status: running
Sandbox ID: 1763309903rt5vs4lm
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const info = await sandbox.getInfo();
console.log(`Status: ${info.status}`);
console.log(`Sandbox ID: ${info.sandboxId}`);
```
**Expected Output:**
```
Status: running
Sandbox ID: 1763309903rt5vs4lm
```
## Starting a Sandbox
Start a stopped sandbox:
```python theme={null}
from hopx_ai import Sandbox
# Connect to a stopped sandbox
sandbox = Sandbox.connect("sandbox_id")
# Check current status
info = sandbox.get_info()
print(f"Current status: {info.status}") # "stopped"
# Start the sandbox
sandbox.start()
# Verify it's running
info = sandbox.get_info()
print(f"New status: {info.status}") # "running"
```
**Expected Output:**
```
Current status: stopped
New status: running
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Connect to a stopped sandbox
const sandbox = await Sandbox.connect('sandbox_id');
// Check current status
let info = await sandbox.getInfo();
console.log(`Current status: ${info.status}`); // "stopped"
// Start the sandbox
await sandbox.start();
// Verify it's running
info = await sandbox.getInfo();
console.log(`New status: ${info.status}`); // "running"
```
**Expected Output:**
```
Current status: stopped
New status: running
```
## Stopping a Sandbox
Stop a running sandbox (preserves filesystem but loses runtime state):
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Stop the sandbox
sandbox.stop()
# Verify it's stopped
info = sandbox.get_info()
print(f"Status: {info.status}") # "stopped"
# Can start it again later
sandbox.start()
```
**Expected Output:**
```
Status: stopped
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Stop the sandbox
await sandbox.stop();
// Verify it's stopped
let info = await sandbox.getInfo();
console.log(`Status: ${info.status}`); // "stopped"
// Can start it again later
await sandbox.start();
```
**Expected Output:**
```
Status: stopped
```
## Pausing a Sandbox
Pause a running sandbox (preserves full state including memory):
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set some state
sandbox.run_code('x = 42', language="python")
# Pause the sandbox
sandbox.pause()
# Verify it's paused
info = sandbox.get_info()
print(f"Status: {info.status}") # "paused"
```
**Expected Output:**
```
Status: paused
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Set some state
await sandbox.runCode('x = 42', { language: 'python' });
// Pause the sandbox
await sandbox.pause();
// Verify it's paused
const info = await sandbox.getInfo();
console.log(`Status: ${info.status}`); // "paused"
```
**Expected Output:**
```
Status: paused
```
## Resuming a Sandbox
Resume a paused sandbox (restores full state):
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.connect("sandbox_id") # Automatically resumes if paused
# Or manually resume
sandbox.resume()
# Verify it's running
info = sandbox.get_info()
print(f"Status: {info.status}") # "running"
# State is preserved
result = sandbox.run_code('print(x)', language="python")
print(result.stdout) # "42" - state preserved!
```
**Expected Output:**
```
Status: running
42
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.connect('sandbox_id'); // Automatically resumes if paused
// Or manually resume
await sandbox.resume();
// Verify it's running
const info = await sandbox.getInfo();
console.log(`Status: ${info.status}`); // "running"
// State is preserved
const result = await sandbox.runCode('print(x)', { language: 'python' });
console.log(result.stdout); // "42" - state preserved!
```
**Expected Output:**
```
Status: running
42
```
## Complete State Management Example
Here's a complete example showing all state operations:
```python theme={null}
from hopx_ai import Sandbox
# Create sandbox
sandbox = Sandbox.create(template="code-interpreter")
print(f"Created: {sandbox.get_info().status}") # "running"
# Set some state
sandbox.run_code('data = [1, 2, 3, 4, 5]', language="python")
# Pause
sandbox.pause()
print(f"After pause: {sandbox.get_info().status}") # "paused"
# Resume (state preserved)
sandbox.resume()
print(f"After resume: {sandbox.get_info().status}") # "running"
# Verify state preserved
result = sandbox.run_code('print(sum(data))', language="python")
print(f"Sum: {result.stdout}") # "15" - state preserved!
# Stop
sandbox.stop()
print(f"After stop: {sandbox.get_info().status}") # "stopped"
# Start again (state lost)
sandbox.start()
result = sandbox.run_code('print(data)', language="python")
print(f"Data: {result.stderr}") # Error - state lost on stop
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Create sandbox
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
let info = await sandbox.getInfo();
console.log(`Created: ${info.status}`); // "running"
// Set some state
await sandbox.runCode('data = [1, 2, 3, 4, 5]', { language: 'python' });
// Pause
await sandbox.pause();
info = await sandbox.getInfo();
console.log(`After pause: ${info.status}`); // "paused"
// Resume (state preserved)
await sandbox.resume();
info = await sandbox.getInfo();
console.log(`After resume: ${info.status}`); // "running"
// Verify state preserved
let result = await sandbox.runCode('print(sum(data))', { language: 'python' });
console.log(`Sum: ${result.stdout}`); // "15" - state preserved!
// Stop
await sandbox.stop();
info = await sandbox.getInfo();
console.log(`After stop: ${info.status}`); // "stopped"
// Start again (state lost)
await sandbox.start();
result = await sandbox.runCode('print(data)', { language: 'python' });
console.log(`Data: ${result.stderr}`); // Error - state lost on stop
```
## State Transitions
Understanding state transitions helps you manage sandboxes effectively:
```
creating → running → paused → running
↓ ↓
stopped → running
↓
(deleted)
```
**Pause**: Preserves full state (memory, variables, running processes). Fast resume.
**Stop**: Preserves filesystem only. Runtime state is lost. Requires full restart.
**Pause**: When you need to temporarily suspend work but keep everything in memory.
**Stop**: When you want to free resources but keep files for later.
## Error Handling
Handle state transition errors:
```python theme={null}
from hopx_ai import Sandbox
from hopx_ai.errors import APIError
sandbox = Sandbox.create(template="code-interpreter")
try:
# Try to pause
sandbox.pause()
except APIError as e:
print(f"Failed to pause: {e}")
try:
# Try to start (might already be running)
sandbox.start()
except APIError as e:
print(f"Failed to start: {e}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import { APIError } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
try {
// Try to pause
await sandbox.pause();
} catch (error) {
if (error instanceof APIError) {
console.error(`Failed to pause: ${error.message}`);
}
}
try {
// Try to start (might already be running)
await sandbox.start();
} catch (error) {
if (error instanceof APIError) {
console.error(`Failed to start: ${error.message}`);
}
}
```
## Best Practices
Use `pause()` when you need to temporarily suspend work but want to preserve all state. Resume is fast and preserves everything.
Use `stop()` when you want to free resources but keep the filesystem. Files are preserved, but runtime state is lost.
Always check the sandbox status before performing operations to avoid errors.
Handle errors when transitioning states - a sandbox might already be in the desired state.
Always call `kill()` when you're completely done with a sandbox to free resources.
## Implementation
* **SDK**: [sandbox.start()](/sdk/python/sandbox#start) - Python SDK method
* **[CLI](/cli/introduction)** - Command-line interface
* **SDK**: [sandbox.stop()](/sdk/python/sandbox#stop) - Python SDK method
* **SDK**: [sandbox.pause()](/sdk/python/sandbox#pause) - Python SDK method
* **SDK**: [sandbox.resume()](/sdk/python/sandbox#resume) - Python SDK method
* **API**: [POST /v1/sandboxes/:id/start](/api/control-plane/start-sandbox) - Control Plane API endpoint
* **API**: [POST /v1/sandboxes/:id/stop](/api/control-plane/stop-sandbox) - Control Plane API endpoint
* **API**: [POST /v1/sandboxes/:id/pause](/api/control-plane/pause-sandbox) - Control Plane API endpoint
* **API**: [POST /v1/sandboxes/:id/resume](/api/control-plane/resume-sandbox) - Control Plane API endpoint
## Related
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create new sandboxes
* **[Connecting to Sandboxes](/core-concepts/sandboxes/connecting)** - Connect to existing sandboxes
* **[Timeout Management](/core-concepts/sandboxes/timeout)** - Set sandbox timeouts
## Next Steps
* Learn about [Timeout Management](/core-concepts/sandboxes/timeout) to control sandbox lifetime
* Review [Creating Sandboxes](/core-concepts/sandboxes/creating) for creating new sandboxes
* Explore [Listing Sandboxes](/core-concepts/sandboxes/listing) to find sandboxes by status
# Timeout
Source: https://docs.hopx.ai/core-concepts/sandboxes/timeout
Set and extend sandbox timeouts to control when sandboxes are automatically destroyed. Configure auto-shutdown timers to manage resources, extend timeouts for long-running tasks, and check remaining time. Essential for cost management and resource optimization. Includes Python and JavaScript SDK examples and REST API endpoints.
Sandboxes can be configured with automatic timeout values that determine when they are automatically destroyed. This helps manage resources and costs while ensuring sandboxes don't run indefinitely.
## Overview
Timeout management allows you to:
* Set an initial timeout when creating a sandbox
* Extend the timeout for running sandboxes
* Automatically destroy sandboxes after the timeout expires
When a timeout expires, the sandbox is automatically destroyed. All data in the sandbox is lost. Make sure to save important data before the timeout expires.
## Setting Timeout on Creation
Set a timeout when creating a sandbox:
```python theme={null}
from hopx_ai import Sandbox
# Create sandbox with 1 hour timeout
sandbox = Sandbox.create(
template="code-interpreter",
timeout_seconds=3600 # 1 hour in seconds
)
info = sandbox.get_info()
if info.expires_at:
print(f"Sandbox expires at: {info.expires_at}")
```
**Expected Output:**
```
Sandbox expires at: 2025-01-27T11:00:00Z
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Create sandbox with 1 hour timeout
const sandbox = await Sandbox.create({
template: 'code-interpreter',
timeoutSeconds: 3600 // 1 hour in seconds
});
const info = await sandbox.getInfo();
if (info.expiresAt) {
console.log(`Sandbox expires at: ${info.expiresAt}`);
}
```
**Expected Output:**
```
Sandbox expires at: 2025-01-27T11:00:00Z
```
## Extending Timeout
Extend the timeout for an existing sandbox:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Extend timeout to 2 hours from now
sandbox.set_timeout(7200) # 2 hours in seconds
# Verify new timeout
info = sandbox.get_info()
if info.expires_at:
print(f"New expiration: {info.expires_at}")
```
**Expected Output:**
```
New expiration: 2025-01-27T12:00:00Z
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Extend timeout to 2 hours from now
await sandbox.setTimeout(7200); // 2 hours in seconds
// Verify new timeout
const info = await sandbox.getInfo();
if (info.expiresAt) {
console.log(`New expiration: ${info.expiresAt}`);
}
```
**Expected Output:**
```
New expiration: 2025-01-27T12:00:00Z
```
The `set_timeout()` method sets a new timeout duration **from the current time**, not from the original expiration. Each call resets the timer.
## Common Timeout Values
Use these common timeout values:
```python theme={null}
from hopx_ai import Sandbox
# Quick tasks (5 minutes)
sandbox = Sandbox.create(
template="code-interpreter",
timeout_seconds=300
)
# Standard tasks (30 minutes)
sandbox = Sandbox.create(
template="code-interpreter",
timeout_seconds=1800
)
# Long-running tasks (1 hour)
sandbox = Sandbox.create(
template="code-interpreter",
timeout_seconds=3600
)
# Extended tasks (4 hours)
sandbox = Sandbox.create(
template="code-interpreter",
timeout_seconds=14400
)
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Quick tasks (5 minutes)
const sandbox1 = await Sandbox.create({
template: 'code-interpreter',
timeoutSeconds: 300
});
// Standard tasks (30 minutes)
const sandbox2 = await Sandbox.create({
template: 'code-interpreter',
timeoutSeconds: 1800
});
// Long-running tasks (1 hour)
const sandbox3 = await Sandbox.create({
template: 'code-interpreter',
timeoutSeconds: 3600
});
// Extended tasks (4 hours)
const sandbox4 = await Sandbox.create({
template: 'code-interpreter',
timeoutSeconds: 14400
});
```
## Checking Expiration
Check when a sandbox will expire:
```python theme={null}
from hopx_ai import Sandbox
from datetime import datetime
sandbox = Sandbox.create(
template="code-interpreter",
timeout_seconds=3600
)
info = sandbox.get_info()
if info.expires_at:
expires = datetime.fromisoformat(info.expires_at.replace('Z', '+00:00'))
now = datetime.now(expires.tzinfo)
remaining = expires - now
print(f"Expires at: {info.expires_at}")
print(f"Time remaining: {remaining.total_seconds() / 60:.1f} minutes")
```
**Expected Output:**
```
Expires at: 2025-01-27T11:00:00Z
Time remaining: 55.2 minutes
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter',
timeoutSeconds: 3600
});
const info = await sandbox.getInfo();
if (info.expiresAt) {
const expires = new Date(info.expiresAt);
const now = new Date();
const remaining = (expires - now) / 1000 / 60; // minutes
console.log(`Expires at: ${info.expiresAt}`);
console.log(`Time remaining: ${remaining.toFixed(1)} minutes`);
}
```
**Expected Output:**
```
Expires at: 2025-01-27T11:00:00Z
Time remaining: 55.2 minutes
```
## Extending Before Expiration
Extend timeout before it expires to prevent automatic destruction:
```python theme={null}
from hopx_ai import Sandbox
from datetime import datetime
sandbox = Sandbox.create(
template="code-interpreter",
timeout_seconds=3600
)
# Check remaining time
info = sandbox.get_info()
if info.expires_at:
expires = datetime.fromisoformat(info.expires_at.replace('Z', '+00:00'))
now = datetime.now(expires.tzinfo)
remaining_minutes = (expires - now).total_seconds() / 60
# Extend if less than 10 minutes remaining
if remaining_minutes < 10:
print("Extending timeout...")
sandbox.set_timeout(3600) # Extend by 1 hour
print("Timeout extended")
```
**Expected Output:**
```
Extending timeout...
Timeout extended
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter',
timeoutSeconds: 3600
});
// Check remaining time
let info = await sandbox.getInfo();
if (info.expiresAt) {
const expires = new Date(info.expiresAt);
const now = new Date();
const remainingMinutes = (expires - now) / 1000 / 60;
// Extend if less than 10 minutes remaining
if (remainingMinutes < 10) {
console.log('Extending timeout...');
await sandbox.setTimeout(3600); // Extend by 1 hour
console.log('Timeout extended');
}
}
```
**Expected Output:**
```
Extending timeout...
Timeout extended
```
## No Timeout (Indefinite)
Create a sandbox without a timeout (runs until manually killed):
```python theme={null}
from hopx_ai import Sandbox
# Create without timeout (or set to None)
sandbox = Sandbox.create(
template="code-interpreter"
# timeout_seconds not specified = no timeout
)
info = sandbox.get_info()
if info.expires_at:
print(f"Expires: {info.expires_at}")
else:
print("No timeout - runs indefinitely")
```
**Expected Output:**
```
No timeout - runs indefinitely
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Create without timeout
const sandbox = await Sandbox.create({
template: 'code-interpreter'
// timeoutSeconds not specified = no timeout
});
const info = await sandbox.getInfo();
if (info.expiresAt) {
console.log(`Expires: ${info.expiresAt}`);
} else {
console.log('No timeout - runs indefinitely');
}
```
**Expected Output:**
```
No timeout - runs indefinitely
```
## Complete Example
Here's a complete example showing timeout management:
```python theme={null}
from hopx_ai import Sandbox
from datetime import datetime
# Create with initial timeout
sandbox = Sandbox.create(
template="code-interpreter",
timeout_seconds=1800 # 30 minutes
)
info = sandbox.get_info()
print(f"Initial timeout: {info.expires_at}")
# Do some work
sandbox.run_code('print("Working...")', language="python")
# Extend timeout before expiration
sandbox.set_timeout(3600) # Extend to 1 hour from now
info = sandbox.get_info()
print(f"Extended timeout: {info.expires_at}")
# Check remaining time
if info.expires_at:
expires = datetime.fromisoformat(info.expires_at.replace('Z', '+00:00'))
remaining = (expires - datetime.now(expires.tzinfo)).total_seconds()
print(f"Time remaining: {remaining / 60:.1f} minutes")
```
**Expected Output:**
```
Initial timeout: 2025-01-27T10:30:00Z
Working...
Extended timeout: 2025-01-27T11:30:00Z
Time remaining: 60.0 minutes
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Create with initial timeout
const sandbox = await Sandbox.create({
template: 'code-interpreter',
timeoutSeconds: 1800 // 30 minutes
});
let info = await sandbox.getInfo();
console.log(`Initial timeout: ${info.expiresAt}`);
// Do some work
await sandbox.runCode('print("Working...")', { language: 'python' });
// Extend timeout before expiration
await sandbox.setTimeout(3600); // Extend to 1 hour from now
info = await sandbox.getInfo();
console.log(`Extended timeout: ${info.expiresAt}`);
// Check remaining time
if (info.expiresAt) {
const expires = new Date(info.expiresAt);
const remaining = (expires - new Date()) / 1000 / 60;
console.log(`Time remaining: ${remaining.toFixed(1)} minutes`);
}
```
**Expected Output:**
```
Initial timeout: 2025-01-27T10:30:00Z
Working...
Extended timeout: 2025-01-27T11:30:00Z
Time remaining: 60.0 minutes
```
## API Direct Access
You can also manage timeouts using direct API calls:
```bash theme={null}
# Set timeout when creating
curl -X POST https://api.hopx.dev/v1/sandboxes \
-H "Authorization: Bearer your-API key" \
-H "Content-Type: application/json" \
-d '{
"template_name": "code-interpreter",
"timeout_seconds": 3600
}'
# Update timeout for existing sandbox
curl -X PUT https://api.hopx.dev/v1/sandboxes/{sandbox_id}/timeout \
-H "Authorization: Bearer your-API key" \
-H "Content-Type: application/json" \
-d '{
"timeout_seconds": 7200
}'
```
## Best Practices
Set timeouts based on expected task duration. For quick scripts, use shorter timeouts. For long-running tasks, set longer timeouts.
Check expiration time regularly for long-running sandboxes to avoid unexpected destruction.
Extend timeouts before they expire to prevent data loss. Consider setting up monitoring to alert when time is running low.
Always save important data before timeout expires. Consider downloading files or storing results externally.
For development and debugging, consider creating sandboxes without timeouts, but remember to clean them up manually.
## Timeout vs Manual Cleanup
Set `timeout_seconds` when creating or use `set_timeout()` to automatically destroy sandboxes after a specified duration. Best for production workloads.
Call `sandbox.kill()` when done. Best for development or when you need precise control over when sandboxes are destroyed.
## Implementation
* **SDK**: [sandbox.set\_timeout()](/sdk/python/sandbox#set_timeout) - Python SDK method
* **[CLI](/cli/introduction)** - Command-line interface
* **API**: [PUT /v1/sandboxes/:id/timeout](/api/control-plane/set-timeout) - Control Plane API endpoint
## Related
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Set timeout on creation
* **[Managing Sandbox State](/core-concepts/sandboxes/managing-state)** - Control sandbox lifecycle
* **[Connecting to Sandboxes](/core-concepts/sandboxes/connecting)** - Connect to existing sandboxes
## Next Steps
* Learn about [Creating Sandboxes](/core-concepts/sandboxes/creating) with timeout configuration
* Explore [Managing State](/core-concepts/sandboxes/managing-state) for lifecycle control
* Review [Listing Sandboxes](/core-concepts/sandboxes/listing) to monitor sandbox status
# Building
Source: https://docs.hopx.ai/core-concepts/templates/building
Create custom templates with dependencies in HopX. Build custom sandbox templates from Docker images, configure resources, add build steps, and install dependencies. Learn how to use TemplateBuilder to create templates tailored to your needs. Includes Python and JavaScript SDK examples and REST API endpoints.
Build custom templates with pre-configured environments, dependencies, and settings. Templates allow you to create reusable sandbox configurations.
## Prerequisites
Before you begin, make sure you have:
* **HopX API key** - Get one from [console.hopx.dev](https://console.hopx.dev) or see \[API key Management]\(/API key)
* **Understanding of templates** - Familiarity with [Listing Templates](/core-concepts/templates/listing) is helpful
* **Base image or template** - Decide on a base image (Python, Node.js, Ubuntu, etc.)
* **Dependencies list** - Know what packages or tools you want pre-installed
## Overview
Building templates enables you to:
* Pre-install packages and dependencies
* Configure environment variables
* Set up working directories and users
* Create reusable sandbox configurations
* Optimize sandbox creation time
Template building is an async operation that can take several minutes. The build process includes uploading files, executing build steps, and waiting for template activation.
## Basic Template Building
Create a simple template from a base image:
```python theme={null}
from hopx_ai.template import Template, BuildOptions
import os
# Create template from base image
template = Template()
template.from_python_image("3.11-slim")
# Add build steps
template.run_cmd("pip install numpy pandas matplotlib")
# Build template
options = BuildOptions(
name="my-python-template",
api_key=os.getenv("HOPX_API_KEY"),
cpu=2,
memory=2048,
disk_gb=10,
context_path=os.getcwd() # Required: working directory for file operations
)
result = await Template.build(template, options)
print(f"Template built: {result.template_id}")
print(f"Build ID: {result.build_id}")
```
```javascript theme={null}
// Note: JavaScript SDK template building may have different API
// This is a conceptual example based on Python SDK patterns
import { Template, BuildOptions } from '@hopx-ai/sdk';
// Create template from base image
const template = new Template('python:3.11-slim');
// Add build steps
template.runCmd('pip install numpy pandas matplotlib');
// Build template
const options = new BuildOptions({
name: 'my-python-template',
apiKey: process.env.HOPX_API_KEY,
cpu: 2,
memory: 2048,
diskGb: 10
});
const result = await Template.build(template, options);
console.log(`Template built: ${result.templateId}`);
```
## Using Base Image Helpers
Use convenient base image helpers:
```python theme={null}
from hopx_ai.template import Template, BuildOptions
import os
# From Ubuntu
template = Template().from_ubuntu_image("22.04")
template.apt_install("curl", "git", "vim")
# From Python
template = Template().from_python_image("3.11")
template.pip_install("numpy", "pandas")
# From Node.js
template = Template().from_node_image("20")
template.npm_install("typescript", "tsx")
# Build
options = BuildOptions(
name="my-template",
api_key=os.getenv("HOPX_API_KEY"),
context_path=os.getcwd()
)
result = await Template.build(template, options)
```
```javascript theme={null}
// Conceptual example
import { Template, BuildOptions } from '@hopx-ai/sdk';
// From Ubuntu
const template = new Template().fromUbuntuImage('22.04');
template.aptInstall('curl', 'git', 'vim');
// From Python
const template2 = new Template().fromPythonImage('3.11');
template2.pipInstall('numpy', 'pandas');
// From Node.js
const template3 = new Template().fromNodeImage('20');
template3.npmInstall('typescript', 'tsx');
```
## Complete Template Example
Build a complete template with multiple steps:
```python theme={null}
from hopx_ai.template import Template, BuildOptions
from hopx_ai.template.ready_checks import wait_for_port
import os
# Create template
template = Template()
template.from_python_image("3.11-slim")
# Install system packages
template.apt_install("curl", "git", "build-essential")
# Set working directory
template.set_workdir("/app")
# Install Python packages
template.pip_install("flask", "gunicorn", "redis")
# Set environment variables
template.set_env("FLASK_ENV", "production")
template.set_env("PORT", "8000")
# Copy files (requires file upload)
# template.copy("/local/path", "/app", options=CopyOptions(owner="appuser"))
# Set start command and ready check
template.set_start_cmd(
"gunicorn -w 4 -b 0.0.0.0:8000 app:app",
ready=wait_for_port(8000, timeout=30000)
)
# Build template
options = BuildOptions(
name="flask-app-template",
api_key=os.getenv("HOPX_API_KEY"),
cpu=2,
memory=2048,
disk_gb=10,
context_path=os.getcwd() # Required for file operations
)
result = await Template.build(template, options)
print(f"✅ Template built: {result.template_id}")
print(f" Build ID: {result.build_id}")
print(f" Duration: {result.duration}s")
```
```javascript theme={null}
// Conceptual example
import { Template, BuildOptions, waitForPort } from '@hopx-ai/sdk';
const template = new Template('python:3.11-slim');
// Install system packages
template.aptInstall('curl', 'git', 'build-essential');
// Set working directory
template.setWorkdir('/app');
// Install Python packages
template.pipInstall('flask', 'gunicorn', 'redis');
// Set environment variables
template.setEnv('FLASK_ENV', 'production');
template.setEnv('PORT', '8000');
// Set start command and ready check
template.setStartCmd(
'gunicorn -w 4 -b 0.0.0.0:8000 app:app',
waitForPort(8000, { timeout: 30000 })
);
// Build template
const options = new BuildOptions({
name: 'flask-app-template',
apiKey: process.env.HOPX_API_KEY,
cpu: 2,
memory: 2048,
diskGb: 10
});
const result = await Template.build(template, options);
console.log(`✅ Template built: ${result.templateId}`);
```
## Build Options
Configure build options:
```python theme={null}
from hopx_ai.template import BuildOptions
import os
options = BuildOptions(
name="my-template", # Required: Template name
api_key=os.getenv("HOPX_API_KEY"), # Required: API key
cpu=2, # CPU cores (default: 2)
memory=2048, # Memory in MB (default: 2048)
disk_gb=10, # Disk in GB (default: 10)
context_path=os.getcwd(), # Required: Working directory for file operations
skip_cache=False, # Skip build cache (default: False)
update=False, # Update existing template (default: False)
template_activation_timeout=2700 # Max wait for activation in seconds (default: 2700)
)
# With progress callbacks
def on_progress(progress: int):
print(f"Build progress: {progress}%")
def on_log(log_entry: dict):
print(f"[{log_entry['level']}] {log_entry['message']}")
options.on_progress = on_progress
options.on_log = on_log
```
```javascript theme={null}
// Conceptual example
const options = new BuildOptions({
name: 'my-template', // Required: Template name
apiKey: process.env.HOPX_API_KEY, // Required: API key
cpu: 2, // CPU cores (default: 2)
memory: 2048, // Memory in MB (default: 2048)
diskGb: 10, // Disk in GB (default: 10)
skipCache: false, // Skip build cache (default: false)
update: false, // Update existing template (default: false)
templateActivationTimeout: 2700, // Max wait for activation in seconds
onProgress: (progress) => {
console.log(`Build progress: ${progress}%`);
},
onLog: (logEntry) => {
console.log(`[${logEntry.level}] ${logEntry.message}`);
}
});
```
## Build Result and Logs
Access build results and logs:
```python theme={null}
from hopx_ai.template import Template, BuildOptions
import os
# Build template
template = Template()
template.from_python_image("3.11-slim")
template.pip_install("numpy")
options = BuildOptions(
name="test-template",
api_key=os.getenv("HOPX_API_KEY"),
context_path=os.getcwd()
)
result = await Template.build(template, options)
# Access build information
print(f"Build ID: {result.build_id}")
print(f"Template ID: {result.template_id}")
print(f"Duration: {result.duration}s")
# Get build logs
logs = await result.get_logs()
print(f"Logs:\n{logs.logs}")
# Poll for new logs
if not logs.complete:
new_logs = await result.get_logs(offset=logs.offset)
print(f"New logs:\n{new_logs.logs}")
```
```javascript theme={null}
// Conceptual example
const result = await Template.build(template, options);
// Access build information
console.log(`Build ID: ${result.buildId}`);
console.log(`Template ID: ${result.templateId}`);
console.log(`Duration: ${result.duration}s`);
// Get build logs
const logs = await result.getLogs();
console.log(`Logs:\n${logs.logs}`);
// Poll for new logs
if (!logs.complete) {
const newLogs = await result.getLogs({ offset: logs.offset });
console.log(`New logs:\n${newLogs.logs}`);
}
```
## Best Practices
Use base image helpers (from\_python\_image, from\_node\_image) for common environments.
Use fluent API to chain operations for readable template definitions.
Configure CPU, memory, and disk based on your application needs.
Set ready checks for services that need to be ready before sandbox is usable.
Use progress and log callbacks to monitor long-running builds.
## Related
* **[Listing Templates](/core-concepts/templates/listing)** - List available templates
* **[Getting Template Details](/core-concepts/templates/getting-details)** - View template information
* **[Template Configuration](/core-concepts/templates/configuration)** - Configure template resources and steps
* **API**: [POST /v1/templates/build](/api/control-plane/build-template) - Control Plane API endpoint
* [CLI Template Commands](/cli/commands/template) - Template management from CLI
## Next Steps
* Learn about [Template Configuration](/core-concepts/templates/configuration) for advanced setup
* Explore [Template Caching](/core-concepts/templates/caching) for build optimization
* Review [Listing Templates](/core-concepts/templates/listing) to see your built templates
# Caching
Source: https://docs.hopx.ai/core-concepts/templates/caching
Template build caching and optimization in HopX. Optimize template loading with caching strategies, reduce sandbox creation time, and manage template cache for improved performance. Learn how caching works, when to clear cache, and best practices for template optimization. Includes caching examples and performance tips.
Optimize template builds with caching strategies. Template caching speeds up builds by reusing layers and steps that haven't changed.
## Overview
Template caching helps you:
* Speed up template builds
* Reduce build costs
* Reuse unchanged layers
* Optimize build performance
Template builds use Docker layer caching. Steps that haven't changed are cached and reused, significantly speeding up rebuilds.
## How Caching Works
Template builds cache each step:
```python theme={null}
from hopx_ai.template import Template
template = Template()
template.from_python_image("3.11-slim")
# These steps are cached if unchanged
template.apt_install("curl", "git") # Cached if packages unchanged
template.pip_install("numpy", "pandas") # Cached if packages unchanged
template.set_env("DEBUG", "true") # Cached if value unchanged
# Only changed steps are rebuilt
template.pip_install("matplotlib") # Only this step rebuilds if added
```
```javascript theme={null}
// Conceptual example
const template = new Template('python:3.11-slim');
// These steps are cached if unchanged
template.aptInstall('curl', 'git'); // Cached if packages unchanged
template.pipInstall('numpy', 'pandas'); // Cached if packages unchanged
template.setEnv('DEBUG', 'true'); // Cached if value unchanged
// Only changed steps are rebuilt
template.pipInstall('matplotlib'); // Only this step rebuilds if added
```
## Skip Cache for Steps
Skip caching for specific steps:
```python theme={null}
from hopx_ai.template import Template
template = Template()
template.from_python_image("3.11-slim")
# Install packages (cached)
template.pip_install("numpy", "pandas")
# Run command that should always execute (skip cache)
template.run_cmd("git clone https://github.com/user/repo.git /app")
template.skip_cache() # Skip cache for previous step
# Next steps are cached again
template.pip_install("flask")
```
```javascript theme={null}
// Conceptual example
const template = new Template('python:3.11-slim');
// Install packages (cached)
template.pipInstall('numpy', 'pandas');
// Run command that should always execute (skip cache)
template.runCmd('git clone https://github.com/user/repo.git /app');
template.skipCache(); // Skip cache for previous step
// Next steps are cached again
template.pipInstall('flask');
```
## Skip Cache for Entire Build
Skip all caching for a build:
```python theme={null}
from hopx_ai.template import BuildOptions
import os
# Skip all caching
options = BuildOptions(
name="my-template",
api_key=os.getenv("HOPX_API_KEY"),
skip_cache=True # Skip all caching
)
# Useful for:
# - Debugging build issues
# - Ensuring fresh builds
# - Testing build steps
```
```javascript theme={null}
// Conceptual example
const options = new BuildOptions({
name: 'my-template',
apiKey: process.env.HOPX_API_KEY,
skipCache: true // Skip all caching
});
```
## Optimizing Build Order
Order steps for optimal caching:
```python theme={null}
from hopx_ai.template import Template
template = Template()
template.from_python_image("3.11-slim")
# ✅ Good: Stable steps first (cached longer)
template.apt_install("curl", "git") # Rarely changes
template.pip_install("numpy", "pandas") # Changes less frequently
template.set_env("NODE_ENV", "production") # Rarely changes
# ✅ Good: Frequently changing steps last
template.run_cmd("git clone repo /app") # Changes often
template.run_cmd("cp config.json /app") # Changes often
# ❌ Bad: Frequently changing steps first
# template.run_cmd("git clone repo /app") # Invalidates all cache
# template.apt_install("curl") # Never cached
```
```javascript theme={null}
// Conceptual example
const template = new Template('python:3.11-slim');
// ✅ Good: Stable steps first (cached longer)
template.aptInstall('curl', 'git'); // Rarely changes
template.pipInstall('numpy', 'pandas'); // Changes less frequently
template.setEnv('NODE_ENV', 'production'); // Rarely changes
// ✅ Good: Frequently changing steps last
template.runCmd('git clone repo /app'); // Changes often
template.runCmd('cp config.json /app'); // Changes often
```
## Cache Invalidation
Understand when cache is invalidated:
```python theme={null}
from hopx_ai.template import Template
template = Template()
template.from_python_image("3.11-slim")
# Cache is invalidated when:
# 1. Step arguments change
template.pip_install("numpy", "pandas") # Cached
template.pip_install("numpy", "pandas", "matplotlib") # Cache invalidated
# 2. Step order changes
template.apt_install("curl")
template.pip_install("numpy")
# vs
template.pip_install("numpy")
template.apt_install("curl") # Different cache key
# 3. Base image changes
template = create_template("python:3.11-slim") # One cache
template = create_template("python:3.12-slim") # Different cache
# 4. Files change (for COPY steps)
# template.copy("/local/src", "/app") # Cache invalidated if files change
```
```javascript theme={null}
// Conceptual example
const template = new Template('python:3.11-slim');
// Cache is invalidated when:
// 1. Step arguments change
template.pipInstall('numpy', 'pandas'); // Cached
template.pipInstall('numpy', 'pandas', 'matplotlib'); // Cache invalidated
// 2. Step order changes
template.aptInstall('curl');
template.pipInstall('numpy');
// vs
template.pipInstall('numpy');
template.aptInstall('curl'); // Different cache key
// 3. Base image changes
const template1 = new Template('python:3.11-slim'); // One cache
const template2 = new Template('python:3.12-slim'); // Different cache
```
## Best Practices
Place stable steps (system packages, language packages) before frequently changing steps (file copies, git clones).
Group related steps together to maximize cache hits.
Only skip cache for steps that must always execute (e.g., git clones with latest changes).
Minimize changes to early steps to preserve cache for later steps.
Test builds to understand cache behavior and optimize step ordering.
## Related
* **[Building Templates](/core-concepts/templates/building)** - Create templates with caching
* **[Template Configuration](/core-concepts/templates/configuration)** - Configure template resources
* **[Getting Template Details](/core-concepts/templates/getting-details)** - View template information
* [CLI Template Commands](/cli/commands/template) - Template management from CLI
## Next Steps
* Learn about [Building Templates](/core-concepts/templates/building) to create templates
* Explore [Template Configuration](/core-concepts/templates/configuration) for advanced setup
* Review [Listing Templates](/core-concepts/templates/listing) to see your templates
# Configuration
Source: https://docs.hopx.ai/core-concepts/templates/configuration
Configure templates with resources, steps, and commands in HopX. Set vCPU, memory, and disk limits, define build steps, install packages, and configure template environments. Learn how to configure templates for optimal performance and functionality. Includes Python and JavaScript SDK examples and configuration options.
Configure templates with resources, build steps, commands, environment variables, and ready checks. Template configuration determines the final sandbox environment.
## Prerequisites
Before you begin, make sure you have:
* **Understanding of template building** - Familiarity with [Building Templates](/core-concepts/templates/building) is required
* **Template builder SDK** - Python SDK with template builder (`from hopx_ai.template import Template`)
* **Resource requirements** - Know your CPU, memory, and disk requirements
* **Build steps** - Plan your installation commands and file operations
## Overview
Template configuration includes:
* Resource specifications (CPU, memory, disk)
* Build steps (commands, file operations)
* Environment variables
* Working directories and users
* Start commands and ready checks
* Port exposure and health checks
Template configuration is set during template building. Once built, templates are immutable - create a new template to change configuration.
## Resource Configuration
Configure template resources:
```python theme={null}
from hopx_ai.template import BuildOptions
import os
# Configure resources in BuildOptions
options = BuildOptions(
name="my-template",
api_key=os.getenv("HOPX_API_KEY"),
cpu=4, # 4 vCPU cores
memory=4096, # 4GB RAM
disk_gb=20, # 20GB disk
context_path=os.getcwd() # Required: Working directory
)
# Resource limits depend on your plan
# Typical ranges:
# - CPU: 1-64 cores
# - Memory: 512MB-64GB
# - Disk: 1GB-250GB
```
```javascript theme={null}
// Conceptual example
const options = new BuildOptions({
name: 'my-template',
apiKey: process.env.HOPX_API_KEY,
cpu: 4, // 4 vCPU cores
memory: 4096, // 4GB RAM
diskGb: 20 // 20GB disk
});
```
## Build Steps
Configure build steps for template:
```python theme={null}
from hopx_ai.template import Template
template = Template()
template.from_python_image("3.11-slim")
# Run commands
template.run_cmd("apt-get update")
template.run_cmd("apt-get install -y git curl")
# Install packages (convenience methods)
template.apt_install("vim", "nano")
template.pip_install("numpy", "pandas")
template.npm_install("typescript", "tsx")
# Set working directory
template.set_workdir("/app")
# Set user
template.set_user("appuser")
# Set environment variables
template.set_env("NODE_ENV", "production")
template.set_env("DEBUG", "false")
# Copy files (requires file upload)
# template.copy("/local/src", "/app", options=CopyOptions(owner="appuser"))
```
```javascript theme={null}
// Conceptual example
const template = new Template('python:3.11-slim');
// Run commands
template.runCmd('apt-get update');
template.runCmd('apt-get install -y git curl');
// Install packages
template.aptInstall('vim', 'nano');
template.pipInstall('numpy', 'pandas');
template.npmInstall('typescript', 'tsx');
// Set working directory
template.setWorkdir('/app');
// Set user
template.setUser('appuser');
// Set environment variables
template.setEnv('NODE_ENV', 'production');
template.setEnv('DEBUG', 'false');
```
## Start Command and Ready Checks
Configure start command and ready checks:
```python theme={null}
from hopx_ai.template import Template
from hopx_ai.template.ready_checks import (
wait_for_port,
wait_for_url,
wait_for_file,
wait_for_process,
wait_for_command
)
template = Template()
template.from_python_image("3.11-slim")
template.pip_install("flask", "gunicorn")
# Start command with port ready check
template.set_start_cmd(
"gunicorn -w 4 -b 0.0.0.0:8000 app:app",
ready=wait_for_port(8000, timeout=30000)
)
# Alternative ready checks
# Wait for URL
template.set_start_cmd(
"python app.py",
ready=wait_for_url("http://localhost:8000/health", timeout=30000)
)
# Wait for file
template.set_start_cmd(
"python app.py",
ready=wait_for_file("/app/ready.txt", timeout=30000)
)
# Wait for process
template.set_start_cmd(
"python app.py",
ready=wait_for_process("python", timeout=30000)
)
# Wait for command
template.set_start_cmd(
"python app.py",
ready=wait_for_command("curl -f http://localhost:8000/health", timeout=30000)
)
```
```javascript theme={null}
// Conceptual example
import { waitForPort, waitForUrl } from '@hopx-ai/sdk';
const template = new Template('python:3.11-slim');
template.pipInstall('flask', 'gunicorn');
// Start command with port ready check
template.setStartCmd(
'gunicorn -w 4 -b 0.0.0.0:8000 app:app',
waitForPort(8000, { timeout: 30000 })
);
// Wait for URL
template.setStartCmd(
'python app.py',
waitForUrl('http://localhost:8000/health', { timeout: 30000 })
);
```
## Port Exposure
Expose ports for services:
```python theme={null}
from hopx_ai.template import Template
template = Template()
template.from_python_image("3.11-slim")
# Expose ports
template.expose(8000) # HTTP server
template.expose(5432) # PostgreSQL
template.expose(6379) # Redis
# Ports are automatically exposed when sandbox is created
# Access via: https://{port}-{sandbox_id}.{region}.vms.hopx.dev/
```
```javascript theme={null}
// Conceptual example
const template = new Template('python:3.11-slim');
// Expose ports
template.expose(8000); // HTTP server
template.expose(5432); // PostgreSQL
template.expose(6379); // Redis
```
## Complete Configuration Example
Here's a complete template configuration:
```python theme={null}
from hopx_ai.template import Template, BuildOptions
from hopx_ai.template.ready_checks import wait_for_port
import os
# Create template
template = Template()
template.from_python_image("3.11-slim")
# System packages
template.apt_install("curl", "git", "build-essential", "postgresql-client")
# Working directory
template.set_workdir("/app")
# Python packages
template.pip_install("flask", "gunicorn", "psycopg2", "redis")
# Environment variables
template.set_env("FLASK_ENV", "production")
template.set_env("DATABASE_URL", "postgresql://localhost/db")
template.set_env("REDIS_URL", "redis://localhost:6379")
# Expose ports
template.expose(8000)
# Start command with ready check
template.set_start_cmd(
"gunicorn -w 4 -b 0.0.0.0:8000 app:app",
ready=wait_for_port(8000, timeout=30000)
)
# Build with resource configuration
options = BuildOptions(
name="flask-production-template",
api_key=os.getenv("HOPX_API_KEY"),
cpu=4,
memory=4096,
disk_gb=20,
context_path=os.getcwd()
)
result = await Template.build(template, options)
print(f"Template configured and built: {result.template_id}")
```
```javascript theme={null}
// Conceptual example
import { Template, BuildOptions, waitForPort } from '@hopx-ai/sdk';
const template = new Template('python:3.11-slim');
// System packages
template.aptInstall('curl', 'git', 'build-essential', 'postgresql-client');
// Working directory
template.setWorkdir('/app');
// Python packages
template.pipInstall('flask', 'gunicorn', 'psycopg2', 'redis');
// Environment variables
template.setEnv('FLASK_ENV', 'production');
template.setEnv('DATABASE_URL', 'postgresql://localhost/db');
template.setEnv('REDIS_URL', 'redis://localhost:6379');
// Expose ports
template.expose(8000);
// Start command with ready check
template.setStartCmd(
'gunicorn -w 4 -b 0.0.0.0:8000 app:app',
waitForPort(8000, { timeout: 30000 })
);
// Build with resource configuration
const options = new BuildOptions({
name: 'flask-production-template',
apiKey: process.env.HOPX_API_KEY,
cpu: 4,
memory: 4096,
diskGb: 20
});
const result = await Template.build(template, options);
console.log(`Template configured and built: ${result.templateId}`);
```
## Best Practices
Set appropriate CPU, memory, and disk based on your application requirements.
Order build steps logically: system packages → language packages → application setup.
Always set ready checks for services that need to be ready before use.
Configure environment variables during template build for consistency.
Expose all ports your application needs to be accessible.
## Related
* **[Building Templates](/core-concepts/templates/building)** - Build custom templates
* **[Listing Templates](/core-concepts/templates/listing)** - List available templates
* **[Getting Template Details](/core-concepts/templates/getting-details)** - View template information
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create sandboxes from templates
* [CLI Template Commands](/cli/commands/template) - Template management from CLI
## Next Steps
* Learn about [Building Templates](/core-concepts/templates/building) to create templates
* Explore [Template Caching](/core-concepts/templates/caching) for build optimization
* Review [Getting Template Details](/core-concepts/templates/getting-details) to verify configuration
# Getting Details
Source: https://docs.hopx.ai/core-concepts/templates/getting-details
Get detailed information about templates in HopX. View template configuration, resources (vCPU, memory, disk), build steps, pre-installed packages, and metadata. Essential for choosing the right template and understanding available resources. Includes Python and JavaScript SDK examples and REST API endpoints.
Retrieve detailed information about a specific template, including full configuration, resources, features, and build information.
## Overview
Getting template details helps you:
* View complete template configuration
* Check resource specifications (min/max/default)
* Review available features and capabilities
* Access build information and status
* Verify template availability before use
Template details include more information than the list view, including full configuration, build steps, and organization-specific details.
## Get Template by Name
Get detailed information about a specific template:
```python theme={null}
from hopx_ai import Sandbox
# Get template details
template = Sandbox.get_template("code-interpreter")
print(f"Template: {template.display_name}")
print(f"Name: {template.name}")
print(f"Description: {template.description}")
print(f"Category: {template.category}")
print(f"Language: {template.language}")
print(f"Status: {template.status}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Get template details
const template = await Sandbox.getTemplate('code-interpreter');
console.log(`Template: ${template.displayName}`);
console.log(`Name: ${template.name}`);
console.log(`Description: ${template.description}`);
console.log(`Category: ${template.category}`);
console.log(`Language: ${template.language}`);
console.log(`Status: ${template.status}`);
```
## Resource Specifications
View resource specifications (default, min, max):
```python theme={null}
from hopx_ai import Sandbox
template = Sandbox.get_template("code-interpreter")
# Default resources
if template.default_resources:
res = template.default_resources
print(f"Default Resources:")
print(f" vCPU: {res.vcpu}")
print(f" Memory: {res.memory_mb}MB")
print(f" Disk: {res.disk_gb}GB")
# Minimum resources
if template.min_resources:
min_res = template.min_resources
print(f"\nMinimum Resources:")
print(f" vCPU: {min_res.vcpu}")
print(f" Memory: {min_res.memory_mb}MB")
print(f" Disk: {min_res.disk_gb}GB")
# Maximum resources
if template.max_resources:
max_res = template.max_resources
print(f"\nMaximum Resources:")
print(f" vCPU: {max_res.vcpu}")
print(f" Memory: {max_res.memory_mb}MB")
print(f" Disk: {max_res.disk_gb}GB")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const template = await Sandbox.getTemplate('code-interpreter');
// Default resources
if (template.defaultResources) {
const res = template.defaultResources;
console.log('Default Resources:');
console.log(` vCPU: ${res.vcpu}`);
console.log(` Memory: ${res.memoryMb}MB`);
console.log(` Disk: ${res.diskGb}GB`);
}
// Minimum resources
if (template.minResources) {
const minRes = template.minResources;
console.log('\nMinimum Resources:');
console.log(` vCPU: ${minRes.vcpu}`);
console.log(` Memory: ${minRes.memoryMb}MB`);
console.log(` Disk: ${minRes.diskGb}GB`);
}
// Maximum resources
if (template.maxResources) {
const maxRes = template.maxResources;
console.log('\nMaximum Resources:');
console.log(` vCPU: ${maxRes.vcpu}`);
console.log(` Memory: ${maxRes.memoryMb}MB`);
console.log(` Disk: ${maxRes.diskGb}GB`);
}
```
## Features and Tags
View template features and tags:
```python theme={null}
from hopx_ai import Sandbox
template = Sandbox.get_template("code-interpreter")
# Features
if template.features:
print("Features:")
for feature in template.features:
print(f" • {feature}")
# Tags
if template.tags:
print("\nTags:")
for tag in template.tags:
print(f" • {tag}")
# Popularity
if template.popularity_score:
print(f"\nPopularity Score: {template.popularity_score}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const template = await Sandbox.getTemplate('code-interpreter');
// Features
if (template.features) {
console.log('Features:');
for (const feature of template.features) {
console.log(` • ${feature}`);
}
}
// Tags
if (template.tags) {
console.log('\nTags:');
for (const tag of template.tags) {
console.log(` • ${tag}`);
}
}
// Popularity
if (template.popularityScore) {
console.log(`\nPopularity Score: ${template.popularityScore}`);
}
```
## Template Status and Availability
Check template status and availability:
```python theme={null}
from hopx_ai import Sandbox
from hopx_ai.errors import NotFoundError
try:
template = Sandbox.get_template("code-interpreter")
print(f"Status: {template.status}")
print(f"Active: {template.is_active}")
print(f"Public: {template.is_public}")
if template.status == "active":
print("✅ Template is available for use")
elif template.status == "building":
print("⏳ Template is currently being built")
elif template.status == "failed":
print("❌ Template build failed")
else:
print(f"⚠️ Template status: {template.status}")
except NotFoundError:
print("❌ Template not found")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import { NotFoundError } from '@hopx-ai/sdk';
try {
const template = await Sandbox.getTemplate('code-interpreter');
console.log(`Status: ${template.status}`);
console.log(`Active: ${template.isActive}`);
console.log(`Public: ${template.isPublic}`);
if (template.status === 'active') {
console.log('✅ Template is available for use');
} else if (template.status === 'building') {
console.log('⏳ Template is currently being built');
} else if (template.status === 'failed') {
console.log('❌ Template build failed');
} else {
console.log(`⚠️ Template status: ${template.status}`);
}
} catch (error) {
if (error instanceof NotFoundError) {
console.log('❌ Template not found');
} else {
throw error;
}
}
```
## Organization-Specific Templates
Check if template is organization-specific:
```python theme={null}
from hopx_ai import Sandbox
template = Sandbox.get_template("my-custom-template")
if template.organization_id:
print(f"Organization Template: {template.organization_id}")
print("This is a custom template for your organization")
else:
print("Public Template")
print("Available to all users")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const template = await Sandbox.getTemplate('my-custom-template');
if (template.organizationId) {
console.log(`Organization Template: ${template.organizationId}`);
console.log('This is a custom template for your organization');
} else {
console.log('Public Template');
console.log('Available to all users');
}
```
## Complete Example
Here's a complete example showing template details:
```python theme={null}
from hopx_ai import Sandbox
from hopx_ai.errors import NotFoundError
def show_template_details(template_name: str):
try:
template = Sandbox.get_template(template_name)
print(f"📋 {template.display_name}")
print(f" Name: {template.name}")
print(f" ID: {template.id}")
print()
if template.description:
print(f"📝 Description:")
print(f" {template.description}")
print()
print(f"🏷️ Metadata:")
print(f" Category: {template.category or 'N/A'}")
print(f" Language: {template.language or 'N/A'}")
print(f" Status: {template.status}")
print(f" Active: {template.is_active}")
print(f" Public: {template.is_public}")
print()
if template.default_resources:
res = template.default_resources
print(f"💻 Default Resources:")
print(f" vCPU: {res.vcpu}")
print(f" Memory: {res.memory_mb}MB")
print(f" Disk: {res.disk_gb}GB")
print()
if template.min_resources or template.max_resources:
print(f"📊 Resource Limits:")
if template.min_resources:
min_res = template.min_resources
print(f" Min: {min_res.vcpu}vCPU, {min_res.memory_mb}MB RAM")
if template.max_resources:
max_res = template.max_resources
print(f" Max: {max_res.vcpu}vCPU, {max_res.memory_mb}MB RAM")
print()
if template.features:
print(f"✨ Features:")
for feature in template.features:
print(f" • {feature}")
print()
if template.tags:
print(f"🏷️ Tags:")
for tag in template.tags:
print(f" • {tag}")
print()
if template.docs_url:
print(f"📚 Documentation: {template.docs_url}")
print()
if template.organization_id:
print(f"🏢 Organization: {template.organization_id}")
print(" (Custom template)")
except NotFoundError:
print(f"❌ Template '{template_name}' not found")
# Show details for a template
show_template_details("code-interpreter")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import { NotFoundError } from '@hopx-ai/sdk';
async function showTemplateDetails(templateName) {
try {
const template = await Sandbox.getTemplate(templateName);
console.log(`📋 ${template.displayName}`);
console.log(` Name: ${template.name}`);
console.log(` ID: ${template.id}`);
console.log();
if (template.description) {
console.log('📝 Description:');
console.log(` ${template.description}`);
console.log();
}
console.log('🏷️ Metadata:');
console.log(` Category: ${template.category || 'N/A'}`);
console.log(` Language: ${template.language || 'N/A'}`);
console.log(` Status: ${template.status}`);
console.log(` Active: ${template.isActive}`);
console.log(` Public: ${template.isPublic}`);
console.log();
if (template.defaultResources) {
const res = template.defaultResources;
console.log('💻 Default Resources:');
console.log(` vCPU: ${res.vcpu}`);
console.log(` Memory: ${res.memoryMb}MB`);
console.log(` Disk: ${res.diskGb}GB`);
console.log();
}
if (template.minResources || template.maxResources) {
console.log('📊 Resource Limits:');
if (template.minResources) {
const minRes = template.minResources;
console.log(` Min: ${minRes.vcpu}vCPU, ${minRes.memoryMb}MB RAM`);
}
if (template.maxResources) {
const maxRes = template.maxResources;
console.log(` Max: ${maxRes.vcpu}vCPU, ${maxRes.memoryMb}MB RAM`);
}
console.log();
}
if (template.features) {
console.log('✨ Features:');
for (const feature of template.features) {
console.log(` • ${feature}`);
}
console.log();
}
if (template.tags) {
console.log('🏷️ Tags:');
for (const tag of template.tags) {
console.log(` • ${tag}`);
}
console.log();
}
if (template.docsUrl) {
console.log(`📚 Documentation: ${template.docsUrl}`);
console.log();
}
if (template.organizationId) {
console.log(`🏢 Organization: ${template.organizationId}`);
console.log(' (Custom template)');
}
} catch (error) {
if (error instanceof NotFoundError) {
console.log(`❌ Template '${templateName}' not found`);
} else {
throw error;
}
}
}
// Show details for a template
await showTemplateDetails('code-interpreter');
```
## Best Practices
Always get template details to verify resources and features before creating sandboxes.
Verify template status is "active" before using it to create sandboxes.
Check default, min, and max resources to ensure they meet your requirements.
Review features list to confirm template has capabilities you need.
Always handle NotFoundError when getting template details.
## Related
* **[Listing Templates](/core-concepts/templates/listing)** - List all available templates
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create sandboxes from templates
* **SDK**: [Sandbox.get\_template()](/sdk/python/sandbox#get_template) - Python SDK method
* **API**: [GET /v1/templates/:name](/api/control-plane/get-template) - Control Plane API endpoint
* [CLI Template Commands](/cli/commands/template) - Template management from CLI
## Next Steps
* Learn about [Listing Templates](/core-concepts/templates/listing) to discover available templates
* Explore [Building Templates](/core-concepts/templates/building) to create custom templates
* Review [Template Configuration](/core-concepts/templates/configuration) for advanced setup
# Templates
Source: https://docs.hopx.ai/core-concepts/templates/index
Complete guide to HopX templates - listing, viewing, building, and configuring templates for sandbox creation. Templates define the base environment for HopX sandboxes. Learn how to list pre-built templates, view template details, build custom templates from Docker images, configure resources, and optimize with caching strategies.
Templates define the base environment for HopX sandboxes. This hub covers all template operations, from listing pre-built templates to building custom templates with Docker images.
## Related
* [CLI Template Commands](/cli/commands/template) - Template management from CLI
## What You'll Learn
* How to list and view available templates
* How to get detailed template information
* How to build custom templates from Docker images
* How to configure template resources and settings
* How to cache and optimize templates
## Template Management Overview
| Operation | SDK Method | API Endpoint |
| --------------------------------------------------------------- | ----------------------------- | -------------------------- |
| **[Listing](/core-concepts/templates/listing)** | `Sandbox.list_templates()` | `GET /v1/templates` |
| **[Getting Details](/core-concepts/templates/getting-details)** | `Sandbox.get_template()` | `GET /v1/templates/:name` |
| **[Building](/core-concepts/templates/building)** | `TemplateBuilder` | `POST /v1/templates/build` |
| **[Configuration](/core-concepts/templates/configuration)** | `TemplateBuilder.configure()` | Template configuration |
| **[Caching](/core-concepts/templates/caching)** | Template caching | Cache management |
## Core Concepts
### Listing Templates
Discover available pre-built and custom templates.
* **[Listing Templates](/core-concepts/templates/listing)** - List available templates
* **SDK**: [Python: Sandbox.list\_templates()](/sdk/python/sandbox#list_templates) | [JavaScript: Sandbox.listTemplates()](/sdk/javascript/sandbox#listtemplates)
* **API**: [GET /v1/templates](/api/control-plane/list-templates)
### Getting Template Details
View detailed information about specific templates.
* **[Getting Template Details](/core-concepts/templates/getting-details)** - View template information
* **SDK**: [Python: Sandbox.get\_template()](/sdk/python/sandbox#get_template) | [JavaScript: Sandbox.getTemplate()](/sdk/javascript/sandbox#gettemplate)
* **API**: [GET /v1/templates/:name](/api/control-plane/get-template)
### Building Templates
Create custom templates from Docker images and build steps.
* **[Building Templates](/core-concepts/templates/building)** - Build custom templates
* **SDK**: [Python: TemplateBuilder](/sdk/python/template-builder) | [JavaScript: TemplateBuilder](/sdk/javascript/template-builder)
* **API**: [POST /v1/templates/build](/api/control-plane/build-template)
### Template Configuration
Configure template resources, environment, and build steps.
* **[Template Configuration](/core-concepts/templates/configuration)** - Configure templates
* **SDK**: [Python: TemplateBuilder.configure()](/sdk/python/template-builder#configure) | [JavaScript: TemplateBuilder.configure()](/sdk/javascript/template-builder#configure)
* **API**: Template configuration in build endpoint
### Template Caching
Optimize template loading with caching strategies.
* **[Template Caching](/core-concepts/templates/caching)** - Cache templates for faster creation
* **SDK**: Template caching options | **API**: Cache management endpoints
## SDK Reference
### Python SDK
Complete reference for Python template operations.
* **[Sandbox.list\_templates()](/sdk/python/sandbox#list_templates)** - List templates
* **[Sandbox.get\_template()](/sdk/python/sandbox#get_template)** - Get template details
* **[TemplateBuilder](/sdk/python/template-builder)** - Build custom templates
* `from_image()` - Create from Docker image
* `configure()` - Configure resources
* `build()` - Build template
### JavaScript SDK
Complete reference for JavaScript/TypeScript template operations.
* **[Sandbox.listTemplates()](/sdk/javascript/sandbox#listtemplates)** - List templates
* **[Sandbox.getTemplate()](/sdk/javascript/sandbox#gettemplate)** - Get template details
* **[TemplateBuilder](/sdk/javascript/template-builder)** - Build custom templates
* `fromImage()` - Create from Docker image
* `configure()` - Configure resources
* `build()` - Build template
## API Reference
### Control Plane API
REST API endpoints for template operations.
* **[Control Plane API Overview](/api/control-plane/overview)** - API overview
* **[List Templates](/api/control-plane/list-templates)** - `GET /v1/templates` - List all templates
* **[Get Template](/api/control-plane/get-template)** - `GET /v1/templates/:name` - Get template details
* **[Build Template](/api/control-plane/build-template)** - `POST /v1/templates/build` - Build custom template
## Quick Start
If you're new to templates, start here:
1. **[Listing Templates](/core-concepts/templates/listing)** - Discover available templates
2. **[Getting Template Details](/core-concepts/templates/getting-details)** - View template information
3. **[Building Templates](/core-concepts/templates/building)** - Create your first custom template
## Related Topics
* **[Sandboxes](/core-concepts/sandboxes/creating)** - Create sandboxes from templates
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Execute code in template environments
* **[Environment Variables](/core-concepts/environment/getting)** - Configure template environments
* **[File Operations](/core-concepts/filesystem/reading)** - Work with files in template-based sandboxes
## Next Steps
* Learn about [Creating Sandboxes](/core-concepts/sandboxes/creating) from templates
* Explore [Building Templates](/core-concepts/templates/building) for custom environments
* Review [Template Configuration](/core-concepts/templates/configuration) for advanced setup
* Check out [Template Caching](/core-concepts/templates/caching) for optimization
# Listing
Source: https://docs.hopx.ai/core-concepts/templates/listing
List available HopX sandbox templates and view their configurations. Discover pre-built templates for Python, JavaScript, Ubuntu, and other environments. Learn how to filter templates by category, language, or features, view template details, and choose the right template for your use case. Includes Python and JavaScript SDK examples and REST API endpoints.
List all available templates to discover pre-configured environments for your sandboxes. Templates define the base system, default resources, and pre-installed packages.
## Overview
Listing templates helps you:
* Discover available pre-configured environments
* Find templates by category or language
* Compare template resources and features
* Choose the right template for your use case
Templates include both public templates (available to all users) and organization-specific templates (custom templates you've built).
## List All Templates
Get a list of all available templates:
```python theme={null}
from hopx_ai import Sandbox
# List all templates
templates = Sandbox.list_templates()
print(f"Found {len(templates)} templates:")
for template in templates:
print(f" - {template.name}: {template.display_name}")
if template.description:
print(f" {template.description}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// List all templates
const templates = await Sandbox.listTemplates();
console.log(`Found ${templates.length} templates:`);
for (const template of templates) {
console.log(` - ${template.name}: ${template.displayName}`);
if (template.description) {
console.log(` ${template.description}`);
}
}
```
## Filter by Category
Filter templates by category:
```python theme={null}
from hopx_ai import Sandbox
# Filter by category
dev_templates = Sandbox.list_templates(category="development")
print(f"Development templates: {len(dev_templates)}")
infra_templates = Sandbox.list_templates(category="infrastructure")
print(f"Infrastructure templates: {len(infra_templates)}")
os_templates = Sandbox.list_templates(category="operating-system")
print(f"OS templates: {len(os_templates)}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Filter by category
const devTemplates = await Sandbox.listTemplates({ category: 'development' });
console.log(`Development templates: ${devTemplates.length}`);
const infraTemplates = await Sandbox.listTemplates({ category: 'infrastructure' });
console.log(`Infrastructure templates: ${infraTemplates.length}`);
const osTemplates = await Sandbox.listTemplates({ category: 'operating-system' });
console.log(`OS templates: ${osTemplates.length}`);
```
## Filter by Language
Filter templates by programming language:
```python theme={null}
from hopx_ai import Sandbox
# Filter by language
python_templates = Sandbox.list_templates(language="python")
print(f"Python templates: {len(python_templates)}")
for t in python_templates:
print(f" - {t.name}: {t.display_name}")
nodejs_templates = Sandbox.list_templates(language="nodejs")
print(f"\nNode.js templates: {len(nodejs_templates)}")
for t in nodejs_templates:
print(f" - {t.name}: {t.display_name}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Filter by language
const pythonTemplates = await Sandbox.listTemplates({ language: 'python' });
console.log(`Python templates: ${pythonTemplates.length}`);
for (const t of pythonTemplates) {
console.log(` - ${t.name}: ${t.displayName}`);
}
const nodejsTemplates = await Sandbox.listTemplates({ language: 'nodejs' });
console.log(`\nNode.js templates: ${nodejsTemplates.length}`);
for (const t of nodejsTemplates) {
console.log(` - ${t.name}: ${t.displayName}`);
}
```
## Template Information
Access template details from the list:
```python theme={null}
from hopx_ai import Sandbox
templates = Sandbox.list_templates()
for template in templates:
print(f"\n{template.display_name} ({template.name})")
print(f" Category: {template.category}")
print(f" Language: {template.language or 'N/A'}")
if template.default_resources:
res = template.default_resources
print(f" Resources: {res.vcpu} vCPU, {res.memory_mb}MB RAM, {res.disk_gb}GB disk")
if template.features:
print(f" Features: {', '.join(template.features)}")
print(f" Status: {template.status}")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const templates = await Sandbox.listTemplates();
for (const template of templates) {
console.log(`\n${template.displayName} (${template.name})`);
console.log(` Category: ${template.category}`);
console.log(` Language: ${template.language || 'N/A'}`);
if (template.defaultResources) {
const res = template.defaultResources;
console.log(` Resources: ${res.vcpu} vCPU, ${res.memoryMb}MB RAM, ${res.diskGb}GB disk`);
}
if (template.features) {
console.log(` Features: ${template.features.join(', ')}`);
}
console.log(` Status: ${template.status}`);
}
```
## Find Template by Name
Search for a specific template:
```python theme={null}
from hopx_ai import Sandbox
# List all and find by name
templates = Sandbox.list_templates()
# Find specific template
code_interpreter = next(
(t for t in templates if t.name == "code-interpreter"),
None
)
if code_interpreter:
print(f"Found: {code_interpreter.display_name}")
print(f"Description: {code_interpreter.description}")
else:
print("Template not found")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// List all and find by name
const templates = await Sandbox.listTemplates();
// Find specific template
const codeInterpreter = templates.find(t => t.name === 'code-interpreter');
if (codeInterpreter) {
console.log(`Found: ${codeInterpreter.displayName}`);
console.log(`Description: ${codeInterpreter.description}`);
} else {
console.log('Template not found');
}
```
## Complete Example
Here's a complete example showing template discovery:
```python theme={null}
from hopx_ai import Sandbox
print("🔍 Discovering Templates\n")
# List all templates
all_templates = Sandbox.list_templates()
print(f"Total templates: {len(all_templates)}\n")
# Group by category
categories = {}
for template in all_templates:
cat = template.category or "uncategorized"
if cat not in categories:
categories[cat] = []
categories[cat].append(template)
# Display by category
for category, templates in categories.items():
print(f"📁 {category.title()} ({len(templates)} templates)")
for template in templates:
print(f" • {template.display_name}")
if template.default_resources:
res = template.default_resources
print(f" {res.vcpu}vCPU, {res.memory_mb}MB RAM")
print()
# Find Python templates
python_templates = Sandbox.list_templates(language="python")
print(f"🐍 Python Templates: {len(python_templates)}")
for t in python_templates[:5]: # Show first 5
print(f" - {t.name}: {t.display_name}")
# Find a specific template
code_interpreter = next(
(t for t in all_templates if t.name == "code-interpreter"),
None
)
if code_interpreter:
print(f"\n✅ Found code-interpreter:")
print(f" {code_interpreter.description}")
if code_interpreter.default_resources:
res = code_interpreter.default_resources
print(f" Resources: {res.vcpu} vCPU, {res.memory_mb}MB RAM")
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
console.log('🔍 Discovering Templates\n');
// List all templates
const allTemplates = await Sandbox.listTemplates();
console.log(`Total templates: ${allTemplates.length}\n`);
// Group by category
const categories = {};
for (const template of allTemplates) {
const cat = template.category || 'uncategorized';
if (!categories[cat]) {
categories[cat] = [];
}
categories[cat].push(template);
}
// Display by category
for (const [category, templates] of Object.entries(categories)) {
console.log(`📁 ${category.charAt(0).toUpperCase() + category.slice(1)} (${templates.length} templates)`);
for (const template of templates) {
console.log(` • ${template.displayName}`);
if (template.defaultResources) {
const res = template.defaultResources;
console.log(` ${res.vcpu}vCPU, ${res.memoryMb}MB RAM`);
}
}
console.log();
}
// Find Python templates
const pythonTemplates = await Sandbox.listTemplates({ language: 'python' });
console.log(`🐍 Python Templates: ${pythonTemplates.length}`);
for (const t of pythonTemplates.slice(0, 5)) { // Show first 5
console.log(` - ${t.name}: ${t.displayName}`);
}
// Find a specific template
const codeInterpreter = allTemplates.find(t => t.name === 'code-interpreter');
if (codeInterpreter) {
console.log(`\n✅ Found code-interpreter:`);
console.log(` ${codeInterpreter.description}`);
if (codeInterpreter.defaultResources) {
const res = codeInterpreter.defaultResources;
console.log(` Resources: ${res.vcpu} vCPU, ${res.memoryMb}MB RAM`);
}
}
```
## Best Practices
Always list templates first to discover available options before creating sandboxes.
Use category and language filters to narrow down templates relevant to your needs.
Review default resources (vCPU, memory, disk) to ensure they meet your requirements.
Check template status (active, building, etc.) before using templates.
Use template names (not IDs) when creating sandboxes for better readability.
## Related
* **[Getting Template Details](/core-concepts/templates/getting-details)** - Get detailed template information
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create sandboxes from templates
* **SDK**: [Sandbox.list\_templates()](/sdk/python/sandbox#list_templates) - Python SDK method
* **API**: [GET /v1/templates](/api/control-plane/list-templates) - Control Plane API endpoint
* [CLI Template Commands](/cli/commands/template) - Template management from CLI
## Next Steps
* Learn about [Getting Template Details](/core-concepts/templates/getting-details) for complete template information
* Explore [Building Templates](/core-concepts/templates/building) to create custom templates
* Review [Template Configuration](/core-concepts/templates/configuration) for advanced setup
# WebSocket Terminal
Source: https://docs.hopx.ai/core-concepts/terminal/websocket
Connect to an interactive terminal via WebSocket for real-time command execution in HopX sandboxes. Access interactive shell sessions, execute commands in real-time, and stream terminal output. Perfect for interactive development, debugging, and system administration. Includes Python and JavaScript SDK examples and WebSocket API endpoints.
The WebSocket terminal provides interactive, real-time access to a PTY (pseudo-terminal) in your sandbox. This enables you to run interactive commands, monitor output in real-time, and handle terminal-specific features like resizing.
## Prerequisites
Before you begin, make sure you have:
* **Active sandbox** - A running sandbox (see [Creating Sandboxes](/core-concepts/sandboxes/creating))
* **WebSocket library** - For Python: `pip install websockets` (for JavaScript, WebSocket is built-in)
* **Understanding of async/await** - Familiarity with asynchronous programming patterns
* **Terminal access** - Basic understanding of terminal/command-line operations
## Overview
The WebSocket terminal is ideal for:
* Interactive command-line tools and REPLs
* Real-time monitoring of long-running processes
* Terminal applications that require PTY support
* Building terminal UIs or dashboards
* Debugging and troubleshooting
The WebSocket terminal requires the `websockets` library for Python. Install it with: `pip install websockets`
## Connecting to Terminal
Connect to the terminal using the `terminal` resource:
```python theme={null}
from hopx_ai import Sandbox
import asyncio
async def connect_terminal():
sandbox = Sandbox.create(template="code-interpreter")
# Connect to terminal
async with await sandbox.terminal.connect() as ws:
# Terminal is ready for input
pass
# Clean up
sandbox.kill()
asyncio.run(connect_terminal())
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
// Connect to terminal
const ws = await sandbox.terminal.connect();
// Terminal is ready for input
// ... use terminal ...
await sandbox.kill();
```
## Sending Input
Send commands and input to the terminal:
```python theme={null}
async def send_commands():
sandbox = Sandbox.create(template="code-interpreter")
async with await sandbox.terminal.connect() as ws:
# Send a command (include \n to execute)
await sandbox.terminal.send_input(ws, "ls -la\n")
# Send another command
await sandbox.terminal.send_input(ws, "cd /workspace\n")
# Send interactive input
await sandbox.terminal.send_input(ws, "python3\n")
await sandbox.terminal.send_input(ws, "print('Hello')\n")
await sandbox.terminal.send_input(ws, "exit()\n")
sandbox.kill()
asyncio.run(send_commands())
```
```javascript theme={null}
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
const ws = await sandbox.terminal.connect();
// Send commands
sandbox.terminal.sendInput(ws, 'ls -la\n');
sandbox.terminal.sendInput(ws, 'cd /workspace\n');
// Send interactive input
sandbox.terminal.sendInput(ws, 'python3\n');
sandbox.terminal.sendInput(ws, "print('Hello')\n");
sandbox.terminal.sendInput(ws, 'exit()\n');
await sandbox.kill();
```
## Receiving Output
Receive terminal output in real-time using async iteration:
```python theme={null}
async def receive_output():
sandbox = Sandbox.create(template="code-interpreter")
async with await sandbox.terminal.connect() as ws:
# Send command
await sandbox.terminal.send_input(ws, "echo 'Hello World'\n")
# Receive output
async for message in sandbox.terminal.iter_output(ws):
if message['type'] == 'output':
print(message['data'], end='')
elif message['type'] == 'exit':
print(f"\nProcess exited with code: {message['code']}")
break
sandbox.kill()
asyncio.run(receive_output())
```
```javascript theme={null}
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
const ws = await sandbox.terminal.connect();
// Send command
sandbox.terminal.sendInput(ws, "echo 'Hello World'\n");
// Receive output
for await (const message of sandbox.terminal.output(ws)) {
if (message.type === 'output') {
process.stdout.write(message.data);
} else if (message.type === 'exit') {
console.log(`\nProcess exited with code: ${message.code}`);
break;
}
}
await sandbox.kill();
```
## Resizing Terminal
Resize the terminal window to match your display:
```python theme={null}
async def resize_terminal():
sandbox = Sandbox.create(template="code-interpreter")
async with await sandbox.terminal.connect() as ws:
# Resize to 120 columns, 40 rows
await sandbox.terminal.resize(ws, cols=120, rows=40)
# Send command that benefits from larger terminal
await sandbox.terminal.send_input(ws, "ls -la\n")
async for message in sandbox.terminal.iter_output(ws):
if message['type'] == 'output':
print(message['data'], end='')
elif message['type'] == 'exit':
break
sandbox.kill()
asyncio.run(resize_terminal())
```
```javascript theme={null}
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
const ws = await sandbox.terminal.connect();
// Resize terminal
sandbox.terminal.resize(ws, 120, 40);
// Send command
sandbox.terminal.sendInput(ws, 'ls -la\n');
// Receive output
for await (const message of sandbox.terminal.output(ws)) {
if (message.type === 'output') {
process.stdout.write(message.data);
} else if (message.type === 'exit') {
break;
}
}
await sandbox.kill();
```
## Complete Example
Here's a complete example that demonstrates interactive terminal usage:
```python theme={null}
from hopx_ai import Sandbox
import asyncio
async def interactive_terminal():
sandbox = Sandbox.create(template="code-interpreter")
try:
async with await sandbox.terminal.connect() as ws:
# Resize terminal
await sandbox.terminal.resize(ws, cols=80, rows=24)
# Run a series of commands
commands = [
"pwd\n",
"whoami\n",
"uname -a\n",
"python3 --version\n"
]
for cmd in commands:
await sandbox.terminal.send_input(ws, cmd)
# Receive output for this command
async for message in sandbox.terminal.iter_output(ws):
if message['type'] == 'output':
print(message['data'], end='')
elif message['type'] == 'exit':
# Command completed, move to next
break
print() # Blank line between commands
finally:
sandbox.kill()
asyncio.run(interactive_terminal())
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function interactiveTerminal() {
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
try {
const ws = await sandbox.terminal.connect();
// Resize terminal
sandbox.terminal.resize(ws, 80, 24);
// Run a series of commands
const commands = [
'pwd\n',
'whoami\n',
'uname -a\n',
'python3 --version\n'
];
for (const cmd of commands) {
sandbox.terminal.sendInput(ws, cmd);
// Receive output for this command
for await (const message of sandbox.terminal.output(ws)) {
if (message.type === 'output') {
process.stdout.write(message.data);
} else if (message.type === 'exit') {
// Command completed, move to next
break;
}
}
console.log(); // Blank line between commands
}
} finally {
await sandbox.kill();
}
}
interactiveTerminal();
```
## Message Types
The terminal sends different message types:
* **`output`**: Terminal output data
```json theme={null}
{"type": "output", "data": "command output text"}
```
* **`exit`**: Process exit notification
```json theme={null}
{"type": "exit", "code": 0}
```
## Error Handling
Handle connection errors and timeouts:
```python theme={null}
import asyncio
from hopx_ai import Sandbox
async def terminal_with_error_handling():
sandbox = Sandbox.create(template="code-interpreter")
try:
async with await sandbox.terminal.connect(timeout=30) as ws:
await sandbox.terminal.send_input(ws, "invalid-command-that-fails\n")
async for message in sandbox.terminal.iter_output(ws):
if message['type'] == 'output':
print(message['data'], end='')
elif message['type'] == 'exit':
exit_code = message['code']
if exit_code != 0:
print(f"\nCommand failed with exit code: {exit_code}")
break
except Exception as e:
print(f"Terminal error: {e}")
finally:
sandbox.kill()
asyncio.run(terminal_with_error_handling())
```
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function terminalWithErrorHandling() {
const sandbox = await Sandbox.create({
template: 'code-interpreter'
});
try {
const ws = await sandbox.terminal.connect();
sandbox.terminal.sendInput(ws, 'invalid-command-that-fails\n');
for await (const message of sandbox.terminal.output(ws)) {
if (message.type === 'output') {
process.stdout.write(message.data);
} else if (message.type === 'exit') {
const exitCode = message.code;
if (exitCode !== 0) {
console.log(`\nCommand failed with exit code: ${exitCode}`);
}
break;
}
}
} catch (error) {
console.error(`Terminal error: ${error.message}`);
} finally {
await sandbox.kill();
}
}
terminalWithErrorHandling();
```
## Best Practices
**Use async context managers** in Python to ensure proper WebSocket cleanup. The `async with` statement automatically closes the connection.
**Include newline characters** (`\n`) when sending commands to execute them immediately. Without `\n`, the command waits for more input.
**Terminal connections are stateful**. Each connection maintains its own shell session. If you need a fresh environment, create a new terminal connection.
**Resize the terminal** before running commands that format output based on terminal width (like `ls -la` or `tree`).
## API Reference
### Python SDK
* `sandbox.terminal.connect(*, timeout=30)` - Connect to terminal WebSocket
* `sandbox.terminal.send_input(ws, data)` - Send input to terminal
* `sandbox.terminal.resize(ws, cols, rows)` - Resize terminal window
* `sandbox.terminal.iter_output(ws)` - Async iterator for terminal messages
### JavaScript SDK
* `sandbox.terminal.connect()` - Connect to terminal WebSocket
* `sandbox.terminal.sendInput(ws, data)` - Send input to terminal
* `sandbox.terminal.resize(ws, cols, rows)` - Resize terminal window
* `sandbox.terminal.output(ws)` - Async iterator for terminal messages
### API Endpoint
* **WebSocket**: `/terminal` - Connect to interactive terminal
* **Message Types**: `input`, `resize`, `output`, `exit`
## Related
* **[Running Commands](/core-concepts/commands/running)** - Execute shell commands synchronously
* **[Background Commands](/core-concepts/commands/background)** - Run commands in background
* **SDK**: [sandbox.terminal.connect()](/sdk/python/terminal#connect) - Python SDK method
* [CLI Terminal](/cli/commands/terminal) - Terminal access from CLI
## Next Steps
* Learn about [Running Commands](/core-concepts/commands/running) for synchronous execution
* Explore [Background Commands](/core-concepts/commands/background) for non-blocking tasks
* Review [Code Execution](/core-concepts/code-execution/synchronous) for programmatic execution
# MCP Server Integration
Source: https://docs.hopx.ai/guides/integrations/mcp-integration
Enable AI assistants to execute code in isolated HopX sandboxes using the Model Context Protocol. Connect Claude, Cursor, and other AI assistants to HopX for secure code execution.
Give your AI assistant **superpowers** with secure, isolated code execution through the [Model Context Protocol (MCP)](https://modelcontextprotocol.io). The HopX MCP server enables Claude, Cursor, and other AI assistants to execute Python, JavaScript, Bash, and Go code in blazing-fast (0.1s startup), isolated cloud containers.
MCP is a protocol that allows AI assistants to interact with external tools and services. The HopX MCP server provides a standardized way for AI assistants to execute code safely in isolated environments.
## What You'll Learn
In this guide, you'll learn how to:
* Install the HopX MCP server using `uvx`
* Configure MCP server in Cursor, VS Code, Claude Desktop, and other IDEs
* Enable AI assistants to execute code in isolated sandboxes
* Use different execution modes (isolated, persistent, rich, background)
* Set up multi-step workflows and rich output capture
* Understand security and best practices for MCP integration
## Prerequisites
Before you begin, make sure you have:
* **Python 3.14+** installed (required for `uvx`)
* **`uvx`** installed (get it from [uv's documentation](https://docs.astral.sh/uv/))
* **HopX API key** from [hopx.ai](https://hopx.ai)
* **MCP-compatible IDE** (Cursor, VS Code, Claude Desktop, Windsurf, etc.)
* Basic familiarity with your IDE's configuration files
## Quick Start
The easiest way to get started:
1. Install the MCP server: `uvx HopX-mcp`
2. Get your API key from [hopx.ai](https://hopx.ai)
3. Configure your IDE with the MCP server
4. Your AI assistant can now execute code safely
## Installation
Install the HopX MCP server using `uvx`:
```bash theme={null}
uvx hopx-mcp
```
You need Python 3.14+ and `uvx` installed. Get `uvx` from [uv's documentation](https://docs.astral.sh/uv/).
## Get Your API key
Sign up at [hopx.ai](https://hopx.ai) to get your free API key. You'll need this to configure the MCP server.
## Configuration
After installing with `uvx hopx-mcp`, configure your IDE by adding the MCP server configuration:
Add to `.cursor/mcp.json` in your project or workspace:
```json theme={null}
{
"mcpServers": {
"HopX-sandbox": {
"command": "uvx",
"args": ["hopx-mcp"],
"env": {
"HOPX_API_KEY": "your-API key-here"
}
}
}
}
```
Add to `.vscode/mcp.json` in your workspace:
```json theme={null}
{
"mcpServers": {
"HopX-sandbox": {
"command": "uvx",
"args": ["hopx-mcp"],
"env": {
"HOPX_API_KEY": "your-API key-here"
}
}
}
}
```
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS or `%APPDATA%\Claude\claude_desktop_config.json` on Windows:
```json theme={null}
{
"mcpServers": {
"HopX-sandbox": {
"command": "uvx",
"args": ["hopx-mcp"],
"env": {
"HOPX_API_KEY": "your-API key-here"
}
}
}
}
```
Restart Claude Desktop after making changes.
Add to `.windsurf/mcp.json` in your project:
```json theme={null}
{
"mcpServers": {
"HopX-sandbox": {
"command": "uvx",
"args": ["hopx-mcp"],
"env": {
"HOPX_API_KEY": "your-API key-here"
}
}
}
}
```
For other IDEs (Visual Studio, Cline, Continue.dev, Zed, Codex), use a similar configuration structure. Refer to your IDE's MCP documentation for the exact configuration file location and format.
Replace `your-API key-here` with your actual API key from [hopx.ai](https://hopx.ai).
## What This Enables
With the HopX MCP server, your AI assistant can:
* ✅ **Execute Python, JavaScript, Bash, and Go** in isolated containers
* ✅ **Analyze data** with pandas, numpy, matplotlib (pre-installed)
* ✅ **Test code snippets** before you use them in production
* ✅ **Process data** securely without touching your local system
* ✅ **Run system commands** safely in isolated environments
* ✅ **Install packages** and test integrations on-the-fly
All executions happen in **secure, ephemeral cloud containers** that auto-destroy after use. Your local system stays clean and protected.
## Execution Modes
The HopX MCP server provides a unified `execute_code()` function with multiple execution modes:
* **`isolated`** (default) - One-shot execution: Creates a new sandbox, executes code, returns output, and auto-destroys. Perfect for quick scripts and data analysis.
* **`persistent`** - Execute in an existing sandbox: Use for multi-step workflows where you need to maintain state between executions.
* **`rich`** - Execute with rich output capture: Automatically captures matplotlib plots, pandas DataFrames, and other visualizations.
* **`background`** - Non-blocking execution: Starts code execution in the background and returns immediately with a process ID.
For most use cases, use `mode="isolated"` for quick, one-off code execution. The sandbox is automatically created and destroyed, so you don't need to manage the lifecycle.
## Advanced Usage
### Multi-Step Workflows
For workflows that require multiple steps (e.g., installing packages, then running code), create a persistent sandbox:
**You:** "Install pandas and analyze this data: \[1, 2, 3, 4, 5]"
**Claude:** *Creates a sandbox, then executes multiple commands:*
1. `create_sandbox(template_id="code-interpreter")` - Creates a persistent sandbox
2. `execute_code(sandbox_id="...", code="pip install pandas", mode="persistent")` - Installs package
3. `execute_code(sandbox_id="...", code="import pandas as pd; ...", mode="persistent")` - Runs analysis
4. `delete_sandbox(sandbox_id="...")` - Cleans up
### Rich Output Capture
For data visualization, use `mode="rich"` to automatically capture plots and DataFrames:
**You:** "Create a plot of \[1, 2, 3, 4, 5]"
**Claude:** *Uses rich mode to capture the visualization:*
```python theme={null}
result = execute_code(
sandbox_id=sandbox_id,
code="import matplotlib.pyplot as plt; plt.plot([1,2,3,4,5]); plt.savefig('/tmp/plot.png')",
mode="rich"
)
# result["rich_outputs"] contains the captured plot
```
## Related
* **[LLM Integration](/guides/integrations/llm-integration)** - Integrate OpenAI, Anthropic, and other LLMs
* **[Quickstart Guide](/quickstart)** - Get started with HopX sandboxes
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Learn about code execution concepts
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Understand sandbox creation
## Next Steps
Now that you've set up MCP integration, explore more:
* **Learn about code execution**: [Synchronous Execution](/core-concepts/code-execution/synchronous) and [Background Execution](/core-concepts/code-execution/background)
* **Explore templates**: [Listing Templates](/core-concepts/templates/listing) to find the right environment
* **Try rich output capture**: [Rich Output Capture](/core-concepts/code-execution/rich-output) for data visualization
* **Integrate with LLMs**: [LLM Integration Guide](/guides/integrations/llm-integration) for direct LLM integration
* **Review best practices**: [Cookbooks](/cookbooks/getting-started/first-sandbox) for real-world examples
# Welcome to HopX
Source: https://docs.hopx.ai/index
Get started with HopX - your guide to building with cloud sandboxes. HopX provides instant access to isolated computing environments for executing code, running applications, and processing data. Whether you're building AI applications, running data analysis, testing code, or automating workflows, HopX provides the infrastructure you need.
HopX is a cloud sandbox platform that gives you instant access to isolated computing environments that enable you to execute code, run applications, and process data in isolated, secure environments. Whether you're building AI applications, running data analysis, testing code, or automating workflows, HopX provides the infrastructure you need without managing servers or containers.
### Key Capabilities
* **Multi-language code execution** - Run Python, JavaScript, Bash, and Go code with full system access
* **Rich output capture** - Automatically capture plots, dataframes, and visualizations
* **File operations** - Read, write, upload, download, and watch files in your sandbox
* **Template system** - Use pre-built templates or create custom environments
* **Desktop automation** - Control VNC servers, mouse, keyboard, and capture screenshots
* **Process management** - Run background processes, manage execution, and monitor system resources
* **Environment management** - Set and manage environment variables securely
* **Real-time streaming** - Stream execution output and monitor sandbox status
## Explore the Documentation
Complete walkthrough from installation to your first sandbox in under 10 minutes.
Comprehensive documentation for Python and JavaScript SDKs with code examples.
Command-line interface for managing sandboxes, executing code, and automating workflows.
Complete API documentation for the Control Plane and VM Agent APIs.
Step-by-step guides for common use cases and integration patterns.
## Core Concepts
Learn about the fundamental concepts and capabilities of HopX:
Create, manage, and connect to sandbox environments.
Execute code synchronously, asynchronously, or in the background.
Read, write, and manage files in your sandbox.
Use pre-built templates or create custom environments.
Control desktop environments with VNC, mouse, and keyboard automation.
Run shell commands and manage background processes.
## Related
* **[Quickstart Guide](/quickstart)** - Get started in under 2 minutes
* **[Python SDK Quickstart](/sdk/python/quickstart)** - Python SDK guide
* **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - JavaScript SDK guide
* **[API Quickstart](/api/quickstart)** - API guide
* **[Core Concepts](/core-concepts/sandboxes/creating)** - Learn about sandboxes
## Next Steps
* **New to HopX?** Start with our [Quickstart guide](/quickstart)
* **Building an integration?** Check out [MCP Integration](/guides/integrations/mcp-integration)
* **Need API details?** Explore the [API Reference](/api/introduction)
***
# Quickstart
Source: https://docs.hopx.ai/quickstart
Get started with HopX - your first HopX sandbox running in less than 2 minutes. Complete quickstart guide for creating sandboxes, executing code, and managing resources using Python SDK, JavaScript SDK, CLI, or REST API.
Get up and running with HopX; this guide walks you through creating your first sandbox, executing code, and cleaning up.
## What You'll Learn
In this quickstart, you'll learn how to:
* Install and set up the HopX SDK (Python or JavaScript) or CLI
* Create your first sandbox from a pre-built template
* Execute code in multiple languages (Python, JavaScript, Bash, Go)
* Work with files in sandboxes (read, write, list)
* Clean up sandboxes to free resources
* Use context managers for automatic cleanup (Python)
## Prerequisites
* [HopX API key](https://console.hopx.dev) (get one [here](/api-key) if you don't have it)
* Python 3.8+ **or** Node.js 18+ **or** CLI installed
* Basic experience with Python, JavaScript, or command line
## Run your first sandbox
Choose your preferred method: **Python SDK**, **JavaScript SDK**, or **CLI**. This guide focuses on SDKs. For CLI, see the [CLI Quickstart](/cli/quickstart).
Install the HopX SDK for your preferred language, or use the CLI:
```bash theme={null}
pip install hopx-ai
```
```bash theme={null}
npm install @hopx-ai/sdk
```
```bash theme={null}
# Quick install
curl -fsSL https://hopx.dev/install.sh | sh
```
See [CLI Installation](/cli/installation) for more options.
Create a sandbox using a pre-built template. Templates provide pre-configured environments with common tools and packages.
```python theme={null}
from hopx_ai import Sandbox
from hopx_ai.exceptions import APIError, ResourceLimitError
try:
# Create a sandbox with the code-interpreter template
sandbox = Sandbox.create(
template="code-interpreter",
api_key="your-api-key-here" # Or set HOPX_API_KEY env var
)
print(f"Sandbox created: {sandbox.sandbox_id}")
print(f"Status: {sandbox.get_info().status}")
except APIError as e:
print(f"API error: {e}")
except ResourceLimitError as e:
print(f"Resource limit exceeded: {e}")
```
**Expected Output:**
```
Sandbox created: sandbox_abc123xyz
Status: running
```
You can also use Sandbox.create() without specifying an API key if you set the HOPX\_API\_KEY environment variable.
```typescript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import { APIError, ResourceLimitError } from '@hopx-ai/sdk';
try {
// Create a sandbox with the code-interpreter template
const sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: 'your-api-key-here' // Or set HOPX_API_KEY env var
});
console.log(`Sandbox created: ${sandbox.sandboxId}`);
const info = await sandbox.getInfo();
console.log(`Status: ${info.status}`);
} catch (error) {
if (error instanceof APIError) {
console.error(`API error: ${error.message}`);
} else if (error instanceof ResourceLimitError) {
console.error(`Resource limit exceeded: ${error.message}`);
} else {
console.error(`Unexpected error: ${error.message}`);
}
}
```
**Expected Output:**
```
Sandbox created: sandbox_abc123xyz
Status: running
```
You can also use Sandbox.create() without specifying an API key if you set the HOPX\_API\_KEY environment variable.
Run code in your sandbox.
```python theme={null}
# Execute Python code
result = sandbox.run_code('''
import math
# Calculate the area of a circle
radius = 5
area = math.pi * radius ** 2
print(f"Area of circle with radius {radius}: {area:.2f}")
''', language: 'python')
print(result.stdout)
# Output: Area of circle with radius 5: 78.54
# Check if execution was successful
if result.success:
print("✅ Code executed successfully!")
else:
print(f"❌ Error: {result.stderr}")
```
The run\_code() method automatically captures rich outputs like matplotlib plots and pandas DataFrames. See [Rich Output Capture](/core-concepts/code-execution/rich-output) for more details.
```typescript theme={null}
// Execute JavaScript code
const result = await sandbox.runCode(`
const radius = 5;
const area = Math.PI * radius ** 2;
console.log(\`Area of circle with radius \${radius}: \${area.toFixed(2)}\`);
`, { language: 'javascript' });
console.log(result.stdout);
// Output: Area of circle with radius 5: 78.54
// Check if execution was successful
if (result.success) {
console.log('✅ Code executed successfully!');
} else {
console.log(`❌ Error: ${result.stderr}`);
}
```
The sandbox will execute code written in any language as long as the template you use provides the necessary dependencies.
See the Getting Template Details page for information on available templates and their environments, alternatively create your own template with the Building Templates guide.
Upload, read, and write files in your sandbox:
```python theme={null}
# Write a file
sandbox.files.write('/workspace/data.txt', 'Hello, HopX!')
# Read the file
content = sandbox.files.read('/workspace/data.txt')
print(content) # Output: Hello, HopX!
# List files in a directory
files = sandbox.files.list('/workspace')
for file in files:
print(f"- {file.name} ({file.size} bytes)")
```
**Expected Output:**
```
Hello, HopX!
- data.txt (12 bytes)
- script.py (245 bytes)
```
```typescript theme={null}
// Write a file
await sandbox.files.write('/workspace/data.txt', 'Hello, HopX!');
// Read the file
const content = await sandbox.files.read('/workspace/data.txt');
console.log(content); // Output: Hello, HopX!
// List files in a directory
const files = await sandbox.files.list('/workspace');
files.forEach(file => {
console.log(`- ${file.name} (${file.size} bytes)`);
});
```
**Expected Output:**
```
Hello, HopX!
- data.txt (12 bytes)
- script.js (189 bytes)
```
Always clean up your sandbox when you're done to free resources:
```python theme={null}
# Delete the sandbox
sandbox.kill()
print("Sandbox deleted")
```
**Expected Output:**
```
Sandbox deleted
```
```typescript theme={null}
// Delete the sandbox
await sandbox.kill();
console.log('Sandbox deleted');
```
**Expected Output:**
```
Sandbox deleted
```
Calling kill() permanently deletes the sandbox and all its data. Make sure you've saved any important files before cleaning up.
See [Downloading Files](./core-concepts/filesystem/downloading) for more details.
## Using Context Managers (Python)
Python SDK supports context managers for automatic cleanup:
```python theme={null}
from hopx_ai import Sandbox
# Automatically cleans up when exiting the context
with Sandbox.create(template="code-interpreter") as sandbox:
result = sandbox.run_code('print("Hello from HopX!")', language='python')
print(result.stdout)
# Sandbox is automatically deleted when exiting the block
```
**Expected Output:**
```
Hello from HopX!
```
***
## Complete Example
Here's a complete example that brings it all together:
```python theme={null}
from hopx_ai import Sandbox
# Setup your API key as an env var or inject it here as previously instructed.
# Create sandbox
sandbox = Sandbox.create(template="code-interpreter")
try:
# Execute code
result = sandbox.run_code('''
import math
# Calculate the area of a circle
radius = 5
area = math.pi * radius ** 2
print(f"Area of circle with radius {radius}: {area:.2f}")
''', language='python')
print("Output:")
print(result.stdout)
sandbox.run_code('mkdir /workspace/test')
# Work with files
sandbox.files.write('/workspace/test/result.json', result.stdout)
print("\n✅ Result saved to file")
# List files in a directory
files = sandbox.files.list('/workspace/test')
for file in files:
print(f"- {file.name} ({file.size} bytes)")\
# Read the file
content = sandbox.files.read('/workspace/test/result.json')
print(content)
finally:
# Always clean up
sandbox.kill()
print("✅ Sandbox cleaned up")
```
```typescript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function main() {
// Create sandbox
const sandbox = await Sandbox.create({ template: 'code-interpreter'});
try {
// Execute JavaScript code
const result = await sandbox.runCode(`
const radius = 5;
const area = Math.PI * radius ** 2;
console.log(\`Area of circle with radius \${radius}: \${area.toFixed(2)}\`);
`, { language: 'javascript' });
console.log('Output:');
console.log(result.stdout);
console.log(result.stderr);
// Work with files
await sandbox.files.write('/workspace/test/result.json', result.stdout);
console.log('\n✅ Result saved to file');
// List files in a directory
const files = await sandbox.files.list('/workspace/test');
console.log(files);
// Read the file
const content = await sandbox.files.read('/workspace/test/result.json');
console.log(content);
} finally {
// Always clean up
await sandbox.kill();
console.log('✅ Sandbox cleaned up');
}
}
main();
```
## Related
* **[Python SDK Quickstart](/sdk/python/quickstart)** - Detailed Python SDK guide
* **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Detailed JavaScript SDK guide
* **[CLI Quickstart](/cli/quickstart)** - Command-line interface quickstart
* **[API Quickstart](/api/quickstart)** - API-based quickstart
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn more about sandbox creation
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Learn about code execution
## Next Steps
Now that you've created your first sandbox, explore more:
* **Learn about sandbox lifecycle**: [Creating Sandboxes](/core-concepts/sandboxes/creating)
* **Execute code in different ways**: [Code Execution](/core-concepts/code-execution/synchronous)
* **Work with templates**: [Templates](/core-concepts/templates/listing)
* **Integrate with MCP**: [MCP Integration](/guides/integrations/mcp-integration)
* **Explore the SDK**: [Python SDK Reference](/sdk/python/introduction) or [JavaScript SDK Reference](/sdk/javascript/introduction)
* **Use the CLI**: [CLI Reference](/cli/introduction) - Command-line interface for HopX
* **Check supported languages**: [Supported Languages](/supported-languages)
For AI agent developers, check out the [MCP Integration guide](/guides/integrations/mcp-integration) to enable AI assistants to execute code safely in sandboxes.
# Cache Management
Source: https://docs.hopx.ai/sdk/javascript/cache
Cache management resource for managing execution result cache in HopX sandboxes using the JavaScript/TypeScript SDK. Complete reference for the Cache class including async methods for viewing cache statistics and clearing execution cache. Includes TypeScript examples for cache optimization.
**Version:** 0.1.22\
**Last Verified:** 2025-01-27\
**Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk)
## Overview
The `Cache` resource provides methods for managing the execution result cache in sandboxes.
## Methods
### `stats`
Get cache statistics.
```typescript theme={null}
async cache.stats(): Promise
```
**Returns:** `Promise` - Cache statistics
**Example:**
```typescript theme={null}
const stats = await sandbox.cache.stats();
console.log(`Cache hits: ${stats.cache.totalHits}`);
console.log(`Cache size: ${stats.cache.size} / ${stats.cache.maxSize}`);
```
***
### `clear`
Clear the execution result cache.
```typescript theme={null}
async cache.clear(): Promise
```
This clears all cached execution results.
***
## Related Classes
* **[Sandbox](/sdk/javascript/sandbox)** - Main sandbox class
* **[Core Concepts: Cache](/core-concepts/cache/statistics)** - Learn about cache management
## See Also
* [Sandbox Class](/sdk/javascript/sandbox) - Access cache via `sandbox.cache`
* [Cache Statistics](/core-concepts/cache/statistics) - Detailed cache documentation
## Related
* **[Python SDK: Cache](/sdk/python/cache)** - Python SDK cache management
* **[Cache Statistics](/core-concepts/cache/statistics)** - Learn about cache statistics
* **[Clearing Cache](/core-concepts/cache/clearing)** - Clear cache to free memory
## Next Steps
* Learn about [Cache Statistics](/core-concepts/cache/statistics) to monitor cache
* Review [Clearing Cache](/core-concepts/cache/clearing) to free memory
* Explore [Code Execution](/core-concepts/code-execution/synchronous) for cached results
* **[CLI System Commands](/cli/commands/system)** - View cache from CLI
# Command Execution
Source: https://docs.hopx.ai/sdk/javascript/commands
Command execution resource for running shell commands in HopX sandboxes using the JavaScript/TypeScript SDK. Complete reference for the Commands class including async methods for running commands synchronously and in the background. Includes TypeScript examples for system administration and automation.
**Version:** 0.1.22\
**Last Verified:** 2025-01-27\
**Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk)
## Overview
The `Commands` resource provides shell command execution capabilities for sandboxes. Access it via the `commands` property on a `Sandbox` instance.
## Methods
### `run`
Run a shell command.
```typescript theme={null}
async commands.run(
command: string,
options?: CommandOptions
): Promise
```
**Parameters:**
* `command` (`string`): Shell command to execute
* `options.timeout` (`number`, optional): Command timeout in seconds (default: `30`)
* `options.background` (`boolean`, optional): Run in background (default: `false`)
* `options.workingDir` (`string`, optional): Working directory (default: `'/workspace'`)
* `options.env` (`Record`, optional): Environment variables
**Returns:** `Promise` - Command execution result
**Example:**
```typescript theme={null}
const result = await sandbox.commands.run('ls -la /workspace');
console.log(result.stdout);
console.log(`Exit code: ${result.exitCode}`);
```
***
### `runBackground`
Run command in background.
```typescript theme={null}
async commands.runBackground(
command: string,
options?: Omit
): Promise<{ processId: string }>
```
**Returns:** `Promise<{ processId: string }>` - Process ID
***
## Related Classes
* **[Sandbox](/sdk/javascript/sandbox)** - Main sandbox class
* **[Files](/sdk/javascript/files)** - File operations resource
## See Also
* [Core Concepts: Execution](/core-concepts/execution) - Learn about code execution
* [Sandbox Class](/sdk/javascript/sandbox) - Access commands via `sandbox.commands`
## Related
* **[Python SDK: Commands](/sdk/python/commands)** - Python SDK command execution
* **[Running Commands](/core-concepts/commands/running)** - Learn about command execution
* **[Background Commands](/core-concepts/commands/background)** - Run commands in background
## Next Steps
* Learn about [Running Commands](/core-concepts/commands/running) for synchronous execution
* Explore [Background Commands](/core-concepts/commands/background) for non-blocking tasks
* Review [Code Execution](/core-concepts/code-execution/synchronous) for programmatic execution
* **[CLI Commands](/cli/commands/cmd)** - Execute shell commands from CLI
# Desktop Automation
Source: https://docs.hopx.ai/sdk/javascript/desktop
Desktop automation resource for sandbox GUI interactions, screenshots, and VNC access in HopX using the JavaScript/TypeScript SDK. Complete reference for the Desktop class including async methods for VNC servers, screenshots, mouse and keyboard control, window management, and clipboard operations. Includes TypeScript examples for desktop automation.
**Version:** 0.1.22\
**Last Verified:** 2025-01-27\
**Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk)
## Overview
The `Desktop` resource provides desktop automation capabilities for sandboxes with GUI support.
Desktop features require a desktop-enabled template. Not all templates support desktop operations.
## Methods
### VNC Methods
* `async desktop.startVnc(): Promise`
* `async desktop.stopVnc(): Promise`
* `async desktop.getVncInfo(): Promise`
* `async desktop.getVncUrl(): Promise`
### Mouse Methods
* `async desktop.mouseClick(x: number, y: number, options?: MouseClickOptions): Promise`
* `async desktop.mouseMove(x: number, y: number): Promise`
* `async desktop.mouseDrag(fromX: number, fromY: number, toX: number, toY: number): Promise`
* `async desktop.mouseScroll(x: number, y: number, deltaY: number): Promise`
### Keyboard Methods
* `async desktop.keyboardType(text: string): Promise`
* `async desktop.keyboardPress(key: string): Promise`
* `async desktop.keyboardCombination(keys: string[]): Promise`
### Screenshot Methods
* `async desktop.screenshot(): Promise`
* `async desktop.screenshotRegion(x: number, y: number, width: number, height: number): Promise`
***
## Related Classes
* **[Sandbox](/sdk/javascript/sandbox)** - Main sandbox class
## Related
* **[Python SDK: Desktop](/sdk/python/desktop)** - Python SDK desktop automation
* **[VNC Server](/core-concepts/desktop/vnc-server)** - Learn about VNC access
* **[Screenshots](/core-concepts/desktop/screenshots)** - Capture screenshots
## Next Steps
* Learn about [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access
* Explore [Screenshots](/core-concepts/desktop/screenshots) for visual verification
* Review [Mouse Control](/core-concepts/desktop/mouse-control) and [Keyboard Control](/core-concepts/desktop/keyboard-control) for GUI automation
* **[Types](/sdk/javascript/types)** - TypeScript type definitions
* **[CLI System Commands](/cli/commands/system)** - System operations from CLI
## See Also
* [Core Concepts: Desktop](/core-concepts/desktop) - Learn about desktop automation
* [Sandbox Class](/sdk/javascript/sandbox) - Access desktop via `sandbox.desktop`
# Environment Variables
Source: https://docs.hopx.ai/sdk/javascript/environment-variables
Environment variable management resource for configuring sandbox environment in HopX using the JavaScript/TypeScript SDK. Complete reference for the Environment class including async methods for getting, setting, updating, and clearing environment variables. Includes TypeScript examples for configuration management.
**Version:** 0.1.22\
**Last Verified:** 2025-01-27\
**Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk)
## Overview
The `EnvironmentVariables` resource (accessed via `sandbox.env`) provides methods for managing environment variables in sandboxes.
## Methods
### `getAll`
Get all environment variables.
```typescript theme={null}
async env.getAll(): Promise>
```
**Returns:** `Promise>` - Dictionary of all environment variables
***
### `get`
Get specific environment variable.
```typescript theme={null}
async env.get(key: string): Promise
```
**Returns:** `Promise` - Variable value or `undefined`
***
### `set`
Set a single environment variable.
```typescript theme={null}
async env.set(key: string, value: string): Promise
```
***
### `setAll`
Replace all environment variables (destructive).
```typescript theme={null}
async env.setAll(envVars: Record): Promise>
```
This replaces ALL existing environment variables. Use `update()` to merge instead.
***
### `update`
Update environment variables (merge with existing).
```typescript theme={null}
async env.update(envVars: Record): Promise>
```
***
### `delete`
Delete a single environment variable.
```typescript theme={null}
async env.delete(key: string): Promise
```
***
## Related Classes
* **[Sandbox](/sdk/javascript/sandbox)** - Main sandbox class
* **[Commands](/sdk/javascript/commands)** - Command execution resource
## See Also
* [Core Concepts: Environment Variables](/core-concepts/environment-variables) - Learn about environment configuration
* [Sandbox Class](/sdk/javascript/sandbox) - Access env via `sandbox.env`
## Related
* **[Python SDK: Environment Variables](/sdk/python/environment-variables)** - Python SDK environment management
* **[Getting Environment Variables](/core-concepts/environment/getting)** - Learn about getting env vars
* **[Setting Environment Variables](/core-concepts/environment/setting)** - Learn about setting env vars
## Next Steps
* Learn about [Getting Environment Variables](/core-concepts/environment/getting) to read values
* Explore [Setting Environment Variables](/core-concepts/environment/setting) to configure environment
* Review [Updating Environment Variables](/core-concepts/environment/updating) for batch updates
* **[CLI Environment Variables](/cli/commands/env)** - Manage env vars from CLI
# Sandbox Error Handling
Source: https://docs.hopx.ai/sdk/javascript/errors
Error classes and exception handling in the HopX JavaScript/TypeScript SDK. Handle API errors, network errors, agent errors, and validation errors gracefully. Learn about error types, error handling patterns, and best practices for robust error handling in your applications. Includes TypeScript error class reference and handling examples.
**Version:** 0.1.22\
**Last Verified:** 2025-01-27\
**Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk)
## Overview
The JavaScript SDK provides a comprehensive error hierarchy for handling different types of errors. All errors inherit from `HopxError`.
## Import
```typescript theme={null}
import {
HopxError,
APIError,
AuthenticationError,
NotFoundError,
ValidationError,
RateLimitError,
ResourceLimitError,
ServerError,
NetworkError,
TimeoutError
} from '@hopx-ai/sdk';
```
## Base Error
### `HopxError`
Base exception for all HopX SDK errors.
**Properties:**
* `message` (`string`): Error message
* `code` (`string`, optional): Error code
* `requestId` (`string`, optional): Request ID for debugging
* `statusCode` (`number`, optional): HTTP status code
* `details` (`Record`, optional): Additional error details
***
## API Errors
### `APIError`
Base class for API request failures.
**Inherits from:** `HopxError`
***
### `AuthenticationError`
Authentication failed (401).
**Inherits from:** `APIError`
**When thrown:**
* Invalid or missing API key
* Expired authentication token
***
### `NotFoundError`
Resource not found (404).
**Inherits from:** `APIError`
**When thrown:**
* Sandbox not found
* Template not found
* File not found
***
### `ValidationError`
Request validation failed (400).
**Inherits from:** `APIError`
**When thrown:**
* Invalid parameters
* Missing required fields
***
### `RateLimitError`
Rate limit exceeded (429).
**Inherits from:** `APIError`
**Properties:**
* `retryAfter` (`number`, optional): Seconds to wait before retrying
***
### `ResourceLimitError`
Resource limit exceeded.
**Inherits from:** `APIError`
**Properties:**
* `limit` (`number`): Resource limit
* `current` (`number`): Current usage
* `available` (`number`): Available resources
***
### `ServerError`
Server error (5xx).
**Inherits from:** `APIError`
***
## Network Errors
### `NetworkError`
Network communication failed.
**Inherits from:** `HopxError`
***
### `TimeoutError`
Request timed out.
**Inherits from:** `NetworkError`
***
## Error Handling Examples
### Example 1: Basic Error Handling
```typescript theme={null}
import { Sandbox, HopxError } from '@hopx-ai/sdk';
try {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const result = await sandbox.runCode("print('Hello')");
} catch (error) {
if (error instanceof HopxError) {
console.error(`Error: ${error.message}`);
if (error.statusCode) {
console.error(`Status: ${error.statusCode}`);
}
}
}
```
### Example 2: Specific Error Handling
```typescript theme={null}
import { Sandbox, AuthenticationError, NotFoundError } from '@hopx-ai/sdk';
try {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
} catch (error) {
if (error instanceof AuthenticationError) {
console.error('Authentication failed. Check your API key.');
} else if (error instanceof NotFoundError) {
console.error('Template not found.');
}
}
```
***
## Related Classes
* **[Types](/sdk/javascript/types)** - TypeScript type definitions
* **[Sandbox](/sdk/javascript/sandbox)** - Sandbox operations that may throw errors
## See Also
* [Types](/sdk/javascript/types) - Learn about type definitions
* [Core Concepts: Errors](/core-concepts/errors) - Learn about error handling
## Next Steps
Now that you understand error handling, explore:
* [Error Handling Basics](/cookbooks/getting-started/error-handling) - Practical error handling patterns
* [Sandbox Operations](/sdk/javascript/sandbox) - See errors in action
* [API Errors](/api/concepts/errors) - Understand API error responses
* **[CLI Reference](/cli/introduction)** - Use HopX from the command line
* [Troubleshooting](/api/concepts/troubleshooting) - Common issues and solutions
# File Operations
Source: https://docs.hopx.ai/sdk/javascript/files
File operations resource for reading, writing, and managing files in HopX sandboxes using the JavaScript/TypeScript SDK. Complete reference for the Files class including async methods for reading, writing, listing, uploading, downloading, and watching files. Includes TypeScript examples for all file operations.
**Version:** 0.1.22\
**Last Verified:** 2025-01-27\
**Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk)
## Overview
The `Files` resource provides file operations for sandboxes. Access it via the `files` property on a `Sandbox` instance. All file operations are async and work with both text and binary files.
## Access
```typescript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const files = sandbox.files; // Lazy-loaded
```
## Methods
### `read`
Read text file contents.
```typescript theme={null}
async files.read(path: string): Promise
```
**Parameters:**
* `path` (`string`): File path to read
**Returns:** `Promise` - File contents as string
**Example:**
```typescript theme={null}
const content = await sandbox.files.read('/workspace/script.py');
console.log(content);
```
***
### `readBytes`
Read binary file contents.
```typescript theme={null}
async files.readBytes(path: string): Promise
```
**Returns:** `Promise` - File contents as Buffer
***
### `write`
Write text file.
```typescript theme={null}
async files.write(
path: string,
content: string,
options?: FileWriteOptions
): Promise
```
**Parameters:**
* `path` (`string`): File path to write
* `content` (`string`): Text content
* `options.mode` (`string`, optional): File permissions
***
### `writeBytes`
Write binary file.
```typescript theme={null}
async files.writeBytes(
path: string,
content: Buffer,
options?: FileWriteOptions
): Promise
```
***
### `list`
List directory contents.
```typescript theme={null}
async files.list(path: string): Promise
```
**Returns:** `Promise` - Array of file/directory information objects
***
### `exists`
Check if file/directory exists.
```typescript theme={null}
async files.exists(path: string): Promise
```
**Returns:** `Promise` - `true` if exists, `false` otherwise
***
### `remove`
Remove file or directory.
```typescript theme={null}
async files.remove(path: string): Promise
```
***
### `mkdir`
Create directory.
```typescript theme={null}
async files.mkdir(path: string): Promise
```
***
### `download`
Download file (alias for `readBytes`).
```typescript theme={null}
async files.download(path: string): Promise
```
***
## Examples
### Example 1: Basic File Operations
```typescript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function main() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Write a file
await sandbox.files.write('/workspace/hello.py', "print('Hello, World!')");
// Read it back
const content = await sandbox.files.read('/workspace/hello.py');
console.log(content);
// Execute it
const result = await sandbox.runCode(
"exec(open('/workspace/hello.py').read())"
);
console.log(result.stdout);
await sandbox.kill();
}
main();
```
***
## Related Classes
* **[Sandbox](/sdk/javascript/sandbox)** - Main sandbox class
* **[Commands](/sdk/javascript/commands)** - Command execution resource
* **[Types](/sdk/javascript/types)** - TypeScript type definitions
## See Also
* [Core Concepts: Files](/core-concepts/files) - Learn about file operations
* [Sandbox Class](/sdk/javascript/sandbox) - Access files via `sandbox.files`
## Related
* **[Python SDK: Files](/sdk/python/files)** - Python SDK file operations
* **[Reading Files](/core-concepts/filesystem/reading)** - Learn about reading files
* **[Writing Files](/core-concepts/filesystem/writing)** - Learn about writing files
## Next Steps
* Learn about [Reading Files](/core-concepts/filesystem/reading) to access file contents
* Explore [Writing Files](/core-concepts/filesystem/writing) to create files
* Review [Uploading Files](/core-concepts/filesystem/uploading) for local file transfers
* **[CLI File Operations](/cli/commands/files)** - Use file operations from CLI
# Installation
Source: https://docs.hopx.ai/sdk/javascript/installation
Install the HopX JavaScript SDK and set up your development environment. Get started with the official JavaScript/TypeScript SDK for HopX, install via npm, configure API keys, and verify installation. Learn system requirements, installation methods, and troubleshooting tips. Includes installation examples for Node.js and browser environments.
**SDK Version:** 0.1.21+\
**Last Verified:** 2025-01-27
## Prerequisites
Before installing the HopX JavaScript SDK, ensure you have:
* **Node.js 18+** (20+ recommended for LTS support)
* **npm, yarn, or pnpm** (package manager)
* **HopX API key** - Get yours at [console.hopx.dev](https://console.hopx.dev)
## Install with npm
The recommended way to install the HopX JavaScript SDK:
```bash theme={null}
npm install @hopx-ai/sdk
```
## Install with yarn
```bash theme={null}
yarn add @hopx-ai/sdk
```
## Install with pnpm
```bash theme={null}
pnpm add @hopx-ai/sdk
```
## Install Specific Version
Install a specific version:
```bash theme={null}
npm install @hopx-ai/sdk@0.1.21
```
## Install from Source
For development or to use the latest unreleased version:
```bash theme={null}
git clone https://github.com/hopx-ai/hopx.git
cd HopX/javascript
npm install
npm run build
```
Building from source requires Node.js 18+, TypeScript 5.3+, and build tools. See the [GitHub repository](https://github.com/hopx-ai/HopX) for detailed development setup instructions.
## TypeScript Support
TypeScript definitions are included automatically. No additional `@types` package needed.
```typescript theme={null}
import { Sandbox, ExecutionResult } from '@hopx-ai/sdk';
const sandbox: Sandbox = await Sandbox.create({ template: 'code-interpreter' });
const result: ExecutionResult = await sandbox.runCode('print("Hello")');
```
## Verify Installation
Verify the installation:
```bash theme={null}
node -e "const { Sandbox } = require('@hopx-ai/sdk'); console.log('SDK installed successfully')"
```
## Set Up Authentication
The SDK requires an API key for authentication. You have three options:
### Option 1: Environment Variable (Recommended)
Set the `HOPX_API_KEY` environment variable:
```bash theme={null}
# Linux/macOS
export HOPX_API_KEY="your-API key-here"
# Windows (PowerShell)
$env:HOPX_API_KEY="your-API key-here"
# Windows (CMD)
set HOPX_API_KEY=your-API key-here
```
### Option 2: Pass API key Directly
Pass the API key when creating a sandbox:
```typescript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({
template: 'code-interpreter',
apiKey: 'your-API key-here'
});
```
### Option 3: Configuration File
Create a `.env` file in your project root:
```bash theme={null}
# .env
HOPX_API_KEY=your-API key-here
```
Then load it in your code (requires `dotenv` package):
```bash theme={null}
npm install dotenv
```
```typescript theme={null}
import 'dotenv/config';
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
```
Never commit your API key to version control. Always use environment variables or secure secret management for production applications.
## Get Your API key
1. Sign up at [console.hopx.dev](https://console.hopx.dev)
2. Navigate to **Settings** → **API Keys**
3. Create a new API key
4. Copy the key (you'll only see it once)
API keys are scoped to your account and have full access to create, manage, and delete sandboxes. Keep them secure.
## Supported Node.js Versions
The SDK is tested and supported on:
* **Node.js 18.x** - Minimum supported version
* **Node.js 20.x** - LTS, recommended for production
* **Node.js 22.x** - Latest LTS, fully supported
## Module Systems
### ES Modules (Recommended)
```typescript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
```
Ensure your `package.json` has:
```json theme={null}
{
"type": "module"
}
```
### CommonJS
```javascript theme={null}
const { Sandbox } = require('@hopx-ai/sdk');
(async () => {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
})();
```
## Dependencies
The SDK has minimal dependencies:
* `node-fetch` - HTTP client for API calls (Node.js 18+ has native fetch)
* `ws` - WebSocket client for streaming
* Type definitions included
All dependencies are automatically installed with `npm install @hopx-ai/sdk`.
## Browser Support
The SDK can be used in browsers with:
1. **CORS Configuration** - Configure your HopX account to allow browser origins
2. **Build Tool** - Use a bundler (webpack, Vite, esbuild) to bundle the SDK
3. **API key Security** - Never expose API keys in client-side code (use a backend proxy)
Using the SDK directly in browsers requires CORS configuration and exposes your API key. For production browser applications, use a backend proxy instead.
## Troubleshooting
### Import Errors
If you get `Cannot find module '@hopx-ai/sdk'`:
1. Verify Node.js version: `node --version` (should be 18+)
2. Check installation: `npm list @hopx-ai/sdk`
3. Reinstall: `npm install --save @hopx-ai/sdk`
### TypeScript Errors
If TypeScript can't find types:
1. Ensure `@hopx-ai/sdk` is in `dependencies` (not `devDependencies`)
2. Restart your TypeScript server/IDE
3. Check `tsconfig.json` includes `node_modules` in type resolution
### Authentication Errors
If you get authentication errors:
1. Verify API key is set: `echo $HOPX_API_KEY` (Linux/macOS) or `echo %HOPX_API_KEY%` (Windows)
2. Check API key is valid at [console.hopx.dev](https://console.hopx.dev)
3. Ensure no extra spaces or quotes in the API key
### Network Errors
If you encounter network errors:
1. Check internet connection
2. Verify firewall allows outbound HTTPS (port 443)
3. Check if you're behind a corporate proxy (may need proxy configuration)
For more troubleshooting help, see the [Troubleshooting Guide](/sdk/javascript/troubleshooting).
## Related
* **[JavaScript SDK Quickstart](/sdk/javascript/quickstart)** - Get started with the SDK
* **\[API key Management]\(/API key)** - Learn about API key security
* **[Sandbox Class Reference](/sdk/javascript/sandbox)** - Complete SDK reference
## Next Steps
Once you've successfully installed the SDK:
* **[Quickstart Guide](/sdk/javascript/quickstart)** - Create your first sandbox and run code
* **[API Reference](/sdk/javascript/sandbox)** - Explore the full SDK API
* **[CLI Installation](/cli/installation)** - Install the HopX CLI
# Overview
Source: https://docs.hopx.ai/sdk/javascript/introduction
Official JavaScript/TypeScript SDK for HopX - Create and manage cloud sandboxes in Node.js and browsers. Install the SDK, authenticate with your API key, and start creating sandboxes, executing code, managing files, and automating desktop interactions. Complete reference with async/await examples for all SDK methods and classes.
**Version:** 0.1.21+\
**Last Verified:** 2025-01-27\
**Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk)
## What is the JavaScript SDK?
The HopX JavaScript SDK provides a modern, type-safe interface for creating and managing cloud sandboxes from Node.js applications, TypeScript projects, or browser environments. Build AI agents, run untrusted code securely, execute tests in isolation, or process data with rich output capture—all with async/await and full TypeScript support.
The SDK is a thin wrapper around the HopX REST API that handles authentication, request formatting, error translation, and response parsing automatically, giving you a better developer experience than working with the raw API.
## Target Audience
This SDK is designed for:
* **Backend Node.js developers** using Node.js 18+ or 20+
* **TypeScript developers** who want full type safety and IDE autocomplete
* **Frontend developers** building browser-based tools (with CORS configuration)
* **Full-stack engineers** working with JavaScript/TypeScript ecosystems
* **Automation engineers** building Node.js-based workflows
## Supported Runtimes
* **Node.js:** 18.x, 20.x, 22.x (LTS versions recommended)
* **TypeScript:** 4.5+ (full type definitions included)
* **Browsers:** Modern browsers with ES2020+ support (with CORS setup)
* **Package Managers:** npm, yarn, pnpm
## When to Use the SDK vs CLI vs Raw API
### Use the JavaScript SDK when:
* ✅ You're building Node.js or TypeScript applications
* ✅ You want TypeScript type definitions and IDE autocomplete
* ✅ You prefer Promise-based async/await patterns
* ✅ You need automatic error handling and retries
* ✅ You're working with JavaScript objects and JSON
* ✅ You want tree-shakeable imports
### Use the CLI when:
* ✅ You prefer command-line workflows
* ✅ You're scripting or automating from shell
* ✅ You want quick one-off operations
* ✅ You're working in CI/CD pipelines
* ✅ You need interactive terminal sessions
### Use the Raw API when:
* ⚠️ You're building in a non-JavaScript language
* ⚠️ You need fine-grained control over HTTP requests
* ⚠️ You're integrating with existing HTTP client libraries (axios, fetch wrappers)
* ⚠️ You need custom retry logic or connection pooling
The SDK is a thin wrapper around the HopX REST API. It handles authentication, request formatting, error translation, and response parsing automatically. For most JavaScript/TypeScript use cases, the SDK provides a better developer experience.
## Architecture
The SDK is built with:
* **TypeScript** - Full type definitions for all APIs
* **ES Modules** - Modern import/export syntax
* **CommonJS** - Also supports `require()` for compatibility
* **Promise-based** - All operations return Promises (async/await friendly)
## Core Capabilities
The JavaScript SDK provides:
* **Sandbox Management** - Create, connect, list, and delete sandboxes
* **Code Execution** - Run Python, JavaScript, Bash, Go, and more
* **Rich Outputs** - Capture matplotlib plots, pandas DataFrames, images
* **File Operations** - Read, write, list, upload, download files
* **Command Execution** - Run shell commands synchronously or in background
* **Environment Variables** - Set, get, update, and clear environment variables
* **Process Management** - List and manage running processes
* **Cache Management** - Monitor and clear execution result cache
* **Desktop Automation** - VNC access, mouse/keyboard control (Premium)
* **Template Building** - Create custom sandbox environments
* **WebSocket Streaming** - Real-time terminal and code execution streaming
## Quick Example
```typescript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
// Create a sandbox (~100ms)
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Execute code
const result = await sandbox.runCode('print("Hello from HopX!")');
console.log(result.stdout); // "Hello from HopX!\n"
// Cleanup
await sandbox.kill();
```
## Next Steps
* **[Installation Guide](/sdk/javascript/installation)** - Install the SDK and set up your environment
* **[Quickstart](/sdk/javascript/quickstart)** - Get your first sandbox running in minutes
* **[API Reference](/sdk/javascript/sandbox)** - Complete class and method documentation
## Related
* [Python SDK](/sdk/python/introduction) - Official Python SDK
* [CLI Reference](/cli/introduction) - Command-line interface for HopX
* [API Reference](/api/introduction) - Raw REST API documentation
* [Core Concepts](/core-concepts/sandboxes/creating) - Learn about sandboxes, execution, and more
# Quickstart
Source: https://docs.hopx.ai/sdk/javascript/quickstart
Get your first sandbox running in minutes with the HopX JavaScript SDK - install, authenticate, execute code, see results. Complete quickstart guide for creating sandboxes, running JavaScript/TypeScript code, managing files, and cleaning up resources. Perfect for developers new to HopX. Includes async/await examples and best practices.
**Goal:** Create a sandbox, execute code, and see the output in under 5 minutes.\
**Prerequisites:** Node.js 18+, npm, HopX API key\
**Time:** \~5 minutes
This quickstart gets you from zero to your first successful code execution. Follow these steps in order.
## What You'll Learn
In this quickstart, you'll learn how to:
* Install and verify the JavaScript SDK
* Set up API key authentication
* Create a sandbox from a template
* Execute code in the sandbox using async/await
* Access execution results and output
* Clean up sandboxes properly
## Step 1: Install the SDK
```bash theme={null}
npm install @hopx-ai/sdk
```
## Step 1.5: Verify Installation
Verify the SDK is installed correctly:
```bash theme={null}
node -e "const { Sandbox } = require('@hopx-ai/sdk'); console.log('HopX SDK installed successfully')"
```
Expected output: `HopX SDK installed successfully`
## Step 2: Set Your API key
Set the `HOPX_API_KEY` environment variable:
```bash theme={null}
# Linux/macOS
export HOPX_API_KEY="your-API key-here"
# Windows (PowerShell)
$env:HOPX_API_KEY="your-API key-here"
```
Get your API key from [console.hopx.dev](https://console.hopx.dev) → Settings → API Keys
## Step 3: Create and Run Your First Sandbox
Create a file `hello-HopX.js`:
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function main() {
// Create a sandbox (~100ms)
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Execute code in the sandbox
const result = await sandbox.runCode('print("Hello from HopX!")');
// Print the output
console.log(result.stdout);
// Cleanup - delete the sandbox
await sandbox.kill();
}
main().catch(console.error);
```
## Step 4: Run It
```bash theme={null}
node hello-HopX.js
```
If using ES modules, ensure your `package.json` has `"type": "module"`, or use `.mjs` extension.
## Expected Output
```
Hello from HopX!
```
🎉 **Success!** You've created your first sandbox and executed code. The sandbox was automatically cleaned up after execution.
## What Just Happened?
1. **`Sandbox.create()`** - Created a new sandbox from the `code-interpreter` template (Python environment)
2. **`sandbox.runCode()`** - Executed Python code in the sandbox
3. **`result.stdout`** - Retrieved the standard output from code execution
4. **`sandbox.kill()`** - Deleted the sandbox to free resources
## Related
* **[API Quickstart](/api/quickstart)** - Get started with the API
* **[Python SDK Quickstart](/sdk/python/quickstart)** - Python SDK equivalent
* **[Sandbox Class Reference](/sdk/javascript/sandbox)** - Complete SDK reference
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn more about sandbox creation
## Next Steps
Now that you have a working setup, explore more:
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn about different templates and options
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Run Python, JavaScript, Bash, and more
* **[File Operations](/core-concepts/filesystem/reading)** - Read, write, and manage files in sandboxes
* **[CLI Quickstart](/cli/quickstart)** - Use HopX from the command line
* **[API Reference](/sdk/javascript/sandbox)** - Complete SDK documentation
## Quickstart Variations
For more advanced quickstart examples including error handling, environment variables, and TypeScript patterns, see the [Advanced Quickstart Guide](/sdk/javascript/advanced-quickstart) (coming soon).
## Troubleshooting
**"API key required" error?**
* Verify `HOPX_API_KEY` is set: `echo $HOPX_API_KEY`
* Get your key at [console.hopx.dev](https://console.hopx.dev)
**"Template not found" error?**
* Use `template: 'code-interpreter'` (default Python template)
* See [Available Templates](/core-concepts/templates/listing) for options
**"Cannot find module" error?**
* Run `npm install @hopx-ai/sdk`
* Check Node.js version: `node --version` (should be 18+)
**Network timeout?**
* Check internet connection
* Verify firewall allows HTTPS (port 443)
For more help, see the [Troubleshooting Guide](/sdk/javascript/troubleshooting).
# Template Ready Checks
Source: https://docs.hopx.ai/sdk/javascript/ready-checks
Utilities for checking template readiness before use in the HopX JavaScript/TypeScript SDK. Verify templates are available and ready before creating sandboxes, check template status, and handle template availability errors. Essential for robust sandbox creation workflows. Includes TypeScript examples and error handling.
**Version:** 0.1.22\
**Last Verified:** 2025-01-27\
**Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk)
## Overview
Ready checks are utilities used in template building to verify that a template is ready before it's considered complete.
## Import
```typescript theme={null}
import {
waitForPort,
waitForUrl,
waitForFile,
waitForProcess,
waitForCommand
} from '@hopx-ai/sdk';
```
## Available Ready Checks
### `waitForPort`
Wait for a port to be listening.
```typescript theme={null}
waitForPort(port: number, timeout?: number): ReadyCheck
```
***
### `waitForUrl`
Wait for a URL to be accessible.
```typescript theme={null}
waitForUrl(url: string, timeout?: number): ReadyCheck
```
***
### `waitForFile`
Wait for a file to exist.
```typescript theme={null}
waitForFile(path: string, timeout?: number): ReadyCheck
```
***
### `waitForProcess`
Wait for a process to be running.
```typescript theme={null}
waitForProcess(processName: string, timeout?: number): ReadyCheck
```
***
### `waitForCommand`
Wait for a command to succeed.
```typescript theme={null}
waitForCommand(command: string, timeout?: number): ReadyCheck
```
***
## Example
```typescript theme={null}
import { Template, waitForPort } from '@hopx-ai/sdk';
const template = new Template()
.fromNodeImage('20')
.run('npm install express')
.expose(3000)
.startCmd('node server.js')
.readyCheck(waitForPort(3000, 120000));
const result = await template.build();
console.log(`Template ready: ${result.templateId}`);
```
***
## Related Classes
* **[Template Builder](/sdk/javascript/template-builder)** - Use ready checks in templates
* **[Sandbox](/sdk/javascript/sandbox)** - Create sandboxes from templates
## See Also
* [Template Builder](/sdk/javascript/template-builder) - Learn about building templates
* [Core Concepts: Templates](/core-concepts/templates) - Learn about templates
## Next Steps
Now that you understand ready checks, explore:
* [Template Builder](/sdk/javascript/template-builder) - Use ready checks in template building
* [Building Templates](/core-concepts/templates/building) - Learn template building concepts
* [Template Configuration](/core-concepts/templates/configuration) - Configure templates
* **[CLI Reference](/cli/introduction)** - Use HopX from the command line
* [Custom Templates](/cookbooks/advanced/custom-templates) - Build custom templates
# Sandbox
Source: https://docs.hopx.ai/sdk/javascript/sandbox
Main sandbox class for creating and managing cloud sandboxes in JavaScript/TypeScript. Complete reference for the HopX JavaScript SDK Sandbox class including async/await methods for creating sandboxes, executing code, managing files, controlling desktop automation, and monitoring resources. Includes TypeScript examples for all methods.
**Version:** 0.1.22\
**Last Verified:** 2025-01-27\
**Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk)
## Overview
The `Sandbox` class is the main entry point for the HopX JavaScript/TypeScript SDK. It provides an async/await interface for creating, managing, and interacting with cloud sandboxes (microVMs). All methods are async and must be called with `await`.
The `Sandbox` class handles authentication, request formatting, error translation, and response parsing automatically, giving you a clean, Promise-based API for sandbox management.
## Import
```typescript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
```
Or with CommonJS:
```javascript theme={null}
const { Sandbox } = require('@hopx-ai/sdk');
```
## Static Methods
### `create`
Create a new sandbox from a template.
```typescript theme={null}
static async Sandbox.create(options: SandboxCreateOptions): Promise
```
**Parameters:**
* `options.template` (`string`, optional): Template name
* `options.templateId` (`string`, optional): Template ID (alternative to template)
* `options.region` (`string`, optional): Preferred region
* `options.timeoutSeconds` (`number`, optional): Auto-kill timeout in seconds
* `options.internetAccess` (`boolean`, optional): Enable internet (default: `true`)
* `options.envVars` (`Record`, optional): Environment variables
* `options.apiKey` (`string`, optional): API key (or use `HOPX_API_KEY` env var)
* `options.baseURL` (`string`, optional): API base URL
**Returns:** `Promise` - New sandbox instance
**Example:**
```typescript theme={null}
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const info = await sandbox.getInfo();
console.log(info.publicHost);
```
**Expected Output:**
```
https://sandbox_abc123xyz.hopx.dev
```
***
### `connect`
Connect to an existing sandbox by ID.
```typescript theme={null}
static async Sandbox.connect(
sandboxId: string,
options?: { apiKey?: string; baseURL?: string }
): Promise
```
**Parameters:**
* `sandboxId` (`string`): Existing sandbox ID
* `options.apiKey` (`string`, optional): API key
* `options.baseURL` (`string`, optional): API base URL
**Returns:** `Promise` - Connected sandbox instance
If VM is paused, resumes it and refreshes JWT token. If stopped, throws error.
**Example:**
```typescript theme={null}
const sandbox = await Sandbox.connect('sandbox-abc123');
const info = await sandbox.getInfo();
console.log(`Status: ${info.status}`);
```
**Expected Output:**
```
Status: running
```
***
### `list`
List all sandboxes.
```typescript theme={null}
static async Sandbox.list(options?: {
apiKey?: string;
baseURL?: string;
limit?: number;
status?: 'running' | 'stopped' | 'paused' | 'creating';
region?: string;
}): Promise
```
**Returns:** `Promise` - Array of sandbox information objects
**Example:**
```typescript theme={null}
const sandboxes = await Sandbox.list({ status: 'running', limit: 50 });
for (const sb of sandboxes) {
console.log(`${sb.sandboxId}: ${sb.status}`);
}
```
**Expected Output:**
```
sandbox_abc123xyz: running
sandbox_def456uvw: running
```
***
### `listTemplates`
List available templates.
```typescript theme={null}
static async Sandbox.listTemplates(options?: {
category?: string;
language?: string;
apiKey?: string;
baseURL?: string;
}): Promise
```
**Returns:** `Promise` - Array of template information objects
**Example:**
```typescript theme={null}
const templates = await Sandbox.listTemplates({ language: 'python' });
for (const template of templates) {
console.log(`${template.name}: ${template.description}`);
}
```
**Expected Output:**
```
code-interpreter: Python environment with data science libraries
python-basic: Minimal Python 3.11 environment
```
***
### `getTemplate`
Get template details by name.
```typescript theme={null}
static async Sandbox.getTemplate(
name: string,
options?: { apiKey?: string; baseURL?: string }
): Promise
```
**Returns:** `Promise` - Template information object
**Example:**
```typescript theme={null}
const template = await Sandbox.getTemplate('code-interpreter');
console.log(`Resources: ${template.defaultResources.vcpu} vCPU`);
```
**Expected Output:**
```
Resources: 2 vCPU
```
***
## Instance Methods
### Lifecycle Methods
#### `getInfo`
Get current sandbox information.
```typescript theme={null}
async sandbox.getInfo(): Promise
```
**Returns:** `Promise` - Sandbox information object
***
#### `kill`
Destroy the sandbox immediately.
```typescript theme={null}
async sandbox.kill(): Promise
```
This action is irreversible. The sandbox and all its data will be permanently deleted.
***
#### `start`
Start a stopped sandbox.
```typescript theme={null}
async sandbox.start(): Promise
```
***
#### `stop`
Stop a running sandbox.
```typescript theme={null}
async sandbox.stop(): Promise
```
***
#### `pause`
Pause a running sandbox.
```typescript theme={null}
async sandbox.pause(): Promise
```
***
#### `resume`
Resume a paused sandbox.
```typescript theme={null}
async sandbox.resume(): Promise
```
***
### Execution Methods
#### `runCode`
Execute code synchronously with rich output capture.
```typescript theme={null}
async sandbox.runCode(
code: string,
options?: CodeExecutionOptions
): Promise
```
**Parameters:**
* `code` (`string`): Code to execute
* `options.language` (`string`, optional): Language (default: `'python'`)
* `options.timeout` (`number`, optional): Timeout in seconds (default: `60`)
* `options.workingDir` (`string`, optional): Working directory (default: `'/workspace'`)
* `options.env` (`Record`, optional): Environment variables
**Returns:** `Promise` - Execution result
**Example:**
```typescript theme={null}
const result = await sandbox.runCode("print('Hello, HopX!')");
console.log(result.stdout); // "Hello, HopX!\n"
console.log(result.exitCode); // 0
```
**Expected Output:**
```
Hello, HopX!
0
```
***
#### `runCodeAsync`
Execute code asynchronously with webhook callback.
```typescript theme={null}
async sandbox.runCodeAsync(
code: string,
options: AsyncExecutionOptions
): Promise
```
**Parameters:**
* `code` (`string`): Code to execute
* `options.callbackUrl` (`string`): URL to POST results to
* `options.language` (`string`, optional): Language
* `options.timeout` (`number`, optional): Timeout in seconds
* `options.workingDir` (`string`, optional): Working directory
* `options.env` (`Record`, optional): Environment variables
* `options.callbackHeaders` (`Record`, optional): Callback headers
* `options.callbackSignatureSecret` (`string`, optional): Signature secret
**Returns:** `Promise` - Response with `executionId` and `status`
***
#### `runCodeBackground`
Execute code in background and return immediately.
```typescript theme={null}
async sandbox.runCodeBackground(
code: string,
options?: BackgroundExecutionOptions
): Promise
```
**Returns:** `Promise` - Response with `processId` and `executionId`
***
#### `runCodeStream`
Execute code with real-time output streaming via WebSocket.
```typescript theme={null}
async *sandbox.runCodeStream(
code: string,
options?: CodeExecutionOptions
): AsyncIterableIterator
```
**Returns:** `AsyncIterableIterator` - Async generator of stream messages
**Example:**
```typescript theme={null}
for await (const message of sandbox.runCodeStream("print('Hello')")) {
if (message.type === 'stdout') {
console.log(message.data);
}
}
```
**Expected Output:**
```
Hello
```
***
#### `listProcesses`
List all background execution processes.
```typescript theme={null}
async sandbox.listProcesses(): Promise
```
**Returns:** `Promise` - Array of process information objects
***
#### `killProcess`
Kill a background execution process.
```typescript theme={null}
async sandbox.killProcess(processId: string): Promise
```
***
### Information Methods
#### `getMetricsSnapshot`
Get current system metrics snapshot.
```typescript theme={null}
async sandbox.getMetricsSnapshot(): Promise
```
***
#### `getAgentInfo`
Get agent information and capabilities.
```typescript theme={null}
async sandbox.getAgentInfo(): Promise
```
***
#### `refreshToken`
Refresh JWT token for agent authentication.
```typescript theme={null}
async sandbox.refreshToken(): Promise
```
***
#### `getToken`
Get current JWT token.
```typescript theme={null}
async sandbox.getToken(): Promise
```
***
## Properties
### `files`
File operations resource (lazy-loaded).
**Type:** `Files`
**Example:**
```typescript theme={null}
const content = await sandbox.files.read('/workspace/script.py');
await sandbox.files.write('/workspace/data.txt', 'Hello, World!');
```
**Expected Output:**
```
File written successfully
```
See [Files Resource](/sdk/javascript/files) for complete documentation.
***
### `commands`
Command execution resource (lazy-loaded).
**Type:** `Commands`
**Example:**
```typescript theme={null}
const result = await sandbox.commands.run('ls -la /workspace');
console.log(result.stdout);
```
**Expected Output:**
```
total 8
drwxr-xr-x 2 root root 4096 Jan 27 10:30 .
drwxr-xr-x 3 root root 4096 Jan 27 10:30 ..
-rw-r--r-- 1 root root 42 Jan 27 10:30 data.txt
```
***
### `env`
Environment variables resource (lazy-loaded).
**Type:** `EnvironmentVariables`
**Example:**
```typescript theme={null}
await sandbox.env.set('API_KEY', 'secret123');
const allVars = await sandbox.env.getAll();
```
**Expected Output:**
```
Environment variable set successfully
```
***
### `cache`
Cache management resource (lazy-loaded).
**Type:** `Cache`
**Example:**
```typescript theme={null}
const stats = await sandbox.cache.stats();
console.log(`Cache size: ${stats.cache.size}`);
```
**Expected Output:**
```
Cache size: 5
```
***
### `desktop`
Desktop automation resource (lazy-loaded).
**Type:** `Desktop`
**Example:**
```typescript theme={null}
const screenshot = await sandbox.desktop.screenshot();
```
**Expected Output:**
```
Screenshot captured (PNG bytes)
```
***
### `terminal`
Interactive terminal resource via WebSocket (lazy-loaded).
**Type:** `Terminal`
***
### `sandboxId`
Read-only sandbox ID.
**Type:** `string` (read-only)
***
## Examples
### Example 1: Basic Usage
```typescript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function main() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
const result = await sandbox.runCode("print('Hello, HopX!')");
console.log(result.stdout);
await sandbox.kill();
}
main();
```
**Expected Output:**
```
Hello, HopX!
```
### Example 2: File Operations
```typescript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function main() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Write a file
await sandbox.files.write('/workspace/script.py', "print('Hello')");
// Execute it
const result = await sandbox.runCode(
"exec(open('/workspace/script.py').read())"
);
console.log(result.stdout);
await sandbox.kill();
}
```
**Expected Output:**
```
Hello
```
### Example 3: Streaming Output
```typescript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
async function main() {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
for await (const message of sandbox.runCodeStream(
"for i in range(5):\n print(f'Count: {i}')\n import time\n time.sleep(1)"
)) {
if (message.type === 'stdout') {
process.stdout.write(message.data);
}
}
await sandbox.kill();
}
```
**Expected Output:**
```
Count: 0
Count: 1
Count: 2
Count: 3
Count: 4
```
***
## Related Classes
* **[Files](/sdk/javascript/files)** - File operations resource
* **[Commands](/sdk/javascript/commands)** - Command execution resource
* **[Environment Variables](/sdk/javascript/environment-variables)** - Environment variable management
* **[Types](/sdk/javascript/types)** - TypeScript type definitions
## See Also
* [Quickstart Guide](/sdk/javascript/quickstart) - Get started with the SDK
* [Installation](/sdk/javascript/installation) - Install and configure the SDK
* [Core Concepts](/core-concepts/sandboxes/creating) - Learn about sandboxes
## Next Steps
* Learn about [Creating Sandboxes](/core-concepts/sandboxes/creating) with different templates
* Explore [Code Execution](/core-concepts/code-execution/synchronous) to run code in sandboxes
* Review [File Operations](/sdk/javascript/files) for managing files
* Check out [API Reference](/api/vm-agent/overview) for direct API access
* **[CLI Sandbox Commands](/cli/commands/sandbox)** - Manage sandboxes from CLI
# Template Builder
Source: https://docs.hopx.ai/sdk/javascript/template-builder
Fluent API for building custom sandbox templates in the HopX JavaScript/TypeScript SDK. Create custom templates from Docker images, configure resources, add build steps, and install dependencies using a fluent builder pattern. Complete reference for TemplateBuilder class with TypeScript examples and template configuration options.
**Version:** 0.1.22\
**Last Verified:** 2025-01-27\
**Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk)
## Overview
The `Template` class provides a fluent API for building custom sandbox templates.
## Import
```typescript theme={null}
import { Template } from '@hopx-ai/sdk';
```
## Methods
### Base Image Methods
* `template.fromUbuntuImage(version: string): Template`
* `template.fromPythonImage(version: string): Template`
* `template.fromNodeImage(version: string): Template`
* `template.fromImage(image: string, auth?: AuthConfig): Template`
### Configuration Methods
* `template.copy(src: string, dest: string): Template`
* `template.run(command: string): Template`
* `template.env(key: string, value: string): Template`
* `template.expose(port: number): Template`
* `template.workdir(path: string): Template`
* `template.readyCheck(check: ReadyCheck): Template`
* `template.startCmd(command: string): Template`
### Building
```typescript theme={null}
async template.build(options?: BuildOptions): Promise
```
**Example:**
```typescript theme={null}
const template = new Template()
.fromPythonImage('3.11')
.run('pip install flask')
.expose(5000)
.startCmd('python app.py');
const result = await template.build();
console.log(`Template ID: ${result.templateId}`);
```
***
## Related Classes
* **[Ready Checks](/sdk/javascript/ready-checks)** - Ready check utilities
* **[Sandbox](/sdk/javascript/sandbox)** - Use templates with `Sandbox.create({ template: ... })`
## See Also
* [Ready Checks](/sdk/javascript/ready-checks) - Learn about ready checks
* [Core Concepts: Templates](/core-concepts/templates) - Learn about templates
## Next Steps
Now that you understand template building, explore:
* [Ready Checks](/sdk/javascript/ready-checks) - Add readiness verification
* [Building Templates](/core-concepts/templates/building) - Learn template building concepts
* [Template Configuration](/core-concepts/templates/configuration) - Configure templates
* **[CLI Reference](/cli/introduction)** - Use HopX from the command line
* [Custom Templates](/cookbooks/advanced/custom-templates) - Build custom templates
# Terminal Access
Source: https://docs.hopx.ai/sdk/javascript/terminal
Interactive terminal resource for WebSocket-based sandbox terminal access in HopX using the JavaScript/TypeScript SDK. Complete reference for the Terminal class including async methods for connecting to interactive terminals, executing commands in real-time, and streaming terminal output. Includes TypeScript examples for terminal automation.
**Version:** 0.1.22\
**Last Verified:** 2025-01-27\
**Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk)
## Overview
The `Terminal` resource provides interactive terminal access via WebSocket.
## Methods
### `connect`
Connect to interactive terminal.
```typescript theme={null}
async terminal.connect(): Promise
```
**Returns:** `Promise` - WebSocket connection
***
### `sendInput`
Send input to terminal.
```typescript theme={null}
terminal.sendInput(ws: WebSocket, data: string): void
```
***
### `resize`
Resize terminal.
```typescript theme={null}
terminal.resize(ws: WebSocket, cols: number, rows: number): void
```
***
### `output`
Async iterator for terminal output.
```typescript theme={null}
async *terminal.output(ws: WebSocket): AsyncIterableIterator
```
**Example:**
```typescript theme={null}
const ws = await sandbox.terminal.connect();
sandbox.terminal.sendInput(ws, "echo 'Hello'\n");
for await (const message of sandbox.terminal.output(ws)) {
if (message.type === 'stdout') {
console.log(message.data);
}
}
```
***
## Related Classes
* **[Sandbox](/sdk/javascript/sandbox)** - Main sandbox class
* **[Types](/sdk/javascript/types)** - TypeScript type definitions
## See Also
* [Core Concepts: Terminal](/core-concepts/terminal) - Learn about terminal access
* [Sandbox Class](/sdk/javascript/sandbox) - Access terminal via `sandbox.terminal`
## Next Steps
Now that you understand terminal access, explore:
* [WebSocket Terminal](/core-concepts/terminal/websocket) - Learn terminal concepts
* [Sandbox Operations](/sdk/javascript/sandbox) - Use terminal in sandbox workflows
* [Running Commands](/core-concepts/commands/running) - Execute commands
* **[CLI Reference](/cli/introduction)** - Use HopX from the command line
* [Background Commands](/core-concepts/commands/background) - Non-blocking execution
# TypeScript Type Definitions
Source: https://docs.hopx.ai/sdk/javascript/types
TypeScript type definitions for the HopX JavaScript SDK. Complete TypeScript type definitions for sandbox objects, execution results, file metadata, template structures, and all SDK methods. Essential for type-safe development with IntelliSense support. Includes complete type reference and usage examples.
**Version:** 0.1.22\
**Last Verified:** 2025-01-27\
**Package:** `@hopx-ai/sdk` on [npm](https://www.npmjs.com/package/@hopx-ai/sdk)
## Overview
The JavaScript SDK provides comprehensive TypeScript type definitions for all API responses and objects.
## Core Types
### `SandboxInfo`
Sandbox information type.
```typescript theme={null}
interface SandboxInfo {
sandboxId: string;
templateId: string;
templateName: string;
organizationId: string;
nodeId: string;
region: string;
status: 'running' | 'stopped' | 'paused' | 'creating';
publicHost: string;
resources: Resources;
startedAt: Date;
endAt?: Date;
createdAt: Date;
}
```
***
### `TemplateInfo`
Template information type.
```typescript theme={null}
interface TemplateInfo {
id: string;
name: string;
displayName: string;
description: string;
category: string;
language: string;
defaultResources: TemplateResources;
// ... more fields
}
```
***
### `ExecutionResult`
Result of code execution.
```typescript theme={null}
interface ExecutionResult {
success: boolean;
stdout: string;
stderr: string;
exitCode: number;
executionTime: number;
richOutputs: RichOutput[];
}
```
***
### `CommandResponse`
Result of command execution.
```typescript theme={null}
interface CommandResponse {
stdout: string;
stderr: string;
exitCode: number;
executionTime: number;
}
```
***
### `FileInfo`
File or directory information.
```typescript theme={null}
interface FileInfo {
name: string;
path: string;
size: number;
isDirectory: boolean;
permissions: string;
modifiedTime: Date;
}
```
***
## Options Types
### `SandboxCreateOptions`
Options for creating a sandbox.
```typescript theme={null}
interface SandboxCreateOptions {
template?: string;
templateId?: string;
region?: string;
timeoutSeconds?: number;
internetAccess?: boolean;
envVars?: Record;
apiKey?: string;
baseURL?: string;
}
```
***
### `CodeExecutionOptions`
Options for code execution.
```typescript theme={null}
interface CodeExecutionOptions {
language?: string;
timeout?: number;
workingDir?: string;
env?: Record;
}
```
***
### `CommandOptions`
Options for command execution.
```typescript theme={null}
interface CommandOptions {
timeout?: number;
background?: boolean;
workingDir?: string;
env?: Record;
}
```
***
## Related Classes
* **[Errors](/sdk/javascript/errors)** - Error classes and exception handling
* **[Sandbox](/sdk/javascript/sandbox)** - Use types with sandbox operations
## See Also
* [Errors](/sdk/javascript/errors) - Learn about error handling
* [Core Concepts](/core-concepts) - Learn about core concepts
## Next Steps
Now that you understand TypeScript types, explore:
* [Sandbox Operations](/sdk/javascript/sandbox) - Use types in practice
* [Error Handling](/sdk/javascript/errors) - Type-safe error handling
* [Quickstart Guide](/sdk/javascript/quickstart) - Get started with the SDK
* **[CLI Reference](/cli/introduction)** - Use HopX from the command line
* [TypeScript Documentation](https://www.typescriptlang.org/docs/) - Learn more about TypeScript
# AsyncSandbox
Source: https://docs.hopx.ai/sdk/python/async-sandbox
Asynchronous sandbox class for async/await workflows in Python. Use AsyncSandbox for non-blocking operations, concurrent sandbox management, and async/await patterns. Complete reference for all async methods including creating sandboxes, executing code, and managing resources asynchronously. Includes async/await examples and best practices.
**Version:** 0.3.0\
**Last Verified:** 2025-01-27\
**Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/)
## Overview
The `AsyncSandbox` class provides an asynchronous interface for creating and managing cloud sandboxes. Use this class when building async Python applications (FastAPI, aiohttp, etc.) or when you need to manage multiple sandboxes concurrently.
All methods in `AsyncSandbox` are async and must be called with `await`. The class supports async context managers for automatic cleanup.
### When to Use AsyncSandbox vs Sandbox
* **Use `AsyncSandbox`** when:
* Building async Python applications (FastAPI, aiohttp, etc.)
* You need to manage multiple sandboxes concurrently
* You want non-blocking operations
* You're already using async/await in your codebase
* **Use `Sandbox`** when:
* Building synchronous Python applications
* Writing scripts or simple automation
* You prefer blocking operations
## Import
```python theme={null}
from hopx_ai import AsyncSandbox
```
## Class Methods
### `create`
Create a new sandbox from a template (async).
```python theme={null}
await AsyncSandbox.create(
template=None,
*,
template_id=None,
region=None,
timeout_seconds=None,
internet_access=None,
env_vars=None,
api_key=None,
base_url='https://api.hopx.dev'
) -> AsyncSandbox
```
**Parameters:** Same as `Sandbox.create()`
**Returns:** `AsyncSandbox` - New sandbox instance
**Example:**
```python theme={null}
sandbox = await AsyncSandbox.create(template="code-interpreter")
info = await sandbox.get_info()
print(info.public_host)
```
**Expected Output:**
```
https://sandbox_abc123xyz.hopx.dev
```
***
### `connect`
Connect to an existing sandbox by ID (async).
```python theme={null}
await AsyncSandbox.connect(
sandbox_id,
*,
api_key=None,
base_url='https://api.hopx.dev'
) -> AsyncSandbox
```
**Example:**
```python theme={null}
sandbox = await AsyncSandbox.connect("sandbox-abc123")
```
**Expected Output:**
```
Connected to sandbox-abc123
```
***
### `list`
List all sandboxes (async).
```python theme={null}
await AsyncSandbox.list(
*,
status=None,
region=None,
limit=100,
api_key=None,
base_url='https://api.hopx.dev'
) -> List[AsyncSandbox]
```
**Example:**
```python theme={null}
sandboxes = await AsyncSandbox.list(status="running")
for sb in sandboxes:
info = await sb.get_info()
print(f"{info.sandbox_id}: {info.status}")
```
**Expected Output:**
```
sandbox_abc123xyz: running
sandbox_def456uvw: running
```
***
### `iter`
Lazy async iterator for sandboxes.
```python theme={null}
async for sandbox in AsyncSandbox.iter(status="running"):
info = await sandbox.get_info()
print(f"{info.sandbox_id}")
```
**Expected Output:**
```
sandbox_abc123xyz
sandbox_def456uvw
```
***
## Instance Methods
### Lifecycle Methods
All lifecycle methods are async versions of `Sandbox` methods:
* `await sandbox.get_info() -> SandboxInfo`
* `await sandbox.start() -> None`
* `await sandbox.stop() -> None`
* `await sandbox.pause() -> None`
* `await sandbox.resume() -> None`
* `await sandbox.kill() -> None`
### Execution Methods
#### `run_code`
Execute code with rich output capture (async).
```python theme={null}
await sandbox.run_code(
code,
*,
language='python',
timeout_seconds=60,
env=None,
working_dir='/workspace'
) -> ExecutionResult
```
**Example:**
```python theme={null}
result = await sandbox.run_code("print('Hello, HopX!')")
print(result.stdout)
```
**Expected Output:**
```
Hello, HopX!
```
***
#### `run_code_stream`
Stream code execution output (async generator).
```python theme={null}
async for message in sandbox.run_code_stream(
code,
*,
language='python',
timeout_seconds=60
):
print(message)
```
**Expected Output:**
```
{'type': 'stdout', 'data': 'Hello\n'}
{'type': 'stderr', 'data': ''}
{'type': 'done', 'exit_code': 0}
```
***
#### `list_processes`
List running processes in sandbox (async).
```python theme={null}
await sandbox.list_processes() -> List[Dict[str, Any]]
```
**Expected Output:**
```
[{'process_id': 'proc_abc123', 'status': 'running', ...}]
```
***
#### `kill_process`
Kill a process by ID (async).
```python theme={null}
await sandbox.kill_process(process_id) -> Dict[str, Any]
```
**Expected Output:**
```
Process killed successfully
```
***
### Utility Methods
* `await sandbox.get_metrics_snapshot() -> Dict[str, Any]`
* `await sandbox.refresh_token() -> None`
* `await sandbox.set_timeout(seconds) -> None`
***
## Properties
All resource properties are async versions:
* `sandbox.files` → `AsyncFiles`
* `sandbox.commands` → `AsyncCommands`
* `sandbox.env` → `AsyncEnvironmentVariables`
* `sandbox.cache` → `AsyncCache`
* `sandbox.terminal` → `AsyncTerminal`
***
## Async Context Manager
The `AsyncSandbox` class supports async context manager protocol.
**Example:**
```python theme={null}
async with AsyncSandbox.create(template="code-interpreter") as sandbox:
result = await sandbox.run_code("print('Hello')")
print(result.stdout)
# Automatically calls await sandbox.kill() when exiting
```
**Expected Output:**
```
Hello
```
***
## Examples
### Example 1: Basic Async Usage
```python theme={null}
import asyncio
from hopx_ai import AsyncSandbox
async def main():
sandbox = await AsyncSandbox.create(template="code-interpreter")
result = await sandbox.run_code("print('Hello, HopX!')")
print(result.stdout)
await sandbox.kill()
asyncio.run(main())
```
**Expected Output:**
```
Hello, HopX!
```
### Example 2: Using Async Context Manager
```python theme={null}
import asyncio
from hopx_ai import AsyncSandbox
async def main():
async with AsyncSandbox.create(template="code-interpreter") as sandbox:
result = await sandbox.run_code("import sys; print(sys.version)")
print(result.stdout)
asyncio.run(main())
```
**Expected Output:**
```
3.11.5 (main, Jan 27 2025, 10:30:00) [GCC 11.2.0]
```
### Example 3: Concurrent Sandboxes
```python theme={null}
import asyncio
from hopx_ai import AsyncSandbox
async def run_in_sandbox(template):
async with AsyncSandbox.create(template=template) as sandbox:
result = await sandbox.run_code("print('Hello from', template)")
return result.stdout
async def main():
templates = ["code-interpreter", "nodejs", "go"]
results = await asyncio.gather(*[run_in_sandbox(t) for t in templates])
for r in results:
print(r)
asyncio.run(main())
```
**Expected Output:**
```
Hello from code-interpreter
Hello from nodejs
Hello from go
```
### Example 4: Streaming Output
```python theme={null}
import asyncio
from hopx_ai import AsyncSandbox
async def main():
sandbox = await AsyncSandbox.create(template="code-interpreter")
async for message in sandbox.run_code_stream(
"for i in range(5):\n print(f'Count: {i}')\n import time\n time.sleep(1)"
):
if message.get('type') == 'stdout':
print(message.get('data', ''), end='')
await sandbox.kill()
asyncio.run(main())
```
**Expected Output:**
```
Count: 0
Count: 1
Count: 2
Count: 3
Count: 4
```
***
## Related Classes
* **[Sandbox](/sdk/python/sandbox)** - Synchronous version of AsyncSandbox
* **[AsyncFiles](/sdk/python/files)** - Async file operations (accessed via `sandbox.files`)
* **[AsyncCommands](/sdk/python/commands)** - Async command execution
* **[AsyncEnvironmentVariables](/sdk/python/environment-variables)** - Async environment variable management
## See Also
* [Quickstart Guide](/sdk/python/quickstart) - Get started with the SDK
* [Sandbox Class](/sdk/python/sandbox) - Synchronous sandbox class
* [Core Concepts](/core-concepts/sandboxes/creating) - Learn about sandboxes
## Next Steps
* Learn about [Synchronous Sandbox](/sdk/python/sandbox) if you prefer blocking operations
* Explore [Code Execution](/core-concepts/code-execution/synchronous) concepts
* Review [File Operations](/sdk/python/files) for async file management
* **[CLI Reference](/cli/introduction)** - Use HopX from the command line
* Check out [API Reference](/api/vm-agent/overview) for direct API access
# Cache Management
Source: https://docs.hopx.ai/sdk/python/cache
Cache management resource for managing execution result cache in HopX sandboxes using the Python SDK. Complete reference for the Cache class including methods for viewing cache statistics and clearing execution cache. Includes code examples for cache optimization and performance tuning.
**Version:** 0.3.0\
**Last Verified:** 2025-01-27\
**Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/)
## Overview
The `Cache` resource provides methods for managing the execution result cache in sandboxes. The cache stores execution results to improve performance for repeated code executions. Use this resource to view cache statistics and clear the cache when needed.
## Access
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
cache = sandbox.cache # Lazy-loaded
```
## Methods
### `stats`
Get cache statistics.
```python theme={null}
cache.stats(*, timeout=None) -> Dict[str, Any]
```
**Returns:** `Dict[str, Any]` - Cache statistics dictionary with:
* `cache.total_hits` (`int`): Total cache hits
* `cache.size` (`int`): Current cache size
* `cache.max_size` (`int`): Maximum cache size
* `cache.ttl` (`int`): Time-to-live in seconds
* `timestamp` (`str`): Timestamp of the statistics
**Example:**
```python theme={null}
stats = sandbox.cache.stats()
cache_data = stats['cache']
print(f"Cache hits: {cache_data['total_hits']}")
print(f"Cache size: {cache_data['size']} / {cache_data['max_size']}")
```
***
### `clear`
Clear the execution result cache.
```python theme={null}
cache.clear(*, timeout=None) -> Dict[str, Any]
```
**Returns:** `Dict[str, Any]` - Confirmation message
This clears all cached execution results. Subsequent executions will not benefit from cached results until cache is repopulated.
**Example:**
```python theme={null}
# Check cache size before clearing
stats_before = sandbox.cache.stats()
print(f"Cache size before: {stats_before['cache']['size']}")
# Clear cache
sandbox.cache.clear()
# Check cache size after clearing
stats_after = sandbox.cache.stats()
print(f"Cache size after: {stats_after['cache']['size']}")
```
**See Also:**
* [API: Clear Cache](/api/vm-agent/clear-cache)
***
## Examples
### Example 1: Viewing Cache Statistics
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Get cache statistics
stats = sandbox.cache.stats()
cache_data = stats['cache']
print(f"Total cache hits: {cache_data['total_hits']}")
print(f"Current size: {cache_data['size']}")
print(f"Max size: {cache_data['max_size']}")
print(f"TTL: {cache_data['ttl']} seconds")
sandbox.kill()
```
### Example 2: Clearing Cache
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Execute code (may be cached)
result1 = sandbox.run_code("print('Hello')")
# Clear cache
sandbox.cache.clear()
print("Cache cleared")
# Execute again (not cached)
result2 = sandbox.run_code("print('Hello')")
sandbox.kill()
```
### Example 3: Monitoring Cache Usage
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Check initial cache state
initial_stats = sandbox.cache.stats()
print(f"Initial cache size: {initial_stats['cache']['size']}")
# Run multiple executions
for i in range(5):
sandbox.run_code(f"print('Execution {i}')")
# Check cache after executions
final_stats = sandbox.cache.stats()
print(f"Final cache size: {final_stats['cache']['size']}")
print(f"Cache hits: {final_stats['cache']['total_hits']}")
sandbox.kill()
```
***
## Related Classes
* **[Sandbox](/sdk/python/sandbox)** - Main sandbox class
* **[Core Concepts: Cache](/core-concepts/cache/statistics)** - Learn about cache management
## See Also
* [Sandbox Class](/sdk/python/sandbox) - Access cache via `sandbox.cache`
* [Cache Statistics](/core-concepts/cache/statistics) - Detailed cache documentation
## Related
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Execution results are cached
* **[API: Cache Management](/api/vm-agent/get-cache-stats)** - VM Agent API endpoints
## Next Steps
* Learn about [Code Execution](/core-concepts/code-execution/synchronous) to see cached results
* Review [Cache Statistics](/core-concepts/cache/statistics) for detailed cache information
* **[CLI Cache](/cli/commands/system)** - View cache statistics from CLI
# Command Execution
Source: https://docs.hopx.ai/sdk/python/commands
Command execution resource for running shell commands in HopX sandboxes using the Python SDK. Complete reference for the Commands class including methods for running commands synchronously and in the background. Includes code examples for system administration, package installation, and automation tasks.
**Version:** 0.3.0\
**Last Verified:** 2025-01-27\
**Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/)
## Overview
The `Commands` resource provides shell command execution capabilities for sandboxes. Access it via the `commands` property on a `Sandbox` instance. Use this resource when you need to run shell commands, install packages, or execute system utilities.
The `Commands` resource is lazy-loaded and provides synchronous command execution.
## Access
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
commands = sandbox.commands # Lazy-loaded
```
## Methods
### `run`
Run a shell command.
```python theme={null}
commands.run(
command,
*,
timeout=30,
background=False,
env=None,
working_dir='/workspace'
) -> CommandResult
```
**Parameters:**
* `command` (`str`): Shell command to execute
* `timeout` (`int`, optional): Command timeout in seconds (default: `30`)
* `background` (`bool`, optional): Run in background (default: `False`)
* `env` (`Dict[str, str]`, optional): Environment variables for command
* `working_dir` (`str`, optional): Working directory (default: `'/workspace'`)
**Returns:** `CommandResult` - Command execution result with `stdout`, `stderr`, `exit_code`, and `execution_time`
**Raises:**
* `CommandExecutionError`: Command execution failed
* `TimeoutError`: Command timed out
**Example:**
```python theme={null}
result = sandbox.commands.run("ls -la /workspace")
print(result.stdout)
print(f"Exit code: {result.exit_code}")
```
**See Also:**
* [API: Run Command](/api/vm-agent/run-command)
***
## CommandResult Model
The `run()` method returns a `CommandResult` object with:
* `stdout` (`str`): Standard output
* `stderr` (`str`): Standard error
* `exit_code` (`int`): Exit code (0 = success)
* `execution_time` (`float`): Execution time in seconds
* `success` (`bool`): Convenience property (`exit_code == 0`)
***
## Examples
### Example 1: Basic Command Execution
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Run a simple command
result = sandbox.commands.run("echo 'Hello, World!'")
print(result.stdout) # "Hello, World!\n"
print(f"Success: {result.success}")
sandbox.kill()
```
### Example 2: Install Packages
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Install a package
result = sandbox.commands.run("pip install requests")
if result.success:
print("Package installed successfully")
else:
print(f"Installation failed: {result.stderr}")
sandbox.kill()
```
### Example 3: Command with Environment Variables
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Run command with custom environment
result = sandbox.commands.run(
"echo $MY_VAR",
env={"MY_VAR": "Hello from env"}
)
print(result.stdout)
sandbox.kill()
```
### Example 4: Working Directory
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Create directory
sandbox.files.mkdir("/workspace/my_project")
# Run command in specific directory
result = sandbox.commands.run(
"pwd",
working_dir="/workspace/my_project"
)
print(result.stdout) # "/workspace/my_project\n"
sandbox.kill()
```
### Example 5: Long-Running Commands
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Run command with longer timeout
result = sandbox.commands.run(
"sleep 10 && echo 'Done'",
timeout=60
)
print(result.stdout)
sandbox.kill()
```
***
## Related Classes
* **[Sandbox](/sdk/python/sandbox)** - Main sandbox class
* **[Files](/sdk/python/files)** - File operations resource
* **[Models](/sdk/python/models)** - Data models including `CommandResult`
## See Also
* [Core Concepts: Execution](/core-concepts/execution) - Learn about code execution
* [Sandbox Class](/sdk/python/sandbox) - Access commands via `sandbox.commands`
## Related
* **[Running Commands](/core-concepts/commands/running)** - Learn about command execution
* **[Background Commands](/core-concepts/commands/background)** - Run commands in background
* **[API: Command Execution](/api/vm-agent/run-command)** - VM Agent API endpoints
## Next Steps
* Learn about [Running Commands](/core-concepts/commands/running) for synchronous execution
* Explore [Background Commands](/core-concepts/commands/background) for non-blocking tasks
* Review [Code Execution](/core-concepts/code-execution/synchronous) for programmatic execution
* **[CLI Commands](/cli/commands/cmd)** - Execute shell commands from the command line
# Desktop Automation
Source: https://docs.hopx.ai/sdk/python/desktop
Desktop automation resource for sandbox GUI interactions, screenshots, and VNC access in HopX using the Python SDK. Complete reference for the Desktop class including methods for VNC servers, screenshots, mouse and keyboard control, window management, and clipboard operations. Includes code examples for desktop automation.
**Version:** 0.3.0\
**Last Verified:** 2025-01-27\
**Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/)
## Overview
The `Desktop` resource provides desktop automation capabilities for sandboxes with GUI support. Use this resource for GUI automation, taking screenshots, controlling mouse/keyboard, managing windows, and accessing VNC.
Desktop features require a desktop-enabled template. Not all templates support desktop operations.
## Access
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop-template")
desktop = sandbox.desktop # Lazy-loaded
```
## VNC Methods
### `start_vnc`
Start VNC server.
```python theme={null}
desktop.start_vnc(display=1, password=None) -> VNCInfo
```
**Parameters:**
* `display` (`int`, optional): Display number (default: `1`)
* `password` (`str`, optional): VNC password
**Returns:** `VNCInfo` - VNC server information with `url`, `port`, `password`
**Example:**
```python theme={null}
vnc = sandbox.desktop.start_vnc(password="mypassword")
print(f"VNC URL: {vnc.url}")
```
**Expected Output:**
```
VNC URL: https://vnc-sandbox_abc123xyz.hopx.dev
```
***
### `stop_vnc`
Stop VNC server.
```python theme={null}
desktop.stop_vnc() -> None
```
**Expected Output:**
```
VNC server stopped successfully
```
***
### `get_vnc_status`
Get VNC server status.
```python theme={null}
desktop.get_vnc_status() -> VNCInfo
```
**Expected Output:**
```
VNC server is running on port 5901
```
***
### `get_vnc_url`
Get VNC URL (convenience method).
```python theme={null}
desktop.get_vnc_url() -> str
```
**Expected Output:**
```
https://vnc-sandbox_abc123xyz.hopx.dev
```
***
## Mouse Methods
### `click`
Click at position.
```python theme={null}
desktop.click(x, y, button='left', clicks=1) -> None
```
**Parameters:**
* `x` (`int`): X coordinate
* `y` (`int`): Y coordinate
* `button` (`str`, optional): Mouse button (`'left'`, `'right'`, `'middle'`) (default: `'left'`)
* `clicks` (`int`, optional): Number of clicks (default: `1`)
**Expected Output:**
```
Mouse clicked at (x, y)
```
***
### `move`
Move mouse cursor to position.
```python theme={null}
desktop.move(x, y) -> None
```
**Expected Output:**
```
Mouse moved to (x, y)
```
***
### `drag`
Drag from one position to another.
```python theme={null}
desktop.drag(from_x, from_y, to_x, to_y, button='left') -> None
```
**Expected Output:**
```
Drag completed from (from_x, from_y) to (to_x, to_y)
```
***
### `scroll`
Scroll mouse wheel.
```python theme={null}
desktop.scroll(amount, direction='down') -> None
```
**Parameters:**
* `amount` (`int`): Scroll amount
* `direction` (`str`, optional): `'up'` or `'down'` (default: `'down'`)
**Expected Output:**
```
Scrolled {amount} units {direction}
```
***
## Keyboard Methods
### `type`
Type text.
```python theme={null}
desktop.type(text, delay_ms=10) -> None
```
**Parameters:**
* `text` (`str`): Text to type
* `delay_ms` (`int`, optional): Delay between keystrokes in milliseconds (default: `10`)
**Expected Output:**
```
Text typed: {text}
```
***
### `press`
Press a key.
```python theme={null}
desktop.press(key) -> None
```
**Parameters:**
* `key` (`str`): Key name (e.g., `'Enter'`, `'Escape'`, `'Tab'`)
**Expected Output:**
```
Key pressed: {key}
```
***
### `combination`
Press key combination.
```python theme={null}
desktop.combination(modifiers, key) -> None
```
**Parameters:**
* `modifiers` (`List[str]`): Modifier keys (e.g., `['Ctrl', 'Alt']`)
* `key` (`str`): Key to press
**Example:**
```python theme={null}
desktop.combination(['Ctrl', 'C'], 'c') # Ctrl+C
```
**Expected Output:**
```
Key combination executed: Ctrl+C
```
***
## Clipboard Methods
### `set_clipboard`
Set clipboard content.
```python theme={null}
desktop.set_clipboard(text) -> None
```
**Expected Output:**
```
Clipboard set successfully
```
### `get_clipboard`
Get clipboard content.
```python theme={null}
desktop.get_clipboard() -> str
```
**Expected Output:**
```
Clipboard content retrieved
```
## Screenshot Methods
### `screenshot`
Capture full screen screenshot.
```python theme={null}
desktop.screenshot() -> bytes
```
**Returns:** `bytes` - Screenshot image as PNG bytes
**Example:**
```python theme={null}
screenshot = sandbox.desktop.screenshot()
with open("screenshot.png", "wb") as f:
f.write(screenshot)
```
**Expected Output:**
```
Screenshot saved to screenshot.png (PNG bytes)
```
***
### `screenshot_region`
Capture screenshot of specific region.
```python theme={null}
desktop.screenshot_region(x, y, width, height) -> bytes
```
**Parameters:**
* `x` (`int`): X coordinate of top-left corner
* `y` (`int`): Y coordinate of top-left corner
* `width` (`int`): Region width
* `height` (`int`): Region height
**Expected Output:**
```
Screenshot captured (PNG bytes, {width}x{height} region)
```
***
## Window Methods
### `get_windows`
Get list of all windows.
```python theme={null}
desktop.get_windows() -> List[WindowInfo]
```
**Returns:** `List[WindowInfo]` - List of window information objects
**Expected Output:**
```
[WindowInfo(id='window_1', title='Application', ...), WindowInfo(id='window_2', ...)]
```
***
### `focus_window`
Focus (activate) window.
```python theme={null}
desktop.focus_window(window_id) -> None
```
**Expected Output:**
```
Window focused successfully
```
***
### `close_window`
Close window.
```python theme={null}
desktop.close_window(window_id) -> None
```
**Expected Output:**
```
Window closed successfully
```
***
## Examples
### Example 1: Taking Screenshots
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop-template")
# Take full screen screenshot
screenshot = sandbox.desktop.screenshot()
with open("fullscreen.png", "wb") as f:
f.write(screenshot)
# Take region screenshot
region = sandbox.desktop.screenshot_region(0, 0, 800, 600)
with open("region.png", "wb") as f:
f.write(region)
sandbox.kill()
```
**Expected Output:**
```
Screenshots saved: fullscreen.png, region.png
```
### Example 2: Mouse and Keyboard Automation
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="desktop-template")
# Click at position
sandbox.desktop.click(100, 200)
# Type text
sandbox.desktop.type("Hello, World!")
# Press Enter
sandbox.desktop.press("Enter")
# Drag and drop
sandbox.desktop.drag(100, 100, 300, 300)
sandbox.kill()
```
**Expected Output:**
```
Mouse clicked at (100, 200)
Text typed: Hello, World!
Enter key pressed
Drag completed from (100, 100) to (300, 300)
```
***
## Related Classes
* **[Sandbox](/sdk/python/sandbox)** - Main sandbox class
* **[Models](/sdk/python/models)** - Data models including `VNCInfo`, `WindowInfo`
## See Also
* [Core Concepts: Desktop](/core-concepts/desktop) - Learn about desktop automation
* [Sandbox Class](/sdk/python/sandbox) - Access desktop via `sandbox.desktop`
## Related
* **[Desktop Automation](/core-concepts/desktop/vnc-server)** - Learn about desktop automation
* **[Sandbox Class](/sdk/python/sandbox)** - Access desktop via `sandbox.desktop`
## Next Steps
* Learn about [VNC Server](/core-concepts/desktop/vnc-server) for remote desktop access
* Explore [Screenshots](/core-concepts/desktop/screenshots) for visual verification
* Review [Mouse Control](/core-concepts/desktop/mouse-control) and [Keyboard Control](/core-concepts/desktop/keyboard-control) for GUI automation
* **[CLI System Commands](/cli/commands/system)** - System operations from CLI
# Environment Variables
Source: https://docs.hopx.ai/sdk/python/environment-variables
Environment variable management resource for configuring sandbox environment in HopX using the Python SDK. Complete reference for the Environment class including methods for getting, setting, updating, and clearing environment variables. Includes code examples for configuration management and environment setup.
**Version:** 0.3.0\
**Last Verified:** 2025-01-27\
**Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/)
## Overview
The `EnvironmentVariables` resource (accessed via `sandbox.env`) provides methods for managing environment variables in sandboxes. Use this resource to set, get, update, and delete environment variables that are available to all code execution and commands.
Environment variables set through this resource persist for the lifetime of the sandbox and are available to all executions.
## Access
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
env = sandbox.env # Lazy-loaded
```
## Methods
### `get_all`
Get all environment variables.
```python theme={null}
env.get_all(*, timeout=None) -> Dict[str, str]
```
**Returns:** `Dict[str, str]` - Dictionary of all environment variables
**Example:**
```python theme={null}
all_vars = sandbox.env.get_all()
for key, value in all_vars.items():
print(f"{key}={value}")
```
**Expected Output:**
```
PATH=/usr/local/bin:/usr/bin:/bin
HOME=/root
LANG=en_US.UTF-8
```
**See Also:**
* [API: Get Environment Variables](/api/vm-agent/get-env)
***
### `get`
Get a specific environment variable value.
```python theme={null}
env.get(key, default=None) -> Optional[str]
```
**Parameters:**
* `key` (`str`): Environment variable name
* `default` (`str`, optional): Default value if not found
**Returns:** `Optional[str]` - Variable value or default
**Example:**
```python theme={null}
api_key = sandbox.env.get("API_KEY", "not-set")
print(f"API key: {api_key}")
```
**Expected Output:**
```
API key: not-set
```
**See Also:**
* [API: Get Environment Variables](/api/vm-agent/get-env)
***
### `set`
Set a single environment variable.
```python theme={null}
env.set(key, value, *, timeout=None) -> Dict[str, str]
```
**Parameters:**
* `key` (`str`): Environment variable name
* `value` (`str`): Variable value
* `timeout` (`int`, optional): Request timeout
**Returns:** `Dict[str, str]` - Updated dictionary of all environment variables
**Example:**
```python theme={null}
sandbox.env.set("API_KEY", "secret123")
all_vars = sandbox.env.get_all()
print(all_vars["API_KEY"]) # "secret123"
```
**Expected Output:**
```
secret123
```
**See Also:**
* [API: Set Environment Variables](/api/vm-agent/set-env)
***
### `set_all`
Set/replace all environment variables (destructive).
```python theme={null}
env.set_all(env_vars, *, timeout=None) -> Dict[str, str]
```
**Parameters:**
* `env_vars` (`Dict[str, str]`): Dictionary of environment variables
* `timeout` (`int`, optional): Request timeout
**Returns:** `Dict[str, str]` - Updated dictionary of all environment variables
This replaces ALL existing environment variables. Use `update()` to merge instead.
**Example:**
```python theme={null}
sandbox.env.set_all({
"API_KEY": "secret123",
"DEBUG": "true",
"ENV": "production"
})
```
**Expected Output:**
```
All environment variables replaced successfully
```
***
### `update`
Update specific environment variables (merge with existing).
```python theme={null}
env.update(env_vars, *, timeout=None) -> Dict[str, str]
```
**Parameters:**
* `env_vars` (`Dict[str, str]`): Dictionary of environment variables to update
* `timeout` (`int`, optional): Request timeout
**Returns:** `Dict[str, str]` - Updated dictionary of all environment variables
**Example:**
```python theme={null}
# Merge new variables with existing
sandbox.env.update({
"NEW_VAR": "value",
"API_KEY": "updated-secret"
})
```
**Expected Output:**
```
Environment variables updated successfully
```
**See Also:**
* [API: Update Environment Variables](/api/vm-agent/update-env)
***
### `delete`
Delete a specific environment variable.
```python theme={null}
env.delete(key, *, timeout=None) -> None
```
**Parameters:**
* `key` (`str`): Environment variable name to delete
* `timeout` (`int`, optional): Request timeout
**Example:**
```python theme={null}
sandbox.env.delete("OLD_VAR")
```
**Expected Output:**
```
Environment variable deleted successfully
```
***
## Examples
### Example 1: Basic Environment Variable Management
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set environment variables
sandbox.env.set("API_KEY", "secret123")
sandbox.env.set("DEBUG", "true")
# Get a variable
api_key = sandbox.env.get("API_KEY")
print(f"API key: {api_key}")
# Get all variables
all_vars = sandbox.env.get_all()
print(f"Total variables: {len(all_vars)}")
sandbox.kill()
```
**Expected Output:**
```
API key: secret123
Total variables: 5
```
### Example 2: Setting Variables at Creation
```python theme={null}
from hopx_ai import Sandbox
# Set environment variables when creating sandbox
sandbox = Sandbox.create(
template="code-interpreter",
env_vars={
"API_KEY": "secret123",
"DEBUG": "true",
"ENV": "development"
}
)
# Verify they're set
result = sandbox.run_code("import os; print(os.getenv('API_KEY'))")
print(result.stdout)
sandbox.kill()
```
**Expected Output:**
```
secret123
```
### Example 3: Updating Variables
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set initial variables
sandbox.env.set_all({
"VAR1": "value1",
"VAR2": "value2"
})
# Update specific variables (merge)
sandbox.env.update({
"VAR2": "updated-value2",
"VAR3": "value3"
})
# VAR1 still exists, VAR2 updated, VAR3 added
all_vars = sandbox.env.get_all()
print(all_vars)
sandbox.kill()
```
**Expected Output:**
```
{'VAR1': 'value1', 'VAR2': 'updated-value2', 'VAR3': 'value3', 'PATH': '/usr/local/bin:/usr/bin:/bin', 'HOME': '/root'}
```
### Example 4: Using Variables in Code Execution
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set environment variable
sandbox.env.set("SECRET", "my-secret-key")
# Use it in code execution
result = sandbox.run_code(
"import os; print(os.getenv('SECRET'))"
)
print(result.stdout) # "my-secret-key\n"
sandbox.kill()
```
**Expected Output:**
```
my-secret-key
```
### Example 5: Using Variables in Commands
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Set environment variable
sandbox.env.set("MY_VAR", "Hello from env")
# Use it in command
result = sandbox.commands.run("echo $MY_VAR")
print(result.stdout) # "Hello from env\n"
sandbox.kill()
```
**Expected Output:**
```
Hello from env
```
***
## Related Classes
* **[Sandbox](/sdk/python/sandbox)** - Main sandbox class
* **[Commands](/sdk/python/commands)** - Command execution resource
* **[Files](/sdk/python/files)** - File operations resource
## See Also
* [Core Concepts: Environment Variables](/core-concepts/environment-variables) - Learn about environment configuration
* [Sandbox Class](/sdk/python/sandbox) - Access env via `sandbox.env`
## Related
* **[Getting Environment Variables](/core-concepts/environment/getting)** - Learn about getting env vars
* **[Setting Environment Variables](/core-concepts/environment/setting)** - Learn about setting env vars
* **[Updating Environment Variables](/core-concepts/environment/updating)** - Batch update env vars
* **API**: [GET /env](/api/vm-agent/get-env) - VM Agent API endpoint
## Next Steps
* Learn about [Getting Environment Variables](/core-concepts/environment/getting) to read values
* Explore [Setting Environment Variables](/core-concepts/environment/setting) to configure environment
* Review [Updating Environment Variables](/core-concepts/environment/updating) for batch updates
* **[CLI Environment Variables](/cli/commands/env)** - Manage environment variables from the command line
## Related
* **[Getting Environment Variables](/core-concepts/environment/getting)** - Learn about retrieving variables
* **[Setting Environment Variables](/core-concepts/environment/setting)** - Learn about setting variables
* **[Updating Environment Variables](/core-concepts/environment/updating)** - Learn about updating variables
* **[API: Environment Variables](/api/vm-agent/get-env)** - VM Agent API endpoints
# Sandbox Error Handling
Source: https://docs.hopx.ai/sdk/python/errors
Error classes and exception handling in the HopX Python SDK. Handle API errors, network errors, agent errors, and validation errors gracefully. Learn about error types, error handling patterns, and best practices for robust error handling in your applications. Includes error class reference and handling examples.
**Version:** 0.3.0\
**Last Verified:** 2025-01-27\
**Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/)
## Overview
The Python SDK provides a comprehensive error hierarchy for handling different types of errors. All errors inherit from `HopxError` and provide detailed error information.
## Import
```python theme={null}
from hopx_ai import (
HopxError,
APIError,
AuthenticationError,
NotFoundError,
ValidationError,
RateLimitError,
ResourceLimitError,
ServerError,
NetworkError,
TimeoutError,
AgentError,
FileNotFoundError,
FileOperationError,
CodeExecutionError,
CommandExecutionError,
DesktopNotAvailableError
)
```
## Base Error
### `HopxError`
Base exception for all HopX SDK errors.
**Fields:**
* `message` (`str`): Error message
* `code` (`str`, optional): Error code
* `request_id` (`str`, optional): Request ID for debugging
* `status_code` (`int`, optional): HTTP status code
* `details` (`Dict[str, Any]`, optional): Additional error details
**Example:**
```python theme={null}
try:
sandbox = Sandbox.create(template="invalid-template")
except HopxError as e:
print(f"Error: {e.message}")
print(f"Code: {e.code}")
```
**Expected Output:**
```
Error: Template not found
Code: TEMPLATE_NOT_FOUND
```
***
## API Errors
### `APIError`
Base class for API request failures.
**Inherits from:** `HopxError`
**Fields:**
* `status_code` (`int`): HTTP status code
***
### `AuthenticationError`
Authentication failed (401).
**Inherits from:** `APIError`
**When raised:**
* Invalid or missing API key
* Expired authentication token
**Example:**
```python theme={null}
try:
sandbox = Sandbox.create(template="code-interpreter", api_key="invalid")
except AuthenticationError:
print("Invalid API key")
```
**Expected Output:**
```
Invalid API key
```
***
### `NotFoundError`
Resource not found (404).
**Inherits from:** `APIError`
**When raised:**
* Sandbox not found
* Template not found
* File not found
**Example:**
```python theme={null}
try:
sandbox = Sandbox.connect("non-existent-id")
except NotFoundError:
print("Sandbox not found")
```
**Expected Output:**
```
Sandbox not found
```
***
### `ValidationError`
Request validation failed (400).
**Inherits from:** `APIError`
**Fields:**
* `field` (`str`, optional): Field that failed validation
**When raised:**
* Invalid parameters
* Missing required fields
* Invalid data format
**Example:**
```python theme={null}
try:
sandbox = Sandbox.create(template="", template_id="")
except ValidationError as e:
print(f"Validation failed: {e.message}")
if e.field:
print(f"Field: {e.field}")
```
**Expected Output:**
```
Validation failed: Either template or template_id must be provided
Field: template
```
***
### `RateLimitError`
Rate limit exceeded (429).
**Inherits from:** `APIError`
**Fields:**
* `retry_after` (`int`, optional): Seconds to wait before retrying
**When raised:**
* Too many requests in a time period
**Example:**
```python theme={null}
try:
sandbox = Sandbox.create(template="code-interpreter")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after} seconds")
```
**Expected Output:**
```
Rate limited. Retry after 60 seconds
```
***
### `ResourceLimitError`
Resource limit exceeded.
**Inherits from:** `APIError`
**Fields:**
* `limit` (`int`): Resource limit
* `current` (`int`): Current usage
* `available` (`int`): Available resources
* `upgrade_url` (`str`, optional): URL to upgrade plan
**When raised:**
* Exceeded sandbox quota
* Insufficient resources
**Example:**
```python theme={null}
try:
sandbox = Sandbox.create(template="code-interpreter")
except ResourceLimitError as e:
print(f"Limit exceeded: {e.current}/{e.limit}")
if e.upgrade_url:
print(f"Upgrade at: {e.upgrade_url}")
```
**Expected Output:**
```
Limit exceeded: 10/10
Upgrade at: https://console.hopx.dev/upgrade
```
***
### `ServerError`
Server error (5xx).
**Inherits from:** `APIError`
**When raised:**
* Internal server error
* Service unavailable
***
## Network Errors
### `NetworkError`
Network communication failed.
**Inherits from:** `HopxError`
**When raised:**
* Connection errors
* DNS resolution failures
***
### `TimeoutError`
Request timed out.
**Inherits from:** `NetworkError`
**When raised:**
* Request exceeded timeout
* Operation took too long
**Example:**
```python theme={null}
try:
result = sandbox.run_code("import time; time.sleep(300)", timeout=60)
except TimeoutError:
print("Execution timed out")
```
**Expected Output:**
```
Execution timed out
```
***
## Agent Errors
### `AgentError`
Base error for agent operations.
**Inherits from:** `HopxError`
***
### `FileNotFoundError`
File or directory not found in sandbox.
**Inherits from:** `AgentError`
**Fields:**
* `path` (`str`): Path that was not found
**Example:**
```python theme={null}
try:
content = sandbox.files.read("/nonexistent/file.txt")
except FileNotFoundError as e:
print(f"File not found: {e.path}")
```
**Expected Output:**
```
File not found: /nonexistent/file.txt
```
***
### `FileOperationError`
File operation failed.
**Inherits from:** `AgentError`
**Fields:**
* `operation` (`str`): Operation that failed
**Example:**
```python theme={null}
try:
sandbox.files.write("/readonly/file.txt", "content")
except FileOperationError as e:
print(f"File operation failed: {e.operation}")
```
**Expected Output:**
```
File operation failed: write
```
***
### `CodeExecutionError`
Code execution failed.
**Inherits from:** `AgentError`
**Fields:**
* `language` (`str`): Language that failed
**Example:**
```python theme={null}
try:
result = sandbox.run_code("invalid syntax here", language="python")
except CodeExecutionError as e:
print(f"Code execution failed: {e.message}")
```
**Expected Output:**
```
Code execution failed: SyntaxError: invalid syntax
```
***
### `CommandExecutionError`
Command execution failed.
**Inherits from:** `AgentError`
**Fields:**
* `command` (`str`): Command that failed
**Example:**
```python theme={null}
try:
result = sandbox.commands.run("nonexistent-command")
except CommandExecutionError as e:
print(f"Command failed: {e.command}")
```
**Expected Output:**
```
Command failed: nonexistent-command
```
***
### `DesktopNotAvailableError`
Desktop automation not available in this sandbox.
**Inherits from:** `AgentError`
**Fields:**
* `missing_dependencies` (`List[str]`): Missing dependencies
* `docs_url` (`str`, optional): Documentation URL
* `install_command` (`str`, optional): Installation command
**Example:**
```python theme={null}
try:
screenshot = sandbox.desktop.screenshot()
except DesktopNotAvailableError as e:
print(f"Desktop not available: {e.message}")
if e.install_command:
print(f"Install with: {e.install_command}")
```
**Expected Output:**
```
Desktop not available: Desktop automation requires desktop-enabled template
Install with: Use template with desktop support
```
***
## Error Handling Examples
### Example 1: Basic Error Handling
```python theme={null}
from hopx_ai import Sandbox, HopxError
try:
sandbox = Sandbox.create(template="code-interpreter")
result = sandbox.run_code("print('Hello')")
except HopxError as e:
print(f"Error: {e.message}")
if hasattr(e, 'status_code'):
print(f"Status: {e.status_code}")
```
**Expected Output:**
```
Hello
```
### Example 2: Specific Error Handling
```python theme={null}
from hopx_ai import Sandbox, AuthenticationError, NotFoundError, ValidationError
try:
sandbox = Sandbox.create(template="code-interpreter")
except AuthenticationError:
print("Authentication failed. Check your API key.")
except NotFoundError:
print("Template not found.")
except ValidationError as e:
print(f"Invalid request: {e.message}")
```
**Expected Output:**
```
Sandbox created successfully
```
### Example 3: Retry on Rate Limit
```python theme={null}
from hopx_ai import Sandbox, RateLimitError
import time
def create_sandbox_with_retry():
max_retries = 3
for attempt in range(max_retries):
try:
return Sandbox.create(template="code-interpreter")
except RateLimitError as e:
if attempt < max_retries - 1:
wait_time = e.retry_after or 60
print(f"Rate limited. Waiting {wait_time} seconds...")
time.sleep(wait_time)
else:
raise
```
**Expected Output:**
```
Sandbox created successfully (after retry if needed)
```
***
## Related Classes
* **[Models](/sdk/python/models)** - Data models
* **[Sandbox](/sdk/python/sandbox)** - Sandbox operations that may raise errors
## See Also
* [Models](/sdk/python/models) - Learn about data models
* [Core Concepts: Errors](/core-concepts/errors) - Learn about error handling
## Next Steps
Now that you understand error handling, explore:
* [Error Handling Basics](/cookbooks/getting-started/error-handling) - Practical error handling patterns
* [Sandbox Operations](/sdk/python/sandbox) - See errors in action
* [API Errors](/api/concepts/errors) - Understand API error responses
* **[CLI Reference](/cli/introduction)** - Use HopX from the command line
* [Troubleshooting](/api/concepts/troubleshooting) - Common issues and solutions
# File Operations
Source: https://docs.hopx.ai/sdk/python/files
File operations resource for reading, writing, and managing files in HopX sandboxes using the Python SDK. Complete reference for the Files class including methods for reading, writing, listing, uploading, downloading, and watching files. Includes code examples for all file operations and error handling.
**Version:** 0.3.0\
**Last Verified:** 2025-01-27\
**Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/)
## Overview
The `Files` resource provides file operations for sandboxes. Access it via the `files` property on a `Sandbox` instance. All file operations are synchronous and work with both text and binary files.
The `Files` resource is lazy-loaded, meaning it's only initialized when first accessed.
## Access
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
files = sandbox.files # Lazy-loaded
```
## Methods
### `read`
Read text file contents.
```python theme={null}
files.read(path, *, timeout=None) -> str
```
**Parameters:**
* `path` (`str`): File path to read
* `timeout` (`int`, optional): Request timeout in seconds
**Returns:** `str` - File contents as string
**Raises:**
* `FileNotFoundError`: File does not exist
* `FileOperationError`: Read operation failed
**Example:**
```python theme={null}
content = sandbox.files.read("/workspace/script.py")
print(content)
```
**Expected Output:**
```
print('Hello, World!')
```
**See Also:**
* [API: Read File](/api/vm-agent/read-file)
***
### `read_bytes`
Read binary file contents.
```python theme={null}
files.read_bytes(path, *, timeout=None) -> bytes
```
**Parameters:**
* `path` (`str`): File path to read
* `timeout` (`int`, optional): Request timeout
**Returns:** `bytes` - File contents as bytes
**Example:**
```python theme={null}
image_data = sandbox.files.read_bytes("/workspace/image.png")
with open("local_image.png", "wb") as f:
f.write(image_data)
```
***
### `write`
Write text file contents.
```python theme={null}
files.write(path, content, mode='0644', *, timeout=None) -> None
```
**Parameters:**
* `path` (`str`): File path to write
* `content` (`str`): Text content to write
* `mode` (`str`, optional): File permissions (default: `'0644'`)
* `timeout` (`int`, optional): Request timeout
**Raises:**
* `FileOperationError`: Write operation failed
**Example:**
```python theme={null}
sandbox.files.write("/workspace/hello.txt", "Hello, World!")
```
**Expected Output:**
```
File written successfully
```
**See Also:**
* [API: Write File](/api/vm-agent/write-file)
***
### `write_bytes`
Write binary file contents.
```python theme={null}
files.write_bytes(path, content, mode='0644', *, timeout=None) -> None
```
**Parameters:**
* `path` (`str`): File path to write
* `content` (`bytes`): Binary content to write
* `mode` (`str`, optional): File permissions
* `timeout` (`int`, optional): Request timeout
**Example:**
```python theme={null}
with open("local_file.bin", "rb") as f:
data = f.read()
sandbox.files.write_bytes("/workspace/remote_file.bin", data)
```
***
### `list`
List directory contents.
```python theme={null}
files.list(path='/workspace', *, timeout=None) -> List[FileInfo]
```
**Parameters:**
* `path` (`str`, optional): Directory path (default: `'/workspace'`)
* `timeout` (`int`, optional): Request timeout
**Returns:** `List[FileInfo]` - List of file/directory information objects
**Example:**
```python theme={null}
items = sandbox.files.list("/workspace")
for item in items:
if item.is_directory:
print(f"Directory: {item.name}")
else:
print(f"File: {item.name} ({item.size} bytes)")
```
**Expected Output:**
```
File: hello.txt (13 bytes)
Directory: my_project
File: script.py (42 bytes)
```
**See Also:**
* [API: List Files](/api/vm-agent/list-files)
***
### `exists`
Check if file or directory exists.
```python theme={null}
files.exists(path, *, timeout=None) -> bool
```
**Parameters:**
* `path` (`str`): File or directory path
* `timeout` (`int`, optional): Request timeout
**Returns:** `bool` - `True` if exists, `False` otherwise
**Example:**
```python theme={null}
if sandbox.files.exists("/workspace/config.json"):
content = sandbox.files.read("/workspace/config.json")
```
**Expected Output:**
```
File exists, content read successfully
```
**See Also:**
* [API: File Exists](/api/vm-agent/file-exists)
***
### `remove`
Delete file or directory.
```python theme={null}
files.remove(path, *, timeout=None) -> None
```
**Parameters:**
* `path` (`str`): File or directory path to delete
* `timeout` (`int`, optional): Request timeout
**Raises:**
* `FileNotFoundError`: Path does not exist
* `FileOperationError`: Delete operation failed
This operation is irreversible. Directories are deleted recursively.
**Example:**
```python theme={null}
sandbox.files.remove("/workspace/temp_file.txt")
```
**Expected Output:**
```
File removed successfully
```
**See Also:**
* [API: Remove File](/api/vm-agent/remove-file)
***
### `mkdir`
Create directory.
```python theme={null}
files.mkdir(path, *, timeout=None) -> None
```
**Parameters:**
* `path` (`str`): Directory path to create
* `timeout` (`int`, optional): Request timeout
**Raises:**
* `FileOperationError`: Directory creation failed
**Example:**
```python theme={null}
sandbox.files.mkdir("/workspace/my_project")
sandbox.files.write("/workspace/my_project/main.py", "print('Hello')")
```
**Expected Output:**
```
Directory created successfully
File written successfully
```
***
### `upload`
Upload file from local filesystem to sandbox.
```python theme={null}
files.upload(local_path, remote_path, *, timeout=None) -> None
```
**Parameters:**
* `local_path` (`str`): Local file path
* `remote_path` (`str`): Remote file path in sandbox
* `timeout` (`int`, optional): Request timeout
**Example:**
```python theme={null}
sandbox.files.upload("./local_script.py", "/workspace/script.py")
```
**Expected Output:**
```
File uploaded successfully
```
***
### `download`
Download file from sandbox to local filesystem.
```python theme={null}
files.download(remote_path, local_path, *, timeout=None) -> None
```
**Parameters:**
* `remote_path` (`str`): Remote file path in sandbox
* `local_path` (`str`): Local file path
* `timeout` (`int`, optional): Request timeout
**Example:**
```python theme={null}
sandbox.files.download("/workspace/output.txt", "./local_output.txt")
```
**Expected Output:**
```
File downloaded successfully
```
***
## Examples
### Example 1: Basic File Operations
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Write a file
sandbox.files.write("/workspace/hello.py", "print('Hello, World!')")
# Read it back
content = sandbox.files.read("/workspace/hello.py")
print(content)
# Execute it
result = sandbox.run_code("exec(open('/workspace/hello.py').read())")
print(result.stdout)
sandbox.kill()
```
**Expected Output:**
```
print('Hello, World!')
Hello, World!
```
### Example 2: Working with Directories
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Create directory structure
sandbox.files.mkdir("/workspace/my_project")
sandbox.files.mkdir("/workspace/my_project/src")
# Write files
sandbox.files.write("/workspace/my_project/src/main.py", "print('Main')")
sandbox.files.write("/workspace/my_project/README.md", "# My Project")
# List directory
items = sandbox.files.list("/workspace/my_project")
for item in items:
print(f"{item.name}: {'dir' if item.is_directory else 'file'}")
sandbox.kill()
```
**Expected Output:**
```
src: dir
README.md: file
```
### Example 3: File Upload/Download
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Upload local file
sandbox.files.upload("./local_script.py", "/workspace/remote_script.py")
# Process it in sandbox
result = sandbox.run_code("exec(open('/workspace/remote_script.py').read())")
# Download result
sandbox.files.write("/workspace/output.txt", result.stdout)
sandbox.files.download("/workspace/output.txt", "./local_output.txt")
sandbox.kill()
```
### Example 4: Binary File Operations
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Read binary file
image_data = sandbox.files.read_bytes("/workspace/image.png")
# Process it (example: get size)
size = len(image_data)
print(f"Image size: {size} bytes")
# Write binary data
sandbox.files.write_bytes("/workspace/copy.png", image_data)
sandbox.kill()
```
***
## FileInfo Model
The `list()` method returns `FileInfo` objects with the following properties:
* `name` (`str`): File or directory name
* `path` (`str`): Full path
* `size` (`int`): Size in bytes
* `is_directory` (`bool`): Whether it's a directory
* `permissions` (`str`): File permissions
* `modified_time` (`datetime`): Last modification time
* `is_file` (`bool`): Convenience property (opposite of `is_directory`)
* `size_kb` (`float`): Size in kilobytes
* `size_mb` (`float`): Size in megabytes
***
## Related Classes
* **[Sandbox](/sdk/python/sandbox)** - Main sandbox class
* **[Commands](/sdk/python/commands)** - Command execution resource
* **[Models](/sdk/python/models)** - Data models including `FileInfo`
## See Also
* [Core Concepts: Files](/core-concepts/files) - Learn about file operations
* [Sandbox Class](/sdk/python/sandbox) - Access files via `sandbox.files`
## Related
* **[Reading Files](/core-concepts/filesystem/reading)** - Learn about reading files
* **[Writing Files](/core-concepts/filesystem/writing)** - Learn about writing files
* **[Listing Files](/core-concepts/filesystem/listing)** - List directory contents
* **[API: File Operations](/api/vm-agent/read-file)** - VM Agent API endpoints
## Next Steps
* Learn about [Reading Files](/core-concepts/filesystem/reading) to access file contents
* Explore [Writing Files](/core-concepts/filesystem/writing) to create files
* Review [Uploading Files](/core-concepts/filesystem/uploading) for local file transfers
* **[CLI File Operations](/cli/commands/files)** - Use file operations from the command line
# Installation
Source: https://docs.hopx.ai/sdk/python/installation
Install the HopX Python SDK and set up your development environment. Get started with the official Python SDK for HopX, install via pip, configure API keys, and verify installation. Learn system requirements, installation methods, and troubleshooting tips. Includes installation examples for different Python versions and environments.
**SDK Version:** 0.3.0\
**Last Verified:** 2025-01-27
## Prerequisites
Before installing the HopX Python SDK, ensure you have:
* **Python 3.8+** (CPython recommended)
* **pip** (Python package installer)
* **HopX API key** - Get yours at [console.hopx.dev](https://console.hopx.dev)
## Install from PyPI
The recommended way to install the HopX Python SDK:
```bash theme={null}
pip install hopx-ai
```
## Install Specific Version
Install a specific version:
```bash theme={null}
pip install hopx-ai==0.3.0
```
## Install from Source
For development or to use the latest unreleased version:
```bash theme={null}
git clone https://github.com/hopx-ai/hopx.git
cd HopX/python
pip install -e .
```
## Verify Installation
Verify the installation:
```bash theme={null}
python -c "import hopx_ai; print(hopx_ai.__version__)"
```
Expected output: `0.3.0`
## Set Up Authentication
The SDK requires an API key for authentication. You have three options:
### Option 1: Environment Variable (Recommended)
Set the `HOPX_API_KEY` environment variable:
```bash theme={null}
# Linux/macOS
export HOPX_API_KEY="your-API key-here"
# Windows (PowerShell)
$env:HOPX_API_KEY="your-API key-here"
# Windows (CMD)
set HOPX_API_KEY=your-API key-here
```
### Option 2: Pass API key Directly
Pass the API key when creating a sandbox:
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(
template="code-interpreter",
api_key="your-API key-here"
)
```
### Option 3: Configuration File
Create a `.env` file in your project root:
```bash theme={null}
# .env
HOPX_API_KEY=your-API key-here
```
Then load it in your Python code:
```python theme={null}
from dotenv import load_dotenv
import os
from hopx_ai import Sandbox
load_dotenv()
sandbox = Sandbox.create(template="code-interpreter")
```
Never commit your API key to version control. Always use environment variables or secure secret management for production applications.
## Get Your API key
1. Sign up at [console.hopx.dev](https://console.hopx.dev)
2. Navigate to **Settings** → **API Keys**
3. Create a new API key
4. Copy the key (you'll only see it once)
API keys are scoped to your account and have full access to create, manage, and delete sandboxes. Keep them secure.
## Supported Python Versions
The SDK is tested and supported on:
* **Python 3.8** - Minimum supported version
* **Python 3.9** - Recommended for best compatibility
* **Python 3.10** - Recommended for new projects
* **Python 3.11** - Recommended for new projects
* **Python 3.12** - Latest, fully supported
## Package Managers
### pip
```bash theme={null}
pip install hopx-ai
```
### poetry
```bash theme={null}
poetry add hopx-ai
```
### pipenv
```bash theme={null}
pipenv install hopx-ai
```
### conda
```bash theme={null}
conda install -c conda-forge hopx-ai
```
## Dependencies
The SDK has minimal dependencies:
* `requests` - HTTP client for API calls
* `websocket-client` - WebSocket support for streaming
* `typing-extensions` - Type hints for Python \< 3.10
All dependencies are automatically installed with `pip install hopx-ai`.
## Troubleshooting
### Import Errors
If you get `ModuleNotFoundError: No module named 'hopx_ai'`:
1. Verify Python version: `python --version` (should be 3.8+)
2. Check installation: `pip list | grep hopx-ai`
3. Reinstall: `pip install --upgrade hopx-ai`
### Authentication Errors
If you get authentication errors:
1. Verify API key is set: `echo $HOPX_API_KEY` (Linux/macOS) or `echo %HOPX_API_KEY%` (Windows)
2. Check API key is valid at [console.hopx.dev](https://console.hopx.dev)
3. Ensure no extra spaces or quotes in the API key
### Network Errors
If you encounter network errors:
1. Check internet connection
2. Verify firewall allows outbound HTTPS (port 443)
3. Check if you're behind a corporate proxy (may need proxy configuration)
For more troubleshooting help, see the [Troubleshooting Guide](/sdk/python/troubleshooting).
## Related
* **[Python SDK Quickstart](/sdk/python/quickstart)** - Get started with the SDK
* **\[API key Management]\(/API key)** - Learn about API key security
* **[Sandbox Class Reference](/sdk/python/sandbox)** - Complete SDK reference
## Next Steps
Once you've successfully installed the SDK:
* **[Quickstart Guide](/sdk/python/quickstart)** - Create your first sandbox and run code
* **[CLI Installation](/cli/installation)** - Install the HopX CLI as an alternative
* **[API Reference](/sdk/python/sandbox)** - Explore the full SDK API
# Overview
Source: https://docs.hopx.ai/sdk/python/introduction
Official Python SDK for HopX - Create and manage cloud sandboxes in Python. Install the SDK, authenticate with your API key, and start creating sandboxes, executing code, managing files, and automating desktop interactions. Complete reference with code examples for all SDK methods and classes.
**Version:** 0.3.0\
**Last Verified:** 2025-01-27\
**Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/)
## What is the Python SDK?
The HopX Python SDK provides a simple, powerful interface for creating and managing cloud sandboxes directly from your Python applications. Build AI agents, run untrusted code securely, execute tests in isolation, or process data with rich output capture—all with a clean, Pythonic API.
The SDK is a thin wrapper around the HopX REST API that handles authentication, request formatting, error translation, and response parsing automatically, giving you a better developer experience than working with the raw API.
## Target Audience
This SDK is designed for:
* **Backend Python developers** using Python 3.8+ (CPython recommended)
* **Data scientists** working with Jupyter notebooks, pandas, matplotlib
* **AI/ML engineers** building agents that need secure code execution
* **DevOps engineers** creating isolated testing environments
* **Automation engineers** building workflows that require sandboxed execution
## Supported Runtimes
* **Python:** 3.8, 3.9, 3.10, 3.11, 3.12 (CPython)
* **Operating Systems:** Linux, macOS, Windows
* **Package Managers:** pip, poetry, pipenv, conda
## When to Use the SDK vs CLI vs Raw API
### Use the Python SDK when:
* ✅ You're building Python applications
* ✅ You want type hints and IDE autocomplete
* ✅ You prefer Pythonic error handling and exceptions
* ✅ You need async/await support (`AsyncSandbox`)
* ✅ You want automatic resource management (context managers)
* ✅ You're working with Python data structures (dicts, lists, models)
### Use the CLI when:
* ✅ You prefer command-line workflows
* ✅ You're scripting or automating from shell
* ✅ You want quick one-off operations
* ✅ You're working in CI/CD pipelines
* ✅ You need interactive terminal sessions
### Use the Raw API when:
* ⚠️ You're building in a non-Python language
* ⚠️ You need fine-grained control over HTTP requests
* ⚠️ You're integrating with existing HTTP client libraries
* ⚠️ You need custom retry logic or connection pooling
The SDK is a thin wrapper around the HopX REST API. It handles authentication, request formatting, error translation, and response parsing automatically. For most Python use cases, the SDK provides a better developer experience.
## Architecture
The SDK consists of two main classes:
* **`Sandbox`** - Synchronous sandbox client (blocking operations)
* **`AsyncSandbox`** - Asynchronous sandbox client (async/await)
Both classes provide the same functionality, with `AsyncSandbox` optimized for concurrent operations and async frameworks.
## Core Capabilities
The Python SDK provides:
* **Sandbox Management** - Create, connect, list, and delete sandboxes
* **Code Execution** - Run Python, JavaScript, Bash, Go, and more
* **Rich Outputs** - Capture matplotlib plots, pandas DataFrames, images
* **File Operations** - Read, write, list, upload, download files
* **Command Execution** - Run shell commands synchronously or in background
* **Environment Variables** - Set, get, update, and clear environment variables
* **Process Management** - List and manage running processes
* **Cache Management** - Monitor and clear execution result cache
* **Desktop Automation** - VNC access, mouse/keyboard control (Premium)
* **Template Building** - Create custom sandbox environments
* **WebSocket Streaming** - Real-time terminal and code execution streaming
## Quick Example
```python theme={null}
from hopx_ai import Sandbox
# Create a sandbox (~100ms)
sandbox = Sandbox.create(template="code-interpreter")
# Execute code
result = sandbox.run_code('print("Hello from HopX!")')
print(result.stdout) # "Hello from HopX!\n"
# Cleanup
sandbox.kill()
```
## Next Steps
* **[Installation Guide](/sdk/python/installation)** - Install the SDK and set up your environment
* **[Quickstart](/sdk/python/quickstart)** - Get your first sandbox running in minutes
* **[API Reference](/sdk/python/sandbox)** - Complete class and method documentation
## Related
* [JavaScript SDK](/sdk/javascript/introduction) - Official JavaScript/TypeScript SDK
* [CLI Reference](/cli/introduction) - Command-line interface for HopX
* [API Reference](/api/introduction) - Raw REST API documentation
* [Core Concepts](/core-concepts/sandboxes/creating) - Learn about sandboxes, execution, and more
# Sandbox Data Models
Source: https://docs.hopx.ai/sdk/python/models
Data models and type definitions for the HopX Python SDK. Understand sandbox objects, execution results, file metadata, template structures, and other data models used throughout the SDK. Essential for working with SDK responses and building type-safe applications. Includes complete model reference and field descriptions.
**Version:** 0.3.0\
**Last Verified:** 2025-01-27\
**Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/)
## Overview
The Python SDK provides data models for all API responses and objects. These models provide type safety, convenience methods, and clear documentation of data structures.
## Import
```python theme={null}
from hopx_ai import (
SandboxInfo,
Template as SandboxTemplate,
ExecutionResult,
CommandResult,
FileInfo,
RichOutput,
VNCInfo,
WindowInfo,
RecordingInfo,
DisplayInfo
)
```
## Core Models
### `SandboxInfo`
Sandbox information model.
**Fields:**
* `sandbox_id` (`str`): Unique sandbox identifier
* `template_id` (`str`): Template ID used to create sandbox
* `template_name` (`str`): Template name
* `organization_id` (`str`): Organization ID
* `node_id` (`str`): Node ID
* `region` (`str`): Deployment region
* `status` (`str`): Sandbox status (`"running"`, `"stopped"`, `"paused"`, `"creating"`)
* `public_host` (`str`): Public hostname
* `resources` (`Resources`): Resource specifications
* `started_at` (`datetime`): Start timestamp
* `end_at` (`datetime`, optional): End timestamp
* `created_at` (`datetime`): Creation timestamp
**Example:**
```python theme={null}
info = sandbox.get_info()
print(f"ID: {info.sandbox_id}")
print(f"Status: {info.status}")
print(f"Host: {info.public_host}")
```
***
### `Template`
Template information model.
**Fields:**
* `id` (`str`): Template ID
* `name` (`str`): Template name
* `display_name` (`str`): Display name
* `description` (`str`): Template description
* `category` (`str`): Template category
* `language` (`str`): Primary language
* `icon` (`str`, optional): Icon URL
* `default_resources` (`TemplateResources`): Default resource specifications
* `min_resources` (`TemplateResources`): Minimum resources
* `max_resources` (`TemplateResources`): Maximum resources
* `features` (`List[str]`): Available features
* `tags` (`List[str]`): Template tags
* `popularity_score` (`float`): Popularity score
* `docs_url` (`str`, optional): Documentation URL
* `is_active` (`bool`): Whether template is active
* `status` (`str`): Template status
**Example:**
```python theme={null}
template = Sandbox.get_template("code-interpreter")
print(f"Name: {template.name}")
print(f"Resources: {template.default_resources.vcpu} vCPU")
```
***
### `ExecutionResult`
Result of code execution.
**Fields:**
* `success` (`bool`): Whether execution succeeded
* `stdout` (`str`): Standard output
* `stderr` (`str`): Standard error
* `exit_code` (`int`): Exit code (0 = success)
* `execution_time` (`float`): Execution time in seconds
* `rich_outputs` (`List[RichOutput]`): Rich outputs (plots, DataFrames, etc.)
**Properties:**
* `rich_count` (`int`): Number of rich outputs
**Example:**
```python theme={null}
result = sandbox.run_code("print('Hello')")
print(result.stdout)
print(f"Success: {result.success}")
print(f"Rich outputs: {result.rich_count}")
```
***
### `CommandResult`
Result of command execution.
**Fields:**
* `stdout` (`str`): Standard output
* `stderr` (`str`): Standard error
* `exit_code` (`int`): Exit code
* `execution_time` (`float`): Execution time in seconds
**Properties:**
* `success` (`bool`): Whether command succeeded (`exit_code == 0`)
**Example:**
```python theme={null}
result = sandbox.commands.run("ls -la")
print(result.stdout)
print(f"Success: {result.success}")
```
***
### `FileInfo`
File or directory information.
**Fields:**
* `name` (`str`): File or directory name
* `path` (`str`): Full path
* `size` (`int`): Size in bytes
* `is_directory` (`bool`): Whether it's a directory
* `permissions` (`str`): File permissions
* `modified_time` (`datetime`): Last modification time
**Properties:**
* `is_file` (`bool`): Whether it's a file
* `is_dir` (`bool`): Whether it's a directory
* `size_kb` (`float`): Size in kilobytes
* `size_mb` (`float`): Size in megabytes
**Example:**
```python theme={null}
items = sandbox.files.list("/workspace")
for item in items:
if item.is_directory:
print(f"Directory: {item.name}")
else:
print(f"File: {item.name} ({item.size_kb:.2f} KB)")
```
***
### `RichOutput`
Rich output from code execution (plots, DataFrames, etc.).
**Fields:**
* `type` (`str`): Output type (`"plot"`, `"dataframe"`, `"html"`, etc.)
* `data` (`str` or `bytes`): Output data
* `metadata` (`Dict[str, Any]`): Additional metadata
* `timestamp` (`datetime`): Output timestamp
**Example:**
```python theme={null}
result = sandbox.run_code("import matplotlib.pyplot as plt; plt.plot([1,2,3]); plt.savefig('/tmp/plot.png')")
for output in result.rich_outputs:
if output.type == "plot":
print(f"Plot generated at {output.timestamp}")
```
***
## Desktop Models
### `VNCInfo`
VNC server information.
**Fields:**
* `running` (`bool`): Whether VNC is running
* `display` (`int`): Display number
* `port` (`int`): VNC port
* `url` (`str`): VNC URL
* `password` (`str`): VNC password
***
### `WindowInfo`
Window information.
**Fields:**
* `id` (`str`): Window ID
* `title` (`str`): Window title
* `x` (`int`): X coordinate
* `y` (`int`): Y coordinate
* `width` (`int`): Window width
* `height` (`int`): Window height
* `desktop` (`int`): Desktop number
* `pid` (`int`): Process ID
***
### `RecordingInfo`
Screen recording information.
**Fields:**
* `recording_id` (`str`): Recording ID
* `status` (`str`): Recording status
* `fps` (`int`): Frames per second
* `format` (`str`): Video format
* `duration` (`float`): Duration in seconds
* `file_size` (`int`): File size in bytes
**Properties:**
* `is_recording` (`bool`): Whether recording is active
* `is_ready` (`bool`): Whether recording is ready
***
### `DisplayInfo`
Display information.
**Fields:**
* `width` (`int`): Display width
* `height` (`int`): Display height
* `depth` (`int`): Color depth
**Properties:**
* `resolution` (`Tuple[int, int]`): Resolution tuple
***
## Resource Models
### `Resources`
Resource specifications.
**Fields:**
* `vcpu` (`int`): Number of vCPUs
* `memory_mb` (`int`): Memory in megabytes
* `disk_mb` (`int`): Disk space in megabytes
***
### `TemplateResources`
Template resource specifications.
**Fields:**
* `vcpu` (`int`): Number of vCPUs
* `memory_mb` (`int`): Memory in megabytes
* `disk_gb` (`int`): Disk space in gigabytes
***
## Related Classes
* **[Errors](/sdk/python/errors)** - Error classes and exception handling
* **[Sandbox](/sdk/python/sandbox)** - Use models with sandbox operations
## See Also
* [Errors](/sdk/python/errors) - Learn about error handling
* [Core Concepts](/core-concepts) - Learn about core concepts
## Next Steps
Now that you understand data models, explore:
* [Sandbox Operations](/sdk/python/sandbox) - Use models in practice
* [Error Handling](/sdk/python/errors) - Type-safe error handling
* [Quickstart Guide](/sdk/python/quickstart) - Get started with the SDK
* **[CLI Reference](/cli/introduction)** - Use HopX from the command line
* [Python Type Hints](https://docs.python.org/3/library/typing.html) - Learn more about type hints
# Quickstart
Source: https://docs.hopx.ai/sdk/python/quickstart
Get your first sandbox running in minutes with the HopX Python SDK - install, authenticate, execute code, see results. Complete quickstart guide for creating sandboxes, running Python code, managing files, and cleaning up resources. Perfect for developers new to HopX. Includes step-by-step examples and best practices.
**Goal:** Create a sandbox, execute code, and see the output in under 5 minutes.\
**Prerequisites:** Python 3.8+, pip, HopX API key\
**Time:** \~5 minutes
This quickstart gets you from zero to your first successful code execution. Follow these steps in order.
## What You'll Learn
In this quickstart, you'll learn how to:
* Install and verify the Python SDK
* Set up API key authentication
* Create a sandbox from a template
* Execute Python code in the sandbox
* Access execution results and output
* Clean up sandboxes properly
## Step 1: Install the SDK
```bash theme={null}
pip install hopx-ai
```
## Step 1.5: Verify Installation
Verify the SDK is installed correctly:
```bash theme={null}
python -c "import hopx_ai; print(f'HopX SDK {hopx_ai.__version__} installed successfully')"
```
Expected output: `HopX SDK 0.3.0 installed successfully`
## Step 2: Set Your API key
Set the `HOPX_API_KEY` environment variable:
```bash theme={null}
# Linux/macOS
export HOPX_API_KEY="your-api-key-here"
# Windows (PowerShell)
$env:HOPX_API_KEY="your-api-key-here"
```
Get your API key from [console.hopx.dev](https://console.hopx.dev) → Settings → API Keys
## Step 3: Create and Run Your First Sandbox
Create a file `hello_hopx.py`:
```python theme={null}
from hopx_ai import Sandbox
# Create a sandbox (~100ms)
sandbox = Sandbox.create(template="code-interpreter")
# Execute code in the sandbox
result = sandbox.run_code('print("Hello from HopX!")')
# Print the output
print(result.stdout)
```
**Expected Output:**
```
Hello from HopX!
```
# Cleanup - delete the sandbox
sandbox.kill()
````
## Step 4: Run It
```bash
python hello_hopx.py
````
## Expected Output
```
Hello from HopX!
```
🎉 **Success!** You've created your first sandbox and executed code. The sandbox was automatically cleaned up after execution.
## What Just Happened?
1. **`Sandbox.create()`** - Created a new sandbox from the `code-interpreter` template (Python environment)
2. **`sandbox.run_code()`** - Executed Python code in the sandbox
3. **`result.stdout`** - Retrieved the standard output from code execution
4. **`sandbox.kill()`** - Deleted the sandbox to free resources
## Related
* **[API Quickstart](/api/quickstart)** - Get started with the API
* **[Sandbox Class Reference](/sdk/python/sandbox)** - Complete SDK reference
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn more about sandbox creation
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Understand code execution
## Next Steps
Now that you have a working setup, explore more:
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Learn about different templates and options
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Run Python, JavaScript, Bash, and more
* **[File Operations](/core-concepts/filesystem/reading)** - Read, write, and manage files in sandboxes
* **[CLI Quickstart](/cli/quickstart)** - Use HopX from the command line
* **[API Reference](/sdk/python/sandbox)** - Complete SDK documentation
## Quickstart Variations
For more advanced quickstart examples including async/await, error handling, and context managers, see the [Advanced Quickstart Guide](/sdk/python/advanced-quickstart) (coming soon).
## Troubleshooting
**"API key required" error?**
* Verify `HOPX_API_KEY` is set: `echo $HOPX_API_KEY`
* Get your key at [console.hopx.dev](https://console.hopx.dev)
**"Template not found" error?**
* Use `template="code-interpreter"` (default Python template)
* See [Available Templates](/core-concepts/templates/listing) for options
**Network timeout?**
* Check internet connection
* Verify firewall allows HTTPS (port 443)
For more help, see the [Troubleshooting Guide](/sdk/python/troubleshooting).
# Template Ready Checks
Source: https://docs.hopx.ai/sdk/python/ready-checks
Utilities for checking template readiness before use in the HopX Python SDK. Verify templates are available and ready before creating sandboxes, check template status, and handle template availability errors. Essential for robust sandbox creation workflows. Includes code examples and error handling.
**Version:** 0.3.0\
**Last Verified:** 2025-01-27\
**Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/)
## Overview
Ready checks are utilities used in template building to verify that a template is ready before it's considered complete. Use ready checks to ensure services are running, files exist, or commands succeed before the template is marked as ready.
## Import
```python theme={null}
from hopx_ai.template import (
wait_for_port,
wait_for_url,
wait_for_file,
wait_for_process,
wait_for_command
)
```
## Available Ready Checks
### `wait_for_port`
Wait for a port to be listening.
```python theme={null}
wait_for_port(port, timeout=60) -> ReadyCheck
```
**Parameters:**
* `port` (`int`): Port number to check
* `timeout` (`int`, optional): Timeout in seconds (default: `60`)
**Example:**
```python theme={null}
from hopx_ai.template import Template, wait_for_port
template = (
Template()
.from_node_image("20")
.expose(3000)
.start_cmd("node server.js")
.ready_check(wait_for_port(3000))
)
```
***
### `wait_for_url`
Wait for a URL to be accessible.
```python theme={null}
wait_for_url(url, timeout=60) -> ReadyCheck
```
**Parameters:**
* `url` (`str`): URL to check
* `timeout` (`int`, optional): Timeout in seconds
**Example:**
```python theme={null}
from hopx_ai.template import Template, wait_for_url
template = (
Template()
.from_python_image("3.11")
.start_cmd("python app.py")
.ready_check(wait_for_url("http://localhost:5000/health"))
)
```
***
### `wait_for_file`
Wait for a file to exist.
```python theme={null}
wait_for_file(path, timeout=60) -> ReadyCheck
```
**Parameters:**
* `path` (`str`): File path to check
* `timeout` (`int`, optional): Timeout in seconds
**Example:**
```python theme={null}
from hopx_ai.template import Template, wait_for_file
template = (
Template()
.from_python_image("3.11")
.run("python setup.py")
.ready_check(wait_for_file("/app/ready.flag"))
)
```
***
### `wait_for_process`
Wait for a process to be running.
```python theme={null}
wait_for_process(process_name, timeout=60) -> ReadyCheck
```
**Parameters:**
* `process_name` (`str`): Process name to check
* `timeout` (`int`, optional): Timeout in seconds
**Example:**
```python theme={null}
from hopx_ai.template import Template, wait_for_process
template = (
Template()
.from_python_image("3.11")
.start_cmd("python worker.py")
.ready_check(wait_for_process("worker.py"))
)
```
***
### `wait_for_command`
Wait for a command to succeed.
```python theme={null}
wait_for_command(command, timeout=60) -> ReadyCheck
```
**Parameters:**
* `command` (`str`): Command to execute
* `timeout` (`int`, optional): Timeout in seconds
**Example:**
```python theme={null}
from hopx_ai.template import Template, wait_for_command
template = (
Template()
.from_python_image("3.11")
.run("pip install -r requirements.txt")
.ready_check(wait_for_command("python -c 'import requests'"))
)
```
***
## Examples
### Example 1: Port Ready Check
```python theme={null}
from hopx_ai.template import Template, wait_for_port
import asyncio
async def main():
template = (
Template()
.from_node_image("20")
.run("npm install express")
.copy("./server.js", "/app/server.js")
.expose(3000)
.start_cmd("node /app/server.js")
.ready_check(wait_for_port(3000, timeout=120))
)
result = await template.build()
print(f"Template ready: {result.template_id}")
asyncio.run(main())
```
### Example 2: URL Ready Check
```python theme={null}
from hopx_ai.template import Template, wait_for_url
import asyncio
async def main():
template = (
Template()
.from_python_image("3.11")
.run("pip install flask")
.copy("./app.py", "/app/app.py")
.expose(5000)
.start_cmd("python /app/app.py")
.ready_check(wait_for_url("http://localhost:5000/health", timeout=90))
)
result = await template.build()
print(f"Template ready: {result.template_id}")
asyncio.run(main())
```
***
## Related Classes
* **[Template Builder](/sdk/python/template-builder)** - Use ready checks in templates
* **[Sandbox](/sdk/python/sandbox)** - Create sandboxes from templates
## See Also
* [Template Builder](/sdk/python/template-builder) - Learn about building templates
* [Core Concepts: Templates](/core-concepts/templates) - Learn about templates
## Next Steps
Now that you understand ready checks, explore:
* [Template Builder](/sdk/python/template-builder) - Use ready checks in template building
* [Building Templates](/core-concepts/templates/building) - Learn template building concepts
* [Template Configuration](/core-concepts/templates/configuration) - Configure templates
* **[CLI Reference](/cli/introduction)** - Use HopX from the command line
* [Custom Templates](/cookbooks/advanced/custom-templates) - Build custom templates
# Sandbox
Source: https://docs.hopx.ai/sdk/python/sandbox
Main synchronous sandbox class for creating and managing cloud sandboxes in Python. Complete reference for the HopX Python SDK Sandbox class including methods for creating sandboxes, executing code, managing files, controlling desktop automation, and monitoring resources. Includes code examples for all methods.
**Version:** 0.3.0\
**Last Verified:** 2025-01-27\
**Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/)
## Overview
The `Sandbox` class is the main entry point for the HopX Python SDK. It provides a synchronous interface for creating, managing, and interacting with cloud sandboxes (microVMs). Use this class when you're building synchronous Python applications or scripts.
The `Sandbox` class handles authentication, request formatting, error translation, and response parsing automatically, giving you a clean, Pythonic API for sandbox management.
### When to Use Sandbox vs AsyncSandbox
* **Use `Sandbox`** when:
* Building synchronous Python applications
* Writing scripts or simple automation
* You prefer blocking operations
* You don't need async/await patterns
* **Use `AsyncSandbox`** when:
* Building async Python applications (FastAPI, aiohttp, etc.)
* You need to manage multiple sandboxes concurrently
* You want non-blocking operations
* You're already using async/await in your codebase
## Import
```python theme={null}
from hopx_ai import Sandbox
```
## Class Methods
### `create`
Create a new sandbox from a template.
```python theme={null}
Sandbox.create(
template=None,
*,
template_id=None,
region=None,
timeout_seconds=None,
internet_access=None,
env_vars=None,
api_key=None,
base_url='https://api.hopx.dev'
) -> Sandbox
```
**Parameters:**
* `template` (`str`, optional): Template name (e.g., `"code-interpreter"`)
* `template_id` (`str`, optional): Template ID (alternative to template name)
* `region` (`str`, optional): Preferred region (auto-selected if not specified)
* `timeout_seconds` (`int`, optional): Auto-kill timeout in seconds (default: no timeout)
* `internet_access` (`bool`, optional): Enable internet access (default: `True`)
* `env_vars` (`Dict[str, str]`, optional): Environment variables to set in the sandbox
* `api_key` (`str`, optional): API key (or use `HOPX_API_KEY` env var)
* `base_url` (`str`, optional): API base URL (default: production)
**Returns:** `Sandbox` - New sandbox instance
**Raises:**
* `ValidationError`: Invalid parameters
* `ResourceLimitError`: Insufficient resources
* `APIError`: API request failed
**Example:**
```python theme={null}
# Create from template name
sandbox = Sandbox.create(template="code-interpreter")
print(sandbox.get_info().public_host)
# Create with timeout and environment variables
sandbox = Sandbox.create(
template="code-interpreter",
timeout_seconds=300,
env_vars={"DEBUG": "true", "API_KEY": "secret"}
)
```
**Expected Output:**
```
https://sandbox_abc123xyz.hopx.dev
```
**See Also:**
* [API: Create Sandbox](/api/control-plane/create-sandbox)
***
### `connect`
Connect to an existing sandbox by ID.
```python theme={null}
Sandbox.connect(
sandbox_id,
*,
api_key=None,
base_url='https://api.hopx.dev'
) -> Sandbox
```
**Parameters:**
* `sandbox_id` (`str`): Existing sandbox ID
* `api_key` (`str`, optional): API key (or use `HOPX_API_KEY` env var)
* `base_url` (`str`, optional): API base URL
**Returns:** `Sandbox` - Connected sandbox instance
**Raises:**
* `NotFoundError`: Sandbox not found
* `APIError`: API request failed
**Example:**
```python theme={null}
sandbox = Sandbox.connect("sandbox-abc123")
info = sandbox.get_info()
print(f"Status: {info.status}")
```
**Expected Output:**
```
Status: running
```
**See Also:**
* [API: Get Sandbox](/api/control-plane/get-sandbox)
***
### `list`
List all sandboxes (loads all into memory).
```python theme={null}
Sandbox.list(
*,
status=None,
region=None,
limit=100,
api_key=None,
base_url='https://api.hopx.dev'
) -> List[Sandbox]
```
**Parameters:**
* `status` (`str`, optional): Filter by status (`"running"`, `"stopped"`, `"paused"`, `"creating"`)
* `region` (`str`, optional): Filter by region
* `limit` (`int`, optional): Maximum number of sandboxes to return (default: `100`)
* `api_key` (`str`, optional): API key
* `base_url` (`str`, optional): API base URL
**Returns:** `List[Sandbox]` - List of sandbox instances
**Example:**
```python theme={null}
# List all running sandboxes
running = Sandbox.list(status="running")
for sb in running:
print(f"{sb.sandbox_id}: {sb.get_info().status}")
# List sandboxes in specific region
sandboxes = Sandbox.list(region="us-east", limit=50)
```
**Expected Output:**
```
sandbox_abc123xyz: running
sandbox_def456uvw: running
sandbox_ghi789rst: paused
```
**See Also:**
* [API: List Sandboxes](/api/control-plane/list-sandboxes)
***
### `iter`
Lazy iterator for sandboxes (memory-efficient).
```python theme={null}
Sandbox.iter(
*,
status=None,
region=None,
api_key=None,
base_url='https://api.hopx.dev'
) -> Iterator[Sandbox]
```
**Parameters:**
* `status` (`str`, optional): Filter by status
* `region` (`str`, optional): Filter by region
* `api_key` (`str`, optional): API key
* `base_url` (`str`, optional): API base URL
**Returns:** `Iterator[Sandbox]` - Iterator of sandbox instances
**Example:**
```python theme={null}
# Iterate over all sandboxes (memory-efficient)
for sandbox in Sandbox.iter(status="running"):
info = sandbox.get_info()
print(f"{info.sandbox_id}: {info.status}")
```
**Expected Output:**
```
sandbox_abc123xyz: running
sandbox_def456uvw: running
```
**See Also:**
* [API: List Sandboxes](/api/control-plane/list-sandboxes)
***
### `list_templates`
List available templates.
```python theme={null}
Sandbox.list_templates(
*,
category=None,
language=None,
api_key=None,
base_url='https://api.hopx.dev'
) -> List[Template]
```
**Parameters:**
* `category` (`str`, optional): Filter by category
* `language` (`str`, optional): Filter by language
* `api_key` (`str`, optional): API key
* `base_url` (`str`, optional): API base URL
**Returns:** `List[Template]` - List of template objects
**Example:**
```python theme={null}
# List all Python templates
python_templates = Sandbox.list_templates(language="python")
for template in python_templates:
print(f"{template.name}: {template.description}")
```
**Expected Output:**
```
code-interpreter: Python environment with data science libraries
python-basic: Minimal Python 3.11 environment
```
**See Also:**
* [API: List Templates](/api/control-plane/list-templates)
***
### `get_template`
Get template details by name.
```python theme={null}
Sandbox.get_template(
name,
*,
api_key=None,
base_url='https://api.hopx.dev'
) -> Template
```
**Parameters:**
* `name` (`str`): Template name
* `api_key` (`str`, optional): API key
* `base_url` (`str`, optional): API base URL
**Returns:** `Template` - Template object with details
**Raises:**
* `NotFoundError`: Template not found
**Example:**
```python theme={null}
template = Sandbox.get_template("code-interpreter")
print(f"Resources: {template.resources.vcpu} vCPU, {template.resources.memory_mb}MB RAM")
```
**Expected Output:**
```
Resources: 2 vCPU, 4096MB RAM
```
**See Also:**
* [API: Get Template](/api/control-plane/get-template)
***
### `health_check`
Check API health status (does not require authentication).
```python theme={null}
Sandbox.health_check(
*,
base_url='https://api.hopx.dev'
) -> Dict[str, Any]
```
**Parameters:**
* `base_url` (`str`, optional): API base URL
**Returns:** `Dict[str, Any]` - Health status information
**Example:**
```python theme={null}
health = Sandbox.health_check()
print(f"API Status: {health.get('status')}")
```
**Expected Output:**
```
API Status: healthy
```
***
## Instance Methods
### Lifecycle Methods
#### `get_info`
Get current sandbox information.
```python theme={null}
sandbox.get_info() -> SandboxInfo
```
**Returns:** `SandboxInfo` - Sandbox information object
**Example:**
```python theme={null}
info = sandbox.get_info()
print(f"ID: {info.sandbox_id}")
print(f"Status: {info.status}")
print(f"Host: {info.public_host}")
```
**Expected Output:**
```
ID: sandbox_abc123xyz
Status: running
Host: https://sandbox_abc123xyz.hopx.dev
```
**See Also:**
* [API: Get Sandbox](/api/control-plane/get-sandbox)
***
#### `start`
Start a stopped sandbox.
```python theme={null}
sandbox.start() -> None
```
**Raises:**
* `APIError`: Failed to start sandbox
**Example:**
```python theme={null}
sandbox.start()
print("Sandbox started")
```
**Expected Output:**
```
Sandbox started
```
**See Also:**
* [API: Start Sandbox](/api/control-plane/start-sandbox)
***
#### `stop`
Stop the sandbox.
```python theme={null}
sandbox.stop() -> None
```
**Example:**
```python theme={null}
sandbox.stop()
print("Sandbox stopped")
```
**Expected Output:**
```
Sandbox stopped
```
**See Also:**
* [API: Stop Sandbox](/api/control-plane/stop-sandbox)
***
#### `pause`
Pause the sandbox.
```python theme={null}
sandbox.pause() -> None
```
**Example:**
```python theme={null}
sandbox.pause()
print("Sandbox paused")
```
**Expected Output:**
```
Sandbox paused
```
**See Also:**
* [API: Pause Sandbox](/api/control-plane/pause-sandbox)
***
#### `resume`
Resume a paused sandbox.
```python theme={null}
sandbox.resume() -> None
```
**Example:**
```python theme={null}
sandbox.resume()
print("Sandbox resumed")
```
**Expected Output:**
```
Sandbox resumed
```
**See Also:**
* [API: Resume Sandbox](/api/control-plane/resume-sandbox)
***
#### `kill`
Destroy the sandbox immediately.
```python theme={null}
sandbox.kill() -> None
```
This action is irreversible. The sandbox and all its data will be permanently deleted.
**Example:**
```python theme={null}
sandbox.kill()
print("Sandbox destroyed")
```
**Expected Output:**
```
Sandbox destroyed
```
**See Also:**
* [API: Delete Sandbox](/api/control-plane/delete-sandbox)
***
### Execution Methods
#### `run_code`
Execute code with rich output capture.
```python theme={null}
sandbox.run_code(
code,
*,
language='python',
timeout=60,
env=None,
working_dir='/workspace'
) -> ExecutionResult
```
**Parameters:**
* `code` (`str`): Code to execute
* `language` (`str`, optional): Language (`"python"`, `"javascript"`, `"bash"`, `"go"`) (default: `"python"`)
* `timeout` (`int`, optional): Execution timeout in seconds (default: `60`)
* `env` (`Dict[str, str]`, optional): Environment variables for execution
* `working_dir` (`str`, optional): Working directory (default: `"/workspace"`)
**Returns:** `ExecutionResult` - Execution result with `stdout`, `stderr`, `exit_code`, and `rich_outputs`
**Example:**
```python theme={null}
result = sandbox.run_code("print('Hello, HopX!')")
print(result.stdout) # "Hello, HopX!\n"
print(result.exit_code) # 0
```
**Expected Output:**
```
Hello, HopX!
0
```
**See Also:**
* [API: Execute Code](/api/vm-agent/execute)
***
#### `run_code_background`
Execute code in background and return immediately.
```python theme={null}
sandbox.run_code_background(
code,
*,
language='python',
timeout=300,
env=None,
working_dir='/workspace',
name=None
) -> Dict[str, Any]
```
**Parameters:**
* `code` (`str`): Code to execute
* `language` (`str`, optional): Language (default: `"python"`)
* `timeout` (`int`, optional): Max execution time in seconds (default: `300`)
* `env` (`Dict[str, str]`, optional): Environment variables
* `working_dir` (`str`, optional): Working directory
* `name` (`str`, optional): Process name for identification
**Returns:** `Dict[str, Any]` - Dict with `process_id`, `execution_id`, and `status`
**Example:**
```python theme={null}
proc = sandbox.run_code_background(
"import time; time.sleep(300); print('Done')",
name="long-task"
)
print(f"Process ID: {proc['process_id']}")
# Check status later
processes = sandbox.list_processes()
```
**Expected Output:**
```
Process ID: proc-abc123xyz
```
**See Also:**
* [API: Execute Code (Background)](/api/vm-agent/execute-background)
***
#### `list_processes`
List all background execution processes.
```python theme={null}
sandbox.list_processes() -> List[Dict[str, Any]]
```
**Returns:** `List[Dict[str, Any]]` - List of process dictionaries
**Example:**
```python theme={null}
processes = sandbox.list_processes()
for proc in processes:
print(f"{proc['process_id']}: {proc['status']}")
```
**Expected Output:**
```
proc_abc123: running
proc_def456: completed
```
**See Also:**
* [API: List Processes](/api/vm-agent/list-processes)
***
#### `kill_process`
Kill a background execution process.
```python theme={null}
sandbox.kill_process(process_id) -> Dict[str, Any]
```
**Parameters:**
* `process_id` (`str`): Process ID from `run_code_background()` or `list_processes()`
**Returns:** `Dict[str, Any]` - Confirmation message
**Example:**
```python theme={null}
sandbox.kill_process("proc-abc123")
```
**Expected Output:**
```
Process killed successfully
```
**See Also:**
* [API: Kill Process](/api/vm-agent/kill-process)
***
### Information Methods
#### `get_agent_metrics`
Get real-time agent metrics.
```python theme={null}
sandbox.get_agent_metrics() -> Dict[str, Any]
```
**Returns:** `Dict[str, Any]` - Metrics dictionary with `total_executions`, `active_executions`, `error_count`, etc.
**Example:**
```python theme={null}
metrics = sandbox.get_agent_metrics()
print(f"Total executions: {metrics['total_executions']}")
print(f"Active: {metrics['active_executions']}")
```
**Expected Output:**
```
Total executions: 42
Active: 2
```
**See Also:**
* [API: Get System Metrics](/api/vm-agent/get-system-metrics)
***
#### `get_agent_info`
Get VM agent information (version, OS, architecture, endpoints, features).
```python theme={null}
sandbox.get_agent_info() -> Dict[str, Any]
```
**Returns:** `Dict[str, Any]` - Agent information dictionary
Requires Agent v3.1.0+. Uses GET /info endpoint.
**Example:**
```python theme={null}
info = sandbox.get_agent_info()
print(f"Agent version: {info['version']}")
print(f"OS: {info['os']}")
```
**Expected Output:**
```
Agent version: 3.1.0
OS: linux
```
***
#### `get_preview_url`
Get preview URL for accessing a service running on a specific port.
```python theme={null}
sandbox.get_preview_url(port=7777) -> str
```
**Parameters:**
* `port` (`int`, optional): Port number (default: `7777`)
**Returns:** `str` - Preview URL
HopX automatically exposes all ports. Use this to get the public URL for any port.
**Example:**
```python theme={null}
# Start a web server
sandbox.run_code("python -m http.server 8000", background=True)
# Get preview URL
url = sandbox.get_preview_url(port=8000)
print(f"Access at: {url}")
```
**Expected Output:**
```
Access at: https://8000-sandbox_abc123xyz.hopx.dev
```
***
#### `get_metrics_snapshot`
Get current system metrics snapshot.
```python theme={null}
sandbox.get_metrics_snapshot() -> Dict[str, Any]
```
**Returns:** `Dict[str, Any]` - System metrics dictionary
**Example:**
```python theme={null}
metrics = sandbox.get_metrics_snapshot()
print(f"CPU: {metrics.get('cpu_percent')}%")
print(f"Memory: {metrics.get('memory_percent')}%")
```
**Expected Output:**
```
CPU: 15.3%
Memory: 42.1%
```
***
### Utility Methods
#### `set_timeout`
Extend sandbox timeout.
```python theme={null}
sandbox.set_timeout(seconds) -> None
```
**Parameters:**
* `seconds` (`int`): New timeout in seconds
**Example:**
```python theme={null}
sandbox.set_timeout(3600) # Extend to 1 hour
```
**See Also:**
* [API: Set Sandbox Timeout](/api/control-plane/set-timeout)
***
#### `refresh_token`
Refresh JWT token for agent authentication.
```python theme={null}
sandbox.refresh_token() -> None
```
**Example:**
```python theme={null}
sandbox.refresh_token()
```
**Expected Output:**
```
Token refreshed successfully
```
***
#### `get_token`
Get current JWT token.
```python theme={null}
sandbox.get_token() -> str
```
**Returns:** `str` - JWT token string
**Example:**
```python theme={null}
token = sandbox.get_token()
print(f"Token: {token[:20]}...")
```
**Expected Output:**
```
Token: eyJhbGciOiJIUzI1NiIs...
```
***
## Properties
### `files`
File operations resource (lazy-loaded).
**Type:** `Files`
**Example:**
```python theme={null}
# Read a file
content = sandbox.files.read("/workspace/script.py")
# Write a file
sandbox.files.write("/workspace/data.txt", "Hello, World!")
```
**Expected Output:**
```
File written successfully
```
See [Files Resource](/sdk/python/files) for complete documentation.
***
### `commands`
Command execution resource (lazy-loaded).
**Type:** `Commands`
**Example:**
```python theme={null}
result = sandbox.commands.run("ls -la /workspace")
print(result.stdout)
```
**Expected Output:**
```
total 8
drwxr-xr-x 2 root root 4096 Jan 27 10:30 .
drwxr-xr-x 3 root root 4096 Jan 27 10:30 ..
-rw-r--r-- 1 root root 42 Jan 27 10:30 data.txt
```
See [Commands Resource](/sdk/python/commands) for complete documentation.
***
### `env`
Environment variables resource (lazy-loaded).
**Type:** `EnvironmentVariables`
**Example:**
```python theme={null}
# Set environment variable
sandbox.env.set("API_KEY", "secret123")
# Get all environment variables
all_vars = sandbox.env.get_all()
```
**Expected Output:**
```
Environment variable set successfully
```
See [Environment Variables Resource](/sdk/python/environment-variables) for complete documentation.
***
### `desktop`
Desktop automation resource (lazy-loaded).
**Type:** `Desktop`
**Example:**
```python theme={null}
# Take a screenshot
screenshot = sandbox.desktop.screenshot()
# Click at position
sandbox.desktop.click(100, 200)
```
**Expected Output:**
```
Screenshot captured (PNG bytes)
Click executed at (100, 200)
```
See [Desktop Resource](/sdk/python/desktop) for complete documentation.
***
### `cache`
Cache management resource (lazy-loaded).
**Type:** `Cache`
**Example:**
```python theme={null}
# Get cache statistics
stats = sandbox.cache.stats()
print(f"Cache size: {stats['cache']['size']}")
# Clear cache
sandbox.cache.clear()
```
**Expected Output:**
```
Cache size: 5
Cache cleared successfully
```
See [Cache Resource](/sdk/python/cache) for complete documentation.
***
### `terminal`
Interactive terminal resource via WebSocket (lazy-loaded).
**Type:** `Terminal`
Requires `websockets` library: `pip install websockets`
**Example:**
```python theme={null}
import asyncio
async def use_terminal():
ws = await sandbox.terminal.connect()
await sandbox.terminal.send_input(ws, "echo 'Hello'\n")
# ... handle output
await ws.close()
asyncio.run(use_terminal())
```
**Expected Output:**
```
Terminal connected
Hello
Terminal closed
```
See [Terminal Resource](/sdk/python/terminal) for complete documentation.
***
### `agent_url`
Get the sandbox agent URL (port 7777) - convenience property.
**Type:** `str` (read-only)
**Example:**
```python theme={null}
url = sandbox.agent_url
print(f"Agent URL: {url}")
```
**Expected Output:**
```
Agent URL: https://sandbox_abc123xyz.hopx.dev
```
***
## Context Manager
The `Sandbox` class supports context manager protocol for automatic cleanup.
**Example:**
```python theme={null}
# Automatically calls kill() when exiting context
with Sandbox.create(template="code-interpreter") as sandbox:
result = sandbox.run_code("print('Hello')")
print(result.stdout)
# Sandbox is automatically destroyed here
```
**Expected Output:**
```
Hello
```
***
## Examples
### Example 1: Basic Usage
```python theme={null}
from hopx_ai import Sandbox
# Create sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Execute code
result = sandbox.run_code("print('Hello, HopX!')")
print(result.stdout)
# Cleanup
sandbox.kill()
```
**Expected Output:**
```
Hello, HopX!
```
### Example 2: Using Context Manager
```python theme={null}
from hopx_ai import Sandbox
with Sandbox.create(template="code-interpreter") as sandbox:
# Work with sandbox
result = sandbox.run_code("import sys; print(sys.version)")
print(result.stdout)
# Automatically cleaned up
```
**Expected Output:**
```
3.11.5 (main, Jan 27 2025, 10:30:00) [GCC 11.2.0]
```
### Example 3: File Operations
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Write a file
sandbox.files.write("/workspace/script.py", "print('Hello')")
# Execute it
result = sandbox.run_code("exec(open('/workspace/script.py').read())")
print(result.stdout)
sandbox.kill()
```
**Expected Output:**
```
Hello
```
### Example 4: Background Execution
```python theme={null}
from hopx_ai import Sandbox
import time
sandbox = Sandbox.create(template="code-interpreter")
# Start long-running task
proc = sandbox.run_code_background(
"import time; time.sleep(60); print('Done')",
name="long-task"
)
# Do other work
time.sleep(5)
# Check status
processes = sandbox.list_processes()
for p in processes:
if p['process_id'] == proc['process_id']:
print(f"Status: {p['status']}")
sandbox.kill()
```
**Expected Output:**
```
Status: running
```
***
## Related Classes
* **[AsyncSandbox](/sdk/python/async-sandbox)** - Async version of Sandbox for async/await workflows
* **[Files](/sdk/python/files)** - File operations resource
* **[Commands](/sdk/python/commands)** - Command execution resource
* **[Environment Variables](/sdk/python/environment-variables)** - Environment variable management
* **[Desktop](/sdk/python/desktop)** - Desktop automation resource
* **[Cache](/sdk/python/cache)** - Cache management resource
* **[Terminal](/sdk/python/terminal)** - Interactive terminal resource
## See Also
* [Quickstart Guide](/sdk/python/quickstart) - Get started with the SDK
* [Installation](/sdk/python/installation) - Install and configure the SDK
* [Core Concepts](/core-concepts/sandboxes/creating) - Learn about sandboxes
## Next Steps
* Learn about [AsyncSandbox](/sdk/python/async-sandbox) for async/await workflows
* Explore [Creating Sandboxes](/core-concepts/sandboxes/creating) with different templates
* Review [Code Execution](/core-concepts/code-execution/synchronous) to run code in sandboxes
* Check out [File Operations](/sdk/python/files) for managing files
* See [API Reference](/api/control-plane/create-sandbox) for direct API access
* **[CLI Reference](/cli/introduction)** - Use HopX from the command line
* [API Reference](/api/introduction) - Raw REST API documentation
# Template Builder
Source: https://docs.hopx.ai/sdk/python/template-builder
Fluent API for building custom sandbox templates in the HopX Python SDK. Create custom templates from Docker images, configure resources, add build steps, and install dependencies using a fluent builder pattern. Complete reference for TemplateBuilder class with code examples and template configuration options.
**Version:** 0.3.0\
**Last Verified:** 2025-01-27\
**Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/)
## Overview
The `Template` class provides a fluent API for building custom sandbox templates. Use this to create reusable templates with specific configurations, dependencies, and ready checks.
Templates are built from base images and can include file copies, command execution, environment variables, port exposure, and ready checks.
## Import
```python theme={null}
from hopx_ai.template import Template
```
## Base Image Methods
### `from_ubuntu_image`
Start from Ubuntu base image.
```python theme={null}
Template.from_ubuntu_image(version) -> Template
```
**Parameters:**
* `version` (`str`): Ubuntu version (e.g., `"22.04"`)
**Returns:** `Template` - Template instance (fluent API)
**Expected Output:**
```
Template instance ready for configuration
```
***
### `from_python_image`
Start from Python base image.
```python theme={null}
Template.from_python_image(version) -> Template
```
**Parameters:**
* `version` (`str`): Python version (e.g., `"3.11"`)
**Expected Output:**
```
Template instance ready for configuration
```
***
### `from_node_image`
Start from Node.js base image.
```python theme={null}
Template.from_node_image(version) -> Template
```
**Parameters:**
* `version` (`str`): Node.js version (e.g., `"20"`)
**Expected Output:**
```
Template instance ready for configuration
```
***
### `from_image`
Start from any Docker image.
```python theme={null}
Template.from_image(image, auth=None) -> Template
```
**Parameters:**
* `image` (`str`): Docker image name
* `auth` (`Dict`, optional): Authentication credentials
**Expected Output:**
```
Template instance ready for configuration
```
***
## Configuration Methods
### `copy`
Copy files to the template.
```python theme={null}
Template.copy(src, dest, options=None) -> Template
```
**Parameters:**
* `src` (`str`): Source path
* `dest` (`str`): Destination path
* `options` (`Dict`, optional): Copy options
**Expected Output:**
```
Template instance (fluent API)
```
***
### `run`
Run command in template.
```python theme={null}
Template.run(command) -> Template
```
**Parameters:**
* `command` (`str`): Command to execute
**Expected Output:**
```
Template instance (fluent API)
```
**Example:**
```python theme={null}
Template.from_python_image("3.11").run("pip install requests")
```
***
### `env`
Set environment variable.
```python theme={null}
Template.env(key, value) -> Template
```
**Parameters:**
* `key` (`str`): Environment variable name
* `value` (`str`): Environment variable value
**Expected Output:**
```
Template instance (fluent API)
```
***
### `expose`
Expose port.
```python theme={null}
Template.expose(port) -> Template
```
**Parameters:**
* `port` (`int`): Port number to expose
**Expected Output:**
```
Template instance (fluent API)
```
***
### `workdir`
Set working directory.
```python theme={null}
Template.workdir(path) -> Template
```
**Parameters:**
* `path` (`str`): Working directory path
**Expected Output:**
```
Template instance (fluent API)
```
***
### `ready_check`
Set ready check.
```python theme={null}
Template.ready_check(check) -> Template
```
**Parameters:**
* `check` (ReadyCheck): Ready check object
**Expected Output:**
```
Template instance (fluent API)
```
See [Ready Checks](/sdk/python/ready-checks) for available ready checks.
***
### `start_cmd`
Set start command.
```python theme={null}
Template.start_cmd(command) -> Template
```
**Parameters:**
* `command` (`str`): Start command
**Expected Output:**
```
Template instance (fluent API)
```
***
## Building
### `build`
Build the template.
```python theme={null}
await Template.build(options=None) -> BuildResult
```
**Parameters:**
* `options` (`Dict`, optional): Build options
**Returns:** `BuildResult` - Build result with template ID and status
**Example:**
```python theme={null}
import asyncio
async def build_template():
template = (
Template
.from_python_image("3.11")
.run("pip install flask")
.expose(5000)
.start_cmd("python app.py")
)
result = await template.build()
print(f"Template ID: {result.template_id}")
asyncio.run(build_template())
```
**Expected Output:**
```
Template ID: template_abc123xyz
```
***
## Examples
### Example 1: Simple Python Template
```python theme={null}
from hopx_ai.template import Template
import asyncio
async def main():
template = (
Template
.from_python_image("3.11")
.run("pip install requests pandas")
.env("PYTHONUNBUFFERED", "1")
)
result = await template.build()
print(f"Built template: {result.template_id}")
asyncio.run(main())
```
**Expected Output:**
```
Built template: template_abc123xyz
```
### Example 2: Web Server Template
```python theme={null}
from hopx_ai.template import Template, wait_for_port
import asyncio
async def main():
template = (
Template
.from_node_image("20")
.run("npm install express")
.copy("./app.js", "/app/app.js")
.expose(3000)
.start_cmd("node /app/app.js")
.ready_check(wait_for_port(3000))
)
result = await template.build()
print(f"Web server template: {result.template_id}")
asyncio.run(main())
```
**Expected Output:**
```
Web server template: template_abc123xyz
```
***
## Related Classes
* **[Ready Checks](/sdk/python/ready-checks)** - Ready check utilities
* **[Sandbox](/sdk/python/sandbox)** - Use templates with `Sandbox.create(template=...)`
## See Also
* [Ready Checks](/sdk/python/ready-checks) - Learn about ready checks
* [Core Concepts: Templates](/core-concepts/templates) - Learn about templates
## Next Steps
Now that you understand template building, explore:
* [Ready Checks](/sdk/python/ready-checks) - Add readiness verification
* [Building Templates](/core-concepts/templates/building) - Learn template building concepts
* [Template Configuration](/core-concepts/templates/configuration) - Configure templates
* **[CLI Reference](/cli/introduction)** - Use HopX from the command line
* [Custom Templates](/cookbooks/advanced/custom-templates) - Build custom templates
# Terminal Access
Source: https://docs.hopx.ai/sdk/python/terminal
Interactive terminal resource for WebSocket-based sandbox terminal access in HopX using the Python SDK. Complete reference for the Terminal class including methods for connecting to interactive terminals, executing commands in real-time, and streaming terminal output. Includes code examples for terminal automation.
**Version:** 0.3.0\
**Last Verified:** 2025-01-27\
**Package:** `hopx-ai` on [PyPI](https://pypi.org/project/hopx-ai/)
## Overview
The `Terminal` resource provides interactive terminal access via WebSocket. Use this resource when you need interactive shell access, real-time terminal output, or terminal resizing capabilities.
Requires `websockets` library: `pip install websockets`
## Access
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
terminal = sandbox.terminal # Lazy-loaded
```
## Methods
### `connect`
Connect to interactive terminal.
```python theme={null}
async terminal.connect(*, timeout=30) -> WebSocketClientProtocol
```
**Parameters:**
* `timeout` (`int`, optional): Connection timeout in seconds (default: `30`)
**Returns:** `WebSocketClientProtocol` - WebSocket connection object
**Example:**
```python theme={null}
import asyncio
async def use_terminal():
ws = await sandbox.terminal.connect()
# Use terminal...
await ws.close()
asyncio.run(use_terminal())
```
***
### `send_input`
Send input to terminal.
```python theme={null}
async terminal.send_input(ws, data) -> None
```
**Parameters:**
* `ws` (`WebSocketClientProtocol`): WebSocket connection
* `data` (`str` or `bytes`): Input data to send
**Example:**
```python theme={null}
await sandbox.terminal.send_input(ws, "echo 'Hello'\n")
```
***
### `resize`
Resize terminal window.
```python theme={null}
async terminal.resize(ws, cols, rows) -> None
```
**Parameters:**
* `ws` (`WebSocketClientProtocol`): WebSocket connection
* `cols` (`int`): Number of columns
* `rows` (`int`): Number of rows
**Example:**
```python theme={null}
await sandbox.terminal.resize(ws, 80, 24)
```
***
### `iter_output`
Iterate over terminal output messages.
```python theme={null}
async terminal.iter_output(ws) -> AsyncIterator[Dict[str, Any]]
```
**Parameters:**
* `ws` (`WebSocketClientProtocol`): WebSocket connection
**Returns:** `AsyncIterator[Dict[str, Any]]` - Iterator of message dictionaries
**Example:**
```python theme={null}
async for message in sandbox.terminal.iter_output(ws):
if message.get('type') == 'stdout':
print(message.get('data', ''), end='')
```
***
## Examples
### Example 1: Basic Terminal Usage
```python theme={null}
import asyncio
from hopx_ai import Sandbox
async def main():
sandbox = Sandbox.create(template="code-interpreter")
# Connect to terminal
ws = await sandbox.terminal.connect()
# Send command
await sandbox.terminal.send_input(ws, "echo 'Hello, Terminal!'\n")
# Read output
async for message in sandbox.terminal.iter_output(ws):
if message.get('type') == 'stdout':
print(message.get('data', ''), end='')
break # Exit after first output
await ws.close()
sandbox.kill()
asyncio.run(main())
```
### Example 2: Interactive Terminal Session
```python theme={null}
import asyncio
from hopx_ai import Sandbox
async def main():
sandbox = Sandbox.create(template="code-interpreter")
ws = await sandbox.terminal.connect()
# Resize terminal
await sandbox.terminal.resize(ws, 120, 40)
# Send multiple commands
commands = [
"pwd\n",
"ls -la\n",
"echo 'Done'\n"
]
for cmd in commands:
await sandbox.terminal.send_input(ws, cmd)
# Read output
async for message in sandbox.terminal.iter_output(ws):
if message.get('type') == 'stdout':
print(message.get('data', ''), end='')
elif message.get('type') == 'done':
break
await ws.close()
sandbox.kill()
asyncio.run(main())
```
***
## Related Classes
* **[Sandbox](/sdk/python/sandbox)** - Main sandbox class
* **[Core Concepts: Terminal](/core-concepts/terminal)** - Learn about terminal access
## See Also
* [Sandbox Class](/sdk/python/sandbox) - Access terminal via `sandbox.terminal`
* [Terminal Documentation](/core-concepts/terminal) - Detailed terminal documentation
## Related
* **[WebSocket Terminal](/core-concepts/terminal/websocket)** - Learn about terminal access
* **[Running Commands](/core-concepts/commands/running)** - Execute shell commands synchronously
* **[Sandbox Class](/sdk/python/sandbox)** - Access terminal via `sandbox.terminal`
## Next Steps
* Learn about [WebSocket Terminal](/core-concepts/terminal/websocket) for interactive terminal access
* Explore [Running Commands](/core-concepts/commands/running) for synchronous command execution
* Review [Background Commands](/core-concepts/commands/background) for non-blocking execution
* **[CLI Terminal](/cli/commands/terminal)** - Access terminal from CLI
# Supported Languages
Source: https://docs.hopx.ai/supported-languages
Programming languages supported by HopX sandboxes and their specific features. Learn about Python, JavaScript, Bash, Go, and other languages available in HopX sandbox environments.
HopX sandboxes support multiple programming languages for code execution. Each language has specific features, pre-installed packages, and capabilities.
## Overview
HopX currently supports the following languages:
* **Python** - Full-featured Python environment with data science libraries
* **JavaScript/Node.js** - Modern JavaScript runtime with npm support
* **Bash** - Shell scripting and command execution
* **Go** - Go programming language runtime
Language support depends on the template you use. The `code-interpreter` template includes Python, JavaScript, and Bash. Other templates may support different language combinations.
## Python
Python is the most feature-rich language in HopX sandboxes, with extensive pre-installed packages for data science, web development, and automation.
### Version
* **Python 3.11+** (varies by template)
### Pre-installed Packages
Common packages available in most Python templates:
* **Data Science**: `pandas`, `numpy`, `matplotlib`, `scipy`, `scikit-learn`
* **Web**: `requests`, `httpx`, `flask`, `fastapi`
* **Utilities**: `beautifulsoup4`, `ipykernel`, `jupyter-client`
* **System**: `git`, `curl`, `wget`, `vim`, `nano`
### Features
* ✅ **Rich Output Capture**: Automatically captures matplotlib plots, pandas DataFrames, and other visualizations
* ✅ **IPython Kernel**: Interactive Python execution with Jupyter kernel support
* ✅ **Package Installation**: Install additional packages with `pip`
* ✅ **File Operations**: Full filesystem access for reading/writing files
* ✅ **Environment Variables**: Access via `os.getenv()` or `os.environ`
### Example
```python theme={null}
from hopx_ai import Sandbox
from hopx_ai.exceptions import APIError, ResourceLimitError
try:
sandbox = Sandbox.create(template="code-interpreter")
# Execute Python code
result = sandbox.run_code("""
import pandas as pd
import matplotlib.pyplot as plt
data = {'x': [1, 2, 3, 4], 'y': [1, 4, 9, 16]}
df = pd.DataFrame(data)
print(df.describe())
plt.plot(df['x'], df['y'])
plt.savefig('/tmp/plot.png')
""", language="python")
print(result.stdout)
# Rich outputs (plots, DataFrames) are automatically captured
sandbox.kill()
except APIError as e:
print(f"API error: {e}")
except ResourceLimitError as e:
print(f"Resource limit exceeded: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
```
**Expected Output:**
```
x y
count 4.000000 4.000000
mean 2.500000 7.500000
std 1.290994 6.454972
min 1.000000 1.000000
25% 1.750000 3.250000
50% 2.500000 6.500000
75% 3.250000 11.750000
max 4.000000 16.000000
```
Rich outputs (plots, DataFrames) are automatically captured in `result.rich_outputs`.
## JavaScript/Node.js
JavaScript execution runs in a Node.js environment with access to npm packages and modern JavaScript features.
### Version
* **Node.js 18+** (varies by template)
### Pre-installed Packages
* **Runtime**: Node.js with npm
* **Kernel**: iJavaScript kernel for interactive execution
* **System Tools**: Standard Unix utilities
### Features
* ✅ **npm Support**: Install packages with `npm install`
* ✅ **ES Modules**: Support for modern ES6+ syntax
* ✅ **Rich Output**: Can generate HTML, JSON, and text outputs
* ✅ **Async/Await**: Full support for asynchronous operations
* ✅ **File System**: Access to Node.js `fs` module
### Example
```javascript theme={null}
import { Sandbox } from '@hopx-ai/sdk';
import { APIError, ResourceLimitError } from '@hopx-ai/sdk';
try {
const sandbox = await Sandbox.create({ template: 'code-interpreter' });
// Execute JavaScript code
const result = await sandbox.runCode(`
const fs = require('fs');
const data = { message: 'Hello from Node.js!', timestamp: Date.now() };
console.log(JSON.stringify(data, null, 2));
// Write to file
fs.writeFileSync('/tmp/output.json', JSON.stringify(data));
`, { language: 'javascript' });
console.log(result.stdout);
await sandbox.kill();
} catch (error) {
if (error instanceof APIError) {
console.error(`API error: ${error.message}`);
} else if (error instanceof ResourceLimitError) {
console.error(`Resource limit exceeded: ${error.message}`);
} else {
console.error(`Unexpected error: ${error.message}`);
}
}
```
**Expected Output:**
```json theme={null}
{
"message": "Hello from Node.js!",
"timestamp": 1706284800000
}
```
### JavaScript-Specific Features
The JavaScript SDK includes some unique features:
* **IPython Kernel Support**: `sandbox.runIpython()` method for interactive JavaScript execution
* **TypeScript Types**: Full TypeScript support with type definitions
* **Async Generators**: WebSocket streaming uses async generators (`for await...of`)
## Bash
Bash provides shell scripting capabilities for system administration, automation, and command execution.
### Features
* ✅ **Shell Commands**: Execute any shell command or script
* ✅ **Pipelines**: Support for command pipelines and redirection
* ✅ **Environment Variables**: Access via `$VARIABLE_NAME` syntax
* ✅ **File Operations**: Standard Unix file operations (cp, mv, rm, etc.)
* ✅ **Process Management**: Background processes, job control
### Example
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Execute bash commands
result = sandbox.run_code("""
#!/bin/bash
echo "Current directory: $(pwd)"
echo "User: $(whoami)"
echo "Date: $(date)"
# List files
ls -la /workspace
# Process data
echo "1,2,3,4,5" | tr ',' '\\n' | awk '{sum+=$1} END {print "Sum:", sum}'
""", language="bash")
print(result.stdout)
```
**Expected Output:**
```
Current directory: /workspace
User: root
Date: Mon Jan 27 10:30:00 UTC 2025
total 8
drwxr-xr-x 2 root root 4096 Jan 27 10:30 .
drwxr-xr-x 3 root root 4096 Jan 27 10:30 ..
-rw-r--r-- 1 root root 42 Jan 27 10:30 data.txt
Sum: 15
```
### Common Use Cases
* Installing system packages with `apt-get` or `yum`
* Running build scripts and automation tasks
* Processing text files with `grep`, `sed`, `awk`
* Managing files and directories
* Running system diagnostics
## Go
Go (Golang) support enables compilation and execution of Go programs in sandboxes.
### Version
* **Go 1.21+** (varies by template)
### Features
* ✅ **Compilation**: Compile Go programs with `go build`
* ✅ **Standard Library**: Full access to Go standard library
* ✅ **Modules**: Support for Go modules and dependency management
* ✅ **Concurrency**: Full support for goroutines and channels
* ✅ **Cross-compilation**: Can compile for different platforms
### Example
```python theme={null}
from hopx_ai import Sandbox
sandbox = Sandbox.create(template="code-interpreter")
# Execute Go code
result = sandbox.run_code("""
package main
import (
"fmt"
"time"
)
func main() {
fmt.Println("Hello from Go!")
fmt.Printf("Current time: %s\\n", time.Now().Format(time.RFC3339))
// Simple goroutine example
go func() {
time.Sleep(1 * time.Second)
fmt.Println("Goroutine completed!")
}()
time.Sleep(2 * time.Second)
}
""", language="go")
print(result.stdout)
```
**Expected Output:**
```
Hello from Go!
Current time: 2025-01-27T10:30:00Z # Actual timestamp will vary
Goroutine completed!
```
The timestamp in the output will be the actual execution time, not a fixed value. The format follows RFC3339 (e.g., `2025-01-27T10:30:00Z`).
## Language-Specific Considerations
### Execution Timeouts
Default timeouts vary by language and execution mode:
* **Synchronous execution**: 30-60 seconds (configurable)
* **Background execution**: Up to 300 seconds (5 minutes)
* **Async execution**: Up to 3600 seconds (1 hour) with webhooks
### Memory and Resources
* Each sandbox has allocated CPU, memory, and disk resources
* Resource limits are defined by the template
* Monitor resource usage to avoid hitting limits
### Package Installation
```python theme={null}
# Install packages during execution
sandbox.run_code("""
import subprocess
subprocess.run(['pip', 'install', 'package-name'], check=True)
""", language="python")
```
Or use commands:
```python theme={null}
sandbox.commands.run("pip install package-name")
```
```javascript theme={null}
// Install packages during execution
await sandbox.runCode(`
const { execSync } = require('child_process');
execSync('npm install package-name', { stdio: 'inherit' });
`, { language: 'javascript' });
```
Or use commands:
```javascript theme={null}
await sandbox.commands.run('npm install package-name');
```
```python theme={null}
sandbox.run_code("""
apt-get update && apt-get install -y package-name
""", language="bash")
```
### Environment Variables
All languages can access environment variables set in the sandbox:
```python theme={null}
import os
value = os.getenv('MY_VAR', 'default')
```
```javascript theme={null}
const value = process.env.MY_VAR || 'default';
```
```bash theme={null}
value=${MY_VAR:-default}
```
```go theme={null}
import "os"
value := os.Getenv("MY_VAR")
if value == "" {
value = "default"
}
```
## Choosing the Right Language
Use **Python** for data analysis, machine learning, and visualization. Pre-installed packages like pandas, numpy, and matplotlib make it ideal for data work.
Use **JavaScript** for Node.js applications, API development, and web scraping. Full npm support enables rapid development.
Use **Bash** for system administration, file processing, and automation scripts. Perfect for DevOps tasks.
Use **Go** for concurrent programs, network services, and performance-critical applications. Excellent for building APIs and microservices.
## Language Support by Template
Different templates support different languages. Check template details to see which languages are available:
```python theme={null}
from hopx_ai import Sandbox
# List available templates
templates = Sandbox.list_templates()
for template in templates:
print(f"{template.name}: {template.language or 'Multiple'}")
```
**Expected Output:**
```
code-interpreter: Multiple
python-basic: Python
node-basic: JavaScript
ubuntu-base: Multiple
```
The actual templates and their languages may vary. Use `Sandbox.list_templates()` to see available templates in your account.
## Related
* **[Code Execution](/core-concepts/code-execution/synchronous)** - Execute code in different languages
* **[Creating Sandboxes](/core-concepts/sandboxes/creating)** - Create sandboxes with language support
* **[Listing Templates](/core-concepts/templates/listing)** - Find templates with language support
* **[Quickstart Guide](/quickstart)** - Get started with code execution
## Next Steps
* Follow the [Quickstart Guide](/quickstart) to execute your first code
* Learn about [Code Execution](/core-concepts/code-execution/synchronous) features
* Explore [Rich Output Capture](/core-concepts/code-execution/rich-output) for data visualization