{"id":13586907,"url":"https://github.com/keithrbennett/wifiwand","last_synced_at":"2025-05-15T10:15:41.848Z","repository":{"id":56898216,"uuid":"102190748","full_name":"keithrbennett/wifiwand","owner":"keithrbennett","description":"A command line tool to manage wifi, including an interactive shell (currently Mac only)","archived":false,"fork":false,"pushed_at":"2024-12-11T17:30:12.000Z","size":874,"stargazers_count":70,"open_issues_count":8,"forks_count":6,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-23T13:49:53.322Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/keithrbennett.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-09-02T11:02:44.000Z","updated_at":"2025-04-10T04:43:09.000Z","dependencies_parsed_at":"2024-06-19T03:07:37.373Z","dependency_job_id":null,"html_url":"https://github.com/keithrbennett/wifiwand","commit_stats":{"total_commits":290,"total_committers":4,"mean_commits":72.5,"dds":"0.020689655172413834","last_synced_commit":"2a6d96cac96602f328893889feac34742a4a3ac6"},"previous_names":[],"tags_count":26,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keithrbennett%2Fwifiwand","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keithrbennett%2Fwifiwand/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keithrbennett%2Fwifiwand/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/keithrbennett%2Fwifiwand/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/keithrbennett","download_url":"https://codeload.github.com/keithrbennett/wifiwand/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254319634,"owners_count":22051077,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T15:05:53.781Z","updated_at":"2025-05-15T10:15:41.818Z","avatar_url":"https://github.com/keithrbennett.png","language":"Ruby","funding_links":[],"categories":["Ruby","System Utilities"],"sub_categories":["Directory Navigation"],"readme":"![logo](logo/wifiwand-logo-horizontal-color.png)\n\n# wifi-wand\n\nTo install this software, run:\n\n`gem install wifi-wand`\n\nor, you may need to precede that command with `sudo`:\n\n`sudo gem install wifi-wand`\n\nThe `wifi-wand` gem enables the query and management \nof WiFi configuration and environment on a Mac.\nThe code encapsulates the Mac OS specific logic in model classes \nto more easily add support for other operating systems,\nbut as of now, only Mac OS is supported. (Feel free to add an OS!)\n\nIt can be run in single-command or interactive mode. \nInteractive mode uses the [pry](https://github.com/pry/pry) gem,\nproviding an interface familiar to Rubyists and other \n[REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) users.\n\n\n### Usage\n\nAvailable commands can be seen by using the `h` (or `help`) option. Here is its\noutput at the time of this writing:\n\n```\n$ wifi-wand -h\nCommand Line Switches:                    [wifi-wand version 2.14.0 at https://github.com/keithrbennett/wifiwand]\n\n-o {i,j,k,p,y}            - outputs data in inspect, JSON, pretty JSON, puts, or YAML format when not in shell mode\n-p wifi_interface_name    - override automatic detection of interface name with this name\n-s                        - run in shell mode\n-v                        - verbose mode (prints OS commands and their outputs)\n\nCommands:\n\na[vail_nets]              - array of names of the available networks\nci                        - connected to Internet (not just wifi on)?\nco[nnect] network-name    - turns wifi on, connects to network-name\ncy[cle]                   - turns wifi off, then on, preserving network selection\nd[isconnect]              - disconnects from current network, does not turn off wifi\nf[orget] name1 [..name_n] - removes network-name(s) from the preferred networks list\n                            in interactive mode, can be a single array of names, e.g. returned by `pref_nets`\nh[elp]                    - prints this help\ni[nfo]                    - a hash of wifi-related information\nna[meservers]             - nameservers: 'show' or no arg to show, 'clear' to clear,\n                            or IP addresses to set, e.g. '9.9.9.9  8.8.8.8'\nne[twork_name]            - name (SSID) of currently connected network\non                        - turns wifi on\nof[f]                     - turns wifi off\npa[ssword] network-name   - password for preferred network-name\npr[ef_nets]               - preferred (saved) networks\nq[uit]                    - exits this program (interactive shell mode only) (see also 'x')\nro[pen]                   - open resource ('cap' (Portal Logins), 'ipl' (IP Location), 'ipw' (What is My IP), 'libre' (LibreSpeed), 'spe' (Speed Test), 'this' (wifi-wand home page))\nt[ill]                    - returns when the desired Internet connection state is true. Options:\n                            1) 'on'/:on, 'off'/:off, 'conn'/:conn, or 'disc'/:disc\n                            2) wait interval between tests, in seconds (optional, defaults to 0.5 seconds)\nw[ifi_on]                 - is the wifi on?\nx[it]                     - exits this program (interactive shell mode only) (see also 'q')\n\nWhen in interactive shell mode:\n  * remember to quote string literals.\n  * for pry commands, use prefix `%`.\n```\n\nInternally, it uses several Mac command line utilities to interact with the\nunderlying operating system.\n\n### Pretty Output\n\nFor nicely formatted output of the `info` command in non-interactive mode,\nthe `awesome_print` gem is used if it is installed;\notherwise, the somewhat less awesome pretty print (`pp`) is used.  Therefore,\ninstallation of the `awesome_print` gem is recommended. \nThis is accomplished by the following command:\n\n`gem install awesome_print`\n\nYou may need to precede this command with `sudo `, especially if you are using the \nversion of Ruby that comes packaged with MacOS.\n\n\n### JSON, YAML, and Other Output Formats\n\nYou can specify that output in _noninteractive_ mode be in a certain format.\nCurrently, JSON, \"Pretty\" JSON, YAML, inspect, and puts formats are supported.\nSee the help for which command line switches to use.\n\n\n### Seeing the Underlying OS Commands and Output\n\nIf you would like to see the Mac OS commands and their output, \nyou can do so by specifying \"-v\" (for _verbose_) on the command line.\n\nYou may notice that some commands are executed more than once. This is to simplify the application logic\nand eliminate the need for the complexity of balancing the speed that a cache offers and the risk\nof stale data.\n\n\n### Troubleshooting\n\nIf you try to run the shell, the script will require the `pry` gem, so that will need to be installed.\n`pry` in turn requires access to a `readline` library. If you encounter an error relating to finding a\n`readline` library, this can probably be fixed by installing the `pry-coolline` gem: `gem install pry-coolline`.\nIf you are using the Ruby packaged with Mac OS, or for some other reason require root access to install\ngems, you will need to precede those commands with `sudo`:\n\n```\nsudo gem install pry\nsudo gem install pry-coolline\n```\n\n\n### Using the Shell\n\n_If the program immediately exits when you try to run the shell, try upgrading `pry` and `pry-byebug`.\nThis can be done by running `gem install pry; gem install pry-byebug`._\n\nThe shell, invoked with the `-s` switch on the command line, provides an interactive\nsession. It can be useful when:\n\n* you want to issue multiple commands\n* you want to combine commands\n* you want the data in a format not provided by this application\n* you want to incorporate these commands into other Ruby code interactively\n* you want to combine the results of commands with other OS commands \n  (you can shell out to run other command line programs by preceding the command with a period (`.`))   .\n\n\n### Using Variables in the Shell\n\nThere are a couple of things (that may be surprising) to keep in mind\nwhen using the shell. They relate to the fact that local variables\nand method calls use the same notation in Ruby (since use of parentheses\nin a method call is optional):\n\n1) In Ruby, when both a method and a local variable have the same name,\nthe local variable will override the method name. Therefore, local variables\nmay override this app's commands.  For example:\n\n```\n[1] pry(#\u003cWifiWandView\u003e)\u003e n  # network_name command\n=\u003e \".@ AIS SUPER WiFi\"\n[2] pry(#\u003cWifiWandView\u003e)\u003e n = 123  # override it with a local variable\n=\u003e 123\n[3] pry(#\u003cWifiWandView\u003e)\u003e n  # 'n' no longer calls the method\n=\u003e 123\n[4] pry(#\u003cWifiWandView\u003e)\u003e ne  # but any other name that `network_name starts with will still call the method\n=\u003e \".@ AIS SUPER WiFi\"\n[5] pry(#\u003cWifiWandView\u003e)\u003e network_name\n=\u003e \".@ AIS SUPER WiFi\"\n[6] pry(#\u003cWifiWandView\u003e)\u003e ne_xzy123\n\"ne_xyz123\" is not a valid command or option. If you intend for this to be a string literal, use quotes.\n``` \n\nIf you don't want to deal with this, you could use global variables, instance variables,\nor constants, which will _not_ hide the methods:\n\n```\n[7] pry(#\u003cWifiWandView\u003e)\u003e N = 123\n[8] pry(#\u003cWifiWandView\u003e)\u003e @n = 456\n[9] pry(#\u003cWifiWandView\u003e)\u003e $n = 789\n[10] pry(#\u003cWifiWandView\u003e)\u003e puts n, N, @n, $n\n.@ AIS SUPER WiFi\n123\n456\n789\n=\u003e nil\n```\n\n2) If you accidentally refer to a nonexistent variable or method name,\nthe result may be mysterious.  For example, if I were write the WiFi information\nto a file, this would work:\n\n```\n[1] pry(#\u003cWifiWandView\u003e)\u003e File.write('x', info)\n=\u003e 431\n```\n\nHowever, if I forget to quote the filename, the program exits:\n\n```\n[2] pry(#\u003cWifiWandView\u003e)\u003e File.write(x, info)\n➜  wifi-wand git:(master) ✗  \n```\n\nWhat happened? `x` was assumed by Ruby to be a method name.\n`method_missing` was called, and since `x` is the exit\ncommand, the program exited.\n\nBottom line is, be careful to quote your strings, and you're probably better off using \nconstants or instance variables if you want to create variables in your shell. \n\n\n\n### Examples\n\n#### Single Command Invocations\n\n```\nwifi-wand i            # prints out wifi info\nwifi-wand a            # prints out names of available networks\nwifi-wand pr           # prints preferred networks\nwifi-wand cy           # cycles the wifi off and on\nwifi-wand co a-network a-password # connects to a network requiring a password\nwifi-wand co a-network            # connects to a network _not_ requiring a password\nwifi-wand t on \u0026\u0026 say \"Internet connected\" # Play audible message when Internet becomes connected\n```\n\n#### Interactive Shell Commands\n\nWhen in shell mode, commands generally return the target object (e.g. the array of\navailable networks) rather than outputting a nicely formatted string. \nThis is intentional, so that you can compose expressions and in general\nhave maximum flexibility. The result may be that `pry` displays \nthat returned value in an ugly way.\n\nIf you don't need the return value but just want to display the value nicely,\nyou can use the `fancy_puts` method to output it nicely. An alias `fp` has been\nprovided for your convenience. You're welcome!  For example:\n\n```\n[5] pry(#\u003cWifiWand::CommandLineInterface\u003e)\u003e fp pr.first(3)\n[\n    [0] \"  AIS SMART Login\",\n    [1] \" BubblesLive\",\n    [2] \"#HKAirport Free WiFi\"\n]\n```\n\nFor best display results, be sure `awesome_print` is `gem install`ed.\nThe program will silently use a not-as-nice formatter without it.\n(This silence is intentional, so that users who don't want to install\n`awesome-print` will not be bothered.)\n\nIf you want to suppress output altogether (e.g. if you are using the value in an\nexpression and don't need to see it displayed,\nyou can simply append `;nil` to the expression\nand `nil` will be value output to the console. For example:\n\n```\n[10] pry(#\u003cWifiWand::CommandLineInterface\u003e)\u003e available_networks = avail_nets; nil\n=\u003e nil\n```\n\n#### Using the Models Without the Command Line Interface\n\nThe code has been structured so that you can call the models\nfrom your own Ruby code, bypassing the command line interface.\nHere is an example of how to do that:\n\n```ruby\nrequire 'wifi-wand'\nmodel = WifiWand::MacOsModel.new\nputs model.available_network_names.to_yaml # etc...\n```\n\n\n**More Examples**\n\n(For brevity, semicolons are used here to put multiple commands on one line, \nbut these commands could also each be specified on a line of its own.)\n\n```\n# Print out WiFi info:\ni\n\n# Cycle (off/on) the network then connect to the specified network not requiring a password\n\u003e cycle; connect 'my-network'\n\n# Cycle (off/on) the network, then connect to the same network not requiring a password\n\u003e @name = network_name; cycle; connect @name\n\n# Cycle (off/on) the network then connect to the specified network using the specified password\n\u003e cycle; connect 'my-network', 'my-password'\n\n\u003e @i = i; puts \"You are connected on port #{@i[:port]} to #{@i[:network]} on IP address #{@i[:ip_address]}.\"\nYou are connected on port en0 to .@ AIS SUPER WiFi on IP address 172.27.145.225.\n\n\u003e puts \"There are #{pr.size} preferred networks.\"\nThere are 341 preferred networks.\n\n# Delete all preferred networks whose names begin with \"TOTTGUEST\", the hard way:\n\u003e pr.grep(/^TOTTGUEST/).each { |n| forget(n) }\n\n# Delete all preferred networks whose names begin with \"TOTTGUEST\", the easy way.\n# 'forget' can take multiple network names, \n# but they must be specified as separate parameters; thus the '*'.\n\u003e forget(*pr.grep(/^TOTTGUEST/))\n\n# Define a method to wait for the Internet connection to be active.\n# (This functionality is included in the `till` command.)\n# Call it, then output celebration message:\n[17] pry(#\u003cWifiWandView\u003e)\u003e def wait_for_internet; loop do; break if ci; sleep 0.5; end; end\n[18] pry(#\u003cWifiWandView\u003e)\u003e wait_for_internet; puts \"Connected!\"\nConnected!\n\n# Same, but using a lambda instead of a method so we can use a variable name\n# and not need to worry about method name collision:\n@wait_for_internet = -\u003e { loop do; break if ci; sleep 0.5; end }\n@wait_for_internet.() ; puts \"Connected!\"\nConnected!\n```\n\n\n### Dependent Gems\n\nCurrently, no dependent gems are installed when this gem is installed.\nHowever, the program _will_ use other gems as follows:\n\n* `pry`, when the interactive shell is requested with the `-s` option\n* `awesome_print`, if it is found, to more nicely format output in non-interactive mode\n\nSo the user can avoid installing gems other than this one altogether\nas long as they don't need to use the interactive shell,\nand as long as they are comfortable with the less pretty output.\n\n\n### Public IP Information\n\nThe information hash will normally include information about the public IP address.\nHowever, the command that provides this information, `curl -s ipinfo.io`, will sometimes\nreturn this:\n\n`Rate limit exceeded. Subscribe to a paid plan to increase your usage limits` \n\nIf this happens, the public IP information will be silently omitted from the\ninformation hash. In this case, the web site 'https://www.iplocation.net/' is\nrecommended, and `wifi-wand ro ipl` on the command line or `ro 'ipl'` in the shell will\nopen that page in your browser for you.\n\n\n### Password Lookup Oddity\n\nYou may find it odd (I did, anyway) that even if you issue the password command \n(`mac_wifi password a-network-name`) using sudo, you will still be prompted \nwith a graphical dialog for both a user id and password. This is no doubt\nfor better security, but it's unfortunate in that it makes it impossible to fully automate this task.\n\nIn particular, it would be nice for the `cycle` command to be able to fetch the current network's\npassword, cycle the network, and then reconnect to the original network with it after turning the network on.\nHowever, since fetching the password without user intervention is not possible, this cannot be automated.\n\nIf you don't mind storing the network password in plain text somewhere, then you could easily\nautomate it (e.g. `wifi-wand cycle \u0026\u0026 wifi-wand connect a-network a-password`). Also, you might find it handy\nto create a script for your most commonly used networks containing something like this:\n\n```\nwifi-wand  connect  my-usual-network  its-password\n```\n\n### Airport Utility Deprecation (April 2024)\n\nStarting in Mac OS version 14.4, the `airport` utility on which some of this project's\nfunctionality relies has been disabled and will presumably eventually be removed.\n\nThe following tasks were restored by using Swift scripts:\n* listing names of all available networks\n* disconnecting from a network (with the added benefit that sudo access is no longer required)\n\nThe following tasks were restored by using `networksetup`:\n* determining whether or not wifi is on\n* the name of the currently connected network\n\nThe only remaining issue is that we were getting some extended information from airport for each available network. This extended information has now been removed in version 2.17.0.\n\nIn addition, the extended information about the available networks (`ls_avail_nets`) has been removed in version 2.17.0.\n\n\n### License\n\nApache 2 License (see LICENSE.txt)\n\n### Logo\n\nLogo designed and generously contributed by Anhar Ismail (Github: [@anharismail](https://github.com/anharismail), Twitter: [@aizenanhar](https://twitter.com/aizenanhar)).\n\n\n### Shameless Ad\n\nI am available for consulting, development, tutoring, training, troubleshooting, etc.\n\nYou can contact me via GMail, Twitter, Github, and LinkedIn, as _keithrbennett_.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeithrbennett%2Fwifiwand","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkeithrbennett%2Fwifiwand","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkeithrbennett%2Fwifiwand/lists"}