@@ -496,21 +496,31 @@ def cmd_update(args: argparse.Namespace) -> int:
496496
497497def cmd_update_local (args : argparse .Namespace ) -> int :
498498 """Update only local installation state (fast, no network)."""
499- print ("=" * 80 , file = sys .stderr )
500- print ("Update Local State" , file = sys .stderr )
501- print ("=" * 80 , file = sys .stderr )
499+ # Check if we're in merge mode (updating specific tools only)
500+ merge_mode = os .environ .get ("CLI_AUDIT_MERGE" , "0" ) == "1"
501+ specific_tools = bool (args .tools )
502+
503+ # Only show header if not in quiet merge mode
504+ if not (merge_mode and specific_tools ):
505+ print ("=" * 80 , file = sys .stderr )
506+ print ("Update Local State" , file = sys .stderr )
507+ print ("=" * 80 , file = sys .stderr )
502508
503509 # Get tools to audit
504510 tools_list = filter_tools (args .tools ) if args .tools else all_tools ()
505511 total = len (tools_list )
506512
507- print (f"# Detecting local installations for { total } tools..." , file = sys .stderr )
513+ if not (merge_mode and specific_tools ):
514+ print (f"# Detecting local installations for { total } tools..." , file = sys .stderr )
508515
509516 # Load existing upstream cache for status determination
510517 upstream_cache = load_upstream_cache ()
511518
512- # Collect local state only (no network calls)
513- local_state = LocalState ()
519+ # In merge mode with specific tools, load existing local state first
520+ if merge_mode and specific_tools :
521+ local_state = load_local_state ()
522+ else :
523+ local_state = LocalState ()
514524 completed = 0
515525
516526 with ThreadPoolExecutor (max_workers = min (MAX_WORKERS , total )) as executor :
@@ -547,14 +557,40 @@ def cmd_update_local(args: argparse.Namespace) -> int:
547557
548558 # Write local state
549559 write_local_state (local_state , offline = OFFLINE_MODE )
550- print ("" , file = sys .stderr )
551- print (f"✓ Local state updated: { get_local_state_path ()} " , file = sys .stderr )
552- print (f"✓ Detected { len (local_state .tools )} tools" , file = sys .stderr )
553560
554- # Also update legacy snapshot for backward compatibility
555- legacy_snapshot = build_legacy_snapshot (upstream_cache , local_state )
556- write_snapshot (legacy_snapshot .get ("tools" , []), offline = OFFLINE_MODE )
557- print (f"✓ Legacy snapshot updated: { get_snapshot_path ()} " , file = sys .stderr )
561+ if not (merge_mode and specific_tools ):
562+ print ("" , file = sys .stderr )
563+ print (f"✓ Local state updated: { get_local_state_path ()} " , file = sys .stderr )
564+ print (f"✓ Detected { len (local_state .tools )} tools" , file = sys .stderr )
565+
566+ # Update legacy snapshot for backward compatibility
567+ if merge_mode and specific_tools :
568+ # In merge mode, load existing snapshot and merge in updated tools
569+ existing_snapshot = load_snapshot ()
570+ existing_tools = existing_snapshot .get ("tools" , [])
571+
572+ # Build dict of existing tools keyed by name
573+ tools_by_name = {t .get ("tool" ): t for t in existing_tools }
574+
575+ # Get updated tool data for the specific tools we just detected
576+ updated_tools = build_legacy_snapshot (upstream_cache , local_state ).get ("tools" , [])
577+ tools_to_update = {tool .name for tool in tools_list }
578+ updated_tool_names = {t .get ("tool" ) for t in updated_tools if t .get ("tool" ) in tools_to_update }
579+
580+ # Merge: update only the tools we re-detected
581+ for updated_tool in updated_tools :
582+ tool_name = updated_tool .get ("tool" )
583+ if tool_name in updated_tool_names :
584+ tools_by_name [tool_name ] = updated_tool
585+
586+ # Write merged snapshot
587+ merged_tools = list (tools_by_name .values ())
588+ write_snapshot (merged_tools , offline = OFFLINE_MODE )
589+ else :
590+ # Full update: replace entire snapshot
591+ legacy_snapshot = build_legacy_snapshot (upstream_cache , local_state )
592+ write_snapshot (legacy_snapshot .get ("tools" , []), offline = OFFLINE_MODE )
593+ print (f"✓ Legacy snapshot updated: { get_snapshot_path ()} " , file = sys .stderr )
558594
559595 return 0
560596
0 commit comments