cli: adopt the subcommand etiquette of the established VPN clis #180

Open
opened 2026-08-27 18:02:26 -04:00 by mysticalsoap · 0 comments
Owner

The cli works (as of #178) but its interface is an upstream-inherited flag soup with interactive traps. Comparing against the established VPN clis (Mullvad, ProtonVPN, Tailscale, NordVPN) shows a consistent etiquette worth adopting.

What the peers converged on:

  • Subcommand verbs, not flags: mullvad connect / disconnect / status / relay set location se mma; protonvpn-cli c / d / s; tailscale up / down / status. Nobody ships -c/-t/-v flag combos as the primary interface.
  • A status command. Every peer has one; it is the single most-used verb. mullvad status even shows the multihop chain ("Connected Relay: se-got via dk-cph"). aqomui-cli has nothing — -o dumps settings, not connection state.
  • Selection by intent, not exact key: country/city/fastest/random (mullvad relay set location se, protonvpn-cli c --cc US -f), with exact server names as the power-user form. aqomui-cli demands the exact server key and drops into an interactive readline retry loop on a typo — which also makes it script-hostile.
  • Multihop as a setting on connect (mullvad relay set entry location <country>), not a separate flag that silently changes what -c does.
  • Non-interactive safety: prompts only where unavoidable (credentials) and only on a TTY; everything else takes arguments and fails with an exit code. Machine-readable output where it matters (status/list).

Current warts, concretely:

  • -e/-d with an invalid option prints the literal "{}" is not a valid option — the .format(o) call is missing at both sites.
  • "Succesfully" typos in user-facing strings.
  • A connect waits on D-Bus signals with no timeout and no progress; any unhandled outcome hangs forever (the doublehop issue is the extreme case, but a plain never-establishing connect also waits indefinitely).
  • The readline autocomplete loop on unknown server names blocks scripts.
  • -l matching is exact-lowercase against all field values; no output for "show me what I can pass to -c" beyond the full dump.
  • Help text still enumerates settings by hand ([autoconnect] [firewall] ...) instead of deriving from config.default_settings.

Suggested direction (after #125, which gives the cli the catalog's query/selection layer — profile resolution, fastest/random, favourites — instead of hand-rolled lookups):

  • argparse subparsers: connect [--via HOP] SERVER, disconnect, status, list [FILTERS], protocol PROVIDER, import PROVIDER, remove PROVIDER, set OPTION VALUE / options. Keep the old flags as hidden aliases or drop them — the fork owes upstream's cli nothing.
  • status reads the service's tunnel state (the state it already tracks per role) and shows main/hop/bypass.
  • Timeouts on every signal wait, non-zero exit codes on failure.
  • Fix the two .format bugs and typos ahead of the restructure — they're one-line.

The peer conventions above are from documentation, not exhaustive local testing — re-check details if mirroring a specific tool's syntax.

The cli works (as of #178) but its interface is an upstream-inherited flag soup with interactive traps. Comparing against the established VPN clis (Mullvad, ProtonVPN, Tailscale, NordVPN) shows a consistent etiquette worth adopting. **What the peers converged on:** - **Subcommand verbs, not flags**: `mullvad connect` / `disconnect` / `status` / `relay set location se mma`; `protonvpn-cli c` / `d` / `s`; `tailscale up` / `down` / `status`. Nobody ships `-c`/`-t`/`-v` flag combos as the primary interface. - **A `status` command.** Every peer has one; it is the single most-used verb. `mullvad status` even shows the multihop chain ("Connected Relay: se-got via dk-cph"). aqomui-cli has nothing — `-o` dumps settings, not connection state. - **Selection by intent, not exact key**: country/city/fastest/random (`mullvad relay set location se`, `protonvpn-cli c --cc US -f`), with exact server names as the power-user form. aqomui-cli demands the exact server key and drops into an interactive readline retry loop on a typo — which also makes it script-hostile. - **Multihop as a setting on connect** (`mullvad relay set entry location <country>`), not a separate flag that silently changes what `-c` does. - **Non-interactive safety**: prompts only where unavoidable (credentials) and only on a TTY; everything else takes arguments and fails with an exit code. Machine-readable output where it matters (status/list). **Current warts, concretely:** - `-e`/`-d` with an invalid option prints the literal `"{}" is not a valid option` — the `.format(o)` call is missing at both sites. - "Succesfully" typos in user-facing strings. - A connect waits on D-Bus signals with no timeout and no progress; any unhandled outcome hangs forever (the doublehop issue is the extreme case, but a plain never-establishing connect also waits indefinitely). - The readline autocomplete loop on unknown server names blocks scripts. - `-l` matching is exact-lowercase against all field values; no output for "show me what I can pass to -c" beyond the full dump. - Help text still enumerates settings by hand (`[autoconnect] [firewall] ...`) instead of deriving from `config.default_settings`. **Suggested direction** (after #125, which gives the cli the catalog's query/selection layer — profile resolution, fastest/random, favourites — instead of hand-rolled lookups): - argparse subparsers: `connect [--via HOP] SERVER`, `disconnect`, `status`, `list [FILTERS]`, `protocol PROVIDER`, `import PROVIDER`, `remove PROVIDER`, `set OPTION VALUE` / `options`. Keep the old flags as hidden aliases or drop them — the fork owes upstream's cli nothing. - `status` reads the service's tunnel state (the state it already tracks per role) and shows main/hop/bypass. - Timeouts on every signal wait, non-zero exit codes on failure. - Fix the two `.format` bugs and typos ahead of the restructure — they're one-line. The peer conventions above are from documentation, not exhaustive local testing — re-check details if mirroring a specific tool's syntax.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
mysticalsoap/aqomui#180
No description provided.