Join the waitlist
Sections

In private development · Native Android and iOS

Catch what only breaks on a phone.

KugCatch is the AI code reviewer being built for native Android and iOS apps. Join the waitlist and confirm your address for one email when it opens.

Kotlin · Jetpack Compose · Swift · SwiftUI · UIKit · in GitHub, when it opens

  • Reads your PRs
  • Stays quiet
  • Glows on the bug

acme/rides-androidAndroid

  1. #2141Bump Compose BOM to 2026.10No comment
  2. #2142Copy fixes on the receiptNo comment
  3. #2143Dark-mode tokens for map pinsNo comment
  4. #2144Search rides by destinationCaught

kugcatchbotcommented on SearchScreen.kt

14var query by remember { mutableStateOf("") }

  1. query lives in remember, so rotating the phone wipes it.
  2. Riders lose their destination mid-typing, and again after process death.
  3. Use rememberSaveable { mutableStateOf("") }.

Nothing to say yet.

Kug stays dark while a pull request is fine. Most of them get no comment at all.

acme/rides-iosiOS

  1. #877Update SwiftLint rulesNo comment
  2. #878Localize the receipt footerNo comment
  3. #879Snapshot tests for MapPinNo comment
  4. #880Show the driver's photoCaught

kugcatchbotcommented on DriverCard.swift

22self.photo = UIImage(data: data!)

  1. data! is nil when the request fails: airplane mode, a tunnel, a dropped cell.
  2. The ride screen crashes for anyone who loses signal.
  3. Use guard let data, let image = UIImage(data: data) else { return }.

Nothing to say yet.

Kug stays dark while a pull request is fine. Most of them get no comment at all.

#2144 breaks on a device: rotation and memory. Kug glows: one comment, three lines.

Fictional pull requests in a fictional repository: an illustration of what KugCatch is being built to catch when it opens, not a recorded review.

Why native

Your code is reviewed in a diff. It runs in a pocket.

Phones rotate, sleep, lose signal and kill apps to save memory. The bugs that live there rarely show up as a wrong line in a diff.

  • It rotates.

    State wiped by a configuration change

  • It goes to the background.

    Work that never stops, or never resumes

  • It loses signal.

    Force-unwraps that crash offline

  • It runs out of memory.

    Process death erases the screen

  • It says “Don't allow.”

    The camera call that crashes anyway

  • It runs an older OS.

    APIs that don't exist on that device yet

The journey

From install to the first catch.

How it will work when KugCatch opens.

  1. 1. Install the GitHub App

    Pick the repositories Kug may read.

  2. 2. Open a pull request

    Same workflow. Nothing new to learn.

  3. 3. Kug reviews it with the phone in mind

    Lifecycles, threads, memory, signal.

  4. 4. Three lines, or silence

    It speaks only when something will break.

Inside a catch

Native on both sides.

Coroutines and Compose on Android. Concurrency and memory on iOS. Four fictional bugs KugCatch is being built to catch when it opens.

Android · Kotlin

Background collect

A Flow keeps collecting after its screen is gone, and the phone pays for it.

1. Reads the diff

LocationFragment.kt

override fun onViewCreated(view: View, state: Bundle?) { lifecycleScope.launch { viewModel.location.collect { loc -> binding.map.moveTo(loc) } }}

2. Pictures the device moment

The app goes to the background

  1. onStop() · nothing cancels the coroutine
  2. location.collect { } still running
  3. GPS stays on for a map nobody sees

3. Writes three lines

kugcatchboton LocationFragment.kt

2lifecycleScope.launch {

  1. lifecycleScope belongs to the Fragment, so this collect outlives its view.
  2. In the background the app keeps burning GPS, and binding can crash after onDestroyView.
  3. Collect inside viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) { … }.

Android · Kotlin

Leaked screen

A ViewModel holds on to the Activity that created it, so the first screen outlives a rotation.

1. Reads the diff

RideViewModel.kt

class RideViewModel( private val activity: Activity, private val rides: RideRepository,) : ViewModel() { fun share() = activity.startActivity(shareIntent())}

2. Pictures the device moment

The phone rotates

  1. RideActivity #1 destroyed · #2 created
  2. RideViewModel → still holds #1
  3. Heap: the destroyed RideActivity #1 retained

3. Writes three lines

kugcatchboton RideViewModel.kt

2private val activity: Activity,

  1. RideViewModel keeps the Activity that created it.
  2. After a rotation the destroyed first screen and its views stay in memory, and share() starts from a dead screen.
  3. Drop the Activity: emit a share event the screen handles.

iOS · Swift

Off the main thread

A network callback touches UIKit from a background queue.

1. Reads the diff

RidesViewController.swift

URLSession.shared.dataTask(with: url) { data, _, _ in self.rides = decode(data) self.tableView.reloadData()}.resume()

2. Pictures the device moment

The response lands on a background queue

  1. Thread 7 · URLSession delegate queue
  2. tableView.reloadData()
  3. Main Thread Checker: UI API on a background thread

3. Writes three lines

kugcatchboton RidesViewController.swift

3self.tableView.reloadData()

  1. reloadData() runs on URLSession’s background queue.
  2. UIKit off the main thread means frozen lists and crashes nobody can reproduce.
  3. Wrap the UI work in DispatchQueue.main.async { … }, or make the method @MainActor.

iOS · Swift

Retain cycle

A repeating timer and its screen keep each other alive forever.

1. Reads the diff

RideViewController.swift

override func viewDidLoad() { super.viewDidLoad() timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true) { _ in self.updateETA() }}

2. Pictures the device moment

The rider closes the ride screen

  1. popViewController(animated: true)
  2. RideViewController.deinit · never called
  3. Timer fires every second, forever

3. Writes three lines

kugcatchboton RideViewController.swift

4self.updateETA()

  1. The repeating timer captures self strongly, so this screen never deallocates.
  2. Every ride a user opens keeps ticking in memory and draining battery.
  3. Capture [weak self] and invalidate the timer in viewWillDisappear.

Fictional examples of what KugCatch is being built to catch when it opens. The code, device sequences and comments are illustrations, not recorded reviews or device runs.

The three-line rule

Speaks rarely. Says it in three lines.

Most pull requests get no comment. When Kug lights up, you get one comment: what breaks and where, who feels it, and the fix.

  • No walls of nitpicks
  • No style lectures
  • Never pushes to your branch

14var query by remember { mutableStateOf("") }

What and where
query lives in remember, so rotating the phone wipes it.
Who feels it
Riders lose their destination mid-typing, and again after process death.
The fix
Use rememberSaveable { mutableStateOf("") }.
Fictional comment on SearchScreen.kt.

KMP

Sharing code with KMP? Kug follows it across.

From commonMain to each actual and the Swift that calls it. One review across the boundary, beside the native Android and iOS review KugCatch is being built for.

commonMain expect fun nowMillis(): LongandroidMain System.currentTimeMillis() millisecondsiosMain NSDate().timeIntervalSince1970 secondsSwift session.isExpired(now: Clock.nowMillis())
Fictional KMP example: iOS returns seconds where the shared contract promises milliseconds, so sessions never look expired.
On iOS, an expired session still looks valid.commonMain clock contract → androidMain / iosMain actual

Fictional KMP example. Synthetic source and illustrative comment. No recorded product run.

kugcatch [bot] commented on Clock.ios.kt

  1. actual fun nowMillis() in iosMain returns seconds.
  2. For the shown millisecond expiry, shouldRefresh stays false and the caller sends an expired token.
  3. Use (NSDate().timeIntervalSince1970 * 1000).toLong() for Android’s millisecond contract.
Where the contract crosses the boundary
  1. Shared · commonMain

    expect fun nowMillis() promises Unix-epoch milliseconds to shouldRefresh.

  2. Platform · iosMain actual

    Foundation's seconds are truncated to a Long without converting the unit; the androidMain actual returns milliseconds.

    The contract breaks here.

Expected contract
nowMillis and expiresAtMillis use Unix-epoch milliseconds. The shared comparison decides whether to refresh.
Faulty behavior
Android returns milliseconds. iOS truncates Foundation’s seconds to a Long without converting the unit.
App consequence
At 1,700,000,001.25 seconds, the fictional expiry of 1,700,000,000,000 milliseconds is past. iOS returns 1,700,000,001: shouldRefresh is false, so the caller sends the expired token. Android returns 1,700,000,001,250 and refreshes.
Correction
Multiply seconds by 1000 before toLong(). iOS then returns 1,700,000,001,250 milliseconds: shouldRefresh is true for this fixture.
Fictional source · faulty boundary
// Kotlin stdlib 2.4 · commonMain/Clock.kt
/** Milliseconds since the Unix epoch. */
expect fun nowMillis(): Long
fun shouldRefresh(expiresAtMillis: Long): Boolean =
    nowMillis() >= expiresAtMillis
// Caller: refresh if true; otherwise send the token.

// androidMain/Clock.android.kt · JVM platform API
actual fun nowMillis(): Long = System.currentTimeMillis()

// iosMain/Clock.ios.kt · Foundation platform API
import platform.Foundation.NSDate
actual fun nowMillis(): Long =
    NSDate().timeIntervalSince1970.toLong()
Suggested correction
// iosMain/Clock.ios.kt · Kotlin 2.4 / Foundation
actual fun nowMillis(): Long =
    (NSDate().timeIntervalSince1970 * 1000).toLong()

Assumptions: nonzero epoch-millisecond expiry; this comparison chooses refresh versus send; a wall clock, not monotonic duration timing. The arithmetic applies to this fixture, not every expiry.

Link to this example
An offline refresh exception terminates the iOS app.commonMain → Objective-C framework → Swift

Fictional KMP example. Synthetic source and illustrative comment. No recorded product run.

kugcatch [bot] commented on SessionRepository.kt

  1. refreshToken() can throw the shared RefreshFailedException.
  2. If it escapes to Swift without @Throws, the iOS app terminates.
  3. List it and CancellationException in @Throws, or return a result.
Where the contract crosses the boundary
  1. Shared · commonMain

    The suspend refreshToken() throws RefreshFailedException when offline.

  2. Platform · Objective-C framework export

    Without @Throws, only CancellationException reaches the Error completion.

    The contract breaks here.

  3. Swift · iOS app

    Swift never receives an error: the undeclared exception terminates the app.

Expected contract
A failed refresh should reach Swift as a handleable error, allowing a retry.
Faulty behavior
RefreshFailedException escapes the exported suspend function without an @Throws declaration.
App consequence
The completion has an Error parameter, but this undeclared exception is unhandled and terminates the app.
Correction
List RefreshFailedException and CancellationException in @Throws. Listed types and their subclasses bridge as errors; other escaping exceptions still terminate. A shared result is an alternative.
Fictional source · faulty boundary
// Kotlin stdlib 2.4 · commonMain
class RefreshFailedException : Exception("Offline")

class SessionRepository {
    suspend fun refreshToken(offline: Boolean): String {
        if (offline) throw RefreshFailedException()
        return "fictional-refreshed-value"
    }
}
Suggested correction
// Kotlin stdlib 2.4 · commonMain
import kotlin.coroutines.cancellation.CancellationException

// On SessionRepository.refreshToken:
@Throws(RefreshFailedException::class, CancellationException::class)
suspend fun refreshToken(offline: Boolean): String {
    if (offline) throw RefreshFailedException()
    return "fictional-refreshed-value"
}

Kotlin 2.4 Objective-C framework export: suspend functions always export an Error completion parameter. Without @Throws, only CancellationException is bridged. RefreshFailedException is defined in common code; the offline fixture needs no networking library.

Link to this example
A locked session falls into Swift's signed-out screen.commonMain sealed class → Objective-C framework → Swift screen selection

Fictional KMP example. Synthetic source and illustrative comment. No recorded product run.

kugcatch [bot] commented on SessionState.kt

  1. SessionState.Locked is new in commonMain, and Swift receives it through Objective-C as a class hierarchy.
  2. The switch in SessionView.swift falls into default, so a locked user lands on the signed-out screen.
  3. Handle Locked explicitly in that switch before default.
Where the contract crosses the boundary
  1. Shared · commonMain

    The sealed class SessionState gains a Locked subclass.

  2. Platform · Objective-C framework export

    Swift receives a class hierarchy, not an exhaustive native Swift enum.

  3. Swift · SessionView.swift

    The switch handles SignedIn only, so Locked falls into default.

    The contract breaks here.

Expected contract
Locked should select the locked-session screen; SignedOut should select sign-in.
Faulty behavior
Swift receives a class hierarchy. The consumer handles SignedIn and routes everything else, including the new Locked subclass, to signed-out.
App consequence
SessionState.Locked() reaches default and returns signed-out. The app shows sign-in instead of explaining the lock.
Correction
Handle Locked, SignedIn and SignedOut explicitly. Use an unavailable fallback for an unexpected state.
Fictional source · faulty boundary
// Kotlin 2.4 · commonMain/SessionState.kt
sealed class SessionState {
    class SignedIn : SessionState()
    class SignedOut : SessionState()
    class Locked : SessionState()
}

// SessionView.swift · imports the Objective-C framework
func screen(for state: SessionState) -> String {
    switch state {
    case is SessionState.SignedIn: return "account"
    default: return "signed-out"
    }
}
Suggested correction
// SessionView.swift · same framework export
func screen(for state: SessionState) -> String {
    switch state {
    case is SessionState.SignedIn: return "account"
    case is SessionState.SignedOut: return "signed-out"
    case is SessionState.Locked: return "locked-session"
    default: return "unavailable"
    }
}

Kotlin 2.4 Objective-C framework export, public nested classes, no collisions or @ObjCName overrides. Swift uses SessionState.SignedIn, SessionState.SignedOut and SessionState.Locked: classes, not an exhaustive native Swift enum. Direct Swift export, SKIE or a custom Swift wrapper may differ; inspect the generated header.

Link to this example

FAQ

Questions, answered.

When can I use KugCatch?

KugCatch is in private development. Join the waitlist and confirm your address, and we will send you one email when it opens. Joining does not grant product access.

Which platforms will it review?

KugCatch is being built for native Android (Kotlin, Jetpack Compose, Views) and native iOS (Swift, SwiftUI, UIKit), and reviews them when it opens. Kotlin Multiplatform shared code is released review scope. Flutter and React Native are not supported.

Will it flood my pull requests?

No. Most pull requests get no comment at all. When Kug finds something that breaks on a device, you get one comment in three lines.

Does it replace human review?

No. Kug looks for the problems that show up on a phone, so your reviewers can spend their time on design and intent. A quiet review is not a guarantee that a change is correct.

What does it read?

Only the repositories you select when you install the GitHub App. A review reads the pull request and the code around it, and KugCatch keeps metadata about your project rather than a copy of your code. Read the privacy notice

How much will it cost?

Prices are not published yet. Joining the waitlist is free and commits you to nothing. Read the commercial notice

Be the first to catch it.

Join the waitlist. We will ask you to confirm your address, then send one email when KugCatch opens, and nothing else.

Request one launch notification. We first send a confirmation email to check the address is yours. Read the privacy notice, including browser storage, and commercial notice before submitting.

Your launch notification request

The form needs JavaScript to submit safely. If it does not become available, no request will be sent.

  1. Join the waitlistTen seconds. Just an email.
  2. Confirm your email, get one launch emailNo newsletter. No drip campaign.
  3. Install on GitHub when it opensPick repositories, open a pull request, meet Kug.

Prelaunch notices.

Privacy notice

Controller and contact

The controller is Javier Gutiérrez Bravo, operating under the product name KugCatch. For privacy questions, withdrawal or rights requests, contact support@kugcatch.com. The postal address is given in the operator information (see Commercial notice, Operator).

Scope

Last updated: 31 October 2026. This notice applies when published on the KugCatch prelaunch website.

This notice covers the isolated prelaunch website and correspondence asking questions, the email form for requesting one launch notification, and the handling of that request. The page does not create a product account, connect a GitHub repository, review code or accept payments. The future service will have separate information before those activities begin.

Data

When you submit the form, we receive your email address, your explicit consent to one launch notification, the version of the notice shown, and request and expiry timestamps. We also use a protected email-matching value to avoid duplicate records, a technical request reference to handle retries safely, and for an unconfirmed request a protected form of the confirmation link and its sending status. The email address is stored encrypted in a separate waitlist database; the support mailbox is not that database. Providing an address and consent is voluntary; without them we cannot accept a notification request. Please submit only an address you control.

The page acknowledges receipt only after the form service has durably processed the request. The same receipt is shown for a new request, a duplicate or a successful retry; it does not reveal whether an address is recorded or reinstate a withdrawn request. Receipt does not verify mailbox ownership or mean that the launch notification has been sent. A new request triggers one confirmation email containing a personal link. Your request is complete only after you open that link and press the button. We cannot guarantee delivery, and because we retry when a sending result is unknown you may rarely receive the same link more than once. Submission does not trigger a recurring campaign.

If you email support, we receive your email address, any sender name, message content, mail headers and the correspondence necessary to handle your inquiry, withdrawal or rights request. An ordinary support question is not a launch notification request. Opening the support email link does not send a message; you choose whether to send it using your own provider. Please do not send source code, diffs, credentials, identity documents or personal information that is unnecessary for your request.

Hosting and network services process technical request information to deliver and protect the page, including IP addresses, requested resources, timestamps and browser or protocol information. Static delivery does not mean that no personal information is processed. We do not use this information to create visitor profiles or populate the waitlist. The waitlist database does not store IP addresses or browser identifiers for admission control.

The page's theme preference is stored on your device. The cookie and storage notice (see Privacy notice, Cookies and browser storage) explains its purpose, duration and controls. The isolated page has no advertising, analytics, checkout or authentication integration.

Cookies and browser storage

Last updated: 20 October 2026. This notice applies when published on the KugCatch prelaunch website.

This notice explains browser storage used by the isolated prelaunch page. The operator and contact details are in the legal notice (see Commercial notice, Operator), and the privacy notice (see Privacy notice) explains website, form-request and support-email data.

If you choose a light or dark theme, the page stores that choice in your browser's local storage using the key kugcatch-theme. It contains the theme choice, not your email address or an account identifier. The page reads it on later visits so that it can display your selected theme.

This preference is used only for the presentation you request. It is not sent as a waitlist record or used for advertising, analytics, profiling or tracking across websites. Local storage has no automatic expiry here: the preference remains in that browser until you change it or clear the site's stored data.

This user-selected preference is treated as storage necessary to provide the presentation function you request under Article 22.2 of the LSSI. The isolated page does not use advertising, analytics, social-media tracking or authentication cookies. Choosing a theme does not consent to any other processing.

You can change the theme using the page's theme control. You can remove the saved choice through your browser's settings for this site's stored data or block local storage in the browser. Blocking or removing it can prevent the page from remembering your choice, but does not prevent reading the page or submitting the form or sending a support email.

The form does not store your email address, consent or request history in cookies or local storage. Its current input and retry reference are temporary page state; leaving or reloading the page does not create a browser-stored waitlist record. The saved request is held by the form service as described in the privacy notice. Submitting the form does not set an authentication cookie.

The page serves its fonts and images from its own origin and does not embed third-party tracking widgets. Opening an external status link or using your own email provider takes you to services with their own privacy and storage arrangements.

Before introducing a different storage purpose or non-exempt technology, we will update this notice and obtain consent where required. No consent for future analytics or advertising is inferred from visiting this page, choosing a theme or requesting a launch notification.

For questions, contact support@kugcatch.com.

Purposes and lawful bases

Requested launch notification: your consent under GDPR Article 6(1)(a). We record your explicit request to contact you once about launch, and to send one confirmation email first. Any later contact or launch notification is subject to the necessary verification of the request and operational checks before sending. An ordinary question is not marketing consent. You may withdraw at any time by emailing support@kugcatch.com or replying to our correspondence. Withdrawal does not affect earlier lawful processing. We do not enroll you in recurring newsletters or use the request for unrelated marketing.

Questions: our legitimate interest under Article 6(1)(f) in answering voluntary inquiries about the project. We limit the correspondence to what is necessary to understand and answer your question.

Website delivery and security: our legitimate interest under Article 6(1)(f) in making the page available and preventing abuse, using proportionate technical processing.

Data-protection requests: compliance with our obligations under GDPR Articles 12–22, on the basis of Article 6(1)(c).

There is no profiling or solely automated decision-making producing legal or similarly significant effects for this waitlist. Requesting a notification does not grant product access or authorize later product processing.

Recipients and international transfers

The waitlist runs on Cloudflare. Cloudflare serves this page and runs the email-form service, which stores requests encrypted in a separate Cloudflare D1 database created in Cloudflare's European Union jurisdiction. The form service and its database do not use the product account or repository database. The form service handles the address you submit, and Cloudflare's network processes the technical information necessary for delivery and security, at whichever Cloudflare location serves you; only the stored requests are kept in the European Union jurisdiction, so EU-only processing is not promised.

Support email passes through Cloudflare Email Routing into an owner-managed personal Gmail mailbox, rather than a Google Workspace mailbox. Replies use Gmail and Cloudflare Email Sending SMTP as support@kugcatch.com. These services process correspondence and delivery information; a form submission is not forwarded into the support mailbox. We do not sell the waitlist or disclose it to advertisers.

The personal Gmail service is governed by Google's own terms and privacy policy. Google states that it does not act as a data processor or offer a data processing agreement for consumer Gmail. We do not claim that Google Workspace processor terms apply to this mailbox.

Cloudflare Email Service sends the confirmation email and processes your address and the message to do so. This sending is not limited to the European Union. Cloudflare may use automated tools to scan the content of these emails. Cloudflare keeps delivery records including your address, the sender, the subject and the delivery result; Cloudflare's documentation says these sending event records can be queried, and are retained, for the past 31 days, and does not state whether other copies are kept longer. If a message to your address bounces or is reported as spam, Cloudflare can add your address to a list that blocks further sending to it. Some entries on that list do not expire, and some cannot be removed by us. Contact support@kugcatch.com to ask about removal.

Google and Cloudflare operate internationally, so processing can take place outside the European Economic Area, including in the United States. Their published transfer information describes adequacy arrangements, including the EU–US Data Privacy Framework for covered transfers, and Standard Contractual Clauses for relevant transfers. The applicable arrangement depends on the service, recipient and destination; this notice does not promise EU-only processing or that one mechanism covers every onward transfer.

The providers publish further information about their processing, safeguards and retention in the Google privacy information (https://policies.google.com/privacy?hl=en), Google transfer information (https://policies.google.com/privacy/frameworks?hl=en), Cloudflare privacy policy (https://www.cloudflare.com/privacypolicy/) and Cloudflare D1 data location (https://developers.cloudflare.com/d1/configuration/data-location/). You may also contact support@kugcatch.com for information about the recipients and safeguards relevant to your correspondence, including how to obtain a copy of applicable safeguards.

Your email provider processes the messages you choose to send and any confirmation email it receives for you. The service-status link opens a separate GitHub-hosted website, whose privacy information applies to its processing. Neither action connects a repository to KugCatch.

Retention

Unconfirmed requests: the confirmation link stops working 7 days after the request, and the record and link are purged within a day after that, or within two days if automatic deletion fails. If you submit the form again after that, we queue a new confirmation email. Deleted records may remain in the database provider's recovery history for up to 30 days.

Launch-notification requests: a maximum of 12 months from the request, with earlier deletion after sending the requested launch notification or receiving your withdrawal. Delaying launch does not restart the period. Duplicate submissions and retries do not extend the original deadline. This applies to the database record, its matching value and related copies under our control. Records expire 330 days after the request once confirmed and are purged within a day, or within two days if automatic deletion fails. Deleted records may remain in the database provider's recovery history for up to 30 days, which cannot be switched off; this stays within the original 12-month maximum. That history is excluded from active use and is not restored while it could bring back withdrawn, notified or expired requests. Any notification-related correspondence under our control, including Sent and Trash, follows this same limit. We do not keep our own indefinite subscriber or suppression list. Cloudflare's delivery records and sending block list, described under Recipients, follow Cloudflare's own handling and may last longer than the limits in this section.

Other questions: only while needed to answer and manage the exchange, with a maximum of 12 months after the last substantive exchange. A question does not extend the period for a separate notification request.

Rights requests: necessary correspondence while the request is being handled and for up to 12 months after closure to address follow-up and demonstrate how it was handled. We do not retain unnecessary identification material.

Cloudflare-managed technical samples: Cloudflare makes sampled HTTP request metadata available through its dashboard, including IP addresses, requested resources and timestamps. These provider-managed samples follow Cloudflare's service settings, with documented retention of at least 31 days. This period is separate from the limits below for copies we create. We do not export these samples for routine use or use them to populate the waitlist or build visitor profiles. Any copies we create for a specific security investigation follow the incident-extract limit below.

Access or security records under our control: at most 30 days for routine records. If a record is necessary to investigate a specific security incident, the relevant extract is restricted to that investigation and deleted within 90 days after the incident is closed.

Deleting support-mailbox content is different from erasure across a provider's service, security records and backups. Provider-managed residual copies follow the provider's applicable deletion and retention processes; we do not promise immediate provider-wide erasure. Google describes its general deletion and backup processes in its retention information (https://policies.google.com/technologies/retention?hl=en). The periods above are our handling limits, not a claim that we control every provider backup.

Your rights

You can request access, correction, erasure, restriction and, where applicable, portability. You may object to processing based on legitimate interests on grounds relating to your situation, and object to direct marketing at any time. You may withdraw notification consent at any time. Contact support@kugcatch.com for any of these requests, including removal of a form submission. We handle these requests through support; the page does not provide a public address lookup or self-service deletion link. There is no charge for withdrawing your request.

We respond without undue delay and ordinarily within one month. Where the GDPR permits an extension because of complexity or the number of requests, we will explain the extension within that first month. If there is reasonable doubt about identity, we ask only for the additional information necessary to verify it; a copy of an identity document is not routinely required.

You may complain to a competent supervisory authority, including where you live or work or where an alleged infringement occurred. In Spain, this is the Spanish Data Protection Agency (https://www.aepd.es/).

Changes to this notice

We will update this notice if prelaunch processing changes and provide further information or obtain new consent when required. Your launch-notification request does not authorize new marketing purposes, purchases or the future service's processing.

Commercial notice

Operator

KugCatch is operated by Javier Gutiérrez Bravo as an individual.

Postal address: Calle Sabia Urganda 1 P3 2C, 28906 Getafe, Madrid, Spain.

Contact for product questions, notification requests and privacy matters: support@kugcatch.com.

KugCatch is a product name. It does not identify an incorporated company.

Service

Last updated: 31 October 2026. This notice applies when published on the KugCatch prelaunch website.

KugCatch is being prepared as a GitHub App for AI-assisted code review for mobile app development, including shared and platform boundaries. The intended service reviews pull requests in GitHub.

This website introduces the project before public onboarding. It does not offer an active review service, connect repositories, create product accounts or promise availability of a particular platform pack or feature.

Launch notification requests

Use the email form to request one launch notification, with your explicit consent. Use an address you control. The page acknowledges receipt only after the form service has durably processed the request. New requests, duplicates and successful retries receive the same acknowledgement; it does not disclose whether an address is recorded or reinstate a withdrawn request. A duplicate or retry does not renew the original retention deadline.

Receipt does not verify mailbox ownership or mean that the launch notification has been sent. A new request triggers one confirmation email containing a personal link, and your request is complete only after you open that link and press the button. Delivery is not guaranteed. The form does not enroll you in a recurring newsletter. Any later contact or launch notification requires the necessary verification and operational checks before sending.

You can ask a question by emailing support@kugcatch.com. The support email link opens your email application and does not send a message automatically. A support question alone does not register a form request or subscribe you to launch marketing.

A notification request is free. It does not create a paid subscription, reserve a price, guarantee launch or a launch date, give product access, connect a repository or authorize code review. Asking a question does not subscribe you to launch marketing.

You may withdraw at any time by emailing or replying to support@kugcatch.com. The privacy notice (see Privacy notice) explains the data used, the maximum notification-request period and your rights. The cookie and storage notice (see Privacy notice, Cookies and browser storage) explains the local theme preference.

Purchases

This page offers no purchase, preorder, card collection, subscription renewal or review-credit sale. We take no payment through the prelaunch page, and there is no paid order to deliver, renew, cancel or refund here. Withdrawing a launch notification request is separate from cancelling any future product subscription.

Before a purchase becomes available, its applicable terms will identify the seller and explain the service scope and availability, prices and currency, taxes, payment arrangements, delivery and access, duration, renewal, cancellation, refunds and any statutory withdrawal rights. A launch email does not itself make or accept a purchase.

Consumer rights

Use the website and support address lawfully. Do not send source code, diffs, credentials, repository access or personal information unnecessary for your request. Do not use the contact address to submit material you are not entitled to disclose.

Website materials remain subject to the rights of their respective owners. Viewing the page does not grant a product licence, repository permission or rights beyond those allowed by applicable law.

We aim to keep the information accurate, but prelaunch plans can change. No launch date, access priority or future commercial offer is guaranteed. We will provide the applicable information before asking you to enter a paid agreement.

Nothing in this notice excludes mandatory consumer or data-protection rights, or limits any liability that cannot lawfully be limited. No exclusive forum, arbitration agreement or waiver of statutory rights is imposed by visiting the prelaunch page.

Contact and complaints

Sending email uses your email application and provider. The service-status link opens a separate GitHub-hosted website. Their applicable terms and privacy information govern their own processing. Following these links does not subscribe you, connect a repository or authorize payment.

For questions or to withdraw a notification request, contact support@kugcatch.com. We will update the published information when the prelaunch arrangements change. Separate notices and purchase terms will be provided before product onboarding or sales begin.

Back to the waitlist