xray

module
v0.4.13 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 26, 2026 License: Apache-2.0

README

xray

Build CodeQL OpenSSF Scorecard SLSA 3 govulncheck License

xray is a read-only extractor that produces a portable engineering-metrics artifact from a client's git, GitHub, CI, and error-tracker systems.

  • Captures: commits, PRs, reviews, CI runs, deploys, incidents — structural data and declared configuration / tooling manifests, never application logic.
  • Produces: a single .tar.gz (SQLite + JSON manifest) — verifiable SHA256, no secrets.
  • Touches: GitHub, GitHub Actions, CircleCI, Sentry, Bugsnag, Honeycomb — read-only, even when tokens hold write scope.
  • Doesn't do: application-logic capture, per-individual rankings, daemon mode, scheduled runs.

[!IMPORTANT] xray runs inside a customer environment against the customer's own credentials. The artifact contains no source code and no secrets. Security review: docs/security.md · docs/threat-model.md. Vulnerability disclosure: SECURITY.md.

Design

xray is engineered against five non-negotiable constraints. The Trust documents below show how the implementation upholds each.

  • Independent. Runs buyer-side under the customer's operator and credentials. No vendor telemetry, no sales channel, no daemon mode.
  • System-level over time. Team-level and system-level granularity, enforced in the schema. No per-individual rollups anywhere.
  • Hypothesis-anchored. The window and connector set are chosen against a stated question; extraction_provenance records what was asked of every endpoint.
  • Brackets the AI-adoption inflection. harness_artifacts.first_seen_at records when each AI-tool config file (CLAUDE.md, .cursor/rules, .github/copilot-instructions.md) first appeared in repo history. Flow metrics join against the inflection inside one extract.
  • Source-free. Reads declared configuration and tooling manifests; never application logic.

Trust

xray is intended to be run inside the customer's environment by the customer's own operator, against the customer's own credentials, and the artifact it produces is meant to survive a security review. The four documents below describe what the binary does, what it cannot do, and what a representative run actually looks like.

  • docs/security.md — what is captured, what is not, and the guarantees the binary makes (read-only, no application logic, no secrets in the artifact, team-level only, logs).
  • docs/threat-model.md — one-page trust boundaries, attack surface, malicious-binary and leaked-artifact analysis.
  • docs/sample-manifest.json — a real manifest.json from a clean single-repo run against goreleaser/chglog, the same target /ready uses for smoke. Real row counts, real extraction_provenance block. Failure-mode endpoint states are documented in docs/security.md rather than reproduced here.
  • docs/sample-run.log — the matching .log file demonstrating no tokens, per-phase logs, and the post-run artifact summary.
  • docs/operator-setup.md — operator-side setup walkthrough: install, probe, configure, validate, and run.
  • docs/engagement-guide.md — the consultant-side counterpart: what happens to the artifact after you send it. Public so the methodology stays auditable.

Install

macOS
brew tap kmcd/xray https://github.com/kmcd/xray
brew install kmcd/xray/xray
Linux
curl -sSfL https://raw.githubusercontent.com/kmcd/xray/main/scripts/install.sh | sh

The script detects OS and architecture, downloads the latest release archive, verifies its sha256 against checksums.txt, and installs to /usr/local/bin/xray. Set XRAY_INSTALL_DIR=$HOME/.local/bin to install without sudo — make sure that directory is on your PATH. Set XRAY_VERIFY_COSIGN=1 to additionally verify the cosign signature (requires cosign on PATH).

Windows
scoop bucket add xray https://github.com/kmcd/xray
scoop install xray
Manual download

Pick the archive for your platform from the releases page and extract xray onto your PATH. For air-gapped or security-team installs, verify the cosign signature first — see Verifying the binary. For corporate proxy, custom CA, and firewall configuration, see docs/enterprise.md.

Go developers
go install github.com/kmcd/xray/cmd/xray@latest
Prerequisites

xray shells out to the system git binary for repository clones over HTTPS. Make sure git has credentials for github.com before running xray check or xray run. If gh is installed, the one-liner is:

gh auth setup-git

Otherwise, configure a credential helper (git credential-osxkeychain, git-credential-manager, or an embedded PAT in ~/.git-credentials). xray check reports a fix hint when this step is missing.

Usage

The default flow: configure → validate → run → export.

1. Configure

Set tokens for each connector, then run xray init --probe to discover live connector state and generate a pre-populated config:

export GITHUB_TOKEN="ghp_..."       # required
export CIRCLECI_TOKEN="..."         # optional
export BUGSNAG_AUTH_TOKEN="..."     # optional
export HONEYCOMB_API_KEY="..."      # optional (or HC_API_KEY)

xray init --from-org my-org --probe

To scaffold from repo names only (no connector discovery), set GITHUB_TOKEN first (the API call to list repos still requires it):

export GITHUB_TOKEN="ghp_..."
xray init --from-org my-org

Hand-edit the generated xray.toml: verify the window, paste any connector tokens not already set as env vars, and split repos into teams. See docs/operator-setup.md for the full walkthrough, PAT scope requirements, and per-connector examples. The config stays on the operator's machine — never committed to git, never shared back to the consultant.

2. Validate and check
# Syntactic + schema check, offline. Defaults to ./xray.toml; pass an
# explicit path to point at a different config.
xray validate

# Live preflight against configured connectors (auth, rate limits, scope).
xray check
3. Run
# Full extraction. Produces ./xray-export-<UTC-timestamp>.tar.gz with a
# sibling .log file mirroring stderr (suppress with --no-run-log). See
# the sample-run block below the code for live TTY output.
xray run

# Machine-readable output. One NDJSON event per progress tick, terminated
# by a {"kind":"run_summary",...} object on stdout. See docs/spec.md.
xray run --output json | jq .

# Quiet success: only the artifact path is written to stdout.
xray run --output quiet
Sample run (live TTY output)

On a TTY, the default (--output auto) renders a live (repo × connector) status grid:

xray run · elapsed 04:12 · ETA 14:47 ±2m · 3/4 workers

repo                clone           github           gh_actions       sentry
kmcd/foo            ✔ done          ✔ 4213 rows      ● gh_actions     ✔ 312 rows
kmcd/bar            ✔ done          ● prs            ▢ pending        🔒 inaccessible
kmcd/baz            ● clone         ▢ pending        ▢ pending        ▢ pending

Non-TTY (CI, pipe to file) falls back to a stderr log with one line per phase boundary; force the log explicitly with --output log.

On a long run (1+ hour), rate-limit waits appear as rate limited, waiting Ns, primary limit low, waiting Ns, or adaptive pacing, waiting Ns lines — these are normal and the run resumes automatically. Run under tmux or screen to keep the process alive if you close your terminal.

Exit codes: 0 clean, 1 config / pre-flight error, 2 partial run (artifact produced, connector error recorded in manifest), 3 fatal. See docs/spec.mdxray run → "Exit codes".

4. Inspect (optional)

Before sending the artifact, verify it is structurally intact:

xray inspect xray-export-<UTC-timestamp>.tar.gz

This runs five checks: end-to-end tar/gzip CRC, manifest shape, SQLite integrity, row-count reconciliation, and schema-version compatibility. All five must pass before the artifact is accepted by the analyser.

PASS  tar_integrity       2 members, 48.3 MB read
PASS  manifest_shape      tool_version=0.4.8 schema_version=2 run_id=...
PASS  sqlite_integrity
PASS  row_counts          12 tables reconciled
PASS  schema_version      schema_version=2 (xray 0.3.0, 0.4.0, ...)

PASS

For machine-readable output: xray inspect <artifact> --json.

Exit codes: 0 all checks pass, 1 one or more failed, 2 usage error. Full check descriptions: docs/spec.mdxray inspect.

5. Export

The run produces two files in the working directory:

  • xray-export-<UTC-timestamp>.tar.gz — the artifact (SQLite + JSON manifest)
  • xray-export-<UTC-timestamp>.log — the run log (mirrors stderr)

Inspect manifest.json inside the archive before sending — it lists every connector's status, row counts, and per-endpoint errors. No source content, no secrets. Sample: docs/sample-manifest.json.

Send the consultant the .tar.gz, the .log, and the output of xray version. Do not send the config file — it contains your token.

Common handover channels are Slack DM, a download link your consultant provides, or a private file share. The artifact is typically 10–200 MiB for a multi-repo engagement.

The full configuration reference and behaviour spec live in docs/spec.md. The output schema is documented in docs/schema.md. Agent-facing constraints (invariants, non-goals, schema-versioning rules) live in CLAUDE.md.

Compatibility

Pre-1.0, the schema is unstable; minor version bumps may introduce breaking schema changes. The analyser refuses to load artifacts at an unknown schema_version. Per-release changes that affect downstream consumers are tracked in CHANGELOG.md.

schema_version xray binary versions notes
1 0.1.0 – 0.2.2 Author handles are raw git idents / GitHub logins.
2 0.3.0 – 0.4.13 Author handles are opaque h_<15 digits> tokens (ADR 023). Analysers built for schema_version = 1 must be updated.

0.3.0 is the first release at schema_version = 2. Analysers pinned to schema_version = 1 will refuse to load 0.3.0+ artifacts — see the CHANGELOG for the author-handle semantics shift driving the bump.

Verifying the binary

Verify the cosign signature on checksums.txt, then verify the archive against the checksum.

VERSION=0.4.13
OS=linux           # or darwin, windows
ARCH=amd64         # or arm64 (not available on windows)

base=https://github.com/kmcd/xray/releases/download/v${VERSION}
curl -LO ${base}/xray_${VERSION}_${OS}_${ARCH}.tar.gz
curl -LO ${base}/checksums.txt
curl -LO ${base}/checksums.txt.sig
curl -LO ${base}/checksums.txt.pem

cosign verify-blob \
  --certificate-identity-regexp 'https://github.com/kmcd/xray/.*' \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate checksums.txt.pem \
  --signature checksums.txt.sig \
  checksums.txt

sha256sum -c --ignore-missing checksums.txt
tar -xzf xray_${VERSION}_${OS}_${ARCH}.tar.gz
sudo mv xray /usr/local/bin/
Verifying provenance

Each release ships a single SLSA L3 build provenance attestation (xray.intoto.jsonl) generated by the SLSA GitHub generator. The file lists every release artifact as a subject (binaries, archives, SBOMs) so one download verifies any platform you pick. Each archive also ships an SPDX-JSON SBOM (*.spdx.json). Verify the attestation with slsa-verifier:

curl -LO ${base}/xray.intoto.jsonl

slsa-verifier verify-artifact \
  --provenance-path xray.intoto.jsonl \
  --source-uri github.com/kmcd/xray \
  --source-tag "v${VERSION}" \
  "xray_${VERSION}_${OS}_${ARCH}.tar.gz"

Security

Report vulnerabilities privately — see SECURITY.md.

License

Apache-2.0. See LICENSE.

xray is a read-only extraction tool. It never writes to any remote system and never stores credentials or source content in the output artifact.

FAQ

Where do I run this?
On your laptop. xray is a ~30 MiB static binary; it clones repos to a temp directory, writes a SQLite file, and packages it into a .tar.gz. No install, no daemon, no system dependencies. macOS, Linux, and Windows are supported. Keep ~5 GiB of disk free for the temp clones (varies with repo sizes). To run on a server instead, copy the binary, config, and token env var — nothing else is needed.

Can I run this against repositories with sensitive history?
Yes. xray reads git metadata — SHAs, timestamps, author handles, file paths, numstat — plus declared configuration and tooling manifests (workflow YAML, dependency manifests, AI-harness config files). It never reads application logic. No diff text, no commit bodies, no application source is read or stored. See the full capture inventory in docs/security.md.

What if a provider returns 403 on a required endpoint?
The endpoint records accessible: false with the reason and emits no rows. The analyser treats absence as unknown, not no signal — a critical distinction for analyses that depend on data presence. The run continues. See docs/security.md.

What happens if I revoke the token mid-run?
The next API call returns 401. The connector records accessible: false on that endpoint and continues; subsequent calls are recorded identically. The run completes with exit code 2 (partial — artifact produced, errors in manifest). See docs/security.md.

How do I verify the artifact has no secrets in it before sending?
Unpack the .tar.gz. manifest.json contains row counts, endpoint status, and provenance metadata — no credentials. A real example is at docs/sample-manifest.json.

What is in manifest.json vs. the SQLite database?
manifest.json is the run summary: schema version, extraction window, connector versions, per-endpoint access status, row counts, and errors. The SQLite DB is the metrics: commits, PRs, reviews, CI builds, error rates, observability signals. Full schema: docs/schema.md.

Does the tool need network access from inside my VPC?
Outbound HTTPS to configured providers (GitHub, Sentry, etc.) and to github.com for repo cloning. No inbound ports, no callbacks. Egress-only. See docs/spec.md for the full connector list.

Can I keep the temp clones for inspection?
Pass --keep-clones to skip cleanup; clone paths are logged to stderr and recorded in the .log file. By default, clones are deleted after each repo finishes. See docs/spec.mdxray run → flags.

Why does xray run finish in under a second for Honeycomb on repeat runs?
The Honeycomb markers API returns the full marker history on every call with no server-side date filter. After the first run, xray caches the response under $UserCacheDir/xray/honeycomb/ (macOS: ~/Library/Caches/xray/honeycomb/; Linux: ~/.cache/xray/honeycomb/) with a 24-hour TTL. Pass --no-cache to force a full re-fetch.

Why a static binary instead of a script or container?
A single static binary has one thing to verify: one file, one SHA256, one cosign signature. No runtime dependencies to audit — no pip, no npm, no base image. See docs/threat-model.md.

Build from source

See CONTRIBUTING.md.

Directories

Path Synopsis
cmd
xray command
Package main implements the xray CLI subcommands.
Package main implements the xray CLI subcommands.
internal
archive
Package archive packages the SQLite database and manifest into the final .tar.gz artifact.
Package archive packages the SQLite database and manifest into the final .tar.gz artifact.
config
Package config parses and validates xray TOML configuration with line-numbered diagnostics.
Package config parses and validates xray TOML configuration with line-numbered diagnostics.
connector
Package connector defines the Connector and Sink interfaces and the Provenance struct returned by each extraction.
Package connector defines the Connector and Sink interfaces and the Provenance struct returned by each extraction.
connectors
Package connectors is the parent package for individual connector implementations (github, githubactions, circleci, sentry, bugsnag, honeycomb).
Package connectors is the parent package for individual connector implementations (github, githubactions, circleci, sentry, bugsnag, honeycomb).
connectors/bugsnag
Package bugsnag implements the Bugsnag Data Access API connector.
Package bugsnag implements the Bugsnag Data Access API connector.
connectors/circleci
Package circleci implements the CircleCI v2 API connector.
Package circleci implements the CircleCI v2 API connector.
connectors/github
Package github is the xray GitHub connector.
Package github is the xray GitHub connector.
connectors/githubactions
Package githubactions implements the GitHub Actions connector.
Package githubactions implements the GitHub Actions connector.
connectors/honeycomb
Package honeycomb implements the Honeycomb API connector.
Package honeycomb implements the Honeycomb API connector.
connectors/sentry
Package sentry implements the Sentry API connector.
Package sentry implements the Sentry API connector.
connectors/vcr
Package vcr provides a shared VCR (cassette-replay) test helper for connector packages that make real HTTP calls.
Package vcr provides a shared VCR (cassette-replay) test helper for connector packages that make real HTTP calls.
gitcli
Package gitcli wraps the system git binary: clone, log --numstat --name-status, and per-path log.
Package gitcli wraps the system git binary: clone, log --numstat --name-status, and per-path log.
inspect
Package inspect implements post-hoc artifact validation for xray .tar.gz artifacts.
Package inspect implements post-hoc artifact validation for xray .tar.gz artifacts.
manifest
Package manifest writes manifest.json including the extraction_provenance block that records what each connector returned per repo.
Package manifest writes manifest.json including the extraction_provenance block that records what each connector returned per repo.
model
Package model defines the canonical row structs, SQLite DDL, and schema_version constant for the metrics.sqlite artifact.
Package model defines the canonical row structs, SQLite DDL, and schema_version constant for the metrics.sqlite artifact.
postprocess
Package postprocess runs cross-cutting linkage passes against the populated metrics SQLite store after every connector has finished extracting and before the manifest is written.
Package postprocess runs cross-cutting linkage passes against the populated metrics SQLite store after every connector has finished extracting and before the manifest is written.
preflight
Package preflight builds a cost-preview Plan for an xray run without performing the run.
Package preflight builds a cost-preview Plan for an xray run without performing the run.
progress
Package progress defines the structured run-time event contract for xray's CLI output cluster (cli-ux).
Package progress defines the structured run-time event contract for xray's CLI output cluster (cli-ux).
ratelimit
Package ratelimit provides a shared exponential-backoff HTTP helper that honours X-RateLimit-* and Retry-After headers, with a 3-attempt and 60-second cumulative cap.
Package ratelimit provides a shared exponential-backoff HTTP helper that honours X-RateLimit-* and Retry-After headers, with a 3-attempt and 60-second cumulative cap.
run
Package run orchestrates an extraction: temp-dir lifecycle, worker pool, per-(repo, connector) dispatch, manifest assembly, and provenance.
Package run orchestrates an extraction: temp-dir lifecycle, worker pool, per-(repo, connector) dispatch, manifest assembly, and provenance.
store
Package store opens metrics.sqlite, applies the DDL, and exposes prepared inserts for the canonical tables.
Package store opens metrics.sqlite, applies the DDL, and exposes prepared inserts for the canonical tables.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL