{"id":31106095,"url":"https://github.com/danielpgross/rmate_launcher","last_synced_at":"2025-09-17T04:59:26.254Z","repository":{"id":313116502,"uuid":"1031421708","full_name":"danielpgross/rmate_launcher","owner":"danielpgross","description":"Edit files over SSH with a local editor of your choice, using the rmate protocol","archived":false,"fork":false,"pushed_at":"2025-09-04T00:55:29.000Z","size":2274,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-04T02:39:53.891Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Zig","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/danielpgross.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-08-03T17:48:24.000Z","updated_at":"2025-09-04T00:57:01.000Z","dependencies_parsed_at":"2025-09-04T02:39:56.594Z","dependency_job_id":"6cfe6c34-0204-46a2-ac53-77a17b5665e4","html_url":"https://github.com/danielpgross/rmate_launcher","commit_stats":null,"previous_names":["danielpgross/rmate_launcher"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/danielpgross/rmate_launcher","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielpgross%2Frmate_launcher","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielpgross%2Frmate_launcher/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielpgross%2Frmate_launcher/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielpgross%2Frmate_launcher/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/danielpgross","download_url":"https://codeload.github.com/danielpgross/rmate_launcher/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/danielpgross%2Frmate_launcher/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":275537166,"owners_count":25482345,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-17T02:00:09.119Z","response_time":84,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":[],"created_at":"2025-09-17T04:59:24.199Z","updated_at":"2025-09-17T04:59:26.244Z","avatar_url":"https://github.com/danielpgross.png","language":"Zig","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"logo.png\" alt=\"RMate Launcher Logo\" width=\"200\"/\u003e\n  \n  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n  [![Version](https://img.shields.io/badge/Version-0.7.0-blue.svg)](https://github.com/danielpgross/rmate-server/releases)\n  [![Zig](https://img.shields.io/badge/Zig-0.15.1+-ff6600.svg?logo=zig\u0026logoColor=white)](https://ziglang.org/)\n  [![Platform](https://img.shields.io/badge/Platform-Linux%20%7C%20macOS-lightgrey.svg)](https://github.com/danielpgross/rmate-server)\n\u003c/div\u003e\n\n# RMate Launcher\n\nSeamlessly edit files over SSH with a local editor of your choice, using the rmate protocol.\n\n## Overview\n\n- ✅ **Lightweight \u0026 Simple** - No external dependencies: runs in ~1MB RAM, installs with a single binary\n- ✅ **Multiple concurrent files** with real-time OS-level file watching\n- ✅ **Cross-platform** (Linux, macOS) with statically linked binaries\n- ✅ **Editor agnostic** - VS Code, Sublime Text, Zed, etc.\n- ✅ **Always available** - Runs as standalone service, independent of editor\n\n### Demo\n\n![RMate Launcher Demo](demo.gif)\n\n### How it works\n\n1. RMate client on remote server connects via SSH tunnel to local RMate Launcher\n2. Server saves file content to temp file and watches for changes with OS-level notifications\n    - Temp files mirror the remote path under a per-host directory: `~/.rmate_launcher/\u003chostname\u003e/\u003cremote path\u003e` (e.g., `hostname:/etc/foo/bar.txt` -\u003e `~/.rmate_launcher/hostname/etc/foo/bar.txt`).\n3. Server spawns local editor to edit temp file\n4. Changes trigger `save` commands; editor close triggers `close` command\n\n### Why the rmate protocol?\n\nOriginally developed for [TextMate](https://github.com/textmate/rmate), this is a proven protocol for editing remote files through SSH tunnels. It's widely supported with clients in [Ruby](https://github.com/textmate/rmate) (original), [Bash](https://github.com/aurora/rmate), [Python](https://github.com/sclukey/rmate-python), [Perl](https://github.com/davidolrik/rmate-perl), [Nim](https://github.com/aurora/rmate-nim), [C](https://github.com/hanklords/rmate.c), [Node.js](https://github.com/jrnewell/jmate), and [Go](https://github.com/mattn/gomate). Use any existing client with RMate Launcher - no changes required.\n\n### Why not use existing editor extensions?\n\nEditor-specific extensions ([RemoteSubl](https://github.com/randy3k/RemoteSubl), [Remote VSCode](https://github.com/rafaelmaiolla/remote-vscode)) require the editor to be running, have inconsistent behavior, and lock you into one editor. RMate Launcher provides consistent functionality across all editors and future-proof remote editing.\n\n## Usage\n\n```bash\n# 1. Start server locally (skip this step if already running as a service)\nRMATE_EDITOR=\"code --wait\" rmate_launcher \u0026\n\n# 2. Start SSH session with tunnel\nssh -R 52698:$HOME/.rmate_launcher/rmate.sock user@remote-server\n\n# 3. Edit remote files (opens in your local editor!)\n# In remote SSH session:\nrmate /path/to/remote/file.txt\n```\n\n### Optional: Automatic SSH Config\n\nAdd to `~/.ssh/config` for automatic forwarding:\n```ssh-config\nHost myserver.example.com          # For specific hosts\n    RemoteForward 52698 ~/.rmate_launcher/rmate.sock\n\nHost *                            # For all hosts (optional)\n    RemoteForward 52698 ~/.rmate_launcher/rmate.sock\n```\n\n### Optional: Set `rmate` as the default editor on the remote\n\nOn the remote host (after you have `rmate` installed and executable, and your SSH session is forwarding as shown above):\n\n```bash\necho 'export VISUAL=\"rmate -w\"' \u003e\u003e ~/.zshrc\necho 'export EDITOR=\"$VISUAL\"' \u003e\u003e ~/.zshrc\n. ~/.zshrc\n```\n\n#### Edit root-owned files safely (sudoedit)\n\nUse `sudoedit` (aka `sudo -e`) so your editor runs unprivileged while sudo writes back with root permissions.\n\n```bash\necho 'export SUDO_EDITOR=\"rmate -w\"' \u003e\u003e ~/.zshrc\n. ~/.zshrc\n\nsudoedit /etc/ssh/sshd_config   # or: sudo -e /etc/hosts\n\nsudo EDITOR=\"rmate -w\" visudo\n```\n\n## Installation\n\n### From GitHub Releases\n\nDownload binaries from the [releases page](../../releases):\n\n| Platform | Architecture | Binary |\n|----------|-------------|--------|\n| Linux | Intel/AMD (x86_64) | `rmate_launcher-linux-x86_64.tar.gz` |\n| Linux | ARM64 (aarch64) | `rmate_launcher-linux-aarch64.tar.gz` |\n| macOS 10.15+ | Intel (x86_64) | `rmate_launcher-macos-x86_64.tar.gz` |\n| macOS 10.15+ | Apple Silicon (aarch64) | `rmate_launcher-macos-aarch64.tar.gz` |\n\n```bash\n# Download and install (example for Linux x86_64)\ncurl -L -o rmate_launcher.tar.gz https://github.com/danielpgross/rmate_launcher/releases/latest/download/rmate_launcher-linux-x86_64.tar.gz\ntar -xzf rmate_launcher.tar.gz \u0026\u0026 chmod +x rmate_launcher-linux-x86_64\nmv rmate_launcher-linux-x86_64 /usr/local/bin/rmate_launcher\n```\n\n### From Source\n\nRequires [Zig](https://ziglang.org/) 0.15.1+:\n```bash\ngit clone https://github.com/danielpgross/rmate_launcher.git \u0026\u0026 cd rmate_launcher\nzig build -Doptimize=ReleaseSafe  # or just 'zig build' for development\n```\n\n## Running as a service\n\nFor daily use, run it as a system service. Templates are provided to set up the service on macOS and Linux:\n\n#### macOS (launchd)\n\n```bash\nmkdir -p ~/.rmate_launcher\ncp macos-launchd.plist.example ~/Library/LaunchAgents/com.user.rmate_launcher.plist\n# Edit plist: paths, RMATE_EDITOR, RMATE_SOCKET, sandbox settings\nlaunchctl load ~/Library/LaunchAgents/com.user.rmate_launcher.plist\nlaunchctl start com.user.rmate_launcher\n```\n\n#### Linux (systemd)\n\n```bash\nmkdir -p ~/.rmate_launcher ~/.config/systemd/user\ncp linux-systemd.service.example ~/.config/systemd/user/rmate_launcher.service\n# Edit service: paths, RMATE_EDITOR, RMATE_SOCKET\nsystemctl --user daemon-reload \u0026\u0026 systemctl --user enable --now rmate_launcher\n```\n\n## Configuration\n\nAll configuration is defined in environment variables.\n\n### Required\n\n`RMATE_EDITOR` - Editor command to run\n* Path to the temp file will be passed as the first argument.\n* **Command must block until editing is done** (pass `--wait` flag or similar).\n```bash\nexport RMATE_EDITOR=\"code --wait\"    # VS Code\nexport RMATE_EDITOR=\"vim\"            # Vim  \nexport RMATE_EDITOR=\"subl --wait\"    # Sublime Text\n```\n\n### Optional Configuration\n\n- `RMATE_SOCKET` - Unix socket path (default: `~/.rmate_launcher/rmate.sock`)\n- `RMATE_PORT` / `RMATE_IP` - Legacy TCP options (default: `52698/127.0.0.1`, less secure)\n\n### Advanced: Dynamic editor selection\n\nSince `RMATE_EDITOR` can be any command, you can use a bash script to launch different editors based on file patterns. The script receives the mirrored temp path (e.g., `~/.rmate_launcher/\u003chostname\u003e/...`), so you can route by hostname, remote path, or file extension:\n\n```bash\n#!/bin/bash\n# ~/.rmate_launcher/editor-selector.sh\ncase \"$(basename \"$1\")\" in\n    *.md|*.txt|README*) zed --wait \"$1\" ;;           # Docs in Zed\n    *.js|*.ts|*.json|*.html) code --wait \"$1\" ;;     # Web dev in VS Code  \n    *) subl --wait \"$1\" ;;                           # Everything else in Sublime\nesac\n```\n```bash\nchmod +x ~/.rmate_launcher/editor-selector.sh\nexport RMATE_EDITOR=\"$HOME/.rmate_launcher/editor-selector.sh\"\n```\n\n## Development\n\n**Prerequisites:** [Zig](https://ziglang.org/) 0.15.1+\n\n```bash\nzig build                                                   # Development build\nzig build -Doptimize=ReleaseSafe                            # Optimized build  \nzig build test                                              # Run tests\nzig build -Dtarget=x86_64-linux-gnu -Doptimize=ReleaseSafe  # Cross-compile\n\n# Run locally\nexport RMATE_EDITOR=\"code --wait\" \u0026\u0026 zig build run\n```\n\n## Technical Design\n\n**File Watching**: Uses native OS APIs - `kqueue` on macOS/BSD and `inotify` on Linux - for efficient, real-time file change notifications without polling or external dependencies.\n\n**Threading**: Multi-threaded architecture with dedicated threads for the main accept loop, individual client handlers, and per-file watchers.\n\n**Static Compilation**: Direct use of native OS APIs enables static compilation to a single binary with zero runtime dependencies.\n\n## License\n\nMIT","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanielpgross%2Frmate_launcher","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdanielpgross%2Frmate_launcher","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdanielpgross%2Frmate_launcher/lists"}