Skip to main content

Connect reference

What Connect writes and runs on a machine, for security review and fleet operations. Connect's runtime runs per user, without privilege. Native packages and system-wide managed-enrollment bootstrap files are installed by IT with administrator privileges; managed --write also needs privilege for fleet policy. Connect installs no CA certificates, machine-wide proxy, DNS changes, or kernel extension. Nothing sits in the request path: tools call the gateway directly, so Connect never sees their method, path, body, or response.

What lands on the machine

CLI state lives in ~/.anyray/ (override the root with $ANYRAY_HOME), created mode 0700; the two files holding credentials are written 0600.

PathWhat it is
bin/anyray-connectThe managed standalone binary. Every hook, MCP registration, and service points at this one stable launcher.
versions/<version>/Previously installed versions, kept so an update can roll back.
connect.jsonThis machine's profile: gateway address, your name and team, which tools are configured. Mode 0600.
dev-key.pemThe device private key that proves this machine's identity when renewing your gateway key. Mode 0600, never logged or printed.
logs/connect-refresh.logCaptured output from scheduled key renewal, where installed. Error names only, no request data. macOS only; Linux logs to journald.
vscode-extension/, vscode-receipts/The bundled Anyray VS Code extension and a receipt per applied install.
openclaw-plugin/The OpenClaw plugin. The Anyray repository is private, so Connect is its distribution channel.
hook-tee/Recovery copies of replaced tool output. The re-read policy writes only when emitting a stub. Owner-only, never uploaded, kept 30 days after the last reference, 90 days at the outside, and 128 MiB in total. ANYRAY_HOOK_TEE=off disables it.
hook-cache.jsonOptimization verdicts for outputs already seen, so a repeat skips a second round trip. 24 hours, 200 entries. ANYRAY_HOOK_CACHE=off disables it.
hook-policy-state.jsonExperimental source-trim counters and bounded session metadata. Stores hashes, handles and tool-call numbers, never file paths or content. Mode 0600.
hook-policy-observation-gapA bookkeeping failure is awaiting recovery. The next successful metadata write resets read history and clears the signal; the cumulative gap counter survives. Contains no content.

The desktop inventory has four categories: the installed app and its bundled engine, the OS login registration, the local profile, and the resident engine process. These are categories, not a four-file limit. Tool integrations, logs, update staging and supporting state remain part of the security inventory.

On macOS 13 or later, login uses Apple's Service Management registration. Windows uses the per-user Run entry; Linux uses the desktop autostart entry. Desktop maintenance runs in the bundled engine on the app's timer, without a separate refresh scheduler. Quitting the app stops renewal until it runs again; it does not remove the login registration. Disabling that registration in OS settings stays effective after reopening the app.

Upgrades retire the old macOS tray job after ownership and native login state are recorded. A short-lived bundled engine worker survives unloading the old job by using a separate process group. Interrupted removal leaves a .plist.retiring marker for retry. IT handles system-wide enrollment bootstrap cleanup separately from this per-user migration.

The running tray reads the login setting every 15 seconds. Changes are saved and reported when detected; unchanged observations are checkpointed every five minutes. Machines shows the last reported native setting and its original timestamp per user. An observation becomes stale after 15 minutes, even if other seat activity continues. Disabled, unknown and stale login settings do not lower routing compliance. These reports use the existing client key without minting a replacement or running maintenance. The gateway's existing renew-on-use rules still apply when it authenticates that key. Older gateways ignore this additive observation; upgrade the gateway to see it.

Maintenance runs every 30 minutes and immediately on ownership handover. If scheduler teardown fails, retries back off from one to 30 minutes. A successful maintenance pass can authorize teardown-only retries for 30 minutes; after that, maintenance runs again.

Seams inside your tools

Beyond each tool's base URL and key, these are the named seams Connect writes. Each carries an ownership marker, so a re-run is idempotent and --revert removes exactly what Connect added, leaving anything it doesn't own untouched.

SeamWhereWhat it does
PostToolUse hook~/.claude/settings.jsonTrims oversized tool output at the source, before it enters the transcript. Size-gated inside the hook.
PostToolUseFailure hook~/.claude/settings.jsonObserves Edit failures for the experimental re-read policy; forwards failures unchanged.
Lifecycle SessionStart, PreCompact, SessionEnd hooks~/.claude/settings.jsonRecord session lifecycle support and clear experimental re-read records and pending windows. Aggregate counters survive.
UserPromptSubmit hook~/.claude/settings.jsonRecords a paste beacon for attribution.
Key-refresh SessionStart hook~/.claude/settings.jsonSubscription mode only: re-mints a short-lived key at session start, so it can't lapse mid-session. Runs async, never delaying startup.
anyray MCP server~/.claude.json under mcpServersThe retrieval server, described below. Re-invokes the same binary over stdio.
Cursor hooks and MCP~/.cursor/hooks.json, ~/.cursor/mcp.jsonCursor's native Team mode: the local Shell, Read, and MCP optimization seams, plus the same anyray retrieval server.
Managed shell block~/.zshrc, ~/.bashrc, or ~/.profileBase-URL environment variables, fenced by # >>> anyray connect >>> and # <<< anyray connect <<< so the rest of your profile is never rewritten.
VS Code extensionVS Code's own extension storeInstalled from the bundled VSIX through the VS Code CLI; its credential goes to VS Code SecretStorage, not to a file.

The retrieval MCP server

The retrieval server is what makes an optimizer trim reversible: where a strategy replaces bulk with an opaque ctx_… handle, these are the read paths that fetch the detail back. Every client gets anyray_retrieve and anyray_recall, plus anyray_history where that archive has content. Clients whose native search and read output cannot use Anyray's replacement hook also get anyray_search and anyray_read. Claude Code does not advertise those two context tools: its native Grep and Read already pass through the PostToolUse optimizer, so a fresh session does not duplicate its first-turn exploration through MCP.

After initialization, the stdio server sends a content-free liveness heartbeat every 5 minutes until the transport closes. The gateway expires that evidence after 6 hours without verified activity, so a stopped server automatically disables fresh handle-producing strategies.

ToolWhat it does
anyray_retrieveFetch the full original behind a known ctx_… handle.
anyray_recallSearch the durable stash semantically when the handle has scrolled out of view, returning ranked handles.
anyray_searchSearch the local workspace and return file:line candidates, ranked and trimmed against the query.
anyray_readRead a workspace file, returned as a relevant slice the model can top back up rather than a lossy cut.
anyray_historySearch your own past context. Advertised only where that archive has content.

Every result is capped before it leaves the MCP server. If a read reaches the limit, it stops at a line boundary and names the next startLine; a search drops the lowest-ranked tail and reports how many matches were omitted. This prevents an MCP host from rejecting the entire result before the gateway hook can optimize it.

Claude Code source trims

Managed Claude settings include the source hook in both credential lanes. Deferred SSO and an explicit fleet binary use the command hook. Without a binary, Connect emits a native HTTP hook with the client key read from the host environment, never embedded in the fleet file.

Managed command hooks require current-session retrieval proof and verify the actual handle before emitting a replacement. They keep original output on failure or after two seconds. HTTP hooks currently stand aside because their event cannot prove session retrieval. Existing content-mode controls still govern gateway capture.

HTTP hooks also cannot invoke Claude's apiKeyHelper. If the credential exists only in that helper, authentication fails open to original output. Local managed --write selects a durable Connect binary automatically; fleet --print uses only the binary explicitly supplied by IT.

doctor and status --json expose sourceHook: installation is command, http, missing, or unknown; retrieval is verified, not_seen, or unknown. A recent report appears separately on the console's Agents row. Missing reports and older gateways never mean a hook is absent.

Two independent experiments live under hookPolicies in the existing Connect profile, ~/.anyray/connect.json (or the legacy ~/.anyray file). Merge these fields into the profile; keep other settings. No environment variable enables them.

Connect profile fields
{
"hookPolicies": {
"greenCollapse": false,
"rereadStub": false
}
}

Set only the policy being benched to true. Each hook reads the switches afresh; setting one back to false stops that policy on the next invocation. Both default to false. Opt-in repairs older hook settings for future sessions. Re-read stubs require a lifecycle receipt from this session’s SessionStart or PreCompact hook; an already-running session without one declines.

SwitchWhen it can hide output
greenCollapseBash ran a recognized test, lint, build or type-check command, reported numeric exit code zero, and printed a recognizable summary. Keeps the runner's summary lines, warning paragraphs, and all stderr.
rereadStubRead returned the same absolute path, offset and limit as an earlier Read in this session, with matching SHA-256 hashes of the whole file and returned region. First and changed reads continue through the shipped hook.

Green collapse recognizes commands such as go test, golangci-lint run, pytest, vitest, jest, tsc, cargo test, make test, and eslint, including common package-runner wrappers. It hides only recognized progress rows. Benchmark, verbose, debug, coverage, duration and reporter flags decline; unaccounted rows such as asset-size tables also decline. It accepts cd … && and chains of recognized runners, but declines pipelines, ||, shell program strings and unsupported syntax. Nonzero, missing, conflicting or interrupted exit status, or any failure marker (including FAIL, panic, Error, Traceback, not ok, or an assertion diff), declines to the shipped hook. No recognizable summary also means no collapse. Every decline preserves the existing digest, gateway and local trim pipeline.

Claude Code 2.1.257 does not send numeric exit status. Green collapse therefore stands down on that client, even when enabled. Synthetic numeric-status tests establish guard behavior, not live savings.

Both policies require the registered Anyray MCP server and a successful anyray_retrieve call in the bounded main transcript tail, a successful local tee, and a replacement shorter than the original. Restricted subagents and unknown contexts decline to the shipped hook. The marker contains retrieve ctx_…; call anyray_retrieve with that handle for the bytes. These handles resolve through Connect's existing local tee reader, not the gateway stash. The original stays on the machine under the tee retention rules above. No extra gateway optimization request runs for policy replacements.

Only native Claude Code Read results qualify for stubs; other result shapes retain the shipped hook behavior on every delivery. The marker refers to your earlier Read of the same file in this conversation. Missing session identity, unreadable files, unsupported Read results, and files over 16 MiB pass through. Records are bounded to 256 reads per session and 64 sessions, with a 24-hour idle expiry checked on use. Compaction and session end remove all read hashes and handles; they do not delete recovery bytes still referenced by transcript markers.

doctor --json and status --json expose hookPolicies and hookPolicyMetrics. Metrics include greenCollapses, rereadStubs, editFailuresAfterStub, stubsFollowedByEditFailure, retrievesAfterStub, retrievesAfterCollapse, retrievalMissesAfterPolicy, completedWindows, censoredWindows, observationGaps, and observationGap. Exact-handle retrievals and Edit failures are observed for the next five main-transcript tool calls. Subagent calls do not advance these windows. An Edit failure counts once per Edit and once per affected stub. Compaction or session end before five calls censors that window. An observation gap invalidates benchmark results. Recovery clears stale read history automatically; observationGaps preserves the evidence loss after the transient signal clears.

These switches remain off until paired runs beat pass-through beyond the 53% noise floor and the third quartile still saves. Include retrieval calls, cache writes, and long-tail turn counts in the comparison. Fewer output bytes alone do not establish a session saving.

Background services

On a default seat, Connect installs no background service at all: a gateway key lives 90 days, so nothing can expire under a running tool. A small unprivileged service appears only where your organization issues fast-rotating keys, or on a seat used solely for SDK and shell work. It sends credential data only, and never your prompts or replies. Per-platform service labels, unit-file paths, and how to opt out: Key renewal.

The authoritative inventory is generated, not written by hand

anyray-connect doctor --security-review prints the service names, unit-file paths, outbound hosts, and the self-updater's full footprint (the release URLs it fetches, the paths it writes, and the two commands it runs on a freshly downloaded binary) that your security or endpoint team needs to allow-list. It is derived from the installers themselves, works offline, needs no key, and says nothing about your traffic. Where that sheet and this page disagree, trust the sheet.

curl -fsSL https://app.anyray.ai/connect.sh | sh -s -- doctor --security-review

Service keys

An agent host (a CI runner, a bot, a scheduled SDK job) has no person to sign in, so the console mints it a service key instead. Connect runs on that host with the key in the environment and the same headless apply a developer uses:

export ANYRAY_CLIENT_KEY=ark_svc_… # from the host's secret store
curl -fsSL https://app.anyray.ai/connect.sh | sh -s -- --gateway <origin> --yes

Detection picks the installed tools; add --tools shell-env to write only the SDK environment. What changes on this lane:

  • Identity and team come from the key. --user and --team are ignored, with a note saying so.
  • There is no enrollment cert, so nothing refreshes: no background service, no LaunchAgent or scheduled task, and the key is never re-minted on the host. Rotate or revoke it from the console.
  • No remote-environment offer, and --project is refused: a committed repo config gets its key through print-key, which mints from a cert the host does not have.
  • Tool configs, the retrieval MCP server, and the profile are written as usual, so doctor, status, and the MCP server all find the key.

doctor titles the credential section Service key (agent), doctor --json and status --json carry keyKind: "service", and the host sends no seat health report: an agent is not a seat. A --json apply marks its applied event with the same keyKind.

Connector grants

anyray-connect connectors authorize <name> connects one of the organization's OAuth connectors (see the organization MCP endpoint) to the developer's own account. It binds a listener on 127.0.0.1 (a random port, for this run only), asks the gateway to start the vendor flow with that port and a per-run nonce, opens the consent page, and redeems the claim code the gateway redirects back with. The redirect carries the nonce's digest and the listener accepts a code only under it, so a code from someone else's consent pushed at that port is ignored and the run keeps waiting. stdout carries one line naming the connector and the account. The claim code, the nonce, the client key, and the authorization URL's query string never reach either stream; the URL is printed only when no browser could be opened, so the developer can open it by hand.

FlagWhat it does
--claim <code>Redeem a claim code the consent page showed. No listener, no browser.
--gateway <origin>Gateway origin, resolved like every other verb.

In an SSH session, a dev container, or a Codespace the browser cannot reach that listener, so the command sends no port, prints the URL to open, and asks for a rerun with --claim once the page shows the code. The same fallback runs when no local port can be bound. A gateway that predates loopbackPort drops it and shows the code in the browser; Connect sees that in the reply, says so, and hands over to --claim without waiting. Consent has five minutes; after a timeout the redirect lands on a closed port, so the hint says to copy the claim= value from the browser's address bar. Each gateway call has a 30 second budget. Exit codes: 0 connected, 1 not connected (a failure, or any hand-over to --claim that leaves a step to do), 2 usage.

Machine maintenance commands

Fleet and local supervisors call a stable, non-interactive command surface. These commands accept no prompts and print one content-free JSON document to stdout. All except directives write the same evidence to ~/.anyray/status.json with mode 0600.

CommandPurpose
anyray-connect reconcilePull org tool policy and repair managed drift.
anyray-connect refreshRenew credentials when due and re-assert configuration.
anyray-connect directivesPull and run one pending admin directive.
anyray-connect repairRun the complete repair pass.
anyray-connect status --jsonPrint current seat evidence for scripts and policy checks.
anyray-connect offboardRevert managed tools, remove resident units, and clear user state.

Exit codes are stable: 0 healthy or complete, 1 unexpected error, 2 usage error, 3 re-enrollment required, and 4 partial with drift still present. stdout never carries keys, private key material, SSO tokens, authorization values, or URLs with credentials; diagnostics go to stderr.

Desktop automation also uses persistence --adopt-app --app-path <path> for ownership handover, persistence --release-app for removal recovery, and managed-enroll --json for enrollment from the machine's managed settings. persistence keeps stdout empty and returns 0 on success or 1 on failure; diagnostics go to stderr. managed-enroll --json is silent when enrollment is skipped and emits enrollment events when it runs. The previous __anyray-persistence, __anyray-managed-enroll and __anyray-refresh spellings remain aliases for one release.

The tray starts resident --protocol-version 1 once and sends maintenance and status requests over stdin. Stdout carries versioned newline-delimited JSON events, bounded to 256 KiB per line. A protocol error or an unresponsive child makes status unavailable; the tray retries with bounded backoff. Ordinary read-only status does not register login or start maintenance.

On a fleet-managed machine, refresh skips ambient updates. The gateway compares the seat's reported Connect version with the published release and sends an update directive through the existing per-seat lane when it is stale. The seat runs the same checksum-verified, smoke-tested updater as the manual update command within 30 minutes on supported CLI runtimes. The desktop poll stages app updates and acknowledges them once the running app is current. Other admin commands take priority while installation is pending; see desktop updates. Off the fleet, refresh keeps the scheduled self-update, because that tick is an unmanaged seat's only unattended update path.

Claude Code managed policy

For Claude Code, apply and doctor inspect the machine-wide managed-settings.json. They flag disableAllHooks: true, and flag allowManagedHooksOnly: true when the managed hooks block does not contain Anyray's PostToolUse hook. Connect never edits IT policy: ask the MDM owner to remove the key, or to add the credential-free hook block emitted by anyray-connect managed --print --sso <link> --bin <path>, then restart Claude Code.

Doctor reports this as the separate claude-code / hook_policy fleet check. The failing statuses are disabled and restricted_dropping_ours; it does not reuse the network-liveness hook_lane check.

Claude Desktop configuration carry

Third-party inference gives Claude Desktop a separate profile, so the local MCP servers, user-created skills, and user-installed plugins in the first-party profile are unread until they are copied across. Every apply lane copies them, MDM reconciles included. MCP servers copy right away; skills and plugins wait for the next full quit, because Claude Desktop rewrites those stores on exit. Conversation history moves only through anyray-connect migrate, which reports to the person whose files they are.

Doctor prints the result under Claude Desktop profile and reports it to the fleet as the connect / desktop_config_carry check. It is a diagnostic: no state counts against the compliance score or the failing-check count.

StateMeaning
carriedEvery local entry is in the third-party profile.
pendingSome entries are not there yet. Connect carries them on the next reconcile, or the next time Claude Desktop is fully quit.
nothing_to_carryThe first-party profile holds no local MCP server, user skill, or user plugin.
not_routedThis machine does not route Claude Desktop through Anyray and nothing is queued to, so no carry applies. Normal on a fleet whose policy holds Desktop back.
unreadableThe first-party profile refused access. Allow Connect to read it, then run doctor again.
unsupportedThe host has no third-party profile (Linux).
unknownNo evidence: a status document written before this check existed, or an inspection that failed for a reason other than access. The gateway records the same word for a doctor report from an older Connect.

Update path variants

Updating an npm install

npx anyray-connect@latest bootstraps the same managed standalone install as connect.sh; it does not create a second steady-state npm installation. The first enrollment, apply, repair, or fleet sync that may persist a runtime downloads and verifies the managed binary, then registers every integration against ~/.anyray/bin/anyray-connect. Later npx runs leave that launcher in charge.

Existing seats whose hooks or services point at an older version-pinned npm runtime migrate on their next automatic refresh. Connect smoke-tests the new binary before repointing registrations and keeps the currently running npm copy as rollback until the migration succeeds. Run anyray-connect update to migrate immediately, or anyray-connect update --check to preview it.

Inside a devcontainer or Codespace this migration, and self-update generally, is skipped: the image updates by rebuilding, not by downloading a new binary. See Remote and ephemeral machines.

Platforms without a standalone binary

If Anyray does not publish a standalone asset for the current OS and architecture, Connect keeps the version-pinned durable npm runtime instead. --version, update, and doctor report that self-update is unavailable; use npx anyray-connect@latest to pick up new releases on that platform. A copy placed by your IT team remains externally managed and is still theirs to roll.

doctor and status --json include sourceTrim.state, read from the verified key on GET /v1/me: unsupported, needs_gateway_upgrade, observing, active, active_no_source_trim, or unavailable. This is successful trim evidence, separate from the local hook invocation/probe check. Support and observation window.