Linux to Android notification bridge.
Project description
GuGa Nexus
Send your Linux terminal and OS notifications straight to your Android.
No cloud. No subscription. No port forwarding.
🔗 View the full Open Source Repository on GitHub
GuGa Nexus is a minimalist, privacy-focused ecosystem that bridges your Linux machine and your Android device. It uses end-to-end AES-256-GCM encryption and works strictly over your own local network or a direct Cloudflare Tunnel—never storing your data on a third-party server.
- Waiting for a long script to finish? Get notified the moment it's done.
- Training a model overnight? Wake up to the final accuracy line in your notification.
- SSHed into a remote server? GuGa reaches your phone over the internet seamlessly.
GuGa is distributed via PyPI for Linux and via Git for the Windows beta.
Linux
pip install guga
guga --install-service
Windows (Beta)
Requires Git.
pip install git+https://github.com/PositiveMatician/GuGa-Nexus.git@windows#subdirectory=server
# Run in Administrator terminal:
guga --install-service
(This interactive setup will cleanly provision your background service (systemd or Windows Service) and configure network routing).
- Reconfiguring: If you ever need to change your connection mode or notification settings later, simply run:
guga --install-service --reconfigure
(This will re-run the interactive setup and update your background daemon).
- Install the Android App:
Download the
stableAndroid APK from the GitHub Releases Page and scan the QR code printed in your terminal!
🚀 Examples & Usage
Once deployed, the guga command-line utility is globally available on your terminal. It's designed to automatically detect whether you want to send a plain text notification, or if you want it to execute and watch a long-running process on your behalf.
1. Plain Notifications (Message Mode)
Send simple text updates directly to your Android device.
# Push a simple message
guga "Build finished successfully ✅"
# You can also stream output into it via stdin!
echo "Database migration complete" | guga
2. Process Watching (Run Mode)
Put guga in front of any command. It will execute the command natively while streaming the output to your terminal just as normal. Once the command finishes, it will instantly notify your phone with the Elapsed Time, Exit Status, and the Last Console Line.
# Get notified when training finishes
guga python train_model.py --epochs 100
# Compile code and get notified if it succeeded or crashed
guga make build-project
# Add custom labels to your notifications for clarity
guga -r ./deploy.sh --title "Production Server"
# Send to a specific tagged device (e.g. "nexus")
guga --send-to nexus "Build complete"
⚙️ Configuration & Polish
GuGa is designed with a premium developer experience in mind.
1. Persistent Configuration
Power users can set default flags in ~/.config/guga/config so they don't have to pass them every time.
Example ~/.config/guga/config:
[default]
title = GPU Server
port = 6769
silent = false
2. Shell Completion
GuGa supports full shell autocompletion for flags like --install-service, --qr, --show-pin, etc.
To activate it for your user, run:
activate-global-python-argcomplete --user
Then restart your shell or run eval "$(register-python-argcomplete guga)".
Post-Install Utilities
If you need to view your pairing credentials or manage your background daemon after installation, GuGa provides several utility commands:
guga --qr # Show the pairing QR code
guga --rename-device # Assign a custom tag to a device
guga --approve # Interactively approve pairing requests
guga --approve -A # Approve all pending requests non-interactively
guga --blocked # List blocked devices
guga --unblock [DEVICE_ID] # Remove a device from the blocklist
guga --revoke [DEVICE_ID] # Revoke a trusted device's access
guga --install-service --reconfigure # Re-run the interactive setup
guga --status # Show service status and connections
guga --url # Show raw pairing URL (scriptable)
guga --version # Show the current version
guga --uninstall # Remove all GuGa system components
🤖 AI Agent Integration (MCP)
GuGa provides a built-in Model Context Protocol (MCP) server, allowing AI agents like Claude Desktop or Antigravity to send notifications and ask you questions directly on your phone.
Local AI (Antigravity / Claude Desktop) — Recommended Setup
Run this once to automatically configure the MCP entry in ~/.gemini/antigravity/mcp_config.json:
guga --install-mcp
This auto-detects the correct Python interpreter (prefers your active virtualenv), verifies all required packages are installed, and writes the entry. Preview without writing:
guga --install-mcp --dry-run
To remove the entry later:
guga --uninstall-mcp
If you prefer to configure manually, the entry uses stdio transport (not SSE/url):
{
"mcpServers": {
"guga": {
"command": "/path/to/venv/bin/python3",
"args": ["-m", "guga.mcp_server"],
"env": {
"PYTHONPATH": "/path/to/server"
}
}
}
}
[!IMPORTANT] Antigravity's MCP client only supports stdio (
command/args) transport, not SSE (url). Always use thecommandform.
After installing, click Refresh in the Antigravity MCP panel.
Remote AI (Custom Tools / GPT Actions / SSE)
For remote access (e.g., calling your GuGa tools from a Custom GPT or a remote server), use the SSE Transport with JWT security.
- Start the server in Public Mode:
Ensure your GuGa server is exposed via Cloudflare Tunnel:
MODE=public guga --start-server
- Generate a JWT Access Token:
Tokens are signed using a persistent secret in
~/.guga/.env. Generate one for your remote tool:guga --mcp-token - Configure your Remote Tool:
- SSE Endpoint:
https://<your-tunnel-url>.trycloudflare.com/mcp/sse - Method:
GET(for SSE stream) andPOST(for sending JSON-RPC messages to/mcp/messages). - Authentication: All requests must include the
Authorizationheader:Authorization: Bearer <your-generated-token> - Note: The token is also accepted via a query parameter
?token=<token>for clients that struggle with headers on SSE.
- SSE Endpoint:
[!SECURITY] Your JWT secret is unique to your machine. Anyone with the token can send notifications or ask questions to your phone. Keep your Cloudflare URL and token secure.
⚠️ Known Issues
Cloudflare Free Tunnel — SSE Streaming Buffered
Affected: Remote MCP SSE access via trycloudflare.com free tunnels.
Symptom: The MCP client (e.g. Claude.ai custom connector) gets a 200 OK with Content-Type: text/event-stream but receives no data — the connection hangs and eventually times out.
Not affected: Local stdio MCP (guga --mcp), LAN access, Android app, browser dashboard — all work normally.
Root Cause
Cloudflare's free tunnel service (trycloudflare.com) buffers HTTP response bodies before forwarding them to the client. Server-Sent Events rely on a persistent, flushed stream — the first event: endpoint frame must arrive immediately. Cloudflare holds this frame until the connection closes, which breaks the MCP handshake.
The standard nginx workaround (X-Accel-Buffering: no) and the Cloudflare-specific header (CF-No-Buffer: true) are both sent by GuGa, but CF-No-Buffer only disables buffering on paid Cloudflare zones — it has no effect on the free trycloudflare.com tunnel service.
Workarounds
Option A — Use ngrok instead of Cloudflare (recommended for SSE)
ngrok's free tier streams SSE correctly. Replace the Cloudflare tunnel:
# Install ngrok: https://ngrok.com/download
ngrok http 6769
# Use the https://xxxx.ngrok-free.app URL as your MCP endpoint
Then connect your remote tool to:
https://xxxx.ngrok-free.app/mcp/sse?token=<your-jwt>
Option B — Paid Cloudflare (if you own a zone)
If you have a Cloudflare account with a registered domain, assign it to the tunnel via cloudflared tunnel route dns. On a proper Cloudflare zone, CF-No-Buffer: true takes effect and SSE streams correctly.
Option C — Local stdio MCP only
For personal AI assistants running on the same machine (Antigravity, Claude Desktop), the stdio transport is both simpler and more reliable than SSE:
guga --install-mcp # writes the correct stdio entry to mcp_config.json
No tunnel, no token, no buffering issues.
Option D — Future: Streamable HTTP transport (planned)
The MCP spec now supports a streamable-http transport that uses standard HTTP POST/response pairs instead of a persistent SSE stream. This is Cloudflare-compatible and will be added to GuGa in a future release as the preferred remote transport.
To control the Linux backend server explicitly:
sudo systemctl start guga # Start the server daemon
sudo systemctl stop guga # Stop the server daemon
journalctl -u guga -f # View live server connection logs
Core Features & Architecture
- Terminal Tracking: Push notifications to Android via the
gugaglobal CLI. - System OS Monitoring: Automatically intercepts DBus to forward your native Linux desktop notifications straight to your phone.
- Zero-Trust Coupling: Cryptographically secure pairing logic relying strictly on visual QR transmission + 8-Digit PINs (No OAuth or cloud-accounts required).
- Network Versatility: Operates flawlessly in LAN-only mode strictly over local WiFi, or seamlessly hooks into Cloudflared to grant you Internet-anywhere access without needing to own a domain or configure port-forwarding.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file guga-1.5.0.tar.gz.
File metadata
- Download URL: guga-1.5.0.tar.gz
- Upload date:
- Size: 71.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d108ec6b769584c972d56a8ba35b44bb8f6d5a4db7c142fa8186e058cb269983
|
|
| MD5 |
d3d39075dd03dd8927336dcbdc8d263e
|
|
| BLAKE2b-256 |
e77d9d19a98f48e19b622da2ad85608d447ada9ffa45cc556d4aaf530b92c2f5
|
Provenance
The following attestation bundles were made for guga-1.5.0.tar.gz:
Publisher:
pypi-publish.yml on PositiveMatician/GuGa-Nexus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
guga-1.5.0.tar.gz -
Subject digest:
d108ec6b769584c972d56a8ba35b44bb8f6d5a4db7c142fa8186e058cb269983 - Sigstore transparency entry: 1458397887
- Sigstore integration time:
-
Permalink:
PositiveMatician/GuGa-Nexus@f6c58f2460cb346ebb3d6203e37160f4bfac08ca -
Branch / Tag:
refs/heads/latest - Owner: https://github.com/PositiveMatician
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@f6c58f2460cb346ebb3d6203e37160f4bfac08ca -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file guga-1.5.0-py3-none-any.whl.
File metadata
- Download URL: guga-1.5.0-py3-none-any.whl
- Upload date:
- Size: 81.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
07c6b5e1b48f3935c8570d185551e2500d169b88a8f1811374e7875dc9239d28
|
|
| MD5 |
827355ebf9565d665c4a438f2befb68d
|
|
| BLAKE2b-256 |
2a741122f5672a1d2dbadcececaab21b9c70423db0c7c50359239f365ac0e424
|
Provenance
The following attestation bundles were made for guga-1.5.0-py3-none-any.whl:
Publisher:
pypi-publish.yml on PositiveMatician/GuGa-Nexus
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
guga-1.5.0-py3-none-any.whl -
Subject digest:
07c6b5e1b48f3935c8570d185551e2500d169b88a8f1811374e7875dc9239d28 - Sigstore transparency entry: 1458397943
- Sigstore integration time:
-
Permalink:
PositiveMatician/GuGa-Nexus@f6c58f2460cb346ebb3d6203e37160f4bfac08ca -
Branch / Tag:
refs/heads/latest - Owner: https://github.com/PositiveMatician
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
pypi-publish.yml@f6c58f2460cb346ebb3d6203e37160f4bfac08ca -
Trigger Event:
workflow_dispatch
-
Statement type: