How to Replace Deprecated ‘airport’ Command Line Application

airportcommand lineNetworkwifi

I am the author of the wifi-wand Ruby gem and command line application that reports and modifies wifi networking information on the Mac (https://github.com/keithrbennett/wifiwand). The airport utility on which many of wifi-wand's commands rely is now deprecated (as of Sonoma 14.4 or thereabouts, I believe), and no longer provides any functionality. (As a side note, is it common to report deprecation and remove the functionality in the same version? This caught me off guard and disabled functionality on which users rely. Or did I miss something?)

Can you help me find alternatives that can be run from a command line program, i.e. not GUI apps, that can provide the following functionality that airport provided?:

  • list the available wifi networks' names
  • list the available wifi networks' details
  • disconnect from the currently connected network (without turning off wifi)

EDIT: I previously included the 2 below in the above list but found options to networksetup that worked:

  • report the currently connected wifi network name
  • report whether or not the wifi is currently turned on

I would prefer not to have to use sudo to run any of these; wifi-wand is used in scripting and as a library that other applications can access.

Also, asking the users to install another utility (e.g. via brew) is not ideal but would be preferable to nothing at all.

Best Answer

I did more research, and the simplest solution I could find was to use Swift to access CoreWLAN to provide the needed functionality, that is:

  • list the available wifi networks' names
  • disconnect from the currently connected network (without turning off wifi)

Unfortunately, CoreWLAN is only available for systems on which XCode has been installed. I was tempted to replace all tasks with Swift, so as not to have to parse text output in command line applications (both for simplicity and reliability, since parsing this text is not 100% errorproof), but decided (for now at least) to leave as much as possible as is so that those without XCode could still use most of the application's functionality.

Here are the Swift programs I am currently using:

AvailableWifiNetworkLister.swift

import Foundation
import CoreWLAN

class NetworkScanner {
    var currentInterface: CWInterface
    
    init?() {
        // Initialize with the default Wi-Fi interface
        guard let defaultInterface = CWWiFiClient.shared().interface(),
              defaultInterface.interfaceName != nil else {
            return nil
        }
        self.currentInterface = defaultInterface
        self.scanForNetworks()
    }
    
    func scanForNetworks() {
        do {
            let networks = try currentInterface.scanForNetworks(withName: nil)
            for network in networks {
                print("\(network.ssid ?? "Unknown")")
            }
        } catch let error as NSError {
            print("Error: \(error.localizedDescription)")
        }
    }
}

NetworkScanner()

WifiNetworkDisconecter.swift

import Foundation
import CoreWLAN

if let wifiInterface = CWWiFiClient.shared().interface() {
    wifiInterface.disassociate()
    print("ok")
} else {
    print("error")
}

The Ruby code that ingests these respective outputs is:

  def run_swift_command(basename)
    swift_filespec = File.join(
      File.dirname(__FILE__), "../../../swift/#{basename}.swift"
    )
    command = "swift #{swift_filespec}"
    `#{command}`
  end
# ...
    run_swift_command('AvailableWifiNetworkLister').split("\n")
# ...
    run_swift_command('WifiNetworkDisconecter')
# ...