/00 — boot sequence

Hello.

cd ../open-source

aiyu-ayaan/Rewire

Rewire

REWIRE is an Android app that reduces unwanted habits by adding intentional friction before distracting apps open. It is not a punishment or surveillance tool. It creates a pause, lets you choose, and measures what happens so you can learn your own patterns.

  • active
  • 1 stars
  • Kotlin
  • MIT
  • pushed 6d ago
Rewire preview

// readmeaiyu-ayaan/Rewire

REWIRE logo

REWIRE

Break habits. Build control.

Android Kotlin Compose License Languages Privacy

REWIRE is an Android app that reduces unwanted habits by adding intentional friction before distracting apps open. It is not a punishment or surveillance tool. It creates a pause, lets you choose, and measures what happens so you can learn your own patterns.

Friction → Awareness → Choice → Action → Measurement → Improvement

REWIRE launch video

Launch video (click for the full-quality MP4)

Screenshots

GuardHabit detailMax block screen
Today dashboard and your habitsFriction level, limits, allowed windowHard boundary with your own reason and an emergency unlock
FocusMatrixMatrix (more)
Focus / break / cycles timerToday's focus and Guard stats with a timelineMonthly profile, trends and focus calendar
Warning libraryProfilePermissions
Data-driven, editable warningsTheme, dynamic color, settingsEvery permission explained

Tablet, foldable and large screens

REWIRE adapts to the window: a navigation rail and list-detail panes on tablets and unfolded foldables, two-column Matrix charts, and the usual bottom bar on phones.

Tablet (landscape)Tablet (landscape)
Guard list with the habit detail beside itMatrix monthly profile and focus calendar
Foldable (unfolded)Foldable (unfolded)Tablet (portrait)Tablet (portrait)
Guard with the railMatrix weeklyHabit detailMatrix monthly

Dynamic color and languages

Guard in six dynamic color palettes

Dynamic color follows your wallpaper: the same screen in six palettes.

Guard in Hindi, Spanish, Arabic, Japanese, Russian and French

Hindi, Spanish, Arabic (right-to-left), Japanese, Russian and French. 27 languages in total.

Every chart also has a Show as table view:

Matrix chart shown as an accessible table

Features

Guard: protected apps and habit rules

  • Habits are first-class. One habit (e.g. Doom Scrolling) groups many apps (Instagram, Reddit, YouTube).
  • Three friction levels
    LevelBehavior
    MinorA short "why are you opening this?" pause. Never blocks. Logged.
    MajorWarning with Go back or Continue anyway. Every warning and override is logged.
    MaxHard block outside your boundary, with a deliberate emergency unlock (device PIN, pattern or biometric) that is logged.
  • Boundaries per habit: daily time limit, launch limit, allowed time window. An app can override them with its own limits.
  • Smart escalation (optional, off by default): configurable Minor, Major and Max tiers by minutes used today, or by how many times you opened the app.
  • Safe by design: rules can be disabled any time, Max never causes a device lockout, and Max bypass is off during Focus by default.

Focus: concentration sessions

  • Configurable focus, break and cycle counts. Built-in presets: Pomodoro (25/5 × 4), Deep work (50/10 × 4), Sprint (20/5 × 3), plus your own saved presets.
  • Validated rule: breakDuration <= focusDuration.
  • State machine: IDLE → FOCUSING → BREAK → PAUSED → COMPLETED / CANCELLED.
  • Runs as a foreground service that survives the app being closed and resumes from Room after a process kill. Optional Do Not Disturb that still lets calls and alarms through.
  • Hold-to-end so escaping is not too easy. Focus can bypass selected Guard levels (Minor on, Major configurable, Max off by default).
  • Full-screen timer with landscape layout, session notes and history.

Quit: private habit counters

  • Multiple independent counters with live progress (days, hours, minutes), best streak preserved, and milestone ring (1, 3, 7, 14, 21, 30, 60, 90, 180, 365 days, then yearly).
  • Calm slip recovery: "I slipped" flow records the moment, keeps your best run saved, and displays restarts in the last 30 days without shame.
  • "Ride the wave" urge surfing: 2-minute paced breathing (4-4-6 rhythm) with a grounding thought per breath, followed by actionable ideas.
  • Thought of the day and browseable reflections from a 1,006-thought collection localized across all 27 languages.
  • Private by design: kept in its own dedicated DataStore, strictly isolated from Room, analytics events, Matrix, and exports.

Matrix: analytics

  • Daily, weekly and monthly views built from the event log and Usage access screen time.
  • Nine chart types: line, area, bar, stacked bar, donut, radar, calendar heatmap, timeline and scatter. Each has an accessible table alternative.
  • Guard breakdown (went back, continued, blocked, overrides), most guarded hour, by-habit and most-opened-app lists.
  • Daily goals (focus target, max overrides) with streaks. A short, light-hearted summary line on top.
  • Charts consume normalized domain metrics and never query Android APIs directly.

Profile

  • Theme (system, light, dark), dynamic color and language.
  • Warning library: add, edit, delete, favorite, enable/disable, randomized selection.
  • Notification categories, goals, permission status and guidance, about and acknowledgements.
  • Your data: export, import, clear history (versioned JSON, validated, one transaction).
  • Updates: opt-in check against GitHub Releases with Stable, Beta and Alpha channels (not in the Play build).

Privacy

Everything stays on the device. No analytics SDKs, no accounts, no cloud sync. Accessibility is used only for window-change events (the foreground package name), never for screen content. The only network call is the optional update check, which reads the public release list and sends nothing about you or your usage. The Play build has no network permission at all.

Languages

REWIRE is available in 27 languages. Pick one in Profile → Language, or, on Android 13+, in Android's own per-app language settings. The default follows your phone.

Englishहिन्दी (Hindi)EspañolPortuguês (Brasil)
Bahasa Indonesiaالعربية (Arabic, RTL)FrançaisРусский
DeutschTürkçe日本語한국어
ItalianoTiếng Việtไทย简体中文
繁體中文Polskiবাংলাதமிழ் (Tamil)
తెలుగు (Telugu)मराठी (Marathi)ગુજરાતી (Gujarati)ಕನ್ನಡ (Kannada)
മലയാളം (Malayalam)ਪੰਜਾਬੀ (Punjabi)اردو (Urdu, RTL)

Everything is translated: the UI, plurals, notification channels, the Matrix summary lines and the built-in warning library. A built-in warning you have not edited follows the app language, and one you reworded stays exactly as you wrote it. The translations are machine-generated and have not had a native-speaker review yet, so corrections are welcome. How to add a language: development/docs/LOCALIZATION.md.

Architecture

flowchart TD
    OS["Android system"]
    A11y["AccessibilityService<br/>(Full / Play flavors)"]
    Usage["Usage-access watch<br/>GuardMonitorService<br/>(Lite, or Full when a11y is off)"]
    Boot["BootReceiver"]
    Work["WorkManager<br/>daily summary, update check"]

    OS --> A11y
    OS --> Usage
    OS --> Boot
    OS --> Work

    A11y --> Engine["HabitEngine"]
    Usage --> Engine
    Boot -->|restores monitoring| Engine
    Engine --> Rules["RuleEngine (pure Kotlin)<br/>limits, windows, escalation, Focus bypass"]
    Rules --> Decision{"RestrictionDecision"}
    Decision -->|Allow| Open["App opens"]
    Decision -->|Warn: Minor / Major| GuardUI["GuardActivity<br/>warning screen"]
    Decision -->|Block: Max| GuardUI
    GuardUI -->|go back / continue / override| Events["EventRepository"]
    Engine --> Events

    Focus["FocusController<br/>+ FocusTimerService"] --> Events
    Focus -.->|bypass levels| Rules

    Events --> Room[("Room v5<br/>habits, rules, warnings,<br/>events, focus sessions, settings")]
    Work --> Room
    Room --> Metrics["MetricsCalculator /<br/>PeriodMetrics"]
    Metrics --> Matrix["Matrix UI<br/>nine chart types"]

Layering: Composable → ViewModel → Repository → Room / DataStore. The domain package has no Android imports, so rule, focus, analytics and update logic is tested on the plain JVM. Hilt wires everything from a single AppModule.

