Skip to main content

bugstweet 0.9.7 copy "bugstweet: ^0.9.7" to clipboard
bugstweet: ^0.9.7 copied to clipboard

[pending analysis]

Testers report bugs from inside your Flutter app as GitHub issues an AI coding agent can fix. Tester builds only: store builds never contain it.

bugsTweet #

Testers report bugs from inside your Flutter app, on the phone. They tap a button, mark the bug on the screenshot, and send. Each report arrives as a GitHub issue with everything a developer or an AI coding agent (Claude Code, Codex, Cursor and the like) needs to fix it.

  • No account, no server, no cost.
  • Your app's code is never changed.
  • Store builds never contain bugsTweet. Only tester builds do.

How it stays out of your app #

bugsTweet comes in two packages. You only ever add and type the first one.

  • bugstweet: the tool. You add it to your pubspec.yaml as a development package. It has no phone parts, and your app never uses its code, so nothing of it is packed into any build.
  • bugstweet_reporter: the button and the phone parts testers use. You never add it. The tool adds it to tester builds only.

How a tester build is made:

  1. Your app gets one small file, .bugstweet/tester.dart. The folder name starts with a dot, so your normal code checks and IDE skip it.
  2. dart run bugstweet build copies your app to a cache folder on your computer, adds bugstweet_reporter to that copy only, and builds the tester app from the copy.
  3. For a store build, you run flutter build as always. Your app does not list bugstweet_reporter, so none of it can be packed into the store app.

What is inside each build (checked on Android and iPhone builds):

Inside the app Store build Tester build
bugsTweet code (button, screens, sending) no yes
bugsTweet phone parts (screenshot and shake listeners) no yes
Android "detect screen capture" permission no yes
iPhone motion permission text no yes

Set up (once per app) #

You need Flutter 3.38 or later. In your app's folder:

  1. Add the tool as a development package:

    flutter pub add --dev bugstweet
    
  2. Create the tester file:

    dart run bugstweet init
    
  3. Try it on a phone or emulator:

    dart run bugstweet run
    

    It starts on the first phone, emulator or simulator it finds, and tells you how to open one if none is there. The app starts with a round bugsTweet button. Reports go out through the phone's share sheet until you connect GitHub (step 4).

  4. Send reports to GitHub as issues: create a reports repository and a key, as described in The GitHub key, then open .bugstweet/tester.dart and check the two repository names.

That is all. Apart from the one bugstweet line under dev_dependencies, your pubspec.yaml, lib/ folder and platform files stay as they were.

Make a tester build #

dart run bugstweet build apk --dart-define=BUGS_TWEET_GITHUB_TOKEN=github_pat_...
dart run bugstweet build ipa --dart-define=BUGS_TWEET_GITHUB_TOKEN=github_pat_...

You can build apk, appbundle, ipa or ios. Every option you would give flutter build works here too (flavors, build numbers, export options). Paths in options, such as --split-debug-info or --dart-define-from-file, are read from your app folder, as in a normal build. A signing key kept outside the app (for example storeFile=../../upload-keystore.jks in android/key.properties) is found as well.

Give tester builds their own build number, for example --build-number=9001. Otherwise a tester build has the same number as your store build, and one uploaded to TestFlight can take the number of a real release.

The finished tester build goes to build/bugstweet/, for example build/bugstweet/apk/app-release.apk. It is kept apart from store builds, which stay in their usual place. Give tester builds to testers only (for example TestFlight internal testing or Firebase App Distribution), never to a store.

The first tester build takes a few minutes longer, because the copy starts empty. Later builds reuse it.

What testers get #

  • Tap the bugsTweet button (the logo): the screen is saved, and a thumbnail waits in the corner for four seconds. Tap the thumbnail to mark it up right away, or swipe it away and keep testing.
  • Hold the button: a menu of choices: Tray, Report now, Long shot, Record 10 s, Timer 3 s, Element and Hide.
  • Timer 3 s: a 3, 2, 1 countdown, then a screenshot, so a menu or a pressed state can be captured.
  • Element: tap a card or button, then tap it again: a screenshot of just that part.
  • Long shot: tap the part of the screen that scrolls, or Whole screen, and bugsTweet scrolls it for you and joins the pictures into one tall capture.
  • Record 10 s: use the app while the button counts down; tap it to stop early. The clip, with every touch drawn as a red dot, becomes a report and plays in the GitHub issue. Only the app is recorded, so the phone asks for no permission, and private areas are covered as in screenshots.
  • Shake the phone: a screenshot, or the hidden button comes back.
  • Screenshot with the phone's own buttons: bugsTweet asks "Report this?". Works on iPhone and on Android 14 or later.
  • Marks: arrow, line, box, circle, pen, highlight, spotlight, magnify, blur, text, numbered steps, stamps (Wrong text, Misaligned, Too slow, Crash...). Tap an element with a shape tool and the shape snaps to it.
  • Design tools: Ruler (in points), Color (hex), Contrast (WCAG AA/AAA).
  • Tray: review, add notes, merge several screenshots of one problem, and send all at once. It also lists reported issues with their status (Open, In progress, Pending, Done); tap one to open it in the GitHub app.
  • Retest: every reported issue offers Retest. A card shows the way back to the bug (old screenshot, screen name, last steps); Capture compares the new screen with the old one on a before/after slider. Fixed closes the issue, Still broken reopens it.
  • Answer the agent: when a coding agent writes its plan (Actual, Expected, Fix) on an issue, the tray shows it as a card. Tap Go to agree, or Not quite and say what is different.
  • Copy for agents: copy one or several open reports as one message for a coding agent.
  • Recap: today's test session on one card, ready to share.
  • Voice notes: the keyboard's own dictation key. bugsTweet never handles audio.

Every report also carries, without any typing: the screen name, the taps before the bug, a filmstrip of the last 30 seconds, phone settings (text size, dark mode, language), phone model and system, app version, recent app errors, the file and line of each widget, a draft test that replays the taps, and a check for duplicate reports.

Where reports go #

  • GitHub (GitHubDelivery): one issue per report, labeled from-bugsTweet. Screenshots are stored on a bugs-tweet-media branch of the same repository and linked from the issue. Sending starts nothing else: you decide when to hand an issue to a coding agent.
  • Share sheet (ShareDelivery): the screenshot and report text go to any app the tester picks. Used by itself when no GitHub key is given.
  • Your own place: implement ReportDelivery.

The GitHub key, and why reports get their own repository #

The key is built into the tester app, so anyone who has the tester app can read it. Keep the damage small:

  1. Create a private repository that holds only reports, for example my-app-reports, with a README (GitHub cannot add the screenshots branch to an empty repository). Never point bugsTweet at your code repository.

  2. Create a fine-grained personal access token for that one reports repository only, with Issues: read and write and Contents: read and write, and a short expiry.

  3. Pass the key at build time, never in a file in git: --dart-define=BUGS_TWEET_GITHUB_TOKEN=github_pat_....

  4. Create the labels once in the reports repository:

    gh label create from-bugsTweet --color 0B7A6E
    gh label create "bugsTweet: in progress" --color 2FBFA9
    gh label create "bugsTweet: pending" --color F2B84B
    

When a test period ends, or a tester build reaches someone it should not, delete the key on GitHub. That build can then no longer send.

Optional: the relay (no GitHub key in the app) #

A small Cloudflare Worker that you deploy for free holds the GitHub key. The tester app holds only a send code, which can do nothing but bugsTweet's own calls in one reports repository. Setup steps: relay/README.md. In .bugstweet/tester.dart, use:

GitHubDelivery.relay(
  url: 'https://bugs-tweet-relay.<you>.workers.dev',
  sendCode: const String.fromEnvironment('BUGS_TWEET_SEND_CODE'),
  repo: 'me/my-app-reports',
  codeRepo: 'me/my-app',
)

Hosted: the bugsTweet service (no GitHub key, no relay) #

The bugsTweet service sends the reports for you. The tester app holds only a project key, which works for one reports repository and only for bugsTweet's own calls. The issues are written by bugsTweet[bot], and the labels are made for you.

  1. Create a private reports repository, with a README, as above.
  2. Open api.bugstweet.com, sign in with GitHub and install the bugsTweet app on that reports repository only.
  3. Click New project, pick the repository, and copy the key. It is shown once.
  4. Run dart run bugstweet init --hosted (or change .bugstweet/tester.dart to GitHubDelivery.hosted). It adds .bugstweet/key to .gitignore.
  5. Paste the key into .bugstweet/key (one line).
  6. Build as usual: dart run bugstweet build apk. bugstweet puts the key into the tester build; there is no key in the command.
GitHubDelivery.hosted(
  key: const String.fromEnvironment('BUGS_TWEET_KEY'),
  repo: 'me/my-app-reports',
  codeRepo: 'me/my-app',
)

If the key is lost or reaches someone it should not, click New key: the old key stops working at once, and the next build uses the new one.

The tester file #

dart run bugstweet init writes .bugstweet/tester.dart. It is plain Dart, so you can change it freely. Common settings in BugsTweetConfig:

  • delivery: where reports go (see above).
  • redact: cleans text before a report leaves the phone, for example redact: (text) => text.replaceAll(RegExp(r'[\w.+-]+@[\w-]+\.[\w.]+'), '[email]').
  • readFirst: which doc a coding agent should read first for a report.
  • autoBlurTextFields: blur every text field in screenshots (off by default; password fields are always blurred).
  • shakeToReport, screenshotToReport: turn those off.
  • reproTestApp, reproTestImport: let the draft test start your app.
  • appState: a few facts your app knows at the moment of a capture, so the agent does not have to guess, for example appState: () => {'signed in': auth.signedIn, 'cart items': cart.length}. Each value is sent as text, with redact applied.
  • askBeforeRecording: on by default in release and profile builds. The first time a tester build opens, a card asks the tester before small pictures of the last 30 seconds and the last 30 taps are kept; a switch in the tray changes the answer later. Set it to false only for your own builds.
  • logoColors: the colors of the bugsTweet logo, which is the capture button. Purple by default; BugsTweetLogoColors.teal, .blue or .coral, or seven colors of your own with BugsTweetLogoColors(face: ..., light: ..., shadow: ..., trim: ..., beak: ..., eyes: ..., shine: ...).
  • speedTest: on by default. When reports are sent, the phone downloads about 1 MB from Cloudflare's public speed test (speed.cloudflare.com) and each report says how fast it came. Set speedTest: false to skip it.

Every report also says the phone's condition when the picture was taken: network (Wi-Fi, mobile data, offline, VPN), the phone's own speed estimate (Android), battery level, charging and power saving, free storage and memory, and heat. None of it asks the tester for a permission.

To blur a part of the screen in every screenshot, wrap it in BugsTweetPrivate from the tester file, for example through a hook your app already has. Your store code never needs to import bugsTweet.

Before each tester build, bugsTweet writes .bugstweet/widget_map.g.dart into the copy, so reports name the file and line of each widget. It never appears in your app.

For the coding agent #

Each issue ends with the steps an agent follows: find the cause, write back Actual, Expected and the proposed fix, wait for the tester to agree, then fix, test, and say what is done and what is not. AGENT.md has the details, including how to fetch the screenshots.

Uninstall #

In your app's folder:

  1. Delete this app's tester copy from the cache folder:

    dart run bugstweet clean
    
  2. Remove the tool:

    flutter pub remove bugstweet
    
  3. Delete the .bugstweet folder.

There is nothing else to undo: bugsTweet never changed your code or your platform files. If you set up GitHub, you can also delete the reports repository and the key.

Limits #

  • Captures what Flutter draws. Platform views (maps, web views) show blank.
  • Widget names in reports come from class names, so --obfuscate builds lose them.
  • dart run bugstweet run starts the app from the copy, so hot reload does not see edits you make in your app while it runs. Stop and run again.

License #

MIT. See LICENSE.

0
likes
0
points
327
downloads

Publisher

unverified uploader

Weekly Downloads

Testers report bugs from inside your Flutter app as GitHub issues an AI coding agent can fix. Tester builds only: store builds never contain it.

Repository (GitHub)
View/report issues

License

(pending) (license)

Dependencies

yaml

More

Packages that depend on bugstweet