# Crush

Canonical: https://hypaware.ai/docs/integrations/crush

**Status:** Supported. **Setup id:** `crush`. **Backfill:** Yes.

HypAware reads [Crush](https://github.com/charmbracelet/crush)'s local
session databases read-only. Crush keeps one database per project, at
`.crush/crush.db` in the project's git root, and lists every project in its
index, `~/.local/share/crush/projects.json`. HypAware polls the databases
every 60 seconds for new messages, and a scheduled import every 15 minutes
brings in existing sessions. It does not route Crush's model traffic or
change Crush's settings. Tested with Crush v0.99.0.

## What is recorded

Sessions and messages, including your prompts, Crush's responses and
reasoning, tool calls and their output, commands you run from Crush's shell
mode (recorded as a tool call and its output, not as a prompt), conversation
summaries, the provider and model of each response, and the project
directory. Images and other attachments are recorded as a placeholder, not
their contents. A session's title is generated by the model from your
conversation, so it is treated as message content.

Sessions Crush starts for a sub-task are recorded as their own sessions,
linked to the session that started them. The sessions Crush uses only to
generate titles are never read.

Crush does not store token counts per response, so no row carries token
usage. A top-level session's row carries Crush's running cost for it in US
dollars, sub-tasks included, as the `crush.session_cost_usd` attribute; it is
left out while the cost is 0.

Crush adds a context message to each request it sends to the model and does
not store it. The rows hold what you and the model wrote, not the whole
request.

HypAware never reads Crush's `files` and `read_files` tables, which hold
copies of the files Crush has read or changed, its `crush.json`
configuration, its `crush.log`, or any credentials.

## Set it up

`hyp setup` offers Crush when it finds the project index. On a new
installation you can pick it without the prompts:

```sh
hyp setup --source crush
hyp status
```

To add Crush to an existing installation, run `hyp setup` in a terminal,
choose **Reconfigure**, and select Crush; your current choices stay selected.
`hyp setup --source crush` refuses to change an existing configuration, and
`--force` replaces it rather than adding to it.

This integration installs no skills into Crush.

### Use a different data location

The daemon does not see a `CRUSH_GLOBAL_DATA` or `XDG_DATA_HOME` set in your
shell, because it runs under launchd or systemd with its own environment, so
it reads the index at the default path. If you set either variable, or want
to name project data dirs directly, add this entry to the existing `plugins`
list in your HypAware configuration, preserving the other entries:

```json
{
  "name": "@hypaware/crush",
  "config": {
    "data_dirs": ["/absolute/path/to/project/.crush"]
  }
}
```

Each entry is a project's `.crush` directory. HypAware reads these as well as
the projects the index lists, up to 256 entries.

See [configuration](https://hypaware.ai/docs/configuration/index.md#locate-and-validate-configuration)
for the config location, then apply and check the change:

```sh
hyp config validate
hyp daemon restart
hyp status
```

## Import existing history

Setup does not import your existing sessions itself. The scheduled import
picks them up within 15 minutes, or run it now:

```sh
hyp backfill crush --dry-run
hyp backfill crush
```

New messages arrive on the next poll, up to a minute after Crush writes them.
A scheduled import also runs every 15 minutes. It picks up changes Crush
makes to a message it already finished, so those can take up to 15 minutes
to appear. Set `backfill.window_days` to limit both imports to recent
sessions. With `backfill.on_join` set to `false`, neither runs.

## Privacy

Directory markings and `.hypignore` apply to each session's project
directory. To stop recording one session, pass its HypAware session id,
which is `crush-` followed by the Crush session id. List the ids HypAware has
recorded with:

```sh
hyp query sql "select distinct session_id from ai_gateway_messages where client_name = 'crush'"
hyp session ignore crush-<session-id>
```

HypAware reads saved exclusions on the next Crush poll, so an ignore takes
effect within a minute.

The command saves the exclusion through the HypAware gateway, so it works only
while HypAware also records another client through its gateway. On an install
that records only Crush, it prints one `hyp session` error line, exits `3`, and
saves nothing.
Ignore the project directory instead, which also stops recording every other
Crush session in that project:

```sh
hyp privacy ignore /path/to/project
```

See [marking directories](https://hypaware.ai/docs/privacy/index.md#marking-directories).

**Crush makes its own network calls.** HypAware does not change them. Crush
v0.99.0 sends usage metrics unless `CRUSH_DISABLE_METRICS` or `DO_NOT_TRACK`
is set or `options.disable_metrics` is `true` in `crush.json`, and fetches
its provider catalog from `catwalk.charm.land` unless
`CRUSH_DISABLE_PROVIDER_AUTO_UPDATE` is set. It also checks
`api.github.com` for a newer release each time it starts, and v0.99.0 has no
setting that turns that check off.

## Limits

- Reading a database can leave an empty `crush.db-wal` and a 32 KiB
  `crush.db-shm` in the project's `.crush/` directory until Crush next closes
  it cleanly. These are SQLite's own index files and hold no content.
- A daemon under launchd or systemd reads only the default index. Projects
  kept under a custom `CRUSH_GLOBAL_DATA` or `XDG_DATA_HOME` need
  `data_dirs`.
- At most 1,024 project databases are read. `hyp status` counts the ones
  skipped.
- If Crush changes its database schema, `hyp status` reports the missing
  table or column and HypAware records nothing from that database until a
  release supports the new schema. It never writes partial rows.
- Capture needs Node 22.12 or later.

For status messages and fixes, see
[troubleshooting](https://hypaware.ai/docs/troubleshooting/index.md#crush-records-nothing).
