proxyctl

proxyctl is a keyboard-driven Linux TUI for coordinating one Active Profile across independently switchable proxy Targets. It manages proxy configuration surfaces; it does not run a proxy server.

Supported systems

The v1 binaries target Linux on amd64 and arm64. General TUI behavior and the Shell Target are distribution-independent. The supported Target boundaries are:

  • Shell: Bash and Zsh only.
  • APT: Debian-family systems with apt-config and apt.conf.d.
  • Docker daemon: Docker installations managed by systemd.
  • Docker containers/builds: the standard per-user Docker client config.json model.
  • GNOME: sessions exposing the expected org.gnome.system.proxy settings schemas.

Unavailable Targets are hidden from the main panel; ? opens contextual, scrollable Help over the current page and includes every built-in Target and its detection evidence.

Install

Verified release binary

Download the binary for your architecture together with SHA256SUMS, then verify it before installing:

grep 'proxyctl-linux-amd64$' SHA256SUMS | sha256sum -c -  # substitute arm64 when needed
chmod +x proxyctl-linux-amd64       # use proxyctl-linux-arm64 on arm64
install -m 0755 proxyctl-linux-amd64 "$HOME/.local/bin/proxyctl"
proxyctl version
proxyctl version --short            # exact value only, for scripts

Release output is two single binaries, not packages or archives. The project does not publish deb, rpm, AUR, Snap, Flatpak, or similar packages.

Install from source with Go

Go 1.24 or newer is required. From a source checkout:

go install ./cmd/proxyctl

The executable is placed in GOBIN, or in $(go env GOPATH)/bin when GOBIN is unset. Ensure that directory is on PATH. Source builds report dev unless a release version is injected by release automation.

First use and Profiles

Start the Target panel with no arguments:

proxyctl

Press m for Proxy Profile management, then n to create a Profile, enter a name and proxy URL, and press Ctrl+S to save. The editor supports cursor movement, Home, End, Delete, Backspace, insertion, paste, and horizontal scrolling; Tab or the arrow keys move between fields, and Escape cancels without saving. Validation stays beside each field. The management page supports reviewing obscured connection details, editing, and safe deletion; Active Profile switching remains a separate dashboard picker workflow rather than a management action. Single mode applies one URL to HTTP, HTTPS, and ALL/SOCKS. Ctrl+T selects advanced mode for separate values without discarding values entered in either mode. A bare host:port is accepted and normalized to http://. With the cursor in the Single proxy URL field, Ctrl+D runs the Protocol Probe, which detects whether the endpoint speaks HTTP or SOCKS5 and fills in the scheme. When one endpoint supports both protocols, the probe switches the form to advanced mode and fills HTTP/HTTPS with http:// and ALL/SOCKS with socks5://. Bypass accepts comma- or newline-delimited hostnames, domain suffixes, IPv4, IPv6, and CIDR entries; the editor previews normalized, deduplicated values and identifies invalid items before save.

The dashboard shows the Active Profile. Press p to open the searchable Active Profile picker, type to filter, use arrows to select, and press Enter to activate; Escape cancels without changing the Active Profile. Use arrows or j/k to select an Available Target and Space to run its contextual action: Enable, Disable, Apply Profile, or Resolve. Drift Resolution explicitly offers Reapply Active Profile and Restore Original; restoration refuses safely if proxyctl no longer has sufficient ownership evidence. Press r to refresh detection, u to show unavailable Targets, and ? on any page or dialog for contextual Help. Help scrolls with arrows, j/k, Page Up/Page Down, Home, and End; q or Escape closes it without changing the page, focus, selection, or viewport beneath it. Applying or reapplying requires an Active Profile, while Restore Original remains available without one.

Escape closes the top dialog or returns one page level. q returns from child pages and exits only from the unobscured dashboard (in the searchable Profile picker it remains search input). Ctrl+C requests exit everywhere. If a system mutation is running, either dashboard q or Ctrl+C visibly defers exit until the mutation completes safely; Target browsing and Help remain available while conflicting changes are disabled.

Profiles are human-readable under the user's XDG configuration directory (normally ~/.config/proxyctl/profiles.json) and are stored owner-only because proxy URLs may contain credentials.

Shell integration

A child TUI cannot change its parent Shell. Install the one-time Bash/Zsh startup hook:

proxyctl shell install

Restart or source the startup file once. Thereafter the wrapper reloads proxy exports and unsets after proxyctl exits. The Shell Target emits conventional upper- and lower-case HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, and NO_PROXY forms. Remove the hook with:

proxyctl shell uninstall

Fish and other Shells are intentionally unsupported in v1.

What each Target affects

  1. Shell — commands started by integrated Bash/Zsh sessions. It does not change existing processes, system services, Docker, or desktop settings.
  2. APT — persistent APT package operations across Shell and privilege boundaries through a tool-owned apt.conf.d overlay. It does not configure other package managers and requires no service restart.
  3. Docker daemon — daemon operations such as registry access. It does not set container networking or container/build defaults. Every change reloads systemd and immediately restarts Docker; confirm only when disruption to running work is acceptable.
  4. Docker containers/builds — proxy variables and build arguments for future containers and builds via the owning user's Docker client configuration. It does not affect existing containers, the Docker CLI connection, or the daemon.
  5. GNOME — GNOME system proxy settings used by compatible desktop applications. It does not rewrite browser-specific profiles or configure non-GNOME desktops. GNOME settings cannot express socks5h remote-DNS semantics, and the Protocol Probe fills socks5h for SOCKS-only endpoints; switch to advanced mode and enter socks5 when a SOCKS endpoint must work through the GNOME Target.

proxyctl prefers isolated, tool-owned overlays. Where that is impossible it records original values and a last-applied fingerprint so disable/reset can restore prior state safely.

Target states

  • Enabled: actual managed configuration matches the Active Profile.
  • Disabled: no managed or positively recognized external proxy configuration was detected.
  • External: a recognized proxy configuration exists but is not owned by proxyctl.
  • Drifted: managed configuration exists but no longer matches the Active Profile, including partial failures or configuration left when the final Profile is deleted.

External detection is best-effort; Disabled does not claim that every possible configuration source was exhaustively searched.

Permissions, sudo, and restarts

User Targets normally need only user-file permissions. APT and Docker daemon files generally require authority to write system locations, and Docker daemon operations require authority to reload/restart its systemd service.

proxyctl never runs sudo, pkexec, or another elevation mechanism. Permission failures are reported normally. If system Targets are wanted, the user must explicitly start sudo proxyctl; under sudo, the invoking user remains the owner of Profiles, Shell, Docker client, and GNOME configuration while current root authority is available to system Targets. In a direct root login, root is the owner. Review the Docker restart warning before confirming any daemon change.

Diagnose, reset, and remove

Run read-only diagnostics for Profile validity, storage permissions, required commands, Target availability/state, and Target-specific authority:

proxyctl doctor

Before removal, restore every managed Target. The command asks for confirmation and does nothing when declined:

proxyctl reset
proxyctl shell uninstall

Inspect failures and rerun until reset reports no failed managed Target. Then remove the installed executable and, after retaining any desired logs, remove empty proxyctl configuration/state directories. Do not delete recovery state before a successful reset because it may be needed to restore original settings.

Privacy and safety boundaries

proxyctl has no telemetry, automatic update checks, or automatic proxy-connectivity tests. It does not contact the network on its own; the only network traffic it generates is the user-initiated Protocol Probe (Ctrl+D in the Profile form), a handshake check that never forwards traffic through the proxy and never contacts anything beyond the endpoint itself. Local diagnostic logs are credential-redacted and bounded in size. Proxy credentials remain present where a selected Target requires them, so normal local file security still matters.

proxyctl does not manage or supervise proxy processes such as Clash, sing-box, or Xray. It does not manage subscriptions, nodes, latency, routing rules, transparent proxying, TUN/iptables/nftables, arbitrary services or commands, plugins, or a complete headless Profile/Target CLI.

Deferred integrations include DNF, Git-specific settings, npm/pip, arbitrary systemd services, Firefox policies, Chromium launch flags, KDE and other desktops, Snap/Ubuntu Core, Fish, Windows, macOS, distribution packages, mouse interaction, and cross-Target rollback. Conventional Shell variables may already cover some deferred command-line tools.

Support is limited to the Linux architectures and Target boundaries above. When reporting an issue, include proxyctl version, redacted proxyctl doctor output, distribution/desktop/Shell details, and the affected Target/state. Never include unredacted proxy credentials.

Build and verification

Create reproducible Linux binaries and checksums without packages or archives:

VERSION=v1.0.0 ./scripts/build-release.sh
sha256sum -c dist/SHA256SUMS
file dist/proxyctl-linux-amd64 dist/proxyctl-linux-arm64

./scripts/test-release.sh builds twice, compares binaries and checksum manifests, verifies both checksums, and checks ELF architectures. ./scripts/verify-clean-machine.sh uses an isolated identity and XDG roots to exercise go install, Profile and hermetic Target workflows, doctor, reset cancellation, Shell install/uninstall, removal, and unchanged host-state snapshots.

S
Description
Proxy management project
Readme
709 KiB
Languages
Go 98.7%
Shell 1.3%