Repository navigation
Releases: emberian/cv
Release list
0.18.0 — 2026-10-23 — the release an agent can trust
ClusterVision 0.18.0 is the release an agent can trust. Every listing, count and search answer
is either exact or says what it skipped: counts are prompts and replies on every harness, a
session the store has not counted shows a dash, and search reads what the index has not seen.
One stored-format version replaces five; upgrading reads every session once. A write to a store
costs the session it touched, not the store: SQLite stores carry per-session certificates and
transcripts resume from their last mark, so cv index is cheap enough to run hourly or not at
all. No hidden limit decides what you get; the bounds that remain are flags you set or caps that
never change a result. Removed names exit 2 with a pointer; stored logs keep reading. Hooks cover
Codex as well as Claude, and cv doctor reports a harness release cv has not verified.
Breaking: commands, MCP, HTTP and JSON. A removed name exits 2 with a pointer to its replacement.
cv search --json(and MCPsearch) prints{"hits": [...], "total": M}, not an array; the table footer readsN of M matches./api/searchaddsX-Cv-Search-Total, every session that matched; its note saysN of M matcheswhenlimitcut it.cv events --json(/api/events, MCP) holds whole commands and error texts, newlines kept; the table marks cuts with…, and--wideprints them whole.cv search --scan(scan=1,cv packwithout an index) matches each session's whole exchange, streamed, instead of its first 256 KiB.cv index --semanticreads each session as far as the model embeds (512 tokens × median token length) and prints it; the 64 KiB head is gone.- The full-text index holds a persisted tool output whole, not its first MiB, and snippets find a term anywhere;
source::VERSION9 rereads once. - Hooks read at most 8 MiB of transcript and say what they left unread:
compactnames the tail it read,starta row's commit search span. cv showon a pipe prints the whole transcript (no 200 KB head+tail guard); MCPshowadds no defaultlast/max_byteswindow.- MCP
observe_streamreturns everything appended by default;char_cap, when given, is stated with atruncatedcount. - Cursor counts only bubbles a read keeps (capability markers dropped); a composer with external bubble cells counts at
cv index. source::VERSIONis 8: listings rediscover once, so rc.2's cached Cursor counts are recounted.message_countcounts prompts and replies only (no tool results or sub-agent returns) and isnull, not0, until counted:ls --json,/api/sessions, search rows.cv archive lscounts turns likecv ls;catalog.jsonlkeeps the raw count asmessages_written; 0.17 rows show a dash until resynced.extra.openclawkeys keep native camelCase (stopReason,customType,error.errorCode);custom_detailsandbranch_from_idbecomedetailsandfromId.- An IR or OpenSession 0.3 message without
kindororiginis refused, not inferred from its role. - Fidelity-report
deltasandcv formatsfindings are{what, a, b, expected, where}, replacing{field, before, after}and the old finding keys. - MCP tools omit
--follow; afollowargument is refused, namingfor. cv scryon a pipe prints the sessions it would follow and exits 0;--followfollows,--for 30s|5m|2hbounds it.- Watch and
observe_streamcursors are version 2; a 0.17 cursor starts a fresh baseline. - A tag-only
decision(pre-0.15, nothing posed) reads as an assigned action, not a decision owed; the page's tagged-decision card is gone. $CLAURDVOYANT_HOMEand$CLAURDVOYANT_MAX_STALE_SECSexit 2, naming theCLUSTERVISION_variables;claurdvoyantdirectories are no longer read.- Renamed:
rewind --from-compaction(the default;--fullfor everything),deferrals --sinceis--at,dataset --outis--file. cv tools --agenttakes an exact id or unique prefix, else exits 2;--acrosswith--agent,--toolor--timelineexits 2.- An unknown
cv task events --kind(/api/events?kind=) exits 2 (400) listing the known kinds, instead of listing nothing. cv workflowexits 2 on flags it dropped: run-only flags without a run,--revive-allwithout--revive,--revivewith--json.-q text:without an index reads live; past--live-bytesor under--frozenit exits 2 namingcv index(/api/stats: 503).cv events,cv touched,cv blameand their HTTP routes fail on an event-catalog error instead of answering empty.
Breaking (library): cv-core, cv-search and cv-testkit.
ParseOptions/ExtraProjection→Demand { tier, spans, offsets };MessageSink::extra_projection→tier; the fiveWatcherpoll methods →poll/try_poll(Poll { .. }).Adapter::resume/try_resume/resume_format→Adapter::transcript(r, demand, Start, sink);append_onlyreturnsbool.Adapter::discoverreturnsDiscovered { refs, skipped }(out-of-tree:Ok(refs.into()));cline::discover_inreturns it,cline_sdk::discoverfills&mut Discovered.Watcher::runis gone (callers schedulepoll);poll_sources→offer_sources.Text: over 4 KiB isText::Source;Spanis wire form only; malformed escapes and unresolved formatting error;matches_strandis_lazyreplace equality andis_span.lazy::json_string_spanis gone;try_resolve_prefixbudgets decoded bytes (max_raw→max);lazy::read_head→read_head_checked(Result).ir::Head→projection::Head(separate byte and character budgets;pushreturnstruewhen full);Counted::newbuildsCounted;hashing()captures SHA-256.emit::Deltaandformats::Finding→emit::Divergence {what, a, b, expected, at};FindingKind::ManifestInvalidreplacessource_file_missingfor unparseable manifests.SubagentInfo/claude::subagent_refs→ir::AgentRef/subagent_tree_of;claude::CARRIER_KEY→ir::CARRIER_KEY;SubagentEnd,ApiErrorNotice,TaskNoticemove tolanes.- Return
Result: agent end, return, task-notice and workflow-launch reads; forest and subagent-reference APIs;one_agent_across;wire::openai::tool_calls;store_affordances;json_files. - Return
Result:codex::parse_str,gemini::parse_all_str[_for],ingest::ingest_files,events::{events_for, sessions_touching, sessions_editing, edits_touching_file}. - Renamed modules:
handoff→codex_handoff,loom→splice,harness::harmony→harness::wire::harmony;decode_contenttakes a call-id generator (ir::derived_call_id). export::{ChatGptExport, ClaudeExport}are gone:harness::for_harness_with_root(Harness::ChatGptExport, dir).affordance:classify_tool,items_of,item_of→classify_tool_json/_view,items_of_view,item_of_view;Returns::ResultInPromptis new (Roo'snew_task).affordance::{unwrap,rewrap}_deferredtake aDeferredWrapper;wire::anthropic's ownedTexter,block_from*andblocks_fromare gone.distill::distill→prepare_distill+distill_pack;Session::first_user_textandsearchable_textare gone.SearchRow::to_json→to_json_with(&SearchRowContext);scan::live_search→live_search_filtered.- Redaction and HTML rendering take a resolver (
share_message(.., resolver)); Markdown useswrite_md_message/write_md_block;scrub_value/scrub_coware private (redact_with,redact_message,redact_text). RedactOptions.keep_emails→classes.emails, inverted;task::AppendOutcome.replay_warningsis gone.source::Published→Record<T>(Table<T: Payload>,admitreplacespublished/fresh);source::rename_consumeris gone;catalog::fill_countis gone.resume::versionreturnsString;resume::MarkUpdateis{session, mark};publish::retractis gone (publish::Setowns rollback).- New fields break exhaustive literals:
EmitOptions.parsed_at,PruneOptions/RewindOptions.skills_policyand results'skills,Stats.uncounted,HarnessCensus.first_error,LaneWork.unread. EmitOptions.sidechain_ofisOption<SidechainOf {root, agent}>;prune::prune_sessiontakes theHarnessfirst.events::ingest_alltakesIngestOptions;query::WindowPresenceis gone (filter_refs_limiteddrops it);query::HAS_FLAGSrows are(name, help, Cost).lanes::Lane.statusisLaneStatus,LaneEvent.eventisLaneEventKind;STRAND_PATTERNSis private (text_is_waiting).ForestTools::for_workflow→tools::forest_tools_selected(r, None, Some(run_id), None);task::store::append_agent_event→TaskStore::default_store().append_agent_event.- cv-search:
text_search*,enrich_text_snippets,semantic_search_filtered→Searcher::{search, search_in};embed_all→embed_sessions;Searcher::semanticis private (Searcher::from). fts::enrich_text_snippetsreturnsResult<Option<String>>(a degradation note).- cv-testkit:
heap::begin/endreturnMeasurement;Env::enter_isolatedreturnsIsolated(armed, Scope);claude::user(sid, uuid, ts, text).
After upgrading, once.
source::VERSIONis 7: the first listing rebuilds the catalog (said on stderr;cv indexdoes it ahead) and every mark, checkpoint and watch state.- The first
cv indexrebuilds the full-text index whole.
Listing and counts.
- A plain
.jsonOpenSession document is discovered wherever its top-level version key sits, not only within the first 64 KiB. - A first
cv lsleaves Codex, Grok, Kimi, Kimi Code, Qwen, Hermes, Goose, Zed, Continue and OpenCode uncounted until a read orcv index. cv statsreports "N not counted yet" (uncountedin--json,/api/stats);--sort-by messagesranks uncounted last.- A count survives refreshes of an unchanged source and is dropped when it changes; rewound or superseded Hermes rows no longer inflate it.
- Kimi, Kimi Code and Grok titles are the recorded native title; Hermes, Goose and Zed list from metadata alone.
- Cursor legacy coun...
0.18.0-rc.5 — 2026-10-23 — the release an agent can trust
Release Notes
Breaking: commands, MCP, HTTP and JSON. A removed name exits 2 with a pointer to its replacement.
Breaking: commands, MCP, HTTP and JSON.
cv indexholds a few open files per worker, not two per compressed Codex rollout, so a cold index stays under macOS's 256-file limit.cv indexdefers a session whose old search baseline cannot be invalidated (catalog unopenable), names it, and completes the pass instead of aborting.cv search --json(and MCPsearch) prints{"hits": [...], "total": M}, not an array; the table footer readsN of M matches./api/searchaddsX-Cv-Search-Total, every session that matched; its note saysN of M matcheswhenlimitcut it.cv pack --excerpt-bytes N(default 1600) bounds each excerpt message; the bundle'sBounds:line names every bound and what it cut.CV_PACK_LLMdigests send up to the model's provider-reported context window (was 60K chars), or--context-bytes N; the bundle states bytes sent and the limit.- A plain
.jsonOpenSession document is discovered wherever its top-level version key sits, not only within the first 64 KiB. cv events --json(/api/events, MCP) holds whole commands and error texts, newlines kept; the table marks cuts with…, and--wideprints them whole.cv search,/api/search, MCP search and-q text:read every session the index has not seen;--live-bytes(live_bytes) now only bounds it when given.cv search --scan(scan=1,cv packwithout an index) matches each session's whole exchange, streamed, instead of its first 256 KiB.cv index --semanticreads each session as far as the model embeds (512 tokens × median token length) and prints it; the 64 KiB head is gone.- The full-text index holds a persisted tool output whole, not its first MiB, and snippets find a term anywhere;
source::VERSION9 rereads once. - Hooks read at most 8 MiB of transcript and say what they left unread:
compactnames the tail it read,starta row's commit search span. cv showon a pipe prints the whole transcript (no 200 KB head+tail guard); MCPshowadds no defaultlast/max_byteswindow.- MCP
observe_streamreturns everything appended by default;char_cap, when given, is stated with atruncatedcount. - Cursor counts only bubbles a read keeps (capability markers dropped); a composer with external bubble cells counts at
cv index. source::VERSIONis 8: listings rediscover once, so rc.2's cached Cursor counts are recounted.message_countcounts prompts and replies only (no tool results or sub-agent returns) and isnull, not0, until counted:ls --json,/api/sessions, search rows.cv archive lscounts turns likecv ls;catalog.jsonlkeeps the raw count asmessages_written; 0.17 rows show a dash until resynced.extra.openclawkeys keep native camelCase (stopReason,customType,error.errorCode);custom_detailsandbranch_from_idbecomedetailsandfromId.- An IR or OpenSession 0.3 message without
kindororiginis refused, not inferred from its role. - Fidelity-report
deltasandcv formatsfindings are{what, a, b, expected, where}, replacing{field, before, after}and the old finding keys. - MCP tools omit
--follow; afollowargument is refused, namingfor. cv scryon a pipe prints the sessions it would follow and exits 0;--followfollows,--for 30s|5m|2hbounds it.- Watch and
observe_streamcursors are version 2; a 0.17 cursor starts a fresh baseline. - A tag-only
decision(pre-0.15, nothing posed) reads as an assigned action, not a decision owed; the page's tagged-decision card is gone. $CLAURDVOYANT_HOMEand$CLAURDVOYANT_MAX_STALE_SECSexit 2, naming theCLUSTERVISION_variables;claurdvoyantdirectories are no longer read.- Renamed:
rewind --from-compaction(the default;--fullfor everything),deferrals --sinceis--at,dataset --outis--file. cv tools --agenttakes an exact id or unique prefix, else exits 2;--acrosswith--agent,--toolor--timelineexits 2.- An unknown
cv task events --kind(/api/events?kind=) exits 2 (400) listing the known kinds, instead of listing nothing. cv workflowexits 2 on flags it dropped: run-only flags without a run,--revive-allwithout--revive,--revivewith--json.-q text:without an index reads live; past--live-bytesor under--frozenit exits 2 namingcv index(/api/stats: 503).cv events,cv touched,cv blameand their HTTP routes fail on an event-catalog error instead of answering empty.
Breaking (library): cv-core, cv-search and cv-testkit.
ParseOptions/ExtraProjection→Demand { tier, spans, offsets };MessageSink::extra_projection→tier; the fiveWatcherpoll methods →poll/try_poll(Poll { .. }).Adapter::resume/try_resume/resume_format→Adapter::transcript(r, demand, Start, sink);append_onlyreturnsbool.Adapter::discoverreturnsDiscovered { refs, skipped }(out-of-tree:Ok(refs.into()));cline::discover_inreturns it,cline_sdk::discoverfills&mut Discovered.Watcher::runis gone (callers schedulepoll);poll_sources→offer_sources.Text: over 4 KiB isText::Source;Spanis wire form only; malformed escapes and unresolved formatting error;matches_strandis_lazyreplace equality andis_span.lazy::json_string_spanis gone;try_resolve_prefixbudgets decoded bytes (max_raw→max);lazy::read_head→read_head_checked(Result).ir::Head→projection::Head(separate byte and character budgets;pushreturnstruewhen full);Counted::newbuildsCounted;hashing()captures SHA-256.emit::Deltaandformats::Finding→emit::Divergence {what, a, b, expected, at};FindingKind::ManifestInvalidreplacessource_file_missingfor unparseable manifests.SubagentInfo/claude::subagent_refs→ir::AgentRef/subagent_tree_of;claude::CARRIER_KEY→ir::CARRIER_KEY;SubagentEnd,ApiErrorNotice,TaskNoticemove tolanes.- Return
Result: agent end, return, task-notice and workflow-launch reads; forest and subagent-reference APIs;one_agent_across;wire::openai::tool_calls;store_affordances;json_files. - Return
Result:codex::parse_str,gemini::parse_all_str[_for],ingest::ingest_files,events::{events_for, sessions_touching, sessions_editing, edits_touching_file}. - Renamed modules:
handoff→codex_handoff,loom→splice,harness::harmony→harness::wire::harmony;decode_contenttakes a call-id generator (ir::derived_call_id). export::{ChatGptExport, ClaudeExport}are gone:harness::for_harness_with_root(Harness::ChatGptExport, dir).affordance:classify_tool,items_of,item_of→classify_tool_json/_view,items_of_view,item_of_view;Returns::ResultInPromptis new (Roo'snew_task).affordance::{unwrap,rewrap}_deferredtake aDeferredWrapper;wire::anthropic's ownedTexter,block_from*andblocks_fromare gone.distill::distill→prepare_distill+distill_pack;Session::first_user_textandsearchable_textare gone.SearchRow::to_json→to_json_with(&SearchRowContext);scan::live_search→live_search_filtered.- Redaction and HTML rendering take a resolver (
share_message(.., resolver)); Markdown useswrite_md_message/write_md_block;scrub_value/scrub_coware private (redact_with,redact_message,redact_text). RedactOptions.keep_emails→classes.emails, inverted;task::AppendOutcome.replay_warningsis gone.source::Published→Record<T>(Table<T: Payload>,admitreplacespublished/fresh);source::rename_consumeris gone;catalog::fill_countis gone.resume::versionreturnsString;resume::MarkUpdateis{session, mark};publish::retractis gone (publish::Setowns rollback).- New fields break exhaustive literals:
EmitOptions.parsed_at,PruneOptions/RewindOptions.skills_policyand results'skills,Stats.uncounted,HarnessCensus.first_error,LaneWork.unread. EmitOptions.sidechain_ofisOption<SidechainOf {root, agent}>;prune::prune_sessiontakes theHarnessfirst.events::ingest_alltakesIngestOptions;query::WindowPresenceis gone (filter_refs_limiteddrops it);query::HAS_FLAGSrows are(name, help, Cost).lanes::Lane.statusisLaneStatus,LaneEvent.eventisLaneEventKind;STRAND_PATTERNSis private (text_is_waiting).ForestTools::for_workflow→tools::forest_tools_selected(r, None, Some(run_id), None);task::store::append_agent_event→TaskStore::default_store().append_agent_event.- cv-search:
text_search*,enrich_text_snippets,semantic_search_filtered→Searcher::{search, search_in};embed_all→embed_sessions;Searcher::semanticis private (Searcher::from). fts::enrich_text_snippetsreturnsResult<Option<String>>(a degradation note).- cv-testkit:
heap::begin/endreturnMeasurement;Env::enter_isolatedreturnsIsolated(armed, Scope);claude::user(sid, uuid, ts, text).
After upgrading, once.
source::VERSIONis 7: the first listing rebuilds the catalog (said on stderr;cv indexdoes it ahead) and every mark, checkpoint and watch state.- The first
cv indexrebuilds the full-text index whole.
Listing and counts.
- A first
cv lsleaves Codex, Grok, Kimi, Kimi Code, Qwen, Hermes, Goose, Zed, Continue and OpenCode uncounted until a read orcv index. cv statsreports "N not counted yet" (uncountedin--json,/api/stats);--sort-by messagesranks uncounted last.- A count survives refreshes of an unchanged source and is dropped when it changes; rewound or superseded Hermes rows no longer inflate it.
- Kimi, Kimi Code and Grok titles are the recorded native title; Hermes, Goose and Zed list from metadata alone.
- Cursor legacy counts exclude empty and malformed bub...
0.18.0-rc.4 — 2026-10-23 — the release an agent can trust
Release Notes
Breaking: commands, MCP, HTTP and JSON. A removed name exits 2 with a pointer to its replacement.
Breaking: commands, MCP, HTTP and JSON.
cv search --json(and MCPsearch) prints{"hits": [...], "total": M}, not an array; the table footer readsN of M matches./api/searchaddsX-Cv-Search-Total, every session that matched; its note saysN of M matcheswhenlimitcut it.cv pack --excerpt-bytes N(default 1600) bounds each excerpt message; the bundle'sBounds:line names every bound and what it cut.CV_PACK_LLMdigests send up to the model's provider-reported context window (was 60K chars), or--context-bytes N; the bundle states bytes sent and the limit.- A plain
.jsonOpenSession document is discovered wherever its top-level version key sits, not only within the first 64 KiB. cv events --json(/api/events, MCP) holds whole commands and error texts, newlines kept; the table marks cuts with…, and--wideprints them whole.cv search,/api/search, MCP search and-q text:read every session the index has not seen;--live-bytes(live_bytes) now only bounds it when given.cv search --scan(scan=1,cv packwithout an index) matches each session's whole exchange, streamed, instead of its first 256 KiB.cv index --semanticreads each session as far as the model embeds (512 tokens × median token length) and prints it; the 64 KiB head is gone.- The full-text index holds a persisted tool output whole, not its first MiB, and snippets find a term anywhere;
source::VERSION9 rereads once. - Hooks read at most 8 MiB of transcript and say what they left unread:
compactnames the tail it read,starta row's commit search span. cv showon a pipe prints the whole transcript (no 200 KB head+tail guard); MCPshowadds no defaultlast/max_byteswindow.- MCP
observe_streamreturns everything appended by default;char_cap, when given, is stated with atruncatedcount. - Cursor counts only bubbles a read keeps (capability markers dropped); a composer with external bubble cells counts at
cv index. source::VERSIONis 8: listings rediscover once, so rc.2's cached Cursor counts are recounted.message_countcounts prompts and replies only (no tool results or sub-agent returns) and isnull, not0, until counted:ls --json,/api/sessions, search rows.cv archive lscounts turns likecv ls;catalog.jsonlkeeps the raw count asmessages_written; 0.17 rows show a dash until resynced.extra.openclawkeys keep native camelCase (stopReason,customType,error.errorCode);custom_detailsandbranch_from_idbecomedetailsandfromId.- An IR or OpenSession 0.3 message without
kindororiginis refused, not inferred from its role. - Fidelity-report
deltasandcv formatsfindings are{what, a, b, expected, where}, replacing{field, before, after}and the old finding keys. - MCP tools omit
--follow; afollowargument is refused, namingfor. cv scryon a pipe prints the sessions it would follow and exits 0;--followfollows,--for 30s|5m|2hbounds it.- Watch and
observe_streamcursors are version 2; a 0.17 cursor starts a fresh baseline. - A tag-only
decision(pre-0.15, nothing posed) reads as an assigned action, not a decision owed; the page's tagged-decision card is gone. $CLAURDVOYANT_HOMEand$CLAURDVOYANT_MAX_STALE_SECSexit 2, naming theCLUSTERVISION_variables;claurdvoyantdirectories are no longer read.- Renamed:
rewind --from-compaction(the default;--fullfor everything),deferrals --sinceis--at,dataset --outis--file. cv tools --agenttakes an exact id or unique prefix, else exits 2;--acrosswith--agent,--toolor--timelineexits 2.- An unknown
cv task events --kind(/api/events?kind=) exits 2 (400) listing the known kinds, instead of listing nothing. cv workflowexits 2 on flags it dropped: run-only flags without a run,--revive-allwithout--revive,--revivewith--json.-q text:without an index reads live; past--live-bytesor under--frozenit exits 2 namingcv index(/api/stats: 503).cv events,cv touched,cv blameand their HTTP routes fail on an event-catalog error instead of answering empty.
Breaking (library): cv-core, cv-search and cv-testkit.
ParseOptions/ExtraProjection→Demand { tier, spans, offsets };MessageSink::extra_projection→tier; the fiveWatcherpoll methods →poll/try_poll(Poll { .. }).Adapter::resume/try_resume/resume_format→Adapter::transcript(r, demand, Start, sink);append_onlyreturnsbool.Adapter::discoverreturnsDiscovered { refs, skipped }(out-of-tree:Ok(refs.into()));cline::discover_inreturns it,cline_sdk::discoverfills&mut Discovered.Watcher::runis gone (callers schedulepoll);poll_sources→offer_sources.Text: over 4 KiB isText::Source;Spanis wire form only; malformed escapes and unresolved formatting error;matches_strandis_lazyreplace equality andis_span.lazy::json_string_spanis gone;try_resolve_prefixbudgets decoded bytes (max_raw→max);lazy::read_head→read_head_checked(Result).ir::Head→projection::Head(separate byte and character budgets;pushreturnstruewhen full);Counted::newbuildsCounted;hashing()captures SHA-256.emit::Deltaandformats::Finding→emit::Divergence {what, a, b, expected, at};FindingKind::ManifestInvalidreplacessource_file_missingfor unparseable manifests.SubagentInfo/claude::subagent_refs→ir::AgentRef/subagent_tree_of;claude::CARRIER_KEY→ir::CARRIER_KEY;SubagentEnd,ApiErrorNotice,TaskNoticemove tolanes.- Return
Result: agent end, return, task-notice and workflow-launch reads; forest and subagent-reference APIs;one_agent_across;wire::openai::tool_calls;store_affordances;json_files. - Return
Result:codex::parse_str,gemini::parse_all_str[_for],ingest::ingest_files,events::{events_for, sessions_touching, sessions_editing, edits_touching_file}. - Renamed modules:
handoff→codex_handoff,loom→splice,harness::harmony→harness::wire::harmony;decode_contenttakes a call-id generator (ir::derived_call_id). export::{ChatGptExport, ClaudeExport}are gone:harness::for_harness_with_root(Harness::ChatGptExport, dir).affordance:classify_tool,items_of,item_of→classify_tool_json/_view,items_of_view,item_of_view;Returns::ResultInPromptis new (Roo'snew_task).affordance::{unwrap,rewrap}_deferredtake aDeferredWrapper;wire::anthropic's ownedTexter,block_from*andblocks_fromare gone.distill::distill→prepare_distill+distill_pack;Session::first_user_textandsearchable_textare gone.SearchRow::to_json→to_json_with(&SearchRowContext);scan::live_search→live_search_filtered.- Redaction and HTML rendering take a resolver (
share_message(.., resolver)); Markdown useswrite_md_message/write_md_block;scrub_value/scrub_coware private (redact_with,redact_message,redact_text). RedactOptions.keep_emails→classes.emails, inverted;task::AppendOutcome.replay_warningsis gone.source::Published→Record<T>(Table<T: Payload>,admitreplacespublished/fresh);source::rename_consumeris gone;catalog::fill_countis gone.resume::versionreturnsString;resume::MarkUpdateis{session, mark};publish::retractis gone (publish::Setowns rollback).- New fields break exhaustive literals:
EmitOptions.parsed_at,PruneOptions/RewindOptions.skills_policyand results'skills,Stats.uncounted,HarnessCensus.first_error,LaneWork.unread. EmitOptions.sidechain_ofisOption<SidechainOf {root, agent}>;prune::prune_sessiontakes theHarnessfirst.events::ingest_alltakesIngestOptions;query::WindowPresenceis gone (filter_refs_limiteddrops it);query::HAS_FLAGSrows are(name, help, Cost).lanes::Lane.statusisLaneStatus,LaneEvent.eventisLaneEventKind;STRAND_PATTERNSis private (text_is_waiting).ForestTools::for_workflow→tools::forest_tools_selected(r, None, Some(run_id), None);task::store::append_agent_event→TaskStore::default_store().append_agent_event.- cv-search:
text_search*,enrich_text_snippets,semantic_search_filtered→Searcher::{search, search_in};embed_all→embed_sessions;Searcher::semanticis private (Searcher::from). fts::enrich_text_snippetsreturnsResult<Option<String>>(a degradation note).- cv-testkit:
heap::begin/endreturnMeasurement;Env::enter_isolatedreturnsIsolated(armed, Scope);claude::user(sid, uuid, ts, text).
After upgrading, once.
source::VERSIONis 7: the first listing rebuilds the catalog (said on stderr;cv indexdoes it ahead) and every mark, checkpoint and watch state.- The first
cv indexrebuilds the full-text index whole.
Listing and counts.
- A first
cv lsleaves Codex, Grok, Kimi, Kimi Code, Qwen, Hermes, Goose, Zed, Continue and OpenCode uncounted until a read orcv index. cv statsreports "N not counted yet" (uncountedin--json,/api/stats);--sort-by messagesranks uncounted last.- A count survives refreshes of an unchanged source and is dropped when it changes; rewound or superseded Hermes rows no longer inflate it.
- Kimi, Kimi Code and Grok titles are the recorded native title; Hermes, Goose and Zed list from metadata alone.
- Cursor legacy counts exclude empty and malformed bubbles.
- A listing racing
cv indexwaits up to 5 s for it instead of discarding its update. created:without a recorded creation time no longer matches on update time.ls --json --ascwith a query selects the same sessions as descending; absent sessions take no window slot; refreshe...
0.18.0-rc.3 — 2026-10-23 — the release an agent can trust
Release Notes
Breaking: commands, MCP, HTTP and JSON. A removed name exits 2 with a pointer to its replacement.
- Cursor counts only bubbles a read keeps (capability markers dropped); a composer with external bubble cells counts at
cv index. source::VERSIONis 8: listings rediscover once, so rc.2's cached Cursor counts are recounted.message_countcounts prompts and replies only (no tool results or sub-agent returns) and isnull, not0, until counted:ls --json,/api/sessions, search rows.cv archive lscounts turns likecv ls;catalog.jsonlkeeps the raw count asmessages_written; 0.17 rows show a dash until resynced.extra.openclawkeys keep native camelCase (stopReason,customType,error.errorCode);custom_detailsandbranch_from_idbecomedetailsandfromId.- An IR or OpenSession 0.3 message without
kindororiginis refused, not inferred from its role. - Fidelity-report
deltasandcv formatsfindings are{what, a, b, expected, where}, replacing{field, before, after}and the old finding keys. - MCP tools omit
--follow; afollowargument is refused, namingfor. cv scryon a pipe prints the sessions it would follow and exits 0;--followfollows,--for 30s|5m|2hbounds it.- Watch and
observe_streamcursors are version 2; a 0.17 cursor starts a fresh baseline. - A tag-only
decision(pre-0.15, nothing posed) reads as an assigned action, not a decision owed; the page's tagged-decision card is gone. $CLAURDVOYANT_HOMEand$CLAURDVOYANT_MAX_STALE_SECSexit 2, naming theCLUSTERVISION_variables;claurdvoyantdirectories are no longer read.- Renamed:
rewind --from-compaction(the default;--fullfor everything),deferrals --sinceis--at,dataset --outis--file. cv tools --agenttakes an exact id or unique prefix, else exits 2;--acrosswith--agent,--toolor--timelineexits 2.- An unknown
cv task events --kind(/api/events?kind=) exits 2 (400) listing the known kinds, instead of listing nothing. cv workflowexits 2 on flags it dropped: run-only flags without a run,--revive-allwithout--revive,--revivewith--json.-q text:without an index reads live; past--live-bytesor under--frozenit exits 2 namingcv index(/api/stats: 503).cv events,cv touched,cv blameand their HTTP routes fail on an event-catalog error instead of answering empty.
Breaking (library): cv-core, cv-search and cv-testkit.
ParseOptions/ExtraProjection→Demand { tier, spans, offsets };MessageSink::extra_projection→tier; the fiveWatcherpoll methods →poll/try_poll(Poll { .. }).Adapter::resume/try_resume/resume_format→Adapter::transcript(r, demand, Start, sink);append_onlyreturnsbool.Adapter::discoverreturnsDiscovered { refs, skipped }(out-of-tree:Ok(refs.into()));cline::discover_inreturns it,cline_sdk::discoverfills&mut Discovered.Watcher::runis gone (callers schedulepoll);poll_sources→offer_sources.Text: over 4 KiB isText::Source;Spanis wire form only; malformed escapes and unresolved formatting error;matches_strandis_lazyreplace equality andis_span.lazy::json_string_spanis gone;try_resolve_prefixbudgets decoded bytes (max_raw→max);lazy::read_head→read_head_checked(Result).ir::Head→projection::Head(separate byte and character budgets;pushreturnstruewhen full);Counted::newbuildsCounted;hashing()captures SHA-256.emit::Deltaandformats::Finding→emit::Divergence {what, a, b, expected, at};FindingKind::ManifestInvalidreplacessource_file_missingfor unparseable manifests.SubagentInfo/claude::subagent_refs→ir::AgentRef/subagent_tree_of;claude::CARRIER_KEY→ir::CARRIER_KEY;SubagentEnd,ApiErrorNotice,TaskNoticemove tolanes.- Return
Result: agent end, return, task-notice and workflow-launch reads; forest and subagent-reference APIs;one_agent_across;wire::openai::tool_calls;store_affordances;json_files. - Return
Result:codex::parse_str,gemini::parse_all_str[_for],ingest::ingest_files,events::{events_for, sessions_touching, sessions_editing, edits_touching_file}. - Renamed modules:
handoff→codex_handoff,loom→splice,harness::harmony→harness::wire::harmony;decode_contenttakes a call-id generator (ir::derived_call_id). export::{ChatGptExport, ClaudeExport}are gone:harness::for_harness_with_root(Harness::ChatGptExport, dir).affordance:classify_tool,items_of,item_of→classify_tool_json/_view,items_of_view,item_of_view;Returns::ResultInPromptis new (Roo'snew_task).affordance::{unwrap,rewrap}_deferredtake aDeferredWrapper;wire::anthropic's ownedTexter,block_from*andblocks_fromare gone.distill::distill→prepare_distill+distill_pack;Session::first_user_textandsearchable_textare gone.SearchRow::to_json→to_json_with(&SearchRowContext);scan::live_search→live_search_filtered.- Redaction and HTML rendering take a resolver (
share_message(.., resolver)); Markdown useswrite_md_message/write_md_block;scrub_value/scrub_coware private (redact_with,redact_message,redact_text). RedactOptions.keep_emails→classes.emails, inverted;task::AppendOutcome.replay_warningsis gone.source::Published→Record<T>(Table<T: Payload>,admitreplacespublished/fresh);source::rename_consumeris gone;catalog::fill_countis gone.resume::versionreturnsString;resume::MarkUpdateis{session, mark};publish::retractis gone (publish::Setowns rollback).- New fields break exhaustive literals:
EmitOptions.parsed_at,PruneOptions/RewindOptions.skills_policyand results'skills,Stats.uncounted,HarnessCensus.first_error,LaneWork.unread. EmitOptions.sidechain_ofisOption<SidechainOf {root, agent}>;prune::prune_sessiontakes theHarnessfirst.events::ingest_alltakesIngestOptions;query::WindowPresenceis gone (filter_refs_limiteddrops it);query::HAS_FLAGSrows are(name, help, Cost).lanes::Lane.statusisLaneStatus,LaneEvent.eventisLaneEventKind;STRAND_PATTERNSis private (text_is_waiting).ForestTools::for_workflow→tools::forest_tools_selected(r, None, Some(run_id), None);task::store::append_agent_event→TaskStore::default_store().append_agent_event.- cv-search:
text_search*,enrich_text_snippets,semantic_search_filtered→Searcher::{search, search_in};embed_all→embed_sessions;Searcher::semanticis private (Searcher::from). fts::enrich_text_snippetsreturnsResult<Option<String>>(a degradation note).- cv-testkit:
heap::begin/endreturnMeasurement;Env::enter_isolatedreturnsIsolated(armed, Scope);claude::user(sid, uuid, ts, text).
After upgrading, once.
source::VERSIONis 7: the first listing rebuilds the catalog (said on stderr;cv indexdoes it ahead) and every mark, checkpoint and watch state.- The first
cv indexrebuilds the full-text index whole.
Listing and counts.
-
A first
cv lsleaves Codex, Grok, Kimi, Kimi Code, Qwen, Hermes, Goose, Zed, Continue and OpenCode uncounted until a read orcv index. -
cv statsreports "N not counted yet" (uncountedin--json,/api/stats);--sort-by messagesranks uncounted last. -
A count survives refreshes of an unchanged source and is dropped when it changes; rewound or superseded Hermes rows no longer inflate it.
-
Kimi, Kimi Code and Grok titles are the recorded native title; Hermes, Goose and Zed list from metadata alone.
-
Cursor legacy counts exclude empty and malformed bubbles.
-
A listing racing
cv indexwaits up to 5 s for it instead of discarding its update. -
created:without a recorded creation time no longer matches on update time. -
ls --json --ascwith a query selects the same sessions as descending; absent sessions take no window slot; refreshed harnesses keep their tie order. -
serve,mcpand followers see Gemini and Qwen projects registered after they started. -
A read-only catalog still serves warm listings; builds without
sqliteno longer spool unpublishable events. -
Semantic indexing caps transcript heads at 64 KiB of decoded text.
-
cv search,/api/searchand-q text:also read what the index has not seen, within--live-bytes(256 MiB);--frozenreads none. -
cv searchwithout an index answers from that live read instead of exiting 1. -
Search staleness counts each session's preferred copy, not older duplicates.
-
Cold SQLite snapshots stage beside the catalog instead of in a multi-gigabyte tmpfs copy.
-
MCP
observe_streamkeeps every followed session's reader state server-side and reportsrereads. -
Codex rollouts over 8 MiB list the title and cwd a full read gives, not a head-and-tail sample.
-
An append or rewrite rereads only that session: Claude forks, Grok cwd groups and Kimi Code sub-agents no longer reread; Codex rereads appended records.
-
A store write rereads only changed sessions: Hermes, Goose, OpenCode, Devin, Zed, Cursor, OpenClaw, Cline SDK databases, Gemini and Qwen
logs.json. -
Discovery rescans only changed sources: Kimi, Kimi Code, Goose legacy, Cline, Roo, Continue, OpenSession files and OpenClaw stores.
-
Sub-agent trees (
show --tree,--subagents, lanes) reuse unchanged agents' saved scans; Codex, Hermes, Devin and OpenClaw read their registries once per state. -
cv indexand live search read only what was appended since the last index; compressed Codex rollouts are read in parallel. -
One changed session rewrites only its catalog row;
cv show agent-…, workflow-name and ghost lookups read the catalog, not rediscovery. -
The prompt hook, task mutations,
cv task listandGET /api/tasksreplay only task-log events appende...
0.18.0-rc.2 — 2026-10-23 — one write costs one session
Release Notes
Breaking: commands, MCP, HTTP and JSON.
message_countis prompts and replies only: Claude, Cline and Roo stop counting tool results, OpenClaw sub-agent returns; OpenCode counts atcv index.
After upgrading, once.
source::VERSIONis 7: listings rediscover once, so rc.1's cached Claude, Cline and OpenClaw counts are recounted.
Listing and counts.
-
A round-trip read (
Demand::COMPLETE) never records counts: Hermes's rewound and superseded rows no longer inflate a session's count. -
Unchanged Hermes and Devin subagent forests load from the catalog without copying or opening their source databases.
-
Cold SQLite snapshots stage beside the catalog, avoiding multi-gigabyte tmpfs copies; frozen or unwritable catalogs retain temporary staging.
-
Hermes scans delegate runs once per database state instead of once per parent during subagent indexing.
-
Claude fork inference reads each sibling's head once per file state, not once per session asking: a directory pass was quadratic.
-
Codex sub-agent forests parse the lane ledger once per ledger state, not once per parent.
-
Kimi Code discovery rescans only a new session, not every session, when the session index grows.
-
Kimi discovery rescans no session when
kimi.jsonis rewritten; the cwd is applied after the scan cache. -
OpenClaw parses its cron and sub-agent registries once per store state, not once per session.
-
Goose legacy
.jsonlsessions are rescanned at discovery only when the file changes. -
cv indexreads compressed Codex rollouts in parallel, charging each its decoded size instead of the whole 2 GiB guard. -
Claude sub-agent trees (
show --tree,--subagents, lanes) reuse each unchanged agent's scan instead of rereading every transcript. -
Codex forests and the edit guard walk the lane ledger through an index, not a scan of every row per parent.
-
A watch checkpoint or archive resume state of any size is kept; past 64 KiB or 1 MiB they were silently dropped.
-
One changed session rewrites its own catalog row, not its harness's every row; a refreshed harness keeps its place among
cv lsties. -
cv show agent-…, workflow-name and ghost lookups read the catalog instead of rediscovering every Claude session on each call. -
MCP
observe_streamkeeps every observed session's reader state in the server, not eight in the cursor, and reportsrereads. -
The sessions API resumes pages and heads for its 1024 most recent sessions of any size, not 32 under 256 KiB.
-
Codex rollouts over 8 MiB list the title and cwd a full read gives, not a head-and-tail sample; a grown rollout rescans only its appended records.
-
The prompt hook, task mutations,
cv task listandGET /api/tasksresume from a stored fold of the task log, parsing only events appended since. -
A sub-agent tree read saves its agent scans: a later
show --tree, lanes orevents --subagentsrescans only changed agents. -
A followed session with over 16 KiB of metadata no longer rereads to its end on every bounded watch read.
-
cv show --treeindents once per fork above a message, not per ancestor: a straight chain prints flat, linear in the session. -
OpenClaw SQLite stores are rediscovered only when the store changes, not on every listing refresh.
-
A copied SQLite store with WAL frames is copied once per command, however large, not again whenever another database opens.
-
A Grok turn resumes from its mark instead of rereading the session; a new session in a cwd group no longer rereads its sub-agents.
-
A write to a Gemini or Qwen
logs.jsonrereads only the sessions whose entries changed, and the file is parsed once per state. -
A Kimi Code main-agent turn no longer rereads its sub-agents: each is certified by its own slice of
state.json. -
A write to the Cline SDK side databases rereads only the lead sessions whose schedule, cron or team rows changed.
-
Cline, Roo, Continue and OpenSession discovery rescan only files that changed; a Roo count reads
ui_messages.jsononce; Continue sessions are certified by their index entry. -
Reading every conversation of an export archive past the 8 MB roster cache scans it once, not once per conversation.
-
Zed, Cursor, Devin, Hermes and OpenClaw re-decode only sessions whose rows moved, and read each shared table or registry once per state.
-
Claude fork inference no longer mistakes a SessionStart hook's earlier timestamp for a copied head; only a copied first prompt or boundary counts.
-
Search staleness counts the preferred copy of each session, avoiding false drift from older duplicates.
-
cv search,/api/searchand-q text:read what the index has not seen live, from its resume mark, within--live-bytes(256 MiB);--frozenreads none. -
A write to a Hermes, Goose, OpenCode, Devin, Zed, Cursor or OpenClaw store rereads only the sessions whose rows changed.
-
cv indexand the live search read only what was appended since the last index, not every session under 4 MiB of text whole. -
An append to one Claude session no longer rereads the forks in its project directory; only a new or rewritten sibling does.
-
cv searchwithout an index answers from that live read instead of exiting 1;--frozenwithout an index still namescv index. -
cv stats --tokenskeeps every live session's cached usage however large the store; it evicts only deleted sources, never re-reading the fleet.
Install clustervision 0.18.0-rc.2
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/emberian/cv/releases/download/v0.18.0-rc.2/clustervision-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/emberian/cv/releases/download/v0.18.0-rc.2/clustervision-installer.ps1 | iex"Download clustervision 0.18.0-rc.2
| File | Platform | Checksum |
|---|---|---|
| clustervision-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| clustervision-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| clustervision-i686-pc-windows-msvc.zip | x86 Windows | checksum |
| clustervision-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| clustervision-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| clustervision-i686-unknown-linux-gnu.tar.xz | x86 Linux | checksum |
| clustervision-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.18.0-rc.1 — 2026-10-22 — the release an agent can trust
Release Notes
Breaking: commands, MCP, HTTP and JSON. A removed name exits 2 with a pointer to its replacement; a changed shape is named here.
- An uncounted session's
message_countwas0;ls --json,/api/sessionsand search rows now emitnull. cv archive lscounts turns likecv ls;catalog.jsonlrows keep the raw count asmessages_written; 0.17's rows show a dash until resynced.extra.openclawkeys copied from records keep native camelCase (stopReason,customType,error.errorCode);custom_detailsandbranch_from_idbecomedetailsandfromId.- An IR or OpenSession 0.3 message without
kindororiginis refused instead of inferred from its role; cv has written both since 0.11. - Fidelity-report
deltaselements andcv formatsfindings serialize as one Divergence,{what, a, b, expected, where}, replacing{field, before, after}and the old finding keys. - MCP tools generated from the CLI omit
--follow(no Ctrl-C in a tool call); afollowargument is refused, namingfor. - Installed hooks run
cv hook <name> --harness <h>;$CV_HOOK_HARNESSexits 2 with a pointer tocv hooks install codex. cv scrywith stdout piped prints the sessions it would follow once and exits 0;--followkeeps following,--for 30s|5m|2hbounds it.- Watch and
observe_streamcursors are version 2 (one mark per position); a 0.17 cursor starts a fresh baseline. - A tag-only
decision(nothing posed, written before 0.15) reads as an assigned action, not a decision owed; the page's tagged-decision card is gone. $CLAURDVOYANT_HOMEand$CLAURDVOYANT_MAX_STALE_SECSexit 2 with a pointer to theCLUSTERVISION_names; theclaurdvoyantconfig, cache and home directories are no longer read.cv rewind --from-compaction(the default start, never a switch) exits 2 with a pointer to--full.cv deferrals --since <msg>is--at <msg>(--sinceis a duration onlanes); the old spelling exits 2 with a pointer.cv dataset --out <path>is--file <path>(--outis a directory everywhere else); the old spelling exits 2 with a pointer.cv tools --agenttakes an exact id or unique prefix on every view, else exits 2;--acrosswith--agent,--toolor--timelineexits 2.- An unknown
cv task events --kind(or/api/events?kind=) exits 2 (400) naming the known kinds; it used to list nothing. cv workflowexits 2 where it dropped flags: run-only flags with no run named,--revive-allwithout--revive,--revivewith--json.- A
-qwithtext:and no full-text index exits 2 namingcv index(/api/stats: 503) instead of matching nothing. cv events,cv touched,cv blameand their HTTP routes fail on an event-catalog error instead of answering empty.
Breaking (library): cv-core, cv-search and cv-testkit APIs. Rust callers migrate as follows.
ParseOptionsandExtraProjectionbecomeDemand { tier, spans, offsets }; the fiveWatcherpoll methods becomepoll/try_poll(Poll { .. }).MessageSink::extra_projectionisMessageSink::tier, returning aTier; a sink that overrode it overridestier.Adapter::resume,try_resumeandresume_formatbecomeAdapter::transcript(r, demand, Start, sink);append_onlyreturnsbool; JSONL transcripts share one driver.Adapter::discoverreturnsDiscovered { refs, skipped }; an out-of-tree adapter returnsOk(refs.into()).cline::discover_inreturnsDiscovered;cline_sdk::discovertakes&mut Discoveredand fills it instead of returning refs.Watcher::runis gone (callers own scheduling aroundpoll);poll_sourcesisoffer_sources.- Transcript text over 4 KiB is
Text::Source(checked);Spanis wire form only, a JSON string body; malformed escapes error instead of decoding lossily. - Unresolved
Textformatting errors;matches_strreplaces string equality, andis_lazyreplacesis_span. lazy::json_string_spanis gone (adapters buildText::Source);try_resolve_prefixbudgets decoded bytes, not raw (max_rawismax).projection::Headreplacesir::Head: byte prefixes and character labels share one builder with separate budgets;pushreturnstrueonce full.projection::Countedis built withCounted::new;hashing()captures an optional SHA-256 digest during writes.emit::Deltaandformats::Findingbecome oneemit::Divergence {what, a, b, expected, at}(atserializes aswhere); format-check returns follow.formats::FindingKind::ManifestInvalidreports a manifest that does not parse, previously taggedsource_file_missing.SubagentInfoandclaude::subagent_refsbecomeir::AgentRefandsubagent_tree_of;claude::CARRIER_KEYisir::CARRIER_KEY.SubagentEnd,ApiErrorNoticeandTaskNoticemove fromharness::claudetolanes.- Agent end, return, task-notice and workflow-launch reads return
Result; aborted reads no longer imply missing or running agents. - Forest and subagent-reference APIs return
Result; unreadable forests fail views, queries, indexing and stats instead of hiding agents. one_agent_acrossreturnsResult<bool>: an unreadable forest is an error, notfalse.- Modules move:
handoffiscodex_handoff,loomissplice,harness::harmonyisharness::wire::harmony. wire::harmony::decode_contenttakes a call-id generator; derive position ids withir::derived_call_id.export::ChatGptExport,ClaudeExportand theirwith_rootsare gone; useharness::for_harness_with_root(Harness::ChatGptExport, dir)(orClaudeExport).codex::parse_str,gemini::parse_all_str,parse_all_str_forandingest::ingest_filesreturnResult; a codec failure is an error, not a partial session.store_affordancesandjson_filesreturnResult; failed side-store reads now fail affordance views and count publication.harness::wire::openai::tool_callsreturnsResult; an entry that fails to decode is an error, not a shorter list.affordance::classify_toolis private anditems_of/item_ofare gone; useclassify_tool_json/classify_tool_viewanditems_of_view/item_of_view.affordance::ReturnsgainsResultInPrompt, the spawn-table row for Roo'snew_task.affordance::{unwrap,rewrap}_deferredtake aDeferredWrapper, not aHarness;wire::anthropic's ownedTexter/block_from*/blocks_fromhelpers are gone.distill::distillsplits intoprepare_distillanddistill_pack;Session::first_user_textandsearchable_textare gone.SearchRow::to_jsonisto_json_with(&SearchRowContext);scan::live_searchislive_search_filtered;lazy::read_headisread_head_checked, returningResult.- Redaction and HTML message rendering require a resolver; Markdown consumers use
write_md_message/write_md_blockinstead of removed buffering wrappers. html::share_message_with_resolverisshare_message(.., resolver);redact::scrub_value/scrub_coware private: useredact_with,redact_messageorredact_text.RedactOptions.keep_emailsisclasses.emails, inverted:falsekeeps emails.task::AppendOutcome.replay_warnings(always empty) is gone.source::PublishedbecomesRecord<T>;Table<T: Payload>,getreturns aRecord,admitreplacespublished/fresh;updateis generic.source::rename_consumeris gone: a consumer missing its baselines under a new identity rereads the source instead of migrating them.catalog::fill_countis gone; a complete read certifies counts in the counts record.resume::versionreturnsString, notOption<String>;resume::MarkUpdateis a struct{session, mark}, not a tuple.publish::retractis gone: apublish::Setowns grouped rollback.EmitOptionsgainsparsed_at, so exhaustive struct literals break.EmitOptions.sidechain_ofisOption<SidechainOf {root, agent}>;PruneOptions/RewindOptionsgainskills_policyand their resultsskills, breaking exhaustive literals.prune::prune_sessiontakes the session'sHarnessfirst; prune and rewind accept a harness whose adapter declares derived copies.events::ingest_alltakes namedIngestOptionsinstead of two positional booleans.events::events_for,sessions_touching,sessions_editingandedits_touching_filereturnResult.query::WindowPresenceis gone:filter_refs_limiteddrops its presence argument and always skips absent sources before choosing the window.lanes::Lane.statusis aLaneStatus(Running,Stopped,Returned,Recorded(word);as_strand JSON unchanged);LaneEvent.eventisLaneEventKind.lanes::STRAND_PATTERNSis private:lanes::text_is_waitingis the strand check.ForestTools::for_workflowis gone;tools::forest_tools_selected(r, None, Some(run_id), None)reads only that workflow.query::HAS_FLAGSrows are(name, help, Cost)triples; destructuring code takes three fields.task::store::append_agent_event(the free function) is gone; callTaskStore::default_store().append_agent_event(event).Searcher::semanticis private; pass configuredSemanticSearchstate throughSearcher::from.- cv-search's root
text_search*,enrich_text_snippets,embed_allandsemantic_search_filteredbecomeSearcher::{search, search_in}andembed_sessions. fts::enrich_text_snippetsreturnsResult<Option<String>>(a degradation note). New fields (Stats.uncounted,HarnessCensus.first_error,LaneWork.unread) break exhaustive literals.- cv-testkit:
heap::begin/endreturn aMeasurementinstead of ausize. Env::enter_isolatedreturnsIsolated(armed, Scope), which derefs to the scope, instead of a bareScope.- cv-testkit:
claude::usertakes the session id first:user(sid, uuid, ts, text).
After upgrading, once.
- The first listing rediscovers the fleet (announced on stderr;
cv indexdoes it ahead): a catalog stamped with anothersource::VERSIONis dropped a...
0.17.0 — 2026-10-17 — stream, never materialize
Release Notes
cv's readers now stream: a giant tool output, a 60 MB escaped string or a 64 MiB SQLite cell
stays in its source file and is read through bounded windows, by one record codec per wire format.
cv index parses on every core and decodes compressed Codex rollouts with libzstd. Freshness is
verified on use, one record per consumer, over every primary source, sidecar and WAL, so a quiet
session's append is never missed. Search matches the exchange (what was asked, answered and run);
injected files, system prompts and hooks are --kind context. Untitled sessions are titled by
their first prompt. cv serve runs on a small built-in server. Measured on a frozen 5,421-session
fleet (Claude 38 GB, Codex 40 GB compressed, 89 GB decoded): a full index from an empty home takes
866 s at a 715 MB footprint, an unchanged index 0.4-0.8 s. No command is renamed or removed; the
table lists the flags, defaults, routes and MCP tool that changed.
| old | new |
|---|---|
GET /api/backlog |
GET /api/tasks?detail=1 (the old route answers 410 with this pointer) |
POST /api/task/{id}/reopen |
gone (410): a closed task stays closed; open a new task and note the old id |
MCP hook |
gone; a call points at hooks_install (it read Claude Code's hook JSON on stdin, so a call did nothing) |
cv search with no usable index scanned transcripts live |
an error naming the cause and the fix; cv search --scan (/api/search?scan=1) asks for the live scan |
| Codex plain rollouts over 8 MiB had extrapolated discovery counts | message_count: 0 means not counted; compressed rollouts are counted in full; indexing supplies exact catalog counts |
cv search matched injected files, system prompts and hooks |
matches the exchange; --kind context (/api/search?kind=context) for those, --kind all for both |
/api/search?semantic=1&kind=context |
400: vectors embed the exchange only |
cv port --thinking native|text|drop, default native; cv rewind copied reasoning byte for byte |
--thinking portable on port, rewind, splice, pack; port and rewind default native when every recorded model is claude-*, else portable |
prune --drop-thinking left an inline marker per flattened block |
omits the block; cv cat <new-id> <record-uuid>#think<i> returns it from the sidecar |
prune --to <taken id>; dataset, pack, share, distill --pack onto an existing name wrote into it |
exit 2, nothing written; --force (prune, dataset, pack, share, distill) replaces by atomic rename |
rewind --to and adopt refused a taken target with exit 1 |
exit 2; adopt --force still replaces; rewind requires another id |
cv index exit 1 when any session was unreadable |
exit 0 with warnings when some sessions succeed; all unreadable still fails; --strict fails on any; --json lists unreadable |
cv index --semantic --subagents |
a usage error before anything is written: run the two separately |
a pre-binary embeddings.json semantic store |
not read or migrated; cv index --semantic rebuilds |
cv tree, cv prompts, cv compaction, cv timeline, cv board and the other 0.15 names still
exit 2 with their pointers; the cvd and cv-mcp shims went in 0.16.0.
- Reject premature EOF in positioned JSONL reads instead of treating missing captured bytes as a partial final record.
- Preserve concurrent directory claims during fallback publication and restoration; retain both trees when restoration is blocked.
What reads differently (--json consumers):
- Codex
message_countcounts logical turns, as the parser does: no duplicated event
echoes, injected instructions or inherited history. OpenCode, Goose, Hermes, Devin and Qwen
discovery counts match their parsers too; cached counts refresh once. Plain Codex rollouts over
8 MiB report 0 until counted, replacing the old extrapolation. - An untitled session's
titleis its first exchange prompt, in index and scan hits, labels,
Markdown, share and archive, never an injected AGENTS.md or environment turn;ls --json --enrich
display_titleprefers the row'stitle. - Search hits match the exchange. Injected instructions, system prompts, skill bodies, hook
output, notices and compaction summaries match only with--kind context(orall); a fork's
copied turns hit their source once; snippets keep the original Unicode. Every indexed answer, hit
or miss, says how many sessions the index trails and by how long: stderr under--json, the
X-Cv-Search-Noteheader on/api/search. - Claude
rewindandportdefault tonativewhen every recorded model isclaude-*, else
portable: plaintext thinking demoted to text, signature-only reasoning removed (no placeholder),
illegal tool IDs mapped collision-free at both ends.rewindreports which.--thinking native
writes what 0.16 wrote. prune --drop-thinkingomits old thinking blocks with no inline marker, removing emptied records
and relinking their children;cv cat <new-id> <record-uuid>#think<i>still retrieves each.cv doctorandpruneseparate byte estimates from recorded prompt usage and rewritten resume
metadata; opaque thinking no longer counts as measured reasoning tokens. One estimator with
per-kind rates calibrated againstcount_tokensreplaces 3.5 bytes/token; prune's revive estimate
anchors on recorded usage and never read more than 1% low against the API. Human labels change;
--jsonkeys do not.- Session JSON (
show --json,/api/session/…/head, OpenSession) may carry a top-level
principal, a string or an object, absent when unset; a splice keeps it only when every source
agrees (#4). - Generated MCP tools return a successful command's stderr (continuation hints such as
task_events'snext: --since) as a second content block. Readcontent[0]; do not concatenate. -q:a|bis OR andfield="x"exact metadata equality; text equality errors naming the syntax
to use. A harness-qualified id (claude:abc) discovers only that harness on a catalog miss; id
prefixes stay case-sensitive.cv serveanswers 400 to malformed numeric parameters (/api/sessions?limit=abcwas ignored),
framing, headers and authorities. Task POSTs reject invalid JSON (400), oversized bodies (413),
and a non-JSON media type or forbidden origin (403).
GET /api/session/{harness}/{id}/exportdownloads the complete session as Markdown or OpenSession.ls --json --limit 0prints[]after argument validation without touching the inventory;
cv index --jsonprints{indexed, path, unreadable: [{id, harness, reason}]}.cv datasetkeeps a session-level system prompt without duplicating explicit system messages.
cv port --harness opencodewrites OpenCode 2.x rows and can bootstrap a fresh store; 1.x stores
still read.- Claude checkpoint counts keep restorable results, so
has:checkpointcan change after the
recount. Cursor Agent CLI chat and ACP stores appear as sessions.
One-time costs after upgrading (docs/design/PERF.md, 2026-10-14, release builds; frozen: an
APFS clone of 5,421 sessions, Claude 38 GB, Codex 40 GB compressed; live: ~7,000 sessions):
- Run
cv indexfirst. The full-text index rebuilds once for the exchange/context split, the
title rule and per-session metadata guards; afterwards a grown transcript is read from where the
last pass stopped. A full build from an empty home: 866 s at a 715 MB footprint frozen; 966 s,
RSS 3.4 GB live. Unchanged afterwards: 0.4-0.8 s frozen, 1.0-1.6 s live. - The first fleet read rediscovers every harness (the catalog's interpretation version changed) and
may print a stderr note suggestingcv indexwhen the old catalog records its interpretation
version:cv ls, first run, frozen, 158-186 s. Do not pay it inside an agent's MCP call. - Indexing refreshes counts, events and search baselines together; usage refreshes on its first
token-statistics read. Affordance counts (has:) are recounted (Claude checkpoints, OpenCode
turns); watch cursors record file identities on their next pass. cv search --semanticneedscv index --semanticonce more: vectors embed the exchange only and
a pre-binaryembeddings.jsonstore is no longer read (not measured).- The task log needs no migration. The catalog upgrades automatically: legacy counts and watch
tables are recreated, cache columns added and discovery invalidated. No manual migration command
is needed. Moving a home preserves its index when transcript paths and identities stay valid.
All changes
Reading
- Schema includes
hook_ledgeramong lane status sources and documents returned lanes; runtime lane JSON is unchanged. - Cursor Agent CLI chat and ACP blob stores are read: prompts, replies, tool calls, summaries, modes and lineage; numeric modes read as names.
- Untitled sessions are titled by their first prompt everywhere (index and scan hits, labels, Markdown, share, archive), never injected AGENTS.md or environment context.
ls --json --enrichdisplay_titleuses the row'stitlewhen present and never picks harness-injected turns such as Codex AGENTS.md instructions.- Codex discovery counts logical turns as parsing does, excluding event echoes, injected instructions and inherited history; OpenCode, Goose, Hermes, Devin and Qwen likewise.
- OpenCode: custom database names are discovered, WAL changes noticed, conflicting native ids refused; non-UTF-8-JSON message and part cells are skipped, not fatal.
- OpenClaw: an empty
event_jsonrow is skipped; exports keep native records, branch links, compaction metadata and grouped tool results; escaped branch controls are recognized. - Gemini accepts escaped wrapper metadata and keeps saved-chat message classification; checkpoint replay and composite tool results read with bounded memory.
- Kimi deferred wire outputs keep their source identity and reject replaced files; Ki...
0.16.1 — 2026-10-12 — approvals, checkpoints, and the side files
Release Notes
Two new affordance kinds, approval (asks, denials, the approval mode in force) and checkpoint
(restorable points, tallies, restores), and the side files 0.16.0 named as unread: Qwen schedules,
Cline schedule fires and team runs, OpenClaw cron and sub-agent registries, Kimi todos, Grok hook
runs; Claude --fork-session and Goose forks now name their source. Catalog counts carry a view
version, so has: recounts after an upgrade instead of answering from 0.16.0's counts: run
cv index once.
- New affordance kinds
approval(asks, denials, the session's approval mode) andcheckpoint(restorable points, restores) inshow --kindandhas:. - Roo
ui_messages.jsoncheckpoints and permission asks, and Grokrewind_points.jsonl, are now read. - Session JSON gains
permission_modesandcheckpointsin the harness bag (Claude, Codex, Kimi, Kimi Code, Qwen, Gemini saved chats). - Devin edit results carry
details.restorable, the files/revertcan restore. - Catalog affordance counts from 0.16.0 are recounted on the next full read, so
has:approval/has:checkpointnever answer from stale counts. - Side stores read: Qwen
scheduled_tasks.json, OpenClaw cron and sub-agent registries, Cline schedule runs andteams.db, Kimistate.jsontodos, Grok hook runs. - Catalog affordance counts are recounted once more, to include these side stores and forks.
- Claude
--fork-sessionand Goose--forksessions name their source inlineage.forked_from, inferred from the records the fork copied.
Install clustervision 0.16.1
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/emberian/cv/releases/download/v0.16.1/clustervision-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/emberian/cv/releases/download/v0.16.1/clustervision-installer.ps1 | iex"Download clustervision 0.16.1
| File | Platform | Checksum |
|---|---|---|
| clustervision-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| clustervision-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| clustervision-i686-pc-windows-msvc.zip | x86 Windows | checksum |
| clustervision-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| clustervision-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| clustervision-i686-unknown-linux-gnu.tar.xz | x86 Linux | checksum |
| clustervision-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.16.0 — 2026-10-12 — every harness, every version, every affordance
Release Notes
cv now carries a corpus of real sessions written by 17 harnesses at the versions in use and their
latest releases, re-read by a golden test, so a format change shows up as a test diff and old
formats keep reading. Building it found sessions cv could not see at all (OpenCode 2.x, Qwen Code
0.25, the Cline CLI store) and data it silently dropped (OpenClaw 10's compressed events, kimi-cli's
rotated segments, Grok reasoning). On top of it, one vocabulary for what swarms run on: plans,
goals, schedules, background jobs, sub-agent spawns and returns, skills, hooks, questions, branches,
forks and model changes, queried the same way on every harness with cv show --kind <affordance>
and -q has:<affordance>.
What reads differently: turns that spawn a sub-agent are subagent_spawn (and synchronous
results subagent_return) where they were reply/tool_result; Claude task-notifications and
interrupt/meta rows are no longer prompt; Hermes and OpenClaw tool_call wrappers read as the
tool they call. --json consumers keying on those kinds should update.
Run cv index once after upgrading: it counts every session's affordances so has: answers
from the catalog (minutes on a large fleet, incremental after).
All changes
-
The
cvdandcv-mcpshims are gone, as 0.15 announced:cv archive|watch|serveandcv mcp. A launchd job or MCP registration that names them needs the new spelling. -
has:planand the other affordance flags answer from per-session counts in the catalog (filled bycv indexand any full read); only uncounted sessions are parsed. -
cv tools --timelineshows each call'stool_use_id(in--jsontoo), the idcv cat <session> <id>takes. -
cv tools --timelineshows one line per tool call, matchingcv toolscounts; a multi-file patch's other files are inmore_targets. -
cv port --harness qwenwrites Qwen Code 0.25 session JSONL under~/.qwen/projects; it wrote the gemini-cli shape 0.25 no longer reads. -
cv show <id> --kind plan,schedule,background_job,…(affordancesfor all) lists plans, goals, schedules, jobs, spawns, skills, hooks and forks across harnesses, side stores included. -
-q has:plan,has:schedule,has:background_job, …: select sessions by affordance on any harness (cv ls, MCP,cv serve). -
Turns that spawn a sub-agent are
subagent_spawn, and synchronous resultssubagent_return, in Claude, OpenCode, Hermes, OpenClaw, Goose, Grok, Kimi, Roo, Cline, Devin, Continue. -
Claude: task-notifications are
subagent_return(agents, workflows) orinjected_context(commands); interrupt markers andisMetarows areinjected_context, notprompt. -
Hermes and OpenClaw 10.1: a
tool_callreads as the tool it calls, namespacetool_call; their emitters wrap it back. -
Side stores read: Claude
tasks/, Grokplan.json, OpenCodetodo, Geminitracker/andplans/, Goose's todo extension, Hermes goals, loops and heartbeats. -
A reply that spawns a sub-agent counts as a turn and stays in
dataset,distilland lane message counts. -
The
compacthook names the command that reads back the session's plan, schedules and background jobs. -
Qwen Code 0.25: sessions in
~/.qwen/projects/*/chats/*.jsonland their sub-agent transcripts are read; cv previously found none. -
Gemini: tool results and thoughts no longer appear twice after a resume, and a resumed 0.46 session is no longer hidden by its empty twin.
-
Gemini: hook context is its own turn;
invoke_agentcalls are sub-agent spawns and returns. -
Gemini and Qwen corpus: real stores from Gemini CLI 0.46.0 and 0.63.0 and Qwen Code 0.25.1 in the golden test.
-
Codex 0.161/0.162:
turn_abortednotes keep the aborterrorandroot_turn_id;cv formatsnames carried recordsevent_msg.<type>as the manifest does. -
Codex corpus: real rollouts from Codex 0.161.0 and 0.162.1, re-read by a golden test so every recorded format keeps reading.
-
cv indexmerges its segments itself, by size, to completion: no more abandoned ~1 GB background merge on long runs. -
cv show --last Nandcv export --last Nread the session once instead of counting it first: about half the time. -
Kimi discovery reuses the scan cache: an unchanged transcript costs a stat, not a full read.
-
A follower of a Codex session holds only the new messages, not the whole parsed rollout (595 MB to 124 MB on a 708 MB rollout).
-
A
cv searchmiss checks index staleness against the catalog instead of rescanning every harness: 0.53 s to 0.21 s. -
cv ls --enrichkeeps only each session's user turns while reading it: 720 MB to 80 MB peak on the largest sessions. -
cv catstops reading at the tool call it prints instead of holding the whole session. -
OpenCode 2.x: sessions in its new
session_v2/session_messagetables are read (2.x databases looked empty before); a migrated 1.x database shows each session once. -
OpenCode corpus: real stores from 1.18.20 and 2.0.25, plus 2.0.25's migration of the 1.18.20 store.
-
kimi-cli: sessions read every
context_N.jsonlsegment, not just the live file;/clearis a branch;subagents/parse as child sessions. -
Kimi Code 2.x:
subagent.spawned/completedare spawn/return turns,/undois a branch,kimi forksetslineage.forked_from. -
Kimi corpus: real stores from kimi-cli 1.48.0/1.51.0, Kimi Code 0.39.1/2.1.1, and a 0.39.1 store reopened by 2.1.1.
-
Cline: sessions from the CLI 3.x and the 4.x extension (
~/.cline/data/sessions/) are read, including spawned sub-agents and teammates. -
Roo: Roo CLI tasks (
~/.vscode-mock/global-storage/tasks/) are found; reasoning blocks, condense summaries andnew_taskparents are read. -
Continue: the cn CLI's tool results (
toolCallStates) and per-turn usage and model are read; they were missing. -
Devin: a
run_subagentchild, which has nosubagent_headsrow, is listed as its own session. -
Corpora for Cline 3.0.70, Roo CLI 0.1.17, Continue cn 1.5.47 and Devin 3000.11.3; schema snapshots for Zed 1.16.1 and LM Studio 0.4.21.
-
Claude Code 2.1.296:
ScheduleWakeupturns read asorigin: scheduler; its corpus (18 sessions, 6 sub-agents, a workflow) joins the golden test. -
Grok 1.0.50: reasoning records read as thinking; forks and sub-agents carry their parent; its corpus joins the golden test.
-
Goose: a real compaction (agent-visibility flip plus agent-only summary) reads as a compaction boundary; delegate results keep the child session id.
-
Goose corpus: real stores from Goose 1.51.0 and 1.54.0, covering every persisted affordance a headless run can drive.
-
OpenClaw 2026.10: zstd-compressed transcript events are read; before, every event of 1 KiB or more (most tool results) was silently dropped.
-
OpenClaw: sub-agent sessions name their parent (
lineage.parent); cron and sub-agent prompts get scheduler/subagent origin; sub-agent announces aresubagent_return. -
OpenClaw corpus: real stores from 2026.1.29 (JSONL) and 2026.10.1 (sqlite), re-read by the golden test.
-
Hermes 0.21: a
failed_turnrow (a turn that got no reply) reads as an error; v29–v31 identity and source columns ride inextra.hermes. -
Hermes corpus: real
state.dbstores from Hermes 2026.8.31 and 0.21.6, re-read by the golden test.
Install clustervision 0.16.0
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/emberian/cv/releases/download/v0.16.0/clustervision-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/emberian/cv/releases/download/v0.16.0/clustervision-installer.ps1 | iex"Download clustervision 0.16.0
| File | Platform | Checksum |
|---|---|---|
| clustervision-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| clustervision-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| clustervision-i686-pc-windows-msvc.zip | x86 Windows | checksum |
| clustervision-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| clustervision-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| clustervision-i686-unknown-linux-gnu.tar.xz | x86 Linux | checksum |
| clustervision-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
0.15.1 — 2026-10-11
Release Notes
- The
clustervisioncrate packages: thecvskill file lives inside the crate, socargo install clustervisionbuilds (0.15.0's CLI crate never reached crates.io). - CI packages every publishable crate on each push, so a file the published tarball lacks fails before a tag.
clustervision 0.15.1
Install clustervision 0.15.1
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/emberian/cv/releases/download/v0.15.1/clustervision-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/emberian/cv/releases/download/v0.15.1/clustervision-installer.ps1 | iex"Download clustervision 0.15.1
| File | Platform | Checksum |
|---|---|---|
| clustervision-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| clustervision-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| clustervision-i686-pc-windows-msvc.zip | x86 Windows | checksum |
| clustervision-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| clustervision-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| clustervision-i686-unknown-linux-gnu.tar.xz | x86 Linux | checksum |
| clustervision-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
cv-mcp 0.15.1
Install cv-mcp 0.15.1
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/emberian/cv/releases/download/v0.15.1/cv-mcp-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/emberian/cv/releases/download/v0.15.1/cv-mcp-installer.ps1 | iex"Download cv-mcp 0.15.1
| File | Platform | Checksum |
|---|---|---|
| cv-mcp-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| cv-mcp-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| cv-mcp-i686-pc-windows-msvc.zip | x86 Windows | checksum |
| cv-mcp-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| cv-mcp-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| cv-mcp-i686-unknown-linux-gnu.tar.xz | x86 Linux | checksum |
| cv-mcp-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |
cvd 0.15.1
Install cvd 0.15.1
Install prebuilt binaries via shell script
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/emberian/cv/releases/download/v0.15.1/cvd-installer.sh | shInstall prebuilt binaries via powershell script
powershell -ExecutionPolicy Bypass -c "irm https://github.com/emberian/cv/releases/download/v0.15.1/cvd-installer.ps1 | iex"Download cvd 0.15.1
| File | Platform | Checksum |
|---|---|---|
| cvd-aarch64-apple-darwin.tar.xz | Apple Silicon macOS | checksum |
| cvd-x86_64-apple-darwin.tar.xz | Intel macOS | checksum |
| cvd-i686-pc-windows-msvc.zip | x86 Windows | checksum |
| cvd-x86_64-pc-windows-msvc.zip | x64 Windows | checksum |
| cvd-aarch64-unknown-linux-gnu.tar.xz | ARM64 Linux | checksum |
| cvd-i686-unknown-linux-gnu.tar.xz | x86 Linux | checksum |
| cvd-x86_64-unknown-linux-gnu.tar.xz | x64 Linux | checksum |