process_treepid=4312As you scroll, the laptop opens and its screen becomes the guardyn console. It runs an illustrative investigation on a fictional laptop, finance-mbp-14: five checks at once, one that could not run, a follow-up, and an answer that quotes the evidence. Three of the results then hang in front of the screen.
Each card is one check, with the fields the agent returned. The answer quotes them, and the console keeps them with the turn.
Bahraini-built
02:1409:14Someone has a question about a laptop.
An AI security analyst that looks before it answers.
Put a read-only agent on your machines and ask what is happening on them. It pulls the evidence a responder would pull, from processes and sockets to autoruns, logons and hashes. Then it answers with the pid, the path and the address quoted.
No card. 100 credits on signup. Two machines on the free plan.
Illustrative data. Fictional machines, people and addresses.
An investigation
The evidence stays attached to the answer.
One question, five checks sent at once, one follow-up. Every result is kept with the turn, including the check that could not run. Save what matters as a finding, and decide how serious it is yourself.
list_processesunsigned_only=trueon finance-mbp-14outbound_connectionson finance-mbp-14list_autorunssuspicious_only=trueon finance-mbp-14recent_changeshours=24executable_only=trueevent_logon finance-mbp-14process_treepid=4312on finance-mbp-14Suspicious. Investigate. An unsigned binary /tmp/.cache/nodeh (pid 4312, started 02:03) holds an established connection to 203.0.113.5:443. A launch agent that starts it was written at 01:23, forty minutes earlier. Three facts that are individually ordinary, and together are not.
Confidence: high. The plist, the binary and the socket agree on timing.
Not checked: event_log needs root, so tonight's system events were not read. needs root, so last night's system events were not read.
Do now: copy /tmp/.cache/nodeh somewhere safe before it is removed, then kill 4312. Check whether any other machine has talked to 203.0.113.5.
- 02:1409:14One question about one laptop.
- Five checks go out at once. The hairline under each is time against that tool’s real limit.
- Results land in the order they finish. One could not run, and the answer says so.
- The answer quotes the pid, the path and the address.
- Illustrative data. Fictional machines, people and addresses.
process_treepid=4312outbound_connections| Process | Remote | Signed |
|---|---|---|
| nodeh 4312 | 203.0.113.5:443 | unsigned |
| Safari 811 | 198.51.100.24:443 | system |
| nsurlsessiond 402 | 198.51.100.77:443 | system |
| Mail 790 | 192.0.2.41:993 | system |
list_autorunssuspicious_only=true- Location
- ~/Library/
LaunchAgents/ com.cache.nodeh.plist - Target
- /tmp/.cache/nodeh
- Signed
- unsigned
- Modified
- 01:23 tonight01:23 last night
- Command
- */30 * * * * ~/bin/sync-notes.sh
- Modified
- 6 days ago
Then it is yours to rank.
- Severity is your call, not the model’s.
Save an answer as a finding and you choose critical, high, medium or low. The title starts from the verdict line, and you can change it.
- One problem, one entry.
Raise the same thing twice and it stays a single finding with a seen count.
- A work queue, not a feed.
Assign it, acknowledge it, resolve it, or mark it not an issue.
No open findings means nothing in the evidence gathered so far looked wrong. That is not the same as nothing being wrong.The empty state of the findings queue
pid 4312 runs /tmp/.cache/nodeh and holds 203.0.113.5:443. A launch agent written at 01:23 starts it.
How it works
Three steps, and the third one is the product.
The first two take about a minute. Then you just ask.
Install the agent
One static binary with no dependencies, for macOS, Linux or Windows. The installer checks its published SHA-256. Enrolment needs a token you paste yourself, so a leaked install command cannot add machines to your fleet.
$ curl -fsSL https://guardyn.dev/install.sh | sh $ guardyn-agent enroll \ --server https://guardyn.dev \ --token gdn_enrol_… enrolled build-runner-03 (linux/amd64)
Connect it
The agent dials out and holds one long-lived stream. It never listens on a port, so there is no inbound firewall rule. When the stream closes, the console says offline instead of guessing.
$ guardyn-agent connect connected as build-runner-03 29 tools offered, elevated=true waiting for jobs
Ask
Pick a machine, pick a model, ask in plain language. It calls the checks it needs in parallel, reads what comes back, and answers with the evidence attached.
> What is listening on build-runner-03? ▸ list_sockets state=listening 0.4s Four ports. Three expected. One is not: 8443, held by a process running from /tmp.
The tool set
Every way to look. None to touch.
30 read-only checks. Each one is argument-validated on the endpoint as well as the server, and each reports its own limits. The agent publishes what it actually has when it connects, so an older binary offers fewer tools instead of failing halfway through an answer.
What is running
Processes, their ancestry, their signatures, the files they hold open, and one frame of the screen itself.
list_processesprocess_treeprocess_open_fileslist_servicesloaded_modulesscreenshotWhat is reachable
Listening ports, live connections, where they go, and what resolves them.
list_socketsoutbound_connectionsresolve_hostWhat survives a reboot
The persistence surface: launchd, Run keys, services, cron, WMI and shell profiles.
list_autorunsinstalled_packageslist_containersWho can get in
Local accounts, administrator membership, recent logons and failed attempts.
list_usersrecent_logonslist_certificatesWhat changed
Recent filesystem activity, executables in writable places, and file hashes.
recent_changesfind_fileshash_filesinspect_pathlist_dirread_textWhat the defences say
Antivirus, firewall, disk encryption, SIP, Gatekeeper, Secure Boot and integrity checks, plus a CIS-aligned configuration benchmark.
security_posturecis_benchmarkcheck_integrity*, only where the operating system provides itevent_log*, only where the operating system provides itfull_scanWhat the browser has been doing
History, downloads and cookie hosts. Metadata only, never a cookie value.
browsing_historybrowser_downloadsbrowser_cookieslist_browser_extensions
screenshot stays off until someone turns it on at the machine itself. The model never receives the image. hash_files returns digests only, with no reputation lookup.Hard limits
Read-only is a property of the binary.
The tool set is compiled into the agent. The server can send a tool name and typed arguments, checked on both ends. It has no way to send a command.
It cannot run commands
Hard limitThere is no shell tool, no script tool and no allowlisted-command tool.
If this server were compromised tomorrow, the worst it could do to your fleet is read from it.
It cannot change anything
Nothing writes, deletes, moves, kills or quarantines. Every remediation is yours to run, spelled out precisely enough to paste.
It only dials out
The agent opens one outbound stream and never listens on a port. The server pings every 20 seconds, and after 70 seconds of silence the agent reconnects. It runs at most three jobs at a time.
It keeps its own record
Every run is written to an audit log on the machine itself, so the endpoint has its own account of what was looked at.
It tells you what it did not check
Truncated lists, skipped privileged checks and a machine that went offline mid-scan are all said out loud. Silence about a gap reads as completeness, and that is how people get hurt.
No arbitrary file reads. File contents come back only for a short allowlist of forensic paths. A deny list for keys, .env files and credential stores always wins, matched against the canonicalised path so a symlink cannot walk around it. An investigation console that can read any file is a data exfiltration tool with a nice interface.
Models
Bring the model to the evidence.
The same investigation can run on Claude, GPT or Gemini, or on any OpenAI-compatible endpoint. Pick per conversation, ask a second vendor about a finding you do not believe, and let an administrator decide which tiers each account may reach.
One interface, three vendors, plus the long tail
Adapters for Anthropic, OpenAI and Google, and for any OpenAI-compatible API. Together, Groq, vLLM or a self-hosted model is a base URL and a row.
Prices are data, not constants
The catalogue lives in Postgres: input, cached-input and output prices, context window, capabilities, tier, minimum plan, credit multiplier, fallback and badge. A model without tools cannot drive an investigation, and that is checked before the call.
Fallback that admits it happened
Each model has a fallback chain. It is walked on a 429, a 5xx or a refusal, and only if nothing has streamed yet. When it happens, you are told.
Reasoning stays with its author
Thinking blocks are replayed only to the exact model that produced them. One system prompt drives every vendor, byte-identical on every turn so it stays behind the prompt cache.
An illustration of the picker. What it lists is read from the catalogue each time the page loads.
The fallback notice, as the console shows it.
| Model | Tier | Minimum plan | Multiplier | Falls back to |
|---|---|---|---|---|
| Claude Opus 5 | frontier | Team | 3× | Claude Sonnet 5 |
| Claude Sonnet 5 | balanced | Starter | 3× | Claude Haiku 4.5 |
| Claude Haiku 4.5 | fast | Free | 3× | none |
Three catalogue rows as an administrator edits them. Each carries a 3× credit multiplier, and prices sit in the same rows.
Spend control
Usage you can actually govern.
Billing platforms meter usage; they do not gate it. By the time a meter event is posted the tokens are already bought. So the balance, the check and the circuit breaker live here, in front of the model call.
- 1
Reserve before the first call
Every turn is reserved against a pessimistic estimate before any provider is called. No balance, no call.
- 2
Settle each call at its exact cost
Each provider call is settled at what it really cost. One credit is US$0.01 of retail model value.
- 3
Keep a ledger you can defend
The ledger is append-only, and the balance can be recomputed from its entries at any time to catch drift.
A runaway guard stops a turn once its charge passes four times the estimate made before it started.
Steps per turn at most. Then it stops and says: “Reached the 24-step limit for one turn. Ask a follow-up to continue from here.”
A refused turn says exactly why:
org_suspendedsubscription_unpaidno_creditsdaily_capuser_daily_captoo_many_runsmodel_not_allowedturn_ceilingPlans
Pay for what the models actually cost, plus a margin we publish.
Every plan gets the full read-only tool set. Plans differ in credits, machines, seats and the model tiers they can reach.
Free
Try it on your own machines- 200 credits a month
- 2 machines, 2 seats
- Fast models
- 1 investigation at a time
Starter
For the person who owns the estate- 5,000 credits a month
- 15 machines, 5 seats
- Balanced models
- 2 investigations at once
- 2 API keys
Team
For a security function- 25,000 credits a month
- 100 machines, 20 seats
- Frontier models
- 5 investigations at once
- 10 API keys
- Audit-log export
Enterprise
For the whole estate- 150,000 credits a month
- 5,000 machines, 500 seats
- 20 investigations at once
- 50 API keys
- Audit-log export
Find out what is actually running on your machines.
One binary, one question, one honest answer, including the parts it could not see.
curl -fsSL https://guardyn.dev/install.sh | shKeep it running with launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/dev.guardyn.agent.plist
irm https://guardyn.dev/install.ps1 | iexNeeds no administrator rights. It installs under your own AppData.
curl -fsSL https://guardyn.dev/install.sh | shKeep it running with sudo systemctl enable --now guardyn-agent
guardyn-agent enroll --server https://guardyn.dev --token gdn_enrol_…