flowchart LR
    subgraph UI["feature/ (Compose)"]
        Guard
        FocusUI["Focus"]
        MatrixUI["Matrix"]
        Profile
    end
    subgraph VM["ViewModels"]
        VMs["Guard / Focus / Matrix /<br/>Settings / Data / Update"]
    end
    subgraph Domain["domain/ (pure Kotlin)"]
        RuleEngine
        FocusTimer
        Analytics["MetricsCalculator,<br/>Streaks, Punchlines"]
        Warn["WarningPicker"]
    end
    subgraph Data["data/ + core/"]
        Repos["Repositories<br/>write-through cache"]
        Room[("Room")]
        DS[("DataStore<br/>goals, presets,<br/>screen-time history")]
        Res["res/raw-xx<br/>warning wording"]
    end

    UI --> VMs --> Repos
    VMs --> Domain
    Repos --> Room
    Repos --> DS
    Repos --> Res

Key rules

  • Restriction decisions live in one place, RuleEngine. The accessibility service only detects the foreground app and forwards it.
  • Warning text is data (res/raw*/default_warnings.json, plus user-edited warnings), and every UI string is in strings.xml, so nothing is hardcoded in the UI.
  • Everything important becomes a HabitEvent (APP_OPENED, WARNING_SHOWN, APP_BLOCKED, OVERRIDE_USED, FOCUS_* and so on), and the events power Matrix.
  • State is persisted in Room so a killed process recovers its rules and any running focus session. REWIRE does not assume Android keeps it alive.
  • Four build flavors share one codebase: Full (Accessibility), Lite (Usage access, no accessibility service), Play (Full without the self-updater) and Play Lite (Lite without the self-updater, the Google Play build; updates through Play). See FLAVORS.md.

Project structure

app/src/main/java/com/aiyu/rewire/
├── RewireApp.kt, MainActivity.kt    Application, entry point
├── di/                              Hilt AppModule (Room, repositories, settings, engines)
├── core/
│   ├── analytics/       Daily summary worker
│   ├── apps/            Installed launcher apps (PackageManager)
│   ├── focus/           FocusController (app-scoped timer, persists every transition)
│   ├── guard/           HabitEngine, UsageTracker, GuardShield
│   ├── notifications/   Channels, notifier, Do Not Disturb, permission helpers
│   ├── permissions/     Accessibility / usage / overlay / battery status checks
│   ├── settings/        Settings model and repository, AppLocale (per-app language)
│   └── update/          GitHub self-updater, worker, install receiver
├── data/                Repositories (write-through cache), backup, presets, goals, screen-time store
│   └── local/           RewireDatabase, entities, DAOs, mappers, legacy import
├── domain/              Pure Kotlin
│   ├── habit/           Habit, ProtectedApp, RestrictionRule, AppLimits
│   ├── restriction/     RuleEngine, RestrictionDecision
│   ├── warning/         Warning, categories, picker
│   ├── focus/           FocusConfig validation, FocusTimer state machine, presets
│   ├── goals/           Goals, streaks
│   ├── analytics/       HabitEvent, metrics, period metrics, punchlines
│   ├── backup/          Versioned export / import format
│   └── update/          Versions, release channels, release notes
├── feature/             landing, onboarding, guard, focus, matrix, profile, update
├── service/
│   ├── accessibility/   RewireAccessibilityService (Full and Play only)
│   ├── monitoring/      GuardMonitorService (usage watch)
│   ├── focus/           FocusTimerService
│   └── boot/            BootReceiver
└── ui/                  theme (color, type, shape, motion), shared components, nav host
app/src/main/res/        values-xx/strings.xml and raw-xx/default_warnings.json per language

More detail: ARCHITECTURE.md, DESIGN.md, DECISIONS.md, ROADMAP.md, LOCALIZATION.md, UPDATES.md. Progress is tracked in development/Todo.md.

Tech stack

AreaChoice
LanguageKotlin 2.4
UIJetpack Compose, Material 3 Expressive (1.5.0-alpha), dynamic color
NavigationNavigation Compose, type-safe routes, shared element transitions
DIHilt
AsyncCoroutines + Flow
PersistenceRoom (schema v5, exported, migration-tested) and DataStore Preferences
BackgroundWorkManager, foreground services, BootReceiver
Serializationkotlinx.serialization
MonitoringAccessibilityService, UsageStatsManager
Localization27 languages, Android per-app language API (LocaleManager, API 33+) with a fallback below
OtherBiometric, Core SplashScreen, Graphics Shapes (morphing shapes)
TestingJUnit (JVM unit tests for domain logic), AndroidX Test (migrations)

SDK: minSdk 26, targetSdk 35. Versions are in gradle/libs.versions.toml.

Permissions

Each permission is explained in-app before it is requested.

PermissionWhy
Accessibility service (Full, Play)Detect which protected app just opened. Reads no screen content.
Usage accessCount time in guarded apps for limits and Matrix, and detect launches in Lite. Stays on device.
Display over other appsShow the warning or block screen on top of a guarded app (needed by Lite).
NotificationsFocus timer, break alerts, daily summary and important Guard status.
Do Not Disturb access (optional)Silence messages during Focus while calls and alarms still ring.
Battery optimization (guidance only)Reduce the chance the system stops protection. The app never changes this silently.
Internet, install packages (not in Play)Optional self-update from GitHub Releases.

Android controls process lifetime. REWIRE is built for resilience (persisted state, system-bound services), not for a promise that it can never be killed.

Install

Every release ships two APKs with the same features:

APKDetects protected apps throughPick it when
Rewire-Lite-<version>.apkUsage access + Display over apps (within ~1 s)You download from a browser. Play Protect lets it install, and banking/UPI apps keep working.
Rewire-<version>.apk (Full)Accessibility (instant)You install with Obtainium or adb install.

Why two: Play Protect's fraud protection blocks browser and file-manager installs of any app that declares an accessibility service. Payment apps also refuse to run while one from outside Play is switched on. On Full, turn Rewire off in Accessibility before paying. Guard keeps working through Usage access (grant it and Display over apps), then turn it back on.

Both are signed with the same key. Install the other APK over the top to switch builds, and your data is kept. Each one updates itself within its own flavor. Profile → About Rewire shows which one you have (Full build / Lite build).

Both keep guarding with Rewire closed or swiped away from recents. The Guard service runs on its own with an ongoing notification and restarts after the system kills it or the phone reboots. Two things stop it until you open Rewire again: Force stop in App info, and an aggressive battery saver. Set Rewire's battery usage to Unrestricted.

Build and run

Requirements: Android Studio (current stable) or JDK 17+ with the Android SDK, and a device or emulator on API 26+.

# Build, install and launch the debug build on a connected device/emulator
./run.sh            # add --logs to stream logcat

# Or manually (Full; installLiteDebug for Lite, REWIRE_FLAVOR=Lite ./run.sh)
./gradlew installFullDebug

# Unit tests
./gradlew test

The debug build installs as com.aiyu.rewire.debug. After install, open Profile → Permissions to enable Accessibility (Full only), Usage access and the other grants, then create a habit in Guard.

Testing

Domain logic is tested without Android: rule engine (Minor, Major, Max, daily and launch limits, allowed window, escalation, Focus bypass), focus state machine and break <= focus validation, warning picking and localisation rules, metrics and streak aggregation, backup format, release/version parsing. Room migrations have instrumented tests. See app/src/test/ and app/src/androidTest/.

./gradlew :app:testFullDebugUnitTest :app:lintLiteDebug

Roadmap

PhaseScopeStatus
1Expressive UI, 4-tab shell, notificationsdone
2Room persistence, Hiltdone
3Guard engine, foreground-service focus timer, boot recovery, Full and Lite monitoringdone
4–5Usage analytics, complete Matrixdone
6 (V2)Smart escalation, streaks, presets, goals, localisation (27 languages)done, native review pending
7 (V3)Opt-in external data adapters, cloud backup, read-only AI insightsplanned

Rules always stay deterministic. Any future AI layer only explains recorded data and never controls restrictions.

Contributing

Small, conventional commits (feat:, fix:, refactor:, test:). Keep business logic out of Activities, services and receivers, keep rule logic in RuleEngine, and add tests for rule-engine changes. See CLAUDE.md for the full project rules.

License

Released under the MIT License.

// stack

  • Kotlin

// specs

status
Working
type
Open Source
year
2026
language
Kotlin
license
MIT
stars
1
branch
master

Repository data last synced