Forcola is not the only way to run external processes from the BEAM. The table below reflects each option's published source and tracker as of mid-2026; rows marked "tested" were verified empirically on macOS with Elixir 1.20 / OTP 29.
| Option | Architecture | BEAM-death cleanup | Grandchild kill | Install footprint | Maintenance (mid-2026) |
|---|---|---|---|---|---|
| System.cmd / Port / :os.cmd | BEAM port | None; no signal on port close (tested) | No | None | OTP/Elixir stdlib |
| erlexec | One C++ port program for all commands | Yes, incl. kill -9: SIGTERM then SIGKILL in 6 s | Opt-in ({group, GID} + kill_group) | C++ toolchain + rebar3 at dep compile, source-only package | Active (2.3.4, June 2026) |
| MuonTrap | C wrapper per command | Yes, incl. kill -9 (tested) | Linux cgroups: full tree; macOS: direct child only (tested) | C compiler (elixir_make) | Active (1.8.0 May 2026, 2.0 rc June 2026) |
| Porcelain + goon | Go middleman, manual download | Closes child stdin and waits; never kills | No | goon fetched by hand; last goon release 2014 | Unmaintained (last release 2016, last commit 2020) |
| Rambo | Rust shim per call | SIGKILLs direct child on stdin EOF | No | Bundled x86-64 binaries only; broken out of the box on Apple Silicon (tested) | Dormant (last release March 2021) |
| exile | NIF IO + spawner that execs into the command | Normal exits yes; kill -9 of BEAM orphans the child (tested) | No | C compiler (elixir_make) | Maintained, single author (0.14.0, Feb 2026) |
| forcola | Rust shim per command | stdin EOF kills the process group, covers kill -9; death confirmed before EXIT | Yes (setsid + kill(-pgid), TERM then KILL) | None on 5 precompiled targets; cargo elsewhere | New (v0.1.0) |
erlexec
The most capable and most mature option: a single C++ port program with pty
support, user switching, and opt-in process-group kill, actively maintained
since 2003. Its costs are a C++ toolchain at dependency compile time and a
larger API surface. forcola now supports a pty in Forcola.Duplex
(pty: true), so a pty alone is no longer a reason to reach for erlexec;
forcola's pty is Duplex-only and does no RFC 4254 option negotiation. forcola
also does a basic run-as-user drop now
(#31): :user/:group
options do a straight setgroups/setgid/setuid from a privileged shim.
erlexec goes further, with a sudo/SUID helper for privilege escalation and
Linux capability management; forcola does neither. Choose erlexec when you need
those.
MuonTrap
Solves the same core problem as forcola with a per-command C wrapper, and on Linux adds cgroup containment that kills entire process trees, including deliberate daemonizers. Without cgroups it kills the direct child only, so grandchildren escape; forcola's group kill covers ordinary grandchildren everywhere but cannot contain a deliberate daemonizer on macOS either. On Nerves or embedded Linux, MuonTrap is the native choice.
exile
Takes a different shape: NIF-based demand-driven IO with real backpressure, ideal when a slow consumer must stream huge output without buffering. The tradeoff is cleanup: with no middleman process, a kill -9 of the BEAM orphans the child (in testing on macOS, exile's child survived where forcola's and MuonTrap's shims cleaned up). Forcola tracks a backpressure streaming mode in #32.
Porcelain and Rambo
Both are effectively frozen. Porcelain has had no release since 2016 and its goon driver's last release is from 2014; the released goon never kills the child, it only closes stdin and waits. Rambo is a one-shot Rust shim design but has had no release since March 2021, ships x86-64-only binaries, and in testing on an Apple Silicon Mac it failed out of the box. Rambo proved a Rust shim works in a hex package; its binary distribution is the cautionary tale forcola's release workflow is designed around.
Choosing something else
- You need privilege escalation via a sudo/SUID helper, or Linux capability
management: erlexec. forcola does a basic uid/gid drop with
:user/:group(#31): a straightsetgroups/setgid/setuidfrom a privileged shim, not sudo/SUID or capabilities. - You need Linux cgroup containment of daemonizers today: MuonTrap (or systemd-run). forcola tracks an optional cgroup layer in #15.
- You need backpressure-first streaming and accept the kill -9 orphan risk: exile. forcola tracks a backpressure mode in #32.
- You need Windows: Rambo's bundled binary or plain System.cmd. forcola tracks Windows support in #34.
- You cannot ship native binaries at all: System.cmd/ports, with the orphan-on-death leak documented and accepted.
- forcola is new (v0.1.0). If that is a blocker, erlexec and MuonTrap are the mature, actively maintained alternatives that cover the closest ground.