cpctl CLI
The cpctl CLI is the command-line interface for Compute Portal. It lets you deploy GPU workloads, manage services, databases, and infrastructure entirely from a terminal — scriptable, agent-friendly, and designed for full CI/CD integration.
Installation
# Linux / macOS (recommended)
curl -fsSL https://install.computeportal.io | sh
# Install a specific version
CP_VERSION=v0.2.0 curl -fsSL https://install.computeportal.io | sh
# Install to a custom directory (no sudo)
CP_INSTALL_DIR=~/.local/bin curl -fsSL https://install.computeportal.io | shOr download a binary directly from GitHub Releases:
| Platform | Binary |
|---|---|
| Linux x86_64 | cpctl-linux-amd64 |
| Linux ARM64 | cpctl-linux-arm64 |
| macOS x86_64 | cpctl-darwin-amd64 |
| macOS Apple Silicon | cpctl-darwin-arm64 |
After installation verify it works:
cpctl versionAuthentication
Login with API token
The recommended method for CI/CD and agents:
cpctl login --token <api-token>Get your API token from computeportal.io/user/orders after purchasing a subscription.
You can also set the token via environment variable — useful in containers and CI pipelines:
export CP_API_TOKEN=<api-token>Run cpctl login without flags for instructions on getting your token.
Logout
cpctl logout # revokes token locally and server-sideShow current user
cpctl whoamiemail alice@example.com
user_id usr_abc123
org example-org
plan pro
token_expires_at 2027-01-01T00:00:00ZGlobal Flags
These flags apply to every command:
| Flag | Description |
|---|---|
--region <region> | Pin all API calls to a specific region (eu-west, us-east, ap-south) |
--json | Output results as machine-readable JSON |
--yes, -y | Skip all confirmation prompts |
Project Setup
Initialize a project
Creates a cp.json in the current directory via interactive prompts:
cpctl initInitialising Compute Portal project...
Project name: my-inference-api
Docker image: myorg/inference:latest
Region (eu-west / us-east / ap-south) [eu-west]: eu-west
Replicas [1]: 2Generated cp.json:
{
"project": "my-inference-api",
"image": "myorg/inference:latest",
"region": "eu-west",
"replicas": 2
}Link a directory to a service
cpctl link my-inference-api
# Linked to service my-inference-api (wrote .cp-link)This writes a .cp-link file so subsequent commands (deploy, logs, env) know which service to target.
Unlink
cpctl unlink
# Unlinked (removed .cp-link)Open a service in the browser
cpctl open # reads service from .cp-link
cpctl open my-inference-api # explicit service nameList all services
cpctl listNAME IMAGE STATUS REGION URL
my-inference-api myorg/inference:latest running eu-west https://my-inference-api.cpctl.app
postgres-db postgres:16 running eu-west —Deploy
Deploy a Docker image or GitHub repo to CP hardware.
# Deploy from Docker image
cpctl deploy --image nginx:latest
# Deploy with GPU
cpctl deploy --image myorg/inference:latest --gpu rtx4090
# Deploy with multiple GPUs
cpctl deploy --image myorg/trainer:latest --gpu rtx5090 --gpu-count 4
# Deploy from a GitHub repo (no Dockerfile needed)
cpctl deploy --repo https://github.com/org/repo
# Deploy from cp.json in the current directory
cpctl deployDeploy from a local directory or existing image
If you have a local Dockerfile or an existing image, choose one of these options:
Option 1 — Push to a registry first, then deploy:
docker build -t myorg/myapp:latest .
docker push myorg/myapp:latest
cpctl deploy --image myorg/myapp:latest --name my-appOption 2 — Push to GitHub and use --repo:
git push origin main
cpctl deploy --repo https://github.com/myorg/myapp --name my-appPublic access only
Both options currently require public access — public Docker Hub/GHCR images for --image, and public GitHub repos for --repo. If you need to deploy from a private registry or private GitHub repo, contact Compute Portal to discuss secure options.
Deploy from a GitHub repo
Pass --repo with a public GitHub URL and CP handles the rest — no Docker knowledge required:
cpctl deploy --repo https://github.com/your-org/your-app --name my-app→ Deploying https://github.com/your-org/your-app...
✓ Deployed my-app
service my-app
id my-app
url https://my-app.cpctl.app
status runningWhat happens behind the scenes:
- CP clones your repo
- Detects and uses the
Dockerfileat the repo root - Builds the Docker image on CP infrastructure
- Pushes it to the internal registry
- Deploys the resulting image as a running service
The registry is fully internal — no Docker Hub account or image push required from your side.
Dockerfile required
Your repo must contain a Dockerfile at the root. CP uses it to build the image.
Deploy flags
| Flag | Description |
|---|---|
--image <image> | Docker image to deploy (e.g. nginx:latest) |
--repo <url> | GitHub repo URL to build and deploy |
--name <name> | Service name (default: derived from image or repo name) |
--env <environment> | Target environment (default: production) |
--region <region> | Region to deploy to (eu-west, us-east, ap-south) |
--gpu <type> | GPU to attach (rtx4090, rtx5090) |
--gpu-count <n> | Number of GPUs (default: 1) |
--node <id> | Pin to a specific node ID |
When --image and --repo are both absent, cpctl deploy reads cp.json from the current directory.
Deploy output
Deploying myorg/inference:latest...
✓ Deployed my-inference-api
service my-inference-api
id svc_abc123
url https://my-inference-api.cpctl.app
status runningService Lifecycle
The most common lifecycle commands are available at the top level:
cpctl stop <name> # stop a running service
cpctl start <name> # start a stopped service
cpctl delete <name> --force # permanently delete a serviceThe full cpctl machine subcommand offers additional operations:
cpctl machine list # list all services
cpctl machine status <name> # show health and resources
cpctl machine start <name> # start a stopped service
cpctl machine stop <name> # stop a running service
cpctl machine restart <name> # restart a service
cpctl machine destroy <name> # permanently destroy a service (alias: cpctl delete)machine status
cpctl machine status my-inference-apiname my-inference-api
id svc_abc123
image myorg/inference:latest
status running
region eu-west
node node-eu1-001
cpu 4.00
memory 16g
url https://my-inference-api.cpctl.app
gpu rtx4090machine destroy
cpctl machine destroy my-inference-api --force--force is required to confirm the destructive operation.
Logs
Stream or tail logs from any service:
cpctl logs <name> # last 100 lines
cpctl logs <name> --tail 500 # last 500 lines
cpctl logs <name> --follow # stream in real time
cpctl logs <name> -f # shorthand for --followStatus
Check platform health or the status of a specific service:
# Platform-wide health
cpctl status
# Per-service status
cpctl status <name>Example output for the service form:
name my-inference-api
status running
image myorg/inference:latest
region eu-west
node node-eu1-001
url https://my-inference-api.cpctl.app
cpu
memory
gpuScale
Adjust replicas or resource limits for a service:
cpctl scale <name> --replicas 3 # set replica count
cpctl scale <name> --cpu 4 # set CPU limit in vCPUs
cpctl scale <name> --ram 16g # set memory limit
cpctl scale <name> --replicas 2 --ram 8g # combine flags| Flag | Description |
|---|---|
--replicas <n> | Number of replicas |
--cpu <n> | CPU limit in vCPUs (e.g. 2, 0.5) |
--ram <size> | Memory limit (e.g. 4g, 512m) |
Exec & SSH
exec — run a command inside a container
cpctl exec <name> -- <command> [args...]
cpctl exec my-api -- sh # open shell
cpctl exec my-api -- python manage.py migrate
cpctl exec my-api -- /bin/bashssh — open a shell in a container
cpctl ssh <name>Alias for cpctl exec <name> -- sh. Opens an interactive shell inside the running container.
Processes
List running processes in a service:
cpctl ps <name>Environment Variables
Set variables
cpctl env set <service> KEY=VALUE [KEY=VALUE ...]
# Single variable
cpctl env set my-api DATABASE_URL=postgres://...
# Multiple variables
cpctl env set my-api DEBUG=false LOG_LEVEL=info
# Import from .env file
cpctl env set my-api --file .envList variables
cpctl env list <service>KEY VALUE
DATABASE_URL postgres://user:pass@host/db
LOG_LEVEL info
DEBUG falseValues longer than 40 characters are masked for safety.
Remove variables
cpctl env unset <service> KEY [KEY ...]
cpctl env unset my-api DEBUG
cpctl env unset my-api DEBUG LOG_LEVELvariable (alias)
cpctl variable is an alias for cpctl env:
cpctl variable list <service>
cpctl variable set <service> KEY=VALUE
cpctl variable delete <service> KEYEnvironments
Environments let you isolate deployments (e.g. production, staging, pr-123).
cpctl environment list # list all environments
cpctl environment create <name> # create a new environment
cpctl environment delete <name> # delete an environment (--force to confirm)
cpctl environment switch <name> # set active environment in .cp-linkSwitch environment
cpctl environment switch staging
# Switched to environment staging (updated .cp-link)The active environment is stored in .cp-link and used automatically by deploy and env commands.
Deployment History
Inspect past deployments for a service:
cpctl deployment list <service> # list all deployments
cpctl deployment status <service> <id> # show a specific deploymentcpctl deployment list my-inference-apiID STATUS IMAGE CREATED_AT
dep_abc123 success myorg/inference:v2.1.0 2026-07-01T12:00:00Z
dep_xyz789 success myorg/inference:v2.0.0 2026-06-28T09:15:00Z
dep_def456 failed myorg/inference:v1.9.0 2026-06-20T18:30:00ZRedeploy
Re-trigger the current deployment:
cpctl redeploy <service>Rollback
Roll back to a previous deployment:
cpctl rollback <service> # roll back to previous
cpctl rollback <service> <dep-id> # roll back to a specific deployment IDCustom Domains
Attach your own domain to a service:
cpctl domain add <service> <domain> # attach a domain
cpctl domain list <service> # list attached domains
cpctl domain status <service> <domain> # check DNS and TLS status
cpctl domain remove <service> <domain> # detach a domaindomain add
Before running this, add a CNAME record at your DNS provider:
| Name | Type | Target | Proxy |
|---|---|---|---|
api | CNAME | cpctl.app | DNS only |
Then attach the domain:
cpctl domain add my-api api.example.com✓ Domain api.example.com attached to my-api
domain api.example.com
service my-api
status active
tls pendingTLS is provisioned automatically via Let's Encrypt within a minute or two.
If DNS hasn't propagated yet, use --skip-dns to bypass the CNAME check:
cpctl domain add my-api api.example.com --skip-dnsdomain status
cpctl domain status my-api api.example.comdomain api.example.com
status active
tls yes
dns_configured yes
cname_target cpctl.app
created_at 2026-07-01T10:00:00ZVolumes
Attach persistent storage volumes to a service:
cpctl volume list <service> # list attached volumes
cpctl volume add <service> <mount-path> # attach a new volume
cpctl volume delete <service> <name> # delete a volume (--force to confirm)# Attach a volume mounted at /data
cpctl volume add my-api /data
# List volumes
cpctl volume list my-apiNAME MOUNT SIZE CREATED_AT
vol_abc123 /data 10GB 2026-07-01T10:00:00ZDatabases
Create a database
cpctl db create postgres # PostgreSQL
cpctl db create redis # Redis
cpctl db create mysql # MySQL
cpctl db create mongo # MongoDBWith options:
cpctl db create postgres \
--name my-postgres \
--region eu-west \
--size 50| Flag | Description |
|---|---|
--name <name> | Database name (default: <type>-db) |
--region <region> | Region (default: account default) |
--size <gb> | Storage size in GB (default: 10) |
List databases
cpctl db listGet connection URL
cpctl db url <name>Prints the full connection URL to stdout — useful for piping into your app's config.
Destroy a database
cpctl db destroy <name> --forceInteractive database shell
cpctl connect <database-name>Automatically selects the right client:
| Database type | Client used |
|---|---|
postgres | psql |
mysql | mysql |
redis | redis-cli |
mongo | mongosh |
The client must be installed locally.
Metrics
View resource metrics for a service:
cpctl metrics <service>service my-inference-api
cpu 12%
memory 4.2 / 16.0 GB
network ↑ 1.2 MB/s ↓ 0.4 MB/sGPU (CP Exclusive)
CP's GPU commands give you direct control over bare-metal GPU inventory — an exclusive capability beyond standard PaaS platforms.
List GPU inventory
cpctl gpu list # all available GPU nodes
cpctl gpu list --region eu-west # filter by region
cpctl gpu list --type rtx4090 # filter by GPU typeNODE GPU AVAIL/TOTAL REGION UTIL VRAM TEMP
node-eu1-001 rtx5090 4 / 4 eu-west 0% 0.0 / 24.0 GB 45°C
node-eu1-002 rtx4090 2 / 8 eu-west 18% 12.4 / 64.0 GB 67°C
node-us1-001 rtx5090 0 / 4 us-east 100% 24.0 / 24.0 GB 82°CGPU status for a service
cpctl gpu status my-inference-apiservice my-inference-api
gpu_type rtx5090
node node-eu1-001
utilization 34.2%
vram 8.3 / 24.0 GB
temperature 58°C
power 220WReserve GPU capacity
Pre-reserve GPUs for guaranteed capacity at a fixed rate:
cpctl gpu reserve --type rtx5090 --count 2 --duration 24h --region eu-west| Flag | Description |
|---|---|
--type <gpu> | GPU type: rtx4090, rtx5090 (required) |
--count <n> | Number of GPUs (default: 1) |
--duration <d> | Duration: 1h, 4h, 24h, 7d, etc. (default: 1h) |
--region <region> | Region (default: account default) |
One-shot GPU jobs
Run a script on a GPU and exit — billed per second, ideal for training runs:
cpctl gpu run \
--image pytorch/pytorch:2.3-cuda12.1 \
--script "python train.py --epochs 10" \
--gpu rtx5090 \
--gpu-count 1Logs stream in real time and billing stops when the job exits.
| Flag | Description |
|---|---|
--image <image> | Docker image to run (required) |
--script <cmd> | Command to run inside the container |
--gpu <type> | GPU type (default: rtx4090) |
--gpu-count <n> | Number of GPUs (default: 1) |
--region <region> | Region |
Infrastructure
Nodes
cpctl node list # list all compute nodes
cpctl node status <node-id> # show node health and resourcesRegions
cpctl region list # list available regionsHosts
cpctl host list # list registered hostsPolicy
cpctl policy list # list scheduling policiesBilling
cpctl billing usage # current billing cycle usage
cpctl billing history # past invoicesMachine Payments
cpctl pay enables per-call, agent-native payments for ComputePortal API operations. AI agents and automated clients can pay for individual API calls using a linked card or USDC wallet — no human checkout, no pre-loaded balance.
pay setup
Link a payment method. Card details are entered securely in your browser via Stripe — raw card numbers never touch the CP server.
cpctl pay setup --method card --limit 1.00This opens a Stripe-hosted checkout page in your browser. Enter your card there, then return to the terminal. The CLI polls until the card is saved.
For USDC payments on the Base network:
cpctl pay setup --method usdc --limit 0.50Output (card):
→ Spend limit: $1.00 per call
Open this URL in your browser to enter your card details:
https://checkout.stripe.com/c/pay/...
Waiting for card setup to complete...
✓ Card linked
cardholder CHOI YOON IL
method card
last4 6880
exp 05/2029
spend_limit $1.00 per call
currency USDpay status
cpctl pay statusOutput:
last4 6880
type card
spend_limit $0.50 per call
currency USD
active yespay authorize
Generate a short-lived payment token for a specific API call. For card payments, the charge is confirmed immediately when you run this command.
cpctl pay authorize <service> <amount> [--action deploy]cpctl pay authorize my-api 0.10Output:
✓ Payment authorized
token mpp_tok_xxxxxxxxxxxxxxxxxxxx...
service my-api
amount $0.10 USD
action deploy
expires_at 2026-07-08T07:06:08Z
charged yes — card charged
stripe_pi pi_3Rxxxxxxxxxxxxxxxxxxxxxxxx
Use this token with your next deploy:
cpctl deploy --image <image> --name my-api --pay-token mpp_tok_xxxxxxxxxxxxxxxxxxxx...The token expires in 5 minutes. Pass it to cpctl deploy via --pay-token:
cpctl deploy --image nginx:latest --name my-api --pay-token mpp_tok_...pay history
cpctl pay history [--limit 20]Output:
ID SERVICE ACTION AMOUNT STATUS STRIPE PI CHARGED AT
pay_xxxxxxxxxxxx my-web deploy $0.50 settled pi_3Rxxxxxxxxxxxxxxxxxxxxxxxx 2026-07-08T07:01:10ZFlags
| Flag | Default | Description |
|---|---|---|
--method | — | card or usdc (required for setup) |
--limit | 1.00 | Per-call spend limit in USD |
--action | deploy | Action being authorized: deploy, start, domain-add |
--limit | 20 | Records to return (history) |
Sandboxes
Sandboxes are ephemeral environments for short-lived experiments:
cpctl sandbox create # create a sandbox
cpctl sandbox list # list active sandboxes
cpctl sandbox destroy <id> # destroy a sandboxUtility
Open documentation
cpctl docsOpens docs.computeportal.io in your default browser.
Upgrade the CLI
cpctl upgradeFetches the latest binary from the CP API and atomically replaces the running binary.
current 0.1.14
latest 0.1.15
Downloading https://install.computeportal.io/releases/v0.1.15/cpctl-darwin-arm64...
✓ Upgraded to v0.1.15Version
cpctl version
# cpctl version v0.1.15Configuration Files
cp.json
The project configuration file, created by cpctl init:
{
"project": "my-inference-api",
"image": "myorg/inference:latest",
"region": "eu-west",
"replicas": 2,
"resources": {
"cpu": 4,
"memory": "16g",
"gpu": "rtx5090"
},
"env": {
"LOG_LEVEL": "info"
},
"domains": ["api.example.com"]
}When cpctl deploy is run without --image or --repo, it reads cp.json automatically.
.cp-link
Written by cpctl link and cpctl environment switch. Stores the linked service and active environment:
{
"service": "my-inference-api",
"environment": "production"
}Add .cp-link to .gitignore if different team members link different environments.
Environment Variables
| Variable | Description |
|---|---|
CP_API_TOKEN | API token — takes precedence over stored credentials |
CP_API_URL | Override the API base URL (for self-hosted or regional endpoints) |
CI/CD Integration
GitHub Actions
- name: Deploy to Compute Portal
env:
CP_API_TOKEN: ${{ secrets.CP_API_TOKEN }}
run: |
cp deploy --image ${{ env.IMAGE_TAG }} --region eu-westDocker build + deploy
docker build -t myorg/inference:$SHA .
docker push myorg/inference:$SHA
cpctl deploy --image myorg/inference:$SHABlue-green with rollback
cpctl deploy --image myorg/inference:v2.0.0
# Verify
cpctl status my-inference-api
# Roll back if needed
cpctl rollback my-inference-apiComplete Command Reference
| Command | Description |
|---|---|
cpctl login | Authenticate with Compute Portal |
cpctl logout | Log out and revoke credentials |
cpctl whoami | Show current authenticated user |
cpctl init | Interactively create cp.json |
cpctl link <service> | Link directory to a service |
cpctl unlink | Remove .cp-link |
cpctl open [service] | Open service URL in browser |
cpctl list | List all services |
cpctl deploy | Deploy a service |
cpctl redeploy <service> | Re-trigger current deployment |
cpctl rollback <service> [id] | Roll back to a previous deployment |
cpctl machine list | List services |
cpctl machine start <name> | Start a service |
cpctl machine stop <name> | Stop a service |
cpctl machine restart <name> | Restart a service |
cpctl machine destroy <name> | Permanently destroy a service |
cpctl machine status <name> | Show service health |
cpctl logs <name> | Stream service logs |
cpctl status <name> | Show platform health, or service status if a name is given |
cpctl scale <name> | Scale replicas or resources (--replicas, --cpu, --ram) |
cpctl exec <name> -- <cmd> | Run command inside container |
cpctl ssh <name> | Open interactive shell in container (alias: exec -- sh) |
cpctl ps <name> | List running processes |
cpctl env set <service> | Set environment variables |
cpctl env list <service> | List environment variables |
cpctl env unset <service> | Remove environment variables |
cpctl variable | Alias for cpctl env |
cpctl environment list | List environments |
cpctl environment create | Create an environment |
cpctl environment delete | Delete an environment |
cpctl environment switch | Switch active environment |
cpctl deployment list <service> | List deployment history |
cpctl deployment status <service> <id> | Show deployment details |
cpctl domain add <service> <domain> | Attach custom domain |
cpctl domain list <service> | List domains |
cpctl domain status <service> <domain> | Check domain/TLS status |
cpctl domain remove <service> <domain> | Remove domain |
cpctl volume list <service> | List volumes |
cpctl volume add <service> <path> | Attach a volume |
cpctl volume delete <service> <name> | Delete a volume |
cpctl db create <type> | Create a managed database |
cpctl db list | List databases |
cpctl db url <name> | Print connection URL |
cpctl db destroy <name> | Destroy a database |
cpctl connect <name> | Open interactive database shell |
cpctl metrics <service> | View service metrics |
cpctl gpu list | List GPU inventory |
cpctl gpu status <service> | Show GPU utilization |
cpctl gpu reserve | Reserve GPU capacity |
cpctl gpu run | Run a one-shot GPU job |
cpctl node list | List compute nodes |
cpctl node status <id> | Show node health |
cpctl region list | List regions |
cpctl host list | List hosts |
cpctl policy list | List scheduling policies |
cpctl billing usage | Show billing usage |
cpctl billing history | Show invoice history |
cpctl pay setup | Link a card or USDC wallet for machine payments |
cpctl pay status | Show linked payment method |
cpctl pay authorize <service> <amount> | Pre-authorize a per-call charge |
cpctl pay history | List per-call payment charges |
cpctl sandbox create | Create a sandbox |
cpctl sandbox list | List sandboxes |
cpctl sandbox destroy <id> | Destroy a sandbox |
cpctl docs | Open documentation in browser |
cpctl upgrade | Upgrade the CLI |
cpctl version | Print CLI version |