Application-aware network monitoring for macOS, with focused visibility into AI agents.
A native macOS network monitor that attributes observed traffic to applications and destinations. It highlights AI agent activity such as sensitive protocols, unfamiliar destinations, and large uploads, with local history and explainable alerts.
Download for macOS · Website · Build from source · How it works
Your Mac now runs software that makes its own decisions. Coding agents read your files, run shell commands and call tools, and any of those tools can open a socket. Activity Monitor shows how much traffic there is. A firewall asks you to allow each connection. Neither answers the question that matters now:
What are my agents talking to, besides their model provider?
Flowlight answers that for observed application traffic, then provides additional context for recognized AI agents.
- Per-app attribution for observed TCP and UDP activity, including CLI tools and background services. Coverage depends on the selected capture source; the nettop sampler can miss short-lived connections.
- Resolved hostnames where available. Learned from observed TLS server names and DNS responses, with an optional fallback to the network owner (Cloudflare, Inc. · AS13335).
- 108 protocols in 13 families, recognized by port and by content: web (HTTP/1–3, QUIC, WebSocket) · email (SMTP, submission, IMAP, POP3 and their TLS variants) · file transfer (FTP/FTPS, SMB, AFP, NFS, rsync, git) · remote access (SSH, RDP, VNC, Telnet) · name resolution (DNS, DoT, DoH, DoQ, mDNS) · VPNs and tunnels (WireGuard, OpenVPN, IPsec, Tailscale, SOCKS, Tor) · databases (Postgres, MySQL, Redis, MongoDB…) · messaging and queues (MQTT, AMQP, Kafka, XMPP, IRC) · voice and video (SIP, STUN, RTSP) · and more.
Flowlight recognizes 16 agents by name (Claude Code, Codex, Cursor, Windsurf, GitHub Copilot, Gemini CLI, Aider, Goose, Ollama, ZCode and more). It also classifies non-browser processes that contact one of 27 known LLM API providers. Provider contact is a classification signal, not proof that a process is autonomous or malicious.
For each agent you see which AI providers it uses, and everything else it contacted, including what its tools and MCP servers did:
-
Tools & MCP servers. Flowlight follows the process tree back to the agent that started each process, so the
curl,git pushornpm installa Claude Code shell tool runs is counted as Claude Code's traffic, labelled via curl. MCP servers are named from the agents' own configs (Claude Code, Claude Desktop, Cursor, Windsurf, VS Code, Codex, Zed, Gemini CLI): via github MCP. -
Allowlists. "Claude Code may talk to GitHub and npm, nothing else." Add domains (subdomains included), IPs or CIDR ranges, or start from a preset (GitHub, npm, PyPI, Homebrew, Docker Hub…). The agent's AI providers and your local network are always allowed; anything else raises an alert, and each destination has a one-click Allow.
-
Tool calls, from the model itself (optional). Turn on HTTPS inspection and Flowlight reads every tool the agent offers the model, every call the model asks for (Anthropic, OpenAI, Gemini, and MCP
tools/call) and the result the agent sent back, then links each tool's request back to the call that caused it: curl → paste.example ← Bash: curl -s https://paste.example/up. For MCP servers reached over HTTP it also records the server's name and version and the tools it offers. Each agent's detail has Tool calls and MCP servers tabs. -
What each agent is set up to do. With your say-so, Flowlight reads the agent configuration on this Mac — skills, subagents, slash commands, hooks (the shell commands they run on events), permission rules and MCP servers — and lists them per agent. A hook that posts to a webhook explains traffic you'd otherwise have to guess at. It looks only at the agent folders in your home folder, plus project folders you pick, and remembers the result instead of rescanning.
These rules watch every agent:
| Rule | Fires when an agent… | Severity |
|---|---|---|
| Allowlist violation | contacts anything not on its allowlist (when you've set one) | critical |
| Sensitive channel | uses email, file transfer, SSH or remote desktop, a tunnel or proxy, peer-to-peer, or a database connection | critical for email, file transfer, tunnels and P2P |
| Possible exfiltration | uploads more than 100 MB/hour to hosts that aren't AI providers | critical |
| Unnamed host | connects to a raw IP with no hostname on an unusual port | warning |
| Active while you're away | moves data after 15 minutes without keyboard or mouse input | warning |
| Fast learning | new destinations are flagged after a 1-hour learning period (24 hours for other apps) | info |
Every threshold is adjustable in Settings.
Off by default. When enabled, Flowlight runs a local proxy (127.0.0.1:8877) with a certificate authority created
on your Mac. For supported HTTP traffic routed through the proxy, it records headers, bodies, status and timing.
- AI agents only, by default. Other apps sent through the proxy pass through encrypted and aren't recorded.
- Route an agent with Open Inspected Terminal (or paste the shell setup): proxy variables plus the Flowlight certificate for Node, Python, curl and Git, for that shell only. Optionally trust the certificate and use the system proxy for desktop apps; its PAC file falls back to a direct connection whenever Flowlight isn't running.
- Excluded by default: Flowlight's built-in list of Apple services and password managers, plus any destination you add. Applications that pin certificates may reject interception and are passed through when detected.
- What each agent declares. Tools it offers the model (and which the model actually used), the provider's own tools (web search, code execution), the model, the number of calls and tokens in/out/cached.
- MCP servers, all three kinds: local processes, servers this Mac calls over HTTPS, and servers the provider connects to for the agent, with their URL, approval setting and allowed tools. The last kind never touches your network.
- Readable bodies: JSON as a collapsible tree in its original key order, event streams one event at a time, or raw.
- Credential headers are never stored, recordings are kept 3 days, and one button removes the certificate, its trust setting and everything recorded.
Answer a chosen host, path and method with your own status, headers, body and delay, to see how an agent copes when an API fails or returns something odd. The request is never sent. Mocked exchanges are recorded and clearly marked, so a session read later still shows what was real. Needs HTTPS inspection, since only decrypted traffic can be answered — and a mock changes the reply, not whether the connection can be made.
- Second, minute, hour, day, week, month and year views. Click a bar to zoom in.
- Group the breakdown by App › Domain › IP, Destination › App › IP, or IP › App.
- Donut and trend charts with a top-5 + Other layout that stays readable with hundreds of apps.
- Hover any bucket to see which apps drove it. Export to CSV.
An allowlist warns by default. Turn on Refuse connections outside the list for an agent and Flowlight drops those connections as well, recording each one as an alert with Allow … from Now On to add it to the list in a click.
It needs the Network Extension — refusing a connection means being in its path, which the sampler can't do. Local traffic, DNS, Apple services and Flowlight's own connections are never refused, enforcement lapses a few seconds after the app stops running, and HTTPS inspection doesn't combine with it.
An allowlist is one agent's idea of where it may go. A rule is the general version: it names a subject — an app, an agent, a destination, a URL, or a pairing of two of those — and says block or allow. Right-click any row in Live, Reports, AI Agents or Inspect to write one about what you're looking at; all of them land in the same editor on the Rules screen.
- The most specific match decides, and a tie goes to the block. An exception written underneath a broad block works; one broader than what it excepts doesn't quietly widen it.
- For as long as you say: forever, until a time, until Flowlight quits, or between chosen hours on chosen days — plus one global Pause Blocking, because the escape hatch is what makes strict rules liveable.
- Unblocking is part of blocking. From the alert, allow it once, for an hour, or until Flowlight quits. Each of those is itself a rule with an expiry, so the list can still answer why is this getting through? next week.
- A rule says where it bites. The extension refuses whole connections and knows nothing about paths; HTTPS inspection refuses one request and answers with a status the agent can read; the sampler refuses nothing. A rule the current setup can't carry out says so in the list instead of looking enforced.
- A violations feed beside the list: every connection a rule decided, refusals and exceptions alike.
Which tools may this agent use is a different question from which hosts may it reach, so it gets its own tab in AI Agents: a switch on every tool the agent declares and every MCP server it reaches, presets (read-only, no shell, no writes), and a record of what has been taken away.
- The declaration is the strongest lever. Agents re-send their whole tool list every turn; Flowlight removes a refused tool from it before the request leaves, so the model is never offered it — no refusal to argue with, no retry loop. Anthropic, OpenAI and Gemini shapes alike.
- A refused MCP call over HTTP comes back as a result with
isError: trueand a sentence, which is the protocol's own shape for a tool that failed.resources/readgets a JSON-RPC error, which is its. - Connectors are narrowed, since the provider reaches those servers and that traffic never touches this Mac.
- Local stdio servers speak over pipes. Flowlight watches the server process's own traffic and hands you the deny list to paste into the agent's settings, which takes effect when it restarts.
- It needs HTTPS inspection, and it is not a sandbox: a refused tool stops being offered and stops being answered, but an agent with a shell can still do by hand what the tool would have done. Flowlight records that rather than pretending to prevent it.
Not all traffic goes to the internet. AirDrop, Handoff, AirPlay, Sidecar and Universal Control go straight to a device in the room over Apple Wireless Direct Link — no router, no internet, no address anyone else can reach. Flowlight was always counting those flows; it had no word for them, so an AirDrop of a 4 GB folder looked like a few megabytes to an address with no name.
Every flow now carries a channel: the network, peer-to-peer Wi-Fi, this Mac, or a tunnel. Narrow a report to one of them from the toolbar, and peer-to-peer rows are named by the feature that opened them — AirDrop and Handoff · nearby device — because a link-local address tells you nothing and the device has no name this Mac can learn.
The sampler reads the interface each socket is bound to, which is exact. The Network Extension is handed sockets rather than interfaces, so it judges by the address instead: link-local means peer-to-peer. That is the coarser of the two answers, and it says so.
macOS runs whichever build of the content filter was activated last, so after an app update the app and the extension can disagree — and then macOS refuses the connection between them. System Settings says Filter enabled, Flowlight says Extension connection invalidated, and neither changes its mind.
Flowlight climbs out of that on its own: redial twice, then ask macOS which build it has and reinstall the extension if it isn't this app's, then redial again — and if none of it works, capture with the nettop sampler so there is still data. It says which rung it is on and how long until the next one. Your chosen source isn't rewritten, blocking is switched off while the sampler stands in (the sampler can't refuse anything, and Rules shouldn't claim otherwise), and Try the extension again starts over.
A Mac sends and receives over more than TCP and UDP. The Devices screen covers the rest, off until you turn it on — not for want of a permission, but because watching more of your Mac should be a decision rather than something an update did.
Bluetooth: which devices are paired, which are connected, when that changed, and which applications are built to use the radio. No byte counts — macOS keeps no per-app accounting for Bluetooth, and the traces that would give one need a profile an app can't read. The app list is who asked for Bluetooth, not who was granted it, and it says so.
USB and external storage: what is attached, what it is, and a drive's capacity, with the moment each arrived and left. Volumes arrive from the workspace the instant one is mounted; USB devices are read periodically. No throughput, for the same reason.
Ask in plain language and get an answer from what Flowlight recorded. What did Claude Code upload yesterday? Which app started talking to somewhere new this week? Summarise the last hour.
The model never gets your history. It is handed seven read-only queries it may call — totals, top apps, top destinations, new destinations, alerts, agents, a series over time — and nothing else. There is no query that takes SQL, and there will not be one. Flowlight runs whichever the model names, locally, and hands back the numbers.
It answers questions about Flowlight itself as well — how do I turn on HTTPS inspection?, why am I not seeing any traffic? — from the app's own guide to every feature and a snapshot of how this Mac is set up, never from the model's memory. And it draws a chart when the shape of the answer matters more than the numbers: a line for change over time, bars to compare, a pie for a split. Flowlight draws it from the rows the query returned, so the picture and the sentence come from one source.
Local first: the on-device model where macOS has one, or a server you already run (Ollama, LM Studio, llama.cpp). Both send nothing. Or bring your own key for Anthropic, OpenAI, Gemini or any OpenAI-compatible endpoint — the key lives in your login Keychain, the screen says when a question will leave the Mac, and every request is shown in full under the answer.
Every query is listed under the answer, and clicking one opens those rows in Reports. And Ask's own traffic shows up in Live like any other app's — including when the model is a server on this same Mac.
A third mode in Reports, beside the breakdown and the charts. It compares the apps in a report with each other and points at the ones whose destinations don't look like the rest — many more places than their peers, addresses that never resolved to a name, hostnames that look generated, far more sent than received, protocols that are a sideline rather than the app's purpose. Each finding shows its evidence; clicking one narrows the report to that app.
It's Worth a look, not Suspicious: the data supports "unusual next to the other apps here", and a backup tool talks to a lot of places for good reasons.
Flowlight keeps recording with its window closed and costs almost nothing while idle. Settings › General › Run in the background drops the Dock icon and the Cmd-Tab entry; the menu bar keeps the rates and offers Show Dock Icon to undo it. Quitting stops the sampler — it does not stop the Network Extension, which runs on its own until you disable it in Capture.
The window reopens where and how you left it; a first run fills the screen. Hostname setup is offered a little after launch and only while a window is open, rather than meeting a first run with a password prompt — and it returns next launch until taken or dismissed.
Pick a few apps and destinations and every screen shows only those — Live, Reports, Alerts, AI Agents and Inspect, plus the menu bar rates. It's for watching one agent work without the rest of the Mac in the way.
- Add an app by name or bundle identifier — every application on the Mac is searchable, so one that has been quiet still works, as does a command-line agent with no bundle — or pick from what has recently been busy.
- One app is a focus. So is one destination. Neither needs the other.
- Focus on something from any table's context menu, or from the Focus control at the bottom of the sidebar.
- ⇧⌘F turns it on and off; the menu bar shows what's focused and can toggle it too.
- Destinations take their subdomains with them (
example.comcoversapi.example.com). IP addresses work; ranges don't. - It filters what you see, never what's recorded. History stays complete and the anomaly baselines keep learning from everything, so turning Focus off shows the traffic it was hiding.
- Alerts name an app and not a destination, so focusing on destinations alone leaves the alert list alone.
Per-app baselines (EWMA + z-score) for hourly volume and daily destination counts, 99th-percentile upload checks, first contact with a new domain, non-standard ports, and uploads from apps you haven't touched. Every alert names the app, the destination and the number that tripped it.
Off until you configure it, with no Flowlight-operated endpoint to send to — you name your own collector. OTLP over HTTP (rollups as metrics, alerts as logs) or newline-delimited JSON. The Settings panel lists every field that leaves and previews a real payload built from your own data first. Auth headers live in the Keychain. Nothing from HTTPS inspection can be exported — the payload types have nowhere to put a header or a body. What Flowlight sends appears in Live and Reports like any other app's traffic, including a collector on localhost.
No account, no cloud, no telemetry. Everything stays in a local SQLite database. Packet capture reads only DNS answers and TLS ClientHellos (a kernel filter drops everything else), and packet contents are never stored. Naming who owns an IP with no known hostname is on by default: it sends those public IPs (never private ones) to Team Cymru's DNS service, and you can turn it off in Capture. The daily update check asks GitHub for the latest release, and you can switch it off in Settings. To attribute tools and MCP servers, Flowlight reads process command lines and your agents' MCP config files on your Mac; none of it leaves your Mac. HTTPS inspection is off unless you turn it on, and what it records stays in the same local database.
![]() |
![]() |
| Reports: every granularity, every grouping | Alerts: explainable, per app |
![]() |
|
| Inspect (optional): every request an agent and its tools made, and the tool call behind it | |
-
With Homebrew:
brew install --cask xinbetween/tap/flowlight
Or download Flowlight.dmg, open it, and drag Flowlight into Applications. Releases are signed and notarized, so it opens straight away. Prefer an installer? Every release also has a
.pkg. -
Launch Flowlight. Traffic appears within a second, and the ↓↑ rates live in your menu bar. Flowlight checks for new releases daily. It downloads and verifies an update, then asks before it quits to install it and reopen (Flowlight › Check for Updates…). Updating by hand? Quit Flowlight before dragging the new version in.
-
On first launch, Name Your Traffic offers the one-time setup that lets Flowlight read hostnames (it asks for your password once). Network-owner lookups are on by default and can be turned off there or in Capture.
Try it without your own data:
open /Applications/Flowlight.app --args -FLDemo YESlaunches with 90 days of synthetic traffic, including an inspected Claude Code session. That's what the screenshots show.
brew install xcodegen
git clone https://github.com/xinbetween/flowlight.git && cd flowlight
xcodegen generate
scripts/build-local.sh # ad-hoc signed, no Apple account needed
open build/Build/Products/Release/Flowlight.app
scripts/build-dmg.sh # optional: drag-to-install disk image (build/Flowlight.dmg)
scripts/build-pkg.sh # optional: installer packageRequirements: macOS 15 or later, Xcode 16 or later. Internals and the Network Extension path are in docs/DEVELOPMENT.md.
flowchart LR
subgraph Capture
N[nettop sampler<br/>per-process byte counts, 1 s]
E[Network Extension<br/>NEFilterDataProvider, audit tokens]
end
P[BPF packet capture<br/>DNS answers + TLS SNI only] --> H[Hostname cache]
N --> B[Per-second batches<br/>app · host · IP · port · protocol]
E --> B
H --> B
B --> DB[(SQLite<br/>1 s → 1 min → 1 h → 1 day)]
B --> A[Anomaly + agent rules]
A --> AL[Alerts + notifications]
DB --> UI[SwiftUI + Swift Charts]
Two capture engines produce the same per-second summaries:
| nettop sampler (default) | Network Extension | |
|---|---|---|
| Needs | nothing | The Network Extension entitlement (paid developer account), app in /Applications, your approval |
| Attribution | process → app bundle | audit token → code-signing identity |
| Hostnames | TLS SNI + DNS from packet capture, reverse DNS, network owner | SNI, HTTP Host, system hostname, DNS |
| Short-lived flows | a connection that opens and closes between two readings is missed entirely | every flow, however brief |
| Byte counts | exact for anything alive across two readings — it compares running totals, so bursts aren't lost | from the filter's own statistics |
| Energy | starts a process every second | no polling |
What the sampler misses is whole connections, not bytes. It reads macOS's running counters once a second and records the
difference, so a long transfer is counted exactly however bursty it was. What never appears is anything that starts and finishes
between two readings — a quick DNS lookup, a fast API call, a script that runs curl and exits. For an agent that makes many short
requests, that is the difference between the two engines. The extension is called as each connection is made, so it sees those;
in exchange, traffic from before you enabled it isn't there and some system traffic is exempt from content filters.
Storage rolls per-second rows into minute, hour and day tables. Week, month and year views read the daily table, so a year of history stays fast.
- TCP and UDP only. That covers essentially all app traffic, but ICMP (ping) and other raw-IP protocols aren't attributed.
- Per process, not per thread or tool call. macOS attributes sockets to processes, so Flowlight can say curl, started by Claude Code or the github MCP server, not which individual tool call inside a long-running server opened it.
- Allowlists only block when you ask them to. Every allowlist warns; turning on Refuse connections outside the list, per agent, makes it refuse as well. That needs the Network Extension engine — the sampler can only watch — and it never refuses local traffic, DNS, Apple services or Flowlight's own.
- Encrypted payloads stay encrypted by default. Flowlight reads metadata (hostnames, ports, byte counts). Decryption happens only with HTTPS inspection turned on, only for apps that use its proxy, and never for apps that pin certificates. Inspection speaks HTTP/1.1 to both sides.
- Hostname capture follows the primary interface. Traffic confined to another interface or tunnel may lack names.
- QUIC server names come from DNS rather than the encrypted QUIC handshake.
- The Network Extension needs approval. Installing the content filter asks you to allow it in System Settings and to confirm the filter. Flowlight works without it on the nettop sampler.
- Only one content filter runs at a time on macOS. On a Mac where security software already holds that slot — Palo Alto Networks GlobalProtect, CrowdStrike Falcon and similar — Flowlight's filter installs and connects but is never handed any traffic. Capture lists the filters it finds and offers the sampler instead, which needs no filter.
Shipped:
- Signed and notarized releases (Developer ID, from 0.1.6)
- Per-agent allowlists ("Claude Code may talk to GitHub and npm, nothing else")
- Tool and MCP server attribution (which process an agent started opened the socket)
- Full HTTPS request inspection, as a separate opt-in mode (local proxy with its own certificate authority; metadata and analytics stay the default)
- Tool calls read from LLM responses, linked to the requests their tools make
- A Homebrew cask (
brew install --cask xinbetween/tap/flowlight, from 0.2.1) - Focus mode: watch only the apps and destinations you pick (0.2.2, symmetric from 0.3.4)
- Block connections: an allowlist can refuse as well as warn (from 0.3.0)
- Rules: block anything, anywhere, for as long as you say, with a violations feed (0.3.5)
- Agent guardrails: block an MCP server, a tool or a resource (0.3.6)
- A site that keeps up with the app: counts read from source at build time, balanced columns, motion that never moves the layout (0.3.7)
- Peer-to-peer Wi-Fi named as its own channel: AirDrop, Handoff, AirPlay, Sidecar, Universal Control (0.4.0)
- The Rules screen renders (0.4.1 — it came up blank from 0.3.5 to 0.4.0)
- Bluetooth: which devices are paired and connected, which apps are built to use it (0.4.2)
- USB and external storage: what is attached, and when each volume arrived and left (0.4.3)
- Ask Flowlight: questions in plain language, answered from the local history (0.5.0)
- Mock responses in HTTPS inspection (from 0.3.1)
- Export to OpenTelemetry / SIEM (from 0.3.2)
- Runs quietly in the background: menu-bar-only mode, window state, a calmer first run (0.2.7 and 0.3.3)
- Build, sign, notarize and publish from CI (release workflow; see docs/DEVELOPMENT.md for the secrets it needs and what they cost)
Planned, in order:
-
0.9.0 — Coverage, stated rather than assumed. Flowlight says it sees every connection, and then the honest paragraphs elsewhere explain the exceptions: traffic from before the filter started, system services exempt from content filters, a Mac where another content filter owns the slot, apps that pin their certificates, QUIC the proxy never sees, and an agent's local MCP server talking over a pipe. Today you have to know all of that to read the screens correctly. A coverage view would say it per app: watched by the extension, decrypted by the proxy, named only by DNS or SNI, or not covered at all — and why, with the fix where there is one. It is the difference between a tool that claims completeness and one that can be trusted about its own limits.
-
0.9.1 — A threat model, written down. What Flowlight defends against, and what it does not, on one page: software on this Mac behaving badly in the open; not software with root, which can switch the filter off. A signed update from someone who is not us — which 0.8.2 closed. A VPN or security agent holding the content filter slot. Certificate pinning, QUIC, and anything routed around the proxy. The product language should say monitoring, not prevention beside every mention of blocking, because "block" invites a guarantee the design cannot make. Alongside it, a security contact address and key for people who can't or won't use GitHub's private reporting, and the web fonts served from this domain rather than Google's — a local-first tool shouldn't make a third-party request to render its own privacy page.
-
0.9.2 — A budget for inspection. HTTPS inspection records request and response bodies for three days, and that is the most sensitive thing Flowlight ever holds. The redaction that protects it is a guess at which headers carry credentials — improved in 0.8.2, still a guess. This turns it into something with limits you set: a header allowlist rather than a denylist, patterns of your own, an option to keep no headers at all, per-app byte ceilings, bodies deleted on a schedule you choose, and an inspection session that expires by itself instead of running until someone remembers.
-
0.9.3 — Show me what this rule would have done. A rule that refuses connections is easy to write and frightening to switch on, because the first thing you learn about it is what it breaks. Simulation replays the last day of recorded traffic against a rule and lists what it would have refused, before it refuses anything. The data is already there; it has only ever been used to explain the past.
-
0.9.4 — What leaves the Mac, before it leaves. The OpenTelemetry export sends recorded traffic to a collector someone typed in. Before the first row goes, it should show the destination, whether the connection is encrypted, exactly which fields travel and whether any of them are headers — the same disclosure Flowlight demands of everything else it watches, applied to itself.
-
1.0 — What an agent did besides the network. Flowlight can say that Claude Code uploaded 40 MB to an unfamiliar host. It cannot say that it read
~/.ssh/id_rsafirst, and that second half is the exfiltration story: a file leaving is a read followed by a send, and only the send is visible today. This would record what an agent's tools opened, wrote and spawned, and line it up against the connections that followed — read the private key, then talked to paste.example as one finding rather than two screens.It is not a resource monitor. CPU, memory and energy per process are Activity Monitor's job, done well and built into the Mac already; the only number of that kind worth having here is "this agent was busy while you were away", which belongs beside the away-activity alert rather than in a tab of its own.
Two things gate it, both stated here rather than discovered later. Per-process file attribution on macOS needs the EndpointSecurity framework, whose entitlement Apple grants on request and review — not a checkbox — and which only works from a system extension. And it would put far more sensitive material in Flowlight's hands than network metadata ever did, so the inspection budget in 0.9.2 stops being a nicety and becomes the thing that has to exist first. A tool that asks you not to monitor it has to deserve that twice over when it can see every file you open.
Later, no version yet:
- Linux (Ubuntu). A daemon plus a local web UI, sharing the Swift core (storage, protocol classification, agent
rules, MCP and LLM readers). Capture would be rewritten on eBPF or nfnetlink, and process attribution on
/proc; SwiftUI doesn't exist there. - Windows. The same core with capture on WFP or ETW and attribution through
GetExtendedTcpTable. A bigger commitment than Linux: three capture backends to maintain, and a thinner Swift ecosystem.
Issues and PRs are welcome. Adding an agent, an LLM provider or a protocol is a one-line change plus a test. See CONTRIBUTING.md.
Shared/ models, XPC contract, protocol classifier + catalog, SNI/HTTP/DNS parsers
FlowlightExtension/ NEFilterDataProvider system extension
Flowlight/
Capture/ nettop sampler, extension client, installer
Enrichment/ BPF packet capture, network-owner lookup
Storage/ SQLite store, rollups, queries
Analysis/ anomaly engine, AI agent catalog + rules
Inspection/ opt-in HTTPS inspection: local CA, proxy, HTTP parser, tool-call reader
UI/ Live · AI Agents · Reports · Alerts · Inspect · Capture
FlowlightTests/ 105 unit tests: parsers, BPF filter, rollups, charts, agents, MCP, allowlists, inspection, updates
docs/ website (GitHub Pages) and developer guide
Flowlight is free software under the GNU General Public License v3.0. You can use, study, share and modify it, and if you distribute a modified version, you must release its source under the same license.
Flowlight isn't affiliated with Apple or with any AI provider named here. Product names are trademarks of their owners.


