rfswift container shell
Enter an existing container with a shell, or run a single command in it.
rfswift container shell takes you back into a lab you created earlier, or runs a single command in it. If the container is stopped, it is started first. Use it every time you come back to your work.
rfswift container shell -c my_sdrOther spellings: the legacy form rfswift exec and the aliases rfswift shell and rfswift enter still work and print a notice. With --engine nix, the same command enters a native Nix environment (the dedicated form is rfswift env shell NAME).
Synopsis
rfswift container shell [-c CONTAINER] [-w WORKDIR] [-e COMMAND] [options]
rfswift exec [-c CONTAINER] [-w WORKDIR] [options] # legacy spelling
rfswift container shell -c CONTAINER -e "rtl_test -t" # one command, no shellWithout -c, a picker lists your containers in an interactive terminal; in a script, the most recent container is used. When you enter, RF Swift prints the container summary (image version and freshness, size, shell, display, privileges, mounts, devices, seccomp, ulimits, GPUs, network, ports) and syncs the hot-pluggable serial ports.
Container picker: the picker shows every container with its name, ID, image and state. The most recent one is marked <- latest.
Options
Container selection
| Flag | Description | Default | Example |
|---|---|---|---|
-c, --container STRING |
Container name or ID | Most recent | -c my_container |
-w, --workdir STRING |
Working directory inside container | /root |
-w /root/projects |
-e, --command STRING |
Shell or command to run | /bin/zsh (Bash when missing) |
-e /bin/bash, -e "hackrf_info" |
-i, --install STRING |
Run an install function from the image’s scripts before the shell | -i gqrx_soft_install |
Display options
| Flag | Description | Default | Example |
|---|---|---|---|
--no-x11 |
Disable X11 forwarding and remove X11 socket binding | false | --no-x11 |
--desktop |
Start remote desktop via VNC/noVNC in the container | false | --desktop |
--desktop-config STRING |
Desktop config as proto:host:port |
http:127.0.0.1:6080 |
--desktop-config "http:0.0.0.0:6080" |
--desktop-pass STRING |
Set VNC password for desktop access | None | --desktop-pass "mypassword" |
--desktop-ssl |
Enable SSL/TLS for desktop connections | false | --desktop-ssl |
VPN options
| Flag | Description | Example |
|---|---|---|
--vpn STRING |
Start VPN inside the container | --vpn tailscale |
Format: --vpn TYPE[:ARGUMENT], the same syntax as container create --vpn.
With --vpn, the VPN client starts inside the running container. WireGuard and OpenVPN need a container created in privileged mode (-u 1). See VPN inside containers.
Recording options
| Flag | Description | Example |
|---|---|---|
--record |
Enable session recording | --record |
--record-output STRING |
Custom recording filename | --record-output debug.cast |
Examples
Basic usage
Enter most recent container
rfswift container shellEnter specific container by name
rfswift container shell -c my_sdr_containerEnter with specific working directory
rfswift container shell -c my_container -w /root/projectsEnter by container ID
rfswift container shell -c a1b2c3d4e5f6Short container ID
rfswift container shell -c a1b2c3With session recording
Record with auto-generated filename
rfswift container shell -c assessment --recordRecord with custom filename
rfswift container shell -c pentest --record --record-output debug-session.castRecord in specific directory with working dir
rfswift container shell -c analysis \
-w /root/data \
--record \
--record-output ~/recordings/analysis-$(date +%Y%m%d-%H%M%S).castWith remote desktop
--desktop starts a remote desktop when you enter, even if the container was created without one.
Start desktop when entering a container
rfswift container shell -c my_container --desktopThen open http://127.0.0.1:6080 in your browser.
Expose on all interfaces with password
rfswift container shell -c my_container \
--desktop --desktop-config "http:0.0.0.0:6080" \
--desktop-pass "mysecretpass"Use VNC client instead of browser
rfswift container shell -c my_container \
--desktop --desktop-config "vnc::5900"With SSL/TLS encryption
rfswift container shell -c my_container \
--desktop --desktop-config "http:0.0.0.0:6080" \
--desktop-pass "mysecretpass" --desktop-sslWith VPN
Start Tailscale when entering a container
rfswift container shell -c my_sdr --vpn tailscaleWireGuard on a privileged container
rfswift container shell -c my_sdr --vpn wireguard:./wg0.confNetbird with setup key
rfswift container shell -c my_sdr --vpn netbird:nb-setup-xxxxxxxxxxxxWorking directory examples
Start in projects directory
rfswift container shell -c dev_container -w /root/projectsStart in captures directory
rfswift container shell -c sdr_work -w /root/capturesStart in mounted volume
rfswift container shell -c analysis -w /mnt/dataEveryday workflows
Resume assessment work
# Yesterday's work
rfswift container create -i network -n client_assessment \
-b ~/client-work:/root/work
# Today - resume where you left off
rfswift container shell -c client_assessment -w /root/workDebug with recording
rfswift container shell -c problematic_container \
--record \
--record-output troubleshooting-$(date +%Y%m%d-%H%M).castQuick check on running container
# Check what's running
rfswift container last
# Jump into most recent
rfswift container shell
# Or specific one
rfswift container shell -c sdr_captureMultiple sessions in same container
# Terminal 1
rfswift container shell -c sdr_analysis -w /root/captures
# Terminal 2 (different session, same container)
rfswift container shell -c sdr_analysis -w /root/toolsDetailed explanations
Container selection (-c, --container)
Which container to enter. You can give:
- the container name you chose at creation;
- the container ID, in full or its first characters;
- nothing: the most recently created container is used.
How auto-selection works
# These containers were created in this order:
# 1. sdr_container
# 2. wifi_container
# 3. bluetooth_container (most recent)
rfswift container shell
# Enters: bluetooth_container (most recent)
rfswift container shell -c sdr_container
# Enters: sdr_container (explicit)Finding container names
# List recent containers
rfswift container last
# Show all containers
docker ps -a
# Show only running containers
docker psPartial container ID matching
# Full ID
rfswift container shell -c a1b2c3d4e5f6g7h8
# Short form (first 12 chars)
rfswift container shell -c a1b2c3d4e5f6
# Minimal (first few unique chars)
rfswift container shell -c a1b2Working directory (-w, --workdir)
The folder you start in. Handy to land directly in a project folder or a mounted volume.
- Default:
/root. - The folder must exist inside the container.
Common working directories
# User home
-w /root
# Project directory
-w /root/projects
# Captures directory
-w /root/captures
# Mounted volume
-w /mnt/shared
# Tool directory
-w /opt/tools
# Temporary work
-w /tmp/analysisNon-existent directory
# This will fail if directory doesn't exist
rfswift container shell -c container -w /root/nonexistent
# Fix: create it in the container first, or bind it from the host
rfswift config bindings add -c container -s /pathto/projects -t /root/projects
rfswift container shell -c container -w /root/projectsSession recording
Records the whole terminal session, for documentation, debugging or training. The recording captures what you type, what the tools print, and the timing, so it plays back exactly as it happened.
Without --record-output, the file is named rfswift-exec-{container}-{YYYYMMDD-HHMMSS}.cast:
rfswift container shell -c my_container --record
# Creates: rfswift-exec-my_container-20240112-143022.castRecording indicator: while recording, the terminal title reads ⏺ REC | RF Swift, and RFSWIFT_RECORDING=1 is set so scripts can detect it.
Custom filenames
# Simple name
--record-output session.cast
# With date
--record-output session-$(date +%Y%m%d).cast
# Full path
--record-output ~/recordings/client-assessment.cast
# Organized structure
--record-output ~/assessments/client-$(date +%Y%m%d)/session.castWhere the file goes:
- with an automatic name: the current folder on your computer;
- with
--record-output: the path you give.
Nothing changes inside the shell itself (only the terminal title). Typing exit ends the recording.
Playback
rfswift log replay -i session.cast
rfswift log replay -i session.cast -s 2.0 # 2x speedContainer states
container shell works whatever state the container is in.
Running containers
Most common use case
# Container is already running
docker ps | grep my_container
# Shows running container
rfswift container shell -c my_container
# Enters immediatelyStopped containers
Container was previously stopped
# Container exists but is stopped
docker ps -a | grep my_container
# Shows exited container
rfswift container shell -c my_container
# RF Swift automatically starts the container, then enters itWhat happens:
- RF Swift sees that the container is stopped.
- It starts the container (
docker start). - It waits until the container is ready.
- It opens the interactive shell.
Non-Existent containers
Error handling
rfswift container shell -c nonexistent_container
# Error: No such container: nonexistent_container
# Fix: create the container first
rfswift container create -i image -n nonexistent_containerShell behavior
Default shell
RF Swift containers use zsh by default, with Oh My Zsh, syntax highlighting, auto-completion and a prompt that shows the container name.
Terminal prompt example
┌─[root@container_name] - [/root/projects] - [Thu Jan 12, 14:30]
└─[$]>Multiple sessions
You can open several shells in the same container at once:
# Terminal 1
rfswift container shell -c my_container
# Terminal 2 (simultaneously)
rfswift container shell -c my_container
# Both sessions work in the same container
# Changes in one are visible in the otherThis is useful to watch logs in one terminal while you work in another, to keep a long capture running while you use other tools, or to record different tasks separately.
Common workflows
Daily assessment workflow
# Morning: Start fresh
rfswift container create -i network -n daily_work -b ~/work:/root/work
# Throughout day: Enter as needed
rfswift container shell -c daily_work
# Exit and return multiple times
exit
rfswift container shell -c daily_work
# End of day: Stop but keep for tomorrow
rfswift container stop -c daily_work
# Next morning: Resume
rfswift container shell -c daily_work # Auto-starts and entersDevelopment workflow
# Setup development container
rfswift container create -i sdr_full -n sdr_dev \
-b ~/code:/root/code \
-b ~/.gitconfig:/root/.gitconfig:ro
# Edit code on host with your IDE
# Test in container
rfswift container shell -c sdr_dev -w /root/code
cd my_project
./build.sh
./test.sh
exit
# Repeat edit-test cycle
rfswift container shell -c sdr_dev -w /root/codeTroubleshooting workflow
# Issue reported in container
rfswift container shell -c problematic_container --record
# Investigate and record findings
ps aux
df -h
netstat -tulpn
exit
# Share recording with team
rfswift log replay -i rfswift-exec-problematic_container-*.castTraining workflow
# Instructor prepares example
rfswift container create -i sdr_full -n training_demo \
-s /dev/bus/usb:/dev/bus/usb
# Record demonstration
rfswift container shell -c training_demo \
--record \
--record-output training-lesson-01.cast
# Demonstrate tools and techniques
rtl_test -t
gqrx
exit
# Students replay later
rfswift log replay -i training-lesson-01.cast -s 1.5Create vs shell
| Aspect | container create |
container shell |
|---|---|---|
| Purpose | Create new container | Enter existing container |
| Container state | Creates new | Uses existing |
| Image required | Yes | No |
| Configuration | Full options available | Limited options |
| Use when | Starting new work | Continuing existing work |
| Typical frequency | Once per project | Multiple times per day |
Typical flow
# Day 1: create it
rfswift container create -i sdr_full -n project -b ~/work:/root/work
# Every day after: enter it
rfswift container shell -c project
# ... work ...
exit
# Come back as often as you need
rfswift container shell -c projectTroubleshooting
Container not found
The error message is: Error: No such container: container_name
To fix it:
# List all containers to find correct name
rfswift container last
# Maybe it was removed?
rfswift container create -i image -n container_nameContainer won’t start
The container fails to start when you enter it.
To fix it:
# Check container status
docker ps -a | grep container_name
# Check logs
docker logs container_name
# Try manual start
docker start container_name
# If still fails, recreate
rfswift container rm -c container_name
rfswift container create -i image -n container_nameWorking directory doesn’t exist
The error message is: cannot change directory to '/root/nonexistent'
To fix it:
# Use default directory
rfswift container shell -c container
# Create directory in container
rfswift container shell -c container
mkdir -p /root/nonexistent
exit
# Or bind from host
rfswift config bindings add -c container -s /pathto/host-dir -t /root/nonexistent
rfswift container shell -c container -w /root/nonexistentRecording fails
--record doesn’t work.
To fix it:
# Check if asciinema is installed on host
which asciinema
# Install if missing (Ubuntu/Debian)
sudo apt-get install asciinema
# Install on macOS
brew install asciinema
# Verify recording works
asciinema rec test.cast
# Press Ctrl+D
asciinema play test.castPermission issues inside container
You can’t open some files or folders.
To fix it:
# Check file permissions inside container
rfswift container shell -c container
ls -la /path/to/file
# Fix permissions inside container
chmod 755 /path/to/file
chown root:root /path/to/file
# Or fix on host (for mounted volumes)
exit
chmod 755 ~/host-path/file
rfswift container shell -c containerTerminal display issues
Terminal formatting looks wrong.
To fix it:
# Reset terminal
rfswift container shell -c container
reset
# Or clear screen
clear
# Set correct TERM
export TERM=xterm-256colorMultiple containers with similar names
A partial name matches more than one container.
To fix it:
# Use full container name
rfswift container shell -c full_container_name
# Or use container ID
docker ps -a # Get full ID
rfswift container shell -c a1b2c3d4e5f6
# List recent to identify
rfswift container lastAdvanced usage
Run one command without a shell
Pass the command with -e. The container is started if needed, and the command runs with the container’s environment (display, audio, workspace):
rfswift container shell -c container_name -e "rtl_test -t"
rfswift container shell -c container_name -e "ulimit -r"Enter as different user
RF Swift containers run as root. To switch to another user inside the container:
# Inside container
rfswift container shell -c container
su - usernameCustom shell environment
# Inside container, customize environment
rfswift container shell -c container
# Set custom aliases
echo 'alias ll="ls -la"' >> ~/.zshrc
echo 'alias scan="rtl_test -t"' >> ~/.zshrc
# Reload
source ~/.zshrcRelated commands
container create: create a new containercontainer stop: stop a running containercontainer last: list recent containerscontainer rm: delete a containerlog: replay recorded sessionsconfig bindings: add devices and folders to a container- VPN inside containers: the VPN setup guide
- Using Podman: Podman specifics
Tip: add a shell alias such as alias rfe='rfswift container shell', then type rfe to enter your most recent container.
While recording: the terminal title shows ⏺ REC | RF Swift. Everything you type and see is captured, so avoid typing secrets.