Second one from me this week: ssherlock, a fleet inventory and posture collector in Crystal.
Point it at your fleet. It logs in read-only over SSH, gathers the evidence, and hands you one JSON file per host — shaped for an LLM to reason over.
The premise is a split of labour. ssherlock plays the detective and does the fieldwork: it visits every host over SSH, runs a catalogue of read-only commands (lscpu, ss -tlnp, pveversion, esxcli … — never a mutation), and writes <label>.json per host plus an aggregated all.json. The writeup — hardware obsolescence, capacity headroom, security posture, config drift across the fleet — is an analyst’s job, and that analyst is an LLM. ssherlock never calls a model itself; it just makes its output deterministic enough that the reasoning on top stands on solid ground.
ssherlock run # collect the whole fleet from ./ssherlock.yml
ssherlock run web01 db01 # only these machines (by label or host)
ssherlock run --redact # mask secrets before anything hits disk
ssherlock presets linux # dump a resolved preset as YAML
Checks, RuboCop-style
The part I’m happiest with. Presets shipped in the binary are the default rule packs; your fleet file’s overrides: block is your .rubocop.yml. It layers on top of a preset, keyed by preset name — set a check to null to disable it, redeclare it to retune (keys deep-merge over the preset’s), or declare one the preset never had, sections created on the fly. The presets themselves are never edited.
overrides:
linux:
services:
packages: ~ # disable
storage:
df:
command: df -hT -x tmpfs # retune
custom: # brand-new section
reboot_pending:
command: '[ -f /var/run/reboot-required ] && echo yes || echo no'
Presets can also inherit from one another (linux-full extends linux), and you can define your own inline in the fleet file or in a presets_dir, resolved inline > directory > baked, without rebuilding.
Each check carries declarative metadata — category (inventory/capacity/security/…), severity, and expected, a free-text description of a good result — which rides into the JSON to steer the analysis. ssherlock deliberately never evaluates expected or computes a pass/fail; that judgement belongs to the analyst.
Other bits
- One static binary, presets baked in via
baked_file_system— drop it on a jump host, nothing to install on the targets, no agent to deploy. - Fleet-parallel with bounded concurrency, per-host and per-command timeouts.
- Bastion relay,
ssh -Gconfig resolution, optionalknown_hostsverification. --redactmasks PEM keys,password=…pairs and bearer tokens before writing — while keeping policy keys likePasswordAuthentication noreadable, so the report doesn’t lose its meaning.ssherlock skill installmaterialises the companion analysis skill (also baked into the binary) into./.claude/skills/, but the binary never runs it.all.jsonis plain structured data — pipe it into whatever assistant you like.
Crystal-specific notes
Built on ssh2.cr (thanks @spider-gazelle), admiral, baked_file_system and spectator.
One limitation worth writing down, because it’s a genuine language-level constraint rather than a bug I can fix: Crystal cannot cancel a fiber blocked on a frozen SSH read. Every check has a caller-side timeout (cmd_timeout + 5s), but if a remote command wedges, the reading fiber parks until the host’s session closes at the end of that host’s collection. Mitigation is server-side timeout wrapping (wrap: true in a preset’s options), with the caller-side guard as the fallback for presets that can’t use it — ESXi’s busybox shell, mainly. Happy to hear if anyone has a better pattern for this; it’s the one place where I wanted a cancellable read and didn’t have one.
Source, releases and full docs: GitHub - jbox-web/ssherlock: Read-only SSH fleet audit collector in Crystal — one static binary, preset-based command catalogues (Linux, Proxmox, VMware ESXi), and one structured JSON envelope per host, shaped for an LLM to reason over. · GitHub (MIT).