Skip to content

Quickstart

Nothing needs to be listening. The demo prints what was caught from the local ledger, so there is no collector, no container runtime, and no dashboard between you and a first result.

Two commands

# 1. Prerequisites and host checks. Downloads nothing.
./scripts/install.sh

# 2. The full demo: local model stub + rogue agent + sensor
./scripts/demo.sh

demo.sh starts an Ollama-compatible local model stub, a simulated unsanctioned agent, and the sensor — then reads back the findings the run recorded.

Run the pieces separately

Watching each component gives you a much better feel for what the sensor is actually doing.

./scripts/run-sensor.sh --verbose

--verbose logs a line per poll, which is the fastest way to confirm the loop is acquiring processes and sockets.

# Terminal 1 — the sensor
./scripts/run-sensor.sh --verbose

# Terminal 2 — the thing it should catch
python3 simulators/rogue_agent.py --iterations 0

# Terminal 3 — an Ollama-compatible stub on :11434
python3 simulators/local_runner_sim.py

--iterations 0 runs until interrupted. The rogue agent burns CPU, reaches provider endpoints, and walks the host-plane tactics in order.

# Terminal 1
./scripts/run-collector.sh

# Terminal 2
./scripts/run-sensor.sh --verbose

Requires ./scripts/install-otelcol.sh first. Only needed when you want the Collector's processing — see OTLP export.

Full coverage

Unprivileged you see the whole process table but only your own sockets. With sudo you get every user's sockets, plus the DNS sniffer for exact hostname attribution:

sudo ./scripts/run-sensor.sh --dns-sniffer

Add --esf for the host plane — credential access, identity creation, privilege escalation, and launch-item persistence:

sudo ./scripts/run-sensor.sh --esf --dns-sniffer

Confirm Endpoint Security will admit the process

--esf needs root and, on many builds, Full Disk Access granted to the terminal application running the sensor. Run --self-test first; it translates the underlying error into a checklist. See Install.

The full local stack

For Loki, Grafana, and the sensor with host-plane coverage in one command, use scripts/ShadowclawAI. Observability binaries live under ~/.shadowclaw-o11y by default, and the sensor step uses sudo internally for --esf and --dns-sniffer.

bash scripts/ShadowclawAI start      # Loki, then Grafana, then sensor
bash scripts/ShadowclawAI status     # pid + HTTP health for each component
bash scripts/ShadowclawAI stop       # sensor, Grafana, Loki (in that order)
bash scripts/ShadowclawAI restart    # stop, then start

On success, start prints Grafana at http://127.0.0.1:3000, the ShadowClaw dashboard URL, and log paths under ~/.shadowclaw-o11y/logs/.

Environment variables

Variable Default Effect
SHADOWCLAW_O11Y_DIR ~/.shadowclaw-o11y Where Loki and Grafana are installed.
SHADOWCLAW_ESF 1 Set to 0 to start without Endpoint Security.
SHADOWCLAW_DNS_SNIFFER 1 Set to 0 to start without the DNS sniffer.
SHADOWCLAW_SENSOR_ARGS (empty) Extra arguments appended to the sensor command.
PYTHON python3 Python interpreter used for the sensor.
# Host plane off — planes A and B only, no sudo prompt
SHADOWCLAW_ESF=0 bash scripts/ShadowclawAI start

# Custom config and a higher reporting threshold
SHADOWCLAW_SENSOR_ARGS="--config config/shadowclaw.json --min-risk 50" \
  bash scripts/ShadowclawAI start

Bounded runs

For a scripted check or a CI gate, stop the sensor deterministically instead of interrupting it:

python3 -m shadowclaw --duration 90          # stop after 90 seconds
python3 -m shadowclaw --cycles 10            # stop after 10 polls
python3 -m shadowclaw --interval 5 --cycles 6

Read what it found

python3 -m shadowclaw --ledger                 # readable summary
python3 -m shadowclaw --ledger --since 30m     # filter by age
python3 -m shadowclaw --ledger watch           # live, plain English

make ledger, make watch, make ledger-verify and make ledger-report wrap the common ones. Full detail in The local ledger.

Next