HypAware records the sessions, logs, and telemetry from your AI agents into one queryable history.
It captures conversations and traffic from local AI clients (Claude Code, Codex), raw Anthropic / OpenAI API traffic, and OpenTelemetry logs / traces / metrics. Recordings land in a local query cache and can stay on your machine or sync to a central server.
There are two ways to run it:
- Shared. Each machine signs into your organization on the central
server with one command,
hyp remote login, and forwards its recordings there. One history follows you across machines and harnesses, and usage, spend, and activity can be queried and reported across the whole team. - Solo, fully local. No central server, no account. Everything stays in
a local query cache on your machine. Start with
npx hypaware.
Part of HypStack, an open-source stack for AI observability.
Contents: Requirements · Quickstart · Team setup · Files · Querying · Activity graph · Clients · Privacy controls · Daemon · Troubleshooting · Uninstalling · Project documents
- Node.js >= 22.12
- macOS (launchd) or Linux (systemd
--user) for the persistent daemon
npx hypawareWhen run through npx, the walkthrough also installs a durable global copy
of the CLI (npm install -g hypaware) so the daemon and the hyp command
outlive the npx cache. Every command below is available as both hyp and
hypaware.
On a TTY this launches the interactive walkthrough:
-
Pick the sources to capture. Any subset of:
- Claude Code conversations (
claude) - Codex conversations, CLI and Desktop (
codex) - OTEL logs / traces / metrics (
otel)
The raw proxy sources (
raw-anthropic,raw-openai) are not offered in the menu. They open a gateway upstream but configure no client and carry no projector of their own, so on their own they proxy traffic and record nothing. They remain real sources:hyp setup --source raw-anthropicstill composes one, and a config that already collects one keeps it through a reconfigure (LLP 0202). - Claude Code conversations (
-
Pick an export strategy: keep the local query cache only, write Parquet files under
<HYP_HOME>/exports, or configure later. -
The retention window is not asked: the pathway sets it,
90days on a team install and120on a local-only one.hyp setup --retention-days <N>overrides it, andquery.cache.retentionin the written config remains the post-install knob. -
HypAware composes a minimal config with only the bundled plugins it needs, writes it to
<HYP_HOME>/hypaware-config.json, installs the persistent daemon (launchd on macOS, systemd--useron Linux), attaches the selected clients, and starts capturing. -
The walkthrough finishes by printing the config path, daemon status, per-client attach results, and a first look at what was captured: token volume per model, activity per day, which repos the sessions ran in, and which tools got called. Reprint it any time with
hyp query overview. -
Last, it offers a few questions worth asking of that data and starts your AI client on the one you pick, opening straight into the answer. Pick it up again any time with
hyp ask, or skip the menu withhyp ask "which sessions touched the auth module".
For unattended installs (CI, scripted bootstraps, dotfiles) use the non-interactive flags:
hyp setup --yes \
--source claude --source otel \
--client claude \
--export local-parquet \
--retention-days 90Other init flags:
| Flag | Meaning |
|---|---|
--yes / -y |
Accept defaults; do not prompt |
--no-daemon |
Skip daemon install and restart |
--dry-run |
Render the config + planned actions, write nothing |
--client claude|codex |
Attach a client (repeatable) |
--source <id> |
Add a capture source (repeatable) |
--export <choice> |
keep-local, local-parquet, or configure-later |
--retention-days <N> |
Override the default 90-day retention window |
--from-file <config.json> |
Skip the picker and load a known-good config |
--bin <path> |
Override the binary path the daemon installer uses |
If your organization is set up on the central server, enrolling a machine is one command:
npx hypaware remote loginThis opens a browser sign-in. Your organization is resolved from your work
email domain, and the machine enrolls itself: it provisions the forwarding
sink, stores a per-machine credential (mode 0600, never in shell history),
installs the persistent daemon, and starts capturing and forwarding. No
bootstrap token, no URL to copy, no hand-edited config.
The same sign-in also unlocks remote queries, so you can ask questions across the whole team's recordings, not just this machine's:
hyp query sql "select count(*) from ai_gateway_messages" --remotePrivacy review before anything ships. Nothing is forwarded immediately.
The first sync (which includes backfilled history) waits until 11:59pm local
time on the day you enroll, and the login prints the exact deadline. Before
then, open Claude or Codex and run the hypaware-privacy skill to review what
will ship, mark directories ignore / local-only / sync, and purge anything
sensitive. Done reviewing, or want to see data on the server sooner? hyp sync
shows what would leave and sends it once you confirm.
Useful login flags: --no-forward signs in for remote queries only (no
enrollment), --no-browser prints the sign-in URL instead of opening one,
--token-file <path> / stdin supply a static token, and --host <label>
overrides the host label the server shows for this machine.
Want this for your team? We host organizations on the central server. Get in touch and we will set one up for your email domain; after that, everyone on the team onboards with the single
hyp remote loginabove.
For the full rollout story (fleet tokens, managed config, Claude Desktop capture, verifying machines) see the team setup guide; for what enrollment means for each person's data, see what HypAware records and how to control it.
For scripted rollouts (MDM, dotfiles, CI images) where no browser is
available, hyp join enrolls a host with a fleet policy token instead of an
interactive sign-in:
hyp join <url> [token]
hyp join <url> --token-file <path> # read the token from a file (recommended for MDM)
echo "<token>" | hyp join <url> # or from stdin
hyp join <url> <token> --no-daemon # write the seed only, skip daemon installIt writes a central-enrollment config (mode 0600) to a dedicated layer under
config-control/, never to your local hypaware-config.json, so joining
augments an existing install rather than replacing it, then installs and starts
the daemon (unless --no-daemon is passed).
The policy token is a multi-use fleet-wide credential. Prefer --token-file
or stdin over a positional argument, which would otherwise land in shell
history and process listings. Other flags: --bin <path> overrides the binary
the daemon installer records, and --no-daemon writes the seed without
installing or restarting the daemon.
| Path | Contents |
|---|---|
<HYP_HOME>/hypaware-config.json |
Active config (rewritten by hyp setup) |
<HYP_HOME>/hypaware/ |
Kernel state root |
<HYP_HOME>/hypaware/plugins/<name>/ |
Per-plugin state |
<HYP_HOME>/hypaware/cache/ |
Local query cache (Iceberg-backed) |
<HYP_HOME>/hypaware/sinks/<name>/outbox/ |
Failed export rows awaiting retry |
<HYP_HOME>/hypaware/dev-telemetry/ |
Daemon self-telemetry (logs, traces, metrics) |
<HYP_HOME>/hypaware/logs/daemon.{out,err}.log |
Daemon stdout / stderr (launchd / systemd) |
<HYP_HOME>/exports/ |
Local Parquet exports (when the local-fs sink is enabled) |
HYP_HOME defaults to ~/.hyp. Override it by exporting HYP_HOME=...
before invoking the CLI or the daemon.
Start with the overview: input, cached and output tokens per provider and
model, the same per day, which repos the sessions ran in, and which tools
get called - the same block hyp setup ends on.
hyp query overview # --json to script it, --sql to print the queries
hyp query overview --days 90 # widen the window past what fits by defaultThe block states the period it covers. It picks a window it can summarize quickly, so a large cache narrows the period rather than hanging - and the line under the title always says which days the numbers describe.
Input is prompt sent fresh and cached is prompt served from (or written
to) the cache, so input + cached is the whole prompt; output is what the
model generated.
Then query anything directly:
hyp query sql "select count(*) from ai_gateway_messages"
hyp query sql "select count(*) from traces"
hyp query sql "select count(*) from logs"Use hyp query schema <dataset> to see the columns available on each
dataset, and hyp cache status to inspect cache freshness per dataset.
Alongside the row datasets, HypAware can project captured activity into a
node/edge activity graph: which sessions ran in which app, against which
model, using which tools, touching which files. The projection is
deterministic (exact-key matching, no models), and the context-graph plugins
are active by default.
Projection is a manual, cheap-to-rerun step. Build or refresh the graph from what has been captured, then walk it from a seed node:
hyp graph project # project captured data into the node/edge graph
hyp graph compact # merge duplicate rows (optional housekeeping)
hyp query graph neighbors <node> --depth 2 # walk out from a seed nodehyp query graph neighbors takes a node_id, natural key, or label as the seed,
plus --depth, --direction out|in|both, --type <node_type>, --edge-type <type> (repeatable), and --limit. The graph is also plain data: the node
and edge datasets are queryable through hyp query sql like any other
dataset.
This plugin ships a graph_neighbors tool and the hyp graph help that
explains the traversal, and the hypaware-query skill covers when to ask the
graph rather than the messages, so an assistant can project and walk the graph
on your behalf.
Attach a single client (idempotent: running twice is a no-op):
hyp client attach <client> # claude, codex, openclaw, ...
# Equivalent flag form:
hyp client attach --client <client>
# Pre-rollover spelling, still accepted:
hyp attach <client>Detach (removes only HypAware-managed settings):
hyp client detach <client>
# Equivalent aliases:
hyp client detach --client <client>
hyp detach <client>
hyp unattach <client>Both commands support --dry-run and --json for inspection and
scripting. Each adapter writes only HypAware-managed settings to its
client's own config file (for example ~/.claude/settings.json for
Claude, a hypaware provider entry in ~/.codex/config.toml for
Codex); unrelated keys in every file are preserved.
hyp client attach claude writes one reversible env block into
~/.claude/settings.json that turns on Claude Code's own OpenTelemetry
export and points it at a loopback listener the daemon runs. It leaves
ANTHROPIC_BASE_URL alone, sets no proxy, and installs no certificate
authority, so Claude Code still talks straight to api.anthropic.com,
Remote Control keeps working, and a daemon that is down or wedged costs
you capture rather than your session. Nothing has to be quit and reopened:
Claude Code reads the env block at launch, on every launch path.
Two things ride along with the conversation rows:
- Raw request and response bodies land in
~/.hyp/spool/claude-bodies(owner-only) until the listener projects them and deletes them. They carry what the events do not: the system prompt, the tool list, and untruncated tool arguments. The directory is capped (512 MB by default, oldest evicted first), and bothhyp privacy purgeandhyp client detach claudeempty it. - Behavioral signals the wire never showed land in their own
claude_telemetry_eventstable: tool accept and reject decisions, permission mode changes, per-request cost, hook and MCP health.
Claude Code 2.1.193 or newer is required (2.1.214 for the full
tool-decision detail). Below the floor, attach refuses the switch, leaves any
existing attach exactly as it is, and prints claude update, rather than
silently capturing less.
hyp client detach claude removes exactly those keys, restores anything they
displaced, and sweeps the spool.
If this machine was attached by proxy before, hyp client attach claude is also the
migration: it releases the proxy keys, unwinds the launchd environment, and
tells you how to end the CA trust that it will not end for you
(hyp client detach claude --purge).
Claude Code no longer uses this path. It remains how the gateway captures a
client that cannot simply be pointed at a different base URL. Turn it on in
the ai-gateway section of ~/.hyp/hypaware-config.json and restart the
daemon:
{ "name": "@hypaware/ai-gateway", "config": { "proxy_mode": true } }hyp daemon restartSuch a client is then pointed at the gateway with HTTPS_PROXY and
NODE_EXTRA_CA_CERTS rather than a base URL. What that changes:
- A machine-local certificate authority is generated under
~/.hyp/hypaware/tls, readable only by you, and name-constrained so it cannot vouch for any host outside the provider set HypAware intercepts. Trust stays file-scoped to the proxied client's own settings: nothing installs it into any OS trust store, including your login keychain, and anything wider is your own decision. Earlier releases attached Claude Code by proxy and did add the CA to the macOS login keychain as a user-domain trusted root, for a transport that trusts only the keychain; macOS raised its own password dialog for that, it never needed admin rights, and the machine-wide system keychain was never touched. If you ran one of those releases, that trust setting is still on your account until you remove it.hyp statusshows the fingerprint, every host the CA is permitted to vouch for, and whether the login keychain still trusts it.hyp client detach <client>leaves the CA and any trust an earlier release was granted in place, because a detach is not a statement about the certificate and no attach re-creates the grant;hyp client detach <client> --purgeandhyp daemon uninstallremove both. - On macOS, an earlier proxy attach also left a login-session variable
behind. Bun picks its trust store before any settings file is read, so a
keychain root only counts if
NODE_USE_SYSTEM_CA=1is already in the process environment. The attach that trusted the CA therefore ranlaunchctl setenv NODE_USE_SYSTEM_CA 1and installed a small LaunchAgent,~/Library/LaunchAgents/com.hyperparam.hypaware.node-system-ca.plist, whose only job is to re-run that command at each login. No attach writes either one today; on a machine that ran one of those releases the agent stays a login item until it is removed, and the variable stays session-wide for other Node programs to read too.launchctl setenvreaches processes launched after it, so a terminal app that was already running must be fully quit and reopened.hyp client detach <client> --purgeandhyp daemon uninstallclear both unconditionally, andhyp client attach claudeunwinds them when it migrates a previously proxied machine. A plainhyp client detach <client>only clears them while that client's attach marker still records a proxy attach, so on a machine already migrated to another attach mode it is not the command that removes the leftover.hyp statusshows whether the variable is currently live. - Only the hosts a registered upstream names are decrypted. Every other host the client talks to is tunnelled through without being decrypted.
- What gets recorded does not change. Only the recorded API paths are stored; the other paths a client calls on the same host are passed through without being stored.
Two things to know before turning it on:
- If the daemon is not running, a proxied client's HTTPS all fails, not just
its model calls. Attach refuses to write the settings unless proxy mode is
actually running, and
hyp client detach <client>is the escape hatch. - If you already use a corporate proxy, set
upstream_proxyto it so traffic still chains through it. Attach warns and backs up your existingHTTPS_PROXY(restored on detach) rather than silently replacing it:
{ "name": "@hypaware/ai-gateway",
"config": { "proxy_mode": true, "upstream_proxy": "http://proxy.corp:8080" } }Codex is unaffected and keeps using the base-URL mechanism.
Codex Desktop needs no separate setup. hyp client attach codex covers the
Codex CLI and Codex Desktop together, because the two share the file it
writes (~/.codex/config.toml, or $CODEX_HOME/config.toml) and the
history it backfills (~/.codex/sessions/**). Rows from either surface land
in ai_gateway_messages; the entrypoint column carries Codex's
originator, which is what tells a Desktop session from a terminal one.
Claude Desktop does need its own setup (hyp client claude-desktop install),
and hyp init will not offer it: Claude Desktop is the one client whose setup
takes a browser sign-in and a sudo prompt to place a root-owned
managed-preferences plist, which is not something a first-run checklist should
ask for (LLP 0297). It is opt-in, macOS-only, and always explicit: enable the
plugins in ~/.hyp/hypaware-config.json, then run the install. See
the CLI reference for the
exact plugins[] entries.
hyp client claude-desktop install
hyp client claude-desktop verifyThe vendor difference is why the shape is different, not a gap in Codex
support: Claude Desktop exposes no user-writable settings file to amend, so
HypAware configures it through that plist, and it delegates inference to its
embedded CLI (rows arrive as client_name = 'claude' with
entrypoint = 'claude-desktop-3p').
What HypAware does not do for Codex Desktop: it never parses the app's
own container at ~/Library/Application Support/Codex. That store is
opaque and undocumented, so hyp client history import codex flags it as an
unsupported_location and moves on. It is not the only copy of those
conversations, so nothing is lost: live traffic is captured through the
gateway, and past sessions come back from ~/.codex/sessions. The same
applies to the ChatGPT desktop app and browser storage, which HypAware does
not capture at all.
See LLP 0141
for the reasoning, and docs/ACCEPTANCE.md for the
manual check that Desktop traffic is actually landing.
Every directory subtree resolves to a usage class, evaluated gitignore-style
from an exchange's working directory: sync (recorded, forwarded to the
team server if enrolled; the default), local-only (recorded, never
forwarded), or ignore (never recorded; the live LLM call is untouched,
only persistence is suppressed). When multiple markings apply, the most
restrictive wins.
There are two ways to mark a subtree:
hyp privacy ignore [path] # write a committable .hypignore dotfile (travels with the repo)
hyp privacy unignore [path] # remove it, re-enabling recording
hyp privacy set <path> ignore # same effect, stored machine-local (no dotfile in the repo)
hyp privacy set <path> local-only # recorded but never forwarded
hyp privacy set <path> sync # explicitly synced, not asked again
hyp privacy show [path] # which class governs, and from which source
hyp privacy list # every machine-local entry
hyp privacy unset <path> [class] # back to the implicit defaultOn a machine connected to a server, folders you have not marked sync without asking. If you would rather be asked once per new folder, a session opened somewhere new can prompt you to classify it instead:
hyp privacy folders ask # ask once per new folder
hyp privacy folders sync # back to syncing without asking (default)
hyp privacy folders # report which is in forceThis gates the question only: folders you already marked keep their class,
and .hypignore files are unaffected either way. hyp setup asks for this
in its own step, and hyp status names it on an enrolled machine.
Markings are prospective only: rows captured before a marking existed stay in the cache. Delete those with the separate destructive step:
hyp privacy purge <path> | --session <id> | --ignored | --all # delete already-cached rows (prompts; --yes to skip)To pause recording for just the current Claude or Codex session (in-memory,
reversible) run hyp session ignore from inside it; hyp session unignore
resumes and hyp session status reports the current answer.
The full model, including what enrollment forwards and the first-sync
privacy review, is in
what HypAware records and how to control it. One
caveat worth repeating: directory markings need a working directory, which
only the Claude and Codex pathways supply, so they are a no-op for the
raw-anthropic / raw-openai proxy and OTEL sources.
hyp daemon install # launchd LaunchAgent (macOS) or systemd --user unit (Linux)
hyp daemon start # ensure the service is started
hyp daemon status # health snapshot
hyp daemon restart # bounce after a config change
hyp daemon stop # signal the running daemon to shut down
hyp daemon uninstall # remove the service and detach clients (config + recordings are kept)hyp daemon install --dry-run --json prints the rendered plist or unit
content and target paths without touching the filesystem, useful for
verifying what hyp setup will install.
hyp status is the entry point for any "is HypAware working?" question.
It prints the active config path, daemon install/run state, active
plugins, source and sink rows, per-client attach state, retention
window, cache size, and a recent-error count. Pass --json for the
stable machine-readable shape that smokes and support tools rely on:
hyp status
hyp status --jsonWhen something is wrong, hyp status surfaces a diagnostics: section
with one row per finding. Each row carries a kind (a stable
machine-readable identifier) and one or more repair: lines you can
run directly. The common Phase 8 conditions:
| kind | meaning | repair |
|---|---|---|
config_missing |
no ~/.hyp/hypaware-config.json was found |
hyp setup or hyp setup --from-file <config.json> |
config_invalid |
the loaded config failed schema / cross-plugin validation | hyp setup --from-file <config.json> |
client_without_gateway |
a client plugin (Claude / Codex) is enabled but @hypaware/ai-gateway is not |
re-run hyp setup, then hyp client attach --client <name> |
gateway_missing_anthropic_upstream |
a gateway-routed Anthropic client (OpenClaw) is enabled but no Anthropic upstream is registered | re-run hyp setup and pick the Anthropic upstream |
gateway_missing_openai_upstream |
@hypaware/codex enabled but no OpenAI upstream is registered |
re-run hyp setup and pick the OpenAI upstream |
sink_missing_encoder |
a local-fs sink is configured but no encoder plugin is enabled | re-run hyp setup and pick "local Parquet export" |
client_attach_missing |
a client plugin is enabled but its settings file shows no HypAware marker | hyp client attach --client claude or hyp client attach --client codex |
daemon_binary_missing |
the daemon installer references a binary that no longer exists on disk | hyp daemon install |
daemon_loaded_no_pid |
the daemon service file is installed but launchd / systemd is not loading it | hyp daemon restart |
recent_errors |
the local telemetry directory has recent error log entries | inspect ~/.hyp/hypaware/dev-telemetry, then hyp daemon restart |
Useful follow-on commands when a diagnostic fires:
hyp daemon restart: bounce the persistent daemonhyp daemon install: re-install the launchd / systemd unithyp client attach --client claude/hyp client attach --client codex: wire a selected client into HypAware capturehyp setup --from-file <path>: rebuild the config from a known-good file without re-running the interactive picker
To remove HypAware from a machine completely:
hyp leave # only if enrolled with a team server: stop forwarding, drop the credential
hyp daemon uninstall # remove the launchd / systemd service and detach every attached client
npm uninstall -g hypaware # remove the CLI
rm -rf ~/.hyp # delete all local recordings, config, and statehyp daemon uninstall restores each attached client's own settings on its
way out, so no client is left pointing at a gateway that no longer exists;
to detach a single client without uninstalling, use hyp client detach <client>.
The first three steps are non-destructive and reversible; deleting ~/.hyp
permanently removes every local recording. Note that copies already
forwarded to a team server or exported to Parquet are not affected; see
docs/PRIVACY.md.
User-facing guides live under docs/:
docs/CLI.md: install, operate, upgrade, and recover HypAware with the task-oriented CLIdocs/CLI_REFERENCE.md: complete syntax and behavior for every visible CLI commanddocs/TEAM_SETUP.md: rolling HypAware out across a teamdocs/PRIVACY.md: what HypAware records and how to control itdocs/PLUGIN_AUTHORING.md: how to write a plugin (hyp dev plugin new/hyp dev plugin doctor)docs/ACCEPTANCE.md: opt-in, manual pre-release checks that need a real client (e.g. Codex Desktop)
Contributor material (repository layout, release checklist, test model)
lives in AGENTS.md.
Design rationale lives in numbered LLP documents under llp/
(Linked Literate Programming). Start here:
llp/0000-hypaware.explainer.md: root overview and subsystem mapllp/0002-v1-scope.decision.md: what actually shipped in V1llp/0001-adopting-llp.plan.md: how this docs system was set up
The former monolithic docs (hypaware-design.md, finish-v1.md,
hypaware-implementation-plan.md) were decomposed into the LLP corpus and are
preserved under llp/tombstones/. Public plugin
interfaces are declared in
hypaware-plugin-kernel-types.d.ts.