{"id":46654822,"url":"https://github.com/runvoy/runvoy","last_synced_at":"2026-03-08T07:31:55.294Z","repository":{"id":325147057,"uuid":"1084514815","full_name":"runvoy/runvoy","owner":"runvoy","description":"Serverless command runner","archived":false,"fork":false,"pushed_at":"2025-12-24T21:01:11.000Z","size":65857,"stargazers_count":14,"open_issues_count":21,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-12-26T09:06:30.583Z","etag":null,"topics":["admin-tool","cli","cloudcomputing","containers","devops","fargate","golang","serverless","sre","terraform"],"latest_commit_sha":null,"homepage":"https://runvoy.site/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/runvoy.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-10-27T19:32:35.000Z","updated_at":"2025-12-24T21:01:15.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/runvoy/runvoy","commit_stats":null,"previous_names":["runvoy/runvoy"],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/runvoy/runvoy","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runvoy%2Frunvoy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runvoy%2Frunvoy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runvoy%2Frunvoy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runvoy%2Frunvoy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/runvoy","download_url":"https://codeload.github.com/runvoy/runvoy/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/runvoy%2Frunvoy/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30248873,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T05:41:50.788Z","status":"ssl_error","status_checked_at":"2026-03-08T05:41:39.075Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["admin-tool","cli","cloudcomputing","containers","devops","fargate","golang","serverless","sre","terraform"],"created_at":"2026-03-08T07:31:52.346Z","updated_at":"2026-03-08T07:31:55.279Z","avatar_url":"https://github.com/runvoy.png","language":"Go","readme":"\u003ch1 align=\"center\"\u003e\n    \u003cp\u003e\n      \u003cimg src=\"https://raw.githubusercontent.com/runvoy/runvoy/refs/heads/main/cmd/webapp/static/runvoy-banner.png\" alt=\"🚀 Runvoy\" width=\"50%\" /\u003e\n    \u003c/p\u003e\n    \u003cp\u003eServerless command runner\u003c/p\u003e\n\u003c/h1\u003e\n\u003cp align=\"center\"\u003e\n    \u003cem\u003eRun arbitrary commands on ephemeral containers in your cloud account — no complex setup required.\u003c/em\u003e\n\u003c/p\u003e\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://github.com/runvoy/runvoy/actions/workflows/tests-and-coverage-go.yml\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://github.com/runvoy/runvoy/actions/workflows/tests-and-coverage-go.yml/badge.svg?event=push\u0026branch=main\" alt=\"Tests (Go)\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/runvoy/runvoy/actions/workflows/tests-and-coverage-svelte.yml\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://github.com/runvoy/runvoy/actions/workflows/tests-and-coverage-svelte.yml/badge.svg?event=push\u0026branch=main\" alt=\"Tests (Svelte)\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://codecov.io/github/runvoy/runvoy\" \u003e\n        \u003cimg src=\"https://codecov.io/github/runvoy/runvoy/graph/badge.svg?token=Q673GMB33N\"/\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://golang.org\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/Go-1.25+-00ADD8?logo=go\" alt=\"Go version\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://goreportcard.com/badge/github.com/runvoy/runvoy\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://goreportcard.com/badge/github.com/runvoy/runvoy\" alt=\"Go Report Card\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/runvoy/runvoy\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/Github-repo-yellow\" alt=\"Github Repository\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/runvoy/runvoy/releases/latest\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/github/release/runvoy/runvoy.svg\" alt=\"Latest Release\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://web.runvoy.site\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/%F0%9F%9A%80%20Webapp-blue\" alt=\"Runvoy Webapp\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://runvoy.site\" target=\"_blank\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/%F0%9F%9A%80%20Docs-orange\" alt=\"Runvoy Docs\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://www.bestpractices.dev/projects/11515\"\u003e\n        \u003cimg src=\"https://www.bestpractices.dev/projects/11515/badge\"\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n---\n\n**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.\n\nWorkstations shouldn't need complex setups. Let remote containers execute commands in a secured and reproducible production-grade environment.\n\n**No more snowflakes, _run envoys_.** ✨\n\n## 🎯 Use cases\n\n- ☁️ **Cloud CLI operations** — AWS CLI, Terraform, Ansible, or any SDK-based tools in remote containers with proper permissions ([AWS CLI example](.runvoy/aws-cli-example.yml))\n- ⚙️ **One-off commands** — Run arbitrary commands as you would with `kubectl run` without maintaining an always-running cluster. Example: `runvoy run ping \u003cmy service ip\u003e`\n- 🏗️ **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](.runvoy/build-caddy-example.yml))\n- 🐢 **Long-running tasks** — Commands that may take a long time to complete like coding agents tasks, schema changes, data migrations, dump/restore operations, etc. See [Opencode](.runvoy/opencode-example.yml) and [PostgreSQL restore](.runvoy/pg-restore-example.yml) examples\n- 📝 **Audit-required operations** — Any command that needs a complete audit trail with user identification\n- 🔐 **Secure operations** — Commands with environment variables secrets without exposing them to local workstations\n\n## 📝 Example\n\n```text\nrunvoy run \"uname -a\"\n\n🚀 runvoy run\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n→ Running command: uname -a\n✓ Command execution started successfully\n  Execution ID: 010adbfb34374116b47c8d0faab2befa\n  Status: STARTING\n  Image ID: amazonlinux/amazonlinux:latest-d7ba6332\n→ Execution status: STARTING\n→ Execution is starting (logs usually ready after ~30 seconds)...\n→ Connecting to log stream...\n✓ Connected to log stream. Press Ctrl+C to exit.\n\nLine  Timestamp (UTC)      Message\n────  ───────────────────  ─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n1     2025-11-19 17:30:54  ### runvoy runner execution started by requestID =\u003e f59378e3-01ed-4b44-a315-618951e048aa\n2     2025-11-19 17:30:54  ### Image ID =\u003e amazonlinux/amazonlinux:latest-d7ba6332\n3     2025-11-19 17:30:54  ### runvoy command =\u003e uname -a\n4     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\n\n→ Execution completed. Closing connection...\n→ WebSocket connection closed\n→ View logs in web viewer: https://web.runvoy.site/?execution_id=010adbfb34374116b47c8d0faab2befa\n```\n\n## 💡 What is Runvoy?\n\n**Runvoy is composed of 3 main parts**:\n\n- 🖥️ **Backend** — Runs on your AWS account (multi-cloud support planned), exposes the HTTP API, and orchestrates cloud resources. Deploy once as a cloud admin.\n- ⌨️ **CLI client** — The `runvoy` command-line tool for interacting with the REST API\n- 🌐 **Web app** — Visit [web.runvoy.site](https://web.runvoy.site) or self-host. Currently supports log viewing with full CLI parity coming soon.\n\nRefer to [Architecture](docs/ARCHITECTURE.md) for details.\n\n## ✨ Key Benefits\n\n- 🖥️ **_Doesn't_ run on your computer** — Commands execute in remote production-grade environments with proper secrets access. Team members only need the `runvoy` CLI and an API key — no complex workstation setup required.\n\n- 📊 **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).\n\n- 🔓 **Self-hosted, no black magic** — The backend runs in _your_ cloud account. You control everything: policies, permissions, and data.\n\n- 💰 **Serverless** — No always-running services. Pay only for the compute your commands consume (essentially free for infrequent use).\n\n## 🎨 Features\n\n- 🔑 **API key authentication** — Secure access with SHA-256 hashed API keys\n- 👥 **User access management** — Role-based and ownership access control. Admins define permissions; users access only what they're allowed to\n- 🐳 **Customizable container roles** — Register Docker images with custom roles for proper resource access (AWS ECS+IAM support, more coming soon)\n- 📋 **Native cloud logging** — Full execution logs and audit trails with request ID tracking\n- 📖 **Reusable playbooks** — Store command configs in YAML, commit them, and share with your team for consistent execution ([Terraform example](.runvoy/terraform-example.yml))\n- 🔐 **Secrets management** — Centralized encrypted secrets with full CRUD operations from the CLI\n- ⚡️ **Real-time WebSocket streaming** — Live logs delivered to CLI and web viewer via authenticated WebSocket connections\n- 🔗 **Automatic Git cloning** — Clone public or private Git repos directly into container working directory ([Build Caddy example](.runvoy/build-caddy-example.yml))\n- 🔧 **Unix-style output streams** — Separate CLI logs (stderr) from data (stdout) for easy piping and scripting\n- 🏗️ **IaC deployment** — Deploy complete backend infrastructure with CloudFormation (multi-cloud support coming)\n- 📦 **Single binary** — Download one ~6MB compressed binary, unzip it and run it. No dependencies, no installation hassle. Available for Linux, macOS and Windows.\n\n### 🚧 Roadmap\n\n- 🌍 **Multi-cloud support** — GCP, Azure...\n- ⏱️ **Execution timeouts** — Automatic SIGTERM for commands exceeding timeout\n- 🔒 **Lock management** — Prevent concurrent execution conflicts\n- 🌐 **Full webapp parity** — All CLI commands available in the web interface\n- 🍺 **Homebrew support** — Native installation via Homebrew package manager\n\n## ⚡️ Quick Start\n\nDownload the latest release from the [releases page](https://github.com/runvoy/runvoy/releases):\n\n\u003c!-- VERSION_EXAMPLES_START --\u003e\n- **Linux example:**\n\n```bash\ncurl -L -o runvoy-cli-linux-arm64.tar.gz https://github.com/runvoy/runvoy/releases/download/v0.5.0/runvoy_linux_amd64.tar.gz\ntar -xzf runvoy_linux_amd64.tar.gz\nsudo mv runvoy_linux_amd64/runvoy /usr/local/bin/runvoy\n```\n\n- **macOS example:**\n\n```bash\ncurl -L -o runvoy_linux_amd64.tar.gz https://github.com/runvoy/runvoy/releases/download/v0.5.0/runvoy_darwin_arm64.tar.gz\ntar -xzf runvoy_darwin_arm64.tar.gz\nxattr -dr com.apple.quarantine runvoy_darwin_arm64/runvoy\ncodesign -s - --deep --force runvoy_darwin_arm64/runvoy\nsudo mv runvoy_darwin_arm64/runvoy /usr/local/bin/runvoy\n```\n\n- **Windows:** Download the archive from the [release page](https://github.com/runvoy/runvoy/releases/download/v0.5.0/runvoy_windows_amd64.tar.gz). Extract the `runvoy.exe` file from the archive using a tool like 7-Zip\n\u003c!-- VERSION_EXAMPLES_END --\u003e\n\n### 🏗️ Deploying the backend infrastructure\n\n**Requirements:**\n\nAWS credentials and region needs to be configured in your shell environment ([AWS CLI settings docs](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html)), the user needs to have the `AdministratorAccess` and `AmazonECS_FullAccess` policies:\n\n- [AdministratorAccess](https://us-east-1.console.aws.amazon.com/iam/home?region=us-west-2#/policies/details/arn%3Aaws%3Aiam%3A%3Aaws%3Apolicy%2FAdministratorAccess)\n- [AmazonECS_FullAccess](https://us-east-1.console.aws.amazon.com/iam/home?region=us-west-2#/policies/details/arn%3Aaws%3Aiam%3A%3Aaws%3Apolicy%2FAmazonECS_FullAccess)\n\nYou can review the full list of resources and permissions required for the backend infrastructure in the released [cloudformation-backend.yaml](https://github.com/runvoy/runvoy/releases/download/v0.2.0/cloudformation-backend.yaml) file\n\nBootstrap the backend infrastructure and seed the admin user:\n\n```bash\nrunvoy infra apply --configure --seed-admin-user admin@example.com\n```\n\n### 👤 Creating a new user\n\nThe admin API key and endpoint are automatically configured in `~/.runvoy/config.yaml` after deployment. Start using runvoy immediately:\n\n```bash\n# Register one image to be used as default, pick any image from any public registry\nrunvoy images register public.ecr.aws/docker/library/alpine:latest\n\n# Run a test command\nrunvoy run \"echo hello world\"\n```\n\nor\n\n```bash\nrunvoy users create \u003cemail\u003e --role developer # or admin, operator, viewer\n```\n\nto 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.\n\n**Important Notes:**\n\n- ⏱  Claim tokens expire after 15 minutes\n- 👁  Each token can only be used once\n\n### Roles\n\nRunvoy ships with default roles:\n\n- `admin` can do everything\n- `operator` can manage executions, images, secrets, and read users\n- `developer` can run commands and manage secrets without accessing user management\n- `viewer` can only read executions\n\nSee the Casbin [policy.csv](internal/auth/authorization/casbin/policy.csv) file for the exact rule set.\n\n## 📖 Usage\n\n\u003c!-- CLI_HELP_START --\u003e\n### Available Commands\n\nTo see all available commands and their descriptions:\n\n```bash\nrunvoy --help\n```\n\n```text\nrunvoy - v0.5.0-20251226-394ccffc\nIsolated, repeatable execution environments for your commands\n\nUsage:\n  runvoy [command]\n\nAvailable Commands:\n  claim       Claim a user's API key\n  completion  Generate the autocompletion script for the specified shell\n  configure   Configure local environment with API key and endpoint URL\n  health      Health and reconciliation commands\n  help        Help about any command\n  images      Docker images management commands\n  infra       Infrastructure management commands\n  kill        Kill a running command execution\n  list        List command executions\n  logs        Get logs for an execution\n  playbook    Manage and execute playbooks\n  run         Run a command\n  secrets     Secrets management commands\n  status      Get the status of a command execution\n  trace       Get backend logs and related resources for a given request ID\n  users       User management commands\n  version     Show the version of the CLI\n\nFlags:\n      --debug            Enable debugging logs\n  -h, --help             help for runvoy\n      --timeout string   Timeout for command execution (e.g., 10m, 30s, 1h) (default \"10m\")\n      --verbose          Verbose output\n\nUse \"runvoy [command] --help\" for more information about a command.\n```\n\n\u003c!-- CLI_HELP_END --\u003e\n\nSee [CLI commands Documentation](docs/CLI.md) for more details.\n\n### 🔧 Output Streams and Piping\n\nRunvoy follows Unix conventions by separating informational messages from data output, making it easy to pipe commands and script automation workflows:\n\n- **stderr (standard error)**: Runtime messages, progress indicators, and logs\n  - Informational messages (→, ✓, ⚠, ✗)\n  - Progress spinners and status updates\n  - Headers and UI formatting\n\n- **stdout (standard output)**: Actual data from API responses\n  - Tables, lists, and structured data\n  - Raw output for piping to other tools\n\n**Examples:**\n\n```bash\n# Hide informational messages, show only data\nrunvoy list 2\u003e/dev/null\n\n# Hide data, show only logs/status messages\nrunvoy list \u003e/dev/null\n\n# Pipe data to another command (jq, grep, etc.)\nrunvoy list 2\u003e/dev/null | grep \"RUNNING\"\n\n# Redirect logs and data to separate files\nrunvoy list 2\u003estatus.log \u003eexecutions.txt\n\n# Pipe between runvoy commands\nrunvoy command1 2\u003e/dev/null | runvoy command2\n\n# Use in scripts with proper error handling\nif runvoy status $EXEC_ID 2\u003e/dev/null | grep -q \"SUCCEEDED\"; then\n  echo \"Execution succeeded\"\nfi\n```\n\nThis separation enables clean automation and integration with other Unix tools without mixing informational output with parseable data.\n\n### 🌐 Web Viewer\n\nThe web viewer is a SvelteKit-based single-page application that provides:\n\n- **Real-time log streaming** - Automatically get updates from the websocket API in real-time\n- **ANSI color support** - Displays colored terminal output\n- **Status tracking** - Shows execution status (RUNNING, SUCCEEDED, FAILED, STOPPED)\n- **Execution metadata** - Displays execution ID, start time, and exit codes\n- **Interactive controls**:\n  - Pause/Resume streaming\n  - Download logs as text file\n  - Clear display\n  - Toggle metadata (line numbers and timestamps)\n\n**Setup (first-time only):**\n\n1. Open the web viewer URL in your browser\n2. Enter your API endpoint URL (same as in `~/.runvoy/config.yaml`)\n3. Enter your API key (same as in `~/.runvoy/config.yaml`)\n4. Settings are saved in browser's localStorage for future use\n\nThe web viewer is hosted on [Netlify](https://www.netlify.com/) by default, but you can configure a custom URL if you deploy your own instance (see Configuration below).\n\n**Configuration:**\n\nThe web application URL can be customized via:\n\n- Environment variable: `RUNVOY_WEB_URL`\n- Config file (`~/.runvoy/config.yaml`): `web_url` field\n\nIf not configured, it defaults to `https://web.runvoy.site/`.\n\n## 🏛️ Architecture\n\n```text\n┌─────────────────┐          ┌─────────────────┐\n│   CLI Client    │          │   Web Viewer    │\n│   (runvoy)      │          │  (browser)      │\n└────────┬────────┘          └────────┬────────┘\n         │                            │\n         │  HTTPS (REST API)          │  HTTPS (REST API)\n         │  WebSocket (logs)          │  WebSocket (logs)\n         │                            │\n         └────────────┬───────────────┘\n                      │\n         ┌────────────▼─────────────────────────┐\n         │     AWS Backend                      │\n         │                                      │\n         │  • Lambda Functions (Orchestrator,   │\n         │    Event Processor)                  │\n         │  • DynamoDB (metadata storage)       │\n         │  • ECS Fargate (command execution)   │\n         │  • CloudWatch Logs (execution logs)  │\n         │  • EventBridge (event routing)       │\n         │  • API Gateway WebSocket (real-time) │\n         │  • SSM Parameter Store (secrets)     │\n         └──────────────────────────────────────┘\n```\n\nFor detailed architecture information, see [ARCHITECTURE](docs/ARCHITECTURE.md).\n\n## 💭 The Story Behind Runvoy\n\nAs 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**. 🚧\n\nI'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. ✨\n\nThe 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. 💰\n\n**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. 🛠️\n\n## 🤝 Development\n\nFor development setup, workflow, and contributing guidelines, see [CONTRIBUTING](CONTRIBUTING.md) and [CODE OF CONDUCT](CODE_OF_CONDUCT.md).\n\nContributions welcome! 🎉\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frunvoy%2Frunvoy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frunvoy%2Frunvoy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frunvoy%2Frunvoy/lists"}