Secure, outbound-only access to physical devices — with a native-feeling development, debugging, and software deployment experience.
m87 is make87's command line and device runtime for connecting to, debugging, and deploying software to distributed hardware fleets — all over a single outbound connection and without VPNs or inbound firewall rules.
In this repo:
m87command = what you type in your terminal- m87 runtime = the on-device process that maintains the outbound connection and executes actions
Install the m87 command on your developer machine. (You'll run the m87 runtime on the edge device in step 3.)
Installs the latest version to $HOME/.local/bin:
curl -fsSL https://get.make87.com | shOther install options
From releases
Download a pre-built binary from the releases page and place it in your $PATH (e.g., $HOME/.local/bin or /usr/local/bin).
From source
Build the binary and move it to a location in your $PATH:
git clone https://github.com/make87/m87.git
cd make87
cargo build --release
cp target/release/m87 $HOME/.local/bin/Via Docker (no local install)
Run m87 from a container without installing anything locally. Useful for CI pipelines or keeping your system clean.
# Build the image
git clone https://github.com/make87/m87.git
cd make87
docker build -f m87-client/Dockerfile -t m87 .
# Run commands (config persists in ~/.config/m87)
docker run -it --rm \
--user "$(id -u):$(id -g)" \
-v "$HOME/.config/m87:/.config/m87" \
-e HOME=/ \
m87 loginFor convenience, add an alias to your shell rc:
alias m87='docker run -it --rm --user "$(id -u):$(id -g)" -v "$HOME/.config/m87:/.config/m87" -e HOME=/ m87'Login to create your account (opens browser for OAuth):
m87 loginOn the edge device, start the m87 runtime (the on-device process):
m87 runtime run --email you@example.comThis registers the device (printing a request ID) and waits for approval. Once approved, the runtime starts automatically.
On your developer machine, approve the pending device:
m87 devices approve <request-id>(You can also approve via the web UI.)
Once approved, you can interact with your device:
m87 devices list
m87 <device> shell
m87 <device> docker psNow you're connected — no inbound access, no firewall rules, and no VPN required.
👀 Try this next:
- forward a local port to a remote service
- run an IDE remote development session
m87 isn't just remote access — it's designed so working with real devices feels like local development and deployment:
- Outbound-only access: works behind NATs / firewalls without opening inbound ports.
- Native dev experience: shell, port/sockets forwarding, logs, and live debugging feel like you're working locally.
- Deployment-ready: one command line that transitions from access to orchestrating software deployments across fleets.
If you've ever SSH'd into an embedded device only to run into network traps or scaling pain, m87 makes those workflows easy and repeatable.
Use native OS tools and IDEs as if the device were local:
# Run shell
m87 <device> shell
# Forward a port for a debugging server
m87 <device> forward 8080:localhost:3000Deploy containers and services using familiar commands:
m87 <device> docker compose up -d(More deployment commands and flags coming soon.)
Full documentation, examples, and tutorials are available here: m87-client/
Requires:
- Rust 1.85+
- Git
git clone https://github.com/make87/m87.git
cd make87
cargo build --releaseContributions, bug reports, and feedback are welcome! Whether you're a tinkerer, an early adopter, or looking to integrate m87 into your stack:
- Open issues for ideas and bugs
- Submit PRs — we review quickly
Let's build a better developer experience for physical systems.
- m87-client, m87-shared: Apache-2.0
- m87-server: AGPL-3.0-or-later
Give the repo a ⭐ and share your feedback — every star helps drive adoption and signals to others that this tool is worth exploring.