Install
shinyctl is one binary for Linux and macOS, on amd64 or arm64. Installing it needs no root, and it runs your apps as your own user.
Requirements
- Linux or macOS, on amd64 or arm64.
- R with the
shinypackage, andRscripton yourPATH. - systemd, to start at boot on Linux (optional).
- Go 1.26.10 or newer, only to build it yourself.
The one-line installer
curl -fsSL https://raw.githubusercontent.com/spriyansh/shinyctl/main/install.sh | sh
install.sh is a short shell script you can read first. It:
- picks the build for your system and downloads it from the latest release;
- checks it against the release's
checksums.txt, and stops if it doesn't match; - copies the single
shinyctlbinary into~/.local/bin, replacing any older one in one step; - says if that folder is not on your
PATHyet, or ifRscriptis missing.
Run it again to upgrade. Three settings change what it does:
| Setting | What it does |
|---|---|
SHINYCTL_VERSION | The release to install, such as v0.1.0. By default, the latest. |
SHINYCTL_INSTALL_DIR | Where the binary goes. By default, ~/.local/bin. |
SHINYCTL_RELEASES | A mirror of the releases page to download from. |
curl -fsSL https://raw.githubusercontent.com/spriyansh/shinyctl/main/install.sh | SHINYCTL_VERSION=v0.1.0 sh
If ~/.local/bin is not on your PATH
On Debian, Ubuntu and Raspberry Pi OS it is added when you next log in. On macOS, add it to your shell's profile and open a new terminal:
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zprofile
By hand
Download the archive for your system and checksums.txt from the releases page, check the download, unpack it, and put shinyctl on your PATH. For Linux on arm64 (a Raspberry Pi), version 0.1.0:
curl -LO https://github.com/spriyansh/shinyctl/releases/download/v0.1.0/shinyctl_0.1.0_linux_arm64.tar.gz
curl -LO https://github.com/spriyansh/shinyctl/releases/download/v0.1.0/checksums.txt
sha256sum --ignore-missing -c checksums.txt # macOS: shasum -a 256 --ignore-missing -c checksums.txt
tar -xzf shinyctl_0.1.0_linux_arm64.tar.gz
mkdir -p ~/.local/bin && cp shinyctl_0.1.0_linux_arm64/shinyctl ~/.local/bin/
The other archives are linux_amd64, darwin_arm64 (Apple silicon) and darwin_amd64. Each unpacks into a folder of its own with shinyctl, the README, the licence and notices, and the example app in examples/hello.
A file downloaded with a browser on macOS is quarantined. curl doesn't do that, and xattr -d com.apple.quarantine shinyctl lifts it.
With Go
go install github.com/spriyansh/shinyctl@v0.1.0
Or, from a clone of the repository, make install.
Check it
shinyctl version
It prints v0.1.0 for a release (and for go install ...@v0.1.0), and dev (abc1234) for a build from a checkout.
Your first app
Write a manifest next to your app, set its entrypoint-file and port, and apply it. The first apply starts shinyctl-api in the background.
shinyctl init # writes ./shinyctl.yaml
$EDITOR shinyctl.yaml # set entrypoint-file and port
shinyctl apply -f shinyctl.yaml # starts shinyctl-api, then the app
shinyctl status
A few seconds later both copies are ready: one takes visitors, the other is the warm spare.
NAME COPY ROLE PORT PID STATUS READY MEM SESSIONS CRASHES STARTED
hello 1 active 8765 77713 alive ready 97M 0 - 2026-10-29T22:05:11+01:00
hello 2 warm 8765 77714 alive ready 97M 0 - 2026-10-29T22:05:11+01:00
Memory: 195M in 2 R processes (1 warm), plus 37M for the load balancer.
Open the port from your manifest, for example http://127.0.0.1:8080. Every field of the manifest is in the reference.
Try the example
The example app is in the archive and in the repository, in examples/hello. From the unpacked archive folder:
shinyctl apply -f examples/hello/shinyctl.yaml
Open http://127.0.0.1:8765 and click Crash this app. The page moves to the other copy within about a second: it reloads by itself and shows that copy's process ID. The crashed copy restarts a few seconds later and becomes the spare, so the roles in status have swapped. To see what both copies printed, including the crash:
shinyctl logs -f examples/hello/shinyctl.yaml
Remove the app with shinyctl delete -f examples/hello/shinyctl.yaml. If something else already uses port 8765, apply says so and status shows port-in-use: change port in the example's manifest and apply again.