Skip to main content

Remote development environment CLI

Project description

Remo

Spin up a fully-configured remote development environment in minutes. One command gives you a persistent, secure coding environment with Dev Containers support — perfect for long-running AI agents that keep working after you disconnect.

Installation

# From PyPI (recommended)
uv tool install remo-cli

# Or with pip
pip install remo-cli

# Initialize (installs Ansible collections)
remo init

Prerequisites

  • Python 3.11+
  • SSH key pair (~/.ssh/id_rsa)
  • uv (recommended) or pip

Shell completion (optional)

Tab completion for subcommands, flags, and known instance/container names is available for bash, zsh, and fish:

# bash
remo completion bash >> ~/.bashrc

# zsh
remo completion zsh >> ~/.zshrc

# fish
remo completion fish > ~/.config/fish/completions/remo.fish

After re-loading your shell, remo proxmox info --name <TAB> will suggest registered container names from your known_hosts registry.


Quick Start

remo hetzner create             # Provision a VM (or: remo aws create / remo incus create / remo proxmox create)
remo shell                      # Connect to your environment

You land in an interactive project menu. Pick a project, and you're in a persistent Zellij session with your DevContainer already running. Disconnect anytime — your session survives.

  Remote Coding Server
  --------------------

> my-project - active
  another-project
  [Clone new repo]
  [Exit to shell]

Choose Your Platform

Hetzner Cloud AWS Incus Proxmox
Type Cloud VM Cloud VM Local container Local container
Location EU/US datacenters Global regions Your hardware Your hardware
Cost ~€4/month $30/month ($10 spot) Your electricity Your electricity
Storage Block volume EBS / root volume Host mounts LVM / ZFS / dir
Access Server IP SSM (no inbound ports) or SSH LAN hostname LAN IP
Best for EU, budget hosting US, enterprise, spot instances Local dev, homelab Proxmox homelab

All platforms give you the same dev workflow and tooling described below.


The Dev Workflow

Persistent Sessions

Zellij keeps your terminal sessions alive across SSH disconnects:

  • Detach: Ctrl+d returns to the project menu
  • Reconnect: SSH back in, select the same project to resume exactly where you left off

Project Menu

The fzf-powered menu shows your projects from ~/projects:

  • Arrow keys or 1-9: Select a project
  • Enter: Launch/attach to the project's Zellij session
  • c: Clone a new repository
  • x: Exit to shell

Jump Straight to a Project

Skip the menu and land directly in a project (devcontainer auto-launches):

remo shell -p my-app

Run a one-shot command inside the project's devcontainer instead of opening a shell — quote the command as a single string:

remo shell -p my-app --exec 'pytest -x'
remo shell -p my-app --exec 'claude --remote-control'

Fire-and-forget — kick off a command on the remote and exit SSH immediately:

remo shell -p my-app --detach --exec 'claude remote-control --name remo-rc'
remo shell -p my-app --detach --exec './long-build.sh'

Detached output is captured to ~/.local/state/remo/<project>.log on the remote, so you can tail it later (remo shell -p my-app --exec 'tail -f ~/.local/state/remo/my-app.log'). The command's environment gets REMO_INSTANCE and REMO_PROJECT exported automatically — handy for deterministic naming, e.g.:

remo shell -p my-app --detach --exec \
  'claude remote-control --name "remo-$REMO_INSTANCE-$REMO_PROJECT"'

Then on your phone, open claude.ai/code and pick the session by name.

Port Forwarding

Forward remote ports to your local machine during SSH sessions:

remo shell -L 8080                  # Forward remote :8080 to local :8080
remo shell -L 9000:8080             # Forward remote :8080 to local :9000
remo shell -L 8080 -L 3000          # Forward multiple ports
remo shell -L 8080 --no-open        # Skip auto-opening browser

Web ports automatically open in your browser when the tunnel is established.

File Transfer

Copy files between your local machine and any remote environment:

remo cp ./file.txt :/tmp/           # Upload
remo cp :/var/log/app.log ./        # Download
remo cp -r ./my-dir :/home/remo/    # Recursive upload
remo cp --progress big-file.tar :/tmp/  # Show transfer progress

Uses colon notation — a bare :path targets your default environment, or name:path for a specific one.

Version Checking

Remo checks that your local CLI and remote environment are running compatible versions before connecting. If the remote is behind, you'll be prompted to update it. Use --no-update-check to skip.


What's Installed

Every remo environment includes:

Tool Description
Docker + Compose Official Docker CE with compose plugin
Dev Containers CLI devcontainer up, devcontainer exec, etc.
Node.js 24 LTS From NodeSource repository
GitHub CLI gh for GitHub workflow integration
Zellij Terminal multiplexer for persistent sessions
fzf Fuzzy finder powering the project menu (server-side)

Snapshots

Capture a point-in-time copy of an instance before a risky change, then roll back if it breaks. Available on every provider, with the same command surface:

remo <provider> snapshot create <instance> [--name NAME] [--description TEXT]
remo <provider> snapshot list    [INSTANCE]
remo <provider> snapshot restore <instance> <snapshot> [-y]
remo <provider> snapshot delete  <instance> <snapshot> [-y]

--name defaults to remo-YYYYMMDD-HHMMSS. -y / --yes bypasses the confirm prompt on destructive operations.

Provider Create Restore Notes
Incus seconds in-place rollback (container stopped briefly) Free; uses native incus snapshot.
Proxmox seconds in-place rollback (container stopped briefly) Free; requires snapshot-capable rootfs storage (ZFS, LVM-thin, Btrfs, Ceph, NFS, CIFS). dir storage is rejected pre-flight.
AWS async — several minutes in-place EBS volume swap; stops the instance, swaps the root volume, restarts. Typically 2-5 min downtime. Costs $ per GB-month in EBS. Pre-restore root volume is preserved as a tagged orphan — delete it manually once you've verified the restore.
Hetzner async — several minutes server rebuild from the snapshot image, in-place. Typically 1-2 min downtime. Costs € per GB-month.

remo does not estimate storage cost — check your provider's billing console.

The destroy command on each provider checks for existing snapshots first and offers to clean them up. Decline and the snapshots remain (you'll be warned they continue to incur storage costs on AWS/Hetzner).

CLI Reference

# Connect to environment
remo shell                          # Auto-connect (or picker if multiple)
remo shell my-env                   # Connect to a specific environment
remo shell -p my-app                # Skip the menu, jump to ~/projects/my-app
remo shell -p my-app --exec 'pytest -x'              # Run command in devcontainer
remo shell -p my-app --detach --exec 'claude remote-control --name rc'  # Fire and exit
remo shell -L 8080                  # Shell + forward remote :8080 to local :8080
remo shell -L 9000:8080             # Shell + forward remote :8080 to local :9000
remo shell -L 8080 -L 3000          # Shell + forward multiple ports
remo shell -L 8080 --no-open        # Skip auto-opening browser
remo shell --no-update-check        # Skip version check

# File transfer
remo cp ./file.txt :/tmp/           # Upload file
remo cp :/var/log/app.log ./        # Download file
remo cp -r ./dir :/home/remo/       # Recursive copy
remo cp --progress big.tar :/tmp/   # Show progress

# Setup
remo init                           # Install Ansible collections

# Hetzner Cloud
remo hetzner create                 # Provision VM
remo hetzner list                   # List registered VMs
remo hetzner info [--name N]        # Show type, cores, memory, volume size
remo hetzner sync                   # Discover existing VMs
remo hetzner update                 # Update dev tools
remo hetzner update --volume-size 100   # Grow persistent volume + FS
remo hetzner destroy [--yes]        # Tear down (keeps volume)

# AWS (SSM access — no inbound ports)
remo aws create                     # Provision EC2 via SSM
remo aws create --spot              # Use spot instance (~70% savings)
remo aws list                       # List registered instances
remo aws sync                       # Discover existing instances
remo aws update                     # Update dev tools
remo aws update --volume-size 100   # Grow EBS volume + FS in place
remo aws stop [--yes]               # Stop instance (pause billing)
remo aws start                      # Start a stopped instance
remo aws reboot                     # Reboot instance
remo aws destroy [--yes]            # Tear down (keeps storage)
remo aws info [--name N]            # Show type, cores, memory, EBS size

# Incus Containers
remo incus create --name <n> [--host H]  # Create container
remo incus list                     # List registered containers
remo incus info --name <n>          # Show cores, memory, root size
remo incus sync [--host H]          # Discover existing containers
remo incus update --name <n>        # Update dev tools
remo incus update --name <n> --volume-size 40 --cores 4 --memory 4096
remo incus destroy --name <n> [--yes]    # Destroy container
remo incus bootstrap                # Initialize Incus on host

# Proxmox VE LXC Containers
remo proxmox create --name <n> --host <node>  # Create LXC container
remo proxmox list                   # List registered containers
remo proxmox info --name <n>        # Show cores, memory, rootfs size
remo proxmox sync --host <node>     # Discover existing containers
remo proxmox update --name <n>      # Update dev tools
remo proxmox update --name <n> --volume-size 40 --cores 4 --memory 4096
remo proxmox destroy --name <n> [--yes] [--purge]   # Destroy container
remo proxmox bootstrap --host <node>  # Verify node + download LXC template

# Snapshots (all four providers)
remo <provider> snapshot create <instance>                       # Auto-named
remo <provider> snapshot create <instance> --name pre-x --description "before upgrade"
remo <provider> snapshot list                                    # All instances
remo <provider> snapshot list <instance>                         # One instance
remo <provider> snapshot restore <instance> <snap-name> [-y]     # In-place rollback
remo <provider> snapshot delete <instance> <snap-name> [-y]      # Remove
# `<provider> destroy` will list existing snapshots and offer to clean them up first.

# Updates
uv tool upgrade remo-cli            # Update CLI to latest version
remo <platform> update              # Update dev tools on remote

# Help
remo --help
remo <command> --help

# Shell completion
remo completion bash                # Print bash activation script (also: zsh, fish)

See platform-specific docs for full options:

Environment Variables

Variable Description
REMO_HOME Config directory for remo state (default: ~/.config/remo)
REMO_DEVCONTAINER_RUNTIME Default devcontainer runtime for new deployments: devcontainer (default) or deacon (experimental). Overridden per-deployment by --devcontainer-runtime. See Proxmox docs.

Web Session Interface

Don't have the remo CLI or an SSH setup on the device in front of you? remo web runs a small home-lab Docker service that discovers every project across all of your registered instances (Proxmox, AWS, Hetzner, Incus) and streams a real interactive terminal to any browser — no local CLI, no SSH keys on the client. It connects to your instances server-to-instance over SSH, the same way the CLI does, and attaches to the exact same persistent Zellij/devcontainer session remo shell would.

⚠️ Security boundary: remo web is a single-trusted-user MVP with no login. Anyone who can reach the service can open a shell on every instance in your registry. There is no authentication, no per-user isolation, and no public-internet exposure story. Bind it only to a trusted LAN interface, a Tailscale/tailnet address, or a loopback reverse proxy — never expose it to the public internet.

Quick install

uv sync --extra web             # installs the FastAPI/Uvicorn web extra (not part of the normal CLI)
uv run remo web check           # validates registry, SSH identity, runtime dir, executables, reachability
uv run remo web serve --host 127.0.0.1 --port 8080   # local dev

For a home-lab install, use Docker Compose — see docker/compose.example.yml for a ready-to-adapt file covering both deployment modes (tmpfs runtime dir, healthcheck, non-root/read-only hardening in either case):

  • Bind-mount mode: mount your existing registry and SSH key read-only — the container runs with your identity, on the same box as your config.
  • Adopted mode: mount nothing. The container generates its own SSH identity in a writable state volume, and a single remo web adopt from your workstation pushes your registry and authorizes that identity on every instance — your personal private key never leaves the workstation (remo web push re-syncs later changes).

Full architecture, security model, Compose walkthrough, adoption workflow, credentials/SSM setup, discovery states, terminal limits, troubleshooting, and upgrade notes: docs/web-session-interface.md.


Troubleshooting

Installed remo on a new machine with existing instances?

remo aws sync                          # Discover AWS instances with 'remo' tag
remo hetzner sync                      # Discover Hetzner VMs with 'remo' label
remo incus sync                        # Discover Incus containers
remo proxmox sync --host <node>        # Discover Proxmox LXC containers

SSH connection fails?

ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa

Ansible collection not found?

remo init  # Reinstalls dependencies

Platform-specific issues? See troubleshooting sections in:


Uninstalling

# Remove the CLI
uv tool uninstall remo-cli      # or: pip uninstall remo-cli

# Remove remo config and state
rm -rf ~/.config/remo
Path Contents
~/.config/remo/ Runtime state: known_hosts (environment registry)

Note: Uninstalling remo does not destroy any cloud resources (EC2 instances, Hetzner VMs, Incus or Proxmox containers). Run remo <platform> destroy first if you want to tear those down.


License

MIT License - see LICENSE file for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

remo_cli-2.2.0rc9.tar.gz (1.8 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

remo_cli-2.2.0rc9-py3-none-any.whl (283.5 kB view details)

Uploaded Python 3

File details

Details for the file remo_cli-2.2.0rc9.tar.gz.

File metadata

  • Download URL: remo_cli-2.2.0rc9.tar.gz
  • Upload date:
  • Size: 1.8 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for remo_cli-2.2.0rc9.tar.gz
Algorithm Hash digest
SHA256 74f8f2e9401d95d93437fc725c846214c5a6b79c745c3fde8c82d73909c7b4cc
MD5 072d36cce6783d400c0fd33ffe3b28da
BLAKE2b-256 6336665b175612af78c232ad9ea29b7c58aa601507c1c79f2d11b0304723b57e

See more details on using hashes here.

Provenance

The following attestation bundles were made for remo_cli-2.2.0rc9.tar.gz:

Publisher: release.yml on get2knowio/remo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file remo_cli-2.2.0rc9-py3-none-any.whl.

File metadata

  • Download URL: remo_cli-2.2.0rc9-py3-none-any.whl
  • Upload date:
  • Size: 283.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for remo_cli-2.2.0rc9-py3-none-any.whl
Algorithm Hash digest
SHA256 4d753607d25f1e50fb40ca1b20c39e34909a9b7b34efae4acfbf45f3c3c9a336
MD5 009e0f765faa2abf24fc2eec7d427881
BLAKE2b-256 324b366d47f170096bf0d12c97f945e09484e9aacbbedaec8e309b580efc0e48

See more details on using hashes here.

Provenance

The following attestation bundles were made for remo_cli-2.2.0rc9-py3-none-any.whl:

Publisher: release.yml on get2knowio/remo

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page