Hey everyone,
Just merged a significant cleanup PR (#30) into the main branch, that I wanted to walk you through.
This merge also was release as version 1.0.1: Release v1.0.1 · PentHertz/RF-Swift · GitHub
Here’s what changed.
CLI refactoring
The entire CLI layer has been split into dedicated, purpose-specific files rather than one monolithic file. Each domain now lives in its own module under go/rfswift/cli/:
| File | What it covers |
|---|---|
container.go |
run, exec, last, stop, remove, install, commit, rename |
images.go |
images local/remote/versions, pull, retag, delete, download |
cleanup.go |
cleanup all/containers/images with age filters and dry-run |
logging.go |
log start/stop/replay/list for session recording |
ulimits.go |
ulimits add/rm/list, realtime mode |
completion.go |
Shell completions for bash, zsh, fish, PowerShell |
winusb.go |
Windows USB passthrough (conditional build) |
dock/ Engine abstraction layer
This is another architecturally significant change in the release. The monolithic rfdock.go / dockerutils.go approach has been replaced with a proper engine abstraction layer.
The core of it is a ContainerEngine interface in dock/engine.go that both Docker and Podman implement:
dock/
├── engine.go <- ContainerEngine interface, auto-detection, singleton
├── engine_docker.go <- Docker implementation (socket discovery, service mgmt)
├── engine_podman.go <- Podman implementation (rootless/rootful, macOS VM init)
└── podman.go <- Podman CLI fallback for features not in the compat API
When Podman is detected, the engine layer automatically sets DOCKER_HOST to point to the Podman socket, meaning the rest of the codebase (container ops, image management, etc.) works without modification regardless of which engine is active.
Engine selection priority works as follows:
--engineCLI flag (highest priority)RFSWIFT_ENGINEenvironment variableCONTAINER_HOST/DOCKER_HOSTenv vars- Auto-detection: Docker first, then Podman
bash
# Force a specific engine
rfswift --engine podman run -n mycontainer -i sdr_full
# Or via env
export RFSWIFT_ENGINE=podman
rfswift run -n mycontainer -i sdr_full
# Inspect which engine is active
rfswift engine
One notable edge case handled cleanly: functions that previously edited hostconfig.json directly (mount bindings, device bindings) now check engine capability first. Docker supports direct file editing; Podman requires container recreation via recreateContainerWithProperties(), and the code routes accordingly.
macOS Podman Machine Auto-Init
This one came directly from a community report (thanks @kaipyroami). If you installed Podman via Homebrew on macOS, you’d hit an error like this when running RF Swift:
[i] Starting Podman machine...
[!] Podman requested but not available, trying Docker...
[!] No container engine available
The root cause: Podman on macOS requires a Linux VM underneath (podman machine), and simply installing Podman via Homebrew doesn’t set it up. Previously, RF Swift would detect Podman, fail to connect to the socket, and fall back to Docker silently.
The fix is now baked into the binary itself. On macOS with Podman, RF Swift will:
- Check if a Podman machine exists (
podman machine list) - If not → automatically run
podman machine init - Check if it’s running → if not,
podman machine start - Wait until the socket is actually available before proceeding
This means Podman on macOS should now “just work” on first run, even with a fresh Homebrew install, without any manual podman machine init dance.
CONTRIBUTING.md
A little contributor guide is now in the repo covering:
- Build instructions (native + cross-compilation for Linux/Windows/macOS/ARM/RISC-V)
- Full architecture diagram
- Package-by-package guide (
cli,dock,common,rfutils) - Step-by-step: how to add a new command, a new container engine feature
- Container config flow explanation
- YAML recipe format reference
- Release process via GoReleaser
If you’ve been wanting to contribute or build on top of RF Swift, this is a good starting point.