Fleet watches the machines you run: servers, build boxes, laptops. Run one command on a machine and it inventories itself, works out what is actually reachable (not just which ports are open), joins your workspace with its own Ed25519 identity, and keeps reporting. The portal shows every machine, every exposed service, the dependency graph between machines, and a firewall plan for each risk that a person reviews and that rolls back on its own.
AI explains; deterministic code decides. Findings, scores and plans come from fixed rules, the same code on the machine and on the server. A model may explain them; it never writes or applies a rule.
It generates its own key and shows a short code (BCDF-GHJK), the link to Fleet, Pair a machine and a QR code of that link with the code filled in. Type the code in the portal (or from Fleet, Add machine), check what is asking to join (hostname, addresses, the key fingerprint, where the request came from and inline’s assessment of what it reported), and approve. The terminal says it joined and keeps running the agent. Approving adds the machine approved: a person looked at it and said yes. Codes last 10 minutes and are single use; nothing is saved on the machine until you approve.
Only approve a code shown on a terminal you are using right now. A page opened from a link with the code already in it asks you to compare the key fingerprint with the terminal before it lets you approve.
Swap join for install to run the agent as a service (systemd, launchd or a scheduled task) so it survives reboots; it pairs first when the machine has not joined yet. The service runs inline-fleet run, which also puts a confirmed firewall plan back after a reboot.
Many machines (cloud-init, Ansible, an image): under Fleet, Add machine, Many machines, name a join token and run join --token <token> (or install --token <token>) on each machine, with no prompt. Join tokens are shown once (only a hash is stored), expire, and can be limited to a number of machines. A machine joined with a token lands pending unless the token was minted with auto-approve: it reports, so you can check it first, but receives no commands until someone approves it.
Without sudo (or Administrator) the agent still runs, but cannot see socket owners, the firewall ruleset or sshd’s effective config. Those show as Unknown on the dashboard, never as fine.
Sent: configuration and socket metadata. Ports, bind addresses, process names, interfaces, firewall rules, SSH and hardening settings, neighbors on the LAN. Every request is signed with the machine’s private key. Machine ids are hashed.
Never sent: file contents, environment variables, traffic payloads, the private key. Command lines only when you opt in (--include-cmdlines), and redacted even then.
Each listening socket gets a reach from its bind address and the interfaces it lands on (this machine, containers, VPN, local network, internet), then the firewall narrows it: Blocked, Allowed, Unknown (unreadable), or Docker bypass (a container-published port on Linux, where Docker’s NAT runs before ufw or firewalld rules). The agent cannot see upstream routers, so “local network” and “internet” mean “reachable as far as this machine decides”.
inline joins every machine’s established connections to every machine’s listeners, so “5432 is open” becomes “PostgreSQL on db listens everywhere; only web uses it”. Fleet, Topology draws that graph left to right in the direction traffic flows, groups external destinations, shows unmanaged devices dashed, and marks the flows a pending plan would block.
A plan contains only two kinds of action on specific ports: restrict (allow these sources, drop the rest) and block. inline-fleet never changes the default policy and never touches rules it did not write. It uses its own nftables table, iptables chain, pf anchor or Windows firewall rule group, so rollback removes exactly what it added.
Every plan keeps the management session, established flows, loopback and inline itself reachable. Applying is provisional: unless it is confirmed within the rollback timer (120 seconds by default), the agent reverts it on its own.
Applying from the dashboard takes two keys: the workspace setting (Fleet, Settings, Allow applying from the dashboard) and the agent started with --allow-remote-apply. Without both, approve the plan in the portal and run npx @pendral/inline-fleet apply on the machine, which shows the same plan and asks before it acts.
Overview: machines online, fleet score, open findings, exposed services, pending approvals and unmanaged devices; a seven-day trend; the live activity feed; every machine, filterable.
Machine: services and their reach, findings, connections in and out, the firewall, the plan (script, rollback script, history), and system facts with what each collector could not see.
Findings: everything across the fleet, worst first, with dismiss and reopen (a reason is required).
Devices: neighbors seen on LAN segments that are not enrolled, to label, mark known or ignore.
npx @pendral/inline-fleet # scan: local, offline, read-only reportinline-fleet join [--token <inlf_...>] # join (a code to approve, or a token), then run the agentinline-fleet run # the agent loop for a machine that has joinedinline-fleet status | doctor # fleet membership; what each collector can seeinline-fleet plan | apply | confirm | rollbackinline-fleet install | uninstall | leave
Module fleet: read, triage (dismiss findings, label devices, rescan, ask the AI), enroll (pair machines, join tokens, approve, quarantine, rename, revoke), enforce (approve and send plans, roll back), configure. Workspace-wide. Fleet is on every plan; the number of machines is what changes: Free includes 3, Pro 50, Enterprise has no limit.