The developer's network environment switcher — CLI + GUI, plugin-powered, team-ready.
Quick Start • Installation • GUI • CLI Usage • Configuration • Plugins • Architecture • Contributing
Every developer juggles multiple network environments daily — corporate proxies at the office, direct connections at home, VPN tunnels for client access, cloud-specific DNS for remote clusters. Each switch means manually updating HTTP_PROXY, HTTPS_PROXY, NO_PROXY, DNS servers, and /etc/hosts entries. Miss one setting and you'll spend 30 minutes debugging a connection that "just worked yesterday." Multiply this by every tool on your machine that respects proxy environment variables (Docker, npm, pip, kubectl, git) and the toil adds up fast.
Current workarounds range from shell aliases and dotfile scripts to platform-specific GUIs that only handle one piece of the puzzle. None of them give you a single source of truth for your entire network footprint — proxy, DNS, hosts, and tool-specific configs — let alone the ability to share those configs with your team, encrypt secrets at rest, or trigger switches automatically based on the Wi-Fi network you just joined.
net-switch changes that. Define your environments once in a YAML file. Switch between them with a single command. Let rules detect your context and switch automatically. Share profiles with your team through encrypted sync. And when you need a visual overview, launch the desktop GUI — all from the same project, the same config, the same workflow.
| Feature | Description |
|---|---|
| ⚡ One-Command Switch | Set proxy, DNS, hosts, and env vars in a single net-switch use <profile> |
| 🔌 Plugin System | Interface-based architecture with EventBus, lifecycle hooks, and manifest-driven loading |
| 🔒 Config Encryption | AES-256-GCM field-level encryption with PBKDF2 key derivation — secrets stay safe at rest |
| 🔄 Auto-Switch Rules | Trigger profile changes on domain, IP, SSID, or process detection |
| ☸️ Kubernetes Integration | List, switch, and namespace-manage kubectl contexts from the CLI |
| 👥 Team Sync | Pull/push profiles via REST API with conflict resolution and merge strategies |
| 🖥️ GUI Desktop App | Tauri v2 + React 18 + TypeScript + Tailwind CSS native desktop application |
| 🌐 Cross-Platform | Windows, macOS, and Linux — ARM64 and AMD64 |
| 🧪 Dry-Run Mode | Preview every change before it happens with --dry-run |
| 📜 JSON Output | Machine-readable --format json on every command for scripting and CI |
| 🔑 OAuth2 + PKCE | Secure team authentication without sharing passwords |
Suitable for users who prefer command-line operations, lightweight and fast.
Prerequisites:
- Go 1.26 or later
Steps:
# Clone the repository
git clone https://github.com/wuqi789/net-switch.git
cd net-switch
# Build directly with Go
go build -o bin/net-switch ./cmd/netenv/The compiled binary will be in the bin/ directory.
A cross-platform desktop application built with Tauri v2 + React 18 + TypeScript + Tailwind CSS.
| Application Home | Team Sync | Config Encryption |
![]() |
![]() |
![]() |
| Plugin Management | Auto Rules | Configuration |
![]() |
![]() |
![]() |
The GUI source lives in a separate repository net-switch-gui:
github.com/wuqi789/
├── net-switch/ # CLI project (this repo)
└── net-switch-gui/ # GUI project (separate repo)
Prerequisites:
Steps:
# 1. Clone the GUI repo
git clone https://github.com/wuqi789/net-switch-gui.git
cd net-switch-gui
# 2. Install GUI dependencies
npm install
# 3. Start the GUI (dev mode)
npm run tauri devThe first launch compiles the Rust backend and may take a few minutes. Subsequent launches use incremental compilation and are much faster.
Features include:
- Visual profile management with status indicators
- Real-time network status monitoring dashboard
- Team sync panel for pulling and pushing profiles
- Encrypted config editing with a built-in YAML editor
- Auto-switch rule configuration with visual triggers
- Plugin management with lifecycle visualization
- Dark and light theme support
$ net-switch list
Available network environments:
─────────────────────────────────────
▸ company - Corporate network
vpn - VPN environment
test - Test environment
direct - Direct connection (no proxy)
─────────────────────────────────────
Use 'net-switch use <profile>' to switch environmentJSON output for scripting:
$ net-switch list --format json
[
{
"name": "company",
"description": "Corporate network",
"http_proxy": "http://proxy.company.com:8080",
"https_proxy": "http://proxy.company.com:8080",
"no_proxy": "localhost,127.0.0.1,.company.com",
"has_dns": true,
"hosts_count": 2
}
]$ net-switch use company --dry-run
[DRY-RUN] Would apply profile: company
HTTP_PROXY: http://proxy.company.com:8080
HTTPS_PROXY: http://proxy.company.com:8080
NO_PROXY: localhost,127.0.0.1,.company.com
DNS: [10.0.0.1 10.0.0.2]
Hosts: 2 entries$ net-switch use company
✓ Switched to: company
Description: Corporate network
HTTP_PROXY: http://proxy.company.com:8080
HTTPS_PROXY: http://proxy.company.com:8080
NO_PROXY: localhost,127.0.0.1,.company.com
DNS: [10.0.0.1 10.0.0.2]
Hosts: 2 entries$ net-switch current
Current profile: company$ net-switch status
Profile: company
HTTP Proxy: http://proxy.company.com:8080
HTTPS Proxy: http://proxy.company.com:8080
DNS: 10.0.0.1, 10.0.0.2
Hosts entries: 2$ net-switch restore
✓ Restored to previous network configuration$ net-switch encrypt
✓ Configuration encrypted (AES-256-GCM)
$ net-switch decrypt
✓ Configuration decrypted$ net-switch rules list
NAME ENABLED TRIGGER PROFILE
office-wifi true SSID: CorpNet company
home-wifi true SSID: Home-5G direct
client-vpn false IP: 10.50.0.0/16 client
$ net-switch rules test "SSID: CorpNet"
✓ Matched rule: office-wifi → company
$ net-switch rules disable office-wifi
✓ Rule disabled: office-wifi$ net-switch auth login
✓ Logged in as: dev@company.com
$ net-switch sync pull
✓ Pulled 3 profiles from team server
company (updated)
staging (new)
prod (conflict — merged)
$ net-switch sync push
✓ Pushed 1 profile to team server
home-dev (created)$ net-switch k8s list
CONTEXT CLUSTER NAMESPACE CURRENT
minikube minikube default ✓
prod-cluster eks-prod kube-system
staging-cluster eks-staging default
$ net-switch k8s switch prod-cluster
✓ kubectl context switched to: prod-cluster
$ net-switch k8s ns monitoring
✓ Namespace set to: monitoring$ net-switch plugin list
PLUGIN VERSION STATUS DESCRIPTION
k8s 0.1.0 active Kubernetes context and namespace management
echo 0.1.0 active Example plugin that echoes profile switches
$ net-switch plugin info k8s
Name: k8s-plugin
Version: 0.1.0
Author: netenv
Description: Kubernetes context and namespace management plugin
Permissions: kubernetes, filesystem
Commands: k8s list, k8s switch, k8s current, k8s ns--config string Config file path (default: ./config.yaml or ~/.net-switch/config.yaml)
--dry-run Preview mode — show what would change without modifying anything
--format string Output format: text or json (default: text)
net-switch reads configuration from ./config.yaml in the current directory or ~/.net-switch/config.yaml.
version: "1"
current_profile: company
profiles:
- name: company
description: "Corporate network"
http_proxy: "http://proxy.corp.com:8080"
https_proxy: "http://proxy.corp.com:8080"
no_proxy: "localhost,127.0.0.1,.corp.com"
dns:
servers:
- 10.0.0.53
- 10.0.0.54
hosts:
- ip: 10.0.1.100
hostname: "git.corp.com"
- ip: 10.0.1.101
hostname: "registry.corp.com"
- name: home
description: "Home network — no proxy"
http_proxy: ""
https_proxy: ""
dns:
servers:
- 8.8.8.8
- 1.1.1.1
- name: cloud-dev
description: "Cloud development cluster"
http_proxy: "socks5://127.0.0.1:1080"
https_proxy: "socks5://127.0.0.1:1080"
no_proxy: "localhost,127.0.0.1,10.0.0.0/8"
dns:
servers:
- 169.254.169.254
hosts:
- ip: 10.20.0.100
hostname: "api.staging.internal"
- ip: 10.20.0.101
hostname: "db.staging.internal"
- ip: 10.20.0.102
hostname: "cache.staging.internal"
- name: direct
description: "Direct connection — no proxy, system DNS"
http_proxy: ""
https_proxy: ""--configflag (highest priority)./config.yamlin current working directory~/.net-switch/config.yaml(user home)
net-switch's plugin architecture is built around a clean Plugin interface with well-defined lifecycle hooks.
Init → Validate → Apply → Rollback → Cleanup
| Phase | When It Runs | Purpose |
|---|---|---|
Init |
Plugin loaded | Register commands, set up resources |
Validate |
Before switch | Verify profile is valid for this plugin |
Apply |
During switch | Execute the plugin's switching logic |
Rollback |
On failure | Undo partial changes |
Cleanup |
Plugin unloaded | Release resources |
Plugins communicate through an EventBus — a pub/sub system that decouples plugins from each other. A plugin can emit events (e.g., profile.switched) and subscribe to events from other plugins.
| Plugin | Description |
|---|---|
k8s |
Kubernetes context and namespace management plugin |
echo |
Example plugin that echoes profile switches |
Implement the Plugin interface in Go, create a manifest.yaml, and place the compiled binary in the plugins directory. See CONTRIBUTING.md for a full guide.
type Plugin interface {
Manifest() Manifest
Init(ctx PluginContext) error
Cleanup() error
Validate(profile *config.Profile) error
Apply(ctx *ExecutionContext) error
Rollback(ctx *ExecutionContext) error
}┌─────────────┐ ┌─────────────┐
│ CLI (cobra) │ │ GUI (Tauri) │
└──────┬──────┘ └──────┬──────┘
│ │
└─────────┬─────────┘
│
┌─────────▼─────────┐
│ Switcher │
│ (orchestration) │
└─────────┬─────────┘
│
┌────────────┼────────────┐
│ │ │
┌───▼───┐ ┌────▼────┐ ┌────▼────┐
│Network│ │ Plugin │ │ Crypto │
│Manager│ │ System │ │ Module │
└───┬───┘ └────┬────┘ └─────────┘
│ │
┌───▼───┐ ┌────▼────┐
│Windows│ │ K8s │
│Linux │ │ Rules │
│macOS │ │ Sync │
└───────┘ └─────────┘
Layer overview:
- CLI / GUI — Two entry points sharing the same core logic. The CLI uses cobra; the GUI uses Tauri with a React frontend.
- Switcher — The orchestration layer that coordinates profile application across all subsystems.
- Network Manager — Platform-specific implementations for proxy settings, DNS configuration, and hosts file management.
- Plugin System — Extensible architecture with EventBus, manifest-driven loading, and permission-based sandboxing.
- Crypto Module — AES-256-GCM encryption with PBKDF2 key derivation for config security.
| Feature | net-switch | CC-Switch |
|---|---|---|
| CLI | ✅ Full-featured | ✅ Basic |
| GUI | ✅ Tauri desktop | ❌ None |
| Plugin System | ✅ Extensible | ❌ None |
| Config Encryption | ✅ AES-256-GCM | ❌ None |
| Auto-Switch Rules | ✅ Domain/IP/SSID | ❌ None |
| K8s Integration | ✅ Context switching | ❌ None |
| Team Sync | ✅ REST API | ❌ None |
| OAuth2 Auth | ✅ PKCE flow | ❌ None |
| Cross-Platform | ✅ Win/Mac/Linux | |
| Config Format | ✅ YAML | |
| Dry-Run Mode | ✅ Built-in | ❌ None |
| JSON Output | ✅ All commands | ❌ None |
| Open Source | ✅ MIT |
We welcome contributions of all kinds — bug reports, feature requests, documentation, and code.
Please read CONTRIBUTING.md before submitting a pull request. It covers:
- Development environment setup
- Code style and conventions
- Plugin development guide
- Testing requirements
- Pull request process
git clone https://github.com/wuqi789/net-switch.git
cd net-switch
go build ./cmd/net-switch
./net-switch listgo test ./...This project is licensed under the MIT License — see the LICENSE file for details.
MIT License
Copyright (c) 2024-2026 netenv
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
Made with ❤️ by netenv
⭐ Star us on GitHub •
Report a Bug •
Join the Discussion
Developer: 吴棋 • wuqi173@outlook.com





