exec
rfswift container shell (exec)
Enter an existing container with an interactive shell, or run a single command in it. Stopped containers are started first.
rfswift container shell. 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 (rfswift env shell NAME is the dedicated form).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, an interactive picker lists your containers (the most recent one is marked); in a script the most recent container is used. Entering 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.
-c in an interactive terminal, RF Swift displays a scrollable container picker listing all containers with their name, ID, image, and state. The most recent container is marked with <- 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 sdrpp_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 run --vpn.
--vpn with exec, the VPN client starts inside the already-running container. For WireGuard/OpenVPN, the container must have been created with privileged mode (-u 1). See VPN Inside Containers for details.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 execEnter specific container by name:
rfswift exec -c my_sdr_containerEnter with specific working directory:
rfswift exec -c my_container -w /root/projectsEnter by container ID:
rfswift exec -c a1b2c3d4e5f6Short container ID:
rfswift exec -c a1b2c3With Session Recording
Record with auto-generated filename:
rfswift exec -c assessment --recordRecord with custom filename:
rfswift exec -c pentest --record --record-output debug-session.castRecord in specific directory with working dir:
rfswift exec -c analysis \
-w /root/data \
--record \
--record-output ~/recordings/analysis-$(date +%Y%m%d-%H%M%S).castWith Remote Desktop
The --desktop flag can be used with exec to start a remote desktop session on-the-fly, even if the container was originally created without desktop mode.
Start desktop when entering a container:
rfswift exec -c my_container --desktopThen open http://127.0.0.1:6080 in your browser.
Expose on all interfaces with password:
rfswift exec -c my_container \
--desktop --desktop-config "http:0.0.0.0:6080" \
--desktop-pass "mysecretpass"Use VNC client instead of browser:
rfswift exec -c my_container \
--desktop --desktop-config "vnc::5900"With SSL/TLS encryption:
rfswift exec -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 exec -c my_sdr --vpn tailscaleWireGuard on a privileged container:
rfswift exec -c my_sdr --vpn wireguard:./wg0.confNetbird with setup key:
rfswift exec -c my_sdr --vpn netbird:nb-setup-xxxxxxxxxxxxWorking Directory Examples
Start in projects directory:
rfswift exec -c dev_container -w /root/projectsStart in captures directory:
rfswift exec -c sdr_work -w /root/capturesStart in mounted volume:
rfswift exec -c analysis -w /mnt/dataReal-World Workflows
Resume assessment work:
# Yesterday's work
rfswift run -i pentest -n client_assessment \
-b ~/client-work:/root/work
# Today - resume where you left off
rfswift exec -c client_assessment -w /root/workDebug with recording:
rfswift exec -c problematic_container \
--record \
--record-output troubleshooting-$(date +%Y%m%d-%H%M).castQuick check on running container:
# Check what's running
rfswift last
# Jump into most recent
rfswift exec
# Or specific one
rfswift exec -c sdr_captureMultiple sessions in same container:
# Terminal 1
rfswift exec -c sdr_analysis -w /root/captures
# Terminal 2 (different session, same container)
rfswift exec -c sdr_analysis -w /root/toolsDetailed Explanations
Container Selection (-c, --container)
Specifies which container to enter. Accepts:
- Container name: Full name as specified during creation
- Container ID: Full or partial Docker container ID
- Auto-selection: If omitted, uses most recently created container
How auto-selection works:
# These containers were created in this order:
# 1. sdr_container
# 2. wifi_container
# 3. bluetooth_container (most recent)
rfswift exec
# Enters: bluetooth_container (most recent)
rfswift exec -c sdr_container
# Enters: sdr_container (explicit)Finding container names:
# List recent containers
rfswift last
# Show all containers
docker ps -a
# Show only running containers
docker psPartial container ID matching:
# Full ID
rfswift exec -c a1b2c3d4e5f6g7h8
# Short form (first 12 chars)
rfswift exec -c a1b2c3d4e5f6
# Minimal (first few unique chars)
rfswift exec -c a1b2Working Directory (-w, --workdir)
Sets the initial directory when entering the container. Useful for:
- Starting in project directories
- Continuing work in specific locations
- Accessing mounted volumes directly
Default behavior:
- If not specified:
/root(container default) - Directory must exist in container
- Can be any valid path
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 exec -c container -w /root/nonexistent
# Solution: Create in container first or bind from host
rfswift config bindings add -c container -s /pathto/projects -t /root/projects
rfswift exec -c container -w /root/projectsSession Recording
Records the entire terminal session for documentation, debugging, or training.
What gets recorded:
- All terminal input (commands typed)
- All terminal output (command results)
- Timing information for accurate playback
- Tool outputs and error messages
Auto-generated filenames:
Format: rfswift-exec-{container}-{YYYYMMDD-HHMMSS}.cast
rfswift exec -c my_container --record
# Creates: rfswift-exec-my_container-20240112-143022.castRecording indicator: During recording, the terminal title changes to ⏺ REC | RF Swift as a visual reminder. The environment variable RFSWIFT_RECORDING=1 is also set, which can be used by scripts to detect recording mode.
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.castRecording location:
- Auto-generated: Current working directory on host
- Custom: As specified in
--record-outputpath
During recording:
- No visible indication inside container
exitof the sessions ends recording
Playback:
rfswift log replay -i session.cast
rfswift log replay -i session.cast -s 2.0 # 2x speedContainer States
The exec command works with containers in different states:
Running Containers
Most common use case:
# Container is already running
docker ps | grep my_container
# Shows running container
rfswift exec -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 exec -c my_container
# RF Swift automatically starts the container, then enters itWhat happens:
- RF Swift detects container is stopped
- Starts the container with
docker start - Waits for container to be ready
- Enters with interactive shell
Non-Existent Containers
Error handling:
rfswift exec -c nonexistent_container
# Error: No such container: nonexistent_container
# Solution: Create container first
rfswift run -i image -n nonexistent_containerShell Behavior
Default Shell
RF Swift containers use zsh as the default shell with:
- Oh My Zsh configuration
- Syntax highlighting
- Auto-completion
- Custom prompt showing container name
Terminal prompt example:
┌─[root@container_name] - [/root/projects] - [Thu Jan 12, 14:30]
└─[$]>Multiple Sessions
You can have multiple exec sessions in the same container:
# Terminal 1
rfswift exec -c my_container
# Terminal 2 (simultaneously)
rfswift exec -c my_container
# Both sessions work in the same container
# Changes in one are visible in the otherUse cases:
- Monitor logs in one terminal while working in another
- Run long-running process in one, interact in another
- Separate recording sessions for different tasks
Common Workflows
Daily Assessment Workflow
# Morning: Start fresh
rfswift run -i pentest -n daily_work -b ~/work:/root/work
# Throughout day: Enter as needed
rfswift exec -c daily_work
# Exit and return multiple times
exit
rfswift exec -c daily_work
# End of day: Stop but keep for tomorrow
rfswift stop -c daily_work
# Next morning: Resume
rfswift exec -c daily_work # Auto-starts and entersDevelopment Workflow
# Setup development container
rfswift run -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 exec -c sdr_dev -w /root/code
cd my_project
./build.sh
./test.sh
exit
# Repeat edit-test cycle
rfswift exec -c sdr_dev -w /root/codeTroubleshooting Workflow
# Issue reported in container
rfswift exec -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 run -i sdr_full -n training_demo \
-s /dev/bus/usb:/dev/bus/usb
# Record demonstration
rfswift exec -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.5Comparison: run vs exec
| Aspect | run |
exec |
|---|---|---|
| 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 with run
rfswift run -i sdr_full -n project -b ~/work:/root/work
# Day 1-N: Enter with exec
rfswift exec -c project
# ... work ...
exit
# Repeat exec as needed
rfswift exec -c projectTroubleshooting
Container Not Found
Error: Error: No such container: container_name
Solutions:
# List all containers to find correct name
rfswift last
# Maybe it was removed?
rfswift run -i image -n container_nameContainer Won’t Start
Error: Container fails to start when entering stopped container
Solutions:
# 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 remove -c container_name
rfswift run -i image -n container_nameWorking Directory Doesn’t Exist
Error: cannot change directory to '/root/nonexistent'
Solutions:
# Use default directory
rfswift exec -c container
# Create directory in container
rfswift exec -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 exec -c container -w /root/nonexistentRecording Fails
Problem: --record flag doesn’t work
Solutions:
# 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
Problem: Can’t access files or directories
Solutions:
# Check file permissions inside container
rfswift exec -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 exec -c containerTerminal Display Issues
Problem: Terminal formatting looks wrong
Solutions:
# Reset terminal
rfswift exec -c container
reset
# Or clear screen
clear
# Set correct TERM
export TERM=xterm-256colorMultiple Containers with Similar Names
Problem: Partial name matches multiple containers
Solutions:
# Use full container name
rfswift exec -c full_container_name
# Or use container ID
docker ps -a # Get full ID
rfswift exec -c a1b2c3d4e5f6
# List recent to identify
rfswift lastAdvanced Usage
Execute Single Command (Non-Interactive)
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 by default. To change user:
# Inside container
rfswift exec -c container
su - username # solution for nowCustom Shell Environment
# Inside container, customize environment
rfswift exec -c container
# Set custom aliases
echo 'alias ll="ls -la"' >> ~/.zshrc
echo 'alias scan="rtl_test -t"' >> ~/.zshrc
# Reload
source ~/.zshrcRelated Commands
run- Create new containersstop- Stop running containerslast- List recent containersremove- Delete containerslog- Replay recorded sessionsbindings- Add devices/volumes to running containers- VPN Inside Containers - Detailed VPN setup guide
- Using Podman - Podman-specific guidance
alias rfe='rfswift exec' then just type rfe to enter your most recent container!--record, remember that your terminal title will show “🔴 RECORDING” as a visual reminder. Everything you type and see will be captured!