Ctrl K
ComunidadGuías…

packages/hone-client/README.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# hone-client

The **send side** of [Hone](https://github.com/artisan-build/hone). Install it in a Laravel
app you want to monitor. It redirects that app's own
[`laravel/nightwatch`](https://github.com/laravel/nightwatch) telemetry to your self-hosted
Hone server.

See the [default integration guide](docs/integrate/default.md) for agent-driven setup and verification.

> **Read-only mirror.** This repository is a read-only split of the
> [`artisan-build/hone`](https://github.com/artisan-build/hone) monorepo. Issues and pull
> requests are disabled here — please open them on the monorepo.

## What it does

`hone-client` is thin by design — its only job is to redirect Nightwatch's output to your
Hone app.

- **Rebinds the Nightwatch ingest transport** through a service provider. Nightwatch exposes
  its ingest as a swappable object on the container-bound `Core`; `hone-client` replaces it
  with one that batches records and POSTs them over HTTPS to your Hone server. No fork of
  `laravel/nightwatch`, no daemon, no on-disk buffer.
- **Batches and POSTs** a versioned envelope to the ingest endpoint, authenticating with
  `HONE_TOKEN`. `HONE_URL` remains the fallback endpoint.
- **Fails open.** If the endpoint is unreachable, records are dropped and counted without
  failing the host app. Web requests keep network work in request termination; long-running
  console processes also send full or aged buffers while they run.
- **Octane-safe** — no per-request static state leakage.

It does **not** do sampling (that lives in your Nightwatch config) and it adds **no
redaction layer** (see [Privacy](#privacy)).

## Activation — by presence of config, no boolean

The rebind fires **only when both `HONE_URL` and `HONE_TOKEN` are present and non-empty.**

| `HONE_URL` | `HONE_TOKEN` | Behavior |
| --- | --- | --- |
| set | set | **Active** — telemetry ships to Hone. |
| unset | unset | Inert (the normal state for an app that isn't monitored). |
| only one set | | Inert, but **logs a warning** (half-configured). |

The kill switch is removing or commenting the `HONE_*` values.

## Installation

```bash
composer require artisan-build/hone-client
php artisan hone:install
```

`hone:install` wires the app for tracking: it sets `HONE_URL` / `HONE_TOKEN`, pins
`hone-client` at a caret constraint (`^X`), and confirms your Nightwatch setup will activate.
It is idempotent and asks for consent before touching any file.

### Setting up with a coding agent (skill)

This package ships a **`configuring-hone-client`** skill so a skill-aware coding agent (Claude
Code, etc.) can do the whole setup for you. After `composer require`, it lives at:

```
vendor/artisan-build/hone-client/skills/configuring-hone-client/SKILL.md
```

Point your agent at that file (or copy the `configuring-hone-client/` directory into your
project's `.claude/skills/`) and ask it to *"configure the Hone client."* The skill walks
through the prerequisites, `hone:install`, **verifying the Nightwatch transport rebind is
active** (the step that actually proves it's working), setting the `NIGHTWATCH_DEPLOY` deploy
dimension, confirming receipt on the Hone server over MCP, and the common
"telemetry isn't arriving" failure modes.

### Source-app environment

```dotenv
NIGHTWATCH_ENABLED=true                       # Nightwatch collects when enabled (the default)
HONE_URL=https://hone.<client>.example/ingest
HONE_TOKEN=<issued by your Hone app's registry>
NIGHTWATCH_DEPLOY=<commit sha, set at deploy; Cloud, Forge and Vapor are read automatically>
# HONE_DISCOVER_INGEST=false                 # Optional: always use HONE_URL
# Optional tuning: console buffers flush every 60 seconds with 2s connect / 5s total timeouts.
# HONE_FLUSH_INTERVAL=60
# HONE_CONSOLE_CONNECT_TIMEOUT=2
# HONE_CONSOLE_TIMEOUT=5
```

You do **not** need a `NIGHTWATCH_TOKEN`. Nightwatch's collection is gated by
`NIGHTWATCH_ENABLED` (default `true`), not the token — and Hone never talks to Nightwatch's
cloud, so no real Nightwatch credential is required.

When discovery is enabled, `hone-client` schedules `hone:refresh-ingest` hourly. The command
reads `/capabilities` and caches its `ingest.url` for one hour. Telemetry delivery never makes
that discovery request: it uses a fresh cached URL when one exists and otherwise immediately
falls back to `HONE_URL`. A base `HONE_URL` is normalized to its `/ingest` endpoint. If the
scheduler is unavailable, the cache expires, or the cache cannot be read, delivery continues
to use the fallback. Set `HONE_DISCOVER_INGEST=false` to skip scheduling and always use the
fallback.

If a separately managed local agent holds the token instead of the app, duplicate `NIGHTWATCH_TOKEN` into the app environment so `hone-client` leaves Nightwatch enabled.

> **On Laravel Cloud:** do **not** enable the built-in Nightwatch toggle — it runs Cloud's
> managed agent and ships to Nightwatch's cloud, which conflicts with the rebind. Install
> `laravel/nightwatch` + `hone-client` and let the rebind own the transport. Set
> `NIGHTWATCH_*_SAMPLE_RATE` explicitly and high — storage is your only cost.

## Keeping in sync — `hone:update`

After any major update, run:

```bash
php artisan hone:update
```

It calls `{HONE_URL}/capabilities`, compares the `hone-contracts` major you have installed
against the majors your Hone server supports, and either gives the all-clear or tells you to
**update your Hone app first.** The canonical upgrade order is always: **update Hone, then
update your apps.**

`hone-client` also emits a one-line local nudge when the installed `hone-contracts` **major**
changes, reminding you to run `hone:update`. It's zero-network — just a reminder.

## Client identity

`hone-client` carries [`artisan-build/bfc-client`](https://github.com/artisan-build/bfc-client),
which gives this installation a **stable, opaque identity** so the Hone server can attribute an
ingest token to a specific install.

- Every telemetry POST to `HONE_URL` carries the identity in an **`X-BfC-Client-Id`** header,
  alongside the `HONE_TOKEN` bearer auth. The identity is a **label, never a credential** — it
  grants nothing on its own. It is only ever sent to your Hone server.
- If the identity cannot be resolved, telemetry still ships — **without** the header. Attribution
  is never worth dropping telemetry for.
- The identity defaults to a UUID generated once and persisted to
  `storage_path('app/bfc-client/identity')`. **On an ephemeral filesystem set
  `BFC_CLIENT_IDENTITY` explicitly**, or the identity churns on every deploy.
- `bfc-client` also registers an unauthenticated, throttled `GET /bfc-client` proof-of-life route
  that returns the package name and this identity. Move it with `BFC_CLIENT_PROOF_OF_LIFE_PATH`
  or disable it with `BFC_CLIENT_PROOF_OF_LIFE=false`.

## Privacy

Hone adds **no** redaction layer; redaction belongs in your Nightwatch config, before
transmission, and `hone-client` ships its recommended defaults **off**:

- **Query bindings are never captured** — SQL arrives parameterized; bound values never enter
  the pipeline.
- **Request-body capture stays off** (the Nightwatch default).
- For apps using raw SQL literals or PII-bearing exception messages, configure Nightwatch's
  `redactQueries` / exception-message hooks.

Because stored telemetry is parameterized and pre-redacted upstream, it is safe to feed to
an LLM. That is the point.

## License

MIT. See [LICENSE](LICENSE).