{"id":50867025,"url":"https://github.com/smellouk/shellify","last_synced_at":"2026-06-15T02:11:50.542Z","repository":{"id":358365959,"uuid":"1241142962","full_name":"smellouk/shellify","owner":"smellouk","description":"An android app that wraps any website into an isolated WebView with per-app ad blocking, biometric lock, and encrypted backup — local-first, no cloud, no analytics.","archived":false,"fork":false,"pushed_at":"2026-06-13T06:11:04.000Z","size":112337,"stargazers_count":12,"open_issues_count":7,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-13T07:14:02.038Z","etag":null,"topics":["android","compose","kotlin","privacy","webapp","webview"],"latest_commit_sha":null,"homepage":"https://shellify.app","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/smellouk.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-17T02:27:03.000Z","updated_at":"2026-06-13T06:11:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/smellouk/shellify","commit_stats":null,"previous_names":["smellouk/shellify"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/smellouk/shellify","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smellouk%2Fshellify","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smellouk%2Fshellify/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smellouk%2Fshellify/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smellouk%2Fshellify/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/smellouk","download_url":"https://codeload.github.com/smellouk/shellify/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/smellouk%2Fshellify/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34344507,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-15T02:00:07.085Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["android","compose","kotlin","privacy","webapp","webview"],"created_at":"2026-06-15T02:11:49.999Z","updated_at":"2026-06-15T02:11:50.535Z","avatar_url":"https://github.com/smellouk.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003e\n  \u003cimg src=\"docs/icon.webp\" alt=\"Shellify icon\" width=\"192\" height=\"192\"/\u003e\n  \u003cbr\u003e\n  Shellify\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\u003cstrong\u003eTurn any website into an isolated, ad-free app on your home screen.\u003c/strong\u003e\u003c/p\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[![Latest release](https://img.shields.io/github/v/release/smellouk/shellify?style=flat\u0026labelColor=D0E8FF\u0026color=0076D6)](https://github.com/smellouk/shellify/releases/latest)\n[![Downloads](https://img.shields.io/github/downloads/smellouk/shellify/total?style=flat\u0026labelColor=D0E8FF\u0026color=0076D6)](https://github.com/smellouk/shellify/releases)\n[![Stars](https://img.shields.io/github/stars/smellouk/shellify?style=flat\u0026labelColor=D0E8FF\u0026color=0076D6)](https://github.com/smellouk/shellify/stargazers)\n[![License](https://img.shields.io/github/license/smellouk/shellify?style=flat\u0026labelColor=D0E8FF\u0026color=0076D6)](LICENSE)\n[![CI](https://github.com/smellouk/shellify/actions/workflows/main.yml/badge.svg)](https://github.com/smellouk/shellify/actions/workflows/main.yml)\n\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n[\u003cimg src=\"docs/get_github.png\" alt=\"Get it on GitHub\" width=\"45%\" align=\"center\"\u003e](https://github.com/smellouk/shellify/releases/latest)\n[\u003cimg src=\"docs/get_obtainium.png\" alt=\"Get it on Obtainium\" width=\"45%\" align=\"center\"\u003e](https://apps.obtainium.imranr.dev/redirect?r=obtainium://app/%7B%22id%22%3A%22io.shellify.app%22%2C%22url%22%3A%22https%3A//github.com/smellouk/shellify%22%2C%22author%22%3A%22smellouk%22%2C%22name%22%3A%22Shellify%22%2C%22preferredApkIndex%22%3A0%2C%22additionalSettings%22%3A%22%7B%5C%22includePrereleases%5C%22%3Afalse%2C%5C%22fallbackToOlderReleases%5C%22%3Atrue%2C%5C%22filterReleaseTitlesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22filterReleaseNotesByRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22verifyLatestTag%5C%22%3Afalse%2C%5C%22dontSortReleasesList%5C%22%3Afalse%2C%5C%22useLatestAssetDateAsReleaseDate%5C%22%3Afalse%2C%5C%22trackOnly%5C%22%3Afalse%2C%5C%22versionExtractionRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22matchGroupToUse%5C%22%3A%5C%22%5C%22%2C%5C%22versionDetection%5C%22%3Atrue%2C%5C%22releaseDateAsVersion%5C%22%3Afalse%2C%5C%22useVersionCodeAsOSVersion%5C%22%3Afalse%2C%5C%22apkFilterRegEx%5C%22%3A%5C%22%5C%22%2C%5C%22invertAPKFilter%5C%22%3Afalse%2C%5C%22autoApkFilterByArch%5C%22%3Atrue%2C%5C%22appName%5C%22%3A%5C%22Shellify%5C%22%2C%5C%22exemptFromBackgroundUpdates%5C%22%3Afalse%2C%5C%22skipUpdateNotifications%5C%22%3Afalse%2C%5C%22about%5C%22%3A%5C%22A%20local-first%20Android%20PWA%20launcher%20that%20wraps%20websites%20in%20isolated%20WebView%20containers%20with%20per-app%20ad%20blocking%2C%20biometric%20lock%2C%20and%20encrypted%20backup.%5C%22%2C%5C%22appAuthor%5C%22%3A%5C%22smellouk%5C%22%7D%22%2C%22overrideSource%22%3Anull%7D)\n\n\u003c/div\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n### Signing Certificate Fingerprints\n\nUse these to verify the APK signature.\n\n```\nSHA-256: EF:A3:C6:37:40:77:87:EE:97:18:58:7C:DE:FE:3F:86:02:E2:41:05:49:BE:DE:71:8F:4E:4D:74:EB:0C:23:21\nSHA-1: 75:F2:73:AF:01:93:EF:08:F3:F2:2F:8C:B2:EA:FE:8B:BC:A0:27:73\n```\n\n\u003c/div\u003e\n\n\n---\n\n\u003ctable\u003e\n\u003ctr\u003e\n\u003ctd valign=\"top\" width=\"60%\"\u003e\n\n## Features\n\n- **PWA launcher** — Add any HTTPS website as a standalone home-screen app with its own icon, name, and theme color\n- **Per-app isolation** — Each app gets its own cookie jar, local storage, and (Android 13+) dedicated WebView profile\n- **Ad blocking** — Built-in content blocker with per-app custom rules and tracker blocking\n- **Tor routing** — Route individual apps through Tor for anonymous browsing; requires GeckoView\n- **Reading mode** — Strip any page down to article text via the control center; powered by Mozilla Readability.js\n- **Translation** — In-page translation via Google Translate; configurable per app\n- **App lock** — Optional password or biometric lock per app or globally\n- **Privacy controls** — Always-incognito mode, cookie auto-wipe on exit, stealth recents, HTTPS enforcement per app\n- **Panic button** — Long-press wipe in the control center: clears all sessions and deletes all apps\n- **Two browser engines** — Android System WebView (default) or Mozilla GeckoView (optional download)\n- **User-agent switching** — Chrome, Firefox, Safari, Edge, or custom user-agent per app\n- **Swipe to refresh** — Pull-to-refresh with a per-app toggle\n- **Encrypted backup** — AES-256-GCM backup files protected with a user-chosen password (Argon2id key derivation); manual or scheduled\n- **Home-screen shortcuts** — Android launcher shortcuts for individual web apps\n- **Icon packs** — Simple Icons integration for brand logos; custom icon selection\n- **Material You** — Dynamic theming, dark/light/system mode, custom accent colors\n- **Deep linking** — Share app configurations via QR code, link, or `shellify://` URI\n- **Multilingual** — English, French, and Arabic\n\n\u003c/td\u003e\n\u003ctd valign=\"top\" align=\"center\" width=\"40%\"\u003e\n\n## Demo\n\n![Shellify demo](docs/demo.gif)\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n---\n\n## Requirements\n\n| Tool | Version |\n|---|---|\n| Android Studio | Ladybug or newer |\n| JDK | 21 |\n| Gradle | wrapper included |\n| Android SDK | Compile SDK 36, Min SDK 26 |\n\nMinimum device: **Android 8.0 (API 26)**\nTarget: **Android 15 (API 36)**\n\n---\n\n## Getting Started\n\n```bash\n# Clone\ngit clone https://github.com/smellouk/shellify.git\ncd shellify\n\n# Build debug APK\n./gradlew assembleDebug\n\n# Install on connected device\n./gradlew installDebug\n\n# Build release APK (requires signing config)\n./gradlew assembleRelease\n```\n\nThe project uses **convention plugins** defined in `build-logic/` — no manual SDK path configuration is required beyond a standard Android Studio setup.\n\n---\n\n## Architecture\n\nShellify follows **Clean Architecture** with strict layer separation enforced by Konsist at compile time.\n\n```mermaid\ngraph TB\n    subgraph Presentation[\"Presentation — feature:*\"]\n        screens[\"Compose Screens · ViewModels\"]\n    end\n    subgraph Infrastructure[\"Infrastructure — core:*\"]\n        infra[\"database · engine · security · backup · crypto\\nisolation · pwa · translate · theme · locale\\niconpack · shortcut · deeplink · ui\"]\n    end\n    subgraph Domain[\"Domain — core:domain  ·  Pure Kotlin, no Android deps\"]\n        domain[\"Models · Repository Interfaces · Use Cases\"]\n    end\n\n    Presentation --\u003e Infrastructure\n    Presentation --\u003e Domain\n    Infrastructure --\u003e Domain\n```\n\n- **`core:domain`** — Pure Kotlin (no Android dependency). Defines all models, repository interfaces, and use cases.\n- **`core:*`** — Infrastructure modules that implement domain interfaces (database, engine, security, backup, etc.).\n- **`feature:*`** — Presentation layer only. Each feature module contains screens and ViewModels; no direct data access.\n- **`core:ui`** — Shared design system: composables, typography, spacing tokens, Material 3 theme.\n\nDependency direction: `feature → core:domain`, `core:* → core:domain`. Feature modules never depend on each other.\n\n---\n\n## Supported Features\n\n### Web Apps\n| Feature | Detail |\n|---|---|\n| PWA launcher | Add any website as a standalone home-screen app — name, icon, and theme color auto-detected from the manifest |\n| Per-app isolation | Dedicated cookie jar and local storage per app; Android 13+ gets a named WebView profile |\n| Ad blocking | Built-in content blocker with per-app enable/disable and custom rule support |\n| In-page translation | Google Translate JS injection — configurable source/target language per app |\n| User-agent override | Chrome, Firefox, Safari, Edge, or fully custom string per app |\n| Fullscreen mode | Hides system bars for immersive web apps |\n| Reading mode | Strip any article to clean text via the control center; Readability.js powered, sanitized before injection |\n| HTTPS enforcement | Force secure connections per app; rejects mixed-content upgrades |\n| Swipe to refresh | Pull-to-refresh with a per-app enable/disable toggle |\n| Control center | Floating toolbar: reload, translate, reading mode, ad blocking, Tor identity, panic wipe, and settings |\n\n### Browser Engines\n| Engine | Notes |\n|---|---|\n| Android System WebView | Default — uses the Chromium-based WebView already on the device |\n| Mozilla GeckoView | Optional — user-initiated download; switchable per app without reinstalling |\n\n### Notifications\n| Feature | Detail |\n|---|---|\n| In-app notifications | Web `Notification` API support with per-app allow/deny |\n| Background notifications | Foreground service with a dedicated GeckoView session for apps that need push-style alerts |\n| Notification channels | Per-app Android notification channel, grouped by category; channel removed when app is deleted |\n| DND scheduling | Per-app quiet hours (start/end hour) to suppress notifications |\n| Rate limiting | 100 notifications per app per day maximum |\n| Notification history | In-app log of recent notifications per app |\n\n### Security \u0026 Privacy\n| Feature | Detail |\n|---|---|\n| App lock | Optional password or biometric (fingerprint / face) lock per app |\n| Global password | Single password that gates all locked apps |\n| Wipe on failed attempts | Optional data wipe after N incorrect password entries |\n| Encrypted database | SQLCipher AES-256 — database is unreadable without the app key |\n| Encrypted backup | `.pwab` archive — Argon2id key derivation + AES-256-GCM cipher |\n| Screenshot protection | Optional `FLAG_SECURE` to block screen capture |\n| Incognito sessions | Ephemeral WebView session that wipes cookies and profile on exit |\n| Always-incognito mode | Force every session into incognito — no persistent cookies or storage |\n| Cookie auto-wipe | Automatically clear cookies when the app goes to background |\n| Tracker blocking | EasyPrivacy domain list blocks trackers on top of ad blocking |\n| Stealth recents | Masks app content in the Android recents screen |\n| HTTPS enforcement | Rejects HTTP loads and upgrades mixed content per app |\n| Tor routing | Per-app anonymous routing via Guardian Project `tor-android`; circuit rotatable on demand |\n| Panic button | Long-press wipe from the control center — deletes all apps and clears all sessions atomically |\n\n### Backup \u0026 Restore\n| Feature | Detail |\n|---|---|\n| Manual backup | Export to any folder via Android SAF |\n| Scheduled backup | Weekly or monthly via WorkManager |\n| Cross-device restore | `.pwab` files are portable — restore with the same password on any device |\n| Backup contents | Database, icons, settings, cookies (re-encrypted), WebView profiles (Android 13+) |\n\n### Customization \u0026 UX\n| Feature | Detail |\n|---|---|\n| Icon packs | Simple Icons integration — 3 000+ brand SVG logos rendered to PNG |\n| Custom icons | Pick any image from storage |\n| Material You | Dynamic color from wallpaper; light / dark / system mode |\n| Home-screen shortcuts | Android launcher shortcuts with the app's icon and theme color |\n| Categories | Group apps into named categories; filter the home grid |\n| Deep linking | Import apps via `shellify://` URI, HTTPS link, or QR code scan |\n| Multilingual | English, French, Arabic (runtime switchable) |\n\n---\n\n## Navigation\n\nNavigation uses **Jetpack Compose Navigation**. All routes are defined in `Screen.kt`; the graph is assembled in `AppNavigation.kt`.\n\n**Start destination logic:**\n\n```\nconsent not given           →  ConsentScreen\nonboarding not done         →  OnboardingScreen\nwhatsNewVersion outdated    →  WhatsNewScreen\notherwise                   →  HomeScreen\n```\n\nBottom navigation (Home, Categories, Shortcuts, Settings) is only visible on top-level routes.\n\n---\n\n## Deep Linking\n\nTwo URI schemes are registered for importing app configurations:\n\n| Scheme | Example |\n|---|---|\n| Custom | `shellify://add?url=\u003cbase64url-encoded-https-url\u003e\u0026name=\u003capp-name\u003e` |\n| HTTPS | `https://shellify.app/add?url=\u003cbase64url-encoded-https-url\u003e\u0026name=\u003capp-name\u003e` |\n\nThe URL parameter must be **Base64url-encoded** (no padding) and must decode to an `https://` URL — HTTP is rejected.\n\nA confirmation dialog showing the destination host is displayed before any app is added.\n\n**Test with ADB:**\n\n```bash\n# Encode a URL\nENCODED=$(printf '%s' \"https://youtube.com\" | base64 | tr '+/' '-_' | tr -d '=')\n\n# Fire the deep link\nadb shell am start -a android.intent.action.VIEW \\\n  -d \"shellify://add?url=${ENCODED}\u0026name=YouTube\" \\\n  io.shellify.app\n```\n\n---\n\n## Backup\n\nBackup files use the `.pwab` extension (an encrypted ZIP archive).\n\n- **Encryption:** Argon2id key derivation → AES-256-GCM cipher\n- **Contents:** Database dump, icons, settings, cookies (re-encrypted into archive), WebView profiles (Android 13+)\n- **Excluded:** App password hash, database passphrase, backup password — all device-specific secrets are never exported\n- **Storage:** User-selected folder via Android Storage Access Framework (SAF)\n- **Schedule:** Manual, weekly, or monthly via WorkManager\n- **Cross-device:** `.pwab` files are portable — restore on any device using the same password\n\n---\n\n## Testing\n\n```bash\n# Unit tests — includes Konsist architecture checks\n./gradlew testDebugUnitTest\n\n# Screenshot regression tests\n./gradlew verifyRoborazziDebug\n\n# Instrumented tests (requires connected device or emulator)\n./gradlew :app:connectedDebugAndroidTest\n\n# Full local check suite\n./gradlew detekt lintDebug testDebugUnitTest\n```\n\n| Layer | Framework |\n|---|---|\n| Unit tests | JUnit 4 + MockK |\n| Compose UI tests | Compose UI Test (JUnit4 rule) |\n| Screenshot tests | Roborazzi (Robolectric runner) — golden images committed alongside UI changes |\n| Architecture tests | Konsist — enforces Clean Architecture layer boundaries |\n| Database tests | Room in-memory database |\n\nInstrumented smoke tests cover navigation, consent gate, deep-link dialogs, and key screens end-to-end.\n\n### Developer Tools\n\n`docs/tools.html` is a single-page in-app test harness for manual feature testing. Serve it locally and load it inside Shellify:\n\n```bash\n# Tunnel host port 8080 to the device\nadb reverse tcp:8080 tcp:8080\n\n# Serve the docs folder (Python)\npython3 -m http.server 8080 --directory docs\n```\n\nThen open `http://localhost:8080/tools.html` as a Shellify web app. Available tabs:\n\n| Tab | What it tests |\n|---|---|\n| **Chrome Tools** | `ShellifyBridge` Java interface — direct notification dispatch, rate limit, and truncation via the Chromium WebView |\n| **GeckoView Tools** | Web `Notification` API via Gecko — permission flow, foreground fire, and 10-second background timer |\n\n---\n\n## Code Quality\n\n| Tool | Purpose |\n|---|---|\n| **Detekt** | Static analysis + ktlint formatting; config in `config/detekt/detekt.yml` |\n| **Android Lint** | Resource, accessibility, and API-level checks; config in `config/lint/lint.xml` |\n| **Konsist** | Architecture consistency — fails the build if layer rules are violated |\n\n```bash\n# Run Detekt\n./gradlew detekt\n\n# Run Lint\n./gradlew lintDebug\n```\n\n---\n\n## Tech Stack\n\n| Component | Library |\n|---|---|\n| Language | Kotlin |\n| UI | Jetpack Compose + Material 3 |\n| Navigation | Navigation Compose |\n| Database | Room + SQLCipher |\n| Preferences | DataStore |\n| Networking | OkHttp |\n| Image loading | Coil (+ SVG) |\n| Browser engine | System WebView + GeckoView (optional) |\n| Tor | Guardian Project `tor-android` + `jtorctl` |\n| QR codes | ZXing Core |\n| Biometrics | AndroidX Biometric |\n| Background work | WorkManager |\n| DI | Manual (ViewModel factories, no framework) |\n| Build | AGP + KSP |\n\n---\n\n## Roadmap\n\nSee [`.planning/ROADMAP.md`](.planning/ROADMAP.md) for the full phase breakdown. Active milestone: **v2 — Privacy-First Feature Parity**.\n\n---\n\n## Localization\n\nThree languages are supported at runtime, switchable from the onboarding screen or settings:\n\n| Code | Language |\n|---|---|\n| `en` | English (default) |\n| `fr` | French |\n| `ar` | Arabic |\n\nString resources live in `core/ui/src/main/res/values/strings.xml` (canonical English) and mirrored to `app/src/main/res/values-fr/` and `app/src/main/res/values-ar/`.\n\n---\n\n## Privacy\n\nShellify is local-first. No account, no cloud sync, no analytics, no crash reporting.\n\nThe only outbound network calls are:\n\n- Favicon fetch from the user's chosen domain\n- PWA manifest detection from the user's chosen domain\n- Optional Simple Icons library download (`cdn.jsdelivr.net`)\n- Optional GeckoView engine download (`maven.mozilla.org`), user-initiated\n- Translation requests (`translate.googleapis.com`), only when translation is enabled for an app\n\nFull details: [`docs/legal/privacy.md`](docs/legal/privacy.md)\n\n---\n\n## Legal\n\n- **Terms of Service:** [`docs/legal/terms.md`](docs/legal/terms.md)\n- **Privacy Policy:** [`docs/legal/privacy.md`](docs/legal/privacy.md)\n- **Branding:** The \"Shellify\" name, logo, and project branding are identifiers of the official project and are not granted under the open-source license. See [`NOTICE`](NOTICE).\n\n---\n\n## Contact\n\n[contact@shellify.app](mailto:contact@shellify.app)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmellouk%2Fshellify","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsmellouk%2Fshellify","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsmellouk%2Fshellify/lists"}