How to Contribute Code to the Amnezia-Client Project: A Complete Developer's Guide
To contribute code to the amnezia-client project, fork the amnezia-vpn/amnezia-client repository, set up a Qt 6 and CMake build environment, verify your changes compile across target platforms using the deploy scripts, and submit a pull request against the dev branch with properly formatted code.
Contributing to this cross-platform VPN client requires understanding its modular Qt/C++ architecture. The amnezia-vpn/amnezia-client repository splits functionality between the graphical interface, background service daemon, and server-side helpers, with build automation handled by CMake and Conan. This guide covers the complete workflow from environment setup to submission, referencing specific source files and build commands used by the maintainers.
Prerequisites and Development Environment
Before modifying any source files, install the required toolchain. The amnezia-client project builds with CMake 3.21+, Qt 6.10+ (Core, Qt 5 Compatibility, and Remote Objects modules), and Conan for dependency management.
Platform-specific requirements:
- Linux: GCC toolchain and
make - macOS: Xcode or Xcode command-line tools (Qt available via
homebrew install qt@6) - Windows: Visual Studio 2022 or Build Tools
- Android: Android SDK, NDK, and Ninja
Most continuous integration jobs use the scripts in deploy/, which auto-detect dependencies if installed in default locations.
Setting Up the Repository
Clone the repository and initialize submodules to pull vendored dependencies like OpenVPN and WireGuard:
git clone https://github.com/amnezia-vpn/amnezia-client.git
cd amnezia-client
git checkout dev
git submodule update --init --recursive
Always work against the dev branch, as main reflects stable releases.
Building the Project
The deploy/ directory contains platform-specific build scripts that invoke CMake with the correct toolchain settings.
Unix-like Systems (Linux/macOS)
./deploy/build.sh # Build host executables
./deploy/build.sh --installer all # Build installer packages
Windows
deploy\build.bat # Build host executables
deploy\build.bat --installer ifw # Build with Qt Installer Framework
Android
./deploy/build.sh -t android --aab # Build Android App Bundle
These scripts automatically set QT_INSTALL_DIR, ANDROID_HOME, and other environment variables. Run deploy/build.sh -h to view all available options.
Understanding the Architecture
The codebase organizes functionality into three high-level components. Knowing where to place your code ensures clean integration.
Client UI (client/)
Desktop and mobile graphical interfaces built with Qt 6. Key files include client/vpnConnection.cpp, which handles UI-level connection states and persists user settings via QSettings.
Service (service/src/)
The background daemon controlling VPN containers and platform networking. The entry point is service/src/qtservice.cpp, which exposes a common QtService interface regardless of platform. Platform-specific adapters like qtservice_win.cpp and qtservice_unix.cpp implement OS-level details.
Server Helpers (service/server/)
Pure C++ utilities for managing Docker-based VPN containers (XRay, WireGuard, OpenVPN). For example, service/server/xray.cpp wraps the XRay core binary, while service/server/router_linux.cpp handles routing tables.
All components communicate via the IPC layer defined in ipc/ipc_interface.rep, with shared utilities located in common/.
Making Changes
Adding UI Features
When extending the interface, inherit from QWidget or QMainWindow and register new files in client/CMakeLists.txt. For example, adding an auto-connect toggle in client/vpnConnection.cpp follows this pattern:
void VpnConnection::toggleAutoConnect(bool enabled) {
QSettings settings;
settings.setValue(QStringLiteral("AutoConnect"), enabled);
emit autoConnectChanged(enabled);
}
Extending Service Logic
To add functionality accessible from the UI, modify the IPC interface definition in ipc/ipc_interface.rep:
[method] GetLatestRelease()
{
string tag;
}
After editing the .rep file, the CI generates the corresponding C++ stub (ipc/ipc_interface.cpp). Implement the logic in service/src/qtservice.cpp, where platform-agnostic code calls the appropriate adapter.
Adding Server Protocols
New VPN protocols require extending the server helpers. Follow the existing pattern in service/server/router_linux.cpp:
bool RouterLinux::addRoute(const QString &cidr) {
QString cmd = QStringLiteral("ip route add %1 dev %2")
.arg(cidr, m_interface);
return system(cmd.toLocal8Bit().data()) == 0;
}
Register new source files in service/server/CMakeLists.txt and ensure they follow the *.cpp/*.h naming convention.
Code Quality and Submission
The project enforces code standards through automated checks. Before submitting:
-
Verify formatting using the project's
clang-formatconfiguration:git clang-format --style=file -i $(git diff --name-only) -
Build locally on your target platform using the
deploy/build.*scripts to catch compilation errors early. -
Update documentation in
README.mdif your change affects user-visible behavior or build requirements. -
Submit a Pull Request against the
devbranch with a clear description of what changed and how to test it.
The CI pipeline automatically runs the build scripts for all supported platforms (Linux, macOS, Windows, Android, iOS) and checks formatting compliance.
Summary
- Fork and branch from
amnezia-vpn/amnezia-client:devto isolate your changes. - Use the deploy scripts (
deploy/build.shordeploy/build.bat) to ensure consistent CMake configuration across platforms. - Place UI code in
client/, service logic inservice/src/, and Docker helpers inservice/server/. - Update IPC definitions in
ipc/ipc_interface.repwhen changing the UI-service contract. - Run
git clang-formatbefore committing to match the project's style requirements. - Reference specific files like
qtservice.cppandvpnConnection.cppto understand implementation patterns.
Frequently Asked Questions
Which branch should I target for pull requests?
Always open pull requests against the dev branch. The main branch contains stable releases, while dev receives active development and integration testing. The repository maintainers merge dev into main during release cycles.
How do I format my code to match the project style?
Run git clang-format --style=file -i $(git diff --name-only) before committing. The repository includes a .clang-format file that defines the style rules. The CI pipeline rejects pull requests that introduce formatting violations, so local verification prevents delays.
Can I build the Android client on Linux or macOS?
Yes. Use ./deploy/build.sh -t android --aab to generate Android App Bundle files on either Linux or macOS. Ensure you have the Android SDK, NDK, and Ninja installed, and set ANDROID_HOME environment variable. The script handles the CMake toolchain configuration automatically.
What is the purpose of the .rep files in the ipc/ directory?
The ipc/ipc_interface.rep file defines the Remote Objects interface used for communication between the UI (client/) and the background service (service/). When you add new methods to this interface, the Qt Remote Objects compiler generates the necessary proxy and replica classes. You must implement the service-side logic in service/src/qtservice.cpp and invoke it from the UI side through the generated interface.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →