Karumi/Dexter
Android library that simplifies the process of requesting permissions at runtime.
Healthy across all four use cases
weakest axisPermissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓26+ active contributors
- ✓Distributed ownership (top contributor 26% of recent commits)
- ✓Apache-2.0 licensed
Show all 6 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Stale — last commit 5y ago
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 "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/karumi/dexter)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/karumi/dexter on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: Karumi/Dexter
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/Karumi/Dexter 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
GO — Healthy across all four use cases
- 26+ active contributors
- Distributed ownership (top contributor 26% of recent commits)
- Apache-2.0 licensed
- CI configured
- Tests present
- ⚠ Stale — last commit 5y ago
<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 Karumi/Dexter
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/Karumi/Dexter.
What it runs against: a local clone of Karumi/Dexter — 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 Karumi/Dexter | Confirms the artifact applies here, not a fork |
| 2 | License is still Apache-2.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 ≤ 1801 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of Karumi/Dexter. If you don't
# have one yet, run these first:
#
# git clone https://github.com/Karumi/Dexter.git
# cd Dexter
#
# 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 Karumi/Dexter and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "Karumi/Dexter(\\.git)?\\b" \\
&& ok "origin remote is Karumi/Dexter" \\
|| miss "origin remote is not Karumi/Dexter (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(Apache-2\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"Apache-2\\.0\"" package.json 2>/dev/null) \\
&& ok "license is Apache-2.0" \\
|| miss "license drift — was Apache-2.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 "dexter/src/main/java/com/karumi/dexter/Dexter.java" \\
&& ok "dexter/src/main/java/com/karumi/dexter/Dexter.java" \\
|| miss "missing critical file: dexter/src/main/java/com/karumi/dexter/Dexter.java"
test -f "dexter/src/main/java/com/karumi/dexter/DexterInstance.java" \\
&& ok "dexter/src/main/java/com/karumi/dexter/DexterInstance.java" \\
|| miss "missing critical file: dexter/src/main/java/com/karumi/dexter/DexterInstance.java"
test -f "dexter/src/main/java/com/karumi/dexter/AndroidPermissionService.java" \\
&& ok "dexter/src/main/java/com/karumi/dexter/AndroidPermissionService.java" \\
|| miss "missing critical file: dexter/src/main/java/com/karumi/dexter/AndroidPermissionService.java"
test -f "dexter/src/main/java/com/karumi/dexter/DexterActivity.java" \\
&& ok "dexter/src/main/java/com/karumi/dexter/DexterActivity.java" \\
|| miss "missing critical file: dexter/src/main/java/com/karumi/dexter/DexterActivity.java"
test -f "dexter/src/main/java/com/karumi/dexter/listener/multi/MultiplePermissionsListener.java" \\
&& ok "dexter/src/main/java/com/karumi/dexter/listener/multi/MultiplePermissionsListener.java" \\
|| miss "missing critical file: dexter/src/main/java/com/karumi/dexter/listener/multi/MultiplePermissionsListener.java"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 1801 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~1771d)"
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/Karumi/Dexter"
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
Dexter is an Android library (Java, 112KB codebase) that abstracts the complexity of Android 6.0+ runtime permissions into a fluent, callback-based API. Instead of writing permission-checking boilerplate in Activities, developers call Dexter.withContext(activity).withPermission(Manifest.permission.CAMERA).withListener(listener).check() and handle grants/denials in listener callbacks. It handles the entire flow: checking grant status, showing system dialogs, managing rationale screens, and invoking permission callbacks on the correct thread. Single-module library structure: dexter/src/main/java/com/karumi/dexter/ contains the core engine (Dexter.java entry point, DexterActivity.java for system dialogs, DexterInstance.java for state), with two listener trees under listener/single/ (BasePermissionListener) and listener/multi/ (MultiplePermissionsListener, CompositeMultiplePermissionsListener, dialog/snackbar UI helpers). No separate test module visible.
👥Who it's for
Android developers (particularly those supporting API 23+) who need to request camera, location, contacts, or other dangerous permissions at runtime without scattering permission logic across multiple Activity lifecycle methods. Teams building camera apps, location services, or photo libraries benefit most from its clean listener pattern and pre-built UI components like DialogOnDeniedPermissionListener.
🌱Maturity & risk
Abandoned / No longer actively developed. The README explicitly states 'This project is no longer under active development' and directs users to android-arsenal alternatives. The codebase is stable (version 6.2.3 on Maven Central), has CI via Travis CI, and follows Checkstyle rules, but expect no bug fixes, security updates, or Android 12+ API level support. Suitable only for legacy apps or as reference material.
High risk for new projects: the library is unmaintained and Google now recommends Jetpack's androidx.activity.result.contract.ActivityResultContracts for permissions. No visible dependency management in build.gradle beyond Gradle 3.6.2 (from 2020). No evidence of tests in the file list (no src/test/ or src/androidTest/ directories shown), making regression detection impossible. Single maintainer (Karumi org) with zero recent commits.
Active areas of work
Nothing. The project is in maintenance-only mode with no active development. The last meaningful activity appears to be version 6.2.3 release. No PRs, milestones, or issues are being tracked based on the file structure shown.
🚀Get running
Clone the repo, sync Gradle dependencies, and run the sample app:
git clone https://github.com/Karumi/Dexter.git
cd Dexter
./gradlew build
./gradlew installDebug # or open in Android Studio and run
Daily commands:
In Android Studio: File → Open → select Dexter root folder → Gradle sync → Run (or ./gradlew installDebug from CLI). No dev server; this is a library meant to be included as a dependency.
🗺️Map of the codebase
dexter/src/main/java/com/karumi/dexter/Dexter.java— Main entry point and public API facade that developers use to request permissions; defines the core DexterBuilder pattern.dexter/src/main/java/com/karumi/dexter/DexterInstance.java— Core state machine that manages the permission request lifecycle and coordinates with the permission service.dexter/src/main/java/com/karumi/dexter/AndroidPermissionService.java— Low-level abstraction over Android's runtime permission system; bridges native Android APIs to the Dexter request model.dexter/src/main/java/com/karumi/dexter/DexterActivity.java— Invisible activity used to capture Android's permission request results and deliver callbacks to listeners.dexter/src/main/java/com/karumi/dexter/listener/multi/MultiplePermissionsListener.java— Core listener interface for multi-permission requests; all permission result handling flows through this contract.dexter/src/main/java/com/karumi/dexter/listener/single/PermissionListener.java— Core listener interface for single-permission requests; defines the callback contract for granted and denied states.
🛠️How to make changes
Create a Custom Single Permission Listener
- Extend BasePermissionListener or implement PermissionListener directly (
dexter/src/main/java/com/karumi/dexter/listener/single/BasePermissionListener.java) - Override onPermissionGranted(PermissionGrantedResponse) to handle granted state (
dexter/src/main/java/com/karumi/dexter/listener/single/PermissionListener.java) - Override onPermissionDenied(PermissionDeniedResponse) to handle denied state (
dexter/src/main/java/com/karumi/dexter/listener/single/PermissionListener.java) - Reference your listener in Dexter.with(context).checkPermissions(permission).withListener(yourListener).check() (
dexter/src/main/java/com/karumi/dexter/Dexter.java)
Request Multiple Permissions with Custom Response Handling
- Implement MultiplePermissionsListener or extend BaseMultiplePermissionsListener (
dexter/src/main/java/com/karumi/dexter/listener/multi/BaseMultiplePermissionsListener.java) - Override onPermissionsChecked(MultiplePermissionsReport) to inspect all permission results (
dexter/src/main/java/com/karumi/dexter/listener/multi/MultiplePermissionsListener.java) - Check report.areAllPermissionsGranted() and report.getDeniedPermissionResponses() to handle mixed results (
dexter/src/main/java/com/karumi/dexter/MultiplePermissionsReport.java) - Call Dexter.with(context).withPermissions(perm1, perm2).withListener(yourListener).check() (
dexter/src/main/java/com/karumi/dexter/Dexter.java)
Compose Multiple Listeners for Combined Behavior
- Create individual listeners (e.g., dialog listener, snackbar listener, custom logic) (
dexter/src/main/java/com/karumi/dexter/listener/multi/DialogOnAnyDeniedMultiplePermissionsListener.java) - Use CompositeMultiplePermissionsListener to chain them together (
dexter/src/main/java/com/karumi/dexter/listener/multi/CompositeMultiplePermissionsListener.java) - Pass the composite listener to your permission request (
dexter/src/main/java/com/karumi/dexter/Dexter.java)
Handle Permission Request Errors
- Implement PermissionRequestErrorListener to handle system-level failures (
dexter/src/main/java/com/karumi/dexter/listener/PermissionRequestErrorListener.java) - Override onError(DexterError) to respond to errors like permission service unavailable (
dexter/src/main/java/com/karumi/dexter/listener/DexterError.java) - Attach via .withErrorListener(yourErrorListener) on any permission request (
dexter/src/main/java/com/karumi/dexter/DexterBuilder.java)
🔧Why these technologies
- Invisible Activity (DexterActivity) — Avoids requiring developers to handle onRequestPermissionsResult in their activities; Dexter intercepts results via its own activity.
- Builder Pattern (DexterBuilder) — Provides fluent, readable API and encapsulates optional configurations (listeners, error handlers) without constructor overloading.
- Thread Decorators (MainThread/WorkerThread) — Guarantees callbacks execute on the correct thread without requiring developers to manage thread switching manually.
- Listener Composition (Composite pattern) — Allows chaining multiple behaviors (dialog, snackbar, custom logic) without tight coupling or inheritance hierarchies.
⚖️Trade-offs already made
-
Invisible DexterActivity added to manifest at runtime
- Why: Avoids requiring developers to declare an activity; decouples permission handling from user-visible activities.
- Consequence: Adds a hidden activity that may be confusing during debugging; slightly increases manifest complexity.
-
Single-permission and multi-permission APIs kept separate
- Why: Simpler, more type-safe APIs for common single-permission use cases.
- Consequence: More code to maintain; developers must choose between PermissionListener and MultiplePermissionsListener interfaces.
-
Listener callbacks always delivered on MainThread
- Why: UI updates (dialogs, snackbars) require main thread; avoids threading errors in user code.
- Consequence: Cannot use Dexter for background-only permission logic without adapters; adds minimal thread overhead.
🚫Non-goals (don't propose these)
- Does not handle dynamic permission groups or Android 13+ permission scope logic; assumes flat permission model.
- Does not provide runtime permission deprecation warnings or migration helpers; targets developers
🪤Traps & gotchas
No test suite: file list shows zero test files; all testing must be manual on Android devices. Thread marshaling: callbacks are forcibly executed on MainThread via MainThread.java—custom listeners that call runOnUiThread() will deadlock. DexterActivity transparency: the library uses an invisible Activity to handle permission dialogs; apps with Process.KILL_BACKGROUND_PROCESSES or aggressive task killers may suppress the dialog. API 31+ scoped storage: Dexter does not handle the new Scoped Storage semantics (no READ_EXTERNAL_STORAGE fallback); use AndroidX alternatives for modern apps. No fragment support: DexterActivity must be added to AndroidManifest.xml manually; fragment-first architectures require boilerplate.
🏗️Architecture
💡Concepts to learn
- Runtime Permissions (Android 6.0+) — Dexter's entire purpose is to abstract the Android permissions model introduced in API 23; understanding the grant flow (check → deny/grant → rationale → retry) is essential to using this library.
- Transparent Activity Pattern — DexterActivity is declared in AndroidManifest.xml but never shown to users; it intercepts permission dialogs and callbacks, a pattern that's critical to understand when debugging lifecycle issues.
- Thread Marshaling / Main Thread Callbacks — Dexter forces all listener callbacks to execute on MainThread via MainThread.java (using Handler.post); understanding why PermissionListener methods are always on the UI thread prevents deadlock bugs.
- Token-Based Async Authorization — The PermissionToken and PermissionRationaleToken pattern allows the user to defer permission requests (e.g., show a rationale dialog, then call token.continuePermissionRequest() later); this is a state machine flow, not immediate.
- Listener Composition & Adapter Pattern — MultiplePermissionsListenerToPermissionListenerAdapter and CompositeMultiplePermissionsListener let you chain listeners (e.g., log + show dialog); essential for building reusable permission UI components.
- Fluent Builder API — DexterBuilder implements a fluent chain (Dexter.withContext(...).withPermission(...).withListener(...).check()); understanding this pattern helps you extend or mock the library.
- ProGuard Obfuscation & Callback Interface Preservation — dexter/proguard-rules.pro must keep callback interfaces unobfuscated so reflection-based Android framework can invoke them; ProGuard mistakes here break permission callbacks in release builds.
🔗Related repos
google/accompanist— Jetpack Compose-native permissions library; the modern replacement for Dexter if you're targeting Compose or API 31+googlearchive/android-PermissionChecker— Google's now-archived compat library that Dexter wraps; shows how AndroidPermissionService.java delegates to ContextCompat.checkSelfPermission()permissions-dispatcher/PermissionsDispatcher— Annotation-based alternative to Dexter using code generation (@NeedsPermission) instead of fluent builders; same era, different approachandroidx/androidx— Contains ActivityResultContracts.RequestPermission and RequestMultiplePermissions; the official Jetpack replacement for runtime permissionsKarumi/Ktor-Client-Mock— Same maintainer (Karumi); shows testing patterns used across their library ecosystem
🪄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 instrumented Android tests for DexterActivity and permission flow integration
The repo only has unit tests in dexter/src/test/java/ but lacks AndroidTest instrumented tests (dexter/src/androidTest/ directory is missing). DexterActivity.java is a critical component that handles the actual permission request flow and dialog interactions, but has no corresponding integration tests. This would validate the real Android framework interactions and permission callback chains.
- [ ] Create dexter/src/androidTest/java/com/karumi/dexter/ directory structure
- [ ] Add DexterActivityTest.java to test permission request flow with ActivityTestRule
- [ ] Add MultiplePermissionsListenerIntegrationTest.java to verify callback chains for granted/denied permissions
- [ ] Add PermissionRationaleTokenTest.java to test rationale dialog handling
- [ ] Update dexter/build.gradle to include androidx.test dependencies (androidTestImplementation)
Add GitHub Actions workflow to replace deprecated Travis CI configuration
The repo uses .travis.yml for CI/CD but Travis CI has deprecated their free tier for open source projects. GitHub Actions is native to GitHub and would be more maintainable. The current build.gradle uses Android Gradle 3.6.2 which is outdated. A GitHub Actions workflow would ensure builds stay current and provide faster feedback.
- [ ] Create .github/workflows/android-build.yml with matrix strategy for multiple API levels
- [ ] Configure workflow to run checkstyle task (already configured in build.gradle)
- [ ] Add test execution step for ./gradlew test
- [ ] Add step to verify ProGuard rules in dexter/proguard-rules.pro
- [ ] Remove or deprecate .travis.yml with a note in README.md pointing to GitHub Actions
Add comprehensive Javadoc documentation for public API classes and generate HTML docs site
The library has public-facing classes (Dexter.java, DexterBuilder.java, MultiplePermissionsListener, PermissionListener) with minimal or missing Javadoc comments. The README is incomplete (cuts off mid-sentence). Proper Javadoc with examples and exception documentation would significantly improve contributor and user experience, especially for a permission-handling library where API clarity is critical.
- [ ] Add class-level and method-level Javadoc to dexter/src/main/java/com/karumi/dexter/Dexter.java with usage examples
- [ ] Add Javadoc to DexterBuilder.java documenting fluent API chain and builder patterns
- [ ] Add exception documentation to methods in PermissionToken.java and PermissionRationaleToken.java
- [ ] Document listener interfaces: MultiplePermissionsListener.java and PermissionListener.java with callback parameters
- [ ] Update build.gradle to add Javadoc generation task and publish to gh-pages (or similar hosting)
- [ ] Complete the truncated README.md file with full feature descriptions and API examples
🌿Good first issues
- Add JUnit 4 + Espresso test suite for DexterBuilder and the permission state machine in DexterInstance.java—currently zero test coverage means regressions go undetected.
- Document the exact Activity launch lifecycle in README with a sequence diagram, since DexterActivity is invisible and many developers report confusion about when callbacks fire.
- Add support for Android 12+ BLUETOOTH and other new dangerous permissions by extending the listener examples in listener/multi/ with Android version guards and migration guide.
⭐Top contributors
Click to expand
Top contributors
- @pedrovgs — 26 commits
- @Serchinastico — 21 commits
- [@Sergio Gutierrez](https://github.com/Sergio Gutierrez) — 19 commits
- [@Fran Fernandez](https://github.com/Fran Fernandez) — 4 commits
- @flipper83 — 4 commits
📝Recent commits
Click to expand
Recent commits
59132a1— Update readme (pedrovgs)af457fe— Prepare next release (pedrovgs)5cf3a7b— Update proguard-rules.pro (#283) (pedrovgs)b35897b— Prepare next development iteration (pedrovgs)5557b90— Prepare release 6.2.2 (pedrovgs)e52b7d0— Fix duplicated permission report (#275) (pedrovgs)11c6351— Prepare next development iteration (pedrovgs)2774042— Prepare release 6.2.1 (pedrovgs)c0af2bd— fix #262 (#264) (binarynoise)a6db8e8— Prepare next development iteration (pedrovgs)
🔒Security observations
The Dexter library has moderate to significant security concerns primarily due to its unmaintained status and outdated dependencies. The project is no longer under active development, which is the most critical issue as security vulnerabilities will not be patched. The use of deprecated JCenter repository and outdated Gradle build tools creates additional risks. The codebase structure suggests proper separation of concerns for Android permission handling, but the lack of visible input validation and the project's unmaintained status mean potential vulnerabilities may exist without remediation. Organizations using this library should strongly consider migrating to actively maintained alternatives like Android's modern permission handling libraries.
- High · Outdated Gradle Build Tools —
build.gradle - classpath 'com.android.tools.build:gradle:3.6.2'. The project uses Gradle Android plugin version 3.6.2, which is significantly outdated (released in 2020). This version contains known security vulnerabilities in the build system and lacks modern security features and updates. Fix: Update to the latest stable version of Android Gradle Plugin (currently 8.x). Review and update all build tool dependencies to their latest versions. - High · Use of Deprecated JCenter Repository —
build.gradle - repositories { jcenter() }. The project uses 'jcenter()' repository which is deprecated and no longer functional. JCenter announced shutdown in 2021. This can lead to build failures and inability to fetch dependencies, potentially pushing developers to use unreliable mirrors. Fix: Remove jcenter() and rely exclusively on 'google()' and 'mavenCentral()' repositories. Update all dependency sources to use Maven Central or Google's Maven repository. - Medium · Project No Longer Under Active Development —
README.md. The README explicitly states 'This project is no longer under active development.' This means security vulnerabilities will not be patched, and the library may have known unfixed security issues. Fix: Consider migrating to an actively maintained permission request library. If using this library, conduct thorough security audits and consider forking for security patches. - Medium · Missing Input Validation in Permission Handling —
dexter/src/main/java/com/karumi/dexter/DexterActivity.java, PermissionToken.java, PermissionRationaleToken.java. The codebase includes permission request handling through DexterActivity and related components. Without reviewing actual implementation, there's a risk of improper permission token validation or intent handling vulnerabilities if not properly sanitized. Fix: Ensure all permission tokens are cryptographically validated and cannot be tampered with. Implement proper intent validation and avoid passing sensitive data through intents. Add input validation for all permission-related callbacks. - Medium · Missing Security Documentation —
Repository root. No security policy, security.md, or vulnerability disclosure guidelines found in the repository. This makes it difficult for security researchers to report vulnerabilities responsibly. Fix: Create a SECURITY.md file with vulnerability disclosure guidelines. Include security best practices for using the library and any known limitations. - Low · ProGuard Configuration Present —
dexter/proguard-rules.pro, sample/proguard-rules.pro. While ProGuard rules are present (proguard-rules.pro), there is a risk of over-aggressive obfuscation hiding security issues or improperly protecting sensitive code paths. Fix: Review ProGuard rules to ensure security-sensitive classes are not over-obfuscated. Keep exception handling clear and maintainable for security debugging. - Low · CI/CD Configuration Outdated —
.travis.yml. The project uses Travis CI (.travis.yml) which has been deprecated. Additionally, the CI configuration is not visible in the provided file structure but likely uses outdated runners and configurations. Fix: Migrate to GitHub Actions or another modern CI/CD platform. Ensure security scanning is enabled in the CI/CD pipeline with tools like SAST, dependency scanning, and secret detection.
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.