Skip to content

Latest commit

 

History

86 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Hone

Self-hosted, MCP-only LLM-facing telemetry for Laravel.

Don't want to run it? Hone is MIT — fork and own it. Or have Artisan Build run it in your Cloud account and keep it updated.

Hone is a thin telemetry layer for Laravel apps. It captures laravel/nightwatch instrumentation, stores a pruned slice in a Postgres database you control, and exposes it to a coding agent (Claude Code, CI, etc.) over MCP to answer one question well:

"What should we improve this week?"

It is deliberately not a Nightwatch competitor. No UI. No deep request traces. No long-term history. No alerting. Just agent-queryable telemetry with no per-event cost.


Why Hone exists

Nightwatch's event-metered pricing doesn't fit a large class of apps where request volume doesn't track revenue. To control cost, those apps throttle sampling so hard the data stops being useful.

Hone is a free, self-hosted floor: agent-queryable telemetry with no per-event cost, for the apps the metered model was never going to fit. Storage is your only cost.

Positioning. Nightwatch is the full-featured product — deep request diving, history, alerting, collaboration, and the excellent UI the Laravel team built. Hone answers one narrow question for one consumer (a coding agent). Outgrow it → Nightwatch is the upgrade.

Hone is built on laravel/nightwatch (MIT, by Taylor Otwell). It rebinds Nightwatch's ingest transport so an app's own telemetry routes to the app owner's own server. Hone never contacts Nightwatch's cloud and never uses their service.

Support posture

Hone is written for how Artisan Build uses it. Bugs get fixed. Feature requests are a fork away. Client-specific features are not backfilled into the OSS release. If you need the full product, that's what Nightwatch is for.


Architecture

  Source app #1 ─┐  (hone-client: rebind transport → batch → HTTPS POST)
  Source app #2 ─┼──►  Hone app (one isolated env per client)
  Source app #N ─┘         │ ingest endpoint (HONE_TOKEN auth, tags source app, version-checks envelope)
                           ▼
                        Redis queue
                           ▼
                        Worker → Postgres  (raw, tagged by app + deploy + record_type)
                           ▼
                        Scheduled rollup (before prune) → aggregates
                           ▼
                        MCP server  ◄── coding agent (Claude Code / CI)
  • One isolated environment per client on Laravel Cloud — its own compute, Postgres, and Redis, sized and billed per client. The Hone app is single-tenant; isolation is environmental.
  • Unlimited source apps per environment. One client may feed many applications into one Hone environment — hence the app dimension and the app registry.
  • Cross-boundary transport is HTTP, not shared Redis. Source apps are separate deployments; a TLS + token endpoint crosses environment isolation cleanly.

Repository layout

This is a monorepo. Three packages are developed here under packages/, each split read-only to its own repository and published to Packagist:

Package Repo Installed in Role
artisan-build/hone-contracts read-only split both packages The versioned wire envelope. The single place compatibility lives.
artisan-build/hone-client read-only split monitored apps The send side: Nightwatch transport rebind, batching, POST, install/update commands.
artisan-build/hone-server read-only split the Hone app The receive side: ingest, storage, rollups, prune, and the MCP server.

The Hone app (this repository's root) is a slim Laravel shell — token handout plus wiring hone-server. It pulls its packages from Packagist and stays thin so there's no Hone-specific business logic to drift.

Contributing

Issues and PRs are disabled on the three split repos — the same model as Laravel's own illuminate/* read-only splits. All development happens here in the monorepo. See SECURITY.md for private vulnerability disclosure; Hone sits on an ingest path.


Compatibility & versioning

Across N independently-deployed senders and one self-hosted receiver, version skew is the normal state, not an error. The wire protocol is built to tolerate it:

  • Versioned envelope. Every payload carries ENVELOPE_VERSION. The envelope evolves additively within a major — new optional fields only, never remove or repurpose one.
  • Backward-compatible server. A newer hone-server parses every older envelope major.
  • Loud failure on the dangerous case. Ingest returns a clear 4xx for an envelope newer than it knows ("your senders are ahead of this Hone instance — upgrade it").
  • Opaque inner payloads. Only the thin Hone envelope is version-sensitive. Nightwatch's own record bodies are stored as jsonb and interpreted at rollup/query time — a change in Nightwatch's payload shape degrades to "a rollup misses a field," never an ingest failure.
  • Canonical upgrade order: update the Hone app first, then bump the clients. A backward-compatible server safely runs ahead of its senders; the only hazard is a sender getting ahead of the server, which server-first prevents.

Deploying on Laravel Cloud

Run one isolated Laravel Cloud environment per client: the Hone app, one Postgres database, and Redis. Hone stores its thin app tables and telemetry tables in Postgres through the hone connection, which defaults to the application's own database — fork, deploy, and one Cloud Postgres serves both with no telemetry-specific configuration. The two sets of tables never join across connections, so a separate telemetry database stays available as an opt-in (see HONE_DB_* below).

Using a coding agent? Let the skill do it. This repo ships a provisioning-hone-on-cloud skill that automates everything in this section. Open the monorepo with a skill-aware agent (Claude Code, etc.) and ask it to "provision a Hone instance on Laravel Cloud." The skill sizes the environment as a small/medium/large tier, and only after you confirm uses the cloud CLI to provision Postgres, Redis, a web instance, a managed queue, and the scheduler, wire the HONE_* config, deploy, migrate, and issue the first source-app token. It specializes the Cloud CLI's generic deploying-laravel-cloud skill. The manual steps below are the same thing by hand.

Required production environment:

  • DB_CONNECTION=pgsql plus DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, and DB_PASSWORD.
  • (optional) HONE_DB_URL, HONE_DB_HOST, HONE_DB_PORT, HONE_DB_DATABASE, HONE_DB_USERNAME, and HONE_DB_PASSWORDonly to isolate telemetry onto a separate Postgres database. Leave them unset and telemetry shares the DB_* database. Set any one of them and the rest are inherited from the app's connection, so overriding just HONE_DB_DATABASE moves telemetry to another database on the same server. Hone's telemetry schema is Postgres-only (jsonb columns, jsonb_typeof() at rollup), so both the app connection and any telemetry override must be Postgres.
  • Bearer tokens for ingest and registry-token MCP access are managed by artisan-build/built-for-cloud: issue per-app tokens with php artisan token:create <name> (stored hashed in api_tokens), or set a single FALLBACK_TOKEN for ingest bootstrap. Any resolving api_tokens entry may both ingest telemetry and read it back over MCP. MCP also accepts a Scalpels-issued delegated assertion whose signed purpose claim is mcp; Hone accepts these assertions but does not issue them.
  • HONE_MCP_PATH; the default MCP HTTP path is /mcp.
  • QUEUE_CONNECTION=redis and HONE_QUEUE_CONNECTION=redis so accepted ingest batches are processed by Redis workers.
  • HONE_RETENTION_RAW_HOURS, HONE_RETENTION_AGGREGATE_DAYS, and HONE_RETENTION_SAMPLE_DAYS; the defaults are 72, 90, and 7.
  • NIGHTWATCH_DEPLOY, used as the deploy dimension when source apps report it.

Do not enable Laravel Cloud's built-in Nightwatch integration for the Hone app. Hone uses Nightwatch instrumentation in source apps but does not send telemetry to Nightwatch Cloud; Cloud's Nightwatch toggle would ship data to Nightwatch's hosted service and conflicts with this setup.

Add a build step that writes the deployed commit to the environment file:

echo "NIGHTWATCH_DEPLOY=$(git rev-parse --short HEAD)" >> .env

This assumes .git is present during the build. If your build runs from an exported archive, write the short commit SHA from CI instead, for example from github.sha in GitHub Actions.

After deploy, run php artisan migrate --force; the hone-server migrations create the raw_events, aggregates, and samples tables on the hone connection. Run Laravel's scheduler in the environment; the package schedules php artisan hone:maintain hourly, which runs hone:rollup and then hone:prune. Run a Redis queue worker cluster for the default queue so ProcessTelemetryBatch jobs drain accepted ingest batches.

Prefer not to operate it?

Everything above — an isolated environment per client, Postgres, Redis, a worker cluster, the scheduler running hone:maintain, retention tuning, and the server-first upgrade dance — is a standing ops commitment. It's all documented because the fork-and-own path is real and complete.

If you'd rather not carry it, Artisan Build will run Hone in your own Laravel Cloud account — your infra, your data, your telemetry never leaves your compute — and keep the app, migrations, and version upgrades current. You get the self-hosted guarantee without the operational overhead.

Adding a source app

On the Hone server, issue a source application token with the artisan-build/built-for-cloud command:

php artisan token:create <app-id>

The command generates the plaintext token, prints it once, and stores only its hash in the api_tokens table — there is no env var to edit and no redeploy needed. Rotate, revoke, list, and inspect usage with token:rotate, token:revoke, token:list, and token:usage. For a low-ceremony bootstrap you can instead set a single FALLBACK_TOKEN in the environment (delete it and use per-app tokens for production).

In the source Laravel app, install Nightwatch and the Hone client:

composer require laravel/nightwatch artisan-build/hone-client
php artisan hone:install

hone:install prompts for the Hone ingest URL and plaintext token, or accepts --url= and --token=. Use the server ingest URL, ending in /ingest; the route is named hone-server.ingest. The installer writes HONE_URL, HONE_TOKEN, and a truthy NIGHTWATCH_ENABLED=true when needed, then pins artisan-build/hone-client to a clean caret major constraint in composer.json. No NIGHTWATCH_TOKEN is needed for Hone. Set NIGHTWATCH_DEPLOY in the source app at deploy time so Hone can compare releases.

Using a coding agent in the source app? hone-client ships a configuring-hone-client skill (under vendor/artisan-build/hone-client/skills/configuring-hone-client/ once the package is installed). Point your agent at it and ask it to "configure the Hone client" — it covers composer require, hone:install, verifying the Nightwatch transport rebind is actually active, setting the deploy dimension, confirming server-side receipt over MCP, and troubleshooting why telemetry isn't arriving. See the hone-client README for details.

Connecting a coding agent (MCP)

The HTTP MCP server is registered at HONE_MCP_PATH and requires an Authorization: Bearer <credential> header. The credential may be any resolving api_tokens entry issued with token:create, or a Scalpels-issued delegated assertion carrying the signed claim purpose: mcp. Hone verifies and accepts delegated assertions but never issues them. Requests without a valid credential fail closed with 401. /bfc/meta advertises the mounted path through endpoints.mcp and the mcp-serve and mcp-delegated capabilities.

Hone exposes 19 read-only MCP tools: discovery tools for apps, record types, deploys, and ingest freshness; slow-path tools for requests, queries, jobs, and outgoing requests; query_metric, regression_check, exceptions, top_users, and volume/stat tools for cache events, queues, mail, notifications, scheduled tasks, commands, and logs by level. Every tool is D14-classified as content and advertises that classification in _meta.classification; even count-oriented responses can carry a customer-defined app id, normalized key, user id, deploy id, task name, or similar customer telemetry.

Upgrading

Upgrade the Hone server first, run its migrations, and then update the source app clients. Clients can run:

php artisan hone:update

The command derives /capabilities from HONE_URL (stripping a trailing /ingest when present), sends its HONE_TOKEN as a bearer header (the capabilities endpoint itself does not require it), and reports whether the client's envelope major is inside the server's supported range. The envelope is additive within a major. If a source app sends an envelope newer than the server understands, ingest returns a 4xx with an upgrade message instead of accepting the batch.

Privacy

Hone is designed to be safe to feed to an LLM when source apps use Nightwatch's normal redaction configuration. Query bindings are not part of Hone's normalized query key, and Hone does not add a second capture path for them; source-app Nightwatch redaction happens before records are sent to Hone. MCP tools summarize by normalized keys such as route, SQL shape, exception class/location, log level, user id, and cache store:type, rather than exposing raw request bodies or arbitrary event payloads.


Out of scope (non-goals)

  • No UI / dashboard. The agent is the interface.
  • No deep distributed traces / span waterfalls — Nightwatch's domain.
  • No long-term history beyond aggregate retention.
  • No alerting / anomaly detection — pull, not push.
  • No in-app multi-tenancy — isolation is per-environment.
  • No sampling logic — that lives in the source app's Nightwatch config.
  • No backfill of client-specific features into the OSS release.

Managed by Artisan Build

Hone is built and maintained by Artisan Build. Bugs get fixed; client-specific features stay in client forks. If you want it deployed and kept current in your own Cloud account, let's talk.

License

Hone is open-sourced software licensed under the MIT license.

About

Self-hosted, MCP-only LLM-facing telemetry for Laravel. Monorepo for hone-contracts, hone-client, hone-server.

Resources

Security policy

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages