Skip to main content

Command overview

beacon share publishes one local agent session as a shared trace on beacon.sh and prints its link. The trace shows the session’s prompts, the agent’s answers and reasoning, and every tool call with its result, in order. For a walkthrough of every way to share (from the CLI, an agent skill, auto-share, git hooks or CI), see Sharing sessions.
Command syntax
Without a session flag, beacon share shares the session it runs inside (see Sharing this session), and otherwise the most recent session that ran in the current directory. It names the session it picked before uploading anything.
Share the session you just finished here
From inside an agent: share this session
See what would be uploaded, without uploading it
Sharing is always something you ask for. Hooks, plugins and background jobs never upload a session, with one exception you turn on yourself: after beacon git setup --share-sessions, the git pre-push hook shares the sessions linked to the commits you push, during that push, within the hook’s time budget and never failing it. Nothing else in Beacon uploads session content to beacon.sh except Beacon Cloud forwarding when you connect an endpoint. Auto-share, which you turn on, asks Beacon Cloud to publish sessions from the events forwarding already sends.

Choosing the session

--current, --session, --source-path and --cwd cannot be combined. --list shows the candidates instead of sharing, newest first, and takes --cwd, --harness and --limit (default 20, 0 for all).
List and pick
Sessions are read the way beacon handoff reads them: from the runtime’s own session store when Beacon reads that runtime’s store, which keeps the most of each step, and otherwise from Beacon’s runtime log. --store-dir <runtime>=<path> reads a store from another location, and --log-path reads another runtime log.

Sharing this session

An agent asked to “share this session” runs beacon share from its own shell, where it does not know its session id. --current, which is also what beacon share does with no selector, finds it in this order:
  1. BEACON_SESSION_ID (with BEACON_HARNESS). Beacon’s Claude Code SessionStart hook appends export BEACON_SESSION_ID=<id> and export BEACON_HARNESS=claude_code to the file Claude Code names in CLAUDE_ENV_FILE, which Claude Code runs before each shell command of the session, so every command the agent runs carries its session id. Any other launcher may set the two variables too. The step is skipped under --cwd, and when --harness names another runtime, because a runtime started from a Claude Code shell (Codex, OpenCode, Cursor, …) inherits Claude Code’s variables. For the same reason, without --harness the variables are trusted only when nothing contradicts them: beacon share refuses, naming both sessions, when the session they name ran in another directory (not this one or a directory above it), or when another runtime has worked in this directory more recently than that session (in the active-session record or the sessions listed here). Pass --harness <runtime> for the runtime you are in, or --session <id>. --harness naming the variables’ own runtime takes them as they are. An id that is set but cannot be read is an error, never a reason to share another session, and so is an id set without BEACON_HARNESS or with a BEACON_HARNESS that names no runtime Beacon knows: set both, or name the session with --session.
  2. The active-session record. Every Beacon hook notes, per runtime and working directory, the session it last saw, in ~/.beacon/endpoint/active-sessions.json (0600 under a 0700 directory). The record holds session ids, runtime names, directories and times, never content, and nothing in it leaves the machine. It keeps at most 256 entries and drops any not seen for 14 days; --current uses an entry seen within the last day, and only when it was seen at least as recently as the directory’s newest session was updated: only hooks write the record, so a runtime Beacon sees only through OTLP or its session store (GitHub Copilot CLI, fx) never updates it, and its newer session wins over an older entry.
  3. The most recent session that ran in the directory.
--harness narrows every step to one runtime, which matters when two runtimes worked in the same directory. When nothing ran in the directory, the error names the most recent sessions elsewhere so one can be passed with --session. --json reports how the session was chosen in selected_by: env, active, recent, session or source_path.

What is uploaded

A shared trace is a beacon.trace.v1 trace: the same projection of the session’s Beacon events that the local dashboard and lenses read. It has two parts:
  • A summary: the runtime and its version, the session id, the title, when the session started and ended, the models, token usage, the project name and repository, and how much content was retained.
  • The events, in order. Each Beacon event of the session becomes one trace event with a stable id, its number, timestamp, type (user_message, agent_message, agent_reasoning, tool_call, tool_result, command, file, mcp, approval, token_usage, session, error, …) and the fields that event carried: prompt or answer text, the tool with its arguments and result, the command with its exit code and output, the file path and diff, the MCP server and tool, the approval or policy decision, the model and token usage, and the tool_call_id and prompt_id that tie a call to its result and an action to its prompt.
beacon.sh derives the chat view from those events: a tool invocation and its completion become one call and its result, and a call reported by more than one capture path is shown once. Lenses run on a shared trace with the same data they get locally. Beacon’s own bookkeeping and status telemetry (heartbeats, inventory, metric datapoints without token usage, the session.shared record) is not uploaded. Before anything leaves the machine:
  • Every event goes through the same secret redaction and size limits the runtime log applies.
  • Paths under the session’s directory are written relative to it, and your home directory becomes ~, in file paths, commands, output and diffs.
  • The session’s working directory and the repository path are left out of the summary. The repository remote (from the session’s events, or else the origin remote in the session’s directory, read locally) is sent without credentials, and project.name is the repository’s or the directory’s name, never a path. The name of your home directory is not used as a project name.
  • A session started from a handoff names the session it continues (related_to, with relationship_type handoff), and a subagent’s session names its parent’s (subagent), by their external ids.
  • Token usage is the session’s total as beacon token-usage counts it. Cost is sent only when the runtime reported one, never a list-price estimate.
beacon.sh redacts every string again on its side. Redaction catches common credential shapes, not everything sensitive, so read --print before sharing a session that touched secrets.

Metadata-only endpoints

When this machine forwards to Beacon Cloud in Metadata-only privacy mode (user or system mode), beacon share leaves out what forwarding leaves out, so a share never sends more than the endpoint’s privacy mode allows. The trace keeps the session’s shape: event types and order, tool and command names, command lines, file paths, MCP servers and tools, approval and policy decisions, models, token usage and the ids that tie events together. It has no prompt text, answers or reasoning, tool arguments or results, command output, diffs, raw payloads, or approval and policy reasons. The title is not taken from the session either, because most runtimes title a session with its first prompt; pass --title to give the trace one. Event ids are the same in both modes, so sharing a session again with beacon share after the endpoint switched to Metadata-only upserts the events already on beacon.sh rather than adding copies; refresh sends only the newer ones. This applies to beacon share, refresh, --follow and the git pre-push hook. On a machine connected in system mode, these commands read the privacy mode from the system config.json, because the enrollment record is readable only by root; when neither can be read, they share as Metadata-only. Run --print to see the result. --print (or --dry-run) prints exactly that payload as JSON and sends nothing: the external id the requests go to, trace (the body of PUT /v1/traces/{external_id}) and events (every event the POST /v1/traces/{external_id}/events/batch requests would carry, at most 1,000 per request):

Visibility

A public share asks for confirmation. Without a terminal to ask on, it is refused unless you pass --yes. Sharing a session again updates the same trace: each session has one stable external id (<runtime>:<session-id>), and every event has a stable id (its Beacon event.id), so nothing is duplicated. A re-share keeps the trace’s visibility unless you pass --visibility. Change a trace’s visibility by sharing it again with --visibility, or from the beacon.sh dashboard, where you can also delete it.

Refresh

beacon share refresh uploads only the events a shared session has gained since it was last uploaded. beacon.sh reports the last event it has, and the events after it are sent, together with that event and everything from the earliest tool call it holds without a result. When that event is not in the session as Beacon reads it now, every event is re-sent, which changes nothing that was already there. The trace’s summary is updated; its visibility is not changed.

Follow a running session

--follow keeps the trace current while the session runs. It shares the session, then checks it again every --interval (default 10s, at least 1s) and uploads what changed, until the session records its end (session.ended, in the runtime’s store or in the runtime log, where the hooks write it; a resumed session’s earlier end does not count once newer activity follows it) or you press Ctrl+C. A check is a local read; a request is made only when the session’s trace events changed, and it sends only the events beacon.sh lacks, the same way refresh does. A failed upload after the first is reported and retried on the next check. When the session has ended and its last events cannot be uploaded, --follow retries three more times, one interval apart, and then exits non-zero naming what the trace holds. If the runtime log cannot be written after an upload, --follow warns and keeps going. A check that cannot read the session is reported once per distinct error, and after five failed checks in a row --follow exits non-zero.
--follow waits for a session that has nothing to share yet. The link is printed after the first upload; with --json, each upload prints one JSON document per line, and the last carries "final":true (and "ended":true when the session ended). The runtime log gets one session.shared event when the trace is first shared and one after each later upload that sent events (a refresh, which keeps the share date), so the dashboard does not show a followed session as out of date. --follow cannot be combined with --print or --list.

Auto-share

beacon share auto enable publishes new sessions without running beacon share each time. It works through Beacon Cloud forwarding, never from the hooks over the network:
  1. On the first event Beacon’s hooks see for a session (its SessionStart where the runtime has one), they write one session.share_requested event to the local runtime log, with the session id, runtime and the chosen visibility in share.visibility. One per session: the hooks remember which sessions they requested in ~/.beacon/endpoint/active-sessions.json.
  2. Forwarding ships that line with the rest of the runtime log.
  3. beacon.sh creates the shared trace from the session’s forwarded events with the same beacon.trace.v1 projection beacon share uses (redaction and path rewriting included), and keeps it current as more arrive. Its external id is the one beacon share uses (<runtime>:<session-id>), so a session shared both ways is one trace.
enable warns when the endpoint is not connected to Beacon Cloud, because then nothing is published (the event is written and stays local), and when forwarding is in metadata-only mode, because the trace then has no prompts, answers, reasoning or tool output. --visibility public lists every new session in Discover; it asks first, and without a terminal it is refused unless you pass --yes. Sessions already running are requested on their next event; earlier sessions are not, so share those with beacon share. Turning auto-share off stops new requests; traces already published stay until you delete them on beacon.sh. disable without --project turns it off everywhere: it overrides every project you enabled with --project, which it names, without changing their settings, so a later enable brings back exactly what was on before. disable --project <dir> turns off only that project. enable --project <dir> while it is off everywhere clears that switch (other sessions stay off) and says so. The setting is in ~/.beacon/endpoint/share.json (0600). --project <dir> applies the choice to one project: it is recorded there for you by path, and <dir>/.beacon/share.json records it in the repository so it can be committed. A project file can turn auto-share off on its own, and an off file wins over your own setting for the same directory, so a repository that opts out stays out for everyone; it turns auto-share on only for someone who ran beacon share auto enable --project in that project, and the visibility always comes from that person’s own setting. A cloned repository can never publish your sessions. The nearest directory with a choice (yours or the repository’s) decides, so a setting you made for a subdirectory applies there even under a parent repository’s opt-out; elsewhere, the setting for every session does. The off switch for every session overrides all of it. status shows which applies in the current directory (or --project) and why, the setting for every session (on, off or not set), each project you set and whether the off switch overrides it, and the forwarding state; --json prints it as a document. The session.share_requested event is marked event.fidelity=inferred because Beacon originated it rather than a runtime reporting it, and it is not itself part of any shared trace.

Credentials

beacon share uses, in this order:
  1. A Beacon API key passed with --key (bcn_api_...).
  2. Your beacon login sign-in, when it carries the traces:write permission.
  3. A Beacon API key in BEACON_API_KEY.
A sign-in from an older beacon login lacks traces:write; run beacon login again.

API keys for CI and other headless machines

Where nobody can run beacon login (CI runners, containers, scheduled jobs), use a Beacon API key:
  1. On beacon.sh, create an API key with the traces:write permission. It starts with bcn_api_.
  2. Store it as a secret in your CI system, for example a GitHub Actions secret or a masked GitLab CI/CD variable named BEACON_API_KEY.
  3. Expose it to the step that runs beacon share as the BEACON_API_KEY environment variable. Prefer the variable to --key, which puts the key on the command line where process listings can see it.
  4. Run beacon share in the same job as the agent, after it: the session is read from the runner’s own disk.
With no sign-in on the machine, BEACON_API_KEY is used. On a machine that also has a sign-in carrying traces:write, the sign-in wins unless you pass --key. A key for a self-hosted Beacon service goes with BEACON_AUTH_URL (or --auth-url) set to that service. An API key is sent to beacon.sh, or to --auth-url / BEACON_AUTH_URL when set. Either credential goes only in the request’s Authorization header, redirects are refused, and neither is printed.

Where the requests go

beacon.sh serves its API from https://api.beacon.sh, so a beacon.sh sign-in or key sends the three trace requests there. Any other service gets them at its own URL (the one you signed in to, or --auth-url / BEACON_AUTH_URL). BEACON_API_URL names the API outright, for a service whose API is on another host; it must be https://, or http:// on loopback. When the host answers with a web page’s 404 instead of the API’s own reply, beacon share stops with <url> has no trace API (HTTP 404: endpoint not found) and creates nothing.

CI examples

These run an agent and share its session in the same job. Claude Code and Codex CLI keep their sessions in stores beacon share reads directly, so nothing else needs to be installed. For a runtime whose sessions Beacon reads only from its runtime log, start Beacon CI telemetry before the agent and pass the CI log with --log-path. Without a terminal, --visibility public needs --yes; the default, direct, makes the trace viewable by anyone with the link.

GitHub Actions

.github/workflows/agent.yml
The URL reaches the script through an environment variable rather than being written into the script, so nothing in the share output can change what the script runs. Sharing failures leave the job green (exit 0); drop that to make a missing trace fail the build. Share after the agent finishes, as above, rather than with --follow: --follow needs the session to exist when it starts (it exits with “no agent session found” otherwise), and most CI runners stop background processes when the step that started them ends. Keep --follow for watching a session from your own terminal, or for a step that runs it alongside the agent and waits for it.

GitLab CI

.gitlab-ci.yml
after_script runs in the same job even when the agent fails, so the session is still on disk.

Local record

After an upload, beacon share writes one session.shared event to the runtime log, in the session’s own timeline. It carries the link, the visibility and when the session was shared (and refreshed), so beacon endpoint traces list --state shared and the local dashboard show the session as shared. A shared session with newer local activity shows as stale; --state shared still lists it, and --state stale lists only those. The event is marked event.fidelity=inferred and has no collection method, because no runtime reported it. It is not itself uploaded with the trace.

Output

The link goes to stdout and a summary to stderr. --json prints one document:
event_count is how many events the trace holds on beacon.sh, and uploaded how many this run sent. On failure, --json prints {"ok":false,"error":"..."} and the command exits non-zero.

Flags

refresh takes --harness, --cwd, --title, --key, --auth-url, --print, --json, --store-dir and --log-path.