Skip to content
TeamGDBPublic

About

A VPN client for subscription links. AmneziaWG, no account, no telemetry.

Topics

Resources

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Repository files navigation

Caelo

Caelo

Paste a link. It works.

A VPN client for subscription links, for people who should not have to learn what a protocol is.

Flutter Core License Platforms AmneziaWG

English · Русский


Early development. The tunnel works. Nothing else is finished, and there are no releases yet.

What it is

No accounts. No ads. No telemetry. Free software under the GPLv3.

Caelo speaks AmneziaWG with the full obfuscation parameter set — junk packets, magic header ranges, and AWG 2.0 signature packets that make a handshake look like DNS, QUIC or SIP. Which of them you end up using is not a question the app asks you.

The main screen is a button, a word, and one line of small text saying what you got. Settings exist for the cases the automatic choice cannot cover, and you should never need to open them.

Protocols

AmneziaWG Jc Jmin Jmax · S1–S4 · H1–H4 · I1–I5
VLESS REALITY or TLS; Vision or XHTTP, including through a CDN; Safari, Chrome, Firefox and other fingerprints — via Xray-core

Subscriptions may carry both, in the Caelo document or as a plain list of vless:// links. A node this build cannot run is left out with its reason rather than connected some other way.

Platforms

Platform Tunnel Covers
macOS NetworkExtension system extension the whole machine
Android VpnService the whole device
iOS NetworkExtension packet tunnel the whole device
Linux privileged service from the deb or rpm; in-process otherwise the whole machine, or this process
Windows — interface only

Architecture

The core knows about configurations, not about subscriptions. It can say what is in one, whether it carries traffic, and raise it — one at a time. Everything that makes a subscription a subscription is delivery: a link, an HTTP request, a refresh interval, a cached copy of the last one that worked, a remaining-traffic header, several sources merged into a list. None of that is executed by a tunnel, and all of it is what the user sees and edits, so it lives in Flutter.

The rule that does not move is connection state. That exists in exactly one place, because state kept in two will eventually disagree with itself about what is connected.

Automatic choice connects through the fastest node that carries traffic from this device, asking the one that worked last time first. The server cannot know where somebody is standing; the device can measure it. caelo_probe answers whether a configuration really carries traffic, on a userspace stack, without touching the machine's networking or a tunnel already up. The server's order is how the list is shown and how ties are broken.

Caelo will fork nothing. AmneziaWG comes from amneziawg-go and VLESS from Xray-core, both imported as published Go modules. Upgrading either is a version bump — for Xray, scripts/update-xray.sh <tag>, which pins the release and runs the VLESS tests against a real Xray server built from it. There is no patch series to rebase.

Every protocol other than AmneziaWG plugs in through one registry in the core (core/internal/protocol): describe a node, carry traffic for this process, run over a host's device. Adding a protocol is a package that implements that and one line that registers it; the probe, the tunnels and the app's subscription reader find it from there. AmneziaWG keeps its own path, unchanged.

Xray-core rather than sing-box: XHTTP, which the VLESS servers this client is built for use, is Xray's own transport, and sing-box does not carry it.

The alternative was forking sagernet/wireguard-go and porting the obfuscation into it. Measured against their common upstream, that fork and amneziawg-go have diverged by comparable amounts — roughly 1700 and 1800 substantive lines — so reconciling them is real work in either direction, and work we would redo on every AmneziaWG release. AmneziaWG is the reason this project exists, so it is the dependency that stays fresh.

Path What it holds
lib/ The interface. Flutter, Cupertino, one look everywhere.
core/ The Go core: the tunnel, the probe, state.
packaging/ Turning a build into something installable.
scripts/ One build script per platform.

Pinned: amneziawg-go v3.1.20260814, Xray-core v26.11.9.

Building

Flutter is pinned to 3.47.9 in .fvmrc. CI and release builds read that same file, so a new stable release cannot silently change the toolchain. Upgrade Flutter in a separate change that checks Android tools, plugins and all platform builds together.

For local development, install FVM, then run these commands from the repository root:

fvm install
fvm flutter --version
fvm flutter pub get
fvm flutter analyze
fvm flutter test
fvm exec ./scripts/build-android.sh debug

Use fvm exec for the other build scripts below too: their flutter commands then use the project's SDK. With a manually installed SDK, put Flutter 3.47.9 on PATH before running the scripts. The local .fvm/ SDK directory is ignored; .fvmrc is committed.

Each script builds the core first, puts it where that platform's loader will find it, and then builds the app.

./scripts/build-macos.sh debug     # universal dylib in Contents/Frameworks
./scripts/build-android.sh debug   # one .so per ABI, packed into the APK
./scripts/build-ios.sh release     # static xcframework linked into the binary
./scripts/build-linux.sh debug     # .so in the bundle's lib/
./scripts/build-windows.sh debug   # .dll beside the executable

Android needs an NDK; the script finds one under the SDK Flutter already knows about. iOS debug builds use a JIT and will not launch without the tooling attached, so release is the default there.

Any of them can be run without a core — flutter build <platform> still builds the interface. The app then says the core is missing rather than pretending otherwise.

Trying the tunnel without the app

cd core && go run ./cmd/caelo-probe -config /path/to/tunnel.conf

Brings up one tunnel on a userspace stack and fetches a URL through it. No privileges, no interface on the host, nothing outside the process routed. If the address it prints is the endpoint's rather than yours, it worked.

Packaging

Platform Formats
Android one APK per ABI, a universal APK for sideloading, and an .aab
Linux .deb, .rpm, AppImage, .tar.gz
macOS .dmg
Windows installer, portable .zip

Four Linux formats because "Linux" is not one thing. Nothing produced is signed or notarised yet, and an unsigned build must never be handed to anyone as a release.

On Linux the .deb and .rpm add whoever installed them to the caelo group, which is what lets the app reach its service: the user behind sudo or pkexec, or, when a package was opened from the file manager, the people with a local graphical session. The group takes effect at the next login. If Caelo says it cannot reach its service, run sudo usermod -aG caelo $USER and log out and back in.

Contributing

CONTRIBUTING.md. Sign your commits off (git commit -s), and never paste a real subscription link, key or server address into an issue.

Found a vulnerability? SECURITY.md — not a public issue.

License

GPL-3.0-or-later. See LICENSE.

Caelo builds on AmneziaWG and Xray-core; see ATTRIBUTION.md for what came from where. Neither project endorses Caelo or is affiliated with it.

About

A VPN client for subscription links. AmneziaWG, no account, no telemetry.

Topics

Resources

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages