Skip to content

Install

There is no pip install. The sensor has no third-party dependencies, so a checkout plus the python3 macOS already ships is a complete installation.

Requirements

Requirement Detail
Operating system macOS. Tested on 26.5.2, Apple Silicon.
Python 3.9 or newer. The stock /usr/bin/python3 is fine.
Base tooling ps and lsof from the base system.
Plane C additionally /usr/bin/eslogger (macOS 13+), root, and Full Disk Access.
Collector (optional) OpenTelemetry Collector contrib 0.158.0, downloaded on request.

Run the host checks

./scripts/install.sh

install.sh downloads nothing by default. It documents everything that is easy to get wrong on a fresh Mac:

  • which Python binary needs Full Disk Access for --esf
  • why sudo python3 is often not the same binary as python3
  • the OTLP endpoint choices — Loki direct on :3100/otlp versus a collector on :4318
  • what root versus unprivileged coverage actually includes
Flag Effect
--check Report prerequisites and exit without changing anything.
--with-otelcol Also download and verify the OpenTelemetry Collector.
--skip-otelcol Accepted for compatibility; a no-op now that the Collector is opt-in.

make help lists every one of the 24 Make targets.

Confirm what the host will actually see

--self-test reports platform capability, host tooling, whether Endpoint Security will admit this process, and a live acquisition sample. Run it before you commit to a deployment.

python3 -m shadowclaw --self-test

platform
  os        : macOS (darwin)
  plane     : inference heartbeat via ps(1)
  plane     : shadow egress via lsof(8) and tcpdump(1)
  plane     : agent actions via Endpoint Security (eslogger) (root)
  coverage  : 3 of 3 planes

host tooling
  ps        : /bin/ps (ok)
  lsof      : /usr/sbin/lsof (ok)
  eslogger  : /usr/bin/eslogger (ok)
  euid root : False

endpoint security
  status    : UNAVAILABLE -- not running as root
  re-run under sudo
  credential access, identity creation, privilege escalation and launch-item
  persistence will NOT be detected on this run
  agent-config persistence and public exfil surfaces still work -- they need
  no privilege

self-test: DEGRADED

DEGRADED here is the honest answer for an unprivileged run, not a failure. It names which half of the coverage is missing rather than leaving you to infer it.

The OpenTelemetry Collector is optional

Loki 3.x accepts OTLP natively at /otlp/v1/logs, so the sensor can post straight to it with nothing in between. The contrib Collector build the shipped pipelines need is a 329 MB download, so it is opt-in:

./scripts/install-otelcol.sh

The download is verified against the upstream SHA-256. You want the Collector only if you need a collector's processing — routing, batching, fan-out to several backends — or if you are running make validate against config/otel-collector.yaml.

Two collectors cannot share a port

DefenseClaw's bundled collector and ShadowClaw's both want 127.0.0.1:4317 and 127.0.0.1:4318. Only one can run at a time. See DefenseClaw integration.

Full coverage needs root

Unprivileged, you already see the whole process table but only your own sockets — enough to validate the detector, not enough to police a machine, because attribution needs both halves for the same pid.

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

Root also unlocks the host plane, --esf, which is where credential access, identity creation and privilege escalation become visible at all.

Full Disk Access

Endpoint Security refuses a client that lacks Full Disk Access, with an error that names neither Full Disk Access nor System Settings.

When you run the sensor from a terminal, eslogger(1) checks the terminal application — Terminal, iTerm, Cursor — for FDA, not Python alone.

  1. Grant Full Disk Access to that app in System Settings → Privacy & Security → Full Disk Access.
  2. Fully quit and reopen the app. A restart is required; a new window is not enough.
  3. Confirm with sudo eslogger exit.

For a launchd daemon, grant FDA to the bundled interpreter named in the plist instead. packaging/README.md covers that case.

--self-test translates the underlying error into this checklist, so use it to confirm rather than guessing.

A Mac with no developer tools

packaging/ builds a .pkg inside a .dmg that carries its own Python 3.13 runtime.

./packaging/build.sh          # -> packaging/dist/ShadowClaw-1.5.1.dmg

The package is unsigned, so the first attempt to open it is refused by Gatekeeper — right-click the .pkg and choose Open. Installing lays down /usr/local/bin/shadowclaw and starts nothing: the root LaunchDaemon is a separate opt-in, and uninstalling deliberately leaves the ledger behind.

Next