Flash needs the Accessibility permission and nothing else to show hints and click. It never reads screen pixels, runs OCR, or records what you type in other apps, and it has no telemetry, analytics, crash reporting, or update checks.
This page lists everything else Flash and its bundled plugins may ask for, read,
store, or send. Disable a plugin with [plugins] disabled = ["<id>"], and inspect
running plugins with :plugins.
| Permission | Asked by | When |
|---|---|---|
| Accessibility | Flash | First launch. Required. |
| Automation: Safari, Chrome, and other Chromium browsers | browsers |
The first time it lists tabs while that browser runs. |
| Automation: the app holding a stuck secure-input flag, and System Events | Flash | The first time a stuck hold is released by blurring a browser or sending its address-bar shortcut. A real password field does not ask. |
| Automation: Notes, Reminders, Contacts | apple |
The first time it indexes that app. |
| Screen Recording | screenshot |
The first :screenshot; macOS screencapture takes the picture. |
| Location | network |
Only on an explicit :network refresh, to read the Wi-Fi name. |
| Calendars, Reminders, Contacts, … | A command you configure yourself, such as icalBuddy in a status source |
The command’s first read. Flash itself never asks. |
Plugins are child processes of Flash, so macOS attributes their requests to
Flash. So are the commands you configure: a named source
([statusbar.sources.<name>]), a #() job in a status format or widget, and
a terminal popup’s command. A calendar CLI such as icalBuddy reads Calendar through
EventKit, so its first run makes macOS ask whether Flash may access your
calendars, and the grant then covers Flash and every command it runs. Deny it
to keep the command from reading Calendar; you can revoke it later in System
Settings › Privacy & Security › Calendars. The
clock and agenda example does this; khal,
which reads its own files, does not.
Flash’s core has no network features. Plugins that reach the network are
listed below. answers uses the host’s fetch, which only reaches URLs
allowlisted in its manifest, so the plugin process itself stays network-denied;
the others make their own requests or run the CLI tools named here.
| Plugin | Destination | When | Default |
|---|---|---|---|
answers |
www.ecb.europa.eu (daily exchange rates) |
At start, then every 6 hours | On |
github |
GitHub, through your gh CLI |
At launch, then when the flashlight opens at most every 10 minutes, only if gh is installed and signed in |
On |
feed |
The URL you configure | Every refresh_interval |
Off until url is set |
tmux |
Noninteractive SSH to hosts running tmux | Every few seconds | Off: only hosts listed in [plugin.tmux] ssh_hosts |
spotify |
Spotify, through the spotify_player CLI |
When you use it | On use |
| third-party plugins | GitHub (git clone of the pinned commit) |
When listed in [plugins] third_party |
Off |
| Path | Contents |
|---|---|
~/.config/flash/flash.toml |
Your configuration. |
~/Library/Logs/Flash/ |
Logs. They never contain keys typed in other apps. Commands Flash’s command line cannot run are logged with their text; the trace level also logs every submitted command line and AX tree dumps. |
~/Library/Application Support/Flash/command-history.json |
The last 200 entries you submitted in Flash’s command line, including flashlight queries. |
~/Library/Application Support/Flash/clipboard/ |
Clipboard history: up to 1000 entries by default ([clipboard] history_size, 1–10000), readable only by you. Flash migrates existing history and images from Plugins/clipboard/share/ on first launch. This is a retention ceiling; Flash cannot recover copies made before it recorded them. The help page loads retained entries in bounded pages. Plain text is kept up to 128 KiB. Formatted HTML is kept up to 64 KiB. One image (PNG, JPEG, GIF, WebP, or a TIFF stored as PNG) is kept up to 4 MiB, including a preview when you copy a single image file of that size. A file copy records up to 20 paths. Items that password managers mark as concealed, transient, or auto-generated are never recorded. |
~/Library/Application Support/Flash/Plugins/history/ |
Copies of Chrome’s History and Firefox’s places.sqlite, refreshed when the flashlight opens or you leave the browser, at most once a minute and only when the originals changed. They only feed explicit searches such as @firefox.history, never default results. |
~/Library/Application Support/Flash/Plugins/marks/share/marks.json |
Up to 36 named app marks: each saved app’s process ID and bundle identifier. |
~/Library/Application Support/Flash/ (other files) |
Ranking data for search results and plugin caches, such as exchange rates. |
brew uninstall --cask --zap flash@nightly removes all of it.
Named yank registers stay in Flash process memory and are exposed to the local
inspector’s Clipboard view while Flash runs. The unnamed (") and system
clipboard (+) registers read the current macOS pasteboard; they are not
stored as separate register files.
browsers): Safari and Chromium browsers through Apple
Events. Firefox, which needs no add-on, through its tab strip in the
Accessibility tree, which Flash walks on the plugin’s behalf, and the
session file Firefox keeps in each installation’s default profile under
~/Library/Application Support/Firefox (named by installs.ini; every
profile under Profiles/ when that file names none):
sessionstore-backups/recovery.jsonlz4, which lists every open window’s
tabs with their URLs and titles. The file is read in place and decoded in
memory, never copied or stored.history).apple).files).tmux CLI; kitty through its remote-control
socket when you enable it in kitty. While one of your clients is attached
to a local tmux server, the tmux plugin keeps one control-mode client of
its own attached to it, on the session your last-used client shows, to hear
about session and window changes. It asks for no pane output, never resizes
a window, never applies update-environment, and leaves when your last
client does. tmux counts it like any client: list-clients shows it with
the control-mode and no-output flags, client-attached and
client-detached hooks run for it, and until your next keystroke a tmux
command that names no client, run from a script outside tmux, may resolve
to it.mouse_menubar reads the focused
app’s menu titles through Accessibility, and where the status items sit from
WindowServer geometry. mouse_notifications reads the banners, alerts and
Notification Center panel on screen through Accessibility: their roles,
positions and labels, which can include a notification’s text. Both read
only when you run them, keep what they read for that hint session only, and
write none of it to disk. While the hints are up, the local inspector’s
state lists them like any other hints.mouse_target --scope=screen
finds players and the Stage Manager strip from WindowServer geometry (which
app owns a window, its level and bounds, never its contents) and reads
their controls through Accessibility, like any other hint target. The
system player and Stage Manager belong to macOS agents
(com.apple.PIPAgent, com.apple.WindowManager), whose controls Flash then
reads too. Nothing is kept past that hint session.[overlay.dark] follows whether macOS is in dark mode.#() jobs run with your
login-shell environment and read whatever they read. Flash keeps their
latest output, and a source’s numeric history, in memory to draw the bar,
popups and widgets, and sends none of it anywhere; a popup showing it goes
through the private pager snapshot described in popups.
Flash does not fetch AI provider quotas. A quota command in your own
configuration does, and its output is kept like any other source.Flash reads keys only while it owns input: a hint overlay, normal mode, or its command line. A session event tap decides for each key whether Flash swallows it or passes it to the app; the tap never stores or logs keys. Modified global hotkeys use the standard macOS hotkey API. Flash does not request Input Monitoring.
While a password field has focus, macOS turns on secure input and hides keys
from the tap. Flash respects it: a hint session started then takes Flash’s own
key window instead, so the labels you type go to Flash and never to the
password field. [app] keyboard_layout reads which input source is selected
and its key layout, to match keys to hint labels; it records neither.
Secure input sometimes stays on after that field is gone, usually because a browser or a password manager enabled it in the background. Flash polls the flag (it cannot see keys while the flag is on) and, when the focused element is not a password field, asks the holding app to release it. A Chromium browser is told, through AppleScript, to blur the focused element in its open windows; the script does not read the field. If the flag remains, or the holder is Firefox or Safari, Flash brings that browser forward and sends the address-bar shortcut (the letter l with Command) via System Events, then returns to the app you were in. Any other holding app is activated and then left, which is what makes a background password manager drop the hold. The first of these can ask for Automation. Flash does not lock the screen, show a dialog, or read what you type. The log line names the app’s bundle id.
[overlay] screen_capture = "hide" asks macOS to leave Flash’s overlay, status
bar and popups out of screenshots, recordings and screen sharing. It is a
request other capture tools may ignore; recent macOS capture APIs can still
record those windows.
flash status and flash doctor answer the flash command through the same
local Apple Event that carries every other command, with JSON printed in your
terminal. The reply describes Flash itself: its version, mode, permissions,
key-capture path, input source ID, config path and diagnostic lines, plugin
health, per-app hint counts and timings keyed by bundle ID (kept in memory for
the last 50 activations of the 32 most recent apps, never on disk), and, for
doctor, the name and process ID of an app holding secure input and whether
Screen Recording is granted. It never contains clipboard
contents, typed keys, window titles or hint targets, and nothing is sent over
a network or written to disk. flash config_check runs entirely in the
flash process and does not contact the resident.
Plugins are child processes that talk to Flash through JSON lines on stdin and
stdout, and Flash stops them when it quits. Most bundled plugins run under a
deny-by-default macOS sandbox profile built from their manifest: they may read
files broadly (that is how history copies browser history databases), but
never ~/.ssh, ~/.aws, ~/.config/gh, your Keychains, or another plugin’s
data; they write only to their own data directory, run only the executables
they declare, and reach the network only when they declare it. Six plugins
run unsandboxed. Five execute helpers the sandbox forbids: caffeinate,
github, screenshot, shortcuts, and tmux. The sixth, browsers,
lists tabs over Apple Events, which Chrome and the other Chromium
browsers refuse from any sandboxed sender, even with Automation granted.
Third-party plugins load only when listed in [plugins] third_party, and GitHub
references must pin a full commit SHA.
:help, ?, :mappings, :logs, :plugins, and :commands open
Flash’s help and runtime pages in your browser.
Flash serves it on localhost (port 4242 by default) from the first such
command until Flash quits, or from launch when
[debug] http_inspector_enabled = true. It shows bundled documentation,
app version and uptime, Accessibility/capture state, the configuration path and
diagnostics, effective mappings for the focused app, logs, plugin state, and recent
clipboard entries (text, images, formatted HTML, and file paths). The homepage
remembers which of its guides this browser has opened, in that browser’s
localStorage only; Flash does not receive the list. A loopback client can read
the full retained clipboard history in pages, delete one entry, or fetch one stored image.
It can also read the configuration file Flash loaded and, on Save, replace
that file. Purge defaults returns text and does not write. The server writes
only that file, and only after the text parses as TOML. Plugin setting values
remain redacted. It rejects requests addressed to other host names and sends
no CORS headers, so web pages cannot read it, but other programs on your Mac
can while it runs.