CLI & TUI · CLI reference
CLI reference
secvf-cli is a Swift-Argument-Parser binary that wraps every operation the GUI does — VM lifecycle, switch state, packet capture, USB, TUI launch. Built for headless work, scripting, and CI integrations.
On this page
Install / build
The CLI ships in the SecVF repo as a Swift package at SecVF/cli/. Build it with:
cd SecVF/cli
swift build # debug build
swift build -c release # release build (use this for daily use)
# resulting binary
.build/debug/secvf-cli # or .build/release/secvf-cli
Make it available on PATH:
# symlink (portable)
ln -s "$(pwd)/.build/release/secvf-cli" ~/.local/bin/secvf
# or copy
cp .build/release/secvf-cli /usr/local/bin/secvf
Verify:
$ secvf --version
1.0.0
$ secvf --help
OVERVIEW: SecVF - Security Virtualization Framework CLI
USAGE: secvf <subcommand>
SUBCOMMANDS:
vm Virtual machine management commands
usb USB device management commands
switch Virtual network switch commands
capture Packet capture commands
tui Launch the Terminal User Interface
DistributedNotificationCenter. list, status, and read-only commands work standalone; start, stop, and similar require SecVF.app running. The CLI tells you so explicitly when it can't reach the app.
Global options
Every subcommand accepts:
| Flag | What it does |
|---|---|
--json | Output as JSON. Use for scripting. Failure path emits {"success": false, "message": "..."}. |
-v, --verbose | Extra diagnostic detail on stderr. |
--help | Print help for the current subcommand. |
secvf vm
Eleven subcommands cover the VM lifecycle.
vm list
secvf vm list # all VMs
secvf vm list --status running # only running
secvf vm list --os-type linux # only Linux guests
secvf vm list --json # for parsing
vm create
secvf vm create <name> \
--os linux \
--distro kali \
--cpu 2 \
--ram 4096 \
--disk 64 \
--network nat \
[--router] # mark as security router VM
[--start] # start immediately after creation
Defaults: --os linux --distro kali --cpu 2 --ram 4096 --disk 64 --network nat. Distros: kali, ubuntu, debian, fedora, arch, manjaro. Network modes: nat, virtual, isolated.
vm start / vm stop
secvf vm start <name>
secvf vm stop <name> [--force] # --force = pull the plug
# (no --force = ACPI graceful)
vm status
secvf vm status <name>
# Prints: state, uptime, CPU/RAM allocated, network mode, IP if known
vm delete
secvf vm delete <name> [--force]
# Without --force, prompts for confirmation.
# Bundle moves to Trash (recoverable until emptied).
vm ssh
Convenience wrapper that finds the VM's IP and opens SSH.
secvf vm ssh <name> [--user agent] [--key ~/.ssh/secvf.pem]
vm exec
Run a one-shot command in the guest. For AI sandbox guests, uses vsock — much faster than SSH.
secvf vm exec <name> -- 'uname -a'
secvf vm exec ai-session-xyz -- 'clang --version'
secvf vm exec my-kali --timeout 30 -- 'nmap -sn 10.0.100.0/24'
vm copy-to / vm copy-from
Push or pull files between host and guest. Uses VirtioFS when available, scp fallback otherwise.
secvf vm copy-to <name> ./payload.bin /tmp/payload.bin
secvf vm copy-from <name> /var/log/syslog ./syslog.txt
vm snapshot
Bundle-level clone (uses APFS CoW under the hood). Stopped VMs only.
secvf vm snapshot <name> --as <new-name>
# Result: ~/.avf/Linux/<new-name>.bundle/ — fresh MachineIdentifier, same data
secvf switch
switch status
$ secvf switch status
VIRTUAL NETWORK SWITCH
--------------------------------------------------
Status: ● RUNNING
Ports: 3/8 connected
MACs Learned: 5
Uptime: 1h 42m 7s
switch stats / switch stats --watch
$ secvf switch stats
SWITCH STATISTICS
--------------------------------------------------
Packets Forwarded: 14,732
Packets Broadcast: 89
Packets Dropped: 0
Bytes Transferred: 12.42 MB
RX: 6.21 MB TX: 6.21 MB
$ secvf switch stats --watch --interval 0.5
# Live, clear-screen update every 500 ms
switch ports
$ secvf switch ports
PORT VM NAME MAC ADDRESS RX TX
-----------------------------------------------------------------
0 kali-router 52:54:00:a1:b2:c3 3.2 MB 3.2 MB
1 ubuntu-malware 52:54:00:d4:e5:f6 1.8 MB 1.8 MB
2 ai-session-7b3a 52:54:00:99:88:77 234 KB 217 KB
switch macs
$ secvf switch macs
MAC ADDRESS PORT VM NAME AGE
-------------------------------------------------------
52:54:00:a1:b2:c3 0 kali-router 1m 2s
52:54:00:d4:e5:f6 1 ubuntu-malware 42s
52:54:00:99:88:77 2 ai-session-7b3a 11s
01:80:c2:00:00:0e 1 ubuntu-malware 8s (multicast)
secvf capture
capture start
secvf capture start \
[-i <iface>] # default: any (whole switch)
[-f "<BPF filter>"] # e.g. -f "tcp port 443"
[-o output.pcap] # write to disk as we capture
[--count N] # stop after N packets (0 = unlimited)
capture stop / capture status
$ secvf capture stop
✓ Packet capture stopped
Packets captured: 14,732
Bytes captured: 12.42 MB
$ secvf capture status
CAPTURE STATUS
----------------------------------------
Status: ● CAPTURING
Interface: any
Filter: tcp port 443
Packets: 7,431
Duration: 04:18
capture live
Streams packets to stdout, table-formatted.
secvf capture live # show everything
secvf capture live -f "dns" # display filter (Wireshark grammar)
secvf capture live -c 100 --details # 100 packets, full layer decode
capture export
secvf capture export out.pcap # pcap
secvf capture export out.json -f json # JSON-EK
secvf capture export out.csv -f csv # for spreadsheet
secvf capture export out.pcap --filter "tls" # filtered export
secvf capture export out.pcap --limit 1000
secvf usb
usb list
$ secvf usb list
DEVICE VENDOR TYPE MOUNTED TO STATUS
---------------------------------------------------------------------------
○ Kingston DT 32GB Kingston Physical -- Available
○ SanDisk Extreme SanDisk Physical -- Available
$ secvf usb list --include-virtual
# Adds virtual disks (e.g. Scripts USB images SecVF created)
usb mount
secvf usb mount "Kingston DT 32GB" --to kali-router
usb eject
secvf usb eject "Kingston DT 32GB"
usb create-virtual
Builds a virtual USB disk image (handy for shipping scripts into a guest).
secvf usb create-virtual \
--name secvf-scripts \
--size 256 \ # MB
--format dmg \ # or iso
--source ./scripts # contents to include
secvf tui
Launches the Textual-based terminal UI. See the TUI guide for the full UX. CLI usage:
secvf tui # launch interactively
secvf tui --show-path # print Python + TUI module paths
# (useful for debugging launch issues)
Requires Python 3.10+ and the secvf-tui package installed. The launcher hunts for Python at /opt/homebrew/bin, /usr/local/bin, /usr/bin, then PATH; rejects anything below 3.10.
JSON mode
Append --json to any subcommand. Schema is consistent:
{
"success": true,
"message": "Optional human-readable message",
"data": <subcommand-specific payload>
}
On failure:
{
"success": false,
"message": "VM 'foo' not found"
}
JSON output goes to stdout; verbose diagnostics still go to stderr.
Scripting recipes
Stop every running VM
secvf vm list --status running --json \
| jq -r '.data[].name' \
| xargs -I{} secvf vm stop {}
Snapshot before detonation, restore after
SAMPLE="$1"
VM="malware-sandbox"
SNAP="${VM}-clean"
# Snapshot once (if it doesn't already exist)
secvf vm list --json | jq -e ".data[]|select(.name==\"$SNAP\")" \
|| secvf vm snapshot "$VM" --as "$SNAP"
# Detonate
secvf vm start "$VM"
secvf capture start -o "/tmp/${SAMPLE}.pcap"
secvf vm exec "$VM" -- "/bin/bash /tmp/run.sh"
sleep 60
secvf capture stop
secvf vm stop "$VM" --force
# Restore
secvf vm delete "$VM" --force
secvf vm snapshot "$SNAP" --as "$VM"
Watch the switch and alert if drops climb
while true; do
drops=$(secvf switch stats --json | jq '.data.packetsDropped')
if [ "$drops" -gt 0 ]; then
osascript -e "display notification \"Switch dropping packets!\" with title \"SecVF\""
fi
sleep 10
done
Build the Scripts USB on demand
secvf usb create-virtual --name secvf-scripts \
--size 64 \
--format dmg \
--source ./scripts/router \
&& secvf usb mount secvf-scripts --to kali-router
Exit codes
| Code | Meaning |
|---|---|
0 | Success. |
1 | Generic failure (bad arguments, command not understood by GUI app). |
2 | Argument parsing error (Swift-Argument-Parser default). |
3 | SecVF.app not running but the operation requires it. |
4 | Resource not found (VM name, USB device, etc.). |
5 | Permission or entitlement failure. |