Nimlet

Privacy · Updated September 28, 2026

Your work stays yours.

What moves between your devices, what stays on them, and when another service is involved.

Publisher: Renyi Cao · Contact: support@nimlet.app
Applies to Nimlet iPhone and Mac beta 0.1.1 (18).

Nimlet does not relay control, images or audio through a developer server, require a Nimlet account, or include an analytics or crash-reporting service. Optional push notifications use a configured notification relay and Apple Push Notification service. Control messages, text, images and screen previews travel directly between your phone and your Mac.

Some supporting services can contact other machines: Apple's speech recognition fallback may process audio, speech language assets may be downloaded from Apple, and optional away access may query a public STUN server. The applications you send content to may also store or upload it under their own privacy policies. The sections below explain these boundaries.

Your voice

The primary speech path uses iOS 26's SpeechAnalyzer and SpeechTranscriber on the phone. Nimlet does not save voice recordings or send them to your Mac. Only the resulting text is sent to the Mac. iOS may download language assets to support on-device recognition.

Sound travels the other way when you switch listening on — see "Hearing your Mac" below. That stream pauses while you dictate; it never carries the phone's microphone to the Mac.

There is one exception, and it is real. When SpeechTranscriber is unavailable, Nimlet falls back to SFSpeechRecognizer and asks for on-device recognition (requiresOnDeviceRecognition) whenever the device reports that it supports it for your locale. On a device that does not support on-device recognition for that locale, the fallback runs as a server request, which means the audio goes to Apple. Permission and setup text disclose this possible fallback, but Nimlet does not show a per-recording indicator of whether Apple is processing it. If you require strictly on-device processing, use typed input instead of dictation until that recognition path can be confirmed for your device and language.

Hearing your Mac

Tapping the headphones on the phone asks the Mac to send its audio, and this is the only thing in Nimlet that carries sound over the network. What it is, exactly:

It is the whole output mix, not one app. ScreenCaptureKit is asked for the display's audio, which is everything your Mac is playing — a call, a video, a notification chime, all of it together. It is not possible to hear one app and not another, and Nimlet does not try to filter: a mix you cannot reason about would be worse than one you can.

Your Mac's own microphone is never part of it. The capture is of what is being played, not of the room. Nimlet never asks for microphone access on the Mac and could not record the room if it wanted to. But the people on a call are being played through your speakers, and so are their voices — which is the real reason to think about who is holding the phone.

Nothing is captured while nobody is listening. The capture starts when a phone switches listening on and stops when the last one switches it off or disconnects. Off is the default, on every phone, every time the app starts.

It uses the Screen Recording grant, because that is what ScreenCaptureKit is. macOS therefore shows its screen-recording indicator while a phone is listening — the same indicator as the window mirror, for the same reason. Nimlet asks the stream for two pixels of picture and throws them away; only the audio is sent. If you would rather the Mac never offer this at all, Let phones listen in the menu bar turns it off, and a phone that asks anyway is told so rather than left with silence.

It is not recorded. The audio is encoded as AAC, sent over the same TLS connection as everything else, played on the phone and discarded. Neither end writes it to disk, and there is no buffer to scroll back through.

It plays with the app in the background. This is the one feature that does — the whole point is that you are not at the desk — so the iOS app declares the audio background mode and registers as what's playing, which is what puts a pause button on your lock screen. Nothing else about Nimlet runs off screen.

Being reachable from away

Switching on Reachable on cellular in the menu bar changes two things worth knowing about, and nothing else.

Your Mac asks your router for a way in. Those requests — PCP, NAT-PMP and UPnP — go to your own router on your own network. They say "please forward TCP port 61423 to this Mac", they are the same requests a games console or a BitTorrent client makes, and they leave nothing behind: the mapping is a lease that expires within the hour, and Nimlet deletes it when you switch away access off.

Your Mac may ask a STUN server what its public address is. This happens only while away access is on, when your router would not tell Nimlet the answer itself. Each request contains a STUN header and twelve random bytes. Nimlet may try another configured server if a request fails. It sends no device name, hostname, persistent identifier or work content in that request. The server does see your public IP address and replies with the address it saw the packet come from, which it learned by receiving the packet, which is true of every packet that leaves your house.

The default servers are Cloudflare's and Google's public STUN endpoints. If you would rather they were neither:

defaults write com.renyicao.mice.host mice.stunServers -array "stun.example.com:3478"
defaults write com.renyicao.mice.host mice.stunServers -array   # or none at all

With none at all, away access still works on any router that reports its own external address, which is most of them.

What does not happen: your Mac's address is not published anywhere. It is sent to your own phones, over the connection they already have, and stored on them. There is no directory, no rendezvous server and nothing to look Nimlet up in.

Your text

Dictated and typed text travels from the phone to the Mac over TLS, keyed by the pairing code on the LAN or a per-device key for away access. Nimlet does not write delivered text to its persistent delivery log. The selected application or agent may store it, upload it, or write it to its own history.

Text for app and frontmost targets can pass through the macOS general pasteboard. Long text is delivered by putting it on the pasteboard and synthesising ⌘V, because typing it character by character is slow and some applications drop characters when synthesis outruns their input handling. The previous pasteboard contents are put back about a third of a second later.

During that window the text is on the system pasteboard, which means:

  • any other application running on your Mac can read it; and
  • if Handoff is on, Universal Clipboard can sync it to your iPhone, iPad and other Macs signed into the same Apple Account.

tmux targets use direct pane delivery and do not use the pasteboard. With away access enabled, the direct phone-to-Mac connection can cross the internet. What macOS then does with the pasteboard depends on your Handoff setting, and if you dictate something you would not want appearing on another device, turn Handoff off in System Settings → General → AirDrop & Handoff.

Your images

An image you attach to a message is resized on the phone, sent to the Mac over the same TLS connection's key on a socket of its own, and written to a file on the Mac — ~/Library/Application Support/Nimlet/inbox/, created mode 0700 with each file mode 0600. That is not a transport detail: a tmux target is sent the file's path, because a pane cannot be handed bytes, so the file has to outlive the delivery for the agent to be able to open it at all.

Unlike text, therefore, images are stored. Two things bound that:

  • anything in the inbox older than a week is deleted on the next upload, and the folder is capped at 512 MB, oldest first; and
  • the folder is yours — delete it, or anything in it, whenever you like. Nimlet makes a new one.

Nimlet sends the image to your Mac; the application or agent you select may then process or upload it under its own policies. The phone never names the file: every name is mice-<date>-<n>.<ext>, chosen on the Mac.

A screenshot you annotate is one of these images, with one extra step before it: the Mac photographs the target's window — or the display the pointer is on, for a pane — and sends it to the phone so you can draw on it. That picture crosses the connection in both directions and is not kept on the Mac by this capture step; what is kept is the flattened result, in the inbox, like any other attachment.

For app and frontmost targets the image passes through the pasteboard, exactly as text does and with the same consequences — an app's composer takes pictures, not paths, so it is pasted. tmux targets do not touch the pasteboard; they get the path.

What is stored, and where

On the Mac, in ~/Library/Preferences/com.renyicao.mice.host.plist:

  • the pairing code;
  • your configured targets (names, bundle identifiers, tmux pane ids);
  • the list of devices you have approved and the list you have rejected, each with the device's name and when it was last seen.

Also on the Mac, in ~/Library/Application Support/Nimlet/:

  • deliveries.log, an append-only line per delivery — timestamp, whether it was delivered or refused, the target's name, how many characters it was, and whether Return was pressed. Not the text. It exists so you can answer "did Nimlet press Return in that pane at 14:02?" without keeping a copy of everything you have ever dictated. It is created mode 0600. Delete it whenever you like; Nimlet makes a new one.
  • targets-<timestamp>.json, written only if your saved target list ever fails to load. It is a copy of the unreadable file, kept so a bad upgrade cannot silently delete the targets you configured.
  • inbox/, the images you have sent from the phone. See Your images above: this is the one thing Nimlet keeps a copy of, because the copy is what gets delivered.

On the phone, in the app's own UserDefaults: the pairing code, the Macs it has seen, your quick replies, your pointer and Air pill preferences, and the target list as the Mac last described it, so that opening the app draws the dock rather than an empty screen while it reconnects. That list is what the dock is drawn from and nothing more — the names, symbols and bundle ids of the tiles, plus the title of a window a target has been pinned to. The app icons behind the tiles are cached as files in the app's own Caches directory, where the system may reclaim them at any time.

If you use the mice command-line tool, it keeps its own copy of the pairing code in ~/.config/mice/config.json, created mode 0600.

No transcript, no delivered text and no pointer history is kept in any of these; attached images are the exception, and are covered above. Away-access keys are stored in the Keychain on both devices. Revoke a phone from the Mac before removing the apps to invalidate its access. Removing an app does not guarantee that all preferences, Keychain entries or Mac support files are erased. Mac preferences, the Application Support folder and the CLI's config file may remain and can be removed separately when no longer needed.

Logs

Both apps log to the unified system log under the subsystem com.renyicao.mice, which you can read with make logs. The host logs connection events, target names, pointer rates and delivery outcomes — not the text that was delivered.

The phone logs the same kind of thing — what the engine did, how long the audio was, how many characters came back — and never the transcript itself, on either the SpeechAnalyzer path or the SFSpeechRecognizer fallback. Listening logs the format, the buffer depth and the number of dropouts, under the category listen; none of that describes what was playing.

Permissions, and why each one exists

Where Permission What it is actually for
Mac Accessibility Posting the keyboard and mouse events. Without it Nimlet silently does nothing.
Mac Local network Accepting the connection from your phone.
Mac Screen Recording Mirroring a window into the phone's panel, taking the screenshot you draw on, and — the same grant, because ScreenCaptureKit is also how audio is captured — sending the Mac's output to a phone that has asked to listen. Asked for the first time one of those actually happens, not at launch.
Phone Microphone Capturing hold-to-talk audio for transcription, with possible Apple service fallback.
Phone Speech recognition Running that transcription.
Phone Motion Steering the pointer while the Air pill is held.
Phone Local network Finding your Mac over Bonjour.
Phone Camera Photographing something on your desk to send. Only if you tap Camera; picking an existing photo goes through the system picker, which hands over the one picture you chose without the app ever seeing your library.

The Mac app asks for nothing else. In particular it does not request microphone access — the only audio it ever captures is what it is playing, through the Screen Recording grant above, and it cannot hear the room — and it does not request permission to send Apple Events, because it never sends any.

Optional Pro purchase

Nimlet Pro is a non-consumable purchase handled by Apple. StoreKit reads verified entitlements, restores purchases and handles revocations. Nimlet does not receive payment card details or send transactions to a developer-operated server. Apple processes purchase information under its privacy policy.

Push notifications and VPN routes

When configured, the Mac sends the phone's APNs token and an encrypted notification envelope to the notification relay; the relay forwards it to Apple. The relay and Apple can observe routing metadata and delivery timing, but the application encrypts the notification content for the paired phone. Notification rules and device registration are stored on the Mac. Revoking a phone removes its push registration. Push delivery does not carry remote-control traffic.

The Mac shares active Tailscale interface addresses with its paired phones over their existing TLS session. Both devices must be connected to the same permitted VPN network to use those addresses. Tailscale supplies the encrypted VPN connection and may relay it according to its own service and privacy policies. Nimlet itself does not run a control relay.

This website and support email

This site is hosted through OpenAI Sites and its hosting infrastructure. Hosting providers receive technical request information such as IP addresses and browser/request metadata to deliver and secure the site. We do not add analytics scripts, advertising pixels or a contact-form tracker.

If you email support, your email address and the information you include are processed by our email providers and used to respond to your request. Please avoid sending private work content or credentials. Contact support@nimlet.app to request deletion of support correspondence, subject to any retention required by law.

Notification service processing

The notification relay implementation forwards requests without a message database. This does not mean the hosting provider or Apple processes no metadata or keeps no operational logs. The configured providers may process routing information, IP addresses, delivery timing and service logs under their policies. Nimlet encrypts notification content before it leaves your Mac; its paired encryption key is not sent to the relay.

Changes and questions

We update this page when Nimlet’s data handling changes. The date at the top identifies this version. For questions or requests about data handled by the publisher, contact support@nimlet.app. You can remove local data using the locations described above; other applications and service providers manage their own copies.