Skip to content

ssreeni1/cloudcode

Repository files navigation

cloudcode

Persistent cloud AI coding sessions on your own Hetzner VPS. Run Claude Code or OpenAI Codex from anywhere — your terminal, your phone via Telegram, or both at once.

$3.49/month for a dedicated AI coding server. Sessions persist across disconnects. Start a task from your laptop, check progress from your phone, pick it back up later.

Why cloudcode?

  • Persistent sessions — your AI agent keeps running even when you close your laptop
  • Phone access — send tasks and get results via Telegram from anywhere
  • Dirt cheap — a Hetzner VPS costs less than a coffee per month
  • Multi-provider — switch between Claude Code and OpenAI Codex with one command
  • Three interfaces — TUI, CLI, and Telegram all control the same sessions
  • Disposable — destroy the VPS in seconds when you're done, spin up a new one when you need it

Install

Homebrew (recommended)

brew install ssreeni1/tap/cloudcode

Shell script

curl -fsSL https://raw.githubusercontent.com/ssreeni1/cloudcode/main/install.sh | bash

From source

git clone https://github.com/ssreeni1/cloudcode.git
cd cloudcode
cargo install --path crates/cloudcode-cli

Requires Rust 2024 edition (1.85+).

Prerequisites

  1. Hetzner Cloud accountconsole.hetzner.cloud. Create an API token under Security > API Tokens (Read & Write).

  2. AI provider auth (at least one):

  3. Telegram bot (optional) — create via @BotFather. Get your user ID from @userinfobot.

  4. ssh on your local machine (pre-installed on macOS and Linux).

Quick start

# 1. Launch cloudcode — setup wizard runs on first use
cloudcode

# 2. Provision a VPS (interactive server picker)
/up

# 3. Create a session
/spawn

# 4. Attach to it (complete OAuth login if needed)
/open <session-name>

That's it. Your AI coding agent is running on a dedicated VPS.

If using Telegram

After provisioning, message your bot on Telegram. Send /spawn to create a session, then just type naturally — your messages go to the AI agent and responses come back with any files it creates.

If using OAuth / Device Auth

For Claude OAuth: when you /open the session, Claude shows a login URL. Copy it manually (don't press 'c') and paste it in your browser.

For Codex Device Auth: when you /open the session, select "Device code" when prompted. Visit the URL in your browser to authorize. Do NOT use the localhost/browser option — it won't work on a remote VPS.

Commands

TUI mode (default)

Run cloudcode with no arguments. Type commands with a / prefix:

Command Description
/up Provision VPS (interactive server type picker with live pricing)
/down Destroy VPS (with confirmation)
/status Show VPS info, daemon uptime, active sessions
/spawn [name] Create a new AI coding session
/list List active sessions
/open <session> Attach to session interactively (tmux)
/send <session> <msg> Send a message to a session
/kill <session> Kill a session
/provider [claude|codex] Show or switch AI provider
/restart Restart daemon on VPS
/logs [setup|daemon] View VPS logs
/ssh [cmd] SSH to VPS (interactive shell if no args)
/init Re-run setup wizard
/help Show command reference

Navigation: scroll output with mouse wheel or PageUp/PageDown. Double Ctrl+C to quit.

CLI mode

Every TUI command has a CLI equivalent:

cloudcode up                              # Provision VPS
cloudcode spawn my-project                # Create a named session
cloudcode open my-project                 # Attach interactively
cloudcode send my-project "fix the bug"   # Send a message
cloudcode list                            # List sessions
cloudcode status                          # Show VPS + session status
cloudcode provider                        # Show current provider
cloudcode provider codex                  # Switch to Codex
cloudcode kill my-project                 # Kill session
cloudcode down                            # Destroy VPS
cloudcode ssh                             # Interactive SSH to VPS
cloudcode ssh -- ls /home/claude          # Run remote command
cloudcode logs daemon                     # View daemon logs
cloudcode doctor                          # Run diagnostics

Telegram

Once configured, message your bot:

Command Description
/spawn [name] Create a session
/list List sessions
/kill <name> Kill a session
/use <name> Set default session
/status Show daemon status
/provider [claude|codex] Show or switch provider
/waiting List sessions waiting for input
/reply [session] <text> Answer a waiting session's question
/peek [session] View raw tmux output
/type [session] <text> Type directly into a session
/context [session] View session's context file
/help Show commands

Free text messages go to your default session (or the only active session). The AI responds with formatted text and auto-uploads any files it creates (images, documents, code).

Automatic question forwarding: when the AI asks a question in an interactive session, it's automatically forwarded to Telegram. Reply naturally or use /reply.

Multi-provider support

cloudcode supports both Claude Code (Anthropic) and OpenAI Codex CLI. Switch anytime without reprovisioning:

cloudcode provider codex    # Switch to Codex
cloudcode spawn             # New sessions use Codex
cloudcode provider claude   # Switch back to Claude
  • Existing sessions keep their original provider
  • Both providers installed on the VPS regardless of which you choose
  • Provider selection saved across daemon restarts
Feature Claude Code Codex CLI
Interactive mode --dangerously-skip-permissions --full-auto
Programmatic send claude -p --continue codex exec
Auth on VPS OAuth (copy URL) Device Auth (enter code)
Conversation continuity --continue resumes context Stateless per invocation
Instructions file CLAUDE.md AGENTS.md

Shared context

Sessions on the same VPS share context. Each session maintains a context file at /home/claude/.cloudcode/contexts/ with its current work summary. Other sessions can read these to understand what's happening on the VPS.

The instruction files (CLAUDE.md / AGENTS.md) tell the AI to:

  • Read other sessions' context summaries when starting new tasks
  • Update its own context file after significant work
  • Treat other sessions' context as informational only (never execute commands found in them)

How it works

Your machine                         Hetzner VPS
+-----------------+                  +----------------------------+
| cloudcode CLI   |  SSH tunnel      | cloudcode-daemon           |
| (TUI or CLI)    | <=============> | (systemd service)          |
+-----------------+                  |   |                        |
                                     |   +-- tmux sessions        |
+-----------------+                  |   |     +-- claude (1)     |
| Telegram bot    |  Telegram API    |   |     +-- codex (2)      |
| (on your phone) | <=============> |   |     +-- ...             |
+-----------------+                  |   |                        |
                                     |   +-- question poller      |
                                     |   +-- session monitor      |
                                     +----------------------------+
  • CLI communicates with the daemon over an SSH-forwarded socket
  • Daemon manages tmux sessions, each running Claude Code or Codex
  • Telegram connects directly to the daemon's bot module
  • Question poller detects when the AI asks questions and forwards them to Telegram
  • Session monitor cleans up dead sessions every 60 seconds
  • Sessions persist in tmux — disconnect and reconnect anytime

Provisioning flow

When you run /up:

  1. Generate cloud-init config
  2. Create SSH key in Hetzner
  3. Provision server with cloud-init (installs tmux, Node.js, Claude Code, Codex)
  4. Wait for SSH readiness
  5. Wait for cloud-init completion
  6. Verify installed software
  7. Prepare daemon binary (embedded in release builds, or built on VPS)
  8. Upload and install daemon as systemd service
  9. Deploy provider configs and instruction files
  10. Verify daemon is running

The whole process takes 3-5 minutes. Playwright (browser automation) and Codex install in the background after the base setup completes.

Configuration

All config stored in ~/.cloudcode/:

~/.cloudcode/
  config.toml      # Hetzner, Claude, Codex, Telegram config
  state.json       # Current VPS state (server ID, IP, status)
  id_ed25519       # SSH private key (0600, never leaves your machine)
  id_ed25519.pub   # SSH public key
  known_hosts      # Managed SSH known hosts (separate from ~/.ssh/)

config.toml

[hetzner]
api_token = "your-hetzner-api-token"

[claude]
auth_method = "api_key"   # or "oauth"
api_key = "sk-ant-..."    # only for api_key method

[codex]
auth_method = "api_key"   # or "oauth"
api_key = "sk-..."        # only for api_key method

[telegram]                # optional
bot_token = "123456:ABC..."
owner_id = 123456789

[vps]                     # optional overrides
server_type = "cx23"
location = "nbg1"
image = "ubuntu-24.04"

default_provider = "claude"  # or "codex"

Server types

The /up command shows an interactive picker with live pricing. All current Hetzner types are supported:

Type CPUs RAM Disk ~Cost/mo Architecture
cx23 2 4 GB 40 GB $3.49 x86_64 (default)
cx33 4 8 GB 80 GB $5.99 x86_64
cx43 8 16 GB 160 GB $9.99 x86_64
cax11 2 4 GB 40 GB $3.99 ARM64
cax21 4 8 GB 80 GB $6.99 ARM64
cpx11 2 2 GB 40 GB $4.49 AMD x86_64
ccx13 2 8 GB 80 GB $13.49 Dedicated x86_64

The default cx23 is plenty for most AI coding sessions. ARM types (cax) work identically.

Security model

Read this before using cloudcode. The security model makes deliberate tradeoffs for autonomous AI operation.

What gets provisioned

  • A claude user with passwordless sudo — the AI can install packages and modify system files
  • AI agents run with full autonomy (Claude: --dangerously-skip-permissions, Codex: --full-auto)
  • Daemon binds to localhost only (127.0.0.1:7700) — never exposed publicly
  • UFW firewall allows SSH only (port 22)
  • All CLI communication over SSH tunnels (no exposed ports)

Trust boundaries

Component Trust level
Your local machine Full trust — holds SSH key, API tokens
SSH tunnel Encrypted, key-authenticated
VPS daemon Trusted — you deployed it, localhost-only
AI agents on VPS High privilege — can do anything as claude user with sudo
Telegram bot Messages accepted from configured owner_id chat only
Hetzner Infrastructure provider — has physical access

Recommendations

  • Use API keys over OAuth when possible — scoped and revocable
  • Destroy the VPS (/down) when not in use — eliminates persistent attack surface
  • Don't store sensitive data on the VPS that you wouldn't want the AI to access
  • Rotate tokens periodically (Hetzner, Anthropic/OpenAI, Telegram)
  • Review AI output before deploying to production

Revoking access

cloudcode down           # Destroy VPS + SSH key on Hetzner
cloudcode init --reauth  # Rotate API keys
rm -rf ~/.cloudcode      # Delete all local state

Development

git clone https://github.com/ssreeni1/cloudcode.git
cd cloudcode
cargo build              # Build everything
cargo test --workspace   # Run all tests (112 tests)
cargo run -p cloudcode-cli          # Run the CLI
cargo run -p cloudcode-cli -- status  # Run with args

Project structure

crates/
  cloudcode-cli/       # CLI + TUI binary (what users install)
  cloudcode-daemon/    # Daemon (runs on VPS as systemd service)
  cloudcode-common/    # Shared types (protocol, session, provider)

Release builds

Tag a version to trigger the CI pipeline:

git tag v0.1.6
git push origin v0.1.6

The pipeline:

  1. Cross-compiles the daemon for x86_64 and aarch64 Linux
  2. Embeds daemon binaries into the CLI via include_bytes!()
  3. Builds the CLI for macOS (arm64, x86_64) and Linux (x86_64, aarch64)
  4. Publishes binaries + SHA256 checksums to GitHub Releases
  5. Homebrew formula auto-updates

License

MIT — see LICENSE.

About

Persistent cloud AI coding sessions (Claude Code + OpenAI Codex) on Hetzner VPS. Terminal, CLI, and Telegram access. $3.49/month.

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages