Freeyourgadget/Gadgetbridge
We are on codeberg.org now! https://codeberg.org/Freeyourgadget/Gadgetbridge - Gadgetbridge - A free and cloudless replacement for your gadget vendors' closed source Android applications. Supports Pebble, Mi Band, Liveview, HPlus and more.
Stale — last commit 1y ago
weakest axiscopyleft license (AGPL-3.0) — review compatibility; last commit was 1y ago…
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
last commit was 1y ago; no CI workflows detected
- ✓22+ active contributors
- ✓Distributed ownership (top contributor 14% of recent commits)
- ✓AGPL-3.0 licensed
Show all 7 evidence items →Show less
- ⚠Stale — last commit 1y ago
- ⚠AGPL-3.0 is copyleft — check downstream compatibility
- ⚠No CI workflows detected
- ⚠No test directory detected
What would change the summary?
- →Use as dependency Concerns → Mixed if: relicense under MIT/Apache-2.0 (rare for established libs)
- →Deploy as-is Mixed → Healthy if: 1 commit in the last 180 days
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/freeyourgadget/gadgetbridge)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/freeyourgadget/gadgetbridge on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: Freeyourgadget/Gadgetbridge
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/Freeyourgadget/Gadgetbridge shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Stale — last commit 1y ago
- 22+ active contributors
- Distributed ownership (top contributor 14% of recent commits)
- AGPL-3.0 licensed
- ⚠ Stale — last commit 1y ago
- ⚠ AGPL-3.0 is copyleft — check downstream compatibility
- ⚠ No CI workflows detected
- ⚠ No test directory detected
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live Freeyourgadget/Gadgetbridge
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/Freeyourgadget/Gadgetbridge.
What it runs against: a local clone of Freeyourgadget/Gadgetbridge — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in Freeyourgadget/Gadgetbridge | Confirms the artifact applies here, not a fork |
| 2 | License is still AGPL-3.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 531 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of Freeyourgadget/Gadgetbridge. If you don't
# have one yet, run these first:
#
# git clone https://github.com/Freeyourgadget/Gadgetbridge.git
# cd Gadgetbridge
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of Freeyourgadget/Gadgetbridge and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "Freeyourgadget/Gadgetbridge(\\.git)?\\b" \\
&& ok "origin remote is Freeyourgadget/Gadgetbridge" \\
|| miss "origin remote is not Freeyourgadget/Gadgetbridge (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(AGPL-3\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"AGPL-3\\.0\"" package.json 2>/dev/null) \\
&& ok "license is AGPL-3.0" \\
|| miss "license drift — was AGPL-3.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "app/build.gradle" \\
&& ok "app/build.gradle" \\
|| miss "missing critical file: app/build.gradle"
test -f "app/src/main/AndroidManifest.xml" \\
&& ok "app/src/main/AndroidManifest.xml" \\
|| miss "missing critical file: app/src/main/AndroidManifest.xml"
test -f "GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java" \\
&& ok "GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java" \\
|| miss "missing critical file: GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java"
test -f ".gitmodules" \\
&& ok ".gitmodules" \\
|| miss "missing critical file: .gitmodules"
test -f "app/src/main/aidl/com/android/internal/telephony/ITelephony.aidl" \\
&& ok "app/src/main/aidl/com/android/internal/telephony/ITelephony.aidl" \\
|| miss "missing critical file: app/src/main/aidl/com/android/internal/telephony/ITelephony.aidl"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 531 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~501d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/Freeyourgadget/Gadgetbridge"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Gadgetbridge is a privacy-focused Android application (5.0+) that replaces vendor closed-source apps for wearables and gadgets like Pebble, Mi Band, Amazfit, and HPlus devices. It syncs fitness data, notifications, and settings directly to your phone without requiring cloud accounts or transmitting data to manufacturer servers, using Bluetooth as the primary communication protocol. Monolithic Android app: app/src/main/ contains core logic organized by device type (Pebble, Mi Band, Casio, etc.); app/src/main/aidl/ exposes AIDL interfaces for inter-process communication; GBDaoGenerator/ is a separate Gradle submodule that auto-generates database access code via greenDAO. Build flavors for Bangle.js and Bangle.js Nightly allow variant builds with different resources.
👥Who it's for
Privacy-conscious Android users who own wearables and want to avoid proprietary vendor apps and cloud services; contributors interested in reverse-engineering device protocols, Android system integration, and open-source mobile development.
🌱Maturity & risk
Production-ready and actively maintained. The project has a structured CI/CD pipeline (.woodpecker/ with lint, test, and nightly build workflows), comprehensive device support across multiple vendors, and is distributed on F-Droid with both stable and nightly release channels. Active development visible through CHANGELOG.md and ongoing contributor participation.
Low-risk for users; architectural risk is limited to device-specific protocol brittleness (vendor firmware updates can break compatibility) and the heavy Java codebase (~15MB) requiring active maintenance. Dependencies include a custom greenDAO fork (Freeyourgadget/greenDAO), which reduces supply chain risk but requires vigilance on that fork's maintenance. Single-maintainer risk is mitigated by a core team of 4+ developers.
Active areas of work
Active development across multiple device families visible in CONTRIBUTORS.rst (recent additions include Roidmi, Sony Headphones, Miband 7 support). CI/CD pipelines (.woodpecker/) run lint, unit tests, and nightly builds. Regular changelog updates indicate ongoing bug fixes and feature additions; repository recently migrated from GitHub to Codeberg.
🚀Get running
git clone https://codeberg.org/Freeyourgadget/Gadgetbridge.git && cd Gadgetbridge && ./gradlew build
Daily commands: gradlew installDebug (builds and installs debug APK to emulator/device); or import into Android Studio and run the 'main' configuration
🗺️Map of the codebase
app/build.gradle— Main app build configuration; defines dependencies, build variants (banglejs, banglejsNightly), and compilation targets for the Android application.app/src/main/AndroidManifest.xml— Android manifest defining all activities, services, permissions, and device integrations; required for understanding how the app registers with the OS.GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java— DAO generator entry point; generates database layer code for all gadget data models—essential for understanding the data persistence architecture..gitmodules— Git submodules configuration; manages external dependencies like greenDAO fork, critical for understanding build prerequisites.app/src/main/aidl/com/android/internal/telephony/ITelephony.aidl— Android AIDL interface for telephony integration; demonstrates how Gadgetbridge intercepts phone state for device notifications.README.md— Project overview stating AGPLv3 licensing, supported devices (Pebble, Mi Band, Amazfit Bip, HPlus), and mission as cloudless replacement—fundamental to understanding scope and constraints.app/src/main/assets/app_config/configure.html— Web-based configuration UI for gadget apps; shows how Gadgetbridge handles device-specific settings and web-to-native communication.
🛠️How to make changes
Add Support for a New Wearable Device
- Define device data model in GBDaoGenerator schema (e.g., DeviceActivity, DeviceHeart, DeviceSteps entities) (
GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java) - Run DAO generator to create database layer: ./gradlew GBDaoGenerator:genSources (
GBDaoGenerator/build.gradle) - Create device-specific protocol handler and register in main AndroidManifest.xml (
app/src/main/AndroidManifest.xml) - Add device variant build source set in app/build.gradle (similar to banglejs) if vendor-specific branding needed (
app/build.gradle) - Create AIDL interfaces in app/src/main/aidl/ if the device requires external service integration (e.g., GPS, weather) (
app/src/main/aidl/com/android/internal/telephony/ITelephony.aidl)
Add a Device Configuration UI
- Create HTML configuration file in app/src/main/assets/app_config/ (e.g., my_device_config.html) (
app/src/main/assets/app_config/configure.html) - Include gadgetbridge_boilerplate.js for native bridge communication (
app/src/main/assets/app_config/js/gadgetbridge_boilerplate.js) - Define device-specific layout JSON files (e.g., battery_layout.json) for complications/widgets (
app/src/main/assets/fossil_hr/battery_layout.json) - Add localized strings for the UI in res/values/strings.xml (
app/src/banglejs/res/values/strings.xml)
Integrate with an External Service (e.g., Navigation, Weather)
- Define AIDL interface(s) in app/src/main/aidl/ (e.g., INavigationManager.aidl) to communicate with the service (
app/src/main/aidl/net/osmand/aidlapi/IOsmAndAidlInterface.aidl) - Create parameter/response AIDL data classes (e.g., NavigationParams.aidl, WeatherInfo.aidl) (
app/src/main/aidl/net/osmand/aidlapi/navigation/ANavigationUpdateParams.aidl) - Declare service binding and permissions in AndroidManifest.xml (
app/src/main/AndroidManifest.xml) - Add ProGuard rules in app/proguard-rules.pro to preserve AIDL stubs in release builds (
app/proguard-rules.pro)
Create a Device Variant Build
- Add new sourceSet and productFlavor in app/build.gradle (e.g., 'mydevice') (
app/build.gradle) - Create directory app/src/mydevice/ with variant-specific AndroidManifest.xml (
app/src/banglejs/AndroidManifest.xml) - Add variant-specific resources (strings, drawables) in app/src/mydevice/res/ (
app/src/banglejs/res/values/strings.xml) - Update .gitea issue templates to include device variant option if this is a major release variant (
.gitea/issue_template/device_request.yml)
🪤Traps & gotchas
Bluetooth pairing state is persistent in Android and requires manual management across app reinstalls. The AIDL service (ITelephony) may not work on all Android versions or ROM customizations (e.g., GrapheneOS, Lineage). Device firmware updates can silently break protocol compatibility without warning. The custom greenDAO fork must be built separately and committed as a submodule; missing it will cause build failures. Build flavors (banglejs, banglejsNightly) have different resource IDs—mixing them in a single APK will cause conflicts. Proguard rules (app/proguard-rules.pro) are essential; missing them breaks obfuscated device adapter classes at runtime.
🏗️Architecture
💡Concepts to learn
- Bluetooth Low Energy (BLE) / Bluetooth Classic — Core communication protocol; understanding GAP/GATT profiles, UUID handling, and MTU negotiation is essential for adding device support or debugging sync failures
- Android AIDL (Android Interface Definition Language) — Used to expose Gadgetbridge's notification and call detection APIs to third-party apps; required for understanding inter-process communication and permissions
- greenDAO (Lightweight ORM) — All persistent data (sync history, device settings, activity logs) flows through greenDAO-generated DAOs; understanding entity relationships and query patterns is critical for feature development
- Protocol Reverse-Engineering via Packet Sniffing — Most device support in Gadgetbridge is built by capturing and analyzing raw Bluetooth packets from vendor apps; this is the bottleneck for adding new device families
- Android Notification Listener Service — Gadgetbridge intercepts system notifications and forwards them to wearables via NotificationListenerService; understanding notification data structures and permissions is essential
- Gradle Build Flavors & Variants — Gadgetbridge uses flavors (banglejs, banglejsNightly) to ship different APKs with variant resources and features; critical for managing build complexity and device-specific customizations
- Intent Broadcasting & Implicit Intents — Gadgetbridge receives device data broadcasts and sends intents to other apps for integration; understanding intent filters and data URIs is necessary for API integration features
🔗Related repos
Freeyourgadget/greenDAO— Custom fork of greenDAO (Java ORM) used by Gadgetbridge for SQLite database access; maintained by the same teamespruino/Espruino— Firmware for Bangle.js watches supported by Gadgetbridge; contributors to Gadgetbridge's Bangle.js flavor collaborate with this project0x4d4f4b/BangleApps— App store and development framework for Bangle.js; integrates with Gadgetbridge as the primary Android companion appBitzaG/GadgetBridgeYML— YAML configuration generator for Gadgetbridge; automates device definition and capability declaration
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add unit tests for GBDaoGenerator data access object generation
The GBDaoGenerator module (app/GBDaoGenerator/src/nodomain/freeyourgadget/gadgetbridge/daogen/GBDaoGenerator.java) is a critical code generation tool that creates database access objects, but there are no visible test files in the repository. Adding unit tests would catch regressions when the schema changes and ensure generated DAOs are valid before they're used in the main application.
- [ ] Create GBDaoGenerator/src/test directory structure
- [ ] Write unit tests in GBDaoGenerator/src/test/java/nodomain/freeyourgadget/gadgetbridge/daogen/ to verify GBDaoGenerator.java correctly parses schema definitions
- [ ] Add test cases for edge cases: empty schemas, invalid field types, duplicate table names
- [ ] Update GBDaoGenerator/build.gradle to include test dependencies (JUnit, Mockito)
- [ ] Add test execution to .woodpecker/run_tests.yml CI pipeline
Create device-specific integration test templates in .gitea/issue_template/
The repo has issue templates for bug reports, feature requests, and device requests, but lacks templates for device-specific testing checklists. New contributors frequently add device support but lack guidance on what testing is needed. A standardized template would improve quality of device additions.
- [ ] Create .gitea/issue_template/device_testing.yml with structured fields for: device model, firmware version, features tested (sync, notifications, battery, etc.), known issues
- [ ] Update .gitea/issue_template/config.yml to include the new device_testing template
- [ ] Document the template in CONTRIBUTORS.rst with examples of what should be tested before merging device support PRs
Add Woodpecker CI workflow for device-specific build variants
The repository supports multiple device flavors (banglejs, banglejsNightly visible in app/src/), but .woodpecker/nightly.yml doesn't show explicit per-device build validation. Adding a workflow to build and lint each flavor separately would catch device-specific build failures early and ensure all device variants compile correctly.
- [ ] Create .woodpecker/build_device_variants.yml to iterate over each flavor in app/src/ (banglejs, banglejsNightly, etc.)
- [ ] Add gradle build tasks for each variant: ./gradlew assembleBanglejs, ./gradlew assembleBanglejsNightly, etc.
- [ ] Include lint checks per variant using app/lint-baseline.xml as reference
- [ ] Trigger this workflow on PRs that modify app/src/ or app/build.gradle files
🌿Good first issues
- Add unit tests for the greenDAO schema generation (GBDaoGenerator/src/) to detect breaking schema changes early; currently no test coverage exists for the auto-generated code
- Document device protocol reverse-engineering process in a PROTOCOL.md; contributors frequently duplicate effort discovering Bluetooth packet formats already known to the team
- Create integration tests for AIDL service (ITelephony) across Android 5.0–14 to prevent regressions in call detection, which affects notification syncing on all devices
⭐Top contributors
Click to expand
Top contributors
- @weblate — 14 commits
- @chenshaoju — 13 commits
- @Fjuro — 13 commits
- @diskacz — 8 commits
- @gallegonovato — 8 commits
📝Recent commits
Click to expand
Recent commits
a0948ee— Xiaomi: Fix typos in comments (sdroege)afc167e— Xiaomi: Change workout type 0x012d from stair climber to stairs (sdroege)4651ed0— Translated using Weblate (Turkish) (joserebelo)c629543— Translated using Weblate (Hungarian) (joserebelo)b83aeb0— fix typo (ashimokawa)1a3f194— Translated using Weblate (Chinese (Simplified Han script)) (chenshaoju)495fb01— Translated using Weblate (Chinese (Simplified Han script)) (ashimokawa)8f5edbc— Translated using Weblate (Polish) (diskacz)998c8f8— Translated using Weblate (Hebrew) (yarons)af2b685— Translated using Weblate (Czech) (Fjuro)
🔒Security observations
- High · Dependency Resolution with Commit Hash Instead of Version —
GBDaoGenerator/build.gradle. The GBDaoGenerator build.gradle uses a direct Git commit hash (1998d7cd2d21f662c6044f6ccf3b3a251bbad341) from a custom fork of greenDAO instead of a stable, versioned release. This bypasses normal dependency resolution and makes it difficult to track what version is actually being used, audit security patches, and reproduce builds consistently. Fix: Use a specific semantic version tag instead of commit hash. If using a custom fork, publish it to a package repository (Maven Central, JCenter, or similar) with proper version management. At minimum, document why the commit hash is necessary and ensure the commit is from a trusted source. - Medium · Missing Dependency Version Constraints —
GBDaoGenerator/build.gradle. The gradle files appear to lack explicit version constraints on the greenDAO dependency. Unversioned or loosely-versioned dependencies can lead to unexpected updates that introduce security vulnerabilities or breaking changes. Fix: Pin all dependencies to specific versions or use version ranges with upper bounds. Implement dependency lock files (gradle.lockfile) to ensure reproducible builds. Regularly audit and update dependencies to their latest secure versions. - Medium · Potential SQL Injection via DAO Generation —
GBDaoGenerator/, app/src/main/aidl/. The project uses greenDAO ORM generator (GBDaoGenerator). While ORM frameworks provide some protection against SQL injection, the codebase structure suggests automatic DAO generation which could potentially be misused if the generated DAOs are used with unsanitized user input. The presence of AIDL interfaces for external content providers increases this risk. Fix: Review all DAO usage throughout the codebase to ensure parameterized queries are used exclusively. Implement input validation for any user-supplied data used in database queries. Use the ORM's built-in query builder exclusively rather than raw SQL when possible. Conduct security code review of database access patterns. - Medium · External AIDL Interfaces with Insufficient Validation —
app/src/main/aidl/. The codebase exposes multiple AIDL interfaces (ITelephony, ILineageWeatherManager, IOsmAndAidlInterface) that allow inter-process communication with external applications. These can be attack vectors if input validation is insufficient. The OsmAnd integration particularly allows third-party apps to interact with the service. Fix: Implement strict input validation on all AIDL interface methods. Use signature-based permissions to restrict which applications can call these interfaces. Review the threat model for each AIDL interface and limit exposed functionality to the minimum necessary. Consider using explicit permission checks beyond the manifest. - Medium · Web Assets in App Config Vulnerable to XSS —
app/src/main/assets/app_config/. The application includes HTML and JavaScript assets for app configuration (app/src/main/assets/app_config/). If these assets load untrusted content or user-supplied data without proper escaping, XSS vulnerabilities could occur. Fix: Ensure all HTML/JavaScript assets follow secure coding practices: use Content Security Policy headers, properly escape all dynamic content, avoid innerHTML/dangerouslySetInnerHTML patterns, validate all user inputs before rendering, and use the DOM API safely. - Low · No Evidence of Security Headers Configuration —
app/src/main/AndroidManifest.xml. No security configuration files (SecurityConfig, AndroidManifest hardening attributes) are visible in the provided structure. The application handles sensitive device data and should implement appropriate security hardening. Fix: Implement security best practices in AndroidManifest.xml including: android:usesCleartextTraffic='false', certificate pinning for network communications, proper permission declarations with minimalPermissions, android:debuggable='false' in release builds. Review manifest for overly permissive attribute configurations. - Low · Build Artifacts Not Explicitly Versioned —
GBDaoGenerator/build.gradle. The build.gradle files set archivesBaseName but no explicit version is visible, which could lead to confusion about which build is deployed. Fix: Explicitly set version = 'x.y.z' in build.gradle files and tie to git tags for releases. Implement build number tracking and ensure artifacts are properly versioned.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.