Command overview
beacon endpoint install configures the local endpoint agent, writes the OpenTelemetry Collector configuration, installs the collector service, configures selected agent harnesses, and optionally adds Splunk HEC or Falcon LogScale HEC collector destinations.
The service is a launchd job on macOS and a systemd unit on Linux. Where neither is available, Beacon runs a supervised collector instead and says so. See macOS or Linux for the platform setup, including the Linux packages and the --service flag.
Command syntax
--harness list disables automatic selection and configures only the runtimes it names: a hook-only list such as --harness omp leaves Claude Code’s and Codex’s settings untouched, and --harness "" installs the collector alone. If discovery finds no automatically installable runtime, Beacon installs the collector without changing any runtime configuration.
Discovery can also find runtimes whose collection path cannot be enabled safely by a machine-wide default. Beacon reports these without treating them as install failures: GitHub Copilot CLI needs launch-environment settings, Claude Cowork needs admin configuration, poll-only fx needs beacon endpoint fx sync, and OpenHands CLI/GUI coverage requires project-level hooks installed from inside each repository. Factory Droid’s hooks are installed automatically when Droid is detected, while its separate OTLP endpoint remains launch-environment managed.
The claude harness writes both Claude Code’s OpenTelemetry settings and its user-level hooks, because the OTLP export alone carries no session start or end, file activity, or subagent lifecycle; beacon endpoint hooks uninstall --harness claude removes the hooks again, and beacon endpoint hooks install --harness claude --level project adds project-level ones. A hook that cannot be written, for example into a settings file whose hooks key is not an object, is reported as a warning with the retry command; the endpoint itself is installed and endpoint install still exits 0. Codex uses OTLP logs plus one selective turn trace for tokens, and its required SessionStart hook adds local OS-user context. Beacon applies redaction, sanitization, truncation, and event-size limits before writing supported content fields.
Flags
Session backfill
After a successful install, user or system mode, Beacon reads the last 30 days of agent sessions from each runtime’s own session store into the runtime log, so the local dashboard has your recent sessions before any agent runs again. It is the same sweep each runtime’s sync command runs (beacon endpoint claude sync, codex sync, cursor sync, opencode sync, copilot sync,
cline sync, factory sync, pi sync, prime sync, hermes sync, devin sync, dsh sync,
fx sync, grok sync, harness2 sync, and integrations openclaw sessions sync), and its events carry
harness.collection_method=poll like theirs. It is local only and never touches the network.
The backfill is bounded so a machine with a lot of history cannot crowd live telemetry out of the
runtime log’s rotation window:
- Only sessions modified in the last 30 days are read, newest first.
- It writes at most 24 MiB in total, and no single runtime takes more than 12 MiB of that.
SUDO_USER or the logind seat on Linux, the console owner on macOS,
the active session on Windows). Its collector cursors stay under the system base directory. Because
root is reading a home that user controls, the read is confined to that home: a link that leads out
of it, a file the user does not own (including a hard link to someone else’s), and a FIFO, socket or
device are skipped rather than read, and install lists what it skipped. SQLite stores are read from
a private copy under the system base directory, retaken if the runtime rewrites its write-ahead log
mid-copy; a database larger than 512 MiB with its log is not copied, and install names the
runtime’s sync command to run as the user instead. A manual beacon endpoint <runtime> sync run as the user is not confined. When
nobody is logged in, install says the backfill was skipped and the next connect or manual sync
reads the sessions. --dry-run installs skip it, and --no-backfill or BEACON_BACKFILL=0 turn it
off. If this install also connects to Beacon Cloud, the same history is
uploaded by the connect.
Scheduled session sync
The session backfill runs once, at install. To keep reading the runtimes’ session stores after that, turn on the scheduled session sync:sessions enable and disable change only this setting and the job. install and repair take --session-sync and --no-session-sync too, but repair rebuilds the endpoint from its flags: run without the ones the endpoint was set up with, it resets the harnesses and OTLP ports and drops a Splunk or Falcon HEC destination. For a package or MDM rollout, set BEACON_SESSION_SYNC=1 in the environment of the package’s install script (/opt/beacon/scripts/install-endpoint.sh), or run /opt/beacon/bin/beacon endpoint sessions enable --system on Macs that already have Beacon. BEACON_SESSION_SYNC=0 turns it off, and leaving it unset keeps what the endpoint already has, so a package upgrade never changes it.
It is off by default. Hooks and OTLP already capture sessions live, and the session stores add what only they record, such as Claude Code’s per-request token usage and complete assistant text from its transcripts. Turning it on writes those records as poll events (harness.collection_method=poll) alongside the live ones, which matters when the runtime log is forwarded elsewhere. Token reports keep live usage authoritative over poll usage for the same session.
How it runs
- The job runs
beacon endpoint sessions syncevery 15 minutes:com.beacon.endpoint.session-sync(a LaunchDaemon in system mode, a LaunchAgent in user mode) orbeacon-session-sync.timeron systemd. The first run is 15 minutes after the job is loaded by the install, a repair, a reboot or a package upgrade, never at load. - Each run is the same sweep as the backfill above, with the same 30-day window, size budget and, in system mode, the same confined read of the console user’s stores. Each runtime’s cursor makes a run read only what is new. With nobody logged in, a system run reads nothing.
- In system mode a SQLite store (Cursor, OpenCode, Devin CLI, Hermes Agent) is read from a private copy, as the backfill does. A copy can approach 512 MiB and those runtimes are captured live by their hooks or plugins, so the scheduled job copies each one at most once an hour. A store over 512 MiB is skipped and named in the job’s output; run that runtime’s sync command as the user to read it.
- Only one sync runs at a time. An install, connect,
beacon endpoint sessions syncorbeacon endpoint <runtime> syncwaits for a sync already in progress and then reads only what it left. A scheduled run or a--watchsweep skips its turn while another sync is running, and--printdry runs never wait. - When the install or a later connect skipped the backfill (
--no-backfillorBEACON_BACKFILL=0), each runtime no sync had read yet is limited to sessions active since that skip, not the last 30 days. A session that continues past the skip is read from its start, a runtime that was already synced reads on from where it was, and a later backfill lifts the limit. - A user-mode job keeps the store locations the install saw (
CLAUDE_CONFIG_DIR,CODEX_HOME,COPILOT_HOME,XDG_DATA_HOME,OPENCODE_DBand the rest), because the scheduler does not pass a shell’s environment.
What to expect when you turn it on
The first runs catch up. When the backfill stopped at its size limit, the rest of the last 30 days is left for the job, and each run writes up to another 12 MiB per runtime (24 MiB in all) until it has read everything. After that, a run writes only what the agents recorded since the previous one. On a machine with a lot of agent history the catch-up takes a few runs, and because the runtime log rotates at 10 MiB and keeps five archives, it pushes older local events out of the log sooner than live telemetry alone would. A connected endpoint forwards the catch-up like any other new events.Settings and status
The setting issession_sync.enabled in config.json. Repair and package upgrades keep it, and beacon endpoint sessions disable or --no-session-sync turns it off and removes the job. A scheduled run also checks the setting, so a job left behind after the config was set to off reads nothing. beacon endpoint status shows Session sync: every 15m0s; job loaded=true, and beacon endpoint sessions sync runs the same sweep by hand. A host without launchd or systemd cannot run the job; run beacon endpoint sessions sync from your own scheduler there.
Interactive onboarding wizard
On a first interactive install the onboarding wizard signs in through beacon.sh, then asks where this machine’s telemetry should go:--connect presets Beacon Cloud and skips the destination question. Whether
connect was chosen in the wizard or by the flag, a failed enrollment leaves the
completed local install exiting successfully and prints beacon endpoint connect as
the retry command. Automation should verify
.managed_ingest.connected with beacon endpoint status --json.
BEACON_MANAGED_INGEST=0 hides the managed answer. The wizard is never shown
for system/root, package, MDM, CI, dry-run, or redirected-input installs.
Customer-managed destinations remain available through the
log forwarding packs after choosing Local.
Examples
Install with the default per-user paths:Install with the default per-user paths
Install without starting the collector service
Configure only one harness
Configure an exact harness list
Configure all supported integrations
Configure VS Code Copilot telemetry
Configure Devin CLI and Devin Desktop hooks alongside the default OTLP harnesses
Include low-level runtime OTLP metrics that are filtered from JSONL by default
Include raw Codex spans for troubleshooting
Install with system paths for a root-managed package or MDM deployment
Install and forward to CrowdStrike Falcon LogScale HEC
Configure Factory Droid's OTLP endpoint through MDM or another customer-owned launch policy
Configure GitHub Copilot CLI's OTLP endpoint through MDM or another customer-owned launch policy
Install runtime hooks
endpoint install. Add project-level hooks, or re-add user-level ones after removing them:
Add Claude Code hooks to a project
Install Grok Build hooks at the user level
Install Hermes Agent hooks at the user level
config.yaml in the Hermes home directory, which follows HERMES_HOME and the active profile (default ~/.hermes/config.yaml; see Hermes home and profiles), and support user-level installs only.
Install Qwen Code hooks at the user level:
Install Qwen Code hooks at the user level
~/.qwen/settings.json. Qwen Code has no OpenTelemetry export to configure, so qwen is a hook harness on this command too: beacon endpoint install --harness qwen installs the same hooks and writes ~/.qwen/settings.json.
Project-level Grok Build hooks write ./.grok/hooks/beacon-endpoint.json and require /hooks-trust in Grok before they execute:
Install project-level Grok Build hooks
System-mode install (
--system) is supported on macOS and on Linux distributions that use systemd. Omit --system for the default non-root local install. GitHub Copilot CLI and Factory Droid OTLP use launch-environment settings rather tha Beacon-managed shell-profile edits.Restricted log access
A system-mode endpoint keeps one runtime log,/var/log/beacon-agent/runtime.jsonl, for every user on the machine. By default the log is shared: hooks run as each logged-in user and append to it directly, so the file is 0666. That also means any local account can truncate or rewrite the log, and read every other user’s prompts, command output and diffs.
--log-access restricted makes the collector the only writer:
Install with restricted log access
- Hooks send their events to the collector over a local Unix socket,
/var/run/beacon-agent/ingest.sock, instead of writing the file. Nothing leaves the machine. - The collector records each event under the account the operating system says sent it, not the account the event claims.
- The log directory becomes
root:beacon-logmode2750, the log and its archives0640, and its lock0600. Only the collector writes the log; only root and members of thebeacon-loggroup read it. Switching an existing log to restricted replaces its files with fresh copies, so a handle another account opened while the log was shared stops reaching it. - If the collector is stopped or restarting, hooks keep their events in a private spool in each user’s home (
~/.beacon/endpoint/spool,0600) and send them with the next event once the collector is back. The agent is never held up.
beacon-log group when it is missing and adds nobody to it. Add each account that should read the log, such as a log shipper’s service account, then restart that shipper:
Let a log shipper read a restricted log
config.json as log_access, and in a root-owned .beacon-log-access marker beside the log. beacon endpoint repair, package upgrades, the Jamf repair-hooks.sh policy, and a reinstall after uninstall --keep-logs keep it. To go back, run sudo beacon endpoint repair --system --log-access shared; the log is writable by every account again at once. For package installs, set BEACON_LOG_ACCESS=restricted in the environment of the package’s install script.
What this does and does not change:
- Local accounts can no longer alter or delete events already in the log, or read other users’ sessions.
- Every event that arrives over the socket records the account that sent it, as the operating system reports it. A user still controls their own agent, so they can still send events of their own choosing, including ones that name another session’s id, but always under their own account.
- The collector’s OTLP ports on
127.0.0.1still accept telemetry from any local process, as they do in the shared mode. Agents that export over OTLP, such as Claude Code and Codex, use them. Events that arrive that way are not attributed by the operating system.
beacon endpoint dashboard, beacon scan, beacon traces, and the session lookups in beacon share, beacon handoff and beacon git commit linking) see it only when run as root or by a beacon-log member. beacon endpoint doctor connects to the socket and reports a collector that is not answering on it, including one that was killed and left its socket behind, and any events waiting in the caller’s spool. On Windows the mode works the same way with Windows mechanisms: hooks send to the named pipe \\.\pipe\beacon-agent-ingest, the log directory’s ACL gives SYSTEM and Administrators full control, the beacon-log local group read and nobody else anything, events record the sender’s SID and account name, and the commands run from an elevated shell (see On Windows). For how the mode fits with log shippers such as Microsoft Sentinel, and what it does and does not protect, see Restricted log access.
Running user and system mode together
A user-mode collector can run beside a system-mode one on the same machine when the two use different ports. Give the user install its own OTLP ports; its health-check port moves with them:Install a user-mode endpoint beside the system one
127.0.0.1:4327, 127.0.0.1:4328, and health check 127.0.0.1:13143. Pass --health-port to choose the health-check port yourself. The port is recorded as collector.health_port in config.json, and beacon endpoint status checks the recorded port. A config written before the field existed has no health_port and keeps using 13133.
If a port the collector needs is already taken, the install stops before it writes anything and names that port. If the collector starts but exits before it is ready, the install error quotes the collector’s last error line and gives the path of its log, then rolls back.
Related
Endpoint status
Inspect collector health, runtime log state, harnesses, diagnostics, and forwarding readiness.
Runtime hooks
Install hook-based telemetry after the endpoint collector is configured.