Serverless command runner
Run arbitrary commands on ephemeral containers in your cloud account — no complex setup required.
Deploy once, issue API keys, and let your team run arbitrary (admin) applications safely from their terminals. Share playbooks to perform common tasks consistently and reliably.
Workstations shouldn't need complex setups. Let remote containers execute commands in a secured and reproducible production-grade environment.
No more snowflakes, run envoys. ✨
🎯 Use cases
- ☁️ Cloud CLI operations — AWS CLI, Terraform, Ansible, or any SDK-based tools in remote containers with proper permissions (AWS CLI example)
- ⚙️ One-off commands — Run arbitrary commands as you would with
kubectl runwithout maintaining an always-running cluster. Example:runvoy run ping <my service ip> - 🏗️ Resource-intensive tasks — Builds, test runners and any other heavy workload which require a specific instance type. Tail and share logs in real-time like GitHub Actions (Build Caddy example)
- 🐢 Long-running tasks — Commands that may take a long time to complete like schema changes, data migrations, dump/restore operations, etc. (PostgreSQL restore example)
- 📝 Audit-required operations — Any command that needs a complete audit trail with user identification
- 🔐 Secure operations — Commands with environment variables secrets without exposing them to local workstations
📝 Example
runvoy run "uname -a"
🚀 runvoy run
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
→ Running command: uname -a
✓ Command execution started successfully
Execution ID: 010adbfb34374116b47c8d0faab2befa
Status: STARTING
Image ID: amazonlinux/amazonlinux:latest-d7ba6332
→ Execution status: STARTING
→ Execution is starting (logs usually ready after ~30 seconds)...
→ Connecting to log stream...
✓ Connected to log stream. Press Ctrl+C to exit.
Line Timestamp (UTC) Message
──── ─────────────────── ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
1 2025-11-19 17:30:54 ### runvoy runner execution started by requestID => f59378e3-01ed-4b44-a315-618951e048aa
2 2025-11-19 17:30:54 ### Image ID => amazonlinux/amazonlinux:latest-d7ba6332
3 2025-11-19 17:30:54 ### runvoy command => uname -a
4 2025-11-19 17:30:54 Linux ip-172-20-1-130.us-east-2.compute.internal 5.10.245-241.978.amzn2.aarch64 #1 SMP Fri Oct 31 17:59:47 UTC 2025 aarch64 aarch64 aarch64 GNU/Linux
→ Execution completed. Closing connection...
→ WebSocket connection closed
→ View logs in web viewer: https://runvoy.site/?execution_id=010adbfb34374116b47c8d0faab2befa
💡 What is Runvoy?
Runvoy is composed of 3 main parts:
- 🖥️ Backend — Runs on your AWS account (multi-cloud support planned), exposes the HTTP API, and orchestrates cloud resources. Deploy once as a cloud admin.
- ⌨️ CLI client — The
runvoycommand-line tool for interacting with the REST API - 🌐 Web app — Visit runvoy.site or self-host. Currently supports log viewing with full CLI parity coming soon.
Refer to Architecture for details.
✨ Key Benefits
-
🖥️ Doesn't run on your computer — Commands execute in remote production-grade environments with proper secrets access. Team members only need the
runvoyCLI and an API key — no complex workstation setup required. -
📊 Complete audit trail — Every backend interaction is logged with user identification. All logs stored in append-only database for compliance (CloudWatch Logs supported, more providers coming).
-
🔓 Self-hosted, no black magic — The backend runs in your cloud account. You control everything: policies, permissions, and data.
-
💰 Serverless — No always-running services. Pay only for the compute your commands consume (essentially free for infrequent use).
🎨 Features
- 🔑 API key authentication — Secure access with SHA-256 hashed API keys
- 👥 User access management — Role-based and ownership access control. Admins define permissions; users access only what they're allowed to
- 🐳 Customizable container roles — Register Docker images with custom roles for proper resource access (AWS ECS+IAM support, more coming soon)
- 📋 Native cloud logging — Full execution logs and audit trails with request ID tracking
- 📖 Reusable playbooks — Store command configs in YAML, commit them, and share with your team for consistent execution (Terraform example)
- 🔐 Secrets management — Centralized encrypted secrets with full CRUD operations from the CLI
- ⚡️ Real-time WebSocket streaming — Live logs delivered to CLI and web viewer via authenticated WebSocket connections
- 🔗 Automatic Git cloning — Clone private Git repos directly into container working directory (Build Caddy example)
- 🔧 Unix-style output streams — Separate CLI logs (stderr) from data (stdout) for easy piping and scripting
- 🏗️ IaC deployment — Deploy complete backend infrastructure with CloudFormation (multi-cloud support coming)
- 📦 Single binary — Download one ~6MB compressed binary, unzip it and run it. No dependencies, no installation hassle. Available for Linux, macOS and Windows.
🚧 Roadmap
- 🌍 Multi-cloud support — GCP, Azure...
- 📡 Robust log streaming — More reliable streaming mechanism (current implementation is lossy)
- ⏱️ Execution timeouts — Automatic SIGTERM for commands exceeding timeout
- 🔒 Lock management — Prevent concurrent execution conflicts
- 🌐 Full webapp parity — All CLI commands available in the web interface
- 🍺 Homebrew support — Native installation via Homebrew package manager
⚡️ Quick Start
Download the latest release from the releases page:
- Linux example:
curl -L -o runvoy-cli-linux-arm64.tar.gz https://github.com/runvoy/runvoy/releases/download/v0.2.0/runvoy_linux_amd64.tar.gz
tar -xzf runvoy_linux_amd64.tar.gz
sudo mv runvoy_linux_amd64/runvoy /usr/local/bin/runvoy
- macOS example:
curl -L -o runvoy_linux_amd64.tar.gz https://github.com/runvoy/runvoy/releases/download/v0.2.0/runvoy_darwin_arm64.tar.gz
tar -xzf runvoy_darwin_arm64.tar.gz
xattr -dr com.apple.quarantine runvoy_darwin_arm64/runvoy
codesign -s - --deep --force runvoy_darwin_arm64/runvoy
sudo mv runvoy_darwin_arm64/runvoy /usr/local/bin/runvoy
- Windows: Download the archive from the release page. Extract the
runvoy.exefile from the archive using a tool like 7-Zip
🏗️ Deploying the backend infrastructure
Requirements:
AWS credentials and region needs to be configured in your shell environment (AWS CLI settings docs), the user needs to have the AdministratorAccess and AmazonECS_FullAccess policies:
You can review the full list of resources and permissions required for the backend infrastructure in the released cloudformation-backend.yaml file
Bootstrap the backend infrastructure and seed the admin user:
runvoy infra apply --configure --seed-admin-user admin@example.com
👤 Creating a new user
The admin API key and endpoint are automatically configured in ~/.runvoy/config.yaml after deployment. Start using runvoy immediately:
# Register one image to be used as default, pick any image from any public registry
runvoy images register public.ecr.aws/docker/library/alpine:latest
# Run a test command
runvoy run "echo hello world"
or
runvoy users create <email> --role developer # or admin, operator, viewer
to create a new user account for a team member. This will generate a claim token that the user can use to claim their API key.
Important Notes:
- ⏱ Claim tokens expire after 15 minutes
- 👁 Each token can only be used once
📖 Usage
Available Commands
To see all available commands and their descriptions:
runvoy --help
runvoy - v0.2.0-20251124-5eb9969
Isolated, repeatable execution environments for your commands
Usage:
runvoy [command]
Available Commands:
claim Claim a user's API key
completion Generate the autocompletion script for the specified shell
configure Configure local environment with API key and endpoint URL
health Health and reconciliation commands
help Help about any command
images Docker images management commands
infra Infrastructure management commands
kill Kill a running command execution
list List command executions
logs Get logs for an execution
playbook Manage and execute playbooks
run Run a command
secrets Secrets management commands
status Get the status of a command execution
trace Get backend logs and related resources for a given request ID
users User management commands
version Show the version of the CLI
Flags:
--debug Enable debugging logs
-h, --help help for runvoy
--timeout string Timeout for command execution (e.g., 10m, 30s, 1h) (default "10m")
--verbose Verbose output
Use "runvoy [command] --help" for more information about a command.
See CLI commands Documentation for more details.
🔧 Output Streams and Piping
Runvoy follows Unix conventions by separating informational messages from data output, making it easy to pipe commands and script automation workflows:
- stderr (standard error): Runtime messages, progress indicators, and logs
- Informational messages (→, ✓, ⚠, ✗)
- Progress spinners and status updates
-
Headers and UI formatting
-
stdout (standard output): Actual data from API responses
- Tables, lists, and structured data
- Raw output for piping to other tools
Examples:
# Hide informational messages, show only data
runvoy list 2>/dev/null
# Hide data, show only logs/status messages
runvoy list >/dev/null
# Pipe data to another command (jq, grep, etc.)
runvoy list 2>/dev/null | grep "RUNNING"
# Redirect logs and data to separate files
runvoy list 2>status.log >executions.txt
# Pipe between runvoy commands
runvoy command1 2>/dev/null | runvoy command2
# Use in scripts with proper error handling
if runvoy status $EXEC_ID 2>/dev/null | grep -q "SUCCEEDED"; then
echo "Execution succeeded"
fi
This separation enables clean automation and integration with other Unix tools without mixing informational output with parseable data.
🌐 Web Viewer
The web viewer is a SvelteKit-based single-page application that provides:
- Real-time log streaming - Automatically get updates from the websocket API in real-time
- ANSI color support - Displays colored terminal output
- Status tracking - Shows execution status (RUNNING, SUCCEEDED, FAILED, STOPPED)
- Execution metadata - Displays execution ID, start time, and exit codes
- Interactive controls:
- Pause/Resume streaming
- Download logs as text file
- Clear display
- Toggle metadata (line numbers and timestamps)
Setup (first-time only):
- Open the web viewer URL in your browser
- Enter your API endpoint URL (same as in
~/.runvoy/config.yaml) - Enter your API key (same as in
~/.runvoy/config.yaml) - Settings are saved in browser's localStorage for future use
The web viewer is hosted on Netlify by default, but you can configure a custom URL if you deploy your own instance (see Configuration below).
Configuration:
The web application URL can be customized via:
- Environment variable:
RUNVOY_WEB_URL - Config file (
~/.runvoy/config.yaml):web_urlfield
If not configured, it defaults to https://runvoy.site/.
🏛️ Architecture
┌─────────────────┐ ┌─────────────────┐
│ CLI Client │ │ Web Viewer │
│ (runvoy) │ │ (browser) │
└────────┬────────┘ └────────┬────────┘
│ │
│ HTTPS (REST API) │ HTTPS (REST API)
│ WebSocket (logs) │ WebSocket (logs)
│ │
└────────────┬───────────────┘
│
┌────────────▼─────────────────────────┐
│ AWS Backend │
│ │
│ • Lambda Functions (Orchestrator, │
│ Event Processor) │
│ • DynamoDB (metadata storage) │
│ • ECS Fargate (command execution) │
│ • CloudWatch Logs (execution logs) │
│ • EventBridge (event routing) │
│ • API Gateway WebSocket (real-time) │
│ • SSM Parameter Store (secrets) │
└──────────────────────────────────────┘
For detailed architecture information, see ARCHITECTURE.
💭 The Story Behind Runvoy
As a software engineer, I frequently found myself needing to run admin commands — and more importantly, enabling my team to run those same commands without becoming a bottleneck. 🚧
I've always been fascinated by "thin clients" — delegating heavy lifting and security concerns to the server while keeping the client simple. Just "log in" and run the commands you're authorized to run. The server handles the rest. ✨
The final piece fell into place with AWS Lambda and the serverless revolution: "you only pay for what you use" is now a commodity in cloud computing. 💰
Full disclosure: I love building applications in Go, and this felt like the perfect opportunity to create something genuinely useful — not just for me and my colleagues, but for teams everywhere. 🛠️
🤝 Development
For development setup, workflow, and contributing guidelines, see CONTRIBUTING and CODE OF CONDUCT.
Contributions welcome! 🎉