Output #

VPN service names and statuses, such as Tailscale connected, Work connecting, with a state-dependent icon. The default label sorts services by name and omits disconnected services. Here, active means any service that is not disconnected, including connecting, disconnecting, and unavailable services. With no active services, the item shows VPN disconnected. Omitting the vpn block is equivalent to vpn: {}.

Failed reads show VPN unavailable, or the affected service’s name followed by unavailable. Known active names remain visible when another service cannot be read.

Configuration #

Use the item-level text template to customise or hide the label.

Set these options inside vpn.

PropertyDefaultDescription
showSymboltrueShow the state icon; false hides even an item-level symbol override.
hideWhenDisconnectedfalseHide only a confirmed disconnected state. Failed reads remain visible.
symbols.font-Shared installed font name for glyph symbols; each glyph can override it.
symbols.sizeResolved item/theme font sizeShared glyph size, 8 to 72 points; each glyph can override it.
symbols state keysIcons belowOverride symbols for the five connection states.
tints state keysNormal tintState colours for the same five states; accept #RRGGBB or #RRGGBBAA.

States and labels #

symbols and tints accept these state keys:

State keyDefault symbolDefault label
connectingarrow.triangle.2.circlepathconnecting
connectedlock.shield.fillconnected
disconnectingarrow.triangle.2.circlepathdisconnecting
disconnectedlock.shielddisconnected
unavailableexclamationmark.shieldunavailable

With multiple services, the overall icon, tint, and aggregate label use the first present state in this order: unavailable, connected, connecting, disconnecting, disconnected. Each visible service keeps its own status label.

Use a services loop with state conditions to customise each service label. Use text: "VPN {{status}}" for an aggregate label or text: "" for an icon alone. Accessibility retains the native names and statuses.

Appearance #

Symbols accept SF Symbol names or font glyph objects. Use symbolFontWeight to set SF Symbol weight independently of text.

An item-level symbol overrides the state icon. showSymbol: false hides all symbols, including this override. Omitted state symbols use the built-in defaults. State tints override the normal item/theme tint.

To change vpn, edit the configuration file. sbar set cannot change this block.

Shared item options cover styling, symbols, actions, priority, and enabled state.

Text templates #

The item-level text setting supports id, value, symbol, status, names, connected, available, services, name, serviceId, index, total, first, last, separator. See text templates for syntax and collection rules.

services includes all monitored VPN services, including disconnected ones. Unavailable service lists are empty; stale entries are not rendered. The default value and names list active services only.

{
  "id": "vpn",
  "type": "vpn",
  "text": "{{#services}}{{name}}: {{#status=connected}}Connected{{/status}}{{^status=connected}}{{status}}{{/status}}{{#separator}}, {{/separator}}{{/services}}{{^services}}{{value}}{{/services}}"
}

Entries sort by name, with their identifier breaking ties. The provider collapses whitespace in names to one line. Unnamed entries use VPN. The provider treats names as literal text, even if they contain template tags. names is sorted and comma-separated.

FieldMeaning inside a loop
nameService name
statusIndividual service status
connectedWhether the entry is connected
availableVPN service status is not unavailable
serviceIdProvider identifier
indexOne-based position in the sorted list
first, lastPosition flags for the source list
valueDefault entry label, such as Work connected
totalCollection count, also available outside the loop
idThe containing item ID

Outside the loop, status follows the precedence in States and labels, and connected is true only when that aggregate status is connected. An unavailable service takes precedence, so connected is false even if another service is connected.

Aggregate available means the service list was read successfully. It can be true while an individual service is unavailable. Inside a loop, available instead reports whether that service’s status is not unavailable.

value outside the loop is the default combined label. Entry-only fields are empty outside the loop. Use an inverse collection section for an empty-list fallback.

Loops produce plain text with the item’s overall symbol and tint. They preserve accessibility descriptions and hide rules. Loops use the same snapshot as other template fields and do not trigger extra scans or queries.

This shows connected VPN services, with commas only between visible names:

{
  "id": "vpn",
  "type": "vpn",
  "text": "{{#connected}}{{#services}}{{#connected}}{{name}}{{/connected}}{{#separator}}, {{/separator}}{{/services}}{{/connected}}{{^connected}}{{value}}{{/connected}}"
}

If Home is disconnected and Office and Work are connected, the label is Office, Work. If Office disconnects, it becomes Work. If none are connected, the outer aggregate condition supplies the default label, such as VPN disconnected. It also preserves the default error label when an unavailable service takes precedence over connected services. A {{^services}} fallback would run only if the service list itself were empty.

Updates #

Items and displays share one native event monitor. The provider reads the service list when enabled, then follows SystemConfiguration service and connection notifications. Unavailable reads retry every two seconds.

Refresh policies capture service states, text, icon, tint, and visibility together. Interval and manual items hold their snapshot until refreshed or triggered. Triggers capture the latest shared state. See refresh policies.

Current limits #

Detects enabled Network Extension, IPSec, and L2TP VPN services registered with macOS. The provider cannot detect standalone tunnels that do not register a macOS service. Templates can filter which services appear in the label, but the provider still monitors all detected services. There is no monitoring filter or built-in connect/disconnect control.

A connected state reports the service’s status. It does not establish whether all traffic uses the VPN or whether the remote network is reachable. Use the Network provider for the active network connection type.

Example #

{
  "id": "vpn",
  "type": "vpn",
  "vpn": {
    "hideWhenDisconnected": true,
    "tints": {
      "connected": "#A6DA95",
      "connecting": "#EED49F",
      "unavailable": "#ED8796"
    }
  }
}

This hides the item only when all detected services are disconnected, including when no services are registered. Connecting, disconnecting, and unavailable states remain visible.

Search docs

Enter a word or command.