Ask five engineers what is running on a given Linux server and you will likely get five different answers, none of which match the box itself. Documentation drifts the moment someone edits a config file, restarts a service, or ships a new container image. Claude Code sitting at the terminal of a live host, reading rather than changing, can close that gap without adding another wiki page nobody updates.
I use Claude Code to inspect servers, draft what it finds as Markdown, and commit the result to Git. The commit history becomes the drift log. No agent framework, no API key to manage, just the CLI running commands and writing files, the same way I would work through a host by hand, only faster and more consistent.
What Claude Code is, and what it needs
Claude Code is Anthropic’s command-line agent. It runs in a terminal, reads files, runs shell commands, and edits code, all under your explicit control. For this use case, that means it can log into a host’s shell, run inspection commands, and write documentation without needing a bespoke integration.
Installation is a single line: curl -fsSL https://claude.ai/install.sh | bash. If you prefer a Node-based install, npm install -g @anthropic-ai/claude-code works on Node 22 and above. Signed apt, dnf, and apk repositories are also available, which matters if you manage packages that way across a fleet. Once installed, claude –version confirms the binary, and claude doctor runs through diagnostics if something is not behaving.
Claude Code needs an account behind it: a Pro, Max, Team, or Enterprise plan, or an API provider such as Bedrock, Vertex, or Microsoft Foundry. The free Claude.ai plan does not include CLI access, so budget for that before you plan a fleet-wide rollout.
None of this needs a bespoke agent, a message queue, or a dashboard. It is a terminal tool that runs the same commands you would type yourself, which is precisely why it fits documentation work. Servers already live in a shell. Putting the documentation step in that same shell, rather than in a separate scanning tool, keeps the process close to how the work already happens.
Permissions before you point it at production
By default, Claude Code asks permission before it runs a Bash command or edits a file. That default is correct and worth keeping for anything touching production. Scope what it can do with –allowedTools rather than approving prompts one at a time, and rather than switching permissions off.
For host inspection, I keep the flag narrow and confirmed-good:
--allowedTools "Bash(systemctl:*),Bash(ss:*),Bash(docker ps:*),Read"
That covers reading service state, listening ports, and running containers, plus reading files, without opening up write access or arbitrary shell execution. Commands such as crontab -l and journalctl are still useful during an interactive session. I simply do not add them to the allowed-tools flag until I have watched Claude use them safely across enough hosts to be confident.
There is a flag that removes the permission prompts entirely: –dangerously-skip-permissions. It exists for sandboxed CI pipelines and nothing else. Do not run it against a production host.
Inspecting a host
Before Claude touches a host, I want it looking at the same handful of things I would check by hand.
| Command | What it shows |
|---|---|
| systemctl list-units –type=service –state=running | Running services |
| ss -tlnp | Listening ports and owning processes |
| docker ps | Running containers |
| crontab -l | Scheduled jobs for the current user |
| journalctl | Recent logs for context on failures |
| Reading /etc configs and unit files | Confirming intent behind what is running |
With the allowed-tools flag from the section above, I start an interactive session on the host and give Claude a direct prompt:
“Inspect this server. Run systemctl to list running services, ss to show listening ports, and docker ps for containers. Read the relevant unit files and config files under /etc to understand why each one is running. Do not change anything. Summarise your findings once you are done.”
Claude works through the commands, reads the files it needs, and reports back in plain language what the host is doing and why. Nothing is written yet. This step is read-only by design, which makes it the safest place to start while you are still building trust in the process.

Figure 1 – Claude Code inspecting a running host and drafting services.md before committing anything to disk.
From inspection to Markdown in Git
Once the inspection prompt has run and I am happy with what it found, the next step asks Claude to turn its findings into a document:
“Write your findings to services.md in the current directory. Use one section per running service or container, describing what it does, its status, its listening ports if any, and its scheduled jobs if relevant. Keep the format plain and scannable.”
A typical result looks like this:
# Host: db01.internal
Last updated: 2026-07-18
## postgresql.service
Status: active (running)
Listening on: 127.0.0.1:5432
Purpose: Primary application database, confirmed via /etc/postgresql/16/main/postgresql.conf.
## nginx.service
Status: active (running)
Listening on: 0.0.0.0:443, 0.0.0.0:80
Purpose: Reverse proxy for the application tier, config at /etc/nginx/sites-enabled/app.conf.
## backup-container (docker)
Status: running
Image: registry.internal/backup-agent:1.4.2
Purpose: Nightly backup agent, triggered by cron.
Scheduled jobs (crontab -l, user: appuser):
0 2 * * * /usr/local/bin/run-backup.sh
That file goes straight into Git alongside the rest of the fleet’s documentation. The next time Claude inspects the same host, it reads the existing services.md, compares it against what it now sees, and updates only what has changed. The diff Git shows between that pass and the last one is your drift log: a new service appearing, a port closing, a cron job disappearing. You do not have to remember to check. The history does it for you.
CLAUDE.md as standing context
CLAUDE.md is read automatically at the start of every Claude Code session, so it is the natural place to put standing context about a host or fleet: naming conventions, which services are expected, who owns what, and which inspection commands are off-limits.
To scaffold one, start an interactive session in the repository and run /init at the prompt:
$ claude
> /init
Claude reads the existing files, works out what the repository contains, and writes a first-pass CLAUDE.md. I then edit it down to what actually matters. A typical entry for a fleet-documentation repository looks like this:
# CLAUDE.md
This repository holds generated documentation for our Linux fleet.
- Each host has one file under hosts/<hostname>.md.
- Only inspect, never modify a host's configuration.
- Use systemctl, ss, docker ps and crontab -l as the primary sources.
- Preserve the existing structure of a host's file when updating it.
- Flag anything listening on a public interface that is not already documented.
Every session that starts in this repository picks that context up without me repeating it in every prompt.
Doing this across a fleet
Interactive sessions suit one host at a time. For a fleet, Claude Code’s headless mode is what makes this repeatable: claude -p “prompt” runs a single pass without a chat interface, –output-format text|json|stream-json controls how results come back, and –max-turns N caps how many steps it can take before stopping. You can also pin a specific model with -m
The mistake I made early on was inspecting hosts by pulling their raw command output back to a central machine and writing it to a scratch file before feeding it to Claude. That works, but it means unencrypted service listings, port maps, and config contents sitting in a temporary path, which undercuts the whole read-only, minimal-footprint point of the exercise. The better approach is to run Claude Code where the host already is: installed on each server, or invoked over ssh so the inspection happens on the box itself and only the finished Markdown travels back.
A plain shell loop is enough:
#!/usr/bin/env bash
set -euo pipefail
REPO_DIR="/opt/fleet-docs"
ALLOWED='Bash(systemctl:*),Bash(ss:*),Bash(docker ps:*),Read,Write(services.md)'
while read -r host; do
echo "Documenting ${host}"
ssh "${host}" "claude -p 'Inspect this server and update ~/services.md with what is running and why. Do not change anything else.' --allowedTools \"${ALLOWED}\" --output-format text --max-turns 8"
scp "${host}:~/services.md" "${REPO_DIR}/hosts/${host}.md"
done < hosts.txt
cd "${REPO_DIR}"
git add hosts/
git commit -m "Fleet documentation pass: $(date -I)"
git push
Each host runs its own inspection over ssh, with Claude reading and writing on the box itself rather than shipping raw command output anywhere. The finished services.md is the only thing that travels, pulled back over the same encrypted connection with scp. One commit and one push covers the whole pass, so the fleet’s documentation history stays as a clean sequence of point-in-time snapshots rather than a stream of noisy per-host commits.

Figure 2 – A non-interactive loop running Claude Code read-only against each host, committing hosts/
Keeping it honest
Where this earns its keep is in the moments documentation usually fails you. Running the inspection prompt before a change gives you a baseline to diff against afterwards. Running it during an incident postmortem tells you what was actually running at the time, not what the runbook claimed. Running it on a schedule turns a config audit from a quarterly scramble into something already done by the time someone asks for it.
None of that requires trusting Claude Code with more access than it needs. Keep it read-only until you have watched it behave correctly across enough hosts to be confident. Keep –allowedTools scoped to the commands you have actually verified. Let Git carry the history, because a commit log that shows exactly what changed and when is worth more than a wiki page nobody dares to edit.
The direction of travel is towards wider use rather than narrower. As the read-only pattern proves itself on inspection and documentation, the same discipline extends naturally to config audits ahead of an upgrade, to comparing a host against its peers in the same fleet, and to feeding a postmortem with a precise account of what was running rather than a reconstruction from memory. Start with one host, expand to the fleet once the pattern holds, and let the diffs do the documenting.