Skip to content

Demote QR pairing from primary surfaces - #8821

Merged
azooz2003-bit merged 7 commits into
mainfrom
feat-qr-demote
Jul 25, 2026
Merged

azooz2003-bit merged 7 commits into
mainfrom
feat-qr-demote

Conversation

@azooz2003-bit

@azooz2003-bit azooz2003-bit commented Jul 24, 2026 •

Copy link
Copy Markdown
Collaborator

QR pairing is iroh-first (the default QR payload is identity-only; the Tailscale host:port code is the legacy fallback behind "Pair an Older iPhone App"), and same-account zero-touch discovery is the primary pairing path. This PR makes every pairing surface read that way.

macOS

  • Titlebar "Connect iPhone/iPad" button (which lands on the QR window) is now hidden by default (mobileConnectButtonDefault = false); PostHog can still re-enable it remotely. Pairing stays reachable via Settings ▸ Mobile and the command palette.
  • The Pair iPhone window sizes itself to its content: a SwiftUI preference key reports the content height and the window controller grows the frame downward, clamped to the screen's visible frame, keeping scroll for short displays and never fighting a user mid-live-resize. Previously the fixed 832pt height cut off the "Pair an Older iPhone App" link and the setup steps.
  • Copy leads with automatic pairing: "iPhones signed in to the same cmux account connect automatically. Scan this code with the cmux app if this Mac doesn't appear on its own." The Settings ▸ Mobile row subtitle matches.

iOS

  • The Add Computer sheet no longer auto-presents on a signed-in phone with no pairings; the empty state teaches the zero-touch path: "Sign in to cmux on your computer with this account and it appears here automatically."
  • Settings ▸ Connection loses the "Rescan QR" row (it never scanned; it called disconnectAndHideActiveMac()), and the workspace overflow menu loses its twin. Per-computer hide on the Computers sheet rows remains the way to drop a Mac; a whole-phone "Forget All Computers" action was built and then omitted per owner decision.

All changed strings localized (EN + JA). Focused tests: MobileShellCompositeHideMacTests 16/16 green.

Summary by CodeRabbit

  • New Features

    • Added “Forget This Computer” actions to device settings on iOS and macOS.
    • Computers connected to the same account now appear automatically; QR pairing remains available as a manual option.
    • Improved macOS pairing window sizing to fit its content and screen.
  • Improvements

    • Updated empty states to explain automatic computer discovery.
    • Removed automatic prompting to add a computer after loading saved devices.
    • Disabled the mobile connect button by default when no remote setting is available.
    • Updated pairing guidance and translations.

Make same-account iroh discovery the primary path by hiding the macOS titlebar pairing button by default, stopping iOS from auto-presenting Add Computer, and renaming the disconnect-and-hide action to Forget This Computer.\n\nKeep QR pairing available as a manual fallback through explicit controls, and update the macOS/iOS copy and English/Japanese localizations to lead with automatic discovery.
@coderabbitai

coderabbitai Bot commented Jul 24, 2026 •

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The changes replace rescan actions with “Forget This Computer,” remove automatic add-device presentation after paired-Mac loading, update connection and empty-state guidance, disable the unavailable-flag fallback, and add content-driven sizing for the macOS pairing window.

Changes

Mobile connection behavior

Layer / File(s) Summary
Forget computer actions and hidden-state reset
Packages/iOS/CmuxMobileShell/..., Packages/iOS/CmuxMobileShellUI/...
Settings and workspace actions now invoke forgetComputer, backed by disconnectAndHideActiveMac(), with updated labels and accessibility identifiers.
Disconnected startup and empty states
Packages/iOS/CmuxMobileShellUI/..., ios/cmux/Resources/Localizable.xcstrings
Paired Macs load without automatically presenting the add-device flow, and empty states now direct users to sign in on their computer.
Pairing guidance and fallback behavior
Packages/macOS/CmuxSettingsUI/..., Sources/Mobile/Pairing/MobilePairingView.swift, Sources/FeatureFlags.swift, Resources/Localizable.xcstrings
Pairing text describes automatic same-account connections and manual QR pairing, while the unavailable Mobile Connect fallback defaults to disabled.

Pairing window layout

Layer / File(s) Summary
Pairing content height reporting
Sources/Mobile/Pairing/MobilePairingView.swift
The pairing view measures scroll content and reports its maximum height through a SwiftUI preference and callback.
Adaptive pairing-window resizing
Sources/Mobile/Pairing/MobilePairingWindowController.swift
The controller resizes and repositions the pairing window from reported content height, while tracking live resizing and screen bounds.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant MobileSettingsView
  participant WorkspaceShellView
  participant MobileShellComposite
  User->>MobileSettingsView: Select Forget This Computer
  MobileSettingsView->>WorkspaceShellView: Invoke forgetComputer
  WorkspaceShellView->>MobileShellComposite: Call disconnectAndHideActiveMac()
  MobileShellComposite-->>WorkspaceShellView: Disconnect and hide active Mac
Loading
sequenceDiagram
  participant MobilePairingView
  participant MobilePairingWindowController
  participant NSWindow
  MobilePairingView->>MobilePairingWindowController: Report measured content height
  MobilePairingWindowController->>NSWindow: Resize and clamp pairing window
  MobilePairingWindowController->>NSWindow: Bring window to front
Loading

Possibly related PRs

Suggested reviewers: lawrencecchen


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (2 errors, 2 warnings)

Check name Status Explanation Resolution
Cmux Algorithmic Complexity ❌ Error MobileShellComposite+WorkspaceChanges.swift:117 sorts chips.keys just to log one sample on every fetch batch, adding an unbounded O(n log n) pass to a socket path. Use an O(1) sample (chips.keys.first) or cap the log sample with an explicit small bound; keep the fetch path linear.
Cmux Full Internationalization ❌ Error FAIL: mobile.pairing.window.* and settings.mobile.pairDevice.subtitle in Resources/Localizable.xcstrings only have en/ja while the catalog supports 20 locales. Add translations for all existing locales (ar, bs, da, de, es, fr, it, km, ko, nb, pl, pt-BR, ru, th, tr, uk, zh-Hans, zh-Hant) to those changed keys.
Description check ⚠️ Warning The description covers Summary and Testing, but it omits the required Demo Video, Review Trigger, and Checklist sections from the template. Add the missing Demo Video, Review Trigger, and Checklist sections, and include any required links or checkbox statuses.
Docstring Coverage ⚠️ Warning Docstring coverage is 22.22% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (21 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: deprioritizing QR pairing in favor of other pairing surfaces.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Cmux Swift Actor Isolation ✅ Passed No new actor-isolation regression: added shared types are value/actor-safe, and the MainActor settings boundary is intentional and matched by its implementations.
Cmux Swift Blocking Runtime ✅ Passed PR-side diff adds no semaphores, sync waits, sleeps, delayed dispatch, polling, or locks; touched Swift changes are UI/copy/wiring only.
Cmux Browser Automation Off-Main ✅ Passed No browser-automation commands or policy routing changed; TerminalController diff is unrelated mobile/workspace code, and the control-policy file is untouched.
Cmux Expensive Synchronous Load ✅ Passed PR only changes pairing UI/copy and async paired-mac refreshes; no RestorableAgentSessionIndex.load() or transcript/JSONL history load was added to a main/interactive path.
Cmux Cache Substitution Correctness ✅ Passed The new hide/switch paths use loaded snapshots with nil fallbacks and scope rechecks; the cache helpers already handle cold/stale states before persisting.
Cmux No Hacky Sleeps ✅ Passed No fixed sleeps/polling were added in covered runtime code; the only wait-like change is a GitHub Actions workflow, which the rule exempts.
Cmux Swift Concurrency ✅ Passed No new DispatchQueue/Combine/completion-handler async plumbing; changed Task usage is existing or SwiftUI/AppKit boundary-bound.
Cmux Swift @Concurrent ✅ Passed No new @concurrent misuse: added async helpers stay on @MainActor/UI-bound paths, and the diff adds no nonisolated async work that should hop off actor.
Cmux Swift Package Boundaries ✅ Passed Changed root Sources files are UI/AppKit glue and a flag default; the rule allows such app-target code, and no reusable domain logic was moved out of a SwiftPM package.
Cmux Swiftpm Lockfiles ✅ Passed No .gitignore or Package.resolved files changed, and cmux.xcodeproj/project.pbxproj diff has no SwiftPM package-reference edits.
Cmux Swift Logging ✅ Passed No diff hunk adds print/debugPrint/dump/NSLog or changes Logger usage; the existing file-scoped Logger in MobileShellComposite.swift is unchanged.
Cmux User-Facing Error Privacy ✅ Passed Changed error/recovery strings are generic; no vendor/provider/internal details or secrets were exposed in user-facing copy.
Cmux Swiftui State Layout ✅ Passed PASS: The only new GeometryReader is a background measurement in an AppKit-hosted pairing view; no new ObservableObject/@published, lazy-row store refs, or render-time state writes.
Cmux Architecture Rethink ✅ Passed PASS: the SwiftUI/AppKit bridge uses a single window controller owner and an explicit height callback; no new sleeps, polling, locks, observers, or split lifecycle ownership were introduced.
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed PASS: MobilePairingWindowController uses stable cmux.mobilePairingWindow, it’s in cmuxAuxiliaryWindowIdentifiers, and Cmd+W routes through cmuxWindowShouldOwnCloseShortcut/lint.
Cmux Source Artifacts ✅ Passed All 12 changed paths are source, tests, or localization catalogs; none match the rule’s artifact/scratch patterns, and the removed test file is allowed.
Cmux No Test Or Debug Seam In Production Source ✅ Passed No production Sources/ file added a test-only accessor; the #if DEBUG in MobileIrohRuntimeComposition.swift backs a real debug setting path with app callers.
Cmux No Ambient Global State ✅ Passed New state/behavior stays on owning types (MobilePairingView, MobilePairingWindowController, MobileShellComposite); no new file-scope API, global var, or singleton.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-qr-demote

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@greptile-apps

greptile-apps Bot commented Jul 24, 2026 •

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR demotes QR pairing from primary macOS and iOS surfaces so that same-account zero-touch discovery is the first path users see. The QR path remains reachable from Settings ▸ Mobile and the command palette.

  • iOS: Removes the auto-present-add-device-sheet-on-empty behavior; updates empty-state copy; strips the "Rescan QR" row from Settings and the workspace overflow menu; renames the action to "Forget This Computer."
  • macOS: Hides the titlebar "Connect iPhone/iPad" button by default (PostHog-overridable); resizes the pairing window dynamically to its content via a GeometryReader+PreferenceKey mechanism and NSWindowDelegate live-resize guard; updates heading and subtitle copy.
  • Both locales (EN + JA) updated across both string catalogs.

Confidence Score: 5/5

Safe to merge. All changed paths are UI surface changes with no correctness-critical state affected.

The window-resize mechanism is correctly wired: ReleasingWindowController.installManagedWindow sets window.delegate = self, so the live-resize guard delegate methods fire correctly. The GeometryReader-in-background PreferenceKey pattern does not disturb layout. The feature flag default and its FLAG comment's defaultWhenUnavailable field are updated consistently. All three MobileSettingsView call sites drop the removed rescanQR parameter. Both string catalogs carry EN and JA entries for every changed string. The deleted tests exactly cover the removed behavior.

Files Needing Attention: No files require special attention.

Important Files Changed

Filename Overview
Sources/Mobile/Pairing/MobilePairingWindowController.swift Adds content-height-driven window resizing with live-resize guard. Delegate wiring is correct (ReleasingWindowController.installManagedWindow sets window.delegate = self). Logic is sound.
Sources/Mobile/Pairing/MobilePairingView.swift Adds GeometryReader-in-background + PreferenceKey mechanism to report content height. Pattern is correct: background GeometryReader does not affect layout; onPreferenceChange fires on main actor; reduce correctly handles single-child hierarchy.
Sources/FeatureFlags.swift Changes mobileConnectButtonDefault and the FLAG comment's defaultWhenUnavailable to false; both the static default and the flag definition are updated consistently.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/DisconnectedWorkspaceShellView.swift Removes auto-present-add-device-on-empty logic and shouldAutoPresentAddDeviceAfterLoadingSavedMacs computed property; updates empty-state copy. MobileSettingsView call site correctly drops rescanQR parameter.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileSettingsView.swift Removes rescanQR parameter and the Rescan QR row from the Connection section; updates hasConnectionSection predicate accordingly.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListView.swift Removes rescanQR property and its overflow-menu button; passes updated MobileSettingsView without the parameter.
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceShellView.swift Removes rescanQR from MobileSettingsView and WorkspaceListView call sites; two-line change.
Packages/iOS/CmuxMobileShellUI/Tests/CmuxMobileShellUITests/DisconnectedWorkspaceShellViewTests.swift Deleted; tests targeted the now-removed auto-present logic. Removal is correct.
Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite.swift Doc comment update only: disconnectAndHideActiveMac now backs Forget This Computer instead of Rescan QR.
Resources/Localizable.xcstrings EN and JA entries updated for mobile.pairing.window.subheading and settings.mobile.pairDevice.subtitle; both locales present.
ios/cmux/Resources/Localizable.xcstrings EN and JA entries updated for mobile.devices.emptyDescription and mobile.devices.emptyTitle; both locales present.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User opens pairing window] --> B[MobilePairingWindowController.show]
    B --> C{Window exists?}
    C -->|No| D[makeWindow: 560x800 initial size]
    C -->|Yes| E[Reuse existing window]
    D --> F[resizeWindowToIdealContentHeight\nidealContentHeight nil → no-op]
    E --> F2[resizeWindowToIdealContentHeight\napply cached height]
    F --> G[makeKeyAndOrderFront]
    F2 --> G
    G --> H[SwiftUI renders MobilePairingView]
    H --> I[GeometryReader in .background\nmeasures content height]
    I --> J[MobilePairingContentHeightPreferenceKey\nonPreferenceChange fires]
    J --> K[pairingContentHeightDidChange]
    K --> L{isUserResizing?}
    L -->|Yes| M[Skip resize — user is dragging]
    L -->|No| N[resizeWindowToIdealContentHeight\nclamp to screen visible frame]
    N --> O[window.setFrame — keep top edge,\ngrow down, shift up if clipped]
Loading

Reviews (6): Last reviewed commit: "Clamp programmatic pairing-window resize..." | Re-trigger Greptile

azooz2003-bit and others added 2 commits July 24, 2026 12:05
The Pair iPhone window now grows to its content's ideal height (clamped
to the screen's visible frame, scroll kept for short displays) so the
legacy Tailscale code link below the QR is discoverable without
scrolling. Settings and the workspace overflow menu lose the
active-Mac-only forget item; the Computers sheet gains a destructive
Forget All Computers action (confirmation dialog) backed by a new
forgetAllComputers() that disconnects and hides every stored pairing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite`+HiddenMacs.swift:
- Around line 186-217: Update forgetAllComputers() in
Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite+HiddenMacs.swift
(lines 186-217) to compare both macDeviceID and the active instance tag in its
fallback contains check, using the available activeTicket/activeInstanceTag
state. Add coverage in
Packages/iOS/CmuxMobileShell/Tests/CmuxMobileShellTests/MobileShellCompositeHideMacTests.swift
(lines 195-247) for an active tag absent from stored pairings while a sibling
tag for the same Mac is present.
- Around line 193-195: Update the forget-all flow around
storedPairedMacsIncludingHidden so it always awaits loadPairedMacs() before
computing the set of pairings to disconnect and hide, rather than refreshing
only when the in-memory list is empty. Use the freshly loaded authoritative
pairing data for the entire destructive operation.

In
`@Packages/iOS/CmuxMobileShell/Tests/CmuxMobileShellTests/MobileShellCompositeHideMacTests.swift`:
- Around line 195-247: The test
forgetAllComputersDisconnectsAndHidesVisibleHiddenAndTaggedPairings must also
cover an active instance tag absent from storedPairedMacsIncludingHidden while
another tag for the same Mac remains stored. Add a distinct active tagged
pairing and a different stored tag for that physical Mac, then assert
forgetAllComputers() hides the active pairing ID alongside all stored pairings
and clears the displayed list.

In `@Sources/Mobile/Pairing/MobilePairingWindowController.swift`:
- Around line 97-123: Update resizeWindowToIdealContentHeight(_:) to clamp the
computed target frame dimensions against window.contentMinSize before calling
setFrame(_:display:), preserving the intended minimum 480x320 floor while still
respecting the visible screen frame and existing positioning behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 4177bb72-7e2f-4cfb-9ef0-c5dbbbc3761a

📥 Commits

Reviewing files that changed from the base of the PR and between fbf1e82 and 67032c3.

📒 Files selected for processing (10)
  • Packages/iOS/CmuxMobileShell/Sources/CmuxMobileShell/MobileShellComposite+HiddenMacs.swift
  • Packages/iOS/CmuxMobileShell/Tests/CmuxMobileShellTests/MobileShellCompositeHideMacTests.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/DeviceTreeView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/DisconnectedWorkspaceShellView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/MobileSettingsView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceShellView.swift
  • Sources/Mobile/Pairing/MobilePairingView.swift
  • Sources/Mobile/Pairing/MobilePairingWindowController.swift
  • ios/cmux/Resources/Localizable.xcstrings
💤 Files with no reviewable changes (3)
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/DisconnectedWorkspaceShellView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceListView.swift
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/WorkspaceShellView.swift

Comment thread Sources/Mobile/Pairing/MobilePairingWindowController.swift
Centered red text with no icon or card background, so the rare
whole-phone action stops competing with the computer rows.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/DeviceTreeView.swift (1)

108-116: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Serialize and own the “Forget All Computers” path.

Task { await store.forgetAllComputers() } starts durable disconnect/hide work without retention or cancellation, and the .task refresh can queue another paired-Mac write while that work is in progress. Move the whole sequence into the store’s serialization boundary (or retain/cancel a store-owned operation) to avoid interleaving forgetAllComputers() with store reloads or reconnect writes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/DeviceTreeView.swift`
around lines 108 - 116, Update the “Forget All Computers” action in
DeviceTreeView so the operation is owned and serialized by the store rather than
launching an unretained Task. Route forgetAllComputers() through the store’s
existing serialization boundary, coordinating reload and reconnect writes so
they cannot interleave while the forget operation is running.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In
`@Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/DeviceTreeView.swift`:
- Around line 108-116: Update the “Forget All Computers” action in
DeviceTreeView so the operation is owned and serialized by the store rather than
launching an unretained Task. Route forgetAllComputers() through the store’s
existing serialization boundary, coordinating reload and reconnect writes so
they cannot interleave while the forget operation is running.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 87fee436-45d5-40f9-92ac-7fc3755c4fb3

📥 Commits

Reviewing files that changed from the base of the PR and between 67032c3 and 979acd5.

📒 Files selected for processing (1)
  • Packages/iOS/CmuxMobileShellUI/Sources/CmuxMobileShellUI/DeviceTreeView.swift

azooz2003-bit and others added 3 commits July 24, 2026 19:02
Per-computer hide on the Computers sheet rows remains the way to drop
a Mac; the whole-phone destructive action, its confirmation dialog,
forgetAllComputers(), its test, and its strings are removed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
setFrame(_:display:) bypasses contentMinSize, so a short in-flight
content measurement (the loading spinner) could shrink the window below
the 480x320 floor.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 25, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@azooz2003-bit
azooz2003-bit merged commit 4d7144e into main Jul 25, 2026
14 checks passed
@azooz2003-bit
azooz2003-bit deleted the feat-qr-demote branch July 25, 2026 03:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant