Deploy, manage, and SSH into your VPS instances from the command line. Available for macOS, Linux, and Windows.
Get up and running in 3 commands:
# Install via Homebrew
brew install hostodo/tap/odo
# Login to your account
odo login
# List your instances and SSH in
odo list
odo ssh my-server
The recommended way to install the Hostodo CLI:
# Add the Hostodo tap and install
brew tap hostodo/tap
brew install hostodo/tap/odo
# Or install directly
brew install hostodo/tap/odo
Download binaries from the releases page. Available for macOS (Intel & Apple Silicon), Linux (amd64, arm64), and Windows (amd64).
# macOS (Apple Silicon)
curl -L https://github.com/hostodo/odo-cli/releases/latest/download/odo_Darwin_arm64.tar.gz | tar xz
sudo mv odo /usr/local/bin/
# Linux (amd64)
curl -L https://github.com/hostodo/odo-cli/releases/latest/download/odo_Linux_x86_64.tar.gz | tar xz
sudo mv odo /usr/local/bin/
# Debian / Ubuntu
wget https://github.com/hostodo/odo-cli/releases/latest/download/odo_Linux_x86_64.deb
sudo dpkg -i odo_Linux_x86_64.deb
# RHEL / CentOS / Fedora
wget https://github.com/hostodo/odo-cli/releases/latest/download/odo_Linux_x86_64.rpm
sudo rpm -i odo_Linux_x86_64.rpm
Requires Go 1.24 or higher:
git clone https://github.com/hostodo/odo-cli.git
cd odo-cli
make install
The CLI uses OAuth device flow for secure authentication. When you run odo login, a browser window opens where you authorize the CLI with your Hostodo account. Your tokens are securely stored in the OS keychain (macOS Keychain, Linux Secret Service) with an encrypted file fallback.
odo login
This opens your default browser to authorize the CLI. Once approved, you're authenticated and ready to go.
| Flag | Description |
|---|---|
--api-url | Use a custom API URL (default: https://api.hostodo.com) |
Clear stored credentials:
odo logout
Display information about the authenticated user:
odo whoami
View your active CLI sessions:
odo auth sessions
Security: Tokens are stored in the OS keychain, never in plain-text config files. The config file (~/.odo/config.json) only stores the API URL and device ID. File permissions are set to 0600 automatically.
List all your VPS instances. Aliases: ls, ps.
# Interactive TUI (default)
odo list
# JSON output for scripting
odo list --json
# Simple ASCII table
odo list --simple
# Detailed view with all info
odo list --details
| Flag | Description |
|---|---|
--json | Output as JSON |
--simple | Output as simple ASCII table |
--details | Show detailed information |
--limit | Max instances to fetch (default: 100) |
--offset | Offset for pagination (default: 0) |
The default interactive TUI supports keyboard navigation:
↑ / ↓ or j / k — Navigate through instancesEnter — View detailed instance informationq or Esc — QuitGet detailed information about a specific instance:
odo status my-server
odo status my-server --json
Displays basic info, network configuration, resource allocation (RAM, CPU, disk, bandwidth), plan details, billing information, and timestamps.
Example output:
Start a stopped instance. Waits up to 30 seconds for the instance to boot:
odo start my-server
Stop a running instance. Waits up to 60 seconds for graceful shutdown:
# Graceful shutdown
odo stop my-server
# Force immediate shutdown
odo stop my-server --force
Restart an instance. Waits up to 90 seconds:
# Graceful restart
odo restart my-server
# Force restart
odo restart my-server --force
| Flag | Applies To | Description |
|---|---|---|
-f, --force | stop, restart | Force immediate shutdown without graceful stop |
Connect to an instance via SSH. The CLI uses the system ssh binary and auto-detects the SSH user from the instance's OS template. If key-based auth fails and the instance has a default password, it automatically retries with sshpass.
# SSH with auto-detected user
odo ssh my-server
# Specify a different user
odo ssh my-server --user ubuntu
| Flag | Description |
|---|---|
-u, --user | SSH user (default: auto-detected from OS template) |
All instance commands accept hostnames as the primary identifier. The CLI resolves hostnames using a three-step fallback:
my-server)my-s resolves to my-server if unique)ins::abc123)Tab completion for hostnames is available when shell completions are enabled.
Deploy a new VPS instance with an interactive wizard or by passing flags. Aliases: new, create.
Run odo deploy without flags for a guided experience. The wizard walks you through selecting an OS template, region, plan, hostname, and optional SSH key.
odo deploy
Skip prompts by passing flags:
# Deploy with specific options
odo deploy --os "Ubuntu 22.04" --region "Los Angeles" --plan KVM-2G
# Custom hostname
odo deploy --hostname my-server
# Skip confirmation
odo deploy --os "Ubuntu 22.04" --region "Los Angeles" --plan KVM-2G --yes
# JSON output (requires --os, --region, --plan)
odo deploy --os "Ubuntu 22.04" --region "Los Angeles" --plan KVM-2G --json
| Flag | Description |
|---|---|
--os | OS template name (skips OS prompt) |
--region | Region name (skips region prompt) |
--plan | Plan name (skips plan prompt) |
--hostname | Custom hostname (skips auto-generation) |
--ssh-key | SSH key name to use for authentication |
-y, --yes | Skip confirmation prompt |
--json | JSON output (requires --os, --region, --plan) |
List your invoices with optional filtering. Alias: bills.
# List all invoices
odo invoices
# Show only unpaid invoices
odo invoices --status=unpaid
| Flag | Description |
|---|---|
--status | Filter by status (e.g., unpaid) |
Pay an invoice by its ID:
odo pay INV-12345
odo keys list
# Add key inline
odo keys add mykey "ssh-rsa AAAAB3NzaC1yc2EAAA... user@host"
# Add key from file
odo keys add mykey --file ~/.ssh/id_rsa.pub
| Flag | Description |
|---|---|
-f, --file | Read public key from file |
odo keys remove mykey
Commands that display data support multiple output modes:
A keyboard-navigable, color-coded table that adapts to your terminal size. Use arrow keys or j/k to navigate, Enter to view details.
--json)Structured JSON output, perfect for scripting and piping to tools like jq:
# Get running instances as JSON
odo list --json | jq '.[] | select(.status == "running")'
--simple)Clean ASCII table for quick viewing or piping:
--details)Comprehensive, human-readable output per instance:
Configuration is stored at ~/.odo/config.json:
{
"api_url": "https://api.hostodo.com",
"device_id": "a1b2c3d4-..."
}
Access tokens are stored separately in the OS keychain, with an AES-encrypted file fallback at ~/.odo/token.enc when no keychain is available.
Permissions: Config file permissions are automatically set to 0600 (owner read/write only) and directory permissions to 0700.
| Variable | Description |
|---|---|
HOSTODO_API_URL | Override the default API URL |
HOME | Used to locate the config directory |
# Use a custom API endpoint
export HOSTODO_API_URL=https://custom-api.example.com
odo login
Generate completion scripts for your shell. This enables tab-completion for commands and hostnames.
# Bash
odo completion bash > /etc/bash_completion.d/odo
# Zsh
odo completion zsh > "${fpath[1]}/_odo"
# Fish
odo completion fish > ~/.config/fish/completions/odo.fish
All commands support these flags:
| Flag | Description |
|---|---|
--api-url | API URL (default: https://api.hostodo.com or $HOSTODO_API_URL) |
--config | Config file path (default: $HOME/.odo/config.json) |
-h, --help | Show help for any command |
-v, --version | Show CLI version |