Skip to content

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
  1. 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.

  2. Select Incomplete runs to see runs that stopped before saving any messages. Hansard keeps them out of Sessions, search, and Stats.

  3. If a conversation seems missing, open Sessions, select Filter & sort, select Reset, and then set Source and Time one at a time.

  4. 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.

Terminal window
hansard status
hansard doctor
hansard index status
hansard watcher status
hansard import status

status 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.

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.

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:

Terminal window
hansard rebuild --provider cursor --since 90d
hansard rebuild --force --since all
hansard rebuild --from-raw --source-type claude-web-export

Archive 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.

Terminal window
hansard rebuild --format 2 --since all

The 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.

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.

Terminal window
hansard watcher restart
hansard watcher logs --follow

Restart 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.

Terminal window
hansard export <session-id> --out ./session-export

This 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.

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:

Terminal window
hansard restore-sources claude --dry-run
hansard restore-sources claude
hansard import --source claude --since all

restore-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:

Terminal window
hansard repair claude-code-backups --dry-run
hansard repair claude-code-backups --yes
hansard import --source claude --since all
Terminal window
hansard prune archive-objects --dry-run
hansard prune sync-outbox --dry-run

With 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:

Terminal window
hansard rebuild --compact-raw --dry-run --json
hansard rebuild --compact-raw

The 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.

Terminal window
hansard prune reveal-cache --dry-run

reveal-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.

Classification retains an immutable revision of every result. New revisions are compressed. To inspect and compress older text revisions:

Terminal window
hansard classify compact
hansard classify compact --apply

The 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.

Terminal window
hansard prune received-history --dry-run
hansard prune received-history --yes

Cleanup 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.

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.

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:

Terminal window
hansard config set storage.limits.minFreeBytes 2147483648
hansard config get storage.limits

storage.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.

Terminal window
npm install -g hansard@latest
hansard watcher restart

The 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.

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.

  1. Run hansard doctor and confirm the configured sources still have their history.

  2. Preview what the update removes and keeps:

    Terminal window
    hansard update --dry-run --since all
  3. Restore any harness files that exist only in Hansard’s preserved copies.

  4. Run the update:

    Terminal window
    hansard update --yes --since all
  5. Check the result with hansard doctor and hansard 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.

An update that stops partway keeps a verified backup of the archive it replaced. List the preserved operations, preview one, then restore it:

Terminal window
hansard update --list-recoveries
hansard update --recover <operation-id> --dry-run
hansard 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.

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.