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:

  1. Verify formatting using the project's clang-format configuration:

    git clang-format --style=file -i $(git diff --name-only)
  2. Build locally on your target platform using the deploy/build.* scripts to catch compilation errors early.

  3. Update documentation in README.md if your change affects user-visible behavior or build requirements.

  4. Submit a Pull Request against the dev branch 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:dev to isolate your changes.
  • Use the deploy scripts (deploy/build.sh or deploy/build.bat) to ensure consistent CMake configuration across platforms.
  • Place UI code in client/, service logic in service/src/, and Docker helpers in service/server/.
  • Update IPC definitions in ipc/ipc_interface.rep when changing the UI-service contract.
  • Run git clang-format before committing to match the project's style requirements.
  • Reference specific files like qtservice.cpp and vpnConnection.cpp to 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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →