Skip to content

Instantly share code, notes, and snippets.

@rnmhdn
Created May 12, 2026 09:06
Show Gist options
  • Select an option

  • Save rnmhdn/f44607d962e014904d2b6bd059be0b6a to your computer and use it in GitHub Desktop.

Select an option

Save rnmhdn/f44607d962e014904d2b6bd059be0b6a to your computer and use it in GitHub Desktop.
A lightweight Awesome WM widget that displays V2Ray proxy status with Wi‑Fi connection awareness. Toggle your proxy with a single click, with visual feedback that makes your connection state immediately clear.

Proxy Toggle Widget for Awesome WM

A lightweight Awesome WM widget that displays V2Ray proxy status with Wi‑Fi connection awareness. Toggle your proxy with a single click, with visual feedback that makes your connection state immediately clear.

Features

  • Wi‑Fi aware: Automatically detects Wi‑Fi connection state
  • Visual indicators: Clear icons for all states
  • Single-click toggle: Left click to toggle V2Ray proxy (only when Wi‑Fi is connected)
  • Manual refresh: Right click to refresh status without toggling
  • Error notifications: Alerts you when operations fail or Wi‑Fi is unavailable
  • Singleton pattern: Ensures only one instance exists

Display States

State Icon Description
Wi‑Fi disconnected 🌚 No Wi‑Fi connection detected
Wi‑Fi connected, proxy off 📡 Connected but V2Ray is not running
Wi‑Fi connected, proxy on 🚀 Connected with V2Ray proxy active

Installation

1. Install the Toggle Script

Save the V2Ray toggle script to a location in your $PATH (e.g., ~/.local/bin/v2ray-toggle):

#!/bin/bash

# The config file you want to use
CONFIG="$HOME/.config/v2ray/latest.json"

# Check if v2ray is already running
if pgrep -f "v2ray run" > /dev/null; then
    # It's running → kill it
    pkill -f "v2ray run"
    echo off              # signal the new state
else
    # Not running → start it (detached)
    v2ray run -c "$CONFIG" &> /dev/null &
    echo on               # signal the new state
fi

Make it executable:

chmod +x ~/.local/bin/v2ray-toggle

Note: The widget expects this script to output either on or off to stdout and return exit code 0 on success. Feel free to adapt the CONFIG path and process matching pattern to your setup.

2. Install the Widget

Copy the widget file to your Awesome WM configuration directory:

cp proxytoggle.lua ~/.config/awesome/

3. Require in Your Configuration

Add the widget to your rc.lua:

local proxytoggle = require("proxytoggle")

Usage

Basic Setup

Add the widget to your wibar or any other widget container:

-- Create the widget with defaults
local proxy_widget = proxytoggle()

-- Add to your wibar
s.mywibox:setup {
    -- ... other widgets ...
    proxy_widget,
    -- ... other widgets ...
}

Custom Configuration

The widget accepts configuration options during creation:

local proxy_widget = proxytoggle({
    interface = "wlp2s0",        -- Network interface to monitor
    command = "v2ray-toggle",    -- Command to toggle V2Ray
    initial_state = false        -- Initial V2Ray state (true if running)
})

Parameters

  • interface (string): Network interface name monitored via nmcli. Default: "wlp2s0"
  • command (string): Path or name of the toggle script. Default: "v2ray-toggle"
  • initial_state (boolean): Starting V2Ray state. Set to true if V2Ray is running at widget creation. Default: false

Mouse Controls

  • Left click: Toggle V2Ray (if Wi‑Fi is connected)
  • Right click: Refresh Wi‑Fi status and update the icon

Requirements

  • Awesome WM 4.x
  • NetworkManager with nmcli command available
  • V2Ray installed and configured
    • Config file at ~/.config/v2ray/latest.json (or update the toggle script)
  • The v2ray-toggle script accessible in your $PATH

How It Works

  1. On left click: The widget checks Wi‑Fi status first
  2. If Wi‑Fi is connected: It runs the toggle script
  3. The toggle script:
    • Checks if V2Ray is running (via pgrep)
    • If running: kills V2Ray and outputs off
    • If not running: starts V2Ray with your config and outputs on
  4. The widget reads the output and updates the icon accordingly

Wi‑Fi Disconnected

  • Left clicks show an error notification: "Wi‑Fi is not connected"
  • V2Ray state remains unchanged
  • Widget shows 🌚

Wi‑Fi Connected

  • Left click toggles V2Ray on/off
  • Widget updates to reflect new proxy state
  • Shows 🚀 (V2Ray running) or 📡 (V2Ray stopped)

Error Handling

  • Failed Wi‑Fi checks trigger a critical notification
  • Failed toggle commands trigger a critical notification
  • Errors are non-blocking and won't crash Awesome WM

Customizing the Toggle Script

If your V2Ray setup differs, modify the toggle script:

  • Different config path: Change the CONFIG variable
  • Different process name: Update the pgrep/pkill pattern (e.g., "v2ray" vs "v2ray run")
  • Different commands: Replace v2ray run with systemctl --user start v2ray if using systemd

The only requirement is that the script:

  • Outputs exactly on or off to stdout
  • Returns exit code 0 on success

License

Free to use and modify. Attribution appreciated.

Credits

Created by Aran and DeepSeek AI.

---------------------------------------------------------------------------
--- Proxy toggle widget with Wi‑Fi connection awareness.
-- Wi‑Fi disconnected → 🌚
-- Wi‑Fi connected, proxy off → 📡
-- Wi‑Fi connected, proxy on → 🚀
-- Left click : if Wi‑Fi off → notify error; else toggle proxy.
-- Right click : refresh Wi‑Fi status and update icon only.
-- @author Aran and Deepseek
-- @classmod awful.widget.proxytoggle
---------------------------------------------------------------------------
local capi = { awesome = awesome }
local setmetatable = setmetatable
local textbox = require("wibox.widget.textbox")
local button = require("awful.button")
local gtable = require("gears.table")
local widget_base = require("wibox.widget.base")
local spawn = require("awful.spawn")
local naughty = require("naughty")
local proxy_toggle = { mt = {} }
-- Determine the icon based on Wi‑Fi and proxy status.
local function get_display_icon(self)
if not self._wifi_on then
return "🌚 " -- Wi‑Fi disconnected
elseif self._proxy_enabled then
return "🚀 " -- Wi‑Fi connected + proxy on
else
return "📡 " -- Wi‑Fi connected + proxy off
end
end
-- Update the widget’s visible text.
local function update_display(self)
self.widget:set_text(get_display_icon(self))
end
-- Check Wi‑Fi status (nmcli on the given interface) and run optional callback.
local function refresh_wifi(self, callback)
spawn.easy_async(
"nmcli -t -f GENERAL.STATE device show " .. self._interface,
function(stdout, stderr, reason, exit_code)
if reason ~= "exit" or exit_code ~= 0 then
naughty.notify {
title = "Proxy Toggle",
text = "Cannot check Wi‑Fi status",
preset = naughty.config.presets.critical,
}
return
end
-- "100 (connected)" or "30 (disconnected)" etc.
self._wifi_on = (stdout:match("^GENERAL.STATE:100") ~= nil)
update_display(self)
if callback then callback(self._wifi_on) end
end
)
end
-- Left‑click handler: check Wi‑Fi, then notify or toggle.
local function check_and_toggle(self)
refresh_wifi(self, function(wifi_on)
if not wifi_on then
-- Wi‑Fi is not connected: show error and don’t touch the proxy
naughty.notify {
title = "Proxy Toggle",
text = "Wi‑Fi is not connected",
preset = naughty.config.presets.critical,
}
else
-- Wi‑Fi is connected: run the toggle command and flip proxy state
spawn.easy_async(
self._command, -- v2ray-toggle script
function(stdout, _, reason, exit_code)
if reason ~= "exit" or exit_code ~= 0 then
naughty.notify {
title = "Proxy Toggle",
text = "Toggle command failed",
preset = naughty.config.presets.critical,
}
else
-- Parse the output: expects "on" or "off"
self._proxy_enabled = (stdout:match("^on") ~= nil)
end
update_display(self)
end
)
end
end)
end
--- Create a proxy toggle widget.
-- @tparam table args
-- @tparam string args.interface Network interface name (default: "wlp2s0").
-- @tparam string args.command Shell cmd to toggle proxy (default: "v2ray-toggle").
-- @tparam boolean args.initial_state Start proxy state (default: false).
-- @return widget
function proxy_toggle.new(args)
args = args or {}
local widget = textbox()
local self = widget_base.make_widget(widget)
self.widget = widget
self._interface = args.interface or "wlp2s0"
self._command = args.command or "v2ray-toggle"
self._proxy_enabled = args.initial_state or false
self._wifi_on = false -- real value will be set asynchronously
-- Initial status check
refresh_wifi(self)
-- Mouse bindings
self:buttons(
gtable.join(
button({}, 1, function() check_and_toggle(self) end), -- left
button({}, 3, function() refresh_wifi(self) end) -- right
)
)
return self
end
-- Singleton
local _instance = nil
function proxy_toggle.mt:__call(...)
if _instance == nil then
_instance = proxy_toggle.new(...)
end
return _instance
end
return setmetatable(proxy_toggle, proxy_toggle.mt)
-- vim: filetype=lua:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
#!/bin/bash
# The config file you want to use
CONFIG="$HOME/.config/v2ray/latest.json"
# Check if v2ray is already running
if pgrep -f "v2ray run" > /dev/null; then
# It's running → kill it
pkill -f "v2ray run"
echo off # signal the new state
else
# Not running → start it (detached)
v2ray run -c "$CONFIG" &> /dev/null &
echo on # signal the new state
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment