Maintenance
Most problems need only one part of the archive refreshed. Check health first, then pick the smallest command that fixes what is stale.
- App
- Settings → Imports
- CLI
hansard doctor
Check health in the app
Section titled “Check health in the app”-
Open Settings → Imports. Check that Background import is running, whether Pause search updates is on, the Selection mode and the agents it follows, and the Look-back window.
-
Select Incomplete runs to see runs that stopped before saving any messages. Hansard keeps them out of Sessions, search, and Stats.
-
If a conversation seems missing, open Sessions, select Filter & sort, select Reset, and then set Source and Time one at a time.
-
Open Settings → About to confirm the running version and whether an update is available.
Settings → Imports → Maintenance runs the common repairs without a terminal:
| Row | What it does | CLI equivalent |
|---|---|---|
| Refresh archive data | Re-derives titles, tool usage, and views after an update. | hansard rebuild --since all |
| Re-read with current importers | Re-imports conversations that older importers archived. | hansard rebuild --stale-parsers |
| Rebuild search index | Rebuilds search from the archive. | hansard index rebuild |
| Restore Claude Code files | Puts back session files Claude Code deleted, from Hansard’s copies, after a review. | hansard repair claude-code-backups |
| Recover Antigravity conversations | Reads older conversations through the running Antigravity app. | hansard import antigravity --recover |
| Recover Windsurf conversations | Reads trajectories through the running Windsurf app. | hansard import windsurf --recover |
| Recover Cursor models and usage | Reads each request’s model and tokens from your Cursor account. | hansard import cursor --recover |
| Run diagnostics | Checks sources, storage, and setup. | hansard doctor |
Refresh after updates controls automatic archive refresh. The watcher
updates older conversation data, reparses supported preserved originals, and
converts eligible storage formats while imports are idle and the computer has
AC power. It preserves newer files and refuses parses with fewer messages.
Turn it off with hansard config set archive.autoRefresh false.
hansard status reports its progress. See Background work
for scheduling, resource controls, and restart behavior.
Import older history on the same page reads each agent’s history again, as far back as you choose. When the watcher runs a different copy of Hansard than the app, Importer version names it; see Several copies of Hansard. Full reimports, raw recovery, and update recovery run from the CLI.
Check health from the CLI
Section titled “Check health from the CLI”hansard statushansard doctorhansard index statushansard watcher statushansard import statusstatus shows the active paths, watcher, conversation counts, search index,
sync, and recent imports. doctor checks required tools, sources, the search
index, login startup, and sync, and lists commands for anything it flags. It
also reports harness history that has disappeared since Hansard archived it,
the slowest steps of recent watcher passes under watcher ticks, and, under
agent hooks, hooks that failed or passed their 3.5-second limit in the last
seven days.
doctor also counts conversations four ways: the archive’s conversation files,
the session list, the session records Stats reads, and search. The four numbers
match on a healthy archive. When they differ, doctor names the repair, usually
hansard index rebuild. A conversation imported in the last few minutes shows
as not searchable yet until the watcher’s next index pass.
Run hansard doctor --deep for an archive-wide check of parser versions,
missing sources, and import health; it also reads every search document. Add
--json to status or doctor for machine-readable output.
Search index repairs and disk space
Section titled “Search index repairs and disk space”The four conversation counts include received sessions, subagents, SDK jobs, and machine probes. A cloud chat copy counts as searchable when another copy of that conversation is indexed. Diagnostics compare stored rows with their metadata files. A newer store or index calls for a Hansard update instead of a rebuild. An unreadable metadata file is reported without a repair command.
Resume paused indexing with hansard index resume before rebuilding.
A rebuild can continue past a conversation with damaged stored events. It
keeps that conversation’s metadata and the passages read before the failure,
and reports the conversation in the rebuild, index status, and watcher log.
If it would skip more than 10 conversations, or 2% when larger, it fails and
keeps the existing index. A permission error also stops replacement.
Ordinary watcher passes replace only changed conversation passages and remove
deleted ones. A title edit replaces only its summary passage and shared
record. A passage-format update refreshes affected passages while search keeps
working. hansard index rebuild replaces the whole index, or refreshes all
passages in place when other processes keep it open, and reports that choice.
A separate rebuild needs free space above the storage floor:
- At least 512 MiB.
- About 1.25 times the live index size when the current version built it.
- About twice the live index size after an index-version change.
A build that exceeds its allowance retries with twice the allowance, up to 16 GiB. Updating an index in place needs about its live size free above the floor for the write log. Search continues using the existing index during a failure or storage refusal. Watcher retries start after a minute and double up to 30 minutes. A storage refusal can retry sooner when enough space returns.
Choose the right refresh
Section titled “Choose the right refresh”| Symptom | Command | Reads harness history? |
|---|---|---|
| The app shows an outdated layout, title, or tool summary | hansard rebuild |
No |
| Search or lists miss conversations that exist | hansard index rebuild |
No |
doctor --deep reports an older parser version |
hansard rebuild --stale-parsers |
Yes, for each source an older release imported |
| Conversations from one source are missing or wrong | hansard import --source <id> --since all |
Yes |
| The harness’s history is gone but Hansard kept the originals | hansard rebuild --from-raw |
No, reads preserved originals |
| A project moved to a different repository | hansard repair repo-keys |
No |
| Release notes require a complete reimport | hansard update |
Yes, all configured sources |
Each release starts a new parser version, so right after an upgrade
doctor --deep reports every source, and hansard rebuild --stale-parsers and
Re-read with current importers re-read every local source. Prefer the
narrower commands the release notes name.
hansard rebuild accepts --provider, --since, and --force. --from-raw
and --stale-parsers also accept --source-type and --session:
hansard rebuild --provider cursor --since 90dhansard rebuild --force --since allhansard rebuild --from-raw --source-type claude-web-exportArchive format 2 is the default. It keeps each conversation’s Markdown
gzip-compressed, the events of large conversations as event records, and their
views only as compressed pages, and updates a growing conversation’s
transcript in place. A configuration in which an earlier release saved format
1 reads as format 2. Conversations archived before keep their files until
--format 2 converts them; --format 1 writes them back as plain
conversation.md, events.jsonl, and view.json. A record that no longer
matches its transcript stays, with its pages, unless
HANSARD_ACCEPT_OLDER_DERIVED=1 is set, since the events derived in its place
would be redacted with the rebuilding process’s inputs rather than the
import’s.
hansard rebuild --since all compresses the Markdown that earlier versions
kept plain, typically to about 35–40% of its original size. Automatic refresh
also converts eligible conversations after an update. Otherwise, each
conversation’s Markdown is compressed when it is next written or read. Commands that
hand out the Markdown’s path, such as hansard show --path, name a plain copy
in Hansard’s cache, which cache cleanup removes after 30 days unused. Exports
and uploads still carry a plain conversation.md.
hansard rebuild --format 2 --since allThe archive.format setting, not this flag, decides what
later imports write. Earlier Hansard releases cannot read all of it, so
imports keep writing format 1, and --format 2 refuses, while a copy of
Hansard that may open the archive lacks the format 2 readers. Update every
copy on the computer, the desktop app and an npm installation alike, first.
hansard config set archive.format 2 names those copies. To keep format 1, run
hansard config set archive.format 1. Before you move back to a release that
cannot read format 2, run hansard rebuild --format 1 --since all and
hansard config set archive.format 1.
Under archive format 2, rebuild first cuts a partial last line that an
interrupted update left in a selected conversation’s transcript or reveal
cache file. hansard doctor reports such lines and cuts them when no import is
running.
rebuild starts from the conversation files already in the archive, so it
cannot apply a new parser. A stale search index, in turn, never needs a
reimport. Preview --from-raw and --stale-parsers with --dry-run.
--from-raw supports sources preserved one file per session, browser captures
such as ChatGPT, Claude.ai, Perplexity, and Devin, Claude.ai account exports,
and the Devin CLI, OpenCode, and MiMo Code databases, which it rebuilds as a
whole snapshot. Other shared databases and multi-session exports report that
they are unsupported. The watcher’s
refresh after updates leaves
Devin CLI, OpenCode, and MiMo Code snapshots as they are, so
hansard rebuild --from-raw is the way to refresh them.
hansard rebuild leaves a conversation whose transcript needs more memory than
the process has as it is, so one oversized conversation does not end the run.
It counts such conversations under Left for a larger heap and prints the
NODE_OPTIONS=--max-old-space-size value that refreshes them.
Returning a rebuilt SQLite snapshot to ordinary live imports currently needs
a full archive refresh. Preview hansard update --dry-run first. Its
--sources option selects the reimport inputs and does not limit archive
cleanup. See Run a full refresh before proceeding.
hansard repair repo-keys finds sessions whose folder now resolves to a
different repository, for example after a remote was renamed. It prints the
import commands that re-file them.
Several copies of Hansard
Section titled “Several copies of Hansard”The desktop app, the npm CLI, and a source checkout can share one archive, and
each imports with its own importers. The watcher runs whichever copy started
it; when that copy differs from the app’s, hansard status and
hansard doctor name it under watcher copy, Settings → Imports →
Importer version names it, and Use this version moves the watcher and login
startup to the app’s copy.
An import never rewrites a conversation that a newer importer archived,
because an older importer can drop attachments, models, or tool details the
newer one extracts. New messages in such a conversation wait for a copy with
the newer importer. hansard status, hansard doctor, and the
Importer version row count them. HANSARD_ACCEPT_OLDER_PARSERS=1 allows a
deliberate downgrade.
Files Hansard derives from a conversation follow a similar rule when a copy
reads a conversation or runs hansard rebuild. Neither rewrites the events,
views, conversation Markdown, tool usage, or inferred titles that a newer
version wrote; the copy shows its own reading of events and views in memory
instead, and hansard rebuild skips those files and counts the conversations
it kept. HANSARD_ACCEPT_OLDER_DERIVED=1 allows a deliberate downgrade. An
import rewrites all of a conversation’s derived files, so only the importer
rule above keeps an older copy from replacing them.
An older copy can read a newer session or search index when that index’s reader version allows it. It never updates or replaces the newer index. When a memory index is newer, it reads memory records directly. Running processes notice these version changes without restarting.
Restart the watcher
Section titled “Restart the watcher”hansard watcher restarthansard watcher logs --followRestart after changing storage. The watcher applies a changed source list
within 30 seconds and moves to a new version of Hansard on its own; a restart
makes either take effect now. To back
up harness memories outside the watcher’s 15-minute schedule, run
hansard memory backup. Unchanged memories do not create new snapshots.
Save a conversation before a repair
Section titled “Save a conversation before a repair”hansard export <session-id> --out ./session-exportThis copies the conversation files and attachments. Add --include-raw to
also copy the original harness files. Those are not redacted, so store the
export somewhere as private as the archive.
A raw export includes the chunk dependencies needed to verify preserved source
bytes independently. Hansard reserves space on the destination volume. An
interrupted export can leave completed files. Use --force to retry into the
same directory after reviewing its contents. Exported files remain in storage
accounting until they are removed and usage is measured again.
Recover missing harness files
Section titled “Recover missing harness files”When hansard doctor reports that a harness deleted its original files,
Hansard can put its preserved copies back so the harness and the importer can
read them again:
hansard restore-sources claude --dry-runhansard restore-sources claudehansard import --source claude --since allrestore-sources writes only files that are missing from their original
paths. It never overwrites a file and never restores shared databases. For
ChatGPT and Claude.ai, it lists the newest preserved exports and the commands
that import them again.
Claude Code has a dedicated repair with an explicit confirmation:
hansard repair claude-code-backups --dry-runhansard repair claude-code-backups --yeshansard import --source claude --since allReclaim disk space
Section titled “Reclaim disk space”hansard prune archive-objects --dry-runhansard prune sync-outbox --dry-runWith Personal Sync and a verified storage copy, hansard storage offload also
frees space by removing original files and attachments older than 30 days from
this computer. See
Offload old files to the backup.
archive-objects deletes stored originals, attachments, and artifacts that no
session references anymore, after a one-day grace period. For older shared
snapshots, it keeps the newest copy and one per day for --keep-days days
(default 7). Anything it cannot verify is kept.
sync-outbox deletes local upload copies that have already reached their sync
destination, and the records of uploads that a newer snapshot replaced, that
were abandoned, or whose object the archive no longer keeps. It also releases
the local copy of the latest upload once every configured Personal Sync
destination holds its exact files, after a 15-minute grace. It then returns
the space they used to the disk. Remote backups do not change.
The watcher schedules archive cleanup separately from successful imports, normally every 15 minutes. It waits while source changes or queued imports are ready. Lock contention or a failed sweep retries after one minute. The last successful sweep time remains visible after a failure.
Run cleanup by hand to reclaim space now, or to include received copies
and older shared snapshots. Remove --dry-run to delete after a confirmation,
or replace it with --yes to delete at once.
hansard prune archive-objects --dry-run --json explains anything that blocks
a cleanup.
Object cleanup preserves references from verified raw manifests even when an interrupted first write left no session metadata. Corrupt manifests or invalid metadata protect the affected object namespace. Unrelated unreachable objects can still be collected.
Outbox cleanup keeps pending uploads and unfinished recovery data. Current inventory entries, pinned uploads, and required release-history records keep their receipts and chunk lists. Other cached receipts have a limited spare allowance. Dropping one can require a later upload again, but does not remove remote backup history. Logical byte reductions can exceed reclaimed disk space because hardlinks and clones share physical storage.
To compress the original harness files already in the archive immediately, run the raw compaction pass. Automatic refresh runs the same pass after updates when Refresh after updates is on:
hansard rebuild --compact-raw --dry-run --jsonhansard rebuild --compact-rawThe preview lists the eligible files and their sizes without estimating the
savings. The pass stores each eligible file losslessly in verified 1 MiB
chunks and reparses nothing. It needs free space for both forms while it
converts, and archive maintenance removes the replaced files after their grace
period. It waits while a copy of Hansard or a Personal Sync device cannot read
chunked files. Once a compacted conversation uploads, the backup requires
every device to read chunked files from then on. Later imports keep the
storage mode that archive.rawStorage sets.
Files below 64 KiB remain whole. Each replacement must save at least 5%. The pass refuses a session above 512 MiB of raw evidence or 128 raw records. Received copies, immutable generations, source cohorts, and recovery directories remain unchanged. The preview reports logical bytes, not estimated compression.
hansard prune reveal-cache --dry-runreveal-cache replaces the whole unredacted copy of each conversation that
earlier versions kept for hansard show --unredacted with what Hansard keeps
now: nothing for a conversation redaction left unchanged, whose archived
transcript already holds every message as it was, and the original form of
the messages redaction changed for the rest. It removes a copy only after the
conversation reads back exactly as the copy held it. It also removes the files
of conversations the archive no longer holds, which an earlier version of
Hansard leaves behind when it deletes a conversation. Background imports do
not run it; each conversation’s next import replaces its own copy. Remove
--dry-run to apply it.
Compress classification history
Section titled “Compress classification history”Classification retains an immutable revision of every result. New revisions are compressed. To inspect and compress older text revisions:
hansard classify compacthansard classify compact --applyThe command checks that each compressed revision decodes to the original text.
Add --rewrite to return freed space to the filesystem when sufficient
space remains. Automatic maintenance compresses revisions for at most
20 seconds per pass. Once none remain, it releases free space when that space
is at least one eighth of the database.
Clean received history
Section titled “Clean received history”hansard prune received-history --dry-runhansard prune received-history --yesCleanup preserves the active snapshot, eight prior completed snapshots, indexed generations, and active readers. It removes only files and manifest nodes that no retained inventory reaches. Pending restores, unverified or legacy inventories, and an unreadable newer session index defer cleanup.
This changes local received copies, not remote history. Automatic maintenance also releases blob-store links for versions that no retained snapshot uses. Bytes become reclaimable after both snapshot and blob-store links are gone.
Review snapshot history
Section titled “Review snapshot history”Settings → Imports → Snapshot history lists saved checkpoints. Open one to preview a verified text file, compare two observations, or pin it. Capture details name the source coverage and observation times. Binary, missing, or oversized files explain why a text preview is unavailable.
Historical checkpoint expiry is off by default. With
storage.historyRetention.enabled on, pressure recovery can expire eligible
checkpoints only after garbage cleanup and an exact admission check show that
a pending write still cannot fit.
Policy key under storage.historyRetention.policy |
Default |
|---|---|
allForMs |
Keep every observed checkpoint for one day. |
hourlyForMs |
Keep hourly checkpoints through seven days. |
retainForMs |
Keep daily checkpoints through 30 days. |
maxBytes |
Allow 10 GiB beyond current evidence. Pins count toward this allowance. |
Current evidence, readers, and pending uploads remain protected. A write without an exact size estimate defers history expiry. This setting does not turn on automatic checkpoint capture.
Storage limits
Section titled “Storage limits”Hansard reserves space before it copies original files and upload payloads, and leaves 2 GiB free on the archive’s disk by default. Change the floor, or set optional allowances for the storage Hansard accounts for:
hansard config set storage.limits.minFreeBytes 2147483648hansard config get storage.limitsstorage.limits.totalBytes and storage.limits.totalObjects default to
null, which means no allowance. The evidence, history, staging, and
pendingUploads entries under storage.limits.categories each accept bytes
and objects. An allowance needs a complete usage scan; while a scan is
incomplete, writes it covers wait. The limits cover original files, session
files, memory snapshots, catalogs, upload payloads, exports, received
downloads, and caches, but not every archive writer, so they are not a quota
for the whole archive. hansard status --json reports the recorded usage and
the current free space.
Files of at least 1 MiB can use copy-on-write clones on supported APFS, Btrfs, or XFS volumes. A clone still reserves and counts its full logical size. Frozen uploads can hardlink immutable archive objects instead of copying them. Interrupted writes remain charged until cleanup establishes their actual usage.
Outbox and receive databases each have a 512 MiB image limit and a 1 GiB write-ahead-log limit. Normal transactions allow at most 8 MiB of database growth and 8 MiB of bound input. Received manifest transactions allow 32 MiB to hold a complete dependency record. Database checkpoints reserve space separately and defer at the free-space floor.
SQLite can hold a dirty image and statement journal in memory, approaching
1 GiB together at the database limit, before query results and input buffers.
hansard personal-sync status and hansard doctor storage report backup
capacity warnings at half of a limit and again at four fifths. A full outbox
stops capture and uploads. Each backup stream also stops at one million files
or a 64 MiB file list.
Upgrade Hansard
Section titled “Upgrade Hansard”npm install -g hansard@latesthansard watcher restartThe restart moves the watcher to the new version now; otherwise it moves on its
own once nothing it started is running. Reopen the app or browser.
The Mac app updates itself when it was installed from the signed installer; see
Update the app. Automatic
installation with hansard app install requires a configured desktop release
manifest.
Reinstall the npm package after changing the Node.js major version so its
SQLite native module matches the runtime. On macOS, Hansard uses Homebrew’s
stable Node link when available, so routine Homebrew upgrades do not leave
integrations pointing at a removed version directory. hansard doctor checks
the viewer and watcher runtimes and their SQLite module.
After an update, the app shows New in Hansard once, as a short sequence of
the release’s highlights and the setup steps that apply to this computer, and
the first interactive command prints a short note. The app runs the steps you
chose only at Finish, and a step that fails shows its reason beside
Run again. hansard whats-new shows the release
again and runs the steps you choose; Settings → About reopens it in the
app. Turn off the dialog and note with
hansard config set updates.whatsNew false or HANSARD_NO_WHATS_NEW=1.
A normal upgrade needs no rebuild. When a release changes how a source is
read, its release notes name the reimport or rebuild
command to run.
Hansard checks the npm registry for new releases at most once a day, from
interactive CLI commands and Settings → About. Turn this off with
hansard config set updates.checkOnStartup false.
Run a full refresh
Section titled “Run a full refresh”hansard update clears the local conversation archive, search indexes, import
records, caches, and local sync records, then reimports your configured
sources. It never deletes remote copies or the harnesses’ own history.
-
Run
hansard doctorand confirm the configured sources still have their history. -
Preview what the update removes and keeps:
Terminal window hansard update --dry-run --since all -
Restore any harness files that exist only in Hansard’s preserved copies.
-
Run the update:
Terminal window hansard update --yes --since all -
Check the result with
hansard doctorandhansard status.
update keeps your configuration, redaction rules, memories, skill history,
imported evaluations, Deep Recall threads, classifications, web-export
archives and account labels, conversations whose sources have disappeared, and
recall integrations. --sources a,b,c limits the reimport, --no-index skips
the search rebuild, and --no-restart leaves the watcher stopped.
Recover from an interrupted update
Section titled “Recover from an interrupted update”An update that stops partway keeps a verified backup of the archive it replaced. List the preserved operations, preview one, then restore it:
hansard update --list-recoverieshansard update --recover <operation-id> --dry-runhansard update --recover <operation-id> --yes--recover restores the preserved archive without reading harness history. It
replaces the files the interrupted update wrote, and the backup stays available
if the restore fails.
Delete, reset, or uninstall
Section titled “Delete, reset, or uninstall”| Command | Effect |
|---|---|
hansard delete <session-id> |
Removes Hansard’s copy of one conversation, after any import that is running finishes. The harness’s history is untouched. With Personal Sync, delete confirms the conversation’s removal, and automatic maintenance removes it from the backup a day later. hansard personal-sync restore-sessions brings it back only when --session names it. |
hansard reset --dry-run |
Lists what a reset removes: configuration, state, logs, indexes, caches, managed account profiles and router, and the archive. |
hansard reset --yes |
Removes all of that for a fresh setup. Harness history outside the Hansard home and recall integration files stay. |
hansard uninstall --keep-data |
Stops the watcher and managed router and removes the login item. Keeps the archive, configuration, and managed profiles. |
hansard uninstall |
Also removes local Hansard data after confirmation. Lists recall and MCP files for you to remove. |
Managed account profiles live in the Hansard home and hold harness sign-ins and history. Move them elsewhere before a reset or uninstall if you want to keep them.
Prefer an export, a narrow rebuild, or a single-source reimport before a reset.