



  

<!DOCTYPE html>
<html
  lang="en"
  
  data-color-mode="auto" data-light-theme="light" data-dark-theme="dark"
  data-a11y-animated-images="system" data-a11y-link-underlines="true"
  
  >




  <head>
    <meta charset="utf-8">
  <link rel="dns-prefetch" href="https://github.githubassets.com">
  <link rel="dns-prefetch" href="https://avatars.githubusercontent.com">
  <link rel="dns-prefetch" href="https://github-cloud.s3.amazonaws.com">
  <link rel="dns-prefetch" href="https://user-images.githubusercontent.com/">
  <link rel="preconnect" href="https://github.githubassets.com" crossorigin>
  <link rel="preconnect" href="https://avatars.githubusercontent.com">

<script type="importmap">{"imports":{"react":"https://github.githubassets.com/assets/react-e27d1b3e03961e68.js","react-dom":"https://github.githubassets.com/assets/react-dom-e5fd46a22d5c4058.js","react-dom/client":"https://github.githubassets.com/assets/react-dom-client-1b4a3ee065998cea.js","react-is":"https://github.githubassets.com/assets/react-is-e0b593954b4706d8.js","react-reconciler":"https://github.githubassets.com/assets/react-reconciler-8e99e505c4429605.js","react/compiler-runtime":"https://github.githubassets.com/assets/react-compiler-runtime-4610bd6d3de9c049.js","react/jsx-dev-runtime":"https://github.githubassets.com/assets/react-jsx-dev-runtime-ea55d68667d559e5.js","react/jsx-runtime":"https://github.githubassets.com/assets/react-jsx-runtime-4915cb0f5b3aff04.js","scheduler":"https://github.githubassets.com/assets/scheduler-58b860b049ca307c.js"}}</script>
<meta name="react-profiling" content="0" data-turbo-transient="true" />
<meta name="react-import-map" content="react,react-dom,react-dom/client,react-dom/profiling,react-is,react-reconciler,react/compiler-runtime,react/jsx-dev-runtime,react/jsx-runtime,scheduler@777f63f87cd0" data-turbo-track="reload" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-e27d1b3e03961e68.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-compiler-runtime-4610bd6d3de9c049.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/scheduler-58b860b049ca307c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-dom-e5fd46a22d5c4058.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-dom-client-1b4a3ee065998cea.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-is-e0b593954b4706d8.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-jsx-runtime-4915cb0f5b3aff04.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-reconciler-8e99e505c4429605.js" />

  


  <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/light-5c4e9fc574bf49f3.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/light_high_contrast-fb37c309e0603a69.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/dark-afff6c53aef9b9d1.css" /><link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/dark_high_contrast-c409873d7987dffa.css" /><link data-color-theme="light" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light-5c4e9fc574bf49f3.css" /><link data-color-theme="light_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_high_contrast-fb37c309e0603a69.css" /><link data-color-theme="light_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_colorblind-0f910d8806d5761b.css" /><link data-color-theme="light_colorblind_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_colorblind_high_contrast-a7abd4d4c49ac593.css" /><link data-color-theme="light_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_tritanopia-5fc4c4a9cb41e596.css" /><link data-color-theme="light_tritanopia_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/light_tritanopia_high_contrast-ed0cee9214dedabd.css" /><link data-color-theme="dark" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark-afff6c53aef9b9d1.css" /><link data-color-theme="dark_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_high_contrast-c409873d7987dffa.css" /><link data-color-theme="dark_colorblind" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_colorblind-78a2491d538dab5a.css" /><link data-color-theme="dark_colorblind_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_colorblind_high_contrast-c26b63d7c532d0a2.css" /><link data-color-theme="dark_tritanopia" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_tritanopia-a6f60cea68c08405.css" /><link data-color-theme="dark_tritanopia_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_tritanopia_high_contrast-f66faf28b2ea18b6.css" /><link data-color-theme="dark_dimmed" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_dimmed-6701f6218c53cf5b.css" /><link data-color-theme="dark_dimmed_high_contrast" crossorigin="anonymous" media="all" rel="stylesheet" data-href="https://github.githubassets.com/assets/dark_dimmed_high_contrast-7037fa46ae124d97.css" />

  <style type="text/css">
    :root {
      --tab-size-preference: 4;
    }

    pre, code {
      tab-size: var(--tab-size-preference);
    }
  </style>

    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-primitives-97df7784617ce1ea.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-9be9fe6313f476af.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/global-62747e27e61258dc.css" />
    <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/github-b04ca6fccda778e2.css" />
  <link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/repository-72bd7d974b5ac1cc.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-4c5c0895f723f870.css" />

  

  <script type="application/json" id="client-env">{"locale":"en","featureFlags":["actions_caches_react_shell","actions_enable_background_steps","actions_new_hosted_runner_image_select_sizes_and_versions","actions_runners_react_shell","agent_author_search_expansion","agent_author_search_expansion_ui_pulls","alternate_user_config_repo","async_conversion_coverage_enabled","billing_billable_licenses_cost_center_bucket_fix","billing_budget_expiration","billing_cost_center_list_assigned_resources","billing_discount_threshold_notification","code_quality_enablement_banner_targeting","code_quality_remove_preview","code_view_raf_sticky_lines","codespaces_prebuild_region_target_update","coding_agent_third_party_model_ui","copilot_agent_snippy","copilot_ahp_tool_call_timing","copilot_api_agentic_issue_marshal_yaml","copilot_automation_repo_mcp_servers","copilot_automations_pagination","copilot_base_model_policy_row","copilot_chat_auto_mode_v2","copilot_chat_clear_model_selection_for_default_change","copilot_chat_early_task_provisioning","copilot_chat_persist_session_drafts","copilot_chat_vision_dotcom_chat_ga_gate","copilot_css_textarea_autosize","copilot_custom_copilots","copilot_custom_copilots_feature_preview","copilot_duplicate_thread","copilot_extensions_removal_on_marketplace","copilot_fix_failed_workflows_all_skus","copilot_hide_hovercard","copilot_immersive_task_hyperlinking","copilot_mc_cli_resume_any_users_task","copilot_mission_control_agent_merge_fix_ci","copilot_mission_control_agent_merge_resolve_conflicts","copilot_mission_control_awps_batching","copilot_mission_control_early_stop","copilot_mission_control_managed_sandbox_environments","copilot_mission_control_needs_attention","copilot_mission_control_reasoning_effort","copilot_mission_control_sandbox_remote_bypass","copilot_mission_control_task_alive_updates","copilot_mission_control_task_sharing","copilot_org_policy_page_focus_mode","copilot_share_active_subthread","copilot_spaces_ga","copilot_spaces_individual_policies_ga","copilot_swe_agent_authorization_status_ui","copilot_swe_agent_automation_resource_scoped_writes","copilot_swe_agent_discussion_comment_trigger","copilot_swe_agent_discussion_opened_trigger","copilot_swe_agent_discussion_updated_trigger","copilot_swe_agent_hide_model_picker_if_only_auto","copilot_swe_agent_issue_assigned_trigger","copilot_swe_agent_issue_comment_trigger","copilot_swe_agent_issue_labeled_trigger","copilot_swe_agent_pr_comment_model_picker","copilot_swe_agent_pull_request_assigned_trigger","copilot_swe_agent_pull_request_comment_trigger","copilot_swe_agent_pull_request_labeled_trigger","copilot_swe_agent_pull_request_merged_trigger","copilot_swe_agent_pull_request_opened_trigger","copilot_swe_agent_pull_request_ready_for_review_trigger","copilot_swe_agent_pull_request_review_requested_trigger","copilot_swe_agent_pull_request_review_submitted_trigger","copilot_swe_agent_pull_request_synchronize_trigger","copilot_swe_agent_sub_issue_added_trigger","copilot_swe_agent_use_subagents","copilot_task_api_github_rest_style","copilot_task_scoped_alive_channel","copilot_token_based_billing","copilot_unconfigured_is_inherited","copilot_user_can_upgrade_plan_field","copilot_web_integration_cutover","copilot_workbench_sunset_redirect","dashboard_agents_module_auth_token_check","dashboard_indexeddb_caching","fgpat_permissions_selector_redesign","glc_code_quality_repo_settings_workflow_config","hyperspace_2025_logged_out_batch_1","hyperspace_2025_logged_out_batch_2","hyperspace_2025_logged_out_batch_3","in_product_messaging_datadog_monitoring","ipm_ubb_individual_budget_banner","issue_fields_multi_select","issue_inline_avatars","issue_pinned_views","issue_pinned_views_team_vs_personal","issue_relative_time_micro","issue_viewer_paved_path","issues_expanded_file_types","issues_hide_closed_sub_issues","issues_lazy_load_comment_box_suggestions","issues_react_chrome_container_query_fix","labels_archiving","labels_archiving_info","landing_pages_ninetailed","lifecycle_label_name_updates","marketing_cookie_consent_banner","marketing_pages_search_explore_provider","memex_default_issue_create_repository","memex_live_update_hovercard","memex_mwl_filter_field_delimiter","memex_remove_deprecated_type_issue","merge_queue_restricted_pushers_warning","merge_status_header_feedback","milestone_closed_issues_prioritization","octocaptcha_origin_optimization","primer_react_css_anchor_positioning","primer_react_merged_forwarded_refs","primer_react_timeline_list_semantics","prs_copilot_app_open_action","prs_css_anchor_positioning","pull_request_copilot_attribution_header","pull_request_overview_merge_control","pull_request_overview_panel_edit_description","pull_request_persister","pull_request_stacks_navigation_shortcuts","pull_request_virtualization_image_estimate","pull_request_virtualization_loader_batching","pull_request_virtualization_scroll_compensation","pull_request_virtualization_scroll_intent","quick_search_lazy_suggestions","react_blob_isolate_code_lines","react_blob_ssr_content_visibility","react_data_router_tanstack_allowed","react_logged_out_repository_header","react_query_props_with_key","react_sandbox_future_tanstack","repo_app_turbo","repo_issues_sidebar_layout","repo_pulls_dashboard_declutter","repo_pulls_dashboard_ga","repo_pulls_dashboard_persistence","repos_contributors_limited_default_range","review_involves_filter","rule_ignored_file_paths","rulesets_actor_list_editor","sample_network_conn_type","security_center_artifact_filters_popover","see_who_reacted","semantic_similarity_duplicate_issue_detection","session_logs_ungroup_reasoning_text","set_sha256_on_repo_creation_form","site_banner_desktop_copilot_app","site_ghca_pixel_mona","site_github_app_ga_page","site_github_app_ga_page_highlight","site_github_app_mobile_native_share","site_global_banner_dev_days_attendee","site_global_nav_spark_models_removed","speculation_rules_ui_service","suggest_custom_property_values_copilot","suppress_automated_browser_vitals","swp_forms_disable_octocaptcha","thread_resolution_reason","update_issue_suggestions","viewscreen_sandbox","warn_inaccessible_attachments","webp_support","workstream_plugin_bootstrap"],"githubDomain":"https://github.com","copilotApiOverrideUrl":"https://api.githubcopilot.com","cmcApiUrl":"https://api.github.com/cmc_internal/api"}</script>
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/high-contrast-cookie-3663bcaacc724f4c.js"></script>
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wp-runtime-721126455a2225e3.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-foundation-156c6259e31cc551.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-runtime-f6ce38f47c2e1d56.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fetch-utilities-804a14996977c014.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ser-fb5d13278eb42203.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/tp-ea613009a991e211.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/environment-107a7753389a8a2d.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/app-runtime.25915bc98fb322a6.module.css" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/catalyst-52ed81112a548e10.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/selector-observer-e8810f64c443fb9b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/relative-time-element-fe7e72f699fdf493.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/by-9da36843ba9d191d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ja9-9a1160b939f2cd52.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/3h-55903cf2303047ad.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hk-0d35a1220587d888.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/jz5-c964b1a3671f2a92.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hj-1d800d09e9a8720a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j0-1ad12374da9777f2.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/github-elements-531d35538b61fd0d.js" defer="defer"></script>
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/element-registry-bf5e3b2aee197122.js" defer="defer"></script>
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/runtime-helpers-5e0b3ae3c4036207.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/aria-live-752acdc868e2da64.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hotkey-e87ffadced20a3c9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/react-core-75bc55d9971828b7.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/a9-34620c7b13885011.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ur-643d2814115561a9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4t6-5d0869970ac0aac0.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/pb0-a5c5ec36d311aeef.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/6n-afcf86ccabc4cad2.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/zj-f08c728cf00018aa.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/o6-2a1c68d269710ee9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/h9a-c6405aa090de0e84.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/vy6-3c3e6e96629c2ce4.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/js-4eb97d5803e657c0.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/g7-baf9e817ae102b01.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/unc-96389cade7bad821.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/nu-65322a6997c6c93c.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/behaviors-5dd3809b5c8bac3c.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/react-core.3792087592bf207a.module.css" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/code-menu-4318f0f4c608f3dd.js" defer="defer"></script>
  
  <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/primer-react-7afef75d393cf294.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/op-acddf38478d45ef9.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ncx-461e4b09f2e67ee5.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/qmp-c7cfba40cf5a93b0.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j6-148a74299e5a01ab.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/t7l-a52ba56147f77909.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4u-ec4874f70bfd5d76.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/s0-481bd34f90bc2bd7.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/y5-ed17e73b4c0bd15e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/n4-be595475cdbf7d4b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j8-23a3c5ff8eef412d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/la-27679061f16e1495.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/iu-9806a0291a782cbe.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ftx-39fb490e3c1d778f.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/zi-32a0c3c081ea5cce.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/sg-7a5d50475874c0e1.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/pd-6a8710840033e042.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/86g-ec28c25ed7d5de06.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/sn-1bab7384818953b7.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/iq-6d4ecf6d2fb6993c.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/p2-7d8e7cee5b46cb45.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/7d-2e3cc25d719f3a95.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/4d-76d8acdf21a33266.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/tsb-e0f6288ab985d9d2.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/lf-910ef220ce85c660.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/2j-2f19c1afd2ceaf93.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/me-f1476ec44a29f34a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/p2u-e654a57b1a70c47d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/5d-d97cc006d4da4d9b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/r5-38f013bc2c0fd298.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/r6s-9039f5619230a653.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/9e-cece06724bf6ea3b.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/x9-3e077a3a37a73f9f.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/pj-87629cb5389d7663.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/eq-3764fd5f66494289.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/13-d889936dff7e5c0f.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/44-8193eea4af825ead.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/v4-9c1327d212e52a0d.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/id-7f39706ba9007db6.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ah-271362a1ed227d03.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/s1g-d434d712bca59d3a.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/vz-d7f4a583896f872e.js" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/47-c8c0ce2700acc5be.js" />
<script crossorigin="anonymous" type="module" src="https://github.githubassets.com/assets/code-view-4118a687d0150749.js" defer="defer"></script>
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/pj.75627bfeb9ceb1da.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/ah.2623f7c6ecbe2ecd.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/47.78770c57a48a810c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/code-view.37656c95a9729fb9.module.css" />


  <title>herdr-switchboard/CLAUDE.md at main · crafts69guy/herdr-switchboard · GitHub</title>



  <meta name="route-pattern" content="/:user_id/:repository/blob/*name(/*path)" data-turbo-transient>
  <meta name="route-controller" content="blob" data-turbo-transient>
  <meta name="route-action" content="show" data-turbo-transient>
  <meta name="fetch-nonce" content="v2:319a490f-7bc9-6778-a8e3-a2008afa0827">

    
  <meta name="current-catalog-service-hash" content="f3abb0cc802f3d7b95fc8762b94bdcb13bf39634c40c357301c4aa1d67a256fb">


  <meta name="request-id" content="A294:3A599A:B17E459:E748514:6ACA5F06" data-pjax-transient="true"/><meta name="html-safe-nonce" content="6c93c603de9764c08258ddf93e7ffc59f4194d127754cf2f325cfee28f4ceaf7" data-pjax-transient="true"/><meta name="visitor-payload" content="eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiJBMjk0OjNBNTk5QTpCMTdFNDU5OkU3NDg1MTQ6NkFDQTVGMDYiLCJ2aXNpdG9yX2lkIjoiMzY3MDY0Mjc3MjgxMTYwMzcxOCIsInJlZ2lvbl9lZGdlIjoiZnJhIiwicmVnaW9uX3JlbmRlciI6ImZyYSJ9" data-pjax-transient="true"/><meta name="visitor-hmac" content="e1ea3824416c7800520beb9dbf298662d639855ce0aba1c5443262ddd73e3d11" data-pjax-transient="true"/>


    <meta name="hovercard-subject-tag" content="repository:1302250949" data-turbo-transient>


  <meta name="github-keyboard-shortcuts" content="repository,source-code,file-tree,copilot" data-turbo-transient="true" />
  

  <meta name="selected-link" value="repo_source" data-turbo-transient>
  <link rel="assets" href="https://github.githubassets.com/">

    <meta name="google-site-verification" content="Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I">

<meta name="octolytics-url" content="https://collector.github.com/github/collect" />





  <meta name="analytics-location" content="/&lt;user-name&gt;/&lt;repo-name&gt;/blob/show" data-turbo-transient="true" />

  




    <meta name="user-login" content="">

  

    <meta name="viewport" content="width=device-width">

    

      <meta name="description" content="A herdr plugin: fuzzy-switch across running agents, open workspaces, and ghq repositories in one Rust TUI — and open a repo in a new workspace, tab, split, or the current pane. - herdr-switchboard/CLAUDE.md at main · crafts69guy/herdr-switchboard">

      <link rel="search" type="application/opensearchdescription+xml" href="/opensearch.xml" title="GitHub">

    <link rel="fluid-icon" href="https://github.com/fluidicon.png" title="GitHub">
    <meta property="fb:app_id" content="1401488693436528">
    <meta name="apple-itunes-app" content="app-id=1477376905, app-argument=https://github.com/crafts69guy/herdr-switchboard/blob/main/CLAUDE.md" />

      <meta name="twitter:image" content="https://opengraph.githubassets.com/d1e2e05d1d2830fa9bb9166043f58edfe28c3640a68393c215535824fd1f7748/crafts69guy/herdr-switchboard" /><meta name="twitter:site" content="@github" /><meta name="twitter:card" content="summary_large_image" /><meta name="twitter:title" content="herdr-switchboard/CLAUDE.md at main · crafts69guy/herdr-switchboard" /><meta name="twitter:description" content="A herdr plugin: fuzzy-switch across running agents, open workspaces, and ghq repositories in one Rust TUI — and open a repo in a new workspace, tab, split, or the current pane. - crafts69guy/herdr-..." />
  <meta property="og:image" content="https://opengraph.githubassets.com/d1e2e05d1d2830fa9bb9166043f58edfe28c3640a68393c215535824fd1f7748/crafts69guy/herdr-switchboard" /><meta property="og:image:alt" content="A herdr plugin: fuzzy-switch across running agents, open workspaces, and ghq repositories in one Rust TUI — and open a repo in a new workspace, tab, split, or the current pane. - crafts69guy/herdr-..." /><meta property="og:image:width" content="1200" /><meta property="og:image:height" content="600" /><meta property="og:site_name" content="GitHub" /><meta property="og:type" content="object" /><meta property="og:title" content="herdr-switchboard/CLAUDE.md at main · crafts69guy/herdr-switchboard" /><meta property="og:url" content="https://github.com/crafts69guy/herdr-switchboard/blob/main/CLAUDE.md" /><meta property="og:description" content="A herdr plugin: fuzzy-switch across running agents, open workspaces, and ghq repositories in one Rust TUI — and open a repo in a new workspace, tab, split, or the current pane. - crafts69guy/herdr-..." />
  




      <meta name="hostname" content="github.com">



        <meta name="expected-hostname" content="github.com">


  <meta http-equiv="x-pjax-version" content="d05be8f8b6905b6460fc264e80447721dfee1e32cf9e4291c4bf58f160c9f705" data-turbo-track="reload">
  <meta http-equiv="x-pjax-csp-version" content="c4a65e47b0c850e1157ae8e66298070851d7e3b558038de5a3b4ff7a93e630ed" data-turbo-track="reload">
  <meta http-equiv="x-pjax-css-version" content="a80b0545b169f440b929ce2b977c76b6988f014cca6513fb83c5df6581635fb3" data-turbo-track="reload">
  <meta http-equiv="x-pjax-js-version" content="af51c6f9d659be0324665373df3ee542f817dbd7f66f352a087935f2ceabe545" data-turbo-track="reload">

  <meta name="turbo-cache-control" content="no-preview" data-turbo-transient="">

      <meta name="turbo-cache-control" content="no-cache" data-turbo-transient>

    <meta data-hydrostats="publish">

  <meta name="go-import" content="github.com/crafts69guy/herdr-switchboard git https://github.com/crafts69guy/herdr-switchboard.git">

  <meta name="octolytics-dimension-user_id" content="64419455" /><meta name="octolytics-dimension-user_login" content="crafts69guy" /><meta name="octolytics-dimension-repository_id" content="1302250949" /><meta name="octolytics-dimension-repository_nwo" content="crafts69guy/herdr-switchboard" /><meta name="octolytics-dimension-repository_public" content="true" /><meta name="octolytics-dimension-repository_is_fork" content="false" /><meta name="octolytics-dimension-repository_network_root_id" content="1302250949" /><meta name="octolytics-dimension-repository_network_root_nwo" content="crafts69guy/herdr-switchboard" />
  



    

    <meta name="turbo-body-classes" content="logged-out env-production page-responsive">
  <meta name="disable-turbo" content="false">


  <meta name="browser-stats-url" content="https://api.github.com/_private/browser/stats">


  <meta name="browser-errors-url" content="https://api.github.com/_private/browser/errors">

  <meta name="release" content="3b1bb5b10f5c7fd1769d56e38b15dfddb34052a8" data-turbo-track="reload">
  <meta name="ui-target" content="full">

  <link rel="mask-icon" href="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" color="#000000">
  <link rel="alternate icon" class="js-site-favicon" type="image/png" href="https://github.githubassets.com/favicons/favicon.png">
  <link rel="icon" class="js-site-favicon" type="image/svg+xml" href="https://github.githubassets.com/favicons/favicon.svg" data-base-href="https://github.githubassets.com/favicons/favicon">

<meta name="theme-color" content="#1e2327">
<meta name="color-scheme" content="light dark" />


  <link rel="manifest" href="/manifest.json" crossOrigin="use-credentials">

  </head>

  <body class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
    <div data-turbo-body class="logged-out env-production page-responsive" style="word-wrap: break-word;" >
      <div id="__primerPortalRoot__" style="z-index: 1000; position: absolute; width: 100%;" data-turbo-permanent></div>
      

    <div class="position-relative header-wrapper js-header-wrapper ">
      <a href="#start-of-content" data-skip-target-assigned="false" class="px-2 tmp-py-4 color-bg-accent-emphasis color-fg-on-emphasis show-on-focus js-skip-to-content">Skip to content</a>

      <span data-view-component="true" class="progress-pjax-loader Progress position-fixed width-full">
    <span style="width: 0%;" data-view-component="true" class="Progress-item progress-pjax-loader-bar left-0 top-0 color-bg-accent-emphasis"></span>
</span>      
      <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/19-c660652a0a1639be.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/keyboard-shortcuts-dialog-47c5223d8d1af8ef.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/keyboard-shortcuts-dialog.d53d993320d57e14.module.css" />

<react-partial
  partial-name="keyboard-shortcuts-dialog"
  data-ssr="false"
  data-attempted-ssr="false"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{"docsUrl":"https://docs.github.com/get-started/accessibility/keyboard-shortcuts"}}</script>
  <div data-target="react-partial.reactRoot"></div>
</react-partial>





      

          <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/app-install-banner-partial-3c87deb7f0f20434.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/app-install-banner-partial.7b357012e82003e7.module.css" />

<react-partial
  partial-name="app-install-banner-partial"
  data-ssr="false"
  data-attempted-ssr="false"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{}}</script>
  <div data-target="react-partial.reactRoot"></div>
</react-partial>


          

                <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/et9-7eeec247c287fca4.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/94v-e20946127faa8f6e.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fz5-892a9e99cc92858d.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/jag-441e702bfd4c7904.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/hw-8ce7888b57d0a23c.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/rq-0ec82a12cf538a4d.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/1m-a7a4c022483b2713.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/marketing-header-70703fe17422eb58.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-brand-css.fbc35b3d20e988ff.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/1m.fec8b575d0e5234f.module.css" />

<react-partial
  partial-name="marketing-header"
  data-ssr="true"
  data-attempted-ssr="true"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{"color_mode":"dark","logged_in":false,"marketing_page":false,"home_path":"/","login_path":"/login?return_to=https%3A%2F%2Fgithub.com%2Fcrafts69guy%2Fherdr-switchboard%2Fblob%2Fmain%2FCLAUDE.md","signup_path":"/signup?ref_cta=Sign+up\u0026ref_loc=header+logged+out\u0026ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fblob%2Fshow\u0026source=header-repo\u0026source_repo=crafts69guy%2Fherdr-switchboard","signup_enabled":true,"is_signup_controller":false,"show_search_and_nav":true,"hide_search":false,"private_mode_enabled":false,"should_use_dotcom_links":true,"auth_hydro_click":"{\"event_type\":\"authentication.click\",\"payload\":{\"location_in_page\":\"site header menu\",\"repository_id\":null,\"auth_type\":\"SIGN_UP\",\"originating_url\":\"https://github.com/crafts69guy/herdr-switchboard/blob/main/CLAUDE.md\",\"user_id\":null}}","auth_hydro_click_hmac":"199aa0d6285e192df4c5a8022b451ee2d8d54c312501a59416de7308f6337d9b","overlay":false,"fixed":false}}</script>
  <div data-target="react-partial.reactRoot"><div data-color-mode="dark" data-light-theme="light" data-dark-theme="dark"><header class="MarketingHeader-module__root__Tk7n3 HeaderMktg header-logged-out" role="banner" data-marketing-header="true" data-color-mode="dark" data-light-theme="light" data-dark-theme="dark" data-is-top="true"><h2 class="MarketingHeader-module__visuallyHidden__sqKsl">Navigation Menu</h2><button type="button" class="MarketingHeader-module__backdrop__sw4RU" aria-label="Close navigation menu"></button><div class="MarketingHeader-module__bar__mBSyE"><div class="MarketingHeader-module__topRow__yeury"><div class="MarketingHeader-module__toggleSlot__hDxbh"><button type="button" class="HeaderMenuToggle-module__toggle__i8EiC" aria-label="Toggle navigation" aria-expanded="false"><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span><span class="HeaderMenuToggle-module__toggleBar__jVN0H"></span></button></div><a href="/" aria-label="Homepage" class="HeaderLogo-module__logo__UFyHI" data-analytics-event="{&quot;action&quot;:&quot;homepage&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;logo&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;homepage_link_logo_header&quot;}"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mark-github" viewBox="0 0 24 24" width="32" height="32" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.226 17.284c-2.965-.36-5.054-2.493-5.054-5.256 0-1.123.404-2.336 1.078-3.144-.292-.741-.247-2.314.09-2.965.898-.112 2.111.36 2.83 1.01.853-.269 1.752-.404 2.853-.404 1.1 0 1.999.135 2.807.382.696-.629 1.932-1.1 2.83-.988.315.606.36 2.179.067 2.942.72.854 1.101 2 1.101 3.167 0 2.763-2.089 4.852-5.098 5.234.763.494 1.28 1.572 1.28 2.807v2.336c0 .674.561 1.056 1.235.786 4.066-1.55 7.255-5.615 7.255-10.646C23.5 6.188 18.334 1 11.978 1 5.62 1 .5 6.188.5 12.545c0 4.986 3.167 9.12 7.435 10.669.606.225 1.19-.18 1.19-.786V20.63a2.9 2.9 0 0 1-1.078.224c-1.483 0-2.359-.808-2.987-2.313-.247-.607-.517-.966-1.034-1.033-.27-.023-.359-.135-.359-.27 0-.27.45-.471.898-.471.652 0 1.213.404 1.797 1.235.45.651.921.943 1.483.943.561 0 .92-.202 1.437-.719.382-.381.674-.718.944-.943"></path></svg></a><div class="AuthCTAs-module__mobileActions__NNzeV"><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq" href="/login?return_to=https%3A%2F%2Fgithub.com%2Fcrafts69guy%2Fherdr-switchboard%2Fblob%2Fmain%2FCLAUDE.md" data-analytics-event="{&quot;action&quot;:&quot;sign_in&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_in_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/crafts69guy/herdr-switchboard/blob/main/CLAUDE.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="199aa0d6285e192df4c5a8022b451ee2d8d54c312501a59416de7308f6337d9b"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH">Sign in</span></span></a><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderAppearanceSettings-module__trigger__hUheK" type="button" aria-haspopup="dialog" aria-labelledby="_R_3dd_"><span class="Primer_Brand__Button-module__Button__leading-visual___jjtTe" data-testid="Button-leading-visual"><svg data-component="Octicon" focusable="false" aria-hidden="true" class="octicon octicon-sliders Primer_Brand__Button-module__Button__icon-visual____qybb" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M15 2.75a.75.75 0 0 1-.75.75h-4a.75.75 0 0 1 0-1.5h4a.75.75 0 0 1 .75.75Zm-8.5.75v1.25a.75.75 0 0 0 1.5 0v-4a.75.75 0 0 0-1.5 0V2H1.75a.75.75 0 0 0 0 1.5H6.5Zm1.25 5.25a.75.75 0 0 0 0-1.5h-6a.75.75 0 0 0 0 1.5h6ZM15 8a.75.75 0 0 1-.75.75H11.5V10a.75.75 0 1 1-1.5 0V6a.75.75 0 0 1 1.5 0v1.25h2.75A.75.75 0 0 1 15 8Zm-9 5.25v-2a.75.75 0 0 0-1.5 0v1.25H1.75a.75.75 0 0 0 0 1.5H4.5v1.25a.75.75 0 0 0 1.5 0v-2Zm9 0a.75.75 0 0 1-.75.75h-6a.75.75 0 0 1 0-1.5h6a.75.75 0 0 1 .75.75Z"></path></svg></span><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"></span></span></button><div class="Primer_Brand__Tooltip-module__Tooltip___0Eipx" data-direction="s" aria-hidden="true" id="_R_3dd_">Appearance settings</div></div></div><div class="MarketingHeader-module__menu__GIy3y"><div class="MarketingHeader-module__menuWrapper__owstH"><nav class="MarketingNavigation-module__nav__W0KYY" aria-label="Global"><ul class="MarketingNavigation-module__list__tFbMb"><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_nd_">Platform<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5knd_">AI CODE CREATION</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5knd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/copilot" data-analytics-event="{&quot;action&quot;:&quot;github_copilot&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_copilot_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copilot NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"></path><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"></path></svg>GitHub Copilot</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Write better code with AI</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/ai/github-app" data-analytics-event="{&quot;action&quot;:&quot;github_copilot_app&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_copilot_app_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mark-github NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.766 11.328c-2.063-.25-3.516-1.734-3.516-3.656 0-.781.281-1.625.75-2.188-.203-.515-.172-1.609.063-2.062.625-.078 1.468.25 1.968.703.594-.187 1.219-.281 1.985-.281.765 0 1.39.094 1.953.265.484-.437 1.344-.765 1.969-.687.218.422.25 1.515.046 2.047.5.593.766 1.39.766 2.203 0 1.922-1.453 3.375-3.547 3.64.531.344.89 1.094.89 1.954v1.625c0 .468.391.734.86.547C13.781 14.359 16 11.53 16 8.03 16 3.61 12.406 0 7.984 0 3.563 0 0 3.61 0 8.031a7.88 7.88 0 0 0 5.172 7.422c.422.156.828-.125.828-.547v-1.25c-.219.094-.5.156-.75.156-1.031 0-1.64-.562-2.078-1.609-.172-.422-.36-.672-.719-.719-.187-.015-.25-.093-.25-.187 0-.188.313-.328.625-.328.453 0 .844.281 1.25.86.313.452.64.655 1.031.655s.641-.14 1-.5c.266-.265.47-.5.657-.656"></path></svg>GitHub Copilot app</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Direct agents from issue to merge</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/mcp" data-analytics-event="{&quot;action&quot;:&quot;mcp_registry&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;mcp_registry_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-mcp NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M5.52 1.12a3.578 3.578 0 0 1 6.078 2.98 3.578 3.578 0 0 1 2.982 6.08l-3.292 3.293a.252.252 0 0 0 0 .354l.843.843a.749.749 0 1 1-1.06 1.06l-.844-.843a1.75 1.75 0 0 1 0-2.474L13.52 9.12a2.08 2.08 0 0 0 0-2.94 2.08 2.08 0 0 0-2.94 0L7.731 9.03A.75.75 0 0 1 6.67 7.97l2.85-2.85a2.08 2.08 0 0 0 0-2.94 2.08 2.08 0 0 0-2.94 0l-4.799 4.8A.75.75 0 0 1 .72 5.92Z"></path><path d="M7.52 3.12a.749.749 0 1 1 1.06 1.06L5.731 7.03A2.079 2.079 0 0 0 8.67 9.97l2.85-2.85a.749.749 0 1 1 1.06 1.06l-2.849 2.85A3.578 3.578 0 0 1 4.67 5.97Z"></path></svg>MCP Registry</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Integrate external tools</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9knd_">DEVELOPER WORKFLOWS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9knd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/actions" data-analytics-event="{&quot;action&quot;:&quot;actions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;actions_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-workflow NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75C0 .784.784 0 1.75 0h3.5C6.216 0 7 .784 7 1.75v3.5A1.75 1.75 0 0 1 5.25 7H4v4a1 1 0 0 0 1 1h4v-1.25C9 9.784 9.784 9 10.75 9h3.5c.966 0 1.75.784 1.75 1.75v3.5A1.75 1.75 0 0 1 14.25 16h-3.5A1.75 1.75 0 0 1 9 14.25v-.75H5A2.5 2.5 0 0 1 2.5 11V7h-.75A1.75 1.75 0 0 1 0 5.25Zm1.75-.25a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Zm9 9a.25.25 0 0 0-.25.25v3.5c0 .138.112.25.25.25h3.5a.25.25 0 0 0 .25-.25v-3.5a.25.25 0 0 0-.25-.25Z"></path></svg>Actions</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Automate any workflow</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/codespaces" data-analytics-event="{&quot;action&quot;:&quot;codespaces&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;codespaces_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-codespaces NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 11.25c0-.966.784-1.75 1.75-1.75h12.5c.966 0 1.75.784 1.75 1.75v3A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm2-9.5C2 .784 2.784 0 3.75 0h8.5C13.216 0 14 .784 14 1.75v5a1.75 1.75 0 0 1-1.75 1.75h-8.5A1.75 1.75 0 0 1 2 6.75Zm1.75-.25a.25.25 0 0 0-.25.25v5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-5a.25.25 0 0 0-.25-.25Zm-2 9.5a.25.25 0 0 0-.25.25v3c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25v-3a.25.25 0 0 0-.25-.25Z"></path><path d="M7 12.75a.75.75 0 0 1 .75-.75h4.5a.75.75 0 0 1 0 1.5h-4.5a.75.75 0 0 1-.75-.75Zm-4 0a.75.75 0 0 1 .75-.75h.5a.75.75 0 0 1 0 1.5h-.5a.75.75 0 0 1-.75-.75Z"></path></svg>Codespaces</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Instant dev environments</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/issues" data-analytics-event="{&quot;action&quot;:&quot;issues&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;issues_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-issue-opened NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path></svg>Issues</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Plan and track work</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/code-review" data-analytics-event="{&quot;action&quot;:&quot;code_review&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_review_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path></svg>Code Review</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Manage code changes</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/code-quality" data-analytics-event="{&quot;action&quot;:&quot;code_quality&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_quality_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-codescan-checkmark NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.28 6.28a.75.75 0 1 0-1.06-1.06L6.25 8.19l-.97-.97a.75.75 0 0 0-1.06 1.06l1.5 1.5a.75.75 0 0 0 1.06 0l3.5-3.5Z"></path><path d="M7.5 15a7.5 7.5 0 1 1 5.807-2.754l2.473 2.474a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-2.474-2.473A7.472 7.472 0 0 1 7.5 15Zm0-13.5a6 6 0 1 0 4.094 10.386.748.748 0 0 1 .293-.292 6.002 6.002 0 0 0 1.117-6.486A6.002 6.002 0 0 0 7.5 1.5Z"></path></svg>Code Quality</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enforce quality at merge</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dknd_">APPLICATION SECURITY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dknd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security" data-analytics-event="{&quot;action&quot;:&quot;github_advanced_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_advanced_security_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield-check NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m8.533.133 5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68a1.748 1.748 0 0 1 1.066 0Zm-.61 1.429.001.001-5.25 1.68a.251.251 0 0 0-.174.237V7c0 1.36.275 2.666 1.057 3.859.784 1.194 2.121 2.342 4.366 3.298a.196.196 0 0 0 .154 0c2.245-.957 3.582-2.103 4.366-3.297C13.225 9.666 13.5 8.358 13.5 7V3.48a.25.25 0 0 0-.174-.238l-5.25-1.68a.25.25 0 0 0-.153 0ZM11.28 6.28l-3.5 3.5a.75.75 0 0 1-1.06 0l-1.5-1.5a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l.97.97 2.97-2.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>GitHub Advanced Security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Find and fix vulnerabilities</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security/code-security" data-analytics-event="{&quot;action&quot;:&quot;code_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;code_security_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code-square NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25Zm1.75-.25a.25.25 0 0 0-.25.25v12.5c0 .138.112.25.25.25h12.5a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25Zm7.47 3.97a.75.75 0 0 1 1.06 0l2 2a.75.75 0 0 1 0 1.06l-2 2a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L10.69 8 9.22 6.53a.75.75 0 0 1 0-1.06ZM6.78 6.53 5.31 8l1.47 1.47a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215l-2-2a.75.75 0 0 1 0-1.06l2-2a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>Code security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Secure your code as you build</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security/secret-protection" data-analytics-event="{&quot;action&quot;:&quot;secret_protection&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;secret_protection_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-lock NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M4 4a4 4 0 0 1 8 0v2h.25c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 12.25 15h-8.5A1.75 1.75 0 0 1 2 13.25v-5.5C2 6.784 2.784 6 3.75 6H4Zm8.25 3.5h-8.5a.25.25 0 0 0-.25.25v5.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25ZM10.5 6V4a2.5 2.5 0 1 0-5 0v2Z"></path></svg>Secret protection</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Stop leaks before they start</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ NavGroup-module__hasSeparator__FnMrN"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_hknd_">EXPLORE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_hknd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/why-github" data-analytics-event="{&quot;action&quot;:&quot;why_github&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;why_github_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Why GitHub</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://docs.github.com" data-analytics-event="{&quot;action&quot;:&quot;documentation&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;documentation_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Documentation</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://github.blog" data-analytics-event="{&quot;action&quot;:&quot;blog&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;blog_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Blog</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://github.blog/changelog" data-analytics-event="{&quot;action&quot;:&quot;changelog&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;changelog_link_platform_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Changelog</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/marketplace" data-analytics-event="{&quot;action&quot;:&quot;marketplace&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;marketplace_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Marketplace</span></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/features" data-analytics-event="{&quot;action&quot;:&quot;view_all_features&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;platform&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_features_link_platform_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all features</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_17d_">Solutions<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_17d_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5l7d_">BY COMPANY SIZE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5l7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/enterprise" data-analytics-event="{&quot;action&quot;:&quot;enterprises&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;enterprises_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Enterprises</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/team" data-analytics-event="{&quot;action&quot;:&quot;small_and_medium_teams&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;small_and_medium_teams_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Small and medium teams</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/enterprise/startups" data-analytics-event="{&quot;action&quot;:&quot;startups&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;startups_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Startups</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/nonprofits" data-analytics-event="{&quot;action&quot;:&quot;nonprofits&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;nonprofits_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Nonprofits</span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9l7d_">BY USE CASE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9l7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/app-modernization" data-analytics-event="{&quot;action&quot;:&quot;app_modernization&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;app_modernization_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">App Modernization</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/devsecops" data-analytics-event="{&quot;action&quot;:&quot;devsecops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devsecops_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevSecOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/devops" data-analytics-event="{&quot;action&quot;:&quot;devops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devops_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/use-case/ci-cd" data-analytics-event="{&quot;action&quot;:&quot;ci/cd&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ci/cd_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">CI/CD</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions/use-case" data-analytics-event="{&quot;action&quot;:&quot;view_all_use_cases&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_use_cases_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all use cases</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dl7d_">BY INDUSTRY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dl7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/healthcare" data-analytics-event="{&quot;action&quot;:&quot;healthcare&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;healthcare_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Healthcare</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/financial-services" data-analytics-event="{&quot;action&quot;:&quot;financial_services&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;financial_services_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Financial services</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/manufacturing" data-analytics-event="{&quot;action&quot;:&quot;manufacturing&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;manufacturing_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Manufacturing</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/industry/government" data-analytics-event="{&quot;action&quot;:&quot;government&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;government_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Government</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions/industry" data-analytics-event="{&quot;action&quot;:&quot;view_all_industries&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_industries_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all industries</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/solutions" data-analytics-event="{&quot;action&quot;:&quot;view_all_solutions&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;solutions&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_solutions_link_solutions_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all solutions</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_1nd_">Resources<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_1nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5lnd_">EXPLORE BY TOPIC</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5lnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=ai" data-analytics-event="{&quot;action&quot;:&quot;ai&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ai_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">AI</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=software-development" data-analytics-event="{&quot;action&quot;:&quot;software_development&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;software_development_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Software Development</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=devops" data-analytics-event="{&quot;action&quot;:&quot;devops&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;devops_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">DevOps</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/articles?topic=security" data-analytics-event="{&quot;action&quot;:&quot;security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;security_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Security</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/resources/articles" data-analytics-event="{&quot;action&quot;:&quot;view_all_topics&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_topics_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all topics</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9lnd_">EXPLORE BY TYPE</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9lnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/customer-stories" data-analytics-event="{&quot;action&quot;:&quot;customer_stories&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;customer_stories_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Customer stories</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/events" data-analytics-event="{&quot;action&quot;:&quot;events__webinars&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;events__webinars_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Events &amp; webinars</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/resources/whitepapers" data-analytics-event="{&quot;action&quot;:&quot;ebooks__reports&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;ebooks__reports_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Ebooks &amp; reports</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/solutions/executive-insights" data-analytics-event="{&quot;action&quot;:&quot;business_insights&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;business_insights_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Business insights</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://skills.github.com" data-analytics-event="{&quot;action&quot;:&quot;github_skills&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_skills_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">GitHub Skills</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dlnd_">SUPPORT &amp; SERVICES</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dlnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://docs.github.com" data-analytics-event="{&quot;action&quot;:&quot;documentation&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;documentation_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Documentation</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://support.github.com" data-analytics-event="{&quot;action&quot;:&quot;customer_support&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;customer_support_link_resources_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Customer support</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/orgs/community/discussions" data-analytics-event="{&quot;action&quot;:&quot;community_forum&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;community_forum_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Community forum</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/trust-center" data-analytics-event="{&quot;action&quot;:&quot;trust_center&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;trust_center_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Trust center</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/partners" data-analytics-event="{&quot;action&quot;:&quot;partners&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;partners_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Partners</span></a></li></ul></div></li></ul><div class="NavDropdown-module__trailingLinkContainer__VgJGL"><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--arrow-end___esdN8" href="https://github.com/resources" data-analytics-event="{&quot;action&quot;:&quot;view_all_resources&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;resources&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;view_all_resources_link_resources_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">View all resources</span><svg class="Primer_Brand__ExpandableArrow-module__ExpandableArrow___aaZs9 Primer_Brand__Link-module__Link-arrow___yd78i" width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true" focusable="false"><path fill="currentColor" d="M7.28033 3.21967C6.98744 2.92678 6.51256 2.92678 6.21967 3.21967C5.92678 3.51256 5.92678 3.98744 6.21967 4.28033L7.28033 3.21967ZM11 8L11.5303 8.53033C11.8232 8.23744 11.8232 7.76256 11.5303 7.46967L11 8ZM6.21967 11.7197C5.92678 12.0126 5.92678 12.4874 6.21967 12.7803C6.51256 13.0732 6.98744 13.0732 7.28033 12.7803L6.21967 11.7197ZM6.21967 4.28033L10.4697 8.53033L11.5303 7.46967L7.28033 3.21967L6.21967 4.28033ZM10.4697 7.46967L6.21967 11.7197L7.28033 12.7803L11.5303 8.53033L10.4697 7.46967Z"></path><path class="Primer_Brand__ExpandableArrow-module__ExpandableArrow-stem___0K8Hz" stroke="currentColor" d="M1.75 8H11" stroke-width="1.5" stroke-linecap="round"></path></svg></a></div></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_27d_">Open Source<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_27d_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5m7d_">COMMUNITY</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5m7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/open-source/sponsors" data-analytics-event="{&quot;action&quot;:&quot;github_sponsors&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_sponsors_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-sponsor-tiers NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.586 1C12.268 1 13.5 2.37 13.5 4.25c0 1.745-.996 3.359-2.622 4.831-.166.15-.336.297-.509.438l1.116 5.584a.75.75 0 0 1-.991.852l-2.409-.876a.25.25 0 0 0-.17 0l-2.409.876a.75.75 0 0 1-.991-.852L5.63 9.519a13.78 13.78 0 0 1-.51-.438C3.497 7.609 2.5 5.995 2.5 4.25 2.5 2.37 3.732 1 5.414 1c.963 0 1.843.403 2.474 1.073L8 2.198l.112-.125a3.385 3.385 0 0 1 2.283-1.068L10.586 1Zm-3.621 9.495-.718 3.594 1.155-.42a1.75 1.75 0 0 1 1.028-.051l.168.051 1.154.42-.718-3.592c-.199.13-.37.235-.505.314l-.169.097a.75.75 0 0 1-.72 0 9.54 9.54 0 0 1-.515-.308l-.16-.105ZM10.586 2.5c-.863 0-1.611.58-1.866 1.459-.209.721-1.231.721-1.44 0C7.025 3.08 6.277 2.5 5.414 2.5 4.598 2.5 4 3.165 4 4.25c0 1.23.786 2.504 2.128 3.719.49.443 1.018.846 1.546 1.198l.325.21.076-.047.251-.163a13.341 13.341 0 0 0 1.546-1.198C11.214 6.754 12 5.479 12 4.25c0-1.085-.598-1.75-1.414-1.75Z"></path></svg>GitHub Sponsors</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Fund open source developers</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9m7d_">PROGRAMS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9m7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://securitylab.github.com" data-analytics-event="{&quot;action&quot;:&quot;security_lab&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;security_lab_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Security Lab</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://maintainers.github.com" data-analytics-event="{&quot;action&quot;:&quot;maintainer_community&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;maintainer_community_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Maintainer Community</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://stars.github.com" data-analytics-event="{&quot;action&quot;:&quot;github_stars&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_stars_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">GitHub Stars</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 Primer_Brand__Link-module__Link--is-external___xsncV" href="https://archiveprogram.github.com" data-analytics-event="{&quot;action&quot;:&quot;archive_program&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;archive_program_link_open_source_navbar&quot;}" target="_blank" rel="noreferrer"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Archive Program</span><svg data-component="Octicon" focusable="false" aria-label="External link" class="octicon octicon-link-external" role="img" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.75 2h3.5a.75.75 0 0 1 0 1.5h-3.5a.25.25 0 0 0-.25.25v8.5c0 .138.112.25.25.25h8.5a.25.25 0 0 0 .25-.25v-3.5a.75.75 0 0 1 1.5 0v3.5A1.75 1.75 0 0 1 12.25 14h-8.5A1.75 1.75 0 0 1 2 12.25v-8.5C2 2.784 2.784 2 3.75 2Zm6.854-1h4.146a.25.25 0 0 1 .25.25v4.146a.25.25 0 0 1-.427.177L13.03 4.03 9.28 7.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.75-3.75-1.543-1.543A.25.25 0 0 1 10.604 1Z"></path></svg></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_dm7d_">REPOSITORIES</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_dm7d_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/topics" data-analytics-event="{&quot;action&quot;:&quot;topics&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;topics_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Topics</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/trending" data-analytics-event="{&quot;action&quot;:&quot;trending&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;trending_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Trending</span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0" href="https://github.com/collections" data-analytics-event="{&quot;action&quot;:&quot;collections&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;open_source&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;collections_link_open_source_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty">Collections</span></a></li></ul></div></li></ul></div></div></li><li><div class="NavDropdown-module__container__l2YeI"><button type="button" class="NavDropdown-module__button__PEHWX" aria-expanded="false" aria-controls="_R_2nd_">Enterprise<svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-right NavDropdown-module__buttonIcon__Tkl8_" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m6.427 4.427 3.396 3.396a.25.25 0 0 1 0 .354l-3.396 3.396A.25.25 0 0 1 6 11.396V4.604a.25.25 0 0 1 .427-.177Z"></path></svg></button><div id="_R_2nd_" class="NavDropdown-module__dropdown__xm1jd"><ul class="NavDropdown-module__list__zuCgG"><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_5mnd_">ENTERPRISE SOLUTIONS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_5mnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/enterprise" data-analytics-event="{&quot;action&quot;:&quot;enterprise_platform&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;enterprise_platform_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-stack NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.122.392a1.75 1.75 0 0 1 1.756 0l5.003 2.902c.83.481.83 1.68 0 2.162L8.878 8.358a1.75 1.75 0 0 1-1.756 0L2.119 5.456a1.251 1.251 0 0 1 0-2.162ZM8.125 1.69a.248.248 0 0 0-.25 0l-4.63 2.685 4.63 2.685a.248.248 0 0 0 .25 0l4.63-2.685ZM1.601 7.789a.75.75 0 0 1 1.025-.273l5.249 3.044a.248.248 0 0 0 .25 0l5.249-3.044a.75.75 0 0 1 .752 1.298l-5.248 3.044a1.75 1.75 0 0 1-1.756 0L1.874 8.814A.75.75 0 0 1 1.6 7.789Zm0 3.5a.75.75 0 0 1 1.025-.273l5.249 3.044a.248.248 0 0 0 .25 0l5.249-3.044a.75.75 0 0 1 .752 1.298l-5.248 3.044a1.75 1.75 0 0 1-1.756 0l-5.248-3.044a.75.75 0 0 1-.273-1.025Z"></path></svg>Enterprise platform</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">AI-powered developer platform</span></span></a></li></ul></div></li><li><div class="NavGroup-module__group__W8SqJ"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--monospace___QXHDQ Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavGroup-module__title__Wzxz2" id="_R_9mnd_">AVAILABLE ADD-ONS</span><ul class="NavGroup-module__list__UCOFy" aria-labelledby="_R_9mnd_"><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/security/advanced-security" data-analytics-event="{&quot;action&quot;:&quot;github_advanced_security&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;github_advanced_security_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield-check NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m8.533.133 5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667l5.25-1.68a1.748 1.748 0 0 1 1.066 0Zm-.61 1.429.001.001-5.25 1.68a.251.251 0 0 0-.174.237V7c0 1.36.275 2.666 1.057 3.859.784 1.194 2.121 2.342 4.366 3.298a.196.196 0 0 0 .154 0c2.245-.957 3.582-2.103 4.366-3.297C13.225 9.666 13.5 8.358 13.5 7V3.48a.25.25 0 0 0-.174-.238l-5.25-1.68a.25.25 0 0 0-.153 0ZM11.28 6.28l-3.5 3.5a.75.75 0 0 1-1.06 0l-1.5-1.5a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l.97.97 2.97-2.97a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg>GitHub Advanced Security</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade security features</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/features/copilot/copilot-business" data-analytics-event="{&quot;action&quot;:&quot;copilot_for_business&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;copilot_for_business_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copilot NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.998 15.035c-4.562 0-7.873-2.914-7.998-3.749V9.338c.085-.628.677-1.686 1.588-2.065.013-.07.024-.143.036-.218.029-.183.06-.384.126-.612-.201-.508-.254-1.084-.254-1.656 0-.87.128-1.769.693-2.484.579-.733 1.494-1.124 2.724-1.261 1.206-.134 2.262.034 2.944.765.05.053.096.108.139.165.044-.057.094-.112.143-.165.682-.731 1.738-.899 2.944-.765 1.23.137 2.145.528 2.724 1.261.566.715.693 1.614.693 2.484 0 .572-.053 1.148-.254 1.656.066.228.098.429.126.612.012.076.024.148.037.218.924.385 1.522 1.471 1.591 2.095v1.872c0 .766-3.351 3.795-8.002 3.795Zm0-1.485c2.28 0 4.584-1.11 5.002-1.433V7.862l-.023-.116c-.49.21-1.075.291-1.727.291-1.146 0-2.059-.327-2.71-.991A3.222 3.222 0 0 1 8 6.303a3.24 3.24 0 0 1-.544.743c-.65.664-1.563.991-2.71.991-.652 0-1.236-.081-1.727-.291l-.023.116v4.255c.419.323 2.722 1.433 5.002 1.433ZM6.762 2.83c-.193-.206-.637-.413-1.682-.297-1.019.113-1.479.404-1.713.7-.247.312-.369.789-.369 1.554 0 .793.129 1.171.308 1.371.162.181.519.379 1.442.379.853 0 1.339-.235 1.638-.54.315-.322.527-.827.617-1.553.117-.935-.037-1.395-.241-1.614Zm4.155-.297c-1.044-.116-1.488.091-1.681.297-.204.219-.359.679-.242 1.614.091.726.303 1.231.618 1.553.299.305.784.54 1.638.54.922 0 1.28-.198 1.442-.379.179-.2.308-.578.308-1.371 0-.765-.123-1.242-.37-1.554-.233-.296-.693-.587-1.713-.7Z"></path><path d="M6.25 9.037a.75.75 0 0 1 .75.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 .75-.75Zm4.25.75v1.501a.75.75 0 0 1-1.5 0V9.787a.75.75 0 0 1 1.5 0Z"></path></svg>Copilot for Business</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade AI features</span></span></a></li><li><a class="Primer_Brand__Link-module__Link___lF11y Primer_Brand__Link-module__Link--default___VRVW0 NavLink-module__link__EG3d4" href="https://github.com/enterprise/premium-support" data-analytics-event="{&quot;action&quot;:&quot;premium_support&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;enterprise&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;premium_support_link_enterprise_navbar&quot;}"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Link-module__Link--label___jM8Ty"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS Primer_Brand__Text-module__Text--weight-medium___qJKf_ NavLink-module__title__Q7t0p"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-comment-discussion NavLink-module__icon__ltGNM" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.75 1h8.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 10.25 10H7.061l-2.574 2.573A1.458 1.458 0 0 1 2 11.543V10h-.25A1.75 1.75 0 0 1 0 8.25v-5.5C0 1.784.784 1 1.75 1ZM1.5 2.75v5.5c0 .138.112.25.25.25h1a.75.75 0 0 1 .75.75v2.19l2.72-2.72a.749.749 0 0 1 .53-.22h3.5a.25.25 0 0 0 .25-.25v-5.5a.25.25 0 0 0-.25-.25h-8.5a.25.25 0 0 0-.25.25Zm13 2a.25.25 0 0 0-.25-.25h-.5a.75.75 0 0 1 0-1.5h.5c.966 0 1.75.784 1.75 1.75v5.5A1.75 1.75 0 0 1 14.25 12H14v1.543a1.458 1.458 0 0 1-2.487 1.03L9.22 12.28a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215l2.22 2.22v-2.19a.75.75 0 0 1 .75-.75h1a.25.25 0 0 0 .25-.25Z"></path></svg>Premium Support</span><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--muted___rE6mh Primer_Brand__Text-module__Text--200____P1wy Primer_Brand__Text-module__Text--antialiased___TYoXS NavLink-module__subtitle__X4gkW">Enterprise-grade 24/7 support</span></span></a></li></ul></div></li></ul></div></div></li><li><a href="https://github.com/pricing" data-analytics-event="{&quot;action&quot;:&quot;pricing&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;pricing&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;pricing_link_pricing_navbar&quot;}" class="MarketingNavigation-module__navLink__hUomM">Pricing</a></li></ul></nav><div class="MarketingHeader-module__ctaContainer__tBmPz"><div class="HeaderSearch-module__searchSlot__oVOUS"><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderSearch-module__trigger__zsF9q" type="button" aria-haspopup="dialog" aria-expanded="false" aria-label="Search or jump to, type / to search" data-analytics-event="{&quot;action&quot;:&quot;searchbar&quot;,&quot;tag&quot;:&quot;input&quot;,&quot;context&quot;:&quot;global&quot;,&quot;location&quot;:&quot;navbar&quot;,&quot;label&quot;:&quot;searchbar_input_global_navbar&quot;}"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"><span class="HeaderSearch-module__content__kMpxU"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-search HeaderSearch-module__icon__wcrHX" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path></svg><span class="HeaderSearch-module__label__d1iWG">Search</span><kbd class="HeaderSearch-module__kbd__HNG0o" aria-hidden="true">/</kbd></span></span></span></button><div class="d-none"></div></div><div class="AuthCTAs-module__signInWrap__q2P60"><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq AuthCTAs-module__desktopActionGap__UZuXT AuthCTAs-module__hiddenBelowLg__BfKBw" href="/login?return_to=https%3A%2F%2Fgithub.com%2Fcrafts69guy%2Fherdr-switchboard%2Fblob%2Fmain%2FCLAUDE.md" data-analytics-event="{&quot;action&quot;:&quot;sign_in&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_in_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/crafts69guy/herdr-switchboard/blob/main/CLAUDE.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="199aa0d6285e192df4c5a8022b451ee2d8d54c312501a59416de7308f6337d9b"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH">Sign in</span></span></a></div><a class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--secondary___gHnw_ Primer_Brand__Button-module__Button--size-small___zQrEw AuthCTAs-module__cta__WpwQq" href="/signup?ref_cta=Sign+up&amp;ref_loc=header+logged+out&amp;ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fblob%2Fshow&amp;source=header-repo&amp;source_repo=crafts69guy%2Fherdr-switchboard" data-analytics-event="{&quot;action&quot;:&quot;sign_up&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;context&quot;:&quot;auth_cta&quot;,&quot;location&quot;:&quot;header&quot;,&quot;label&quot;:&quot;sign_up_link_auth_cta_header&quot;}" data-hydro-click="{&quot;event_type&quot;:&quot;authentication.click&quot;,&quot;payload&quot;:{&quot;location_in_page&quot;:&quot;site header menu&quot;,&quot;repository_id&quot;:null,&quot;auth_type&quot;:&quot;SIGN_UP&quot;,&quot;originating_url&quot;:&quot;https://github.com/crafts69guy/herdr-switchboard/blob/main/CLAUDE.md&quot;,&quot;user_id&quot;:null}}" data-hydro-click-hmac="199aa0d6285e192df4c5a8022b451ee2d8d54c312501a59416de7308f6337d9b"><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-secondary___eJ0_a">Sign up</span></span></a><button class="Primer_Brand__Button-module__Button___scH9Z Primer_Brand__Button-module__Button--subtle___F7pEE Primer_Brand__Button-module__Button--size-small___zQrEw HeaderAppearanceSettings-module__trigger__hUheK" type="button" aria-haspopup="dialog" aria-labelledby="_R_fbd_"><span class="Primer_Brand__Button-module__Button__leading-visual___jjtTe" data-testid="Button-leading-visual"><svg data-component="Octicon" focusable="false" aria-hidden="true" class="octicon octicon-sliders Primer_Brand__Button-module__Button__icon-visual____qybb" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M15 2.75a.75.75 0 0 1-.75.75h-4a.75.75 0 0 1 0-1.5h4a.75.75 0 0 1 .75.75Zm-8.5.75v1.25a.75.75 0 0 0 1.5 0v-4a.75.75 0 0 0-1.5 0V2H1.75a.75.75 0 0 0 0 1.5H6.5Zm1.25 5.25a.75.75 0 0 0 0-1.5h-6a.75.75 0 0 0 0 1.5h6ZM15 8a.75.75 0 0 1-.75.75H11.5V10a.75.75 0 1 1-1.5 0V6a.75.75 0 0 1 1.5 0v1.25h2.75A.75.75 0 0 1 15 8Zm-9 5.25v-2a.75.75 0 0 0-1.5 0v1.25H1.75a.75.75 0 0 0 0 1.5H4.5v1.25a.75.75 0 0 0 1.5 0v-2Zm9 0a.75.75 0 0 1-.75.75h-6a.75.75 0 0 1 0-1.5h6a.75.75 0 0 1 .75.75Z"></path></svg></span><span class="Primer_Brand__Button-module__Button__text___ED0bX"><span class="Primer_Brand__Text-module__Text___XeGJJ Primer_Brand__Text-module__Text-font--mona-sans___a8XJD Primer_Brand__Text-module__Text--default___GhPh_ Primer_Brand__Text-module__Text--100___B2ueX Primer_Brand__Text-module__Text--weight-medium___qJKf_ Primer_Brand__Button-module__Button--label___qrkyz Primer_Brand__Button-module__Button--label-subtle___8ndWH"></span></span></button><div class="Primer_Brand__Tooltip-module__Tooltip___0Eipx" data-direction="s" aria-hidden="true" id="_R_fbd_">Appearance settings</div></div></div></div></div><div class="MarketingHeader-module__bottomBorder__uZT38" aria-hidden="true"></div></header></div></div>
</react-partial>



      <div hidden="hidden" data-view-component="true" class="js-stale-session-flash stale-session-flash flash flash-warn flash-full">
  
        <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
        <span class="js-stale-session-flash-signed-in" hidden>You signed in with another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>
        <span class="js-stale-session-flash-signed-out" hidden>You signed out in another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>
        <span class="js-stale-session-flash-switched" hidden>You switched accounts on another tab or window. <a class="Link--inTextBlock" href="">Reload</a> to refresh your session.</span>

    <button id="icon-button-4176f5ae-b968-4896-b968-5401ba7dee16" aria-labelledby="tooltip-dbd6c196-4ef3-4f18-b2ed-7ef347478986" type="button" data-view-component="true" class="Button Button--iconOnly Button--invisible Button--medium flash-close js-flash-close">  <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x Button-visual">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
</button><tool-tip id="tooltip-dbd6c196-4ef3-4f18-b2ed-7ef347478986" for="icon-button-4176f5ae-b968-4896-b968-5401ba7dee16" popover="manual" data-direction="s" data-type="label" data-view-component="true" class="sr-only position-absolute">Dismiss alert</tool-tip>


  
</div>
    </div>

  <div id="start-of-content" class="show-on-focus"></div>








    <div id="js-flash-container" class="flash-container" data-turbo-replace>






  <template class="js-flash-template">
    
<div class="flash flash-full   {{ className }}">
  <div >
    <button autofocus class="flash-close js-flash-close" type="button" aria-label="Dismiss this message">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
    </button>
    <div aria-atomic="true" role="alert" class="js-flash-alert">
      
      <div>{{ message }}</div>

    </div>
  </div>
</div>
  </template>
</div>


    






  <div
    class="application-main "
    data-commit-hovercards-enabled
    data-discussion-hovercards-enabled
    data-issue-and-pr-hovercards-enabled
    data-project-hovercards-enabled
  >
        <div itemscope itemtype="http://schema.org/SoftwareSourceCode" class="">
    <main id="js-repo-pjax-container" >
      
      








  

    <link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ym-6bc2c9bf8112c038.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/sk2-8deeef9351be3911.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/ni-3e194d222c7770bf.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/7x-71d30cb240cd901f.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wwk-ad869086822937b1.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/a1-9f79841ecac1da8e.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/wzg-40a3213b3e83400b.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/5f-64f8e7d5bcbd4787.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/z5-b53a93078d026f1e.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/8h-cef26f68c1331011.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/fq-3ce13a77e863807a.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/a7-596b507bd20acddc.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/xfx-c82d8352413aea0a.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/j4-b3a9e87fa7878a98.js" fetchpriority="low" />
<link crossorigin="anonymous" rel="modulepreload" href="https://github.githubassets.com/assets/global-nav-bar-29c7aef68ee9db41.js" fetchpriority="low" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/primer-react-css.2d881b4d4a503d1c.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/pj.75627bfeb9ceb1da.module.css" />
<link crossorigin="anonymous" media="all" rel="stylesheet" href="https://github.githubassets.com/assets/global-nav-bar.2f2560cba06ab359.module.css" />

<react-partial
  partial-name="global-nav-bar"
  data-ssr="true"
  data-attempted-ssr="true"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-partial.embeddedData">{"props":{"contextRegion":{"crumbs":[{"crumb_type":"user","label":"crafts69guy","is_root":false,"href":"/crafts69guy"},{"crumb_type":"repository","label":"herdr-switchboard","is_root":false,"href":"/crafts69guy/herdr-switchboard"}],"localNavigation":[{"id":"code","icon":"code","label":"Code","href":"/crafts69guy/herdr-switchboard","selectedLinks":["repo_source","repo_downloads","repo_commits","repo_releases","repo_tags","repo_branches","repo_packages","repo_deployments","repo_attestations"],"popoverTarget":false,"commandId":"repositories:go-to-code","reactNav":{"appTarget":"code-view","anchor":"code-view-repo-link"},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"issues","icon":"issue-opened","label":"Issues","href":"/crafts69guy/herdr-switchboard/issues","selectedLinks":["repo_issues","repo_labels","repo_milestones"],"count":0,"popoverTarget":false,"commandId":"repositories:go-to-issues","reactNav":{"appTarget":"repo","anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"pull-requests","icon":"git-pull-request","label":"Pull requests","href":"/crafts69guy/herdr-switchboard/pulls","selectedLinks":["repo_pulls","checks"],"count":0,"popoverTarget":false,"commandId":"repositories:go-to-pull-requests","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"actions","icon":"play","label":"Actions","href":"/crafts69guy/herdr-switchboard/actions","selectedLinks":["repo_actions"],"popoverTarget":false,"commandId":"repositories:go-to-actions","reactNav":{"appTarget":"actions-workflows","anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"projects","icon":"table","label":"Projects","href":"/crafts69guy/herdr-switchboard/projects","selectedLinks":["repo_projects","new_repo_project","repo_project"],"popoverTarget":false,"commandId":"repositories:go-to-projects","reactNav":{"appTarget":"repo","anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"security-and-quality","icon":"shield","label":"Security and quality","href":"/crafts69guy/herdr-switchboard/security","selectedLinks":["security","overview","alerts","policy","token_scanning","code_scanning"],"count":0,"popoverTarget":false,"commandId":"repositories:go-to-security","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}},{"id":"insights","icon":"graph","label":"Insights","href":"/crafts69guy/herdr-switchboard/pulse","selectedLinks":["repo_graphs","repo_contributors","dependency_graph","dependabot_updates","pulse","people","community"],"popoverTarget":false,"commandId":"repositories:go-to-insights","reactNav":{"appTarget":null,"anchor":null},"turboNav":{"frame":"repo-content-turbo-frame"}}],"localNavigationUpdateChannel":null,"selectedLink":"repo_source"},"owner":null,"headerLogo":{"href":"/","aria-label":"Homepage "},"notifications":{"indicatorMode":"disabled","websocketChannel":null,"fetchIndicatorSrc":"/notifications/indicator","fetchIndicatorEnabled":false},"issues":{"href":"/issues"},"pulls":{"href":"/pulls"},"contributedRepos":{"href":"/repos"},"copilot":{"show":false,"showAgentsButton":false,"showRelaunchAnnouncement":false,"copilotChatUrl":null,"copilotApiUrl":"https://api.githubcopilot.com"},"search":{"show":true,"showCommandPalette":false,"isSearchPage":false,"isJumpToSearch":false,"searchContext":{"scope":"repo:crafts69guy/herdr-switchboard","current_repo_name":"herdr-switchboard","current_repo_nwo":"crafts69guy/herdr-switchboard","user_id":"crafts69guy"}},"commandPalette":null,"enterpriseBar":{"show":false},"globalTransactionalMessage":[],"payloadsUrl":"/_global-navigation/payloads.json?can_toggle_site_admin_and_employee_status=0\u0026is_admin_mode_on=0\u0026is_ui_opted_out=0\u0026show_ui_opt_out=0\u0026v=7","contextRegionUrl":"/_global-navigation/context-region.json"}}</script>
  <div data-target="react-partial.reactRoot"><header aria-label="Global navigation menu" data-component="Stack" class="GlobalNav styles-module__appHeader__YzYWk prc-Stack-Stack-UQ9k6" data-gap="none" data-direction="vertical" data-align="stretch" data-wrap="nowrap" data-justify="start" data-padding="none"><div data-component="Stack" class="prc-Stack-Stack-UQ9k6" data-direction="horizontal" data-align="center" data-wrap="nowrap" data-justify="center" data-padding="none"><div data-testid="top-nav-center" data-component="Stack" class="styles-module__center__R3QRv styles-module__withLocalNavigation__rjTJ_ GlobalNavBar-module__loggedOut__Jv1rk prc-Stack-Stack-UQ9k6" data-gap="condensed" data-direction="horizontal" data-align="stretch" data-wrap="nowrap" data-justify="start" data-padding="normal"><nav class="styles-module__contextRegion__VbSp2 prc-Breadcrumbs-BreadcrumbsBase-3Gb-B" aria-label="Breadcrumbs" data-overflow="menu" data-variant="normal" data-component="Breadcrumbs"><ol class="prc-Breadcrumbs-BreadcrumbsList-BKjpe"><li class="prc-Breadcrumbs-ItemWrapper-k0NLn"><a class="styles-module__contextCrumb__IzGIq prc-Breadcrumbs-Item-jcraJ" data-component="Breadcrumbs.Item" href="/crafts69guy" data-discover="true"><span class="">crafts69guy</span></a></li><li class="prc-Breadcrumbs-ItemWrapper-k0NLn"><a class="styles-module__contextCrumb__IzGIq prc-Breadcrumbs-Item-jcraJ" data-component="Breadcrumbs.Item" href="/crafts69guy/herdr-switchboard" data-discover="true"><span class="styles-module__contextCrumbLast__tI2e3">herdr-switchboard</span></a></li></ol></nav></div><div data-testid="top-nav-right" data-component="Stack" class="styles-module__right__mlBQg styles-module__withLocalNavigation__rjTJ_ styles-module__rightWithResponsiveCreateButton__SKn2W prc-Stack-Stack-UQ9k6" data-gap="condensed" data-direction="horizontal" data-align="center" data-wrap="nowrap" data-justify="start" data-padding="normal"></div></div><h2 class="prc-src-InternalVisuallyHidden-2YaI6">Repository navigation</h2><nav class="prc-components-UnderlineWrapper-eT-Yj prc-UnderlineNav-UnderlineWrapper-GWONT LocalNavigation-module__LocalNavigation__b0Xc0" aria-label="Repository" data-variant="inset" data-overflow-mode="wrap" data-hide-icons-breakpoint="medium"><ul class="prc-UnderlineNav-ItemsList-oj8gN prc-components-UnderlineItemList-xKlKC" role="list"><li role="presentation" aria-hidden="true" class="prc-UnderlineNav-WrapSpacer--aLgz"></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a aria-current="page" data-tab-item="code" data-react-nav="code-view" data-react-nav-anchor="code-view-repo-link" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/crafts69guy/herdr-switchboard" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-code" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m11.28 3.22 4.25 4.25a.75.75 0 0 1 0 1.06l-4.25 4.25a.749.749 0 0 1-1.275-.326.749.749 0 0 1 .215-.734L13.94 8l-3.72-3.72a.749.749 0 0 1 .326-1.275.749.749 0 0 1 .734.215Zm-6.56 0a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L2.06 8l3.72 3.72a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L.47 8.53a.75.75 0 0 1 0-1.06Z"></path></svg></span><span data-component="text" data-content="Code">Code</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="issues" data-react-nav="repo" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/crafts69guy/herdr-switchboard/issues" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-issue-opened" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9.5a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Z"></path></svg></span><span data-component="text" data-content="Issues">Issues</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="pull-requests" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/crafts69guy/herdr-switchboard/pulls" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-pull-request" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.5 3.25a2.25 2.25 0 1 1 3 2.122v5.256a2.251 2.251 0 1 1-1.5 0V5.372A2.25 2.25 0 0 1 1.5 3.25Zm5.677-.177L9.573.677A.25.25 0 0 1 10 .854V2.5h1A2.5 2.5 0 0 1 13.5 5v5.628a2.251 2.251 0 1 1-1.5 0V5a1 1 0 0 0-1-1h-1v1.646a.25.25 0 0 1-.427.177L7.177 3.427a.25.25 0 0 1 0-.354ZM3.75 2.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm0 9.5a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Zm8.25.75a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Z"></path></svg></span><span data-component="text" data-content="Pull requests">Pull requests</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="actions" data-react-nav="actions-workflows" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/crafts69guy/herdr-switchboard/actions" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-play" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 0a8 8 0 1 1 0 16A8 8 0 0 1 8 0ZM1.5 8a6.5 6.5 0 1 0 13 0 6.5 6.5 0 0 0-13 0Zm4.879-2.773 4.264 2.559a.25.25 0 0 1 0 .428l-4.264 2.559A.25.25 0 0 1 6 10.559V5.442a.25.25 0 0 1 .379-.215Z"></path></svg></span><span data-component="text" data-content="Actions">Actions</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="projects" data-react-nav="repo" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/crafts69guy/herdr-switchboard/projects" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-table" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 1.75C0 .784.784 0 1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25ZM6.5 6.5v8h7.75a.25.25 0 0 0 .25-.25V6.5Zm8-1.5V1.75a.25.25 0 0 0-.25-.25H6.5V5Zm-13 1.5v7.75c0 .138.112.25.25.25H5v-8ZM5 5V1.5H1.75a.25.25 0 0 0-.25.25V5Z"></path></svg></span><span data-component="text" data-content="Projects">Projects</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="security-and-quality" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/crafts69guy/herdr-switchboard/security" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-shield" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.467.133a1.748 1.748 0 0 1 1.066 0l5.25 1.68A1.75 1.75 0 0 1 15 3.48V7c0 1.566-.32 3.182-1.303 4.682-.983 1.498-2.585 2.813-5.032 3.855a1.697 1.697 0 0 1-1.33 0c-2.447-1.042-4.049-2.357-5.032-3.855C1.32 10.182 1 8.566 1 7V3.48a1.75 1.75 0 0 1 1.217-1.667Zm.61 1.429a.25.25 0 0 0-.153 0l-5.25 1.68a.25.25 0 0 0-.174.238V7c0 1.358.275 2.666 1.057 3.86.784 1.194 2.121 2.34 4.366 3.297a.196.196 0 0 0 .154 0c2.245-.956 3.582-2.104 4.366-3.298C13.225 9.666 13.5 8.36 13.5 7V3.48a.251.251 0 0 0-.174-.237l-5.25-1.68ZM8.75 4.75v3a.75.75 0 0 1-1.5 0v-3a.75.75 0 0 1 1.5 0ZM9 10.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path></svg></span><span data-component="text" data-content="Security and quality">Security and quality</span></a></li><li class="prc-UnderlineNav-UnderlineNavItem-syRjR"><a data-tab-item="insights" data-turbo-frame="repo-content-turbo-frame" class="prc-components-UnderlineItem-7fP-n" href="/crafts69guy/herdr-switchboard/pulse" data-discover="true"><span data-component="icon"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-graph" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M1.5 1.75V13.5h13.75a.75.75 0 0 1 0 1.5H.75a.75.75 0 0 1-.75-.75V1.75a.75.75 0 0 1 1.5 0Zm14.28 2.53-5.25 5.25a.75.75 0 0 1-1.06 0L7 7.06 4.28 9.78a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042l3.25-3.25a.75.75 0 0 1 1.06 0L10 7.94l4.72-4.72a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042Z"></path></svg></span><span data-component="text" data-content="Insights">Insights</span></a></li></ul><div class="prc-UnderlineNav-MoreButtonContainer-Dnrq6"><div class="prc-UnderlineNav-MoreButtonDivider-dN0a-"></div><button data-component="overflow-menu-button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk prc-UnderlineNav-MoreButton-Y8soj" data-loading="false" data-size="medium" data-variant="invisible" id="_R_2ktp_"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3"><span>More<span class="prc-src-InternalVisuallyHidden-2YaI6"> items</span></span></span></span><span data-component="trailingAction" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></button></div></nav><div class="d-none"></div></header></div>
</react-partial>


  



<turbo-frame id="repo-content-turbo-frame" target="_top" data-turbo-action="advance" class="">
    <div id="repo-content-pjax-container" class="repository-content " >
    



    
      
    








<react-app
  app-name="code-view"
  initial-path="/crafts69guy/herdr-switchboard/blob/main/CLAUDE.md"
  style="display: block; min-height: calc(100vh - 64px);"
  data-attempted-ssr="true"
  data-ssr="true"
  data-lazy="false"
  data-alternate="false"
  data-data-router-enabled="true"
  data-react-profiling="false"
>
  
  <script type="application/json" data-target="react-app.embeddedData">{"payload":{"codeViewBlobRoute":{"csv":null,"csvError":null,"headerInfo":{"toc":[{"level":1,"text":"CLAUDE.md","anchor":"claudemd","htmlText":"CLAUDE.md"},{"level":2,"text":"What this is","anchor":"what-this-is","htmlText":"What this is"},{"level":2,"text":"Commands","anchor":"commands","htmlText":"Commands"},{"level":2,"text":"Architecture","anchor":"architecture","htmlText":"Architecture"},{"level":2,"text":"Non-obvious constraints","anchor":"non-obvious-constraints","htmlText":"Non-obvious constraints"},{"level":2,"text":"Conventions","anchor":"conventions","htmlText":"Conventions"},{"level":2,"text":"Agent skills","anchor":"agent-skills","htmlText":"Agent skills"},{"level":3,"text":"Issue tracker","anchor":"issue-tracker","htmlText":"Issue tracker"},{"level":3,"text":"Triage labels","anchor":"triage-labels","htmlText":"Triage labels"},{"level":3,"text":"Domain docs","anchor":"domain-docs","htmlText":"Domain docs"}]},"issueTemplate":null,"discussionTemplate":null,"richText":"\u003carticle class=\"markdown-body entry-content container-lg\" itemprop=\"text\"\u003e\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch1 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCLAUDE.md\u003c/h1\u003e\u003ca id=\"user-content-claudemd\" class=\"anchor\" aria-label=\"Permalink: CLAUDE.md\" href=\"#claudemd\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eWhat this is\u003c/h2\u003e\u003ca id=\"user-content-what-this-is\" class=\"anchor\" aria-label=\"Permalink: What this is\" href=\"#what-this-is\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eA \u003ca href=\"https://herdr.dev\" rel=\"nofollow\"\u003eherdr\u003c/a\u003e plugin providing a unified switcher over running herdr \u003cstrong\u003eagents\u003c/strong\u003e,\nopen herdr \u003cstrong\u003eworkspaces\u003c/strong\u003e, \u003cstrong\u003eghq repos\u003c/strong\u003e, and linked Git \u003cstrong\u003eworktrees\u003c/strong\u003e in one fuzzy picker. It is a\nRust TUI (ratatui + nucleo), not an fzf wrapper. Every surface is a mode of the same binary,\nselected by argv (\u003ccode\u003e--menu\u003c/code\u003e, \u003ccode\u003e--agents\u003c/code\u003e, \u003ccode\u003e--usage\u003c/code\u003e, \u003ccode\u003e--commands\u003c/code\u003e, \u003ccode\u003e--ports\u003c/code\u003e, \u003ccode\u003e--zen\u003c/code\u003e,\n\u003ccode\u003e--changelog\u003c/code\u003e, \u003ccode\u003e--settings\u003c/code\u003e, \u003ccode\u003e--git\u003c/code\u003e; no flag is the switcher); the settings form is \u003cstrong\u003ealso\u003c/strong\u003e a\nfloating overlay inside the switcher (⌥,), not only a pane. \u003cstrong\u003e\u003ccode\u003e--usage\u003c/code\u003e is the only mode that reads\na credential and the only in-process HTTP client\u003c/strong\u003e — both fenced, see the constraints below. Git\ncan fetch pull requests through \u003ccode\u003egh\u003c/code\u003e only when that row is activated, and update checks use a\ndetached \u003ccode\u003egit ls-remote\u003c/code\u003e child. The \u003cstrong\u003egit menu is a herdr pane of its own\u003c/strong\u003e (\u003ccode\u003ePrefix + g\u003c/code\u003e →\n\u003ccode\u003ebin/git.sh\u003c/code\u003e → \u003ccode\u003e--git\u003c/code\u003e), not an overlay on the switcher, and its selection \u003ccode\u003eexec\u003c/code\u003es a review tool\nover that pane. The review launcher (\u003ccode\u003ebin/review.sh\u003c/code\u003e, which runs\n\u003ccode\u003etuicr\u003c/code\u003e/\u003ccode\u003elazygit\u003c/code\u003e), the guarded updater, and \u003ccode\u003ebin/picker.sh\u003c/code\u003e's one-time bootstrap feedback are the\nBash terminal owners. The plugin needs no fzf.\nSee \u003ccode\u003eREADME.md\u003c/code\u003e for user-facing keybindings and configuration.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eCommands\u003c/h2\u003e\u003ca id=\"user-content-commands\" class=\"anchor\" aria-label=\"Permalink: Commands\" href=\"#commands\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"highlight highlight-source-shell notranslate position-relative overflow-auto\" dir=\"auto\" data-snippet-clipboard-copy-content=\"cargo build                                  # debug binary\ncargo build --release                        # what bin/picker.sh actually launches\ncargo test                                   # unit tests (sorting, group filter, history parsing)\ncargo test recent_sort_puts_latest_opened_first   # single test by name\nbash bin/check.sh                            # complete local/CI/release gate\nbash bin/coverage.sh                         # line coverage, gated at 98% (CI runs this too)\nbash bin/coverage.sh --open                  # ... and open the annotated HTML report\nbash bin/release.sh 0.5.0                    # cut a release (gates, bump, changelog, tag, gh release)\n\nherdr plugin link /path/to/herdr-switchboard         # install this checkout for manual testing\nherdr server reload-config                   # after touching keybindings/config\nherdr plugin config-dir switchboard          # where the runtime config.toml lives\"\u003e\u003cpre\u003ecargo build                                  \u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e debug binary\u003c/span\u003e\ncargo build --release                        \u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e what bin/picker.sh actually launches\u003c/span\u003e\ncargo \u003cspan class=\"pl-c1\"\u003etest\u003c/span\u003e                                   \u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e unit tests (sorting, group filter, history parsing)\u003c/span\u003e\ncargo \u003cspan class=\"pl-c1\"\u003etest\u003c/span\u003e recent_sort_puts_latest_opened_first   \u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e single test by name\u003c/span\u003e\nbash bin/check.sh                            \u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e complete local/CI/release gate\u003c/span\u003e\nbash bin/coverage.sh                         \u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e line coverage, gated at 98% (CI runs this too)\u003c/span\u003e\nbash bin/coverage.sh --open                  \u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e ... and open the annotated HTML report\u003c/span\u003e\nbash bin/release.sh 0.5.0                    \u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e cut a release (gates, bump, changelog, tag, gh release)\u003c/span\u003e\n\nherdr plugin link /path/to/herdr-switchboard         \u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e install this checkout for manual testing\u003c/span\u003e\nherdr server reload-config                   \u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e after touching keybindings/config\u003c/span\u003e\nherdr plugin config-dir switchboard          \u003cspan class=\"pl-c\"\u003e\u003cspan class=\"pl-c\"\u003e#\u003c/span\u003e where the runtime config.toml lives\u003c/span\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003ccode\u003ebin/check.sh\u003c/code\u003e is the single full-gate interface for local sessions, CI, and releases. Layout,\nkeybinding, or Herdr CLI changes still need manual exercise in a real Herdr session in addition to\nRust render tests.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003eCoverage is deliberately \u003cstrong\u003enot\u003c/strong\u003e part of \u003ccode\u003echeck.sh\u003c/code\u003e: it needs its own instrumented build, which\nwould turn the ~5s gate you run constantly into a ~90s one. CI runs \u003ccode\u003ebin/coverage.sh\u003c/code\u003e as a separate\njob. It needs \u003ccode\u003erustup component add llvm-tools-preview\u003c/code\u003e and \u003ccode\u003ecargo install cargo-llvm-cov --locked\u003c/code\u003e;\nthe script prefers a rustup toolchain when one carries the tools, because a Homebrew rust can sit\nfirst on PATH beside a perfectly good rustup toolchain and only the latter can instrument.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eArchitecture\u003c/h2\u003e\u003ca id=\"user-content-architecture\" class=\"anchor\" aria-label=\"Permalink: Architecture\" href=\"#architecture\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eTwo layers, joined by environment variables.\u003c/strong\u003e Every action starts in bash and may end in Rust:\u003c/p\u003e\n\u003col dir=\"auto\"\u003e\n\u003cli\u003e\u003ccode\u003ebin/action.sh\u003c/code\u003e is the single entrypoint for all manifest actions. It maps the action id\n(via \u003ccode\u003eHERDR_PLUGIN_ACTION_ID\u003c/code\u003e) to a pane id (\u003ccode\u003epicker\u003c/code\u003e / \u003ccode\u003egit\u003c/code\u003e / \u003ccode\u003eget\u003c/code\u003e overlays, \u003ccode\u003echangelog\u003c/code\u003e\npopup) and its placement, captures the \u003cstrong\u003eorigin pane id and cwd\u003c/strong\u003e before the pane steals focus,\nand passes them forward as\n\u003ccode\u003eSWITCHBOARD_ORIGIN_PANE_ID\u003c/code\u003e / \u003ccode\u003eSWITCHBOARD_ORIGIN_CWD\u003c/code\u003e on \u003ccode\u003eherdr plugin pane open\u003c/code\u003e. The \u003ccode\u003egit\u003c/code\u003e action opens the\ndedicated \u003ccode\u003egit\u003c/code\u003e pane; that pane acts on a \u003cstrong\u003ecwd\u003c/strong\u003e, not a pane id.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003ebin/picker.sh\u003c/code\u003e resolves a versioned, checksummed release binary for managed installs and\nfalls back to Cargo for offline/linked checkouts. Its Bash typing-cat owns first-run feedback;\n\u003ccode\u003e--prepare\u003c/code\u003e resolves the binary without launching it.\u003c/li\u003e\n\u003cli\u003eThe TUI (\u003ccode\u003esrc/\u003c/code\u003e) claims the terminal and draws the final Projects chrome immediately with a\nstatic \u003ccode\u003eStanding by…\u003c/code\u003e state while a feature-local worker loads the catalogue. Completion returns\nthrough a typed, generation-tagged effect; an empty initial result opens the Clone form.\n\u003ccode\u003esurface::run\u003c/code\u003e hosts the Projects surface and guarantees terminal\nrestoration before an open outcome runs. Interactive accepts (repository remove\nconfirmation, \u003ccode\u003eghq get -u\u003c/code\u003e output) deliberately run on the restored terminal. Linked-worktree\nremoval instead confirms in a modal TUI overlay and runs through a typed background effect.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eWhy the origin pane matters:\u003c/strong\u003e \u003ccode\u003esplit\u003c/code\u003e and \u003ccode\u003epane\u003c/code\u003e targets act on the captured \u003ccode\u003eSWITCHBOARD_ORIGIN_PANE_ID\u003c/code\u003e.\nThe overlay pane is \u003cem\u003enot\u003c/em\u003e the user's pane. Never guess or infer a pane/workspace/agent id — every id\nmust come from \u003ccode\u003eherdr agent list\u003c/code\u003e, \u003ccode\u003eherdr workspace list\u003c/code\u003e, or the captured origin.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eModule ownership:\u003c/strong\u003e current file ownership and module seams live only in\n\u003ccode\u003edocs/architecture.md\u003c/code\u003e. Keep this file focused on non-obvious invariants; when moving or\nsplitting code, update the architecture document in the same commit and run\n\u003ccode\u003ebash tests/docs_spec.sh\u003c/code\u003e.\u003c/p\u003e\n\u003cp dir=\"auto\"\u003e\u003cstrong\u003eSort vs. search:\u003c/strong\u003e fuzzy score always wins while a query is present; \u003ccode\u003eSortMode\u003c/code\u003e (recent/name/kind)\nonly orders the resting, no-query list. Both paths honour the \u003ccode\u003eGroupFilter\u003c/code\u003e. Ties break on load\norder so the list stays stable.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eNon-obvious constraints\u003c/h2\u003e\u003ca id=\"user-content-non-obvious-constraints\" class=\"anchor\" aria-label=\"Permalink: Non-obvious constraints\" href=\"#non-obvious-constraints\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cul dir=\"auto\"\u003e\n\u003cli\u003e\u003cstrong\u003eherdr draws the pane frame; the TUI must not compete with it.\u003c/strong\u003e Every plugin pane is\n\u003ccode\u003epopup\u003c/code\u003e or \u003ccode\u003eoverlay\u003c/code\u003e, and herdr frames both and requires a non-empty title. So a pane\ntitle is a \u003cstrong\u003esingle icon\u003c/strong\u003e (\u003ccode\u003e󰊢\u003c/code\u003e, \u003ccode\u003e󰍜\u003c/code\u003e, \u003ccode\u003e󰆍\u003c/code\u003e, \u003ccode\u003e󰛳\u003c/code\u003e) and the human-readable mode name goes on\nthe \u003cem\u003elist panel\u003c/em\u003e inside — word titles on both produced \u003ccode\u003ePorts\u003c/code\u003e twice, two rows apart.\nFor the same reason the plugin's own borders recede in \u003ccode\u003eoverlay0\u003c/code\u003e while herdr's frame\nkeeps the accent. \u003cstrong\u003eBackground policy belongs only to \u003ccode\u003etui::SurfaceBackground\u003c/code\u003e:\u003c/strong\u003e\n\u003ccode\u003ecommon.transparency = \"transparent\"\u003c/code\u003e clears every root and floating card to the terminal\ndefault, while \u003ccode\u003e\"opaque\"\u003c/code\u003e fills every one with \u003ccode\u003epanel_bg\u003c/code\u003e. A renderer never hand-writes\n\u003ccode\u003eClear\u003c/code\u003e or \u003ccode\u003e.bg(panel_bg)\u003c/code\u003e for a surface. \u003ccode\u003epanel_bg\u003c/code\u003e remains the foreground ink on coloured\npills and mode chips in either mode. Tests in \u003ccode\u003epicker.rs\u003c/code\u003e, \u003ccode\u003eprojects.rs\u003c/code\u003e, and \u003ccode\u003egit.rs\u003c/code\u003e\n(\u003ccode\u003ethe_search_box_is_captioned_search_and_the_list_carries_the_mode_title\u003c/code\u003e,\n\u003ccode\u003epanels_use_the_projects_pickers_border_and_caption_slots\u003c/code\u003e,\n\u003ccode\u003eno_panel_paints_an_opaque_background\u003c/code\u003e, and the opaque-mode contracts) pin this down.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThere is one panel frame, \u003ccode\u003etui::framed\u003c/code\u003e, and every framed surface goes through it or\nthrough \u003ccode\u003etui::boxed\u003c/code\u003e\u003c/strong\u003e (the same frame plus a caption, and defined in terms of it, so the\nborder style is spelled once). It lived in \u003ccode\u003eui.rs\u003c/code\u003e while \u003ccode\u003epicker.rs\u003c/code\u003e hand-rolled its own\n\u003ccode\u003eBlock\u003c/code\u003es, and the two drifted exactly as you would expect: accent borders instead of\n\u003ccode\u003eoverlay0\u003c/code\u003e, and captions passed as bare \u003ccode\u003e\u0026amp;str\u003c/code\u003e so they rendered in the terminal's default\nforeground rather than \u003ccode\u003etitle_color\u003c/code\u003e. \u003ccode\u003egit.rs\u003c/code\u003e drifted the same way and went further, filling\nall three of its cards with \u003ccode\u003epanel_bg\u003c/code\u003e — the transparency bug that shipped in 1.2.0. A new\nframed surface calls \u003ccode\u003eboxed\u003c/code\u003e, or \u003ccode\u003eframed\u003c/code\u003e when its caption slot holds something richer than a\nword (the switcher's tab strip); it does not build a \u003ccode\u003eBlock\u003c/code\u003e itself.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThe git menu is a pane, and a review \u003ccode\u003eexec\u003c/code\u003es over that pane.\u003c/strong\u003e There is a manifest pane for\nthe \u003cem\u003emenu\u003c/em\u003e (\u003ccode\u003e[[panes]] id = \"git\"\u003c/code\u003e), but \u003cstrong\u003enone for the review\u003c/strong\u003e: \u003ccode\u003egit::main\u003c/code\u003e \u003ccode\u003eexec\u003c/code\u003es\n\u003ccode\u003ebin/review.sh\u003c/code\u003e over itself, so tuicr\ninherits the pane and quitting it returns to the pane \u003ccode\u003ePrefix + g\u003c/code\u003e was pressed in. The pane's\nplacement must stay \u003cstrong\u003efull-frame \u003ccode\u003eoverlay\u003c/code\u003e\u003c/strong\u003e — tuicr renders into whatever window it is handed,\nand a popup would hand it a tiny one. The picker knows nothing about git: there is no \u003ccode\u003e⌥g\u003c/code\u003e, no\n\u003ccode\u003eAccept::Git\u003c/code\u003e, no \u003ccode\u003eApp::git\u003c/code\u003e. Two entry points would drift apart, and only one of them can be\nthe fast one. \u003ccode\u003etuicr\u003c/code\u003e is a TUI — never run it non-interactively (it blocks); only ever in a pane.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSaved-review integration never takes ownership of tuicr content.\u003c/strong\u003e A handoff is a pointer-only,\nnon-blocking effect whose inputs are the repository, session slug, and a pane id returned by\n\u003ccode\u003eherdr agent list\u003c/code\u003e; delivery uses \u003ccode\u003eherdr agent prompt\u003c/code\u003e without \u003ccode\u003e--wait\u003c/code\u003e. Archive state contains\nonly exact session slugs and changes Switchboard visibility, never tuicr's session JSON. Comment\nbodies never enter Switchboard state, logs, notifications, or another command line.\n\u003ccode\u003edocs/git-menu.md\u003c/code\u003e owns the user-facing archive, target-selection, and fallback behaviour.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAgent handoffs share one target seam and never wait for a turn.\u003c/strong\u003e \u003ccode\u003eagent_handoff.rs\u003c/code\u003e is the only\nowner of promptable-agent parsing, same-worktree/origin selection, and \u003ccode\u003eherdr agent prompt\u003c/code\u003e;\nneither Git nor Projects adds \u003ccode\u003e--wait\u003c/code\u003e. Projects sends only JSON-escaped item kind, label, and\nabsolute path as data-only context. Paths and labels never enter notifications or traces, and a\nWorkspace never pretends its several pane directories are one selectable path.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProjects catalogue discovery is a feature-local background effect.\u003c/strong\u003e Startup draws the final\nSearch/Context/Navigator/Preview geometry first and shows static \u003ccode\u003eStanding by…\u003c/code\u003e; it accepts only\nClose until the generation-tagged completion arrives. Settings Apply keeps the old rows visible\nunder \u003ccode\u003eRefreshing…\u003c/code\u003e, locks selection-dependent actions, and restores selection by entry ID.\nThere is no minimum-visible floor. Repository and worktree discovery share one \u003ccode\u003eghq list --full-path\u003c/code\u003e\nsnapshot, and per-repository worktree probes use at most four threads while their results are\ninstalled in snapshot order. Full paths are retained across all ghq roots; durable IDs stay\nrelative to the longest matching root. An empty initial catalogue opens the Clone form in place.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eClone never asks for credentials in the TUI.\u003c/strong\u003e Git/SSH use configured credential helpers\nand agents with interactive prompts disabled. The URL form rejects embedded credentials;\nexternal clone output is never drawn, traced, or logged. Cancellation stops and reaps the\nentire child process group before allowing another clone, and never deletes partial directories.\nDefault completion refreshes/selects; explicit \u003ccode\u003eclone.open_after = true\u003c/code\u003e returns a typed open\noutcome so Herdr work still runs after terminal restoration.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProjects stars are durable-entry state, not another source.\u003c/strong\u003e Only Repo and Worktree identities\ncan be starred; Agent and Workspace IDs are live and must never enter the persistent set. The\nfinal Starred group filters the already-loaded catalogue and keeps its search, sort, and actions.\n\u003ccode\u003eprojects::stars\u003c/code\u003e owns typed identity and mutation; \u003ccode\u003estate\u003c/code\u003e owns the private tempfile, atomic\nreplace, and cross-process lock around the complete read-modify-write transaction. Writes return\nthrough a typed Projects effect before the reducer changes the marker or list. Missing or\nmalformed state degrades to no stars and must never block the first Projects frame.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThe pre-build cat runs before Rust exists and sizes itself from the plugin PTY.\u003c/strong\u003e\n\u003ccode\u003erun_with_splash\u003c/code\u003e reads \u003ccode\u003estty size \u0026lt;/dev/tty\u003c/code\u003e and passes those cells to \u003ccode\u003ebootstrap_frame\u003c/code\u003e on each\nanimation frame. Do not replace it with \u003ccode\u003etput\u003c/code\u003e: redirecting \u003ccode\u003etput\u003c/code\u003e away from the TTY makes it\nreturn terminfo's 80x24 default in a wide Herdr pane. Horizontal padding is spaces; vertical\npadding is rows. \u003ccode\u003etests/bootstrap_spec.sh\u003c/code\u003e pins both coordinates.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eA list fetch runs outside \u003ccode\u003eGit::on_key\u003c/code\u003e and off the input thread.\u003c/strong\u003e \u003ccode\u003eon_key\u003c/code\u003e returns a \u003ccode\u003eStep\u003c/code\u003e;\n\u003ccode\u003eGitSurface\u003c/code\u003e turns \u003ccode\u003eStep::Load\u003c/code\u003e and \u003ccode\u003eStep::CountFiles\u003c/code\u003e into typed background effects, then applies\ntheir results from \u003ccode\u003eon_tick\u003c/code\u003e. That keeps the key interface IO-free and unit-testable through\n\u003ccode\u003eMockRunner\u003c/code\u003e, while \u003ccode\u003egh pr list\u003c/code\u003e leaves the menu responsive instead of freezing a half-drawn list.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNothing writes to tuicr's config.\u003c/strong\u003e The theme is a whole file that\n\u003ca href=\"https://github.com/crafts69guy/hue-theme\"\u003ehue-theme\u003c/a\u003e owns\n(\u003ccode\u003e~/.config/tuicr/themes/hue-\u0026lt;mood\u0026gt;.toml\u003c/code\u003e, 41 keys, none optional). tuicr \u003cstrong\u003eexits 2\u003c/strong\u003e on a theme\nit cannot fully resolve, and \u003ccode\u003e--theme\u003c/code\u003e on a mismatched name takes the whole review path down —\nso \u003ccode\u003ebin/review.sh\u003c/code\u003e never passes \u003ccode\u003e--theme\u003c/code\u003e and \u003ccode\u003eensure_tuicr\u003c/code\u003e only checks the binary exists.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOpen + config live in Rust.\u003c/strong\u003e The clone form uses the same restored open dispatch as Projects;\n\u003ccode\u003ebin/get.sh\u003c/code\u003e only launches \u003ccode\u003e--clone\u003c/code\u003e. The \u003ccode\u003eopen\u003c/code\u003e and \u003ccode\u003econfig get\u003c/code\u003e CLI interfaces remain available,\nso the Herdr open verbs (\u003ccode\u003esrc/action.rs::open_target\u003c/code\u003e) and typed config reader (\u003ccode\u003eConfig::load\u003c/code\u003e)\nlive in one place. \u003ccode\u003ebin/lib.sh\u003c/code\u003e keeps \u003ccode\u003eensure_built\u003c/code\u003e (build-on-demand, shared by the picker entrypoints),\n\u003ccode\u003etoml_get\u003c/code\u003e (used only by \u003ccode\u003econfigure_notifications\u003c/code\u003e, the pre-build notification path that must not\ndepend on a cargo build), and the pane-context/JSON helpers. \u003cstrong\u003eA change to how a target opens\nlands only in \u003ccode\u003eaction.rs\u003c/code\u003e.\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003efnm activation is opt-in, local, and post-selection.\u003c/strong\u003e \u003ccode\u003e[fnm].enabled\u003c/code\u003e defaults off. Preview\nreads declarations from disk only; \u003ccode\u003efnm exec --using \u0026lt;repo\u0026gt; -- printenv PATH\u003c/code\u003e runs after an open\nis accepted, never installs a version, and never performs network work. Fresh targets receive\nthat PATH through Herdr's \u003ccode\u003e--env\u003c/code\u003e and never receive post-create terminal input; shell startup\nowns session-local initialization and must preserve the launch PATH or activate the initial cwd.\nThe current-pane target remains \u003ccode\u003ecd\u003c/code\u003e-only and relies on fnm's standard \u003ccode\u003e--use-on-cd\u003c/code\u003e shell hook.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThe Node Versions manager is the only explicit fnm mutation surface.\u003c/strong\u003e It loads installed\nversions locally, runs \u003ccode\u003efnm list-remote\u003c/code\u003e on a worker only after the user opens the dedicated\npane, and performs install/default/uninstall after terminal restoration. \u003ccode\u003euse\u003c/code\u003e is sent to the\ncaptured origin pane because a child process cannot change its parent shell; uninstall requires\nthe exact selected version as typed confirmation.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eSettings has two presentations, not two renderers.\u003c/strong\u003e The embedded form is a centred floating\ncard because it overlays Projects. The standalone action already lives in a Herdr-framed popup,\nso it draws the same form full-area with a content margin and no second border or duplicate\ntitle. Both presentations share the columns, tabs, hit zones, hints, and command bar.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eConfiguration is typed and namespaced.\u003c/strong\u003e \u003ccode\u003econfig.rs\u003c/code\u003e deserializes the section structs with\n\u003ccode\u003edeny_unknown_fields\u003c/code\u003e; Rust code reads those fields directly. \u003ccode\u003eConfig::value_for_cli\u003c/code\u003e is the\ndeliberately narrow compatibility seam for Bash's \u003ccode\u003econfig get\u003c/code\u003e calls, not an internal\nlookup interface. \u003ccode\u003esettings.rs\u003c/code\u003e writes namespaced values through \u003ccode\u003etoml_edit\u003c/code\u003e, preserving comments\nand hand-added keys before validating the complete result. \u003cstrong\u003eEvery picker has a \u003ccode\u003e[keys.*]\u003c/code\u003e table\u003c/strong\u003e\n— \u003ccode\u003eprojects\u003c/code\u003e, \u003ccode\u003eagents\u003c/code\u003e, \u003ccode\u003ecommands\u003c/code\u003e, \u003ccode\u003eports\u003c/code\u003e, \u003ccode\u003ezen\u003c/code\u003e, \u003ccode\u003emenu\u003c/code\u003e, \u003ccode\u003efnm\u003c/code\u003e — reached through\n\u003ccode\u003ePickerMode::key_bindings\u003c/code\u003e plus a \u003ccode\u003ereload_config\u003c/code\u003e that re-reads it; a mode that implements neither\nis one whose keys nobody can move, which is what Menu and the fnm manager silently were.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eA click zone is measured by the loop that draws the thing.\u003c/strong\u003e \u003ccode\u003etab_zones\u003c/code\u003e and\n\u003ccode\u003efooter_zones\u003c/code\u003e (\u003ccode\u003esrc/projects/view.rs\u003c/code\u003e) are built inside the same loops that lay out the tab strip\nand the command bar, because a zone computed separately drifts the moment a label\nchanges — and drifts \u003cem\u003esilently\u003c/em\u003e, into clicking the wrong action. \u003ccode\u003elist_state\u003c/code\u003e is kept\non the \u003ccode\u003eApp\u003c/code\u003e for the same reason: its scroll offset is the only thing that turns a\nclicked row back into an entry, so it cannot be a fresh \u003ccode\u003eListState\u003c/code\u003e per frame.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThe cheatsheet's descriptions must fit \u003ccode\u003eHELP_DESC\u003c/code\u003e\u003c/strong\u003e (\u003ccode\u003esrc/projects/view.rs\u003c/code\u003e) — the popup's half\nwidth less the key pill, around 19 columns. A longer one is cut with no ellipsis, so it\nships looking like a shorter phrase; \u003ccode\u003ewheel  Scroll whatever is under it\u003c/code\u003e reached a\nREADME screenshot as \u003ccode\u003eScroll whatever is\u003c/code\u003e. \u003ccode\u003erow\u003c/code\u003e asserts, and a \u003ccode\u003eTestBackend\u003c/code\u003e render\ntest in \u003ccode\u003eprojects.rs\u003c/code\u003e fires it.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eA prefix names the kind of work, never the mode.\u003c/strong\u003e \u003ccode\u003e^\u0026lt;key\u0026gt;\u003c/code\u003e acts on the selected row; \u003ccode\u003e⌥\u0026lt;key\u0026gt;\u003c/code\u003e\nchanges the view or the app (or is the heavier form of the \u003ccode\u003e^\u003c/code\u003e verb on the same letter, as\nPorts' \u003ccode\u003e^x\u003c/code\u003e TERM / \u003ccode\u003e⌥x\u003c/code\u003e KILL); \u003ccode\u003e↵\u003c/code\u003e runs the row's primary action with \u003ccode\u003e^↵\u003c/code\u003e/\u003ccode\u003e⌥↵\u003c/code\u003e as its variants.\nSo \u003cstrong\u003eevery modified chord appears in both \u003ccode\u003edefault_insert\u003c/code\u003e and \u003ccode\u003edefault_normal\u003c/code\u003e with the same\naction\u003c/strong\u003e, and Normal's bare letters are \u003cem\u003ealiases carrying the same letter\u003c/em\u003e, never a respelling.\nThree tests in \u003ccode\u003ekeymap.rs\u003c/code\u003e enforce exactly this and are the reason the layout stops drifting:\n\u003ccode\u003eevery_modified_chord_means_the_same_thing_in_both_modes\u003c/code\u003e,\n\u003ccode\u003eno_action_straddles_the_ctrl_and_alt_families\u003c/code\u003e, and\n\u003ccode\u003ea_bare_alias_carries_the_same_letter_as_its_chord\u003c/code\u003e. Two vocabularies are carved out by name in\n\u003ccode\u003emode_idiomatic\u003c/code\u003e: motion (readline in Insert, Vim in Normal) and query editing (\u003ccode\u003e^u\u003c/code\u003e clear,\n\u003ccode\u003e⌥⌫\u003c/code\u003e delete-word, Insert-only). \u003ccode\u003e^u\u003c/code\u003e and \u003ccode\u003e^c\u003c/code\u003e are reserved on every surface — no \u003ccode\u003eActionSpec\u003c/code\u003e\nmay take them, which is why the fnm manager's \u003ccode\u003euse\u003c/code\u003e/\u003ccode\u003einstall\u003c/code\u003e sit on the \u003ccode\u003e↵\u003c/code\u003e ladder.\n\u003cstrong\u003eA chord that is somebody's multiplexer prefix never reaches the pane at all\u003c/strong\u003e, so opening in a\ntab is the mnemonic-free \u003ccode\u003e^e\u003c/code\u003e: herdr's default prefix is \u003ccode\u003e^b\u003c/code\u003e and \u003ccode\u003e^t\u003c/code\u003e is the usual tmux-refugee\nalternative, so the open group avoids both. \u003ccode\u003e^b\u003c/code\u003e is refused by\n\u003ccode\u003eno_default_chord_takes_herdrs_prefix\u003c/code\u003e and by the shared picker's check; do not \"fix\" \u003ccode\u003e^e\u003c/code\u003e into\n\u003ccode\u003e^t\u003c/code\u003e, and do not reclaim \u003ccode\u003e^b\u003c/code\u003e for anything.\n\u003cstrong\u003eThere is no \u003ccode\u003e␣\u003c/code\u003e leader, and adding one back is the bug.\u003c/strong\u003e Space can only be a leader in Normal\n— in Insert it is a character the user is typing — so any group living there was forced to change\nprefix with the mode, which is the whole inconsistency this layout removes. The Git menu, the\nCentral Menu, the settings form, and the Usage/changelog viewers sit outside the rule on purpose:\ntheir keys name a row, a destination, or a form field rather than a verb on a selection.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThe shared picker answers five chords itself, and they live in one table.\u003c/strong\u003e \u003ccode\u003eRESERVED\u003c/code\u003e\n(\u003ccode\u003esrc/picker.rs\u003c/code\u003e) holds \u003ccode\u003e⌥,\u003c/code\u003e, \u003ccode\u003e⌥j\u003c/code\u003e, \u003ccode\u003e⌥k\u003c/code\u003e, \u003ccode\u003e⇥\u003c/code\u003e, \u003ccode\u003e⇧⇥\u003c/code\u003e; \u003ccode\u003ePickerSurface::on_key\u003c/code\u003e dispatches from it\nthrough \u003ccode\u003ereserved_for\u003c/code\u003e, \u003cem\u003eahead\u003c/em\u003e of any \u003ccode\u003eActionSpec\u003c/code\u003e. They used to be five hand-written \u003ccode\u003eif\u003c/code\u003es that\nnothing checked against, so a mode declaring one of those chords had its action swallowed with no\nerror — the same silent shape as Ports' \u003ccode\u003e^w\u003c/code\u003e, which shadowed delete-word for that picker alone.\nA new \u003ccode\u003eActionSpec\u003c/code\u003e is therefore checked by \u003ccode\u003epicker::assert_follows_prefix_concept\u003c/code\u003e, which every\nmode calls from its \u003cstrong\u003eown\u003c/strong\u003e test module (the modes are private to their files, so the check\ntravels to them). It refuses a bare \u003ccode\u003eChar\u003c/code\u003e (it would be matched ahead of the typing arm and make\nthat letter untypeable), \u003ccode\u003e^c\u003c/code\u003e/\u003ccode\u003e^u\u003c/code\u003e, anything in \u003ccode\u003eRESERVED\u003c/code\u003e, a \u003ccode\u003ekey_label\u003c/code\u003e that is not the chord it\nlistens for, and a shared action id bound to a chord it does not carry elsewhere.\n\u003ccode\u003ethe_prefix_concept_check_rejects_every_shape_it_names\u003c/code\u003e asserts the guard actually bites, because\na guard that silently passes is the failure it exists to prevent.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOne keypress gets one answer, and \u003ccode\u003esame_chord\u003c/code\u003e is where that is decided.\u003c/strong\u003e Matching weighs only\nCTRL and ALT, exactly as \u003ccode\u003ekeymap::chord_of\u003c/code\u003e does: SHIFT is already baked into the character a\nterminal reports and terminals disagree about whether they set the bit too. \u003ccode\u003eActionSpec::matches\u003c/code\u003e\ncompared modifier bits with \u003ccode\u003e==\u003c/code\u003e while the keymap used \u003ccode\u003econtains\u003c/code\u003e, so the same press acted in\nProjects and did nothing in every other picker — \u003ccode\u003e⇧↵\u003c/code\u003e ran the row in one and was inert in the\nother, and a \u003ccode\u003e^⇧\u003c/code\u003e chord missed its \u003ccode\u003e^\u003c/code\u003e action outright. Because SHIFT no longer separates two\nchords, \u003ccode\u003eassert_follows_prefix_concept\u003c/code\u003e also refuses two specs that normalise to the same chord;\nwithout that rule the second one would simply never run.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKeys are a config-driven keymap, not hardcoded \u003ccode\u003ematch\u003c/code\u003e arms.\u003c/strong\u003e \u003ccode\u003ehandle_key\u003c/code\u003e resolves a\n\u003ccode\u003eChord\u003c/code\u003e through \u003ccode\u003eApp::keymap\u003c/code\u003e (\u003ccode\u003esrc/keymap.rs\u003c/code\u003e) and runs \u003ccode\u003eapply_action\u003c/code\u003e. Two ordered tables\n(Insert + Normal); typed \u003ccode\u003ecommon.keymode\u003c/code\u003e defaults to Normal and \u003ccode\u003eesc\u003c/code\u003e toggles Insert↔Normal.\n\u003ccode\u003e[keys.projects]\u003c/code\u003e entries rebind actions (first chord wins as the shown one) into \u003cstrong\u003eboth\u003c/strong\u003e tables,\nso an override cannot reintroduce a per-mode split.\n\u003cstrong\u003eThe footer (\u003ccode\u003edraw_footer\u003c/code\u003e) and the cheatsheet (\u003ccode\u003edraw_help\u003c/code\u003e) render from the keymap via\n\u003ccode\u003eKeymap::label_for(mode, action)\u003c/code\u003e\u003c/strong\u003e, so both re-label per remap — never hardcode a\nkey cap in either; add the action to the curated list and it picks up its live chord. A row\nwhose action is unbound in the current mode drops out. \u003ccode\u003elabel_for\u003c/code\u003e returns the \u003cem\u003efirst\u003c/em\u003e matching\nchord, which is why a bare alias is listed after the chord it shadows.\nAdding an action is one row in \u003ccode\u003ekeymap::NAMES\u003c/code\u003e, its default chord in \u003cstrong\u003eboth\u003c/strong\u003e tables, and an\n\u003ccode\u003eapply_action\u003c/code\u003e arm; a new \u003ccode\u003eAccept\u003c/code\u003e also needs the footer curated list and \u003ccode\u003edispatch\u003c/code\u003e. Cheatsheet\ndescriptions must still fit \u003ccode\u003eHELP_DESC\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOne frame absorbs every event already queued, and a list row borrows rather than copies.\u003c/strong\u003e\nThese two are one fact from opposite ends. A terminal delivers a wheel turn or a held key as a\nburst, and \u003ccode\u003esurface::run\u003c/code\u003e used to answer each with its own full repaint; meanwhile \u003ccode\u003edraw_list\u003c/code\u003e\n(\u003ccode\u003eprojects/view.rs\u003c/code\u003e) and the shared picker's row builder cloned every column of every \u003cem\u003efiltered\u003c/em\u003e\nentry per frame — including the rows a \u003ccode\u003eList\u003c/code\u003e scrolls past and never paints, over a Commands\ncatalogue that is \u003ccode\u003ecommands.history_limit\u003c/code\u003e (5,000) rows deep by default. So a burst multiplied a\nper-entry cost that was already linear. \u003ccode\u003edrain_frame\u003c/code\u003e now takes queued input up to\n\u003ccode\u003eMAX_COALESCED_EVENTS\u003c/code\u003e before repainting — the cap is what stops a paste from starving the\nscreen — and rows borrow out of \u003ccode\u003estate.items\u003c/code\u003e / \u003ccode\u003epicker.entries\u003c/code\u003e, which is why both draw\nfunctions destructure their \u003ccode\u003e\u0026amp;mut\u003c/code\u003e state into disjoint field borrows and why the shared picker\nmoves its \u003ccode\u003eListState\u003c/code\u003e out with \u003ccode\u003emem::take\u003c/code\u003e before building rows. Padding comes from\n\u003ccode\u003etui::spaces\u003c/code\u003e, a slice of one static. Do not \"tidy\" a row builder back to \u003ccode\u003eto_string()\u003c/code\u003e: it\ncompiles, it looks identical, and it silently restores the whole cost.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e\u003ccode\u003eStars::contains\u003c/code\u003e and the tab counts must not allocate or rescan.\u003c/strong\u003e \u003ccode\u003econtains\u003c/code\u003e is asked once\nper entry per keystroke by the reducer, once per entry per group by the Context panel, and once\nper entry per frame by the list. It answers from \u003ccode\u003eStarSet\u003c/code\u003e, which stores one ID set \u003cem\u003eper kind\u003c/em\u003e so\nthe probe is a borrowed \u003ccode\u003e\u0026amp;str\u003c/code\u003e; a \u003ccode\u003eBTreeSet\u0026lt;StarKey\u0026gt;\u003c/code\u003e cannot, because building the probe key\nmeans cloning the entry's ID. \u003ccode\u003eStarKey\u003c/code\u003e stays the on-disk shape, so the file is unchanged.\nTab counts are cached on \u003ccode\u003ePicker\u003c/code\u003e and rebuilt by \u003ccode\u003erecount\u003c/code\u003e at the three points that can\ninvalidate them — construction, \u003ccode\u003ereplace_stars\u003c/code\u003e, \u003ccode\u003ereplace_entries\u003c/code\u003e — never in \u003ccode\u003erecompute\u003c/code\u003e, which\nruns per keystroke and cannot change them. A stale cache here fails silently, so\n\u003ccode\u003etab_counts_are_rebuilt_whenever_the_entries_or_the_stars_change\u003c/code\u003e checks every tab against a\nfresh scan.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eA probe that a \u003ccode\u003eread_dir\u003c/code\u003e can rule out must not be a process.\u003c/strong\u003e \u003ccode\u003emay_have_worktrees\u003c/code\u003e\n(\u003ccode\u003edata.rs\u003c/code\u003e) asks whether \u003ccode\u003e.git/worktrees/\u003c/code\u003e has anything in it before spending a \u003ccode\u003egit worktree list\u003c/code\u003e on a repository, because that probe runs once per \u003cem\u003eghq repository\u003c/em\u003e — hundreds of forks for\nthe handful of repositories that actually have linked worktrees. It \u003cstrong\u003efails open\u003c/strong\u003e: a \u003ccode\u003e.git\u003c/code\u003e\n\u003cem\u003efile\u003c/em\u003e (this path is itself a linked worktree or a submodule) and an unreadable directory both\nstill probe, since a wrong \"no\" loses a worktree from the catalogue silently while a wrong \"yes\"\ncosts one subprocess. \u003ccode\u003ethe_worktree_prefilter_only_refuses_what_the_filesystem_settles\u003c/code\u003e pins\nevery case.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eIndependent reads that each pay a process start are overlapped, and only those.\u003c/strong\u003e\n\u003ccode\u003eprojects/effect.rs\u003c/code\u003e overlaps \u003ccode\u003eghq root\u003c/code\u003e with \u003ccode\u003eghq list\u003c/code\u003e, \u003ccode\u003esource.rs\u003c/code\u003e overlaps \u003ccode\u003eherdr agent list\u003c/code\u003e\nwith \u003ccode\u003eherdr workspace list\u003c/code\u003e, and \u003ccode\u003erepo_card\u003c/code\u003e (\u003ccode\u003eprojects/preview.rs\u003c/code\u003e) fans out branch, dirty\nstate, last commit, and the \u003ccode\u003epreview.sh\u003c/code\u003e tree so the card costs the slowest rather than their\nsum. This is only sound because every one of them is an independent \u003cem\u003eread\u003c/em\u003e. Nothing that mutates,\nand nothing whose result another call depends on, goes in a scope like these.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e\u003ccode\u003estate.rs\u003c/code\u003e owns every durable write, and a read-modify-write is one locked transaction.\u003c/strong\u003e\nFive callers used to hand-roll \u003ccode\u003efs::write\u003c/code\u003e to a \u003cstrong\u003efixed\u003c/strong\u003e \u003ccode\u003e.tmp\u003c/code\u003e sibling and rename — so two\nSwitchboard processes writing the same file raced on one temp name, and \u003ccode\u003ehistory\u003c/code\u003e and\n\u003ccode\u003ereview_archive\u003c/code\u003e, which load-modify-write, silently erased each other's rows. All of them now go\nthrough \u003ccode\u003estate\u003c/code\u003e: \u003ccode\u003ewrite_private\u003c/code\u003e / \u003ccode\u003eupdate_private\u003c/code\u003e for this plugin's own state (owner-only), and\n\u003ccode\u003ereplace_atomically\u003c/code\u003e for a file the \u003cem\u003euser\u003c/em\u003e owns — its own \u003ccode\u003econfig.toml\u003c/code\u003e and, for zen chrome,\nherdr's — which gains the lock and the unique tempfile but keeps the mode its owner gave it. A\nnew persistent file adds no sixth implementation.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThe mouse is turned on by hand, and must be turned off on every exit path.\u003c/strong\u003e \u003ccode\u003esurface.rs\u003c/code\u003e\nwrites \u003ccode\u003e?1000h\u003c/code\u003e/\u003ccode\u003e?1006h\u003c/code\u003e itself rather than using crossterm's \u003ccode\u003eEnableMouseCapture\u003c/code\u003e, which\nalso enables any-event tracking (\u003ccode\u003e?1003h\u003c/code\u003e) — every pointer move would wake the loop into\na redraw for an event we discard. \u003ccode\u003e?1000h\u003c/code\u003e reports the wheel \u003cem\u003eand\u003c/em\u003e buttons, which is\nexactly what every surface consumes; drags stay herdr's, which runs with\n\u003ccode\u003emouse_capture = true\u003c/code\u003e. The universal host pairs claim/restore and\nchains the disable ahead of the panic hook \u003ccode\u003eratatui::init\u003c/code\u003e installs,\nsince that hook restores the screen but knows nothing about the mouse. Leaving it on\ndrops mouse escapes into the user's shell. \u003cstrong\u003eEvery new terminal mode implements \u003ccode\u003eSurface\u003c/code\u003e and\nruns through \u003ccode\u003esurface::run\u003c/code\u003e; it never calls \u003ccode\u003eratatui::init\u003c/code\u003e or reads crossterm events itself.\u003c/strong\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eA click selects; a click on the already-selected row acts.\u003c/strong\u003e Terminals report no\ndouble-click (crossterm gives \u003ccode\u003eDown\u003c/code\u003e only), so single-click-to-run would let a stray\nclick \u003ccode\u003eexec\u003c/code\u003e tuicr over a pane or write a setting, and a timestamp heuristic would put\nthe same guesswork in five places. A command-bar pill carries the \u003cstrong\u003ekey printed on its\ncap\u003c/strong\u003e as its payload and routes through \u003ccode\u003eon_key\u003c/code\u003e, so the label cannot drift from the\nbehaviour. The rule is the same in \u003ccode\u003eprojects.rs\u003c/code\u003e, \u003ccode\u003epicker.rs\u003c/code\u003e, \u003ccode\u003egit.rs\u003c/code\u003e and \u003ccode\u003esettings.rs\u003c/code\u003e;\nwhat is shared between them is \u003ccode\u003etui::zone_at\u003c/code\u003e, the lookup — never the measurement, which\nstays in the loop that draws the thing.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePicker command bars may wrap, but their hit zones wrap with them.\u003c/strong\u003e \u003ccode\u003ePickerMode\u003c/code\u003e defaults to\none action row; the Central Menu requests two because it exposes every direct route. The picker\nbalances whole pills by their rendered widths, leaves one terminal row between wrapped rows,\nmeasures each row with \u003ccode\u003etui::pill_row\u003c/code\u003e, and stores the row coordinate beside its zones. Never\nsplit or reposition the spans independently of those zones.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThe preview clips; it must never wrap.\u003c/strong\u003e Every body goes through \u003ccode\u003eclip\u003c/code\u003e/\u003ccode\u003eclip_line\u003c/code\u003e\n(\u003ccode\u003esrc/projects/preview.rs\u003c/code\u003e) so one card line is exactly one screen row — that is what makes\n\u003ccode\u003epreview_scroll\u003c/code\u003e mean what it says and \u003ccode\u003epreview_len\u003c/code\u003e/\u003ccode\u003epreview_rows\u003c/code\u003e bound it correctly.\n\u003ccode\u003edraw_preview\u003c/code\u003e therefore has no \u003ccode\u003eWrap\u003c/code\u003e. Re-adding one, or emitting an unclipped line,\nbreaks the scroll silently: the offset drifts from the content instead of erroring. The\npane's width reaches the worker through \u003ccode\u003eApp::preview_width\u003c/code\u003e, published by \u003ccode\u003eprojects/view.rs\u003c/code\u003e, which is\nwhy \u003ccode\u003eProjectsSurface::after_draw\u003c/code\u003e requests a preview only after the host has drawn geometry.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNothing uses \u003ccode\u003ejq\u003c/code\u003e — keep it that way.\u003c/strong\u003e No code path shells out to it: the bash layer reads\nherdr's JSON with the awk-based \u003ccode\u003ejson_string_value\u003c/code\u003e / \u003ccode\u003ejson_bool_value\u003c/code\u003e in \u003ccode\u003ebin/lib.sh\u003c/code\u003e, and the\nRust layer uses \u003ccode\u003eserde_json\u003c/code\u003e (\u003ccode\u003edata.rs\u003c/code\u003e, \u003ccode\u003eprojects/preview.rs\u003c/code\u003e). It is not a documented requirement, so a\nnew jq call would be a new hard dependency on a machine that may not have it — and a silent one,\nsince a missing jq fails the same way a wrong filter does: empty output, no error.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e\u003ccode\u003eSWITCHBOARD_FORCE_TARGET\u003c/code\u003e overrides \u003ccode\u003edefault_target\u003c/code\u003e for Enter, repos only.\u003c/strong\u003e \u003ccode\u003ebin/action.sh\u003c/code\u003e exports it\nfor the \u003ccode\u003eopen-workspace\u003c/code\u003e / \u003ccode\u003eopen-tab\u003c/code\u003e / \u003ccode\u003eopen-split\u003c/code\u003e hot-path actions; \u003ccode\u003esrc/action.rs\u003c/code\u003e\n(\u003ccode\u003eforced_target\u003c/code\u003e + \u003ccode\u003eresolve_default_target\u003c/code\u003e) resolves it once in \u003ccode\u003emain\u003c/code\u003e and passes it to\n\u003ccode\u003edispatch\u003c/code\u003e. Enter on an \u003cstrong\u003eagent\u003c/strong\u003e or \u003cstrong\u003eworkspace\u003c/strong\u003e still focuses that entry — forcing a target\nonly changes where a \u003cem\u003erepo\u003c/em\u003e lands, matching the manifest's \"Pick a repo; Enter opens it in…\".\nInvalid values on either the env var or the config degrade to \u003ccode\u003eworkspace\u003c/code\u003e instead of erroring.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eZen cannot be built on \u003ccode\u003eherdr pane zoom\u003c/code\u003e, and this was measured.\u003c/strong\u003e Splitting a zoomed tab\n\u003cstrong\u003esilently cancels the zoom\u003c/strong\u003e (\u003ccode\u003ezoomed\u003c/code\u003e flips to \u003ccode\u003efalse\u003c/code\u003e the moment a gutter appears), and\n\u003ccode\u003epane layout\u003c/code\u003e on a zoomed tab reports the \u003cem\u003eunderlying\u003c/em\u003e rects rather than the rendered ones, so\ngutters sized from it land wrong. Zen therefore \u003ccode\u003epane move --new-tab\u003c/code\u003es the target instead —\nwhich preserves its \u003ccode\u003eterminal_id\u003c/code\u003e, so the process survives — and \u003cstrong\u003enever touches another pane\u003c/strong\u003e.\nDo not \"simplify\" zen back to zoom: it silently produces a tab with an uncentred pane and two\nstray shells. Two further counter-intuitive facts the centring depends on: \u003ccode\u003epane split\u003c/code\u003e can only\nplace a new pane \u003cstrong\u003eright or down\u003c/strong\u003e, and \u003ccode\u003e--ratio R\u003c/code\u003e gives \u003ccode\u003eR\u003c/code\u003e to the \u003cstrong\u003eexisting\u003c/strong\u003e pane, not the\nnew one — hence the swap in step 3 of \u003ccode\u003ezen::enter\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e\u003ccode\u003elayout.apply\u003c/code\u003e is destructive — never call it.\u003c/strong\u003e It looks like the natural way to restore a\ntab's layout, and given a tree of existing \u003ccode\u003epane_id\u003c/code\u003es it does \u003cstrong\u003enot\u003c/strong\u003e re-parent them: it builds\na \u003cem\u003enew\u003c/em\u003e tab full of \u003cem\u003enew\u003c/em\u003e panes and discards the originals, processes and all (measured against\n0.8.0 — it silently replaced three live panes with fresh shells). Its sibling \u003ccode\u003elayout.export\u003c/code\u003e is\nread-only and safe, and is what \u003ccode\u003ezen::sibling_anchor\u003c/code\u003e reads. This is why zen's restore is\n\u003ccode\u003epane move\u003c/code\u003e + \u003ccode\u003epane swap\u003c/code\u003e, and why a deeply nested tab restores approximately: there is no\nnon-destructive verb for \"insert at this point in the tree\". \u003ccode\u003eAnchor::exact\u003c/code\u003e carries that fact\nand the exit notifies rather than silently rearranging.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eherdr's chrome has no per-pane switch, so \u003ccode\u003ezen_chrome\u003c/code\u003e edits herdr's own config — and that\nis the only file outside the plugin anything here may write.\u003c/strong\u003e The sidebar, tab row, pane\nborders/gaps and scrollbars are global \u003ccode\u003e[ui]\u003c/code\u003e keys; \u003ccode\u003eherdr pane|tab|server|config --help\u003c/code\u003e and\nthe socket method list have nothing UI-shaped, and \u003ccode\u003eherdr config\u003c/code\u003e has no \u003ccode\u003eset\u003c/code\u003e, so\n\u003ccode\u003eserver reload-config\u003c/code\u003e after a \u003ccode\u003etoml_edit\u003c/code\u003e rewrite is the only lever. Two orderings are load\nbearing and easy to invert: \u003ccode\u003eenter\u003c/code\u003e \u003cstrong\u003esnapshots before it writes\u003c/strong\u003e and only then engages (last\nof the herdr work — a reload while the splits are settling lays the gutters out against a stale\nframe), and \u003ccode\u003eleave\u003c/code\u003e \u003cstrong\u003erestores before it clears\u003c/strong\u003e, keeping the snapshot when herdr refuses so\n\u003ccode\u003ezen chrome-restore\u003c/code\u003e can retry. The snapshot is its own state file (\u003ccode\u003ezen.chrome.tsv\u003c/code\u003e) rather\nthan part of the session record precisely because it must outlive the session. \u003ccode\u003eenter\u003c/code\u003e never\nre-snapshots over a leftover snapshot: that would record zen's own values as the user's and\nlose the way home for good. Default is \u003ccode\u003eoff\u003c/code\u003e. Tests may exercise every level, because the test\nbuild points \u003ccode\u003echrome::config_path\u003c/code\u003e at its scratch directory (see the coverage rule below); a\ntest that writes that scratch herdr config holds \u003ccode\u003eCHROME_LOCK\u003c/code\u003e in \u003ccode\u003ezen.rs\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e\u003ccode\u003esocket.rs\u003c/code\u003e is a deliberate exception to the \u003ccode\u003eCommandRunner\u003c/code\u003e rule, not a precedent.\u003c/strong\u003e\n\u003ccode\u003epane.graphics.*\u003c/code\u003e is absent from \u003ccode\u003eherdr pane --help\u003c/code\u003e and reachable only over the socket, so the\ngutter scrim has no CLI path. Everything else must keep shelling out through \u003ccode\u003eCommandRunner\u003c/code\u003e,\nwhich is what keeps the IO edge mockable. herdr composites the scrim \u003cstrong\u003eopaque\u003c/strong\u003e regardless of the\nalpha byte, so there is no translucency knob to add — and the scrim is painted over \u003cem\u003eparked\ngutters\u003c/em\u003e, never over live panes, because a pane that redraws would punch through it.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTwo build profiles, because two consumers want opposite things.\u003c/strong\u003e \u003ccode\u003erelease\u003c/code\u003e stays\n\u003ccode\u003eopt-level = \"s\"\u003c/code\u003e with no LTO: it is what \u003ccode\u003ebin/picker.sh\u003c/code\u003e falls back to for an offline install or\na linked checkout, compiled on the user's machine while they wait for a pane. \u003ccode\u003edist\u003c/code\u003e (\u003ccode\u003eopt-level = 3\u003c/code\u003e, thin LTO, one codegen unit) is what \u003ccode\u003e.github/workflows/release.yml\u003c/code\u003e ships, where the\ncompile time is CI's and the run time is the installer's. Archives are packaged from\n\u003ccode\u003etarget/\u0026lt;triple\u0026gt;/dist/\u003c/code\u003e; \u003ccode\u003ebin/lib.sh\u003c/code\u003e still builds and reads \u003ccode\u003etarget/release/\u003c/code\u003e. Do not collapse\nthem — either the local fallback gets eight times slower or every shipped binary gets slower.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNothing is excluded from the coverage denominator, and the gate is 98%.\u003c/strong\u003e Some code genuinely\ncannot run under a unit test — \u003ccode\u003esurface::run\u003c/code\u003e and \u003ccode\u003epreroll\u003c/code\u003e claiming a real terminal, the\n\u003ccode\u003eexec\u003c/code\u003e that replaces the process, a stdin prompt's wrapper — and it still counts against\n\u003ccode\u003eMINIMUM\u003c/code\u003e in \u003ccode\u003ebin/coverage.sh\u003c/code\u003e. An exclusion list (or \u003ccode\u003e#[cfg(not(test))]\u003c/code\u003e, which is one in\ndisguise) is a second thing to argue about and a place for the number to quietly stop meaning\nwhat it says; the answer to a low file is a test, or an honest seam. The seams that exist are\nnarrow and each replaces something a test has no business starting: \u003ccode\u003esurface::Host\u003c/code\u003e\n(\u003ccode\u003eTerminalHost\u003c/code\u003e in production, \u003ccode\u003eScriptedHost\u003c/code\u003e driving the real host loop on a \u003ccode\u003eTestBackend\u003c/code\u003e),\ninjected runners on every mode and background step, \u003ccode\u003efn\u003c/code\u003e pointers for the clipboard, URL\nopener, typed confirmations, process replacement, and Zen's chrome restore, prompts that read\nany \u003ccode\u003eBufRead\u003c/code\u003e, \u003ccode\u003ePortWorker::seeded\u003c/code\u003e, and \u003ccode\u003eCatalogWorker::disconnected\u003c/code\u003e. A test that would fire a\nreal notification uses \u003ccode\u003eNotifier::silent\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eTests never touch the developer's machine state.\u003c/strong\u003e In the test build, \u003ccode\u003estate::state_dir\u003c/code\u003e, the\nplugin's \u003ccode\u003econfig::config_path\u003c/code\u003e, \u003ccode\u003echrome::config_path\u003c/code\u003e (herdr's config), and the herdr socket all\nresolve under \u003ccode\u003estate::test_scratch()\u003c/code\u003e, one directory per test process, and \u003ccode\u003etrace\u003c/code\u003e always writes\nto a scratch log. A background step once reached the real \u003ccode\u003ereview_archive::set\u003c/code\u003e from a test and\nleft a fixture slug in the developer's archive; that class of leak is now structurally\nimpossible. The real path rules are pure \u003ccode\u003e*_from\u003c/code\u003e functions tested on their own. Never add a\ntest that reads or writes \u003ccode\u003e$HOME\u003c/code\u003e directly — take the directory as a parameter instead, as\n\u003ccode\u003ecodex::load_from\u003c/code\u003e and \u003ccode\u003eclaude::load_with\u003c/code\u003e do.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eVersion sync:\u003c/strong\u003e \u003ccode\u003eCargo.toml\u003c/code\u003e and \u003ccode\u003eherdr-plugin.toml\u003c/code\u003e versions must match; \u003ccode\u003etests/manifest_spec.sh\u003c/code\u003e\nenforces it. \u003ccode\u003ebin/release.sh\u003c/code\u003e bumps both, so bump through it rather than by hand.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThe changelog is the release notes.\u003c/strong\u003e Every user-facing change adds a line to\n\u003ccode\u003eCHANGELOG.md\u003c/code\u003e's \u003ccode\u003e[Unreleased]\u003c/code\u003e section \u003cem\u003ein the same commit\u003c/em\u003e; \u003ccode\u003ebin/release.sh\u003c/code\u003e promotes that\nsection to a dated one and tags. The tag workflow builds four native archives, generates\n\u003ccode\u003eSHA256SUMS\u003c/code\u003e, and publishes that section verbatim after all targets pass. Commits are not\nConventional Commits and nothing comes from \u003ccode\u003egit log\u003c/code\u003e — an empty \u003ccode\u003e[Unreleased]\u003c/code\u003e aborts.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eNo launch or navigation hot path waits on the network.\u003c/strong\u003e \u003ccode\u003eupdate.rs\u003c/code\u003e spawns a detached\n\u003ccode\u003e--update-check\u003c/code\u003e child (own process group, no stdio) that runs \u003ccode\u003egit ls-remote\u003c/code\u003e and writes a cache;\nthe Projects Picker only reads that file, so the badge lands on a \u003cem\u003elater\u003c/em\u003e launch.\nDo not \"simplify\" this into a thread: the picker frequently exits in under a second and the fetch\ntakes several, so the cache would never be written. \u003ccode\u003egit ls-remote\u003c/code\u003e uses Git's HTTPS transport\non purpose — no \u003ccode\u003ejq\u003c/code\u003e, no 60/hour unauthenticated API limit, no auth. Everything fails silently.\nGit's pull-request row may call \u003ccode\u003egh pr list\u003c/code\u003e, but only after explicit activation and through a\nbackground effect. Clone/update commands may fetch because the user invoked that work directly.\nThe \u003ccode\u003eusage\u003c/code\u003e pane is allowed to fetch \u003cem\u003ewhile you watch\u003c/em\u003e because it exists to answer a question\nwhose only correct answer is the current one, and it is a pane you opened on purpose rather than\na hot path — but it still never blocks the first frame: the offline provider is loaded before\nthe terminal is claimed, the networked one runs on a worker thread bounded by\n\u003ccode\u003eusage.timeout_ms\u003c/code\u003e, and its card sits in \u003ccode\u003eSlot::Loading\u003c/code\u003e until the answer arrives. No other\nsurface may read a credential or add an in-process HTTP client.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e\u003ccode\u003eusage\u003c/code\u003e is the only code that reads a credential, and the token must never reach argv.\u003c/strong\u003e\n\u003ccode\u003eargv\u003c/code\u003e is readable through \u003ccode\u003eps\u003c/code\u003e by every process the user owns, for the whole life of the call,\nso \u003ccode\u003eClaude::fetch\u003c/code\u003e hands \u003ccode\u003ecurl\u003c/code\u003e its \u003ccode\u003eAuthorization\u003c/code\u003e header through stdin as a \u003ccode\u003e--config -\u003c/code\u003e file.\nThat is the entire reason \u003ccode\u003eCommandRunner::output_stdin\u003c/code\u003e exists — do not add a second caller\nwithout the same justification, and do not \"tidy\" the header back into a \u003ccode\u003e-H\u003c/code\u003e flag. The token is\nnever cached, written, traced, or drawn; \u003ccode\u003ethe_token_reaches_curl_through_stdin_and_never_through_argv\u003c/code\u003e\nin \u003ccode\u003eusage.rs\u003c/code\u003e pins it down by asserting the secret is absent from \u003ccode\u003erunner.calls()\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThe account line reads credential-adjacent files, and reads only named, non-secret labels.\u003c/strong\u003e\nCodex exposes no command that prints its address, so \u003ccode\u003eidentity_from_codex_auth\u003c/code\u003e decodes the ID\ntoken in \u003ccode\u003e~/.codex/auth.json\u003c/code\u003e — payload only, signature unverified on purpose, because these are\nlabels and nothing here trusts them. It takes exactly two claims: \u003ccode\u003eemail\u003c/code\u003e, and\n\u003ccode\u003echatgpt_subscription_active_until\u003c/code\u003e under the namespaced \u003ccode\u003ehttps://api.openai.com/auth\u003c/code\u003e claim\n(the \u003ccode\u003erenews\u003c/code\u003e row). One read and one decode for both, which is why \u003ccode\u003ecodex_account\u003c/code\u003e became\n\u003ccode\u003ecodex_identity\u003c/code\u003e. The access and refresh tokens sitting beside them in that file are read past\nand dropped: never log, draw, or forward anything from it but those two values. Claude's address\nand plan come from \u003ccode\u003e~/.claude.json\u003c/code\u003e, an ordinary settings file. \u003ccode\u003ebase64url_decode\u003c/code\u003e is hand-rolled\nand refuses padded input; do not swap in a base64 crate for sixty-four characters.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eA renewal date is shown only when it is a fact, never when it is arithmetic.\u003c/strong\u003e Codex publishes\none; Anthropic publishes none anywhere local — \u003ccode\u003e~/.claude.json\u003c/code\u003e carries \u003ccode\u003esubscriptionCreatedAt\u003c/code\u003e\nand \u003ccode\u003ebillingType: apple_subscription\u003c/code\u003e, and the usage endpoint carries no period end, so a Claude\nrenewal could only be a monthly-anniversary guess against a date Apple actually owns. The card\nsays \u003ccode\u003eunknown\u003c/code\u003e instead. \u003ccode\u003eformat_renewal\u003c/code\u003e also answers \u003ccode\u003eunknown\u003c/code\u003e for a date already \u003cstrong\u003epast\u003c/strong\u003e: the\nCodex claim only refreshes while Codex runs, so a machine left alone for a month still holds the\nprevious period's date, and a stale date under a heading that says \u003cem\u003erenews\u003c/em\u003e reads as one that is\ncoming — wrong in the reassuring direction, which is the failure this popup exists to prevent.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eA quota card grades by the provider's word when it has one.\u003c/strong\u003e Claude's usage endpoint ships a\n\u003ccode\u003eseverity\u003c/code\u003e per limit and Codex ships none, so \u003ccode\u003ewindow_color\u003c/code\u003e takes \u003ccode\u003eSeverity\u003c/code\u003e when present and\nfalls back to \u003ccode\u003eusage.warn_percent\u003c/code\u003e/\u003ccode\u003ealert_percent\u003c/code\u003e otherwise. Yes, that means two cards can\ncolour by two different rules — deliberately: the provider knows what its own plan considers\nclose to the edge, and a threshold invented here does not. \u003ccode\u003elimits[]\u003c/code\u003e and the named buckets share\nno id, so \u003ccode\u003eclaude_severities\u003c/code\u003e joins them on the rounded percentage; a weak key whose worst case\nis two windows at the same percentage sharing a colour that is correct for both.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eEvery usage card is laid out to the same row heights.\u003c/strong\u003e \u003ccode\u003edraw\u003c/code\u003e computes one \u003ccode\u003eCardRows\u003c/code\u003e from the\nbusiest slot and hands it to every card, because sizing per card puts a one-window provider's\ndonut at a different height from a four-window provider's, and two cards that do not line up read\nas two unrelated widgets. \u003ccode\u003eevery_card_puts_its_rows_at_the_same_height\u003c/code\u003e pins it. The fact lists\nare built once, by \u003ccode\u003ecard_facts\u003c/code\u003e, and used for \u003cem\u003eboth\u003c/em\u003e the count and the render — a row that the\ndrawing layer appends (\u003ccode\u003erenews\u003c/code\u003e) but the sizing layer does not count is a card one row too short.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eLocal time comes from \u003ccode\u003edate +%z\u003c/code\u003e, once per refresh.\u003c/strong\u003e \u003ccode\u003estd\u003c/code\u003e has no local-time API and there is\nno date crate here, so \u003ccode\u003elocal_offset\u003c/code\u003e shells out through \u003ccode\u003eCommandRunner\u003c/code\u003e and \u003ccode\u003eformat_clock\u003c/code\u003e does\nthe civil-calendar arithmetic. An unreadable offset degrades to UTC — wrong by hours, never wrong\nabout which number resets. Do not add a time zone crate for one line of one card.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eA quota percentage is used as reported, never rescaled.\u003c/strong\u003e Both sources were measured on a real\naccount: Codex writes \u003ccode\u003eused_percent: 41.0\u003c/code\u003e and the usage endpoint answers \u003ccode\u003eutilization: 51.0\u003c/code\u003e.\nAn earlier \u003ccode\u003enormalize_utilization\u003c/code\u003e guessed that anything at or below \u003ccode\u003e1.0\u003c/code\u003e was a fraction and\nmultiplied by 100 — which reads a genuine \u003ccode\u003e0.8%\u003c/code\u003e, the state of every plan just after its window\nrolls over, as \u003ccode\u003e80%\u003c/code\u003e. \u003ccode\u003eclamp_percent\u003c/code\u003e only clamps. Guessing a scale fails silently and in the\nalarming direction; do not reintroduce it.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThe update flow fails closed.\u003c/strong\u003e \u003ccode\u003ebin/update-plugin.sh\u003c/code\u003e installs only when herdr reports\nan unambiguous \u003ccode\u003e\"source\":{\"kind\":\"github\"…}\u003c/code\u003e; local links, unreadable output, and shapes it\ndoes not recognise all refuse. The failure it must never make is the permissive one —\n\u003ccode\u003eherdr plugin install\u003c/code\u003e would overwrite a contributor's working tree. \u003ccode\u003etests/update_guard_spec.sh\u003c/code\u003e\nstubs \u003ccode\u003eherdr\u003c/code\u003e through \u003ccode\u003eHERDR_BIN_PATH\u003c/code\u003e and asserts every case. Never widen the guard without\nextending that spec, and never name a real mutating command inside backticks in it.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eAn update must force a rebuild.\u003c/strong\u003e \u003ccode\u003etarget/\u003c/code\u003e is gitignored, so re-fetching the source leaves\nthe old binary in place and \u003ccode\u003ebin/picker.sh\u003c/code\u003e only builds when the binary is \u003cem\u003emissing\u003c/em\u003e — the new\ncode would ship with the old switcher still running. \u003ccode\u003eupdate-plugin.sh\u003c/code\u003e removes it and rebuilds.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProjects \u003ccode\u003ectrl-x\u003c/code\u003e (remove) requires typed confirmation.\u003c/strong\u003e Repositories use their name on the\nrestored terminal; linked worktrees use their name in a modal overlay, or \u003ccode\u003eforce \u0026lt;name\u0026gt;\u003c/code\u003e when\nForce is explicitly selected. Git revalidates the linked worktree before removal; main and\nlocked worktrees refuse, branch deletion only uses \u003ccode\u003e-d\u003c/code\u003e, and partial branch failure still drops\nthe removed worktree from the list. Never cancel a pending removal or substitute \u003ccode\u003erm -rf\u003c/code\u003e for\nGit's metadata cleanup. Preserve these guards; test against disposable repos.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003ePane commands must launch through \u003ccode\u003e$HERDR_PLUGIN_ROOT\u003c/code\u003e\u003c/strong\u003e — \u003ccode\u003etests/manifest_spec.sh\u003c/code\u003e asserts the\nexact manifest string, since herdr starts panes from the user's repo, not the plugin checkout.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eConventions\u003c/h2\u003e\u003ca id=\"user-content-conventions\" class=\"anchor\" aria-label=\"Permalink: Conventions\" href=\"#conventions\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eRustfmt defaults; \u003ccode\u003eanyhow::Result\u003c/code\u003e with typed errors; no \u003ccode\u003eunwrap()\u003c/code\u003e in production paths. Bash uses\n\u003ccode\u003e#!/usr/bin/env bash\u003c/code\u003e, \u003ccode\u003eset -euo pipefail\u003c/code\u003e, quoted expansions, and helpers from \u003ccode\u003ebin/lib.sh\u003c/code\u003e.\nTOML keys are snake_case; plugin action ids are kebab-case. Commits are short and imperative;\n\u003ccode\u003ebin/release.sh\u003c/code\u003e makes the \u003ccode\u003eRelease vX.Y.Z\u003c/code\u003e commit, so do not hand-tag subjects like \u003ccode\u003e(v0.4.0)\u003c/code\u003e\nthe way pre-0.5.0 commits did. Never commit \u003ccode\u003etarget/\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch2 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eAgent skills\u003c/h2\u003e\u003ca id=\"user-content-agent-skills\" class=\"anchor\" aria-label=\"Permalink: Agent skills\" href=\"#agent-skills\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eIssue tracker\u003c/h3\u003e\u003ca id=\"user-content-issue-tracker\" class=\"anchor\" aria-label=\"Permalink: Issue tracker\" href=\"#issue-tracker\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eLocal markdown — issues and specs live as files under \u003ccode\u003e.scratch/\u0026lt;feature\u0026gt;/\u003c/code\u003e in this repo\n(gitignored). See \u003ccode\u003edocs/agents/issue-tracker.md\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eTriage labels\u003c/h3\u003e\u003ca id=\"user-content-triage-labels\" class=\"anchor\" aria-label=\"Permalink: Triage labels\" href=\"#triage-labels\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eThe five canonical roles (\u003ccode\u003eneeds-triage\u003c/code\u003e, \u003ccode\u003eneeds-info\u003c/code\u003e, \u003ccode\u003eready-for-agent\u003c/code\u003e, \u003ccode\u003eready-for-human\u003c/code\u003e,\n\u003ccode\u003ewontfix\u003c/code\u003e), used as-is. See \u003ccode\u003edocs/agents/triage-labels.md\u003c/code\u003e.\u003c/p\u003e\n\u003cdiv class=\"markdown-heading\" dir=\"auto\"\u003e\u003ch3 tabindex=\"-1\" class=\"heading-element\" dir=\"auto\"\u003eDomain docs\u003c/h3\u003e\u003ca id=\"user-content-domain-docs\" class=\"anchor\" aria-label=\"Permalink: Domain docs\" href=\"#domain-docs\"\u003e\u003csvg data-component=\"Octicon\" class=\"octicon octicon-link\" viewBox=\"0 0 16 16\" version=\"1.1\" width=\"16\" height=\"16\" aria-hidden=\"true\"\u003e\u003cpath d=\"m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z\"\u003e\u003c/path\u003e\u003c/svg\u003e\u003c/a\u003e\u003c/div\u003e\n\u003cp dir=\"auto\"\u003eSingle-context — \u003ccode\u003eCONTEXT.md\u003c/code\u003e + \u003ccode\u003edocs/adr/\u003c/code\u003e at the repo root. See \u003ccode\u003edocs/agents/domain.md\u003c/code\u003e.\u003c/p\u003e\n\u003c/article\u003e","richTextTruncated":false,"renderedFileInfo":null,"symbols":{"timed_out":false,"not_analyzed":false,"symbols":[{"name":"CLAUDE.md","fully_qualified_name":"CLAUDE.md","kind":"section_1","ident_start":2,"ident_end":11,"extent_start":0,"extent_end":43740,"ident_utf16":{"start":{"line_number":0,"utf16_col":2},"end":{"line_number":0,"utf16_col":11}},"extent_utf16":{"start":{"line_number":0,"utf16_col":0},"end":{"line_number":516,"utf16_col":0}}},{"name":"What this is","fully_qualified_name":"What this is","kind":"section_2","ident_start":120,"ident_end":132,"extent_start":117,"extent_end":1367,"ident_utf16":{"start":{"line_number":4,"utf16_col":3},"end":{"line_number":4,"utf16_col":15}},"extent_utf16":{"start":{"line_number":4,"utf16_col":0},"end":{"line_number":21,"utf16_col":0}}},{"name":"Commands","fully_qualified_name":"Commands","kind":"section_2","ident_start":1370,"ident_end":1378,"extent_start":1367,"extent_end":3031,"ident_utf16":{"start":{"line_number":21,"utf16_col":3},"end":{"line_number":21,"utf16_col":11}},"extent_utf16":{"start":{"line_number":21,"utf16_col":0},"end":{"line_number":48,"utf16_col":0}}},{"name":"Architecture","fully_qualified_name":"Architecture","kind":"section_2","ident_start":3034,"ident_end":3046,"extent_start":3031,"extent_end":5324,"ident_utf16":{"start":{"line_number":48,"utf16_col":3},"end":{"line_number":48,"utf16_col":15}},"extent_utf16":{"start":{"line_number":48,"utf16_col":0},"end":{"line_number":82,"utf16_col":0}}},{"name":"Non-obvious constraints","fully_qualified_name":"Non-obvious constraints","kind":"section_2","ident_start":5327,"ident_end":5350,"extent_start":5324,"extent_end":42823,"ident_utf16":{"start":{"line_number":82,"utf16_col":3},"end":{"line_number":82,"utf16_col":26}},"extent_utf16":{"start":{"line_number":82,"utf16_col":0},"end":{"line_number":493,"utf16_col":0}}},{"name":"Conventions","fully_qualified_name":"Conventions","kind":"section_2","ident_start":42826,"ident_end":42837,"extent_start":42823,"extent_end":43278,"ident_utf16":{"start":{"line_number":493,"utf16_col":3},"end":{"line_number":493,"utf16_col":14}},"extent_utf16":{"start":{"line_number":493,"utf16_col":0},"end":{"line_number":501,"utf16_col":0}}},{"name":"Agent skills","fully_qualified_name":"Agent skills","kind":"section_2","ident_start":43281,"ident_end":43293,"extent_start":43278,"extent_end":43740,"ident_utf16":{"start":{"line_number":501,"utf16_col":3},"end":{"line_number":501,"utf16_col":15}},"extent_utf16":{"start":{"line_number":501,"utf16_col":0},"end":{"line_number":516,"utf16_col":0}}},{"name":"Issue tracker","fully_qualified_name":"Issue tracker","kind":"section_3","ident_start":43299,"ident_end":43312,"extent_start":43295,"extent_end":43456,"ident_utf16":{"start":{"line_number":503,"utf16_col":4},"end":{"line_number":503,"utf16_col":17}},"extent_utf16":{"start":{"line_number":503,"utf16_col":0},"end":{"line_number":508,"utf16_col":0}}},{"name":"Triage labels","fully_qualified_name":"Triage labels","kind":"section_3","ident_start":43460,"ident_end":43473,"extent_start":43456,"extent_end":43630,"ident_utf16":{"start":{"line_number":508,"utf16_col":4},"end":{"line_number":508,"utf16_col":17}},"extent_utf16":{"start":{"line_number":508,"utf16_col":0},"end":{"line_number":513,"utf16_col":0}}},{"name":"Domain docs","fully_qualified_name":"Domain docs","kind":"section_3","ident_start":43634,"ident_end":43645,"extent_start":43630,"extent_end":43740,"ident_utf16":{"start":{"line_number":513,"utf16_col":4},"end":{"line_number":513,"utf16_col":15}},"extent_utf16":{"start":{"line_number":513,"utf16_col":0},"end":{"line_number":516,"utf16_col":0}}}]}},"codeViewLayoutRoute":{"repo":{"id":1302250949,"defaultBranch":"main","name":"herdr-switchboard","ownerLogin":"crafts69guy","currentUserCanPush":false,"isFork":false,"isEmpty":false,"createdAt":"2026-07-16T03:05:50.000Z","ownerAvatar":"https://avatars.githubusercontent.com/u/64419455?v=4","public":true,"private":false,"isOrgOwned":false,"isArchived":false},"currentUser":null,"uploadToken":"7X4F2lmZqAmYIG9ICSJi3DYgQlyqoiXCNPvtqTXkZrpp2nVbzo0dWgWTdtnb6pHgLNkqo-7eKH5z2mzC-c_dsA","allShortcutsEnabled":false,"treeExpanded":true,"path":"CLAUDE.md","symbolsExpanded":false,"refInfo":{"name":"main","listCacheKey":"v0:1791528190.0","canEdit":false,"currentOid":"c17dc57bb61bdbf8042bbf7581a516bc179588e8"},"helpUrl":"https://docs.github.com","githubDevUrl":null},"codeViewFileTreeLayoutRoute":{"fileTree":{"":{"items":[{"name":".github","path":".github","contentType":"directory"},{"name":"bin","path":"bin","contentType":"directory"},{"name":"demo","path":"demo","contentType":"directory"},{"name":"docs","path":"docs","contentType":"directory"},{"name":"examples","path":"examples","contentType":"directory"},{"name":"src","path":"src","contentType":"directory"},{"name":"tests","path":"tests","contentType":"directory"},{"name":".gitignore","path":".gitignore","contentType":"file"},{"name":"AGENTS.md","path":"AGENTS.md","contentType":"file"},{"name":"CHANGELOG.md","path":"CHANGELOG.md","contentType":"file"},{"name":"CLAUDE.md","path":"CLAUDE.md","contentType":"file"},{"name":"CONTEXT.md","path":"CONTEXT.md","contentType":"file"},{"name":"Cargo.lock","path":"Cargo.lock","contentType":"file"},{"name":"Cargo.toml","path":"Cargo.toml","contentType":"file"},{"name":"LICENSE","path":"LICENSE","contentType":"file"},{"name":"README.md","path":"README.md","contentType":"file"},{"name":"herdr-plugin.toml","path":"herdr-plugin.toml","contentType":"file"}],"totalCount":17}},"fileTreeProcessingTime":13.532245999999999,"foldersToFetch":[]},"codeViewBlobLayoutRoute":{"codeLineWrapEnabled":false,"refInfo":{"name":"main","listCacheKey":"v0:1791528190.0","canEdit":false,"refType":"branch","currentOid":"c17dc57bb61bdbf8042bbf7581a516bc179588e8","canEditOnDefaultBranch":false,"fileExistsOnDefault":true},"path":"CLAUDE.md","blob":{"copilotSWEAgentEnabled":false,"dependabotInfo":{"showConfigurationBanner":false,"configFilePath":null,"networkDependabotPath":"/crafts69guy/herdr-switchboard/network/updates","dismissConfigurationNoticePath":"/settings/dismiss-notice/dependabot_configuration_notice","configurationNoticeDismissed":null},"displayName":"CLAUDE.md","displayUrl":"https://github.com/crafts69guy/herdr-switchboard/blob/main/CLAUDE.md?raw=true","headerInfo":{"blobSize":"42.7 KB","deleteTooltip":"You must be signed in to make or propose changes","editTooltip":"You must be signed in to make or propose changes","ghDesktopPath":"https://desktop.github.com","isGitLfs":false,"onBranch":true,"shortPath":"4796b8b","siteNavLoginPath":"/login?return_to=https%3A%2F%2Fgithub.com%2Fcrafts69guy%2Fherdr-switchboard%2Fblob%2Fmain%2FCLAUDE.md","isCSV":false,"isRichtext":true,"lineInfo":{"truncatedLoc":"516","truncatedSloc":"491"},"mode":"file"},"image":false,"isCodeownersFile":null,"isPlain":false,"isValidLegacyIssueTemplate":false,"isIssueTemplate":false,"isDiscussionTemplate":false,"language":"Markdown","languageID":222,"large":false,"planSupportInfo":{"repoIsFork":null,"repoOwnedByCurrentUser":null,"requestFullPath":"/crafts69guy/herdr-switchboard/blob/main/CLAUDE.md","showFreeOrgGatedFeatureMessage":null,"showPlanSupportBanner":null,"upgradeDataAttributes":null,"upgradePath":null},"publishBannersInfo":{"dismissActionNoticePath":"/settings/dismiss-notice/publish_action_from_dockerfile","releasePath":"/crafts69guy/herdr-switchboard/releases/new?marketplace=true","showPublishActionBanner":false},"rawBlobUrl":"https://github.com/crafts69guy/herdr-switchboard/raw/refs/heads/main/CLAUDE.md","renderImageOrRaw":false,"shortPath":null,"symbolsEnabled":true,"tabSize":4,"topBannersInfo":{"overridingGlobalFundingFile":false,"globalPreferredFundingPath":null,"showInvalidCitationWarning":false,"citationHelpUrl":"https://docs.github.com/github/creating-cloning-and-archiving-repositories/creating-a-repository-on-github/about-citation-files","actionsOnboardingTip":null},"truncated":false,"viewable":true,"workflowRedirectUrl":null},"copilotInfo":null,"copilotAccessAllowed":false,"copilotSpacesEnabled":false,"modelsAccessAllowed":false,"modelsRepoIntegrationEnabled":false,"isMarketplaceEnabled":true},"codeViewBlobLayoutRoute.StyledBlob":{"rawLines":["# CLAUDE.md","","This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.","","## What this is","","A [herdr](https://herdr.dev) plugin providing a unified switcher over running herdr **agents**,","open herdr **workspaces**, **ghq repos**, and linked Git **worktrees** in one fuzzy picker. It is a","Rust TUI (ratatui + nucleo), not an fzf wrapper. Every surface is a mode of the same binary,","selected by argv (`--menu`, `--agents`, `--usage`, `--commands`, `--ports`, `--zen`,","`--changelog`, `--settings`, `--git`; no flag is the switcher); the settings form is **also** a","floating overlay inside the switcher (⌥,), not only a pane. **`--usage` is the only mode that reads","a credential and the only in-process HTTP client** — both fenced, see the constraints below. Git","can fetch pull requests through `gh` only when that row is activated, and update checks use a","detached `git ls-remote` child. The **git menu is a herdr pane of its own** (`Prefix + g` →","`bin/git.sh` → `--git`), not an overlay on the switcher, and its selection `exec`s a review tool","over that pane. The review launcher (`bin/review.sh`, which runs","`tuicr`/`lazygit`), the guarded updater, and `bin/picker.sh`'s one-time bootstrap feedback are the","Bash terminal owners. The plugin needs no fzf.","See `README.md` for user-facing keybindings and configuration.","","## Commands","","```bash","cargo build                                  # debug binary","cargo build --release                        # what bin/picker.sh actually launches","cargo test                                   # unit tests (sorting, group filter, history parsing)","cargo test recent_sort_puts_latest_opened_first   # single test by name","bash bin/check.sh                            # complete local/CI/release gate","bash bin/coverage.sh                         # line coverage, gated at 98% (CI runs this too)","bash bin/coverage.sh --open                  # ... and open the annotated HTML report","bash bin/release.sh 0.5.0                    # cut a release (gates, bump, changelog, tag, gh release)","","herdr plugin link /path/to/herdr-switchboard         # install this checkout for manual testing","herdr server reload-config                   # after touching keybindings/config","herdr plugin config-dir switchboard          # where the runtime config.toml lives","```","","`bin/check.sh` is the single full-gate interface for local sessions, CI, and releases. Layout,","keybinding, or Herdr CLI changes still need manual exercise in a real Herdr session in addition to","Rust render tests.","","Coverage is deliberately **not** part of `check.sh`: it needs its own instrumented build, which","would turn the ~5s gate you run constantly into a ~90s one. CI runs `bin/coverage.sh` as a separate","job. It needs `rustup component add llvm-tools-preview` and `cargo install cargo-llvm-cov --locked`;","the script prefers a rustup toolchain when one carries the tools, because a Homebrew rust can sit","first on PATH beside a perfectly good rustup toolchain and only the latter can instrument.","","## Architecture","","**Two layers, joined by environment variables.** Every action starts in bash and may end in Rust:","","1. `bin/action.sh` is the single entrypoint for all manifest actions. It maps the action id","   (via `HERDR_PLUGIN_ACTION_ID`) to a pane id (`picker` / `git` / `get` overlays, `changelog`","   popup) and its placement, captures the **origin pane id and cwd** before the pane steals focus,","   and passes them forward as","   `SWITCHBOARD_ORIGIN_PANE_ID` / `SWITCHBOARD_ORIGIN_CWD` on `herdr plugin pane open`. The `git` action opens the","   dedicated `git` pane; that pane acts on a **cwd**, not a pane id.","2. `bin/picker.sh` resolves a versioned, checksummed release binary for managed installs and","   falls back to Cargo for offline/linked checkouts. Its Bash typing-cat owns first-run feedback;","   `--prepare` resolves the binary without launching it.","3. The TUI (`src/`) claims the terminal and draws the final Projects chrome immediately with a","   static `Standing by…` state while a feature-local worker loads the catalogue. Completion returns","   through a typed, generation-tagged effect; an empty initial result opens the Clone form.","   `surface::run` hosts the Projects surface and guarantees terminal","   restoration before an open outcome runs. Interactive accepts (repository remove","   confirmation, `ghq get -u` output) deliberately run on the restored terminal. Linked-worktree","   removal instead confirms in a modal TUI overlay and runs through a typed background effect.","","**Why the origin pane matters:** `split` and `pane` targets act on the captured `SWITCHBOARD_ORIGIN_PANE_ID`.","The overlay pane is _not_ the user's pane. Never guess or infer a pane/workspace/agent id — every id","must come from `herdr agent list`, `herdr workspace list`, or the captured origin.","","**Module ownership:** current file ownership and module seams live only in","`docs/architecture.md`. Keep this file focused on non-obvious invariants; when moving or","splitting code, update the architecture document in the same commit and run","`bash tests/docs_spec.sh`.","","**Sort vs. search:** fuzzy score always wins while a query is present; `SortMode` (recent/name/kind)","only orders the resting, no-query list. Both paths honour the `GroupFilter`. Ties break on load","order so the list stays stable.","","## Non-obvious constraints","","- **herdr draws the pane frame; the TUI must not compete with it.** Every plugin pane is","  `popup` or `overlay`, and herdr frames both and requires a non-empty title. So a pane","  title is a **single icon** (`󰊢`, `󰍜`, `󰆍`, `󰛳`) and the human-readable mode name goes on","  the *list panel* inside — word titles on both produced `Ports` twice, two rows apart.","  For the same reason the plugin's own borders recede in `overlay0` while herdr's frame","  keeps the accent. **Background policy belongs only to `tui::SurfaceBackground`:**","  `common.transparency = \"transparent\"` clears every root and floating card to the terminal","  default, while `\"opaque\"` fills every one with `panel_bg`. A renderer never hand-writes","  `Clear` or `.bg(panel_bg)` for a surface. `panel_bg` remains the foreground ink on coloured","  pills and mode chips in either mode. Tests in `picker.rs`, `projects.rs`, and `git.rs`","  (`the_search_box_is_captioned_search_and_the_list_carries_the_mode_title`,","  `panels_use_the_projects_pickers_border_and_caption_slots`,","  `no_panel_paints_an_opaque_background`, and the opaque-mode contracts) pin this down.","- **There is one panel frame, `tui::framed`, and every framed surface goes through it or","  through `tui::boxed`** (the same frame plus a caption, and defined in terms of it, so the","  border style is spelled once). It lived in `ui.rs` while `picker.rs` hand-rolled its own","  `Block`s, and the two drifted exactly as you would expect: accent borders instead of","  `overlay0`, and captions passed as bare `\u0026str` so they rendered in the terminal's default","  foreground rather than `title_color`. `git.rs` drifted the same way and went further, filling","  all three of its cards with `panel_bg` — the transparency bug that shipped in 1.2.0. A new","  framed surface calls `boxed`, or `framed` when its caption slot holds something richer than a","  word (the switcher's tab strip); it does not build a `Block` itself.","- **The git menu is a pane, and a review `exec`s over that pane.** There is a manifest pane for","  the *menu* (`[[panes]] id = \"git\"`), but **none for the review**: `git::main` `exec`s","  `bin/review.sh` over itself, so tuicr","  inherits the pane and quitting it returns to the pane `Prefix + g` was pressed in. The pane's","  placement must stay **full-frame `overlay`** — tuicr renders into whatever window it is handed,","  and a popup would hand it a tiny one. The picker knows nothing about git: there is no `⌥g`, no","  `Accept::Git`, no `App::git`. Two entry points would drift apart, and only one of them can be","  the fast one. `tuicr` is a TUI — never run it non-interactively (it blocks); only ever in a pane.","- **Saved-review integration never takes ownership of tuicr content.** A handoff is a pointer-only,","  non-blocking effect whose inputs are the repository, session slug, and a pane id returned by","  `herdr agent list`; delivery uses `herdr agent prompt` without `--wait`. Archive state contains","  only exact session slugs and changes Switchboard visibility, never tuicr's session JSON. Comment","  bodies never enter Switchboard state, logs, notifications, or another command line.","  `docs/git-menu.md` owns the user-facing archive, target-selection, and fallback behaviour.","- **Agent handoffs share one target seam and never wait for a turn.** `agent_handoff.rs` is the only","  owner of promptable-agent parsing, same-worktree/origin selection, and `herdr agent prompt`;","  neither Git nor Projects adds `--wait`. Projects sends only JSON-escaped item kind, label, and","  absolute path as data-only context. Paths and labels never enter notifications or traces, and a","  Workspace never pretends its several pane directories are one selectable path.","- **Projects catalogue discovery is a feature-local background effect.** Startup draws the final","  Search/Context/Navigator/Preview geometry first and shows static `Standing by…`; it accepts only","  Close until the generation-tagged completion arrives. Settings Apply keeps the old rows visible","  under `Refreshing…`, locks selection-dependent actions, and restores selection by entry ID.","  There is no minimum-visible floor. Repository and worktree discovery share one `ghq list --full-path`","  snapshot, and per-repository worktree probes use at most four threads while their results are","  installed in snapshot order. Full paths are retained across all ghq roots; durable IDs stay","  relative to the longest matching root. An empty initial catalogue opens the Clone form in place.","- **Clone never asks for credentials in the TUI.** Git/SSH use configured credential helpers","  and agents with interactive prompts disabled. The URL form rejects embedded credentials;","  external clone output is never drawn, traced, or logged. Cancellation stops and reaps the","  entire child process group before allowing another clone, and never deletes partial directories.","  Default completion refreshes/selects; explicit `clone.open_after = true` returns a typed open","  outcome so Herdr work still runs after terminal restoration.","- **Projects stars are durable-entry state, not another source.** Only Repo and Worktree identities","  can be starred; Agent and Workspace IDs are live and must never enter the persistent set. The","  final Starred group filters the already-loaded catalogue and keeps its search, sort, and actions.","  `projects::stars` owns typed identity and mutation; `state` owns the private tempfile, atomic","  replace, and cross-process lock around the complete read-modify-write transaction. Writes return","  through a typed Projects effect before the reducer changes the marker or list. Missing or","  malformed state degrades to no stars and must never block the first Projects frame.","- **The pre-build cat runs before Rust exists and sizes itself from the plugin PTY.**","  `run_with_splash` reads `stty size \u003c/dev/tty` and passes those cells to `bootstrap_frame` on each","  animation frame. Do not replace it with `tput`: redirecting `tput` away from the TTY makes it","  return terminfo's 80x24 default in a wide Herdr pane. Horizontal padding is spaces; vertical","  padding is rows. `tests/bootstrap_spec.sh` pins both coordinates.","- **A list fetch runs outside `Git::on_key` and off the input thread.** `on_key` returns a `Step`;","  `GitSurface` turns `Step::Load` and `Step::CountFiles` into typed background effects, then applies","  their results from `on_tick`. That keeps the key interface IO-free and unit-testable through","  `MockRunner`, while `gh pr list` leaves the menu responsive instead of freezing a half-drawn list.","- **Nothing writes to tuicr's config.** The theme is a whole file that","  [hue-theme](https://github.com/crafts69guy/hue-theme) owns","  (`~/.config/tuicr/themes/hue-\u003cmood\u003e.toml`, 41 keys, none optional). tuicr **exits 2** on a theme","  it cannot fully resolve, and `--theme` on a mismatched name takes the whole review path down —","  so `bin/review.sh` never passes `--theme` and `ensure_tuicr` only checks the binary exists.","- **Open + config live in Rust.** The clone form uses the same restored open dispatch as Projects;","  `bin/get.sh` only launches `--clone`. The `open` and `config get` CLI interfaces remain available,","  so the Herdr open verbs (`src/action.rs::open_target`) and typed config reader (`Config::load`)","  live in one place. `bin/lib.sh` keeps `ensure_built` (build-on-demand, shared by the picker entrypoints),","  `toml_get` (used only by `configure_notifications`, the pre-build notification path that must not","  depend on a cargo build), and the pane-context/JSON helpers. **A change to how a target opens","  lands only in `action.rs`.**","- **fnm activation is opt-in, local, and post-selection.** `[fnm].enabled` defaults off. Preview","  reads declarations from disk only; `fnm exec --using \u003crepo\u003e -- printenv PATH` runs after an open","  is accepted, never installs a version, and never performs network work. Fresh targets receive","  that PATH through Herdr's `--env` and never receive post-create terminal input; shell startup","  owns session-local initialization and must preserve the launch PATH or activate the initial cwd.","  The current-pane target remains `cd`-only and relies on fnm's standard `--use-on-cd` shell hook.","- **The Node Versions manager is the only explicit fnm mutation surface.** It loads installed","  versions locally, runs `fnm list-remote` on a worker only after the user opens the dedicated","  pane, and performs install/default/uninstall after terminal restoration. `use` is sent to the","  captured origin pane because a child process cannot change its parent shell; uninstall requires","  the exact selected version as typed confirmation.","- **Settings has two presentations, not two renderers.** The embedded form is a centred floating","  card because it overlays Projects. The standalone action already lives in a Herdr-framed popup,","  so it draws the same form full-area with a content margin and no second border or duplicate","  title. Both presentations share the columns, tabs, hit zones, hints, and command bar.","- **Configuration is typed and namespaced.** `config.rs` deserializes the section structs with","  `deny_unknown_fields`; Rust code reads those fields directly. `Config::value_for_cli` is the","  deliberately narrow compatibility seam for Bash's `config get` calls, not an internal","  lookup interface. `settings.rs` writes namespaced values through `toml_edit`, preserving comments","  and hand-added keys before validating the complete result. **Every picker has a `[keys.*]` table**","  — `projects`, `agents`, `commands`, `ports`, `zen`, `menu`, `fnm` — reached through","  `PickerMode::key_bindings` plus a `reload_config` that re-reads it; a mode that implements neither","  is one whose keys nobody can move, which is what Menu and the fnm manager silently were.","- **A click zone is measured by the loop that draws the thing.** `tab_zones` and","  `footer_zones` (`src/projects/view.rs`) are built inside the same loops that lay out the tab strip","  and the command bar, because a zone computed separately drifts the moment a label","  changes — and drifts _silently_, into clicking the wrong action. `list_state` is kept","  on the `App` for the same reason: its scroll offset is the only thing that turns a","  clicked row back into an entry, so it cannot be a fresh `ListState` per frame.","- **The cheatsheet's descriptions must fit `HELP_DESC`** (`src/projects/view.rs`) — the popup's half","  width less the key pill, around 19 columns. A longer one is cut with no ellipsis, so it","  ships looking like a shorter phrase; `wheel  Scroll whatever is under it` reached a","  README screenshot as `Scroll whatever is`. `row` asserts, and a `TestBackend` render","  test in `projects.rs` fires it.","- **A prefix names the kind of work, never the mode.** `^\u003ckey\u003e` acts on the selected row; `⌥\u003ckey\u003e`","  changes the view or the app (or is the heavier form of the `^` verb on the same letter, as","  Ports' `^x` TERM / `⌥x` KILL); `↵` runs the row's primary action with `^↵`/`⌥↵` as its variants.","  So **every modified chord appears in both `default_insert` and `default_normal` with the same","  action**, and Normal's bare letters are *aliases carrying the same letter*, never a respelling.","  Three tests in `keymap.rs` enforce exactly this and are the reason the layout stops drifting:","  `every_modified_chord_means_the_same_thing_in_both_modes`,","  `no_action_straddles_the_ctrl_and_alt_families`, and","  `a_bare_alias_carries_the_same_letter_as_its_chord`. Two vocabularies are carved out by name in","  `mode_idiomatic`: motion (readline in Insert, Vim in Normal) and query editing (`^u` clear,","  `⌥⌫` delete-word, Insert-only). `^u` and `^c` are reserved on every surface — no `ActionSpec`","  may take them, which is why the fnm manager's `use`/`install` sit on the `↵` ladder.","  **A chord that is somebody's multiplexer prefix never reaches the pane at all**, so opening in a","  tab is the mnemonic-free `^e`: herdr's default prefix is `^b` and `^t` is the usual tmux-refugee","  alternative, so the open group avoids both. `^b` is refused by","  `no_default_chord_takes_herdrs_prefix` and by the shared picker's check; do not \"fix\" `^e` into","  `^t`, and do not reclaim `^b` for anything.","  **There is no `␣` leader, and adding one back is the bug.** Space can only be a leader in Normal","  — in Insert it is a character the user is typing — so any group living there was forced to change","  prefix with the mode, which is the whole inconsistency this layout removes. The Git menu, the","  Central Menu, the settings form, and the Usage/changelog viewers sit outside the rule on purpose:","  their keys name a row, a destination, or a form field rather than a verb on a selection.","- **The shared picker answers five chords itself, and they live in one table.** `RESERVED`","  (`src/picker.rs`) holds `⌥,`, `⌥j`, `⌥k`, `⇥`, `⇧⇥`; `PickerSurface::on_key` dispatches from it","  through `reserved_for`, *ahead* of any `ActionSpec`. They used to be five hand-written `if`s that","  nothing checked against, so a mode declaring one of those chords had its action swallowed with no","  error — the same silent shape as Ports' `^w`, which shadowed delete-word for that picker alone.","  A new `ActionSpec` is therefore checked by `picker::assert_follows_prefix_concept`, which every","  mode calls from its **own** test module (the modes are private to their files, so the check","  travels to them). It refuses a bare `Char` (it would be matched ahead of the typing arm and make","  that letter untypeable), `^c`/`^u`, anything in `RESERVED`, a `key_label` that is not the chord it","  listens for, and a shared action id bound to a chord it does not carry elsewhere.","  `the_prefix_concept_check_rejects_every_shape_it_names` asserts the guard actually bites, because","  a guard that silently passes is the failure it exists to prevent.","- **One keypress gets one answer, and `same_chord` is where that is decided.** Matching weighs only","  CTRL and ALT, exactly as `keymap::chord_of` does: SHIFT is already baked into the character a","  terminal reports and terminals disagree about whether they set the bit too. `ActionSpec::matches`","  compared modifier bits with `==` while the keymap used `contains`, so the same press acted in","  Projects and did nothing in every other picker — `⇧↵` ran the row in one and was inert in the","  other, and a `^⇧` chord missed its `^` action outright. Because SHIFT no longer separates two","  chords, `assert_follows_prefix_concept` also refuses two specs that normalise to the same chord;","  without that rule the second one would simply never run.","- **Keys are a config-driven keymap, not hardcoded `match` arms.** `handle_key` resolves a","  `Chord` through `App::keymap` (`src/keymap.rs`) and runs `apply_action`. Two ordered tables","  (Insert + Normal); typed `common.keymode` defaults to Normal and `esc` toggles Insert↔Normal.","  `[keys.projects]` entries rebind actions (first chord wins as the shown one) into **both** tables,","  so an override cannot reintroduce a per-mode split.","  **The footer (`draw_footer`) and the cheatsheet (`draw_help`) render from the keymap via","  `Keymap::label_for(mode, action)`**, so both re-label per remap — never hardcode a","  key cap in either; add the action to the curated list and it picks up its live chord. A row","  whose action is unbound in the current mode drops out. `label_for` returns the *first* matching","  chord, which is why a bare alias is listed after the chord it shadows.","  Adding an action is one row in `keymap::NAMES`, its default chord in **both** tables, and an","  `apply_action` arm; a new `Accept` also needs the footer curated list and `dispatch`. Cheatsheet","  descriptions must still fit `HELP_DESC`.","- **One frame absorbs every event already queued, and a list row borrows rather than copies.**","  These two are one fact from opposite ends. A terminal delivers a wheel turn or a held key as a","  burst, and `surface::run` used to answer each with its own full repaint; meanwhile `draw_list`","  (`projects/view.rs`) and the shared picker's row builder cloned every column of every *filtered*","  entry per frame — including the rows a `List` scrolls past and never paints, over a Commands","  catalogue that is `commands.history_limit` (5,000) rows deep by default. So a burst multiplied a","  per-entry cost that was already linear. `drain_frame` now takes queued input up to","  `MAX_COALESCED_EVENTS` before repainting — the cap is what stops a paste from starving the","  screen — and rows borrow out of `state.items` / `picker.entries`, which is why both draw","  functions destructure their `\u0026mut` state into disjoint field borrows and why the shared picker","  moves its `ListState` out with `mem::take` before building rows. Padding comes from","  `tui::spaces`, a slice of one static. Do not \"tidy\" a row builder back to `to_string()`: it","  compiles, it looks identical, and it silently restores the whole cost.","- **`Stars::contains` and the tab counts must not allocate or rescan.** `contains` is asked once","  per entry per keystroke by the reducer, once per entry per group by the Context panel, and once","  per entry per frame by the list. It answers from `StarSet`, which stores one ID set *per kind* so","  the probe is a borrowed `\u0026str`; a `BTreeSet\u003cStarKey\u003e` cannot, because building the probe key","  means cloning the entry's ID. `StarKey` stays the on-disk shape, so the file is unchanged.","  Tab counts are cached on `Picker` and rebuilt by `recount` at the three points that can","  invalidate them — construction, `replace_stars`, `replace_entries` — never in `recompute`, which","  runs per keystroke and cannot change them. A stale cache here fails silently, so","  `tab_counts_are_rebuilt_whenever_the_entries_or_the_stars_change` checks every tab against a","  fresh scan.","- **A probe that a `read_dir` can rule out must not be a process.** `may_have_worktrees`","  (`data.rs`) asks whether `.git/worktrees/` has anything in it before spending a `git worktree","  list` on a repository, because that probe runs once per *ghq repository* — hundreds of forks for","  the handful of repositories that actually have linked worktrees. It **fails open**: a `.git`","  *file* (this path is itself a linked worktree or a submodule) and an unreadable directory both","  still probe, since a wrong \"no\" loses a worktree from the catalogue silently while a wrong \"yes\"","  costs one subprocess. `the_worktree_prefilter_only_refuses_what_the_filesystem_settles` pins","  every case.","- **Independent reads that each pay a process start are overlapped, and only those.**","  `projects/effect.rs` overlaps `ghq root` with `ghq list`, `source.rs` overlaps `herdr agent list`","  with `herdr workspace list`, and `repo_card` (`projects/preview.rs`) fans out branch, dirty","  state, last commit, and the `preview.sh` tree so the card costs the slowest rather than their","  sum. This is only sound because every one of them is an independent *read*. Nothing that mutates,","  and nothing whose result another call depends on, goes in a scope like these.","- **`state.rs` owns every durable write, and a read-modify-write is one locked transaction.**","  Five callers used to hand-roll `fs::write` to a **fixed** `.tmp` sibling and rename — so two","  Switchboard processes writing the same file raced on one temp name, and `history` and","  `review_archive`, which load-modify-write, silently erased each other's rows. All of them now go","  through `state`: `write_private` / `update_private` for this plugin's own state (owner-only), and","  `replace_atomically` for a file the *user* owns — its own `config.toml` and, for zen chrome,","  herdr's — which gains the lock and the unique tempfile but keeps the mode its owner gave it. A","  new persistent file adds no sixth implementation.","- **The mouse is turned on by hand, and must be turned off on every exit path.** `surface.rs`","  writes `?1000h`/`?1006h` itself rather than using crossterm's `EnableMouseCapture`, which","  also enables any-event tracking (`?1003h`) — every pointer move would wake the loop into","  a redraw for an event we discard. `?1000h` reports the wheel *and* buttons, which is","  exactly what every surface consumes; drags stay herdr's, which runs with","  `mouse_capture = true`. The universal host pairs claim/restore and","  chains the disable ahead of the panic hook `ratatui::init` installs,","  since that hook restores the screen but knows nothing about the mouse. Leaving it on","  drops mouse escapes into the user's shell. **Every new terminal mode implements `Surface` and","  runs through `surface::run`; it never calls `ratatui::init` or reads crossterm events itself.**","- **A click selects; a click on the already-selected row acts.** Terminals report no","  double-click (crossterm gives `Down` only), so single-click-to-run would let a stray","  click `exec` tuicr over a pane or write a setting, and a timestamp heuristic would put","  the same guesswork in five places. A command-bar pill carries the **key printed on its","  cap** as its payload and routes through `on_key`, so the label cannot drift from the","  behaviour. The rule is the same in `projects.rs`, `picker.rs`, `git.rs` and `settings.rs`;","  what is shared between them is `tui::zone_at`, the lookup — never the measurement, which","  stays in the loop that draws the thing.","- **Picker command bars may wrap, but their hit zones wrap with them.** `PickerMode` defaults to","  one action row; the Central Menu requests two because it exposes every direct route. The picker","  balances whole pills by their rendered widths, leaves one terminal row between wrapped rows,","  measures each row with `tui::pill_row`, and stores the row coordinate beside its zones. Never","  split or reposition the spans independently of those zones.","- **The preview clips; it must never wrap.** Every body goes through `clip`/`clip_line`","  (`src/projects/preview.rs`) so one card line is exactly one screen row — that is what makes","  `preview_scroll` mean what it says and `preview_len`/`preview_rows` bound it correctly.","  `draw_preview` therefore has no `Wrap`. Re-adding one, or emitting an unclipped line,","  breaks the scroll silently: the offset drifts from the content instead of erroring. The","  pane's width reaches the worker through `App::preview_width`, published by `projects/view.rs`, which is","  why `ProjectsSurface::after_draw` requests a preview only after the host has drawn geometry.","- **Nothing uses `jq` — keep it that way.** No code path shells out to it: the bash layer reads","  herdr's JSON with the awk-based `json_string_value` / `json_bool_value` in `bin/lib.sh`, and the","  Rust layer uses `serde_json` (`data.rs`, `projects/preview.rs`). It is not a documented requirement, so a","  new jq call would be a new hard dependency on a machine that may not have it — and a silent one,","  since a missing jq fails the same way a wrong filter does: empty output, no error.","- **`SWITCHBOARD_FORCE_TARGET` overrides `default_target` for Enter, repos only.** `bin/action.sh` exports it","  for the `open-workspace` / `open-tab` / `open-split` hot-path actions; `src/action.rs`","  (`forced_target` + `resolve_default_target`) resolves it once in `main` and passes it to","  `dispatch`. Enter on an **agent** or **workspace** still focuses that entry — forcing a target","  only changes where a _repo_ lands, matching the manifest's \"Pick a repo; Enter opens it in…\".","  Invalid values on either the env var or the config degrade to `workspace` instead of erroring.","- **Zen cannot be built on `herdr pane zoom`, and this was measured.** Splitting a zoomed tab","  **silently cancels the zoom** (`zoomed` flips to `false` the moment a gutter appears), and","  `pane layout` on a zoomed tab reports the *underlying* rects rather than the rendered ones, so","  gutters sized from it land wrong. Zen therefore `pane move --new-tab`s the target instead —","  which preserves its `terminal_id`, so the process survives — and **never touches another pane**.","  Do not \"simplify\" zen back to zoom: it silently produces a tab with an uncentred pane and two","  stray shells. Two further counter-intuitive facts the centring depends on: `pane split` can only","  place a new pane **right or down**, and `--ratio R` gives `R` to the **existing** pane, not the","  new one — hence the swap in step 3 of `zen::enter`.","- **`layout.apply` is destructive — never call it.** It looks like the natural way to restore a","  tab's layout, and given a tree of existing `pane_id`s it does **not** re-parent them: it builds","  a *new* tab full of *new* panes and discards the originals, processes and all (measured against","  0.8.0 — it silently replaced three live panes with fresh shells). Its sibling `layout.export` is","  read-only and safe, and is what `zen::sibling_anchor` reads. This is why zen's restore is","  `pane move` + `pane swap`, and why a deeply nested tab restores approximately: there is no","  non-destructive verb for \"insert at this point in the tree\". `Anchor::exact` carries that fact","  and the exit notifies rather than silently rearranging.","- **herdr's chrome has no per-pane switch, so `zen_chrome` edits herdr's own config — and that","  is the only file outside the plugin anything here may write.** The sidebar, tab row, pane","  borders/gaps and scrollbars are global `[ui]` keys; `herdr pane|tab|server|config --help` and","  the socket method list have nothing UI-shaped, and `herdr config` has no `set`, so","  `server reload-config` after a `toml_edit` rewrite is the only lever. Two orderings are load","  bearing and easy to invert: `enter` **snapshots before it writes** and only then engages (last","  of the herdr work — a reload while the splits are settling lays the gutters out against a stale","  frame), and `leave` **restores before it clears**, keeping the snapshot when herdr refuses so","  `zen chrome-restore` can retry. The snapshot is its own state file (`zen.chrome.tsv`) rather","  than part of the session record precisely because it must outlive the session. `enter` never","  re-snapshots over a leftover snapshot: that would record zen's own values as the user's and","  lose the way home for good. Default is `off`. Tests may exercise every level, because the test","  build points `chrome::config_path` at its scratch directory (see the coverage rule below); a","  test that writes that scratch herdr config holds `CHROME_LOCK` in `zen.rs`.","- **`socket.rs` is a deliberate exception to the `CommandRunner` rule, not a precedent.**","  `pane.graphics.*` is absent from `herdr pane --help` and reachable only over the socket, so the","  gutter scrim has no CLI path. Everything else must keep shelling out through `CommandRunner`,","  which is what keeps the IO edge mockable. herdr composites the scrim **opaque** regardless of the","  alpha byte, so there is no translucency knob to add — and the scrim is painted over *parked","  gutters*, never over live panes, because a pane that redraws would punch through it.","- **Two build profiles, because two consumers want opposite things.** `release` stays","  `opt-level = \"s\"` with no LTO: it is what `bin/picker.sh` falls back to for an offline install or","  a linked checkout, compiled on the user's machine while they wait for a pane. `dist` (`opt-level","  = 3`, thin LTO, one codegen unit) is what `.github/workflows/release.yml` ships, where the","  compile time is CI's and the run time is the installer's. Archives are packaged from","  `target/\u003ctriple\u003e/dist/`; `bin/lib.sh` still builds and reads `target/release/`. Do not collapse","  them — either the local fallback gets eight times slower or every shipped binary gets slower.","- **Nothing is excluded from the coverage denominator, and the gate is 98%.** Some code genuinely","  cannot run under a unit test — `surface::run` and `preroll` claiming a real terminal, the","  `exec` that replaces the process, a stdin prompt's wrapper — and it still counts against","  `MINIMUM` in `bin/coverage.sh`. An exclusion list (or `#[cfg(not(test))]`, which is one in","  disguise) is a second thing to argue about and a place for the number to quietly stop meaning","  what it says; the answer to a low file is a test, or an honest seam. The seams that exist are","  narrow and each replaces something a test has no business starting: `surface::Host`","  (`TerminalHost` in production, `ScriptedHost` driving the real host loop on a `TestBackend`),","  injected runners on every mode and background step, `fn` pointers for the clipboard, URL","  opener, typed confirmations, process replacement, and Zen's chrome restore, prompts that read","  any `BufRead`, `PortWorker::seeded`, and `CatalogWorker::disconnected`. A test that would fire a","  real notification uses `Notifier::silent`.","- **Tests never touch the developer's machine state.** In the test build, `state::state_dir`, the","  plugin's `config::config_path`, `chrome::config_path` (herdr's config), and the herdr socket all","  resolve under `state::test_scratch()`, one directory per test process, and `trace` always writes","  to a scratch log. A background step once reached the real `review_archive::set` from a test and","  left a fixture slug in the developer's archive; that class of leak is now structurally","  impossible. The real path rules are pure `*_from` functions tested on their own. Never add a","  test that reads or writes `$HOME` directly — take the directory as a parameter instead, as","  `codex::load_from` and `claude::load_with` do.","- **Version sync:** `Cargo.toml` and `herdr-plugin.toml` versions must match; `tests/manifest_spec.sh`","  enforces it. `bin/release.sh` bumps both, so bump through it rather than by hand.","- **The changelog is the release notes.** Every user-facing change adds a line to","  `CHANGELOG.md`'s `[Unreleased]` section _in the same commit_; `bin/release.sh` promotes that","  section to a dated one and tags. The tag workflow builds four native archives, generates","  `SHA256SUMS`, and publishes that section verbatim after all targets pass. Commits are not","  Conventional Commits and nothing comes from `git log` — an empty `[Unreleased]` aborts.","- **No launch or navigation hot path waits on the network.** `update.rs` spawns a detached","  `--update-check` child (own process group, no stdio) that runs `git ls-remote` and writes a cache;","  the Projects Picker only reads that file, so the badge lands on a _later_ launch.","  Do not \"simplify\" this into a thread: the picker frequently exits in under a second and the fetch","  takes several, so the cache would never be written. `git ls-remote` uses Git's HTTPS transport","  on purpose — no `jq`, no 60/hour unauthenticated API limit, no auth. Everything fails silently.","  Git's pull-request row may call `gh pr list`, but only after explicit activation and through a","  background effect. Clone/update commands may fetch because the user invoked that work directly.","  The `usage` pane is allowed to fetch *while you watch* because it exists to answer a question","  whose only correct answer is the current one, and it is a pane you opened on purpose rather than","  a hot path — but it still never blocks the first frame: the offline provider is loaded before","  the terminal is claimed, the networked one runs on a worker thread bounded by","  `usage.timeout_ms`, and its card sits in `Slot::Loading` until the answer arrives. No other","  surface may read a credential or add an in-process HTTP client.","- **`usage` is the only code that reads a credential, and the token must never reach argv.**","  `argv` is readable through `ps` by every process the user owns, for the whole life of the call,","  so `Claude::fetch` hands `curl` its `Authorization` header through stdin as a `--config -` file.","  That is the entire reason `CommandRunner::output_stdin` exists — do not add a second caller","  without the same justification, and do not \"tidy\" the header back into a `-H` flag. The token is","  never cached, written, traced, or drawn; `the_token_reaches_curl_through_stdin_and_never_through_argv`","  in `usage.rs` pins it down by asserting the secret is absent from `runner.calls()`.","- **The account line reads credential-adjacent files, and reads only named, non-secret labels.**","  Codex exposes no command that prints its address, so `identity_from_codex_auth` decodes the ID","  token in `~/.codex/auth.json` — payload only, signature unverified on purpose, because these are","  labels and nothing here trusts them. It takes exactly two claims: `email`, and","  `chatgpt_subscription_active_until` under the namespaced `https://api.openai.com/auth` claim","  (the `renews` row). One read and one decode for both, which is why `codex_account` became","  `codex_identity`. The access and refresh tokens sitting beside them in that file are read past","  and dropped: never log, draw, or forward anything from it but those two values. Claude's address","  and plan come from `~/.claude.json`, an ordinary settings file. `base64url_decode` is hand-rolled","  and refuses padded input; do not swap in a base64 crate for sixty-four characters.","- **A renewal date is shown only when it is a fact, never when it is arithmetic.** Codex publishes","  one; Anthropic publishes none anywhere local — `~/.claude.json` carries `subscriptionCreatedAt`","  and `billingType: apple_subscription`, and the usage endpoint carries no period end, so a Claude","  renewal could only be a monthly-anniversary guess against a date Apple actually owns. The card","  says `unknown` instead. `format_renewal` also answers `unknown` for a date already **past**: the","  Codex claim only refreshes while Codex runs, so a machine left alone for a month still holds the","  previous period's date, and a stale date under a heading that says *renews* reads as one that is","  coming — wrong in the reassuring direction, which is the failure this popup exists to prevent.","- **A quota card grades by the provider's word when it has one.** Claude's usage endpoint ships a","  `severity` per limit and Codex ships none, so `window_color` takes `Severity` when present and","  falls back to `usage.warn_percent`/`alert_percent` otherwise. Yes, that means two cards can","  colour by two different rules — deliberately: the provider knows what its own plan considers","  close to the edge, and a threshold invented here does not. `limits[]` and the named buckets share","  no id, so `claude_severities` joins them on the rounded percentage; a weak key whose worst case","  is two windows at the same percentage sharing a colour that is correct for both.","- **Every usage card is laid out to the same row heights.** `draw` computes one `CardRows` from the","  busiest slot and hands it to every card, because sizing per card puts a one-window provider's","  donut at a different height from a four-window provider's, and two cards that do not line up read","  as two unrelated widgets. `every_card_puts_its_rows_at_the_same_height` pins it. The fact lists","  are built once, by `card_facts`, and used for *both* the count and the render — a row that the","  drawing layer appends (`renews`) but the sizing layer does not count is a card one row too short.","- **Local time comes from `date +%z`, once per refresh.** `std` has no local-time API and there is","  no date crate here, so `local_offset` shells out through `CommandRunner` and `format_clock` does","  the civil-calendar arithmetic. An unreadable offset degrades to UTC — wrong by hours, never wrong","  about which number resets. Do not add a time zone crate for one line of one card.","- **A quota percentage is used as reported, never rescaled.** Both sources were measured on a real","  account: Codex writes `used_percent: 41.0` and the usage endpoint answers `utilization: 51.0`.","  An earlier `normalize_utilization` guessed that anything at or below `1.0` was a fraction and","  multiplied by 100 — which reads a genuine `0.8%`, the state of every plan just after its window","  rolls over, as `80%`. `clamp_percent` only clamps. Guessing a scale fails silently and in the","  alarming direction; do not reintroduce it.","- **The update flow fails closed.** `bin/update-plugin.sh` installs only when herdr reports","  an unambiguous `\"source\":{\"kind\":\"github\"…}`; local links, unreadable output, and shapes it","  does not recognise all refuse. The failure it must never make is the permissive one —","  `herdr plugin install` would overwrite a contributor's working tree. `tests/update_guard_spec.sh`","  stubs `herdr` through `HERDR_BIN_PATH` and asserts every case. Never widen the guard without","  extending that spec, and never name a real mutating command inside backticks in it.","- **An update must force a rebuild.** `target/` is gitignored, so re-fetching the source leaves","  the old binary in place and `bin/picker.sh` only builds when the binary is _missing_ — the new","  code would ship with the old switcher still running. `update-plugin.sh` removes it and rebuilds.","- **Projects `ctrl-x` (remove) requires typed confirmation.** Repositories use their name on the","  restored terminal; linked worktrees use their name in a modal overlay, or `force \u003cname\u003e` when","  Force is explicitly selected. Git revalidates the linked worktree before removal; main and","  locked worktrees refuse, branch deletion only uses `-d`, and partial branch failure still drops","  the removed worktree from the list. Never cancel a pending removal or substitute `rm -rf` for","  Git's metadata cleanup. Preserve these guards; test against disposable repos.","- **Pane commands must launch through `$HERDR_PLUGIN_ROOT`** — `tests/manifest_spec.sh` asserts the","  exact manifest string, since herdr starts panes from the user's repo, not the plugin checkout.","","## Conventions","","Rustfmt defaults; `anyhow::Result` with typed errors; no `unwrap()` in production paths. Bash uses","`#!/usr/bin/env bash`, `set -euo pipefail`, quoted expansions, and helpers from `bin/lib.sh`.","TOML keys are snake_case; plugin action ids are kebab-case. Commits are short and imperative;","`bin/release.sh` makes the `Release vX.Y.Z` commit, so do not hand-tag subjects like `(v0.4.0)`","the way pre-0.5.0 commits did. Never commit `target/`.","","## Agent skills","","### Issue tracker","","Local markdown — issues and specs live as files under `.scratch/\u003cfeature\u003e/` in this repo","(gitignored). See `docs/agents/issue-tracker.md`.","","### Triage labels","","The five canonical roles (`needs-triage`, `needs-info`, `ready-for-agent`, `ready-for-human`,","`wontfix`), used as-is. See `docs/agents/triage-labels.md`.","","### Domain docs","","Single-context — `CONTEXT.md` + `docs/adr/` at the repo root. See `docs/agents/domain.md`."],"stylingDirectives":[[[0,11,"pl-mh"],[2,11,"pl-en"]],[],[],[],[[0,15,"pl-mh"],[3,15,"pl-en"]],[],[[2,3,"pl-s"],[8,9,"pl-s"],[9,10,"pl-s"],[10,27,"pl-corl"],[27,28,"pl-s"],[84,86,"pl-s"],[92,94,"pl-s"]],[[11,13,"pl-s"],[23,25,"pl-s"],[27,29,"pl-s"],[38,40,"pl-s"],[57,59,"pl-s"],[68,70,"pl-s"]],[],[[18,19,"pl-s"],[19,25,"pl-c1"],[25,26,"pl-s"],[28,29,"pl-s"],[29,37,"pl-c1"],[37,38,"pl-s"],[40,41,"pl-s"],[41,48,"pl-c1"],[48,49,"pl-s"],[51,52,"pl-s"],[52,62,"pl-c1"],[62,63,"pl-s"],[65,66,"pl-s"],[66,73,"pl-c1"],[73,74,"pl-s"],[76,77,"pl-s"],[77,82,"pl-c1"],[82,83,"pl-s"]],[[0,1,"pl-s"],[1,12,"pl-c1"],[12,13,"pl-s"],[15,16,"pl-s"],[16,26,"pl-c1"],[26,27,"pl-s"],[29,30,"pl-s"],[30,35,"pl-c1"],[35,36,"pl-s"],[85,87,"pl-s"],[91,93,"pl-s"]],[[60,62,"pl-s"],[62,63,"pl-s"],[63,70,"pl-c1"],[70,71,"pl-s"]],[[48,50,"pl-s"]],[[32,33,"pl-s"],[33,35,"pl-c1"],[35,36,"pl-s"]],[[9,10,"pl-s"],[10,23,"pl-c1"],[23,24,"pl-s"],[36,38,"pl-s"],[73,75,"pl-s"],[77,78,"pl-s"],[78,88,"pl-c1"],[88,89,"pl-s"]],[[0,1,"pl-s"],[1,11,"pl-c1"],[11,12,"pl-s"],[15,16,"pl-s"],[16,21,"pl-c1"],[21,22,"pl-s"],[75,76,"pl-s"],[76,80,"pl-c1"],[80,81,"pl-s"]],[[37,38,"pl-s"],[38,51,"pl-c1"],[51,52,"pl-s"]],[[0,1,"pl-s"],[1,6,"pl-c1"],[6,7,"pl-s"],[8,9,"pl-s"],[9,16,"pl-c1"],[16,17,"pl-s"],[45,46,"pl-s"],[46,59,"pl-c1"],[59,60,"pl-s"]],[],[[4,5,"pl-s"],[5,14,"pl-c1"],[14,15,"pl-s"]],[],[[0,11,"pl-mh"],[3,11,"pl-en"]],[],[[0,3,"pl-s"],[3,7,"pl-en"]],[[45,59,"pl-c"],[45,46,"pl-c"]],[[45,83,"pl-c"],[45,46,"pl-c"]],[[6,10,"pl-c1"],[45,98,"pl-c"],[45,46,"pl-c"]],[[6,10,"pl-c1"],[50,71,"pl-c"],[50,51,"pl-c"]],[[45,77,"pl-c"],[45,46,"pl-c"]],[[45,93,"pl-c"],[45,46,"pl-c"]],[[45,85,"pl-c"],[45,46,"pl-c"]],[[45,102,"pl-c"],[45,46,"pl-c"]],[],[[53,95,"pl-c"],[53,54,"pl-c"]],[[45,80,"pl-c"],[45,46,"pl-c"]],[[45,82,"pl-c"],[45,46,"pl-c"]],[[0,3,"pl-s"]],[],[[0,1,"pl-s"],[1,13,"pl-c1"],[13,14,"pl-s"]],[],[],[],[[25,27,"pl-s"],[30,32,"pl-s"],[41,42,"pl-s"],[42,50,"pl-c1"],[50,51,"pl-s"]],[[15,16,"pl-s"],[50,51,"pl-s"],[68,69,"pl-s"],[69,84,"pl-c1"],[84,85,"pl-s"]],[[14,15,"pl-s"],[15,54,"pl-c1"],[54,55,"pl-s"],[60,61,"pl-s"],[61,98,"pl-c1"],[98,99,"pl-s"]],[],[],[],[[0,15,"pl-mh"],[3,15,"pl-en"]],[],[[0,2,"pl-s"],[46,48,"pl-s"]],[],[[0,1,"pl-s"],[1,2,"pl-v"],[3,4,"pl-s"],[4,17,"pl-c1"],[17,18,"pl-s"]],[[8,9,"pl-s"],[9,31,"pl-c1"],[31,32,"pl-s"],[48,49,"pl-s"],[49,55,"pl-c1"],[55,56,"pl-s"],[59,60,"pl-s"],[60,63,"pl-c1"],[63,64,"pl-s"],[67,68,"pl-s"],[68,71,"pl-c1"],[71,72,"pl-s"],[83,84,"pl-s"],[84,93,"pl-c1"],[93,94,"pl-s"]],[[42,44,"pl-s"],[66,68,"pl-s"]],[],[[3,4,"pl-s"],[4,30,"pl-c1"],[30,31,"pl-s"],[34,35,"pl-s"],[35,57,"pl-c1"],[57,58,"pl-s"],[62,63,"pl-s"],[63,85,"pl-c1"],[85,86,"pl-s"],[92,93,"pl-s"],[93,96,"pl-c1"],[96,97,"pl-s"]],[[13,14,"pl-s"],[14,17,"pl-c1"],[17,18,"pl-s"],[45,47,"pl-s"],[50,52,"pl-s"]],[[0,1,"pl-s"],[1,2,"pl-v"],[3,4,"pl-s"],[4,17,"pl-c1"],[17,18,"pl-s"]],[],[[3,4,"pl-s"],[4,13,"pl-c1"],[13,14,"pl-s"]],[[0,1,"pl-s"],[1,2,"pl-v"],[12,13,"pl-s"],[13,17,"pl-c1"],[17,18,"pl-s"]],[[10,11,"pl-s"],[11,23,"pl-c1"],[23,24,"pl-s"]],[],[[3,4,"pl-s"],[4,16,"pl-c1"],[16,17,"pl-s"]],[],[[17,18,"pl-s"],[18,28,"pl-c1"],[28,29,"pl-s"]],[],[],[[0,2,"pl-s"],[30,32,"pl-s"],[33,34,"pl-s"],[34,39,"pl-c1"],[39,40,"pl-s"],[45,46,"pl-s"],[46,50,"pl-c1"],[50,51,"pl-s"],[80,81,"pl-s"],[81,107,"pl-c1"],[107,108,"pl-s"]],[[20,21,"pl-s"],[24,25,"pl-s"]],[[15,16,"pl-s"],[16,32,"pl-c1"],[32,33,"pl-s"],[35,36,"pl-s"],[36,56,"pl-c1"],[56,57,"pl-s"]],[],[[0,2,"pl-s"],[19,21,"pl-s"]],[[0,1,"pl-s"],[1,21,"pl-c1"],[21,22,"pl-s"]],[],[[0,1,"pl-s"],[1,24,"pl-c1"],[24,25,"pl-s"]],[],[[0,2,"pl-s"],[18,20,"pl-s"],[71,72,"pl-s"],[72,80,"pl-c1"],[80,81,"pl-s"]],[[62,63,"pl-s"],[63,74,"pl-c1"],[74,75,"pl-s"]],[],[],[[0,26,"pl-mh"],[3,26,"pl-en"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[65,67,"pl-s"]],[[2,3,"pl-s"],[3,8,"pl-c1"],[8,9,"pl-s"],[13,14,"pl-s"],[14,21,"pl-c1"],[21,22,"pl-s"]],[[13,15,"pl-s"],[26,28,"pl-s"],[30,31,"pl-s"],[31,33,"pl-c1"],[33,34,"pl-s"],[36,37,"pl-s"],[37,39,"pl-c1"],[39,40,"pl-s"],[42,43,"pl-s"],[43,45,"pl-c1"],[45,46,"pl-s"],[48,49,"pl-s"],[49,51,"pl-c1"],[51,52,"pl-s"]],[[6,7,"pl-s"],[17,18,"pl-s"],[57,58,"pl-s"],[58,63,"pl-c1"],[63,64,"pl-s"]],[[57,58,"pl-s"],[58,66,"pl-c1"],[66,67,"pl-s"]],[[20,22,"pl-s"],[56,57,"pl-s"],[57,79,"pl-c1"],[79,80,"pl-s"],[81,83,"pl-s"]],[[2,3,"pl-s"],[3,38,"pl-c1"],[38,39,"pl-s"]],[[17,18,"pl-s"],[18,26,"pl-c1"],[26,27,"pl-s"],[49,50,"pl-s"],[50,58,"pl-c1"],[58,59,"pl-s"]],[[2,3,"pl-s"],[3,8,"pl-c1"],[8,9,"pl-s"],[13,14,"pl-s"],[14,27,"pl-c1"],[27,28,"pl-s"],[44,45,"pl-s"],[45,53,"pl-c1"],[53,54,"pl-s"]],[[48,49,"pl-s"],[49,58,"pl-c1"],[58,59,"pl-s"],[61,62,"pl-s"],[62,73,"pl-c1"],[73,74,"pl-s"],[80,81,"pl-s"],[81,87,"pl-c1"],[87,88,"pl-s"]],[[3,4,"pl-s"],[4,74,"pl-c1"],[74,75,"pl-s"]],[[2,3,"pl-s"],[3,59,"pl-c1"],[59,60,"pl-s"]],[[2,3,"pl-s"],[3,39,"pl-c1"],[39,40,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[30,31,"pl-s"],[31,42,"pl-c1"],[42,43,"pl-s"]],[[10,11,"pl-s"],[11,21,"pl-c1"],[21,22,"pl-s"],[22,24,"pl-s"]],[[45,46,"pl-s"],[46,51,"pl-c1"],[51,52,"pl-s"],[59,60,"pl-s"],[60,69,"pl-c1"],[69,70,"pl-s"]],[[2,3,"pl-s"],[3,8,"pl-c1"],[8,9,"pl-s"]],[[2,3,"pl-s"],[3,11,"pl-c1"],[11,12,"pl-s"],[42,43,"pl-s"],[43,47,"pl-c1"],[47,48,"pl-s"]],[[25,26,"pl-s"],[26,37,"pl-c1"],[37,38,"pl-s"],[40,41,"pl-s"],[41,47,"pl-c1"],[47,48,"pl-s"]],[[30,31,"pl-s"],[31,39,"pl-c1"],[39,40,"pl-s"]],[[23,24,"pl-s"],[24,29,"pl-c1"],[29,30,"pl-s"],[35,36,"pl-s"],[36,42,"pl-c1"],[42,43,"pl-s"]],[[55,56,"pl-s"],[56,61,"pl-c1"],[61,62,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[41,42,"pl-s"],[42,46,"pl-c1"],[46,47,"pl-s"],[64,66,"pl-s"]],[[6,7,"pl-s"],[11,12,"pl-s"],[14,15,"pl-s"],[15,35,"pl-c1"],[35,36,"pl-s"],[43,45,"pl-s"],[64,66,"pl-s"],[68,69,"pl-s"],[69,78,"pl-c1"],[78,79,"pl-s"],[80,81,"pl-s"],[81,85,"pl-c1"],[85,86,"pl-s"]],[[2,3,"pl-s"],[3,16,"pl-c1"],[16,17,"pl-s"]],[[56,57,"pl-s"],[57,67,"pl-c1"],[67,68,"pl-s"]],[[22,24,"pl-s"],[35,36,"pl-s"],[36,43,"pl-c1"],[43,44,"pl-s"],[44,46,"pl-s"]],[[88,89,"pl-s"],[89,91,"pl-c1"],[91,92,"pl-s"]],[[2,3,"pl-s"],[3,14,"pl-c1"],[14,15,"pl-s"],[20,21,"pl-s"],[21,29,"pl-c1"],[29,30,"pl-s"]],[[16,17,"pl-s"],[17,22,"pl-c1"],[22,23,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[68,70,"pl-s"]],[],[[2,3,"pl-s"],[3,19,"pl-c1"],[19,20,"pl-s"],[36,37,"pl-s"],[37,55,"pl-c1"],[55,56,"pl-s"],[65,66,"pl-s"],[66,72,"pl-c1"],[72,73,"pl-s"]],[],[],[[2,3,"pl-s"],[3,19,"pl-c1"],[19,20,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[67,69,"pl-s"],[70,71,"pl-s"],[71,87,"pl-c1"],[87,88,"pl-s"]],[[73,74,"pl-s"],[74,92,"pl-c1"],[92,93,"pl-s"]],[[32,33,"pl-s"],[33,39,"pl-c1"],[39,40,"pl-s"]],[],[],[[0,1,"pl-v"],[2,4,"pl-s"],[70,72,"pl-s"]],[[67,68,"pl-s"],[68,80,"pl-c1"],[80,81,"pl-s"]],[],[[8,9,"pl-s"],[9,20,"pl-c1"],[20,21,"pl-s"]],[[81,82,"pl-s"],[82,102,"pl-c1"],[102,103,"pl-s"]],[],[],[],[[0,1,"pl-v"],[2,4,"pl-s"],[48,50,"pl-s"]],[],[],[],[[49,50,"pl-s"],[50,73,"pl-c1"],[73,74,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[63,65,"pl-s"]],[],[],[[2,3,"pl-s"],[3,18,"pl-c1"],[18,19,"pl-s"],[54,55,"pl-s"],[55,60,"pl-c1"],[60,61,"pl-s"]],[],[],[],[[0,1,"pl-v"],[2,4,"pl-s"],[83,85,"pl-s"]],[[2,3,"pl-s"],[3,18,"pl-c1"],[18,19,"pl-s"],[26,27,"pl-s"],[27,46,"pl-c1"],[46,47,"pl-s"],[74,75,"pl-s"],[75,90,"pl-c1"],[90,91,"pl-s"]],[[42,43,"pl-s"],[43,47,"pl-c1"],[47,48,"pl-s"],[62,63,"pl-s"],[63,67,"pl-c1"],[67,68,"pl-s"]],[],[[19,20,"pl-s"],[20,43,"pl-c1"],[43,44,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[30,31,"pl-s"],[31,42,"pl-c1"],[42,43,"pl-s"],[69,71,"pl-s"],[72,73,"pl-s"],[73,79,"pl-c1"],[79,80,"pl-s"],[91,92,"pl-s"],[92,96,"pl-c1"],[96,97,"pl-s"]],[[2,3,"pl-s"],[3,13,"pl-c1"],[13,14,"pl-s"],[21,22,"pl-s"],[22,32,"pl-c1"],[32,33,"pl-s"],[38,39,"pl-s"],[39,55,"pl-c1"],[55,56,"pl-s"]],[[21,22,"pl-s"],[22,29,"pl-c1"],[29,30,"pl-s"]],[[2,3,"pl-s"],[3,13,"pl-c1"],[13,14,"pl-s"],[22,23,"pl-s"],[23,33,"pl-c1"],[33,34,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[37,39,"pl-s"]],[[2,3,"pl-s"],[12,13,"pl-s"],[13,14,"pl-s"],[14,54,"pl-corl"],[54,55,"pl-s"]],[[3,4,"pl-s"],[4,42,"pl-c1"],[42,43,"pl-s"],[76,78,"pl-s"],[85,87,"pl-s"]],[[31,32,"pl-s"],[32,39,"pl-c1"],[39,40,"pl-s"]],[[5,6,"pl-s"],[6,19,"pl-c1"],[19,20,"pl-s"],[34,35,"pl-s"],[35,42,"pl-c1"],[42,43,"pl-s"],[48,49,"pl-s"],[49,61,"pl-c1"],[61,62,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[31,33,"pl-s"]],[[2,3,"pl-s"],[3,13,"pl-c1"],[13,14,"pl-s"],[29,30,"pl-s"],[30,37,"pl-c1"],[37,38,"pl-s"],[44,45,"pl-s"],[45,49,"pl-c1"],[49,50,"pl-s"],[55,56,"pl-s"],[56,66,"pl-c1"],[66,67,"pl-s"]],[[27,28,"pl-s"],[28,54,"pl-c1"],[54,55,"pl-s"],[82,83,"pl-s"],[83,95,"pl-c1"],[95,96,"pl-s"]],[[21,22,"pl-s"],[22,32,"pl-c1"],[32,33,"pl-s"],[40,41,"pl-s"],[41,53,"pl-c1"],[53,54,"pl-s"]],[[2,3,"pl-s"],[3,11,"pl-c1"],[11,12,"pl-s"],[27,28,"pl-s"],[28,51,"pl-c1"],[51,52,"pl-s"]],[[63,65,"pl-s"]],[[16,17,"pl-s"],[17,26,"pl-c1"],[26,27,"pl-s"],[28,30,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[56,58,"pl-s"],[59,60,"pl-s"],[60,73,"pl-c1"],[73,74,"pl-s"]],[[37,38,"pl-s"],[38,78,"pl-c1"],[78,79,"pl-s"]],[],[[28,29,"pl-s"],[29,34,"pl-c1"],[34,35,"pl-s"]],[],[[34,35,"pl-s"],[35,37,"pl-c1"],[37,38,"pl-s"],[73,74,"pl-s"],[74,85,"pl-c1"],[85,86,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[72,74,"pl-s"]],[[25,26,"pl-s"],[26,41,"pl-c1"],[41,42,"pl-s"]],[[75,76,"pl-s"],[76,79,"pl-c1"],[79,80,"pl-s"]],[],[],[[0,1,"pl-v"],[2,4,"pl-s"],[54,56,"pl-s"]],[],[],[],[[0,1,"pl-v"],[2,4,"pl-s"],[42,44,"pl-s"],[45,46,"pl-s"],[46,55,"pl-c1"],[55,56,"pl-s"]],[[2,3,"pl-s"],[3,22,"pl-c1"],[22,23,"pl-s"],[64,65,"pl-s"],[65,86,"pl-c1"],[86,87,"pl-s"]],[[52,53,"pl-s"],[53,63,"pl-c1"],[63,64,"pl-s"]],[[20,21,"pl-s"],[21,32,"pl-c1"],[32,33,"pl-s"],[67,68,"pl-s"],[68,77,"pl-c1"],[77,78,"pl-s"]],[[61,63,"pl-s"],[82,83,"pl-s"],[83,91,"pl-c1"],[91,92,"pl-s"],[98,100,"pl-s"]],[[4,5,"pl-s"],[5,13,"pl-c1"],[13,14,"pl-s"],[16,17,"pl-s"],[17,23,"pl-c1"],[23,24,"pl-s"],[26,27,"pl-s"],[27,35,"pl-c1"],[35,36,"pl-s"],[38,39,"pl-s"],[39,44,"pl-c1"],[44,45,"pl-s"],[47,48,"pl-s"],[48,51,"pl-c1"],[51,52,"pl-s"],[54,55,"pl-s"],[55,59,"pl-c1"],[59,60,"pl-s"],[62,63,"pl-s"],[63,66,"pl-c1"],[66,67,"pl-s"]],[[2,3,"pl-s"],[3,27,"pl-c1"],[27,28,"pl-s"],[36,37,"pl-s"],[37,50,"pl-c1"],[50,51,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[62,64,"pl-s"],[65,66,"pl-s"],[66,75,"pl-c1"],[75,76,"pl-s"]],[[2,3,"pl-s"],[3,15,"pl-c1"],[15,16,"pl-s"],[18,19,"pl-s"],[19,39,"pl-c1"],[39,40,"pl-s"]],[],[[23,24,"pl-s"],[32,33,"pl-s"],[67,68,"pl-s"],[68,78,"pl-c1"],[78,79,"pl-s"]],[[9,10,"pl-s"],[10,13,"pl-c1"],[13,14,"pl-s"]],[[58,59,"pl-s"],[59,68,"pl-c1"],[68,69,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[43,44,"pl-s"],[44,53,"pl-c1"],[53,54,"pl-s"],[54,56,"pl-s"],[58,59,"pl-s"],[59,79,"pl-c1"],[79,80,"pl-s"]],[],[[39,40,"pl-s"],[40,74,"pl-c1"],[74,75,"pl-s"]],[[23,24,"pl-s"],[24,42,"pl-c1"],[42,43,"pl-s"],[45,46,"pl-s"],[46,49,"pl-c1"],[49,50,"pl-s"],[66,67,"pl-s"],[67,78,"pl-c1"],[78,79,"pl-s"]],[[10,11,"pl-s"],[11,22,"pl-c1"],[22,23,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[52,54,"pl-s"],[55,56,"pl-s"],[56,62,"pl-c1"],[62,63,"pl-s"],[90,91,"pl-s"],[91,97,"pl-c1"],[97,98,"pl-s"]],[[61,62,"pl-s"],[62,63,"pl-c1"],[63,64,"pl-s"]],[[9,10,"pl-s"],[10,12,"pl-c1"],[12,13,"pl-s"],[21,22,"pl-s"],[22,24,"pl-c1"],[24,25,"pl-s"],[33,34,"pl-s"],[34,35,"pl-c1"],[35,36,"pl-s"],[72,73,"pl-s"],[73,75,"pl-c1"],[75,76,"pl-s"],[77,78,"pl-s"],[78,80,"pl-c1"],[80,81,"pl-s"]],[[5,7,"pl-s"],[44,45,"pl-s"],[45,59,"pl-c1"],[59,60,"pl-s"],[65,66,"pl-s"],[66,80,"pl-c1"],[80,81,"pl-s"]],[[8,10,"pl-s"],[42,43,"pl-s"],[75,76,"pl-s"]],[[17,18,"pl-s"],[18,27,"pl-c1"],[27,28,"pl-s"]],[[2,3,"pl-s"],[3,58,"pl-c1"],[58,59,"pl-s"]],[[2,3,"pl-s"],[3,48,"pl-c1"],[48,49,"pl-s"]],[[2,3,"pl-s"],[3,52,"pl-c1"],[52,53,"pl-s"]],[[2,3,"pl-s"],[3,17,"pl-c1"],[17,18,"pl-s"],[82,83,"pl-s"],[83,85,"pl-c1"],[85,86,"pl-s"]],[[2,3,"pl-s"],[3,5,"pl-c1"],[5,6,"pl-s"],[34,35,"pl-s"],[35,37,"pl-c1"],[37,38,"pl-s"],[43,44,"pl-s"],[44,46,"pl-c1"],[46,47,"pl-s"],[83,84,"pl-s"],[84,94,"pl-c1"],[94,95,"pl-s"]],[[48,49,"pl-s"],[49,52,"pl-c1"],[52,53,"pl-s"],[54,55,"pl-s"],[55,62,"pl-c1"],[62,63,"pl-s"],[75,76,"pl-s"],[76,77,"pl-c1"],[77,78,"pl-s"]],[[2,4,"pl-s"],[79,81,"pl-s"]],[[27,28,"pl-s"],[28,30,"pl-c1"],[30,31,"pl-s"],[59,60,"pl-s"],[60,62,"pl-c1"],[62,63,"pl-s"],[68,69,"pl-s"],[69,71,"pl-c1"],[71,72,"pl-s"]],[[46,47,"pl-s"],[47,49,"pl-c1"],[49,50,"pl-s"]],[[2,3,"pl-s"],[3,39,"pl-c1"],[39,40,"pl-s"],[88,89,"pl-s"],[89,91,"pl-c1"],[91,92,"pl-s"]],[[2,3,"pl-s"],[3,5,"pl-c1"],[5,6,"pl-s"],[27,28,"pl-s"],[28,30,"pl-c1"],[30,31,"pl-s"]],[[2,4,"pl-s"],[16,17,"pl-s"],[17,18,"pl-c1"],[18,19,"pl-s"],[59,61,"pl-s"]],[],[],[],[],[[0,1,"pl-v"],[2,4,"pl-s"],[77,79,"pl-s"],[80,81,"pl-s"],[81,89,"pl-c1"],[89,90,"pl-s"]],[[3,4,"pl-s"],[4,17,"pl-c1"],[17,18,"pl-s"],[26,27,"pl-s"],[27,29,"pl-c1"],[29,30,"pl-s"],[32,33,"pl-s"],[33,35,"pl-c1"],[35,36,"pl-s"],[38,39,"pl-s"],[39,41,"pl-c1"],[41,42,"pl-s"],[44,45,"pl-s"],[45,46,"pl-c1"],[46,47,"pl-s"],[49,50,"pl-s"],[50,52,"pl-c1"],[52,53,"pl-s"],[55,56,"pl-s"],[56,77,"pl-c1"],[77,78,"pl-s"]],[[10,11,"pl-s"],[11,23,"pl-c1"],[23,24,"pl-s"],[26,27,"pl-s"],[32,33,"pl-s"],[41,42,"pl-s"],[42,52,"pl-c1"],[52,53,"pl-s"],[89,90,"pl-s"],[90,92,"pl-c1"],[92,93,"pl-s"]],[],[[42,43,"pl-s"],[43,45,"pl-c1"],[45,46,"pl-s"]],[[8,9,"pl-s"],[9,19,"pl-c1"],[19,20,"pl-s"],[45,46,"pl-s"],[46,83,"pl-c1"],[83,84,"pl-s"]],[[22,24,"pl-s"],[27,29,"pl-s"]],[[38,39,"pl-s"],[39,43,"pl-c1"],[43,44,"pl-s"]],[[27,28,"pl-s"],[28,30,"pl-c1"],[30,31,"pl-s"],[32,33,"pl-s"],[33,35,"pl-c1"],[35,36,"pl-s"],[50,51,"pl-s"],[51,59,"pl-c1"],[59,60,"pl-s"],[64,65,"pl-s"],[65,74,"pl-c1"],[74,75,"pl-s"]],[],[[2,3,"pl-s"],[3,56,"pl-c1"],[56,57,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[38,39,"pl-s"],[39,49,"pl-c1"],[49,50,"pl-s"],[76,78,"pl-s"]],[[27,28,"pl-s"],[28,44,"pl-c1"],[44,45,"pl-s"]],[[78,79,"pl-s"],[79,98,"pl-c1"],[98,99,"pl-s"]],[[30,31,"pl-s"],[31,33,"pl-c1"],[33,34,"pl-s"],[57,58,"pl-s"],[58,66,"pl-c1"],[66,67,"pl-s"]],[[51,52,"pl-s"],[52,54,"pl-c1"],[54,55,"pl-s"]],[[15,16,"pl-s"],[16,18,"pl-c1"],[18,19,"pl-s"],[37,38,"pl-s"],[38,39,"pl-c1"],[39,40,"pl-s"]],[[10,11,"pl-s"],[11,40,"pl-c1"],[40,41,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[51,52,"pl-s"],[52,57,"pl-c1"],[57,58,"pl-s"],[64,66,"pl-s"],[67,68,"pl-s"],[68,78,"pl-c1"],[78,79,"pl-s"]],[[2,3,"pl-s"],[3,8,"pl-c1"],[8,9,"pl-s"],[18,19,"pl-s"],[19,30,"pl-c1"],[30,31,"pl-s"],[33,34,"pl-s"],[34,47,"pl-c1"],[47,48,"pl-s"],[59,60,"pl-s"],[60,72,"pl-c1"],[72,73,"pl-s"]],[[27,28,"pl-s"],[28,42,"pl-c1"],[42,43,"pl-s"],[67,68,"pl-s"],[68,71,"pl-c1"],[71,72,"pl-s"]],[[2,3,"pl-s"],[3,18,"pl-c1"],[18,19,"pl-s"],[84,86,"pl-s"],[90,92,"pl-s"]],[],[[2,4,"pl-s"],[16,17,"pl-s"],[17,28,"pl-c1"],[28,29,"pl-s"],[51,52,"pl-s"],[52,61,"pl-c1"],[61,62,"pl-s"]],[[2,3,"pl-s"],[3,34,"pl-c1"],[34,35,"pl-s"],[35,37,"pl-s"]],[],[[57,58,"pl-s"],[58,67,"pl-c1"],[67,68,"pl-s"],[81,82,"pl-s"],[87,88,"pl-s"]],[],[[33,34,"pl-s"],[34,47,"pl-c1"],[47,48,"pl-s"],[71,73,"pl-s"],[77,79,"pl-s"]],[[2,3,"pl-s"],[3,15,"pl-c1"],[15,16,"pl-s"],[28,29,"pl-s"],[29,35,"pl-c1"],[35,36,"pl-s"],[76,77,"pl-s"],[77,85,"pl-c1"],[85,86,"pl-s"]],[[30,31,"pl-s"],[31,40,"pl-c1"],[40,41,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[92,94,"pl-s"]],[],[[13,14,"pl-s"],[14,26,"pl-c1"],[26,27,"pl-s"],[85,86,"pl-s"],[86,95,"pl-c1"],[95,96,"pl-s"]],[[3,4,"pl-s"],[4,20,"pl-c1"],[20,21,"pl-s"],[88,89,"pl-s"],[97,98,"pl-s"]],[[41,42,"pl-s"],[42,46,"pl-c1"],[46,47,"pl-s"]],[[20,21,"pl-s"],[21,43,"pl-c1"],[43,44,"pl-s"]],[[42,43,"pl-s"],[43,54,"pl-c1"],[54,55,"pl-s"]],[[2,3,"pl-s"],[3,23,"pl-c1"],[23,24,"pl-s"]],[[34,35,"pl-s"],[35,46,"pl-c1"],[46,47,"pl-s"],[50,51,"pl-s"],[51,65,"pl-c1"],[65,66,"pl-s"]],[[30,31,"pl-s"],[31,35,"pl-c1"],[35,36,"pl-s"]],[[12,13,"pl-s"],[13,22,"pl-c1"],[22,23,"pl-s"],[33,34,"pl-s"],[34,43,"pl-c1"],[43,44,"pl-s"]],[[2,3,"pl-s"],[3,14,"pl-c1"],[14,15,"pl-s"],[76,77,"pl-s"],[77,88,"pl-c1"],[88,89,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[4,5,"pl-s"],[5,20,"pl-c1"],[20,21,"pl-s"],[69,71,"pl-s"],[72,73,"pl-s"],[73,81,"pl-c1"],[81,82,"pl-s"]],[],[[51,52,"pl-s"],[52,59,"pl-c1"],[59,60,"pl-s"],[86,87,"pl-s"],[95,96,"pl-s"]],[[26,27,"pl-s"],[27,31,"pl-c1"],[31,32,"pl-s"],[36,37,"pl-s"],[37,54,"pl-c1"],[54,55,"pl-s"]],[[32,33,"pl-s"],[33,40,"pl-c1"],[40,41,"pl-s"]],[[27,28,"pl-s"],[28,34,"pl-c1"],[34,35,"pl-s"],[51,52,"pl-s"],[52,59,"pl-c1"],[59,60,"pl-s"]],[[34,35,"pl-s"],[35,48,"pl-c1"],[48,49,"pl-s"],[51,52,"pl-s"],[52,67,"pl-c1"],[67,68,"pl-s"],[80,81,"pl-s"],[81,90,"pl-c1"],[90,91,"pl-s"]],[],[[2,3,"pl-s"],[3,66,"pl-c1"],[66,67,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[19,20,"pl-s"],[20,28,"pl-c1"],[28,29,"pl-s"],[65,67,"pl-s"],[68,69,"pl-s"],[69,87,"pl-c1"],[87,88,"pl-s"]],[[3,4,"pl-s"],[4,11,"pl-c1"],[11,12,"pl-s"],[27,28,"pl-s"],[28,43,"pl-c1"],[43,44,"pl-s"]],[[58,59,"pl-s"],[73,74,"pl-s"]],[[70,72,"pl-s"],[82,84,"pl-s"],[88,89,"pl-s"],[89,93,"pl-c1"],[93,94,"pl-s"]],[[2,3,"pl-s"],[7,8,"pl-s"]],[],[[24,25,"pl-s"],[25,88,"pl-c1"],[88,89,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[83,85,"pl-s"]],[[2,3,"pl-s"],[3,21,"pl-c1"],[21,22,"pl-s"],[32,33,"pl-s"],[33,41,"pl-c1"],[41,42,"pl-s"],[48,49,"pl-s"],[49,57,"pl-c1"],[57,58,"pl-s"],[60,61,"pl-s"],[61,70,"pl-c1"],[70,71,"pl-s"],[81,82,"pl-s"],[82,98,"pl-c1"],[98,99,"pl-s"]],[[7,8,"pl-s"],[8,28,"pl-c1"],[28,29,"pl-s"],[35,36,"pl-s"],[36,45,"pl-c1"],[45,46,"pl-s"],[48,49,"pl-s"],[49,68,"pl-c1"],[68,69,"pl-s"]],[[30,31,"pl-s"],[31,41,"pl-c1"],[41,42,"pl-s"]],[[70,71,"pl-s"],[75,76,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[4,5,"pl-s"],[5,13,"pl-c1"],[13,14,"pl-s"],[91,93,"pl-s"]],[[33,34,"pl-s"],[34,43,"pl-c1"],[43,44,"pl-s"],[50,52,"pl-s"],[57,59,"pl-s"],[60,61,"pl-s"],[61,65,"pl-c1"],[65,66,"pl-s"]],[[74,75,"pl-s"],[75,82,"pl-c1"],[82,83,"pl-s"]],[[2,3,"pl-s"],[3,17,"pl-c1"],[17,18,"pl-s"]],[[10,11,"pl-s"],[11,16,"pl-c1"],[16,17,"pl-s"],[19,20,"pl-s"],[20,33,"pl-c1"],[33,34,"pl-s"],[37,38,"pl-s"],[38,52,"pl-c1"],[52,53,"pl-s"]],[[2,3,"pl-s"],[3,21,"pl-c1"],[21,22,"pl-s"],[38,39,"pl-s"],[43,44,"pl-s"],[60,61,"pl-s"],[61,72,"pl-c1"],[72,73,"pl-s"]],[],[],[[0,1,"pl-v"],[2,4,"pl-s"],[78,80,"pl-s"],[81,82,"pl-s"],[82,92,"pl-c1"],[92,93,"pl-s"]],[[9,10,"pl-s"],[10,16,"pl-c1"],[16,17,"pl-s"],[18,19,"pl-s"],[19,25,"pl-c1"],[25,26,"pl-s"],[64,65,"pl-s"],[65,83,"pl-c1"],[83,84,"pl-s"]],[[35,36,"pl-s"],[36,42,"pl-c1"],[42,43,"pl-s"]],[[36,37,"pl-s"],[37,43,"pl-c1"],[43,44,"pl-s"],[63,64,"pl-s"],[67,68,"pl-s"]],[],[[2,3,"pl-s"],[3,23,"pl-c1"],[23,24,"pl-s"]],[[45,46,"pl-s"],[46,59,"pl-c1"],[59,60,"pl-s"]],[],[[45,47,"pl-s"],[82,83,"pl-s"],[83,90,"pl-c1"],[90,91,"pl-s"]],[[15,16,"pl-s"],[16,28,"pl-c1"],[28,29,"pl-s"],[46,47,"pl-s"],[47,60,"pl-c1"],[60,61,"pl-s"],[95,97,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[62,64,"pl-s"]],[[32,33,"pl-s"],[33,37,"pl-c1"],[37,38,"pl-s"]],[[8,9,"pl-s"],[9,13,"pl-c1"],[13,14,"pl-s"]],[[68,70,"pl-s"]],[[5,7,"pl-s"],[42,43,"pl-s"],[43,49,"pl-c1"],[49,50,"pl-s"]],[[37,38,"pl-s"],[38,49,"pl-c1"],[49,50,"pl-s"],[52,53,"pl-s"],[53,62,"pl-c1"],[62,63,"pl-s"],[65,66,"pl-s"],[66,72,"pl-c1"],[72,73,"pl-s"],[78,79,"pl-s"],[79,90,"pl-c1"],[90,91,"pl-s"]],[[33,34,"pl-s"],[34,46,"pl-c1"],[46,47,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[69,71,"pl-s"],[72,73,"pl-s"],[73,83,"pl-c1"],[83,84,"pl-s"]],[],[],[[25,26,"pl-s"],[26,39,"pl-c1"],[39,40,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[42,44,"pl-s"],[69,70,"pl-s"],[70,74,"pl-c1"],[74,75,"pl-s"],[76,77,"pl-s"],[77,86,"pl-c1"],[86,87,"pl-s"]],[[3,4,"pl-s"],[4,27,"pl-c1"],[27,28,"pl-s"]],[[2,3,"pl-s"],[3,17,"pl-c1"],[17,18,"pl-s"],[41,42,"pl-s"],[42,53,"pl-c1"],[53,54,"pl-s"],[55,56,"pl-s"],[56,68,"pl-c1"],[68,69,"pl-s"]],[[2,3,"pl-s"],[3,15,"pl-c1"],[15,16,"pl-s"],[34,35,"pl-s"],[35,39,"pl-c1"],[39,40,"pl-s"]],[],[[42,43,"pl-s"],[43,61,"pl-c1"],[61,62,"pl-s"],[77,78,"pl-s"],[78,94,"pl-c1"],[94,95,"pl-s"]],[[6,7,"pl-s"],[7,34,"pl-c1"],[34,35,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[17,18,"pl-s"],[18,20,"pl-c1"],[20,21,"pl-s"],[41,43,"pl-s"]],[[34,35,"pl-s"],[35,52,"pl-c1"],[52,53,"pl-s"],[56,57,"pl-s"],[57,72,"pl-c1"],[72,73,"pl-s"],[77,78,"pl-s"],[78,88,"pl-c1"],[88,89,"pl-s"]],[[18,19,"pl-s"],[19,29,"pl-c1"],[29,30,"pl-s"],[32,33,"pl-s"],[33,40,"pl-c1"],[40,41,"pl-s"],[43,44,"pl-s"],[44,63,"pl-c1"],[63,64,"pl-s"]],[],[],[[0,1,"pl-v"],[2,4,"pl-s"],[4,5,"pl-s"],[5,29,"pl-c1"],[29,30,"pl-s"],[41,42,"pl-s"],[42,56,"pl-c1"],[56,57,"pl-s"],[80,82,"pl-s"],[83,84,"pl-s"],[84,97,"pl-c1"],[97,98,"pl-s"]],[[10,11,"pl-s"],[11,25,"pl-c1"],[25,26,"pl-s"],[29,30,"pl-s"],[30,38,"pl-c1"],[38,39,"pl-s"],[42,43,"pl-s"],[43,53,"pl-c1"],[53,54,"pl-s"],[73,74,"pl-s"],[74,87,"pl-c1"],[87,88,"pl-s"]],[[3,4,"pl-s"],[4,17,"pl-c1"],[17,18,"pl-s"],[21,22,"pl-s"],[22,44,"pl-c1"],[44,45,"pl-s"],[67,68,"pl-s"],[68,72,"pl-c1"],[72,73,"pl-s"]],[[2,3,"pl-s"],[3,11,"pl-c1"],[11,12,"pl-s"],[26,28,"pl-s"],[33,35,"pl-s"],[39,41,"pl-s"],[50,52,"pl-s"]],[[23,24,"pl-s"],[28,29,"pl-s"]],[[64,65,"pl-s"],[65,74,"pl-c1"],[74,75,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[27,28,"pl-s"],[28,43,"pl-c1"],[43,44,"pl-s"],[68,70,"pl-s"]],[[2,4,"pl-s"],[29,31,"pl-s"],[33,34,"pl-s"],[34,40,"pl-c1"],[40,41,"pl-s"],[51,52,"pl-s"],[52,57,"pl-c1"],[57,58,"pl-s"]],[[2,3,"pl-s"],[3,14,"pl-c1"],[14,15,"pl-s"],[44,45,"pl-s"],[55,56,"pl-s"]],[[50,51,"pl-s"],[51,70,"pl-c1"],[70,71,"pl-s"]],[[22,23,"pl-s"],[23,34,"pl-c1"],[34,35,"pl-s"],[67,69,"pl-s"],[95,97,"pl-s"]],[],[[77,78,"pl-s"],[78,88,"pl-c1"],[88,89,"pl-s"]],[[19,21,"pl-s"],[34,36,"pl-s"],[42,43,"pl-s"],[43,52,"pl-c1"],[52,53,"pl-s"],[60,61,"pl-s"],[61,62,"pl-c1"],[62,63,"pl-s"],[71,73,"pl-s"],[81,83,"pl-s"]],[[40,41,"pl-s"],[41,51,"pl-c1"],[51,52,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[4,5,"pl-s"],[5,17,"pl-c1"],[17,18,"pl-s"],[50,52,"pl-s"]],[[45,46,"pl-s"],[46,53,"pl-c1"],[53,54,"pl-s"],[64,66,"pl-s"],[69,71,"pl-s"]],[[4,5,"pl-s"],[8,9,"pl-s"],[22,23,"pl-s"],[26,27,"pl-s"]],[[80,81,"pl-s"],[81,94,"pl-c1"],[94,95,"pl-s"]],[[34,35,"pl-s"],[35,54,"pl-c1"],[54,55,"pl-s"]],[[2,3,"pl-s"],[3,12,"pl-c1"],[12,13,"pl-s"],[16,17,"pl-s"],[17,26,"pl-c1"],[26,27,"pl-s"]],[[63,64,"pl-s"],[64,77,"pl-c1"],[77,78,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[46,47,"pl-s"],[47,57,"pl-c1"],[57,58,"pl-s"]],[[62,64,"pl-s"]],[[41,42,"pl-s"],[42,46,"pl-c1"],[46,47,"pl-s"],[54,55,"pl-s"],[55,90,"pl-c1"],[90,91,"pl-s"]],[[53,54,"pl-s"],[54,66,"pl-c1"],[66,67,"pl-s"],[75,76,"pl-s"],[76,79,"pl-c1"],[79,80,"pl-s"]],[[2,3,"pl-s"],[3,23,"pl-c1"],[23,24,"pl-s"],[33,34,"pl-s"],[34,43,"pl-c1"],[43,44,"pl-s"]],[[30,31,"pl-s"],[31,36,"pl-c1"],[36,37,"pl-s"],[38,40,"pl-s"],[66,68,"pl-s"]],[],[[14,15,"pl-s"],[15,20,"pl-c1"],[20,21,"pl-s"],[22,24,"pl-s"],[49,51,"pl-s"]],[[2,3,"pl-s"],[3,21,"pl-c1"],[21,22,"pl-s"],[70,71,"pl-s"],[71,85,"pl-c1"],[85,86,"pl-s"]],[[81,82,"pl-s"],[82,87,"pl-c1"],[87,88,"pl-s"]],[],[[41,42,"pl-s"],[42,45,"pl-c1"],[45,46,"pl-s"]],[[15,16,"pl-s"],[16,35,"pl-c1"],[35,36,"pl-s"]],[[51,52,"pl-s"],[52,63,"pl-c1"],[63,64,"pl-s"],[68,69,"pl-s"],[69,75,"pl-c1"],[75,76,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[4,5,"pl-s"],[5,14,"pl-c1"],[14,15,"pl-s"],[49,50,"pl-s"],[50,63,"pl-c1"],[63,64,"pl-s"],[87,89,"pl-s"]],[[2,3,"pl-s"],[3,18,"pl-c1"],[18,19,"pl-s"],[35,36,"pl-s"],[36,53,"pl-c1"],[53,54,"pl-s"]],[[79,80,"pl-s"],[80,93,"pl-c1"],[93,94,"pl-s"]],[[71,73,"pl-s"],[79,81,"pl-s"]],[[86,87,"pl-s"]],[[9,10,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[67,69,"pl-s"],[70,71,"pl-s"],[71,78,"pl-c1"],[78,79,"pl-s"]],[[2,3,"pl-s"],[3,18,"pl-c1"],[18,19,"pl-s"],[44,45,"pl-s"],[45,58,"pl-c1"],[58,59,"pl-s"]],[[80,81,"pl-s"],[81,85,"pl-c1"],[85,86,"pl-s"]],[[5,6,"pl-s"],[6,44,"pl-c1"],[44,45,"pl-s"]],[],[[2,3,"pl-s"],[3,24,"pl-c1"],[24,25,"pl-s"],[27,28,"pl-s"],[28,38,"pl-c1"],[38,39,"pl-s"],[63,64,"pl-s"],[64,79,"pl-c1"],[79,80,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[75,77,"pl-s"]],[[33,34,"pl-s"],[34,46,"pl-c1"],[46,47,"pl-s"],[52,53,"pl-s"],[53,60,"pl-c1"],[60,61,"pl-s"]],[[2,3,"pl-s"],[3,7,"pl-c1"],[7,8,"pl-s"]],[[2,3,"pl-s"],[3,10,"pl-c1"],[10,11,"pl-s"],[15,16,"pl-s"],[16,31,"pl-c1"],[31,32,"pl-s"],[56,57,"pl-s"],[57,74,"pl-c1"],[74,75,"pl-s"]],[],[],[[70,71,"pl-s"],[71,84,"pl-c1"],[84,85,"pl-s"]],[[3,4,"pl-s"],[4,16,"pl-c1"],[16,17,"pl-s"],[33,34,"pl-s"],[34,46,"pl-c1"],[46,47,"pl-s"],[80,81,"pl-s"],[81,92,"pl-c1"],[92,93,"pl-s"]],[[54,55,"pl-s"],[55,57,"pl-c1"],[57,58,"pl-s"]],[],[[6,7,"pl-s"],[7,14,"pl-c1"],[14,15,"pl-s"],[17,18,"pl-s"],[18,36,"pl-c1"],[36,37,"pl-s"],[43,44,"pl-s"],[44,71,"pl-c1"],[71,72,"pl-s"]],[[25,26,"pl-s"],[26,42,"pl-c1"],[42,43,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[52,54,"pl-s"],[74,75,"pl-s"],[75,91,"pl-c1"],[91,92,"pl-s"]],[[11,12,"pl-s"],[12,31,"pl-c1"],[31,32,"pl-s"],[34,35,"pl-s"],[35,54,"pl-c1"],[54,55,"pl-s"]],[[16,17,"pl-s"],[17,38,"pl-c1"],[38,39,"pl-s"],[77,78,"pl-s"],[78,83,"pl-c1"],[83,84,"pl-s"]],[[60,61,"pl-s"],[61,80,"pl-c1"],[80,81,"pl-s"]],[],[[43,44,"pl-s"],[44,50,"pl-c1"],[50,51,"pl-s"]],[[28,29,"pl-s"],[29,34,"pl-c1"],[34,35,"pl-s"]],[[2,3,"pl-s"],[3,19,"pl-c1"],[19,20,"pl-s"],[25,26,"pl-s"],[26,43,"pl-c1"],[43,44,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[17,19,"pl-s"],[20,21,"pl-s"],[21,31,"pl-c1"],[31,32,"pl-s"],[37,38,"pl-s"],[38,55,"pl-c1"],[55,56,"pl-s"],[78,79,"pl-s"],[79,101,"pl-c1"],[101,102,"pl-s"]],[[15,16,"pl-s"],[16,30,"pl-c1"],[30,31,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[39,41,"pl-s"]],[[2,3,"pl-s"],[3,15,"pl-c1"],[15,16,"pl-s"],[19,20,"pl-s"],[20,32,"pl-c1"],[32,33,"pl-s"],[42,43,"pl-s"],[61,62,"pl-s"],[64,65,"pl-s"],[65,79,"pl-c1"],[79,80,"pl-s"]],[],[[2,3,"pl-s"],[3,13,"pl-c1"],[13,14,"pl-s"]],[[46,47,"pl-s"],[47,54,"pl-c1"],[54,55,"pl-s"],[67,68,"pl-s"],[68,80,"pl-c1"],[80,81,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[58,60,"pl-s"],[61,62,"pl-s"],[62,71,"pl-c1"],[71,72,"pl-s"]],[[2,3,"pl-s"],[3,17,"pl-c1"],[17,18,"pl-s"],[65,66,"pl-s"],[66,79,"pl-c1"],[79,80,"pl-s"]],[[68,69,"pl-s"],[74,75,"pl-s"]],[],[[54,55,"pl-s"],[55,68,"pl-c1"],[68,69,"pl-s"]],[[18,19,"pl-s"],[19,21,"pl-c1"],[21,22,"pl-s"]],[[34,35,"pl-s"],[35,45,"pl-c1"],[45,46,"pl-s"]],[],[[6,7,"pl-s"],[7,12,"pl-c1"],[12,13,"pl-s"],[39,40,"pl-s"],[55,56,"pl-s"]],[],[],[],[[2,3,"pl-s"],[3,19,"pl-c1"],[19,20,"pl-s"],[43,44,"pl-s"],[44,57,"pl-c1"],[57,58,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[4,5,"pl-s"],[5,10,"pl-c1"],[10,11,"pl-s"],[90,92,"pl-s"]],[[2,3,"pl-s"],[3,7,"pl-c1"],[7,8,"pl-s"],[29,30,"pl-s"],[30,32,"pl-c1"],[32,33,"pl-s"]],[[5,6,"pl-s"],[6,19,"pl-c1"],[19,20,"pl-s"],[27,28,"pl-s"],[28,32,"pl-c1"],[32,33,"pl-s"],[38,39,"pl-s"],[39,52,"pl-c1"],[52,53,"pl-s"],[80,81,"pl-s"],[81,91,"pl-c1"],[91,92,"pl-s"]],[[28,29,"pl-s"],[29,56,"pl-c1"],[56,57,"pl-s"]],[[75,76,"pl-s"],[76,78,"pl-c1"],[78,79,"pl-s"]],[[43,44,"pl-s"],[44,103,"pl-c1"],[103,104,"pl-s"]],[[5,6,"pl-s"],[6,14,"pl-c1"],[14,15,"pl-s"],[68,69,"pl-s"],[69,83,"pl-c1"],[83,84,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[94,96,"pl-s"]],[[55,56,"pl-s"],[56,80,"pl-c1"],[80,81,"pl-s"]],[[11,12,"pl-s"],[12,30,"pl-c1"],[30,31,"pl-s"]],[[68,69,"pl-s"],[69,74,"pl-c1"],[74,75,"pl-s"]],[[2,3,"pl-s"],[3,36,"pl-c1"],[36,37,"pl-s"],[59,60,"pl-s"],[60,87,"pl-c1"],[87,88,"pl-s"]],[[7,8,"pl-s"],[8,14,"pl-c1"],[14,15,"pl-s"],[69,70,"pl-s"],[70,83,"pl-c1"],[83,84,"pl-s"]],[[2,3,"pl-s"],[3,17,"pl-c1"],[17,18,"pl-s"]],[],[[21,22,"pl-s"],[22,36,"pl-c1"],[36,37,"pl-s"],[66,67,"pl-s"],[67,83,"pl-c1"],[83,84,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[80,82,"pl-s"]],[[49,50,"pl-s"],[50,64,"pl-c1"],[64,65,"pl-s"],[74,75,"pl-s"],[75,96,"pl-c1"],[96,97,"pl-s"]],[[6,7,"pl-s"],[7,38,"pl-c1"],[38,39,"pl-s"]],[],[[7,8,"pl-s"],[8,15,"pl-c1"],[15,16,"pl-s"],[26,27,"pl-s"],[27,41,"pl-c1"],[41,42,"pl-s"],[56,57,"pl-s"],[57,64,"pl-c1"],[64,65,"pl-s"],[85,87,"pl-s"],[91,93,"pl-s"]],[],[[69,70,"pl-s"],[76,77,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[63,65,"pl-s"]],[[2,3,"pl-s"],[3,11,"pl-c1"],[11,12,"pl-s"],[48,49,"pl-s"],[49,61,"pl-c1"],[61,62,"pl-s"],[69,70,"pl-s"],[70,78,"pl-c1"],[78,79,"pl-s"]],[[16,17,"pl-s"],[17,35,"pl-c1"],[35,36,"pl-s"],[37,38,"pl-s"],[38,51,"pl-c1"],[51,52,"pl-s"]],[],[[61,62,"pl-s"],[62,70,"pl-c1"],[70,71,"pl-s"]],[[12,13,"pl-s"],[13,30,"pl-c1"],[30,31,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[57,59,"pl-s"],[60,61,"pl-s"],[61,65,"pl-c1"],[65,66,"pl-s"],[80,81,"pl-s"],[81,89,"pl-c1"],[89,90,"pl-s"]],[],[],[[28,29,"pl-s"],[29,72,"pl-c1"],[72,73,"pl-s"]],[[21,22,"pl-s"],[22,32,"pl-c1"],[32,33,"pl-s"],[48,49,"pl-s"],[53,54,"pl-s"]],[[25,26,"pl-s"],[26,32,"pl-c1"],[32,33,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[26,27,"pl-s"],[27,35,"pl-c1"],[35,36,"pl-s"],[55,57,"pl-s"],[58,59,"pl-s"],[59,62,"pl-c1"],[62,63,"pl-s"]],[[25,26,"pl-s"],[26,38,"pl-c1"],[38,39,"pl-s"],[59,60,"pl-s"],[60,73,"pl-c1"],[73,74,"pl-s"],[79,80,"pl-s"],[80,92,"pl-c1"],[92,93,"pl-s"]],[],[],[[0,1,"pl-v"],[2,4,"pl-s"],[59,61,"pl-s"]],[[24,25,"pl-s"],[25,43,"pl-c1"],[43,44,"pl-s"],[76,77,"pl-s"],[77,94,"pl-c1"],[94,95,"pl-s"]],[[13,14,"pl-s"],[14,35,"pl-c1"],[35,36,"pl-s"],[71,72,"pl-s"],[72,75,"pl-c1"],[75,76,"pl-s"]],[[44,45,"pl-s"],[45,49,"pl-c1"],[49,50,"pl-s"]],[[17,18,"pl-s"],[18,21,"pl-c1"],[21,22,"pl-s"],[24,25,"pl-s"],[25,38,"pl-c1"],[38,39,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[33,35,"pl-s"],[36,37,"pl-s"],[37,57,"pl-c1"],[57,58,"pl-s"]],[[17,18,"pl-s"],[18,45,"pl-c1"],[45,46,"pl-s"]],[],[[2,3,"pl-s"],[3,23,"pl-c1"],[23,24,"pl-s"],[71,72,"pl-s"],[72,98,"pl-c1"],[98,99,"pl-s"]],[[8,9,"pl-s"],[9,14,"pl-c1"],[14,15,"pl-s"],[24,25,"pl-s"],[25,39,"pl-c1"],[39,40,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[35,37,"pl-s"],[38,39,"pl-s"],[39,46,"pl-c1"],[46,47,"pl-s"]],[[30,31,"pl-s"],[31,44,"pl-c1"],[44,45,"pl-s"],[77,78,"pl-s"],[85,86,"pl-s"]],[[55,56,"pl-s"],[56,72,"pl-c1"],[72,73,"pl-s"]],[[0,1,"pl-v"],[2,4,"pl-s"],[13,14,"pl-s"],[14,20,"pl-c1"],[20,21,"pl-s"],[59,61,"pl-s"]],[[76,77,"pl-s"],[77,89,"pl-c1"],[89,90,"pl-s"]],[],[[53,54,"pl-s"],[54,56,"pl-c1"],[56,57,"pl-s"]],[[83,84,"pl-s"],[84,90,"pl-c1"],[90,91,"pl-s"]],[],[[0,1,"pl-v"],[2,4,"pl-s"],[38,39,"pl-s"],[39,57,"pl-c1"],[57,58,"pl-s"],[58,60,"pl-s"],[63,64,"pl-s"],[64,86,"pl-c1"],[86,87,"pl-s"]],[],[],[[0,14,"pl-mh"],[3,14,"pl-en"]],[],[[18,19,"pl-s"],[19,33,"pl-c1"],[33,34,"pl-s"],[57,58,"pl-s"],[58,66,"pl-c1"],[66,67,"pl-s"]],[[0,1,"pl-s"],[1,20,"pl-c1"],[20,21,"pl-s"],[23,24,"pl-s"],[24,41,"pl-c1"],[41,42,"pl-s"],[80,81,"pl-s"],[81,91,"pl-c1"],[91,92,"pl-s"]],[],[[0,1,"pl-s"],[1,15,"pl-c1"],[15,16,"pl-s"],[27,28,"pl-s"],[28,42,"pl-c1"],[42,43,"pl-s"],[85,86,"pl-s"],[86,94,"pl-c1"],[94,95,"pl-s"]],[[44,45,"pl-s"],[45,52,"pl-c1"],[52,53,"pl-s"]],[],[[0,15,"pl-mh"],[3,15,"pl-en"]],[],[[0,17,"pl-mh"],[4,17,"pl-en"]],[],[[54,55,"pl-s"],[55,74,"pl-c1"],[74,75,"pl-s"]],[[18,19,"pl-s"],[19,47,"pl-c1"],[47,48,"pl-s"]],[],[[0,17,"pl-mh"],[4,17,"pl-en"]],[],[[26,27,"pl-s"],[27,39,"pl-c1"],[39,40,"pl-s"],[42,43,"pl-s"],[43,53,"pl-c1"],[53,54,"pl-s"],[56,57,"pl-s"],[57,72,"pl-c1"],[72,73,"pl-s"],[75,76,"pl-s"],[76,91,"pl-c1"],[91,92,"pl-s"]],[[0,1,"pl-s"],[1,8,"pl-c1"],[8,9,"pl-s"],[28,29,"pl-s"],[29,57,"pl-c1"],[57,58,"pl-s"]],[],[[0,15,"pl-mh"],[4,15,"pl-en"]],[],[[17,18,"pl-s"],[18,28,"pl-c1"],[28,29,"pl-s"],[32,33,"pl-s"],[33,42,"pl-c1"],[42,43,"pl-s"],[66,67,"pl-s"],[67,88,"pl-c1"],[88,89,"pl-s"]]],"colorizedLines":null}},"title":"herdr-switchboard/CLAUDE.md at main · crafts69guy/herdr-switchboard","appPayload":{},"meta":{"title":"herdr-switchboard/CLAUDE.md at main · crafts69guy/herdr-switchboard"}}</script>
  <div data-target="react-app.reactRoot"><meta name="github-code-view-meta-stats" id="github-code-view-meta-stats" data-hydrostats="publish"/> <!-- --> <a hidden="" id="code-view-repo-link" href="/crafts69guy/herdr-switchboard" data-discover="true"></a> <div class="d-none"></div><div><div style="--spacing:var(--spacing-none)" class="prc-PageLayout-PageLayoutRoot--KH-d" data-component="SplitPageLayout" data-has-sidebar="true"><div class="prc-PageLayout-SidebarWrapper-kLG4B CopilotSidePanelSidebar-module__SidePanel__L3O0C CopilotSidePanelSidebar-module__HiddenSidePanel__TBRGn" style="--spacing-column:var(--spacing-none)" data-is-hidden="false" data-position="end" data-sticky="true" data-responsive-variant="fullscreen"><div class="prc-PageLayout-VerticalDivider-9QRmK prc-PageLayout-SidebarVerticalDivider-0Rl0V" data-component="PageLayout.VerticalDivider" data-variant="line" data-position="end" style="--spacing:var(--spacing-none)"><div class="prc-PageLayout-DraggableHandle-9s6B4" data-component="PageLayout.DragHandle" role="slider" aria-label="Draggable pane splitter" aria-valuemin="450" aria-valuemax="768" aria-valuenow="544" aria-valuetext="Pane width 544 pixels" tabindex="0"></div></div><div class="prc-PageLayout-Sidebar-iciWg" data-component="SplitPageLayout.Sidebar" data-resizable="true" style="--spacing:var(--spacing-normal);--pane-min-width:450px;--pane-max-width:768px;--pane-width-custom:544px;--pane-width-size:var(--pane-width-custom);--pane-width:544px"><div class="height-full" data-testid="copilot-code-view-side-panel"><div id="copilot-side-panel-content" class="height-full"></div></div></div></div><div class="prc-PageLayout-PageLayoutWrapper-2BhU2" data-width="full"><div class="prc-PageLayout-PageLayoutContent-BneH9"><div id="repos-file-tree-sidebar" class="CodeViewFileTreeLayout-module__sidebar__n_Aau" tabindex="0"><div class="prc-PageLayout-PaneWrapper-pHPop ReposFileTreePane-module__Pane__rBZpI ReposFileTreePane-module__HideTree__AYZnm ReposFileTreePane-module__HidePane__VHAVt" style="--offset-header:0px;--spacing-row:var(--spacing-none);--spacing-column:var(--spacing-none)" data-is-hidden="false" data-position="start" data-sticky="true"><div class="prc-PageLayout-HorizontalDivider-JLVqp prc-PageLayout-PaneHorizontalDivider-9tbnE" data-component="PageLayout.HorizontalDivider" data-variant-regular="none" data-variant-narrow="none" data-position="start" style="--spacing-divider:var(--spacing-none);--spacing:var(--spacing-none)"></div><div class="prc-PageLayout-Pane-AyzHK" data-component="SplitPageLayout.Pane" data-resizable="true" style="--spacing:var(--spacing-none);--pane-min-width:256px;--pane-max-width:calc(100vw - var(--pane-max-width-diff));--pane-width-size:var(--pane-width-large);--pane-width:320px"></div><div class="prc-PageLayout-VerticalDivider-9QRmK prc-PageLayout-PaneVerticalDivider-le57g" data-component="PageLayout.VerticalDivider" data-variant-narrow="none" data-variant-regular="line" data-variant-wide="line" data-position="start" style="--spacing:var(--spacing-none)"><div class="prc-PageLayout-DraggableHandle-9s6B4" data-component="PageLayout.DragHandle" role="slider" aria-label="Draggable pane splitter" aria-valuemin="256" aria-valuemax="600" aria-valuenow="320" aria-valuetext="Pane width 320 pixels" tabindex="0"></div></div></div></div><div data-component="SplitPageLayout.Content" class="prc-PageLayout-ContentWrapper-gR9eG"><div class="prc-PageLayout-Content-xWL-A" data-width="full" style="--spacing:var(--spacing-none)"><div class="SharedPageLayout-module__content__IwGAp" data-selector="repos-split-pane-content" id="repos-split-pane-content" tabindex="0"> <!-- --> <div class="container CodeViewHeader-module__Box__JkPOb"><div class="CodeViewHeader-module__StickyHeader__Qn7UN" id="StickyHeader"><div class="CodeViewHeader-module__Box_1__SbNDV"><div class="CodeViewHeader-module__Box_2__TB46f"><div class="react-code-view-header-wrap--narrow CodeViewHeader-module__Box_3__q1zUL"><div class="CodeViewHeader-module__treeToggleWrapper__RQ__9"><h2 class="use-tree-pane-module__Heading__s4QbZ prc-Heading-Heading-MtWFE" data-component="Heading"><button data-component="Button" type="button" aria-label="Expand file tree" data-testid="expand-file-tree-button-mobile" class="prc-Button-ButtonBase-9n-Xk ExpandFileTreeButton-module__Button_1__Svs95" data-loading="false" data-size="medium" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-arrow-left" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M7.78 12.53a.75.75 0 0 1-1.06 0L2.47 8.28a.75.75 0 0 1 0-1.06l4.25-4.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042L4.81 7h7.44a.75.75 0 0 1 0 1.5H4.81l2.97 2.97a.75.75 0 0 1 0 1.06Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3">Files</span></span></button><button data-component="IconButton" type="button" data-testid="expand-file-tree-button" aria-controls="repos-file-tree" class="prc-Button-ButtonBase-9n-Xk position-relative ExpandFileTreeButton-module__expandButton__hDOcv ExpandFileTreeButton-module__filesButtonBreakpoint__zEvz3 fgColor-muted prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="invisible" aria-labelledby="_R_4lla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-sidebar-collapse" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M6.823 7.823a.25.25 0 0 1 0 .354l-2.396 2.396A.25.25 0 0 1 4 10.396V5.604a.25.25 0 0 1 .427-.177Z"></path><path d="M1.75 0h12.5C15.216 0 16 .784 16 1.75v12.5A1.75 1.75 0 0 1 14.25 16H1.75A1.75 1.75 0 0 1 0 14.25V1.75C0 .784.784 0 1.75 0ZM1.5 1.75v12.5c0 .138.112.25.25.25H9.5v-13H1.75a.25.25 0 0 0-.25.25ZM11 14.5h3.25a.25.25 0 0 0 .25-.25V1.75a.25.25 0 0 0-.25-.25H11Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="se" data-component="Tooltip" aria-hidden="true" id="_R_4lla9lik5_">Expand file tree</span><div class="d-none"></div></h2></div><div class="react-code-view-header-mb--narrow mr-2"><button data-component="Button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="main branch" data-testid="anchor-button" data-icv-name="Switch branches/tags" class="prc-Button-ButtonBase-9n-Xk ref-selector-class RefSelectorAnchoredOverlay-module__RefSelectorOverlayBtn__a3WK3" data-loading="false" data-size="medium" data-variant="default" id="ref-picker-repos-header-ref-selector-wide"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><div class="RefSelectorAnchoredOverlay-module__RefSelectorOverlayContainer__yaf4p"><div style="max-width:125px" class="ref-selector-button-text-container RefSelectorAnchoredOverlay-module__RefSelectorBtnTextContainer__Di3rk"><span class="RefSelectorAnchoredOverlay-module__RefSelectorText__w_fmP">main</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><div class="d-none"></div></div><div class="react-code-view-header-mb--narrow CodeViewHeader-module__Box_5__MQ0hL"><div class="Breadcrumb-module__container__Vxvev Breadcrumb-module__lg__Rjz0A"><nav data-testid="breadcrumbs" aria-labelledby="repos-header-breadcrumb-heading" id="repos-header-breadcrumb" class="Breadcrumb-module__nav__rQFDj"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading" id="repos-header-breadcrumb-heading">Breadcrumbs</h2><ol class="Breadcrumb-module__list__ZH6zr"><li class="Breadcrumb-module__listItem__Ib0x_"><a class="Breadcrumb-module__repoLink__O2Nbs prc-Link-Link-9ZwDx" data-component="Link" data-testid="breadcrumbs-repo-link" href="/crafts69guy/herdr-switchboard/tree/main" data-discover="true">herdr-switchboard</a></li></ol></nav><div data-testid="breadcrumbs-filename" class="Breadcrumb-module__filename__equZR"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__lg__Rjz0A" aria-hidden="true">/</span><h1 class="Breadcrumb-module__filenameHeading__MNMtw Breadcrumb-module__lg__Rjz0A prc-Heading-Heading-MtWFE" data-component="Heading" tabindex="-1" id="file-name-id">CLAUDE.md</h1></div><button data-component="IconButton" type="button" class="prc-Button-ButtonBase-9n-Xk ml-2 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_7lla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="CopyToClipboardIconButton-module__tooltip__WyiwL prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-label="Copy path" aria-hidden="true" id="_R_7lla9lik5_">Copy path</span></div></div></div><div class="react-code-view-header-element--wide"><div class="CodeViewHeader-module__Box_7___0R6c"><div class="d-flex gap-2"><div><div class="CodeViewHeader-module__FileResultsList__JDzUy"><span class="d-flex FileResultsList-module__FilesSearchBox__ivVkc TextInput-wrapper prc-components-TextInputWrapper-Hpdqi prc-components-TextInputBaseWrapper-wY-n0" data-no-trailing-action="true" data-component="TextInput" data-leading-visual="true" data-trailing-visual="true" aria-busy="false"><span class="TextInput-icon" id="_R_1cpla9lik5_" aria-hidden="true" data-component="TextInput.LeadingVisual"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-search" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M10.68 11.74a6 6 0 0 1-7.922-8.982 6 6 0 0 1 8.982 7.922l3.04 3.04a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215ZM11.5 7a4.499 4.499 0 1 0-8.997 0A4.499 4.499 0 0 0 11.5 7Z"></path></svg></span><input type="text" aria-label="Go to file" role="combobox" aria-controls="file-results-list" aria-expanded="false" aria-haspopup="dialog" autoCorrect="off" spellCheck="false" placeholder="Go to file" aria-describedby="_R_1cpla9lik5_ _R_1cpla9lik5H1_" data-component="input" class="prc-components-Input-IwWrt" value=""/><span class="TextInput-icon" id="_R_1cpla9lik5H1_" aria-hidden="true" data-component="TextInput.TrailingVisual"></span></span></div><div class="d-none"></div></div><button data-component="Button" type="button" style="display:none" class="prc-Button-ButtonBase-9n-Xk NavigationMenu-module__Button__LpKgm" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Blame</span></span></button><div class="d-none"></div><button data-component="IconButton" type="button" data-testid="more-file-actions-button-nav-menu-wide" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click NavigationMenu-module__IconButton__HpX3G prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-labelledby="_R_7p9la9lik5_" id="_R_99la9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_7p9la9lik5_">More file actions</span></div></div></div><div class="react-code-view-header-element--narrow"><div class="CodeViewHeader-module__Box_7___0R6c"><div class="d-flex gap-2"><button data-component="Button" type="button" style="display:none" class="prc-Button-ButtonBase-9n-Xk NavigationMenu-module__Button__LpKgm" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Blame</span></span></button><div class="d-none"></div><button data-component="IconButton" type="button" data-testid="more-file-actions-button-nav-menu-narrow" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click NavigationMenu-module__IconButton__HpX3G prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="medium" data-variant="default" aria-labelledby="_R_7pdla9lik5_" id="_R_9dla9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_7pdla9lik5_">More file actions</span></div></div></div></div></div></div></div><div class="CodeView-module__contentWrapper__cG2JH"><div class="react-code-view-bottom-padding"><div class="BlobTopBanners-module__Box__v_nvx"></div></div> <div class="d-none"></div><div class="d-flex flex-column border rounded-2 tmp-mb-3 pl-1"><div class="LatestCommit-module__Box__B25ZT"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">Latest commit</h2><div style="width:120px" class="Skeleton Skeleton--text" data-testid="loading"> </div><div class="d-flex flex-shrink-0 gap-2"><div data-testid="latest-commit-details" class="d-none d-sm-flex flex-items-center"></div><div class="d-flex gap-2"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">History</h2><a data-component="LinkButton" href="/crafts69guy/herdr-switchboard/commits/main/CLAUDE.md" class="prc-Button-ButtonBase-9n-Xk d-none d-lg-flex LinkButton-module__linkButton__nFnov flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><span class="fgColor-default">History</span></span></span></a><div class="d-sm-none"></div><div class="d-flex d-lg-none"><a data-component="LinkButton" aria-label="View commit history for this file." href="/crafts69guy/herdr-switchboard/commits/main/CLAUDE.md" class="prc-Button-ButtonBase-9n-Xk LinkButton-module__linkButton__nFnov flex-items-center fgColor-default" data-loading="false" data-size="small" data-variant="invisible" aria-describedby="_R_4mlala9lik5_"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-history" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m.427 1.927 1.215 1.215a8.002 8.002 0 1 1-1.6 5.685.75.75 0 1 1 1.493-.154 6.5 6.5 0 1 0 1.18-4.458l1.358 1.358A.25.25 0 0 1 3.896 6H.25A.25.25 0 0 1 0 5.75V2.104a.25.25 0 0 1 .427-.177ZM7.75 4a.75.75 0 0 1 .75.75v2.992l2.028.812a.75.75 0 0 1-.557 1.392l-2.5-1A.751.751 0 0 1 7 8.25v-3.5A.75.75 0 0 1 7.75 4Z"></path></svg></span></span></a><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="s" data-component="Tooltip" role="tooltip" aria-hidden="true" id="_R_4mlala9lik5_">History</span></div></div></div></div></div><div class="d-flex flex-row"><div class="container BlobViewContent-module__blobContainer__DtH2d"><div class="react-code-size-details-banner BlobViewContent-module__codeSizeDetails__e5sUw"><div class="react-code-size-details-banner CodeSizeDetails-module__Box__VcD6l"><div class="text-mono CodeSizeDetails-module__Box_1__GVxQL"><div data-testid="blob-size" class="CodeSizeDetails-module__Truncate_1__lE93V prc-Truncate-Truncate-2G1eo" data-inline="true" title="42.7 KB" style="--truncate-max-width:100%"><span>516 lines (491 loc) · 42.7 KB</span></div></div></div></div><div class="react-blob-view-header-sticky BlobViewContent-module__stickyHeader__VwxB5" id="repos-sticky-header"><div class="BlobViewHeader-module__Box__yhm9u"><div class="react-blob-sticky-header"><div class="FileNameStickyHeader-module__outerWrapper__ZL4Xc FileNameStickyHeader-module__outerWrapperHidden__Zpynk"><div class="FileNameStickyHeader-module__Box_1__Hazu5"><div class="FileNameStickyHeader-module__Box_2__hoolP"><div class="FileNameStickyHeader-module__Box_3__MVKsk"><button data-component="Button" type="button" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-label="main branch" data-testid="anchor-button" data-icv-name="Switch branches/tags" class="prc-Button-ButtonBase-9n-Xk ref-selector-class RefSelectorAnchoredOverlay-module__RefSelectorOverlayBtn__a3WK3" data-loading="false" data-size="medium" data-variant="default" id="ref-picker-repos-header-ref-selector"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-git-branch" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M9.5 3.25a2.25 2.25 0 1 1 3 2.122V6A2.5 2.5 0 0 1 10 8.5H6a1 1 0 0 0-1 1v1.128a2.251 2.251 0 1 1-1.5 0V5.372a2.25 2.25 0 1 1 1.5 0v1.836A2.493 2.493 0 0 1 6 7h4a1 1 0 0 0 1-1v-.628A2.25 2.25 0 0 1 9.5 3.25Zm-6 0a.75.75 0 1 0 1.5 0 .75.75 0 0 0-1.5 0Zm8.25-.75a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5ZM4.25 12a.75.75 0 1 0 0 1.5.75.75 0 0 0 0-1.5Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3"><div class="RefSelectorAnchoredOverlay-module__RefSelectorOverlayContainer__yaf4p"><div style="max-width:125px" class="ref-selector-button-text-container RefSelectorAnchoredOverlay-module__RefSelectorBtnTextContainer__Di3rk"><span class="RefSelectorAnchoredOverlay-module__RefSelectorText__w_fmP">main</span></div></div></span><span data-component="trailingVisual" class="prc-Button-Visual-YNt2F prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-triangle-down" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="m4.427 7.427 3.396 3.396a.25.25 0 0 0 .354 0l3.396-3.396A.25.25 0 0 0 11.396 7H4.604a.25.25 0 0 0-.177.427Z"></path></svg></span></span></button><div class="d-none"></div></div><div class="FileNameStickyHeader-module__Box_4__FLhtt"><div class="Breadcrumb-module__container__Vxvev Breadcrumb-module__md__Wb1Gs"><nav data-testid="breadcrumbs" aria-labelledby="sticky-breadcrumb-heading" id="sticky-breadcrumb" class="Breadcrumb-module__nav__rQFDj"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading" id="sticky-breadcrumb-heading">Breadcrumbs</h2><ol class="Breadcrumb-module__list__ZH6zr"><li class="Breadcrumb-module__listItem__Ib0x_"><a class="Breadcrumb-module__repoLink__O2Nbs prc-Link-Link-9ZwDx" data-component="Link" data-testid="breadcrumbs-repo-link" href="/crafts69guy/herdr-switchboard/tree/main" data-discover="true">herdr-switchboard</a></li></ol></nav><div data-testid="breadcrumbs-filename" class="Breadcrumb-module__filename__equZR"><span class="Breadcrumb-module__separator__eNwsI Breadcrumb-module__md__Wb1Gs" aria-hidden="true">/</span><h1 class="Breadcrumb-module__filenameHeading__MNMtw Breadcrumb-module__md__Wb1Gs prc-Heading-Heading-MtWFE" data-component="Heading" tabindex="-1" id="sticky-file-name-id">CLAUDE.md</h1></div><button data-component="IconButton" type="button" class="prc-Button-ButtonBase-9n-Xk ml-2 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_7lcpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="CopyToClipboardIconButton-module__tooltip__WyiwL prc-TooltipV2-Tooltip-tLeuB" data-direction="s" data-component="Tooltip" aria-label="Copy path" aria-hidden="true" id="_R_7lcpala9lik5_">Copy path</span></div></div></div><button data-component="Button" type="button" class="prc-Button-ButtonBase-9n-Xk FileNameStickyHeader-module__Button__LSEU_ FileNameStickyHeader-module__GoToTopButton__nxAFn" data-loading="false" data-size="small" data-variant="invisible"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="leadingVisual" class="prc-Button-Visual-YNt2F prc-Button-LeadingVisual-UySKu prc-Button-VisualWrap-E4cnq"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-arrow-up" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M3.47 7.78a.75.75 0 0 1 0-1.06l4.25-4.25a.75.75 0 0 1 1.06 0l4.25 4.25a.751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018L9 4.81v7.44a.75.75 0 0 1-1.5 0V4.81L4.53 7.78a.75.75 0 0 1-1.06 0Z"></path></svg></span><span data-component="text" class="prc-Button-Label-FWkx3">Top</span></span></button></div></div></div><div class="BlobViewHeader-module__Box_1__VEmuQ"><h2 class="sr-only ScreenReaderHeading-module__userSelectNone__rwWIk prc-Heading-Heading-MtWFE" data-component="Heading" data-testid="screen-reader-heading">File metadata and controls</h2><div class="BlobViewHeader-module__Box_2__icUs2"><ul aria-label="File view" class="prc-SegmentedControl-SegmentedControl-lqIXp BlobTabButtons-module__SegmentedControl__jen2u" data-variant="default" data-size="small" data-component="SegmentedControl"><li class="prc-SegmentedControl-Item-tSCQh" data-selected="" data-component="SegmentedControl.Button"><button aria-pressed="true" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:transparent"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Preview">Preview</div></span></button></li><li class="prc-SegmentedControl-Item-tSCQh" data-component="SegmentedControl.Button"><button aria-pressed="false" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:var(--borderColor-default)"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Code">Code</div></span></button></li><li class="prc-SegmentedControl-Item-tSCQh" data-component="SegmentedControl.Button"><button aria-pressed="false" class="prc-SegmentedControl-Button-E48xz" type="button" style="--separator-color:var(--borderColor-default)"><span class="prc-SegmentedControl-Content-1COlk segmentedControl-content"><div class="prc-SegmentedControl-Text-7S2y2 segmentedControl-text" data-text="Blame">Blame</div></span></button></li></ul><div class="d-none"></div><div class="react-code-size-details-in-header CodeSizeDetails-module__Box__VcD6l"><div class="text-mono CodeSizeDetails-module__Box_1__GVxQL"><div data-testid="blob-size" class="CodeSizeDetails-module__Truncate_1__lE93V prc-Truncate-Truncate-2G1eo" data-inline="true" title="42.7 KB" style="--truncate-max-width:100%"><span>516 lines (491 loc) · 42.7 KB</span></div></div></div></div><div class="BlobViewHeader-module__Box_3__ng6v2"><div class="d-none"></div><div class="react-blob-header-edit-and-raw-actions BlobViewHeader-module__Box_4__J4Y4W"><div class="d-none"></div><div class="prc-ButtonGroup-ButtonGroup-vFUrY" data-component="ButtonGroup"><div class="prc-ButtonGroup-Item-PqvDl"><a data-component="LinkButton" href="https://github.com/crafts69guy/herdr-switchboard/raw/refs/heads/main/CLAUDE.md" data-testid="raw-button" class="prc-Button-ButtonBase-9n-Xk LinkButton-module__linkButton__nFnov BlobViewHeader-module__LinkButton__X9kx2" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default"><span data-component="buttonContent" data-align="center" class="prc-Button-ButtonContent-Iohp5"><span data-component="text" class="prc-Button-Label-FWkx3">Raw</span></span></a></div><div class="prc-ButtonGroup-Item-PqvDl"><button data-component="IconButton" type="button" data-testid="copy-raw-button" class="prc-Button-ButtonBase-9n-Xk prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-labelledby="_R_qaucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-copy" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_qaucpala9lik5_">Copy raw file</span></div><div class="prc-ButtonGroup-Item-PqvDl"><button data-component="IconButton" type="button" data-testid="download-raw-button" class="prc-Button-ButtonBase-9n-Xk BlobViewHeader-module__downloadButton__ef459 prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="default" aria-labelledby="_R_eaucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-download" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M2.75 14A1.75 1.75 0 0 1 1 12.25v-2.5a.75.75 0 0 1 1.5 0v2.5c0 .138.112.25.25.25h10.5a.25.25 0 0 0 .25-.25v-2.5a.75.75 0 0 1 1.5 0v2.5A1.75 1.75 0 0 1 13.25 14Z"></path><path d="M7.25 7.689V2a.75.75 0 0 1 1.5 0v5.689l1.97-1.969a.749.749 0 1 1 1.06 1.06l-3.25 3.25a.749.749 0 0 1-1.06 0L4.22 6.78a.749.749 0 1 1 1.06-1.06l1.97 1.969Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_eaucpala9lik5_">Download raw file</span></div></div></div><button data-component="IconButton" type="button" aria-pressed="false" class="prc-Button-ButtonBase-9n-Xk tmp-mr-2 TableOfContents-module__IconButton__jrlNM prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_3ucpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-list-unordered" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M5.75 2.5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5Zm0 5h8.5a.75.75 0 0 1 0 1.5h-8.5a.75.75 0 0 1 0-1.5ZM2 14a1 1 0 1 1 0-2 1 1 0 0 1 0 2Zm1-6a1 1 0 1 1-2 0 1 1 0 0 1 2 0ZM2 4a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="n" data-component="Tooltip" aria-hidden="true" id="_R_3ucpala9lik5_">Outline</span><div class="react-blob-header-edit-and-raw-actions-combined"><button data-component="IconButton" type="button" title="More file actions" data-testid="more-file-actions-button" aria-haspopup="true" aria-expanded="false" tabindex="0" class="prc-Button-ButtonBase-9n-Xk js-blob-dropdown-click BlobViewHeader-module__IconButton__XrMQY prc-Button-IconButton-fyge7" data-loading="false" data-no-visuals="true" data-size="small" data-variant="invisible" aria-labelledby="_R_fkecpala9lik5_" id="_R_kecpala9lik5_"><svg data-component="Octicon" aria-hidden="true" focusable="false" class="octicon octicon-kebab-horizontal" viewBox="0 0 16 16" width="16" height="16" fill="currentColor" display="inline-block" overflow="visible" style="vertical-align:text-bottom"><path d="M8 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3ZM1.5 9a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Zm13 0a1.5 1.5 0 1 0 0-3 1.5 1.5 0 0 0 0 3Z"></path></svg></button><span class="prc-TooltipV2-Tooltip-tLeuB" data-direction="nw" data-component="Tooltip" aria-hidden="true" id="_R_fkecpala9lik5_">Edit and raw actions</span></div></div></div></div><div></div></div><div class="BlobViewContent-module__blobContentWrapper__JS0W6"><section aria-labelledby="file-name-id-wide file-name-id-mobile" class="BlobContent-module__blobContentSection__VOgZq BlobContent-module__blobContentSectionMarkdown__mPLOK" style="margin-top:46px"><div class="js-snippet-clipboard-copy-unpositioned BlobContent-module__markdownBlob__T8jpG" data-hpc="true" containertiming="hpc"><article class="markdown-body entry-content container-lg" itemprop="text"><div class="markdown-heading" dir="auto"><h1 tabindex="-1" class="heading-element" dir="auto">CLAUDE.md</h1><a id="user-content-claudemd" class="anchor" aria-label="Permalink: CLAUDE.md" href="#claudemd"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">What this is</h2><a id="user-content-what-this-is" class="anchor" aria-label="Permalink: What this is" href="#what-this-is"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">A <a href="https://herdr.dev" rel="nofollow">herdr</a> plugin providing a unified switcher over running herdr <strong>agents</strong>,
open herdr <strong>workspaces</strong>, <strong>ghq repos</strong>, and linked Git <strong>worktrees</strong> in one fuzzy picker. It is a
Rust TUI (ratatui + nucleo), not an fzf wrapper. Every surface is a mode of the same binary,
selected by argv (<code>--menu</code>, <code>--agents</code>, <code>--usage</code>, <code>--commands</code>, <code>--ports</code>, <code>--zen</code>,
<code>--changelog</code>, <code>--settings</code>, <code>--git</code>; no flag is the switcher); the settings form is <strong>also</strong> a
floating overlay inside the switcher (⌥,), not only a pane. <strong><code>--usage</code> is the only mode that reads
a credential and the only in-process HTTP client</strong> — both fenced, see the constraints below. Git
can fetch pull requests through <code>gh</code> only when that row is activated, and update checks use a
detached <code>git ls-remote</code> child. The <strong>git menu is a herdr pane of its own</strong> (<code>Prefix + g</code> →
<code>bin/git.sh</code> → <code>--git</code>), not an overlay on the switcher, and its selection <code>exec</code>s a review tool
over that pane. The review launcher (<code>bin/review.sh</code>, which runs
<code>tuicr</code>/<code>lazygit</code>), the guarded updater, and <code>bin/picker.sh</code>'s one-time bootstrap feedback are the
Bash terminal owners. The plugin needs no fzf.
See <code>README.md</code> for user-facing keybindings and configuration.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Commands</h2><a id="user-content-commands" class="anchor" aria-label="Permalink: Commands" href="#commands"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="cargo build                                  # debug binary
cargo build --release                        # what bin/picker.sh actually launches
cargo test                                   # unit tests (sorting, group filter, history parsing)
cargo test recent_sort_puts_latest_opened_first   # single test by name
bash bin/check.sh                            # complete local/CI/release gate
bash bin/coverage.sh                         # line coverage, gated at 98% (CI runs this too)
bash bin/coverage.sh --open                  # ... and open the annotated HTML report
bash bin/release.sh 0.5.0                    # cut a release (gates, bump, changelog, tag, gh release)

herdr plugin link /path/to/herdr-switchboard         # install this checkout for manual testing
herdr server reload-config                   # after touching keybindings/config
herdr plugin config-dir switchboard          # where the runtime config.toml lives"><pre>cargo build                                  <span class="pl-c"><span class="pl-c">#</span> debug binary</span>
cargo build --release                        <span class="pl-c"><span class="pl-c">#</span> what bin/picker.sh actually launches</span>
cargo <span class="pl-c1">test</span>                                   <span class="pl-c"><span class="pl-c">#</span> unit tests (sorting, group filter, history parsing)</span>
cargo <span class="pl-c1">test</span> recent_sort_puts_latest_opened_first   <span class="pl-c"><span class="pl-c">#</span> single test by name</span>
bash bin/check.sh                            <span class="pl-c"><span class="pl-c">#</span> complete local/CI/release gate</span>
bash bin/coverage.sh                         <span class="pl-c"><span class="pl-c">#</span> line coverage, gated at 98% (CI runs this too)</span>
bash bin/coverage.sh --open                  <span class="pl-c"><span class="pl-c">#</span> ... and open the annotated HTML report</span>
bash bin/release.sh 0.5.0                    <span class="pl-c"><span class="pl-c">#</span> cut a release (gates, bump, changelog, tag, gh release)</span>

herdr plugin link /path/to/herdr-switchboard         <span class="pl-c"><span class="pl-c">#</span> install this checkout for manual testing</span>
herdr server reload-config                   <span class="pl-c"><span class="pl-c">#</span> after touching keybindings/config</span>
herdr plugin config-dir switchboard          <span class="pl-c"><span class="pl-c">#</span> where the runtime config.toml lives</span></pre></div>
<p dir="auto"><code>bin/check.sh</code> is the single full-gate interface for local sessions, CI, and releases. Layout,
keybinding, or Herdr CLI changes still need manual exercise in a real Herdr session in addition to
Rust render tests.</p>
<p dir="auto">Coverage is deliberately <strong>not</strong> part of <code>check.sh</code>: it needs its own instrumented build, which
would turn the ~5s gate you run constantly into a ~90s one. CI runs <code>bin/coverage.sh</code> as a separate
job. It needs <code>rustup component add llvm-tools-preview</code> and <code>cargo install cargo-llvm-cov --locked</code>;
the script prefers a rustup toolchain when one carries the tools, because a Homebrew rust can sit
first on PATH beside a perfectly good rustup toolchain and only the latter can instrument.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Architecture</h2><a id="user-content-architecture" class="anchor" aria-label="Permalink: Architecture" href="#architecture"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto"><strong>Two layers, joined by environment variables.</strong> Every action starts in bash and may end in Rust:</p>
<ol dir="auto">
<li><code>bin/action.sh</code> is the single entrypoint for all manifest actions. It maps the action id
(via <code>HERDR_PLUGIN_ACTION_ID</code>) to a pane id (<code>picker</code> / <code>git</code> / <code>get</code> overlays, <code>changelog</code>
popup) and its placement, captures the <strong>origin pane id and cwd</strong> before the pane steals focus,
and passes them forward as
<code>SWITCHBOARD_ORIGIN_PANE_ID</code> / <code>SWITCHBOARD_ORIGIN_CWD</code> on <code>herdr plugin pane open</code>. The <code>git</code> action opens the
dedicated <code>git</code> pane; that pane acts on a <strong>cwd</strong>, not a pane id.</li>
<li><code>bin/picker.sh</code> resolves a versioned, checksummed release binary for managed installs and
falls back to Cargo for offline/linked checkouts. Its Bash typing-cat owns first-run feedback;
<code>--prepare</code> resolves the binary without launching it.</li>
<li>The TUI (<code>src/</code>) claims the terminal and draws the final Projects chrome immediately with a
static <code>Standing by…</code> state while a feature-local worker loads the catalogue. Completion returns
through a typed, generation-tagged effect; an empty initial result opens the Clone form.
<code>surface::run</code> hosts the Projects surface and guarantees terminal
restoration before an open outcome runs. Interactive accepts (repository remove
confirmation, <code>ghq get -u</code> output) deliberately run on the restored terminal. Linked-worktree
removal instead confirms in a modal TUI overlay and runs through a typed background effect.</li>
</ol>
<p dir="auto"><strong>Why the origin pane matters:</strong> <code>split</code> and <code>pane</code> targets act on the captured <code>SWITCHBOARD_ORIGIN_PANE_ID</code>.
The overlay pane is <em>not</em> the user's pane. Never guess or infer a pane/workspace/agent id — every id
must come from <code>herdr agent list</code>, <code>herdr workspace list</code>, or the captured origin.</p>
<p dir="auto"><strong>Module ownership:</strong> current file ownership and module seams live only in
<code>docs/architecture.md</code>. Keep this file focused on non-obvious invariants; when moving or
splitting code, update the architecture document in the same commit and run
<code>bash tests/docs_spec.sh</code>.</p>
<p dir="auto"><strong>Sort vs. search:</strong> fuzzy score always wins while a query is present; <code>SortMode</code> (recent/name/kind)
only orders the resting, no-query list. Both paths honour the <code>GroupFilter</code>. Ties break on load
order so the list stays stable.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Non-obvious constraints</h2><a id="user-content-non-obvious-constraints" class="anchor" aria-label="Permalink: Non-obvious constraints" href="#non-obvious-constraints"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<ul dir="auto">
<li><strong>herdr draws the pane frame; the TUI must not compete with it.</strong> Every plugin pane is
<code>popup</code> or <code>overlay</code>, and herdr frames both and requires a non-empty title. So a pane
title is a <strong>single icon</strong> (<code>󰊢</code>, <code>󰍜</code>, <code>󰆍</code>, <code>󰛳</code>) and the human-readable mode name goes on
the <em>list panel</em> inside — word titles on both produced <code>Ports</code> twice, two rows apart.
For the same reason the plugin's own borders recede in <code>overlay0</code> while herdr's frame
keeps the accent. <strong>Background policy belongs only to <code>tui::SurfaceBackground</code>:</strong>
<code>common.transparency = "transparent"</code> clears every root and floating card to the terminal
default, while <code>"opaque"</code> fills every one with <code>panel_bg</code>. A renderer never hand-writes
<code>Clear</code> or <code>.bg(panel_bg)</code> for a surface. <code>panel_bg</code> remains the foreground ink on coloured
pills and mode chips in either mode. Tests in <code>picker.rs</code>, <code>projects.rs</code>, and <code>git.rs</code>
(<code>the_search_box_is_captioned_search_and_the_list_carries_the_mode_title</code>,
<code>panels_use_the_projects_pickers_border_and_caption_slots</code>,
<code>no_panel_paints_an_opaque_background</code>, and the opaque-mode contracts) pin this down.</li>
<li><strong>There is one panel frame, <code>tui::framed</code>, and every framed surface goes through it or
through <code>tui::boxed</code></strong> (the same frame plus a caption, and defined in terms of it, so the
border style is spelled once). It lived in <code>ui.rs</code> while <code>picker.rs</code> hand-rolled its own
<code>Block</code>s, and the two drifted exactly as you would expect: accent borders instead of
<code>overlay0</code>, and captions passed as bare <code>&amp;str</code> so they rendered in the terminal's default
foreground rather than <code>title_color</code>. <code>git.rs</code> drifted the same way and went further, filling
all three of its cards with <code>panel_bg</code> — the transparency bug that shipped in 1.2.0. A new
framed surface calls <code>boxed</code>, or <code>framed</code> when its caption slot holds something richer than a
word (the switcher's tab strip); it does not build a <code>Block</code> itself.</li>
<li><strong>The git menu is a pane, and a review <code>exec</code>s over that pane.</strong> There is a manifest pane for
the <em>menu</em> (<code>[[panes]] id = "git"</code>), but <strong>none for the review</strong>: <code>git::main</code> <code>exec</code>s
<code>bin/review.sh</code> over itself, so tuicr
inherits the pane and quitting it returns to the pane <code>Prefix + g</code> was pressed in. The pane's
placement must stay <strong>full-frame <code>overlay</code></strong> — tuicr renders into whatever window it is handed,
and a popup would hand it a tiny one. The picker knows nothing about git: there is no <code>⌥g</code>, no
<code>Accept::Git</code>, no <code>App::git</code>. Two entry points would drift apart, and only one of them can be
the fast one. <code>tuicr</code> is a TUI — never run it non-interactively (it blocks); only ever in a pane.</li>
<li><strong>Saved-review integration never takes ownership of tuicr content.</strong> A handoff is a pointer-only,
non-blocking effect whose inputs are the repository, session slug, and a pane id returned by
<code>herdr agent list</code>; delivery uses <code>herdr agent prompt</code> without <code>--wait</code>. Archive state contains
only exact session slugs and changes Switchboard visibility, never tuicr's session JSON. Comment
bodies never enter Switchboard state, logs, notifications, or another command line.
<code>docs/git-menu.md</code> owns the user-facing archive, target-selection, and fallback behaviour.</li>
<li><strong>Agent handoffs share one target seam and never wait for a turn.</strong> <code>agent_handoff.rs</code> is the only
owner of promptable-agent parsing, same-worktree/origin selection, and <code>herdr agent prompt</code>;
neither Git nor Projects adds <code>--wait</code>. Projects sends only JSON-escaped item kind, label, and
absolute path as data-only context. Paths and labels never enter notifications or traces, and a
Workspace never pretends its several pane directories are one selectable path.</li>
<li><strong>Projects catalogue discovery is a feature-local background effect.</strong> Startup draws the final
Search/Context/Navigator/Preview geometry first and shows static <code>Standing by…</code>; it accepts only
Close until the generation-tagged completion arrives. Settings Apply keeps the old rows visible
under <code>Refreshing…</code>, locks selection-dependent actions, and restores selection by entry ID.
There is no minimum-visible floor. Repository and worktree discovery share one <code>ghq list --full-path</code>
snapshot, and per-repository worktree probes use at most four threads while their results are
installed in snapshot order. Full paths are retained across all ghq roots; durable IDs stay
relative to the longest matching root. An empty initial catalogue opens the Clone form in place.</li>
<li><strong>Clone never asks for credentials in the TUI.</strong> Git/SSH use configured credential helpers
and agents with interactive prompts disabled. The URL form rejects embedded credentials;
external clone output is never drawn, traced, or logged. Cancellation stops and reaps the
entire child process group before allowing another clone, and never deletes partial directories.
Default completion refreshes/selects; explicit <code>clone.open_after = true</code> returns a typed open
outcome so Herdr work still runs after terminal restoration.</li>
<li><strong>Projects stars are durable-entry state, not another source.</strong> Only Repo and Worktree identities
can be starred; Agent and Workspace IDs are live and must never enter the persistent set. The
final Starred group filters the already-loaded catalogue and keeps its search, sort, and actions.
<code>projects::stars</code> owns typed identity and mutation; <code>state</code> owns the private tempfile, atomic
replace, and cross-process lock around the complete read-modify-write transaction. Writes return
through a typed Projects effect before the reducer changes the marker or list. Missing or
malformed state degrades to no stars and must never block the first Projects frame.</li>
<li><strong>The pre-build cat runs before Rust exists and sizes itself from the plugin PTY.</strong>
<code>run_with_splash</code> reads <code>stty size &lt;/dev/tty</code> and passes those cells to <code>bootstrap_frame</code> on each
animation frame. Do not replace it with <code>tput</code>: redirecting <code>tput</code> away from the TTY makes it
return terminfo's 80x24 default in a wide Herdr pane. Horizontal padding is spaces; vertical
padding is rows. <code>tests/bootstrap_spec.sh</code> pins both coordinates.</li>
<li><strong>A list fetch runs outside <code>Git::on_key</code> and off the input thread.</strong> <code>on_key</code> returns a <code>Step</code>;
<code>GitSurface</code> turns <code>Step::Load</code> and <code>Step::CountFiles</code> into typed background effects, then applies
their results from <code>on_tick</code>. That keeps the key interface IO-free and unit-testable through
<code>MockRunner</code>, while <code>gh pr list</code> leaves the menu responsive instead of freezing a half-drawn list.</li>
<li><strong>Nothing writes to tuicr's config.</strong> The theme is a whole file that
<a href="https://github.com/crafts69guy/hue-theme">hue-theme</a> owns
(<code>~/.config/tuicr/themes/hue-&lt;mood&gt;.toml</code>, 41 keys, none optional). tuicr <strong>exits 2</strong> on a theme
it cannot fully resolve, and <code>--theme</code> on a mismatched name takes the whole review path down —
so <code>bin/review.sh</code> never passes <code>--theme</code> and <code>ensure_tuicr</code> only checks the binary exists.</li>
<li><strong>Open + config live in Rust.</strong> The clone form uses the same restored open dispatch as Projects;
<code>bin/get.sh</code> only launches <code>--clone</code>. The <code>open</code> and <code>config get</code> CLI interfaces remain available,
so the Herdr open verbs (<code>src/action.rs::open_target</code>) and typed config reader (<code>Config::load</code>)
live in one place. <code>bin/lib.sh</code> keeps <code>ensure_built</code> (build-on-demand, shared by the picker entrypoints),
<code>toml_get</code> (used only by <code>configure_notifications</code>, the pre-build notification path that must not
depend on a cargo build), and the pane-context/JSON helpers. <strong>A change to how a target opens
lands only in <code>action.rs</code>.</strong></li>
<li><strong>fnm activation is opt-in, local, and post-selection.</strong> <code>[fnm].enabled</code> defaults off. Preview
reads declarations from disk only; <code>fnm exec --using &lt;repo&gt; -- printenv PATH</code> runs after an open
is accepted, never installs a version, and never performs network work. Fresh targets receive
that PATH through Herdr's <code>--env</code> and never receive post-create terminal input; shell startup
owns session-local initialization and must preserve the launch PATH or activate the initial cwd.
The current-pane target remains <code>cd</code>-only and relies on fnm's standard <code>--use-on-cd</code> shell hook.</li>
<li><strong>The Node Versions manager is the only explicit fnm mutation surface.</strong> It loads installed
versions locally, runs <code>fnm list-remote</code> on a worker only after the user opens the dedicated
pane, and performs install/default/uninstall after terminal restoration. <code>use</code> is sent to the
captured origin pane because a child process cannot change its parent shell; uninstall requires
the exact selected version as typed confirmation.</li>
<li><strong>Settings has two presentations, not two renderers.</strong> The embedded form is a centred floating
card because it overlays Projects. The standalone action already lives in a Herdr-framed popup,
so it draws the same form full-area with a content margin and no second border or duplicate
title. Both presentations share the columns, tabs, hit zones, hints, and command bar.</li>
<li><strong>Configuration is typed and namespaced.</strong> <code>config.rs</code> deserializes the section structs with
<code>deny_unknown_fields</code>; Rust code reads those fields directly. <code>Config::value_for_cli</code> is the
deliberately narrow compatibility seam for Bash's <code>config get</code> calls, not an internal
lookup interface. <code>settings.rs</code> writes namespaced values through <code>toml_edit</code>, preserving comments
and hand-added keys before validating the complete result. <strong>Every picker has a <code>[keys.*]</code> table</strong>
— <code>projects</code>, <code>agents</code>, <code>commands</code>, <code>ports</code>, <code>zen</code>, <code>menu</code>, <code>fnm</code> — reached through
<code>PickerMode::key_bindings</code> plus a <code>reload_config</code> that re-reads it; a mode that implements neither
is one whose keys nobody can move, which is what Menu and the fnm manager silently were.</li>
<li><strong>A click zone is measured by the loop that draws the thing.</strong> <code>tab_zones</code> and
<code>footer_zones</code> (<code>src/projects/view.rs</code>) are built inside the same loops that lay out the tab strip
and the command bar, because a zone computed separately drifts the moment a label
changes — and drifts <em>silently</em>, into clicking the wrong action. <code>list_state</code> is kept
on the <code>App</code> for the same reason: its scroll offset is the only thing that turns a
clicked row back into an entry, so it cannot be a fresh <code>ListState</code> per frame.</li>
<li><strong>The cheatsheet's descriptions must fit <code>HELP_DESC</code></strong> (<code>src/projects/view.rs</code>) — the popup's half
width less the key pill, around 19 columns. A longer one is cut with no ellipsis, so it
ships looking like a shorter phrase; <code>wheel  Scroll whatever is under it</code> reached a
README screenshot as <code>Scroll whatever is</code>. <code>row</code> asserts, and a <code>TestBackend</code> render
test in <code>projects.rs</code> fires it.</li>
<li><strong>A prefix names the kind of work, never the mode.</strong> <code>^&lt;key&gt;</code> acts on the selected row; <code>⌥&lt;key&gt;</code>
changes the view or the app (or is the heavier form of the <code>^</code> verb on the same letter, as
Ports' <code>^x</code> TERM / <code>⌥x</code> KILL); <code>↵</code> runs the row's primary action with <code>^↵</code>/<code>⌥↵</code> as its variants.
So <strong>every modified chord appears in both <code>default_insert</code> and <code>default_normal</code> with the same
action</strong>, and Normal's bare letters are <em>aliases carrying the same letter</em>, never a respelling.
Three tests in <code>keymap.rs</code> enforce exactly this and are the reason the layout stops drifting:
<code>every_modified_chord_means_the_same_thing_in_both_modes</code>,
<code>no_action_straddles_the_ctrl_and_alt_families</code>, and
<code>a_bare_alias_carries_the_same_letter_as_its_chord</code>. Two vocabularies are carved out by name in
<code>mode_idiomatic</code>: motion (readline in Insert, Vim in Normal) and query editing (<code>^u</code> clear,
<code>⌥⌫</code> delete-word, Insert-only). <code>^u</code> and <code>^c</code> are reserved on every surface — no <code>ActionSpec</code>
may take them, which is why the fnm manager's <code>use</code>/<code>install</code> sit on the <code>↵</code> ladder.
<strong>A chord that is somebody's multiplexer prefix never reaches the pane at all</strong>, so opening in a
tab is the mnemonic-free <code>^e</code>: herdr's default prefix is <code>^b</code> and <code>^t</code> is the usual tmux-refugee
alternative, so the open group avoids both. <code>^b</code> is refused by
<code>no_default_chord_takes_herdrs_prefix</code> and by the shared picker's check; do not "fix" <code>^e</code> into
<code>^t</code>, and do not reclaim <code>^b</code> for anything.
<strong>There is no <code>␣</code> leader, and adding one back is the bug.</strong> Space can only be a leader in Normal
— in Insert it is a character the user is typing — so any group living there was forced to change
prefix with the mode, which is the whole inconsistency this layout removes. The Git menu, the
Central Menu, the settings form, and the Usage/changelog viewers sit outside the rule on purpose:
their keys name a row, a destination, or a form field rather than a verb on a selection.</li>
<li><strong>The shared picker answers five chords itself, and they live in one table.</strong> <code>RESERVED</code>
(<code>src/picker.rs</code>) holds <code>⌥,</code>, <code>⌥j</code>, <code>⌥k</code>, <code>⇥</code>, <code>⇧⇥</code>; <code>PickerSurface::on_key</code> dispatches from it
through <code>reserved_for</code>, <em>ahead</em> of any <code>ActionSpec</code>. They used to be five hand-written <code>if</code>s that
nothing checked against, so a mode declaring one of those chords had its action swallowed with no
error — the same silent shape as Ports' <code>^w</code>, which shadowed delete-word for that picker alone.
A new <code>ActionSpec</code> is therefore checked by <code>picker::assert_follows_prefix_concept</code>, which every
mode calls from its <strong>own</strong> test module (the modes are private to their files, so the check
travels to them). It refuses a bare <code>Char</code> (it would be matched ahead of the typing arm and make
that letter untypeable), <code>^c</code>/<code>^u</code>, anything in <code>RESERVED</code>, a <code>key_label</code> that is not the chord it
listens for, and a shared action id bound to a chord it does not carry elsewhere.
<code>the_prefix_concept_check_rejects_every_shape_it_names</code> asserts the guard actually bites, because
a guard that silently passes is the failure it exists to prevent.</li>
<li><strong>One keypress gets one answer, and <code>same_chord</code> is where that is decided.</strong> Matching weighs only
CTRL and ALT, exactly as <code>keymap::chord_of</code> does: SHIFT is already baked into the character a
terminal reports and terminals disagree about whether they set the bit too. <code>ActionSpec::matches</code>
compared modifier bits with <code>==</code> while the keymap used <code>contains</code>, so the same press acted in
Projects and did nothing in every other picker — <code>⇧↵</code> ran the row in one and was inert in the
other, and a <code>^⇧</code> chord missed its <code>^</code> action outright. Because SHIFT no longer separates two
chords, <code>assert_follows_prefix_concept</code> also refuses two specs that normalise to the same chord;
without that rule the second one would simply never run.</li>
<li><strong>Keys are a config-driven keymap, not hardcoded <code>match</code> arms.</strong> <code>handle_key</code> resolves a
<code>Chord</code> through <code>App::keymap</code> (<code>src/keymap.rs</code>) and runs <code>apply_action</code>. Two ordered tables
(Insert + Normal); typed <code>common.keymode</code> defaults to Normal and <code>esc</code> toggles Insert↔Normal.
<code>[keys.projects]</code> entries rebind actions (first chord wins as the shown one) into <strong>both</strong> tables,
so an override cannot reintroduce a per-mode split.
<strong>The footer (<code>draw_footer</code>) and the cheatsheet (<code>draw_help</code>) render from the keymap via
<code>Keymap::label_for(mode, action)</code></strong>, so both re-label per remap — never hardcode a
key cap in either; add the action to the curated list and it picks up its live chord. A row
whose action is unbound in the current mode drops out. <code>label_for</code> returns the <em>first</em> matching
chord, which is why a bare alias is listed after the chord it shadows.
Adding an action is one row in <code>keymap::NAMES</code>, its default chord in <strong>both</strong> tables, and an
<code>apply_action</code> arm; a new <code>Accept</code> also needs the footer curated list and <code>dispatch</code>. Cheatsheet
descriptions must still fit <code>HELP_DESC</code>.</li>
<li><strong>One frame absorbs every event already queued, and a list row borrows rather than copies.</strong>
These two are one fact from opposite ends. A terminal delivers a wheel turn or a held key as a
burst, and <code>surface::run</code> used to answer each with its own full repaint; meanwhile <code>draw_list</code>
(<code>projects/view.rs</code>) and the shared picker's row builder cloned every column of every <em>filtered</em>
entry per frame — including the rows a <code>List</code> scrolls past and never paints, over a Commands
catalogue that is <code>commands.history_limit</code> (5,000) rows deep by default. So a burst multiplied a
per-entry cost that was already linear. <code>drain_frame</code> now takes queued input up to
<code>MAX_COALESCED_EVENTS</code> before repainting — the cap is what stops a paste from starving the
screen — and rows borrow out of <code>state.items</code> / <code>picker.entries</code>, which is why both draw
functions destructure their <code>&amp;mut</code> state into disjoint field borrows and why the shared picker
moves its <code>ListState</code> out with <code>mem::take</code> before building rows. Padding comes from
<code>tui::spaces</code>, a slice of one static. Do not "tidy" a row builder back to <code>to_string()</code>: it
compiles, it looks identical, and it silently restores the whole cost.</li>
<li><strong><code>Stars::contains</code> and the tab counts must not allocate or rescan.</strong> <code>contains</code> is asked once
per entry per keystroke by the reducer, once per entry per group by the Context panel, and once
per entry per frame by the list. It answers from <code>StarSet</code>, which stores one ID set <em>per kind</em> so
the probe is a borrowed <code>&amp;str</code>; a <code>BTreeSet&lt;StarKey&gt;</code> cannot, because building the probe key
means cloning the entry's ID. <code>StarKey</code> stays the on-disk shape, so the file is unchanged.
Tab counts are cached on <code>Picker</code> and rebuilt by <code>recount</code> at the three points that can
invalidate them — construction, <code>replace_stars</code>, <code>replace_entries</code> — never in <code>recompute</code>, which
runs per keystroke and cannot change them. A stale cache here fails silently, so
<code>tab_counts_are_rebuilt_whenever_the_entries_or_the_stars_change</code> checks every tab against a
fresh scan.</li>
<li><strong>A probe that a <code>read_dir</code> can rule out must not be a process.</strong> <code>may_have_worktrees</code>
(<code>data.rs</code>) asks whether <code>.git/worktrees/</code> has anything in it before spending a <code>git worktree list</code> on a repository, because that probe runs once per <em>ghq repository</em> — hundreds of forks for
the handful of repositories that actually have linked worktrees. It <strong>fails open</strong>: a <code>.git</code>
<em>file</em> (this path is itself a linked worktree or a submodule) and an unreadable directory both
still probe, since a wrong "no" loses a worktree from the catalogue silently while a wrong "yes"
costs one subprocess. <code>the_worktree_prefilter_only_refuses_what_the_filesystem_settles</code> pins
every case.</li>
<li><strong>Independent reads that each pay a process start are overlapped, and only those.</strong>
<code>projects/effect.rs</code> overlaps <code>ghq root</code> with <code>ghq list</code>, <code>source.rs</code> overlaps <code>herdr agent list</code>
with <code>herdr workspace list</code>, and <code>repo_card</code> (<code>projects/preview.rs</code>) fans out branch, dirty
state, last commit, and the <code>preview.sh</code> tree so the card costs the slowest rather than their
sum. This is only sound because every one of them is an independent <em>read</em>. Nothing that mutates,
and nothing whose result another call depends on, goes in a scope like these.</li>
<li><strong><code>state.rs</code> owns every durable write, and a read-modify-write is one locked transaction.</strong>
Five callers used to hand-roll <code>fs::write</code> to a <strong>fixed</strong> <code>.tmp</code> sibling and rename — so two
Switchboard processes writing the same file raced on one temp name, and <code>history</code> and
<code>review_archive</code>, which load-modify-write, silently erased each other's rows. All of them now go
through <code>state</code>: <code>write_private</code> / <code>update_private</code> for this plugin's own state (owner-only), and
<code>replace_atomically</code> for a file the <em>user</em> owns — its own <code>config.toml</code> and, for zen chrome,
herdr's — which gains the lock and the unique tempfile but keeps the mode its owner gave it. A
new persistent file adds no sixth implementation.</li>
<li><strong>The mouse is turned on by hand, and must be turned off on every exit path.</strong> <code>surface.rs</code>
writes <code>?1000h</code>/<code>?1006h</code> itself rather than using crossterm's <code>EnableMouseCapture</code>, which
also enables any-event tracking (<code>?1003h</code>) — every pointer move would wake the loop into
a redraw for an event we discard. <code>?1000h</code> reports the wheel <em>and</em> buttons, which is
exactly what every surface consumes; drags stay herdr's, which runs with
<code>mouse_capture = true</code>. The universal host pairs claim/restore and
chains the disable ahead of the panic hook <code>ratatui::init</code> installs,
since that hook restores the screen but knows nothing about the mouse. Leaving it on
drops mouse escapes into the user's shell. <strong>Every new terminal mode implements <code>Surface</code> and
runs through <code>surface::run</code>; it never calls <code>ratatui::init</code> or reads crossterm events itself.</strong></li>
<li><strong>A click selects; a click on the already-selected row acts.</strong> Terminals report no
double-click (crossterm gives <code>Down</code> only), so single-click-to-run would let a stray
click <code>exec</code> tuicr over a pane or write a setting, and a timestamp heuristic would put
the same guesswork in five places. A command-bar pill carries the <strong>key printed on its
cap</strong> as its payload and routes through <code>on_key</code>, so the label cannot drift from the
behaviour. The rule is the same in <code>projects.rs</code>, <code>picker.rs</code>, <code>git.rs</code> and <code>settings.rs</code>;
what is shared between them is <code>tui::zone_at</code>, the lookup — never the measurement, which
stays in the loop that draws the thing.</li>
<li><strong>Picker command bars may wrap, but their hit zones wrap with them.</strong> <code>PickerMode</code> defaults to
one action row; the Central Menu requests two because it exposes every direct route. The picker
balances whole pills by their rendered widths, leaves one terminal row between wrapped rows,
measures each row with <code>tui::pill_row</code>, and stores the row coordinate beside its zones. Never
split or reposition the spans independently of those zones.</li>
<li><strong>The preview clips; it must never wrap.</strong> Every body goes through <code>clip</code>/<code>clip_line</code>
(<code>src/projects/preview.rs</code>) so one card line is exactly one screen row — that is what makes
<code>preview_scroll</code> mean what it says and <code>preview_len</code>/<code>preview_rows</code> bound it correctly.
<code>draw_preview</code> therefore has no <code>Wrap</code>. Re-adding one, or emitting an unclipped line,
breaks the scroll silently: the offset drifts from the content instead of erroring. The
pane's width reaches the worker through <code>App::preview_width</code>, published by <code>projects/view.rs</code>, which is
why <code>ProjectsSurface::after_draw</code> requests a preview only after the host has drawn geometry.</li>
<li><strong>Nothing uses <code>jq</code> — keep it that way.</strong> No code path shells out to it: the bash layer reads
herdr's JSON with the awk-based <code>json_string_value</code> / <code>json_bool_value</code> in <code>bin/lib.sh</code>, and the
Rust layer uses <code>serde_json</code> (<code>data.rs</code>, <code>projects/preview.rs</code>). It is not a documented requirement, so a
new jq call would be a new hard dependency on a machine that may not have it — and a silent one,
since a missing jq fails the same way a wrong filter does: empty output, no error.</li>
<li><strong><code>SWITCHBOARD_FORCE_TARGET</code> overrides <code>default_target</code> for Enter, repos only.</strong> <code>bin/action.sh</code> exports it
for the <code>open-workspace</code> / <code>open-tab</code> / <code>open-split</code> hot-path actions; <code>src/action.rs</code>
(<code>forced_target</code> + <code>resolve_default_target</code>) resolves it once in <code>main</code> and passes it to
<code>dispatch</code>. Enter on an <strong>agent</strong> or <strong>workspace</strong> still focuses that entry — forcing a target
only changes where a <em>repo</em> lands, matching the manifest's "Pick a repo; Enter opens it in…".
Invalid values on either the env var or the config degrade to <code>workspace</code> instead of erroring.</li>
<li><strong>Zen cannot be built on <code>herdr pane zoom</code>, and this was measured.</strong> Splitting a zoomed tab
<strong>silently cancels the zoom</strong> (<code>zoomed</code> flips to <code>false</code> the moment a gutter appears), and
<code>pane layout</code> on a zoomed tab reports the <em>underlying</em> rects rather than the rendered ones, so
gutters sized from it land wrong. Zen therefore <code>pane move --new-tab</code>s the target instead —
which preserves its <code>terminal_id</code>, so the process survives — and <strong>never touches another pane</strong>.
Do not "simplify" zen back to zoom: it silently produces a tab with an uncentred pane and two
stray shells. Two further counter-intuitive facts the centring depends on: <code>pane split</code> can only
place a new pane <strong>right or down</strong>, and <code>--ratio R</code> gives <code>R</code> to the <strong>existing</strong> pane, not the
new one — hence the swap in step 3 of <code>zen::enter</code>.</li>
<li><strong><code>layout.apply</code> is destructive — never call it.</strong> It looks like the natural way to restore a
tab's layout, and given a tree of existing <code>pane_id</code>s it does <strong>not</strong> re-parent them: it builds
a <em>new</em> tab full of <em>new</em> panes and discards the originals, processes and all (measured against
0.8.0 — it silently replaced three live panes with fresh shells). Its sibling <code>layout.export</code> is
read-only and safe, and is what <code>zen::sibling_anchor</code> reads. This is why zen's restore is
<code>pane move</code> + <code>pane swap</code>, and why a deeply nested tab restores approximately: there is no
non-destructive verb for "insert at this point in the tree". <code>Anchor::exact</code> carries that fact
and the exit notifies rather than silently rearranging.</li>
<li><strong>herdr's chrome has no per-pane switch, so <code>zen_chrome</code> edits herdr's own config — and that
is the only file outside the plugin anything here may write.</strong> The sidebar, tab row, pane
borders/gaps and scrollbars are global <code>[ui]</code> keys; <code>herdr pane|tab|server|config --help</code> and
the socket method list have nothing UI-shaped, and <code>herdr config</code> has no <code>set</code>, so
<code>server reload-config</code> after a <code>toml_edit</code> rewrite is the only lever. Two orderings are load
bearing and easy to invert: <code>enter</code> <strong>snapshots before it writes</strong> and only then engages (last
of the herdr work — a reload while the splits are settling lays the gutters out against a stale
frame), and <code>leave</code> <strong>restores before it clears</strong>, keeping the snapshot when herdr refuses so
<code>zen chrome-restore</code> can retry. The snapshot is its own state file (<code>zen.chrome.tsv</code>) rather
than part of the session record precisely because it must outlive the session. <code>enter</code> never
re-snapshots over a leftover snapshot: that would record zen's own values as the user's and
lose the way home for good. Default is <code>off</code>. Tests may exercise every level, because the test
build points <code>chrome::config_path</code> at its scratch directory (see the coverage rule below); a
test that writes that scratch herdr config holds <code>CHROME_LOCK</code> in <code>zen.rs</code>.</li>
<li><strong><code>socket.rs</code> is a deliberate exception to the <code>CommandRunner</code> rule, not a precedent.</strong>
<code>pane.graphics.*</code> is absent from <code>herdr pane --help</code> and reachable only over the socket, so the
gutter scrim has no CLI path. Everything else must keep shelling out through <code>CommandRunner</code>,
which is what keeps the IO edge mockable. herdr composites the scrim <strong>opaque</strong> regardless of the
alpha byte, so there is no translucency knob to add — and the scrim is painted over <em>parked
gutters</em>, never over live panes, because a pane that redraws would punch through it.</li>
<li><strong>Two build profiles, because two consumers want opposite things.</strong> <code>release</code> stays
<code>opt-level = "s"</code> with no LTO: it is what <code>bin/picker.sh</code> falls back to for an offline install or
a linked checkout, compiled on the user's machine while they wait for a pane. <code>dist</code> (<code>opt-level = 3</code>, thin LTO, one codegen unit) is what <code>.github/workflows/release.yml</code> ships, where the
compile time is CI's and the run time is the installer's. Archives are packaged from
<code>target/&lt;triple&gt;/dist/</code>; <code>bin/lib.sh</code> still builds and reads <code>target/release/</code>. Do not collapse
them — either the local fallback gets eight times slower or every shipped binary gets slower.</li>
<li><strong>Nothing is excluded from the coverage denominator, and the gate is 98%.</strong> Some code genuinely
cannot run under a unit test — <code>surface::run</code> and <code>preroll</code> claiming a real terminal, the
<code>exec</code> that replaces the process, a stdin prompt's wrapper — and it still counts against
<code>MINIMUM</code> in <code>bin/coverage.sh</code>. An exclusion list (or <code>#[cfg(not(test))]</code>, which is one in
disguise) is a second thing to argue about and a place for the number to quietly stop meaning
what it says; the answer to a low file is a test, or an honest seam. The seams that exist are
narrow and each replaces something a test has no business starting: <code>surface::Host</code>
(<code>TerminalHost</code> in production, <code>ScriptedHost</code> driving the real host loop on a <code>TestBackend</code>),
injected runners on every mode and background step, <code>fn</code> pointers for the clipboard, URL
opener, typed confirmations, process replacement, and Zen's chrome restore, prompts that read
any <code>BufRead</code>, <code>PortWorker::seeded</code>, and <code>CatalogWorker::disconnected</code>. A test that would fire a
real notification uses <code>Notifier::silent</code>.</li>
<li><strong>Tests never touch the developer's machine state.</strong> In the test build, <code>state::state_dir</code>, the
plugin's <code>config::config_path</code>, <code>chrome::config_path</code> (herdr's config), and the herdr socket all
resolve under <code>state::test_scratch()</code>, one directory per test process, and <code>trace</code> always writes
to a scratch log. A background step once reached the real <code>review_archive::set</code> from a test and
left a fixture slug in the developer's archive; that class of leak is now structurally
impossible. The real path rules are pure <code>*_from</code> functions tested on their own. Never add a
test that reads or writes <code>$HOME</code> directly — take the directory as a parameter instead, as
<code>codex::load_from</code> and <code>claude::load_with</code> do.</li>
<li><strong>Version sync:</strong> <code>Cargo.toml</code> and <code>herdr-plugin.toml</code> versions must match; <code>tests/manifest_spec.sh</code>
enforces it. <code>bin/release.sh</code> bumps both, so bump through it rather than by hand.</li>
<li><strong>The changelog is the release notes.</strong> Every user-facing change adds a line to
<code>CHANGELOG.md</code>'s <code>[Unreleased]</code> section <em>in the same commit</em>; <code>bin/release.sh</code> promotes that
section to a dated one and tags. The tag workflow builds four native archives, generates
<code>SHA256SUMS</code>, and publishes that section verbatim after all targets pass. Commits are not
Conventional Commits and nothing comes from <code>git log</code> — an empty <code>[Unreleased]</code> aborts.</li>
<li><strong>No launch or navigation hot path waits on the network.</strong> <code>update.rs</code> spawns a detached
<code>--update-check</code> child (own process group, no stdio) that runs <code>git ls-remote</code> and writes a cache;
the Projects Picker only reads that file, so the badge lands on a <em>later</em> launch.
Do not "simplify" this into a thread: the picker frequently exits in under a second and the fetch
takes several, so the cache would never be written. <code>git ls-remote</code> uses Git's HTTPS transport
on purpose — no <code>jq</code>, no 60/hour unauthenticated API limit, no auth. Everything fails silently.
Git's pull-request row may call <code>gh pr list</code>, but only after explicit activation and through a
background effect. Clone/update commands may fetch because the user invoked that work directly.
The <code>usage</code> pane is allowed to fetch <em>while you watch</em> because it exists to answer a question
whose only correct answer is the current one, and it is a pane you opened on purpose rather than
a hot path — but it still never blocks the first frame: the offline provider is loaded before
the terminal is claimed, the networked one runs on a worker thread bounded by
<code>usage.timeout_ms</code>, and its card sits in <code>Slot::Loading</code> until the answer arrives. No other
surface may read a credential or add an in-process HTTP client.</li>
<li><strong><code>usage</code> is the only code that reads a credential, and the token must never reach argv.</strong>
<code>argv</code> is readable through <code>ps</code> by every process the user owns, for the whole life of the call,
so <code>Claude::fetch</code> hands <code>curl</code> its <code>Authorization</code> header through stdin as a <code>--config -</code> file.
That is the entire reason <code>CommandRunner::output_stdin</code> exists — do not add a second caller
without the same justification, and do not "tidy" the header back into a <code>-H</code> flag. The token is
never cached, written, traced, or drawn; <code>the_token_reaches_curl_through_stdin_and_never_through_argv</code>
in <code>usage.rs</code> pins it down by asserting the secret is absent from <code>runner.calls()</code>.</li>
<li><strong>The account line reads credential-adjacent files, and reads only named, non-secret labels.</strong>
Codex exposes no command that prints its address, so <code>identity_from_codex_auth</code> decodes the ID
token in <code>~/.codex/auth.json</code> — payload only, signature unverified on purpose, because these are
labels and nothing here trusts them. It takes exactly two claims: <code>email</code>, and
<code>chatgpt_subscription_active_until</code> under the namespaced <code>https://api.openai.com/auth</code> claim
(the <code>renews</code> row). One read and one decode for both, which is why <code>codex_account</code> became
<code>codex_identity</code>. The access and refresh tokens sitting beside them in that file are read past
and dropped: never log, draw, or forward anything from it but those two values. Claude's address
and plan come from <code>~/.claude.json</code>, an ordinary settings file. <code>base64url_decode</code> is hand-rolled
and refuses padded input; do not swap in a base64 crate for sixty-four characters.</li>
<li><strong>A renewal date is shown only when it is a fact, never when it is arithmetic.</strong> Codex publishes
one; Anthropic publishes none anywhere local — <code>~/.claude.json</code> carries <code>subscriptionCreatedAt</code>
and <code>billingType: apple_subscription</code>, and the usage endpoint carries no period end, so a Claude
renewal could only be a monthly-anniversary guess against a date Apple actually owns. The card
says <code>unknown</code> instead. <code>format_renewal</code> also answers <code>unknown</code> for a date already <strong>past</strong>: the
Codex claim only refreshes while Codex runs, so a machine left alone for a month still holds the
previous period's date, and a stale date under a heading that says <em>renews</em> reads as one that is
coming — wrong in the reassuring direction, which is the failure this popup exists to prevent.</li>
<li><strong>A quota card grades by the provider's word when it has one.</strong> Claude's usage endpoint ships a
<code>severity</code> per limit and Codex ships none, so <code>window_color</code> takes <code>Severity</code> when present and
falls back to <code>usage.warn_percent</code>/<code>alert_percent</code> otherwise. Yes, that means two cards can
colour by two different rules — deliberately: the provider knows what its own plan considers
close to the edge, and a threshold invented here does not. <code>limits[]</code> and the named buckets share
no id, so <code>claude_severities</code> joins them on the rounded percentage; a weak key whose worst case
is two windows at the same percentage sharing a colour that is correct for both.</li>
<li><strong>Every usage card is laid out to the same row heights.</strong> <code>draw</code> computes one <code>CardRows</code> from the
busiest slot and hands it to every card, because sizing per card puts a one-window provider's
donut at a different height from a four-window provider's, and two cards that do not line up read
as two unrelated widgets. <code>every_card_puts_its_rows_at_the_same_height</code> pins it. The fact lists
are built once, by <code>card_facts</code>, and used for <em>both</em> the count and the render — a row that the
drawing layer appends (<code>renews</code>) but the sizing layer does not count is a card one row too short.</li>
<li><strong>Local time comes from <code>date +%z</code>, once per refresh.</strong> <code>std</code> has no local-time API and there is
no date crate here, so <code>local_offset</code> shells out through <code>CommandRunner</code> and <code>format_clock</code> does
the civil-calendar arithmetic. An unreadable offset degrades to UTC — wrong by hours, never wrong
about which number resets. Do not add a time zone crate for one line of one card.</li>
<li><strong>A quota percentage is used as reported, never rescaled.</strong> Both sources were measured on a real
account: Codex writes <code>used_percent: 41.0</code> and the usage endpoint answers <code>utilization: 51.0</code>.
An earlier <code>normalize_utilization</code> guessed that anything at or below <code>1.0</code> was a fraction and
multiplied by 100 — which reads a genuine <code>0.8%</code>, the state of every plan just after its window
rolls over, as <code>80%</code>. <code>clamp_percent</code> only clamps. Guessing a scale fails silently and in the
alarming direction; do not reintroduce it.</li>
<li><strong>The update flow fails closed.</strong> <code>bin/update-plugin.sh</code> installs only when herdr reports
an unambiguous <code>"source":{"kind":"github"…}</code>; local links, unreadable output, and shapes it
does not recognise all refuse. The failure it must never make is the permissive one —
<code>herdr plugin install</code> would overwrite a contributor's working tree. <code>tests/update_guard_spec.sh</code>
stubs <code>herdr</code> through <code>HERDR_BIN_PATH</code> and asserts every case. Never widen the guard without
extending that spec, and never name a real mutating command inside backticks in it.</li>
<li><strong>An update must force a rebuild.</strong> <code>target/</code> is gitignored, so re-fetching the source leaves
the old binary in place and <code>bin/picker.sh</code> only builds when the binary is <em>missing</em> — the new
code would ship with the old switcher still running. <code>update-plugin.sh</code> removes it and rebuilds.</li>
<li><strong>Projects <code>ctrl-x</code> (remove) requires typed confirmation.</strong> Repositories use their name on the
restored terminal; linked worktrees use their name in a modal overlay, or <code>force &lt;name&gt;</code> when
Force is explicitly selected. Git revalidates the linked worktree before removal; main and
locked worktrees refuse, branch deletion only uses <code>-d</code>, and partial branch failure still drops
the removed worktree from the list. Never cancel a pending removal or substitute <code>rm -rf</code> for
Git's metadata cleanup. Preserve these guards; test against disposable repos.</li>
<li><strong>Pane commands must launch through <code>$HERDR_PLUGIN_ROOT</code></strong> — <code>tests/manifest_spec.sh</code> asserts the
exact manifest string, since herdr starts panes from the user's repo, not the plugin checkout.</li>
</ul>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Conventions</h2><a id="user-content-conventions" class="anchor" aria-label="Permalink: Conventions" href="#conventions"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Rustfmt defaults; <code>anyhow::Result</code> with typed errors; no <code>unwrap()</code> in production paths. Bash uses
<code>#!/usr/bin/env bash</code>, <code>set -euo pipefail</code>, quoted expansions, and helpers from <code>bin/lib.sh</code>.
TOML keys are snake_case; plugin action ids are kebab-case. Commits are short and imperative;
<code>bin/release.sh</code> makes the <code>Release vX.Y.Z</code> commit, so do not hand-tag subjects like <code>(v0.4.0)</code>
the way pre-0.5.0 commits did. Never commit <code>target/</code>.</p>
<div class="markdown-heading" dir="auto"><h2 tabindex="-1" class="heading-element" dir="auto">Agent skills</h2><a id="user-content-agent-skills" class="anchor" aria-label="Permalink: Agent skills" href="#agent-skills"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Issue tracker</h3><a id="user-content-issue-tracker" class="anchor" aria-label="Permalink: Issue tracker" href="#issue-tracker"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Local markdown — issues and specs live as files under <code>.scratch/&lt;feature&gt;/</code> in this repo
(gitignored). See <code>docs/agents/issue-tracker.md</code>.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Triage labels</h3><a id="user-content-triage-labels" class="anchor" aria-label="Permalink: Triage labels" href="#triage-labels"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">The five canonical roles (<code>needs-triage</code>, <code>needs-info</code>, <code>ready-for-agent</code>, <code>ready-for-human</code>,
<code>wontfix</code>), used as-is. See <code>docs/agents/triage-labels.md</code>.</p>
<div class="markdown-heading" dir="auto"><h3 tabindex="-1" class="heading-element" dir="auto">Domain docs</h3><a id="user-content-domain-docs" class="anchor" aria-label="Permalink: Domain docs" href="#domain-docs"><svg data-component="Octicon" class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path d="m7.775 3.275 1.25-1.25a3.5 3.5 0 1 1 4.95 4.95l-2.5 2.5a3.5 3.5 0 0 1-4.95 0 .751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018 1.998 1.998 0 0 0 2.83 0l2.5-2.5a2.002 2.002 0 0 0-2.83-2.83l-1.25 1.25a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042Zm-4.69 9.64a1.998 1.998 0 0 0 2.83 0l1.25-1.25a.751.751 0 0 1 1.042.018.751.751 0 0 1 .018 1.042l-1.25 1.25a3.5 3.5 0 1 1-4.95-4.95l2.5-2.5a3.5 3.5 0 0 1 4.95 0 .751.751 0 0 1-.018 1.042.751.751 0 0 1-1.042.018 1.998 1.998 0 0 0-2.83 0l-2.5 2.5a1.998 1.998 0 0 0 0 2.83Z"></path></svg></a></div>
<p dir="auto">Single-context — <code>CONTEXT.md</code> + <code>docs/adr/</code> at the repo root. See <code>docs/agents/domain.md</code>.</p>
</article></div><div class="d-none"></div></section></div></div></div> </div> <!-- --> </div></div></div></div></div></div><div class="ScrollMarksContainer-module__scrollMarksContainer__Eu7uU" id="find-result-marks-container"></div><div class="d-none"></div><div class="d-none"></div></div> <!-- --> <!-- --> </div>
</react-app>




  </div>

</turbo-frame>

    </main>
  </div>

  </div>

          <footer class="footer f6 color-fg-muted color-border-subtle tmp-pt-7 tmp-pb-6 p-responsive" role="contentinfo"  >
  <h2 class='sr-only'>Footer</h2>

  


  <div class="d-flex flex-justify-center flex-items-center flex-column-reverse flex-lg-row flex-wrap flex-lg-nowrap">
    <div class="d-flex flex-items-center flex-shrink-0 mx-2">
      <a aria-label="GitHub Homepage" class="footer-octicon mr-2" href="https://github.com">
        <svg aria-hidden="true" data-component="Octicon" height="24" viewBox="0 0 24 24" version="1.1" width="24" data-view-component="true" class="octicon octicon-mark-github">
    <path d="M10.226 17.284c-2.965-.36-5.054-2.493-5.054-5.256 0-1.123.404-2.336 1.078-3.144-.292-.741-.247-2.314.09-2.965.898-.112 2.111.36 2.83 1.01.853-.269 1.752-.404 2.853-.404 1.1 0 1.999.135 2.807.382.696-.629 1.932-1.1 2.83-.988.315.606.36 2.179.067 2.942.72.854 1.101 2 1.101 3.167 0 2.763-2.089 4.852-5.098 5.234.763.494 1.28 1.572 1.28 2.807v2.336c0 .674.561 1.056 1.235.786 4.066-1.55 7.255-5.615 7.255-10.646C23.5 6.188 18.334 1 11.978 1 5.62 1 .5 6.188.5 12.545c0 4.986 3.167 9.12 7.435 10.669.606.225 1.19-.18 1.19-.786V20.63a2.9 2.9 0 0 1-1.078.224c-1.483 0-2.359-.808-2.987-2.313-.247-.607-.517-.966-1.034-1.033-.27-.023-.359-.135-.359-.27 0-.27.45-.471.898-.471.652 0 1.213.404 1.797 1.235.45.651.921.943 1.483.943.561 0 .92-.202 1.437-.719.382-.381.674-.718.944-.943"></path>
</svg>
</a>
      <span>
        &copy; 2026 GitHub,&nbsp;Inc.
      </span>
    </div>

    <nav aria-label="Footer">
      <h3 class="sr-only" id="sr-footer-heading">Footer navigation</h3>

      <ul class="list-style-none d-flex flex-justify-center flex-wrap mb-2 mb-lg-0" aria-labelledby="sr-footer-heading">


          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to Terms&quot;,&quot;label&quot;:&quot;text:terms&quot;}" href="https://docs.github.com/site-policy/github-terms/github-terms-of-service" data-view-component="true" class="Link--secondary Link">Terms</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to privacy&quot;,&quot;label&quot;:&quot;text:privacy&quot;}" href="https://docs.github.com/site-policy/privacy-policies/github-privacy-statement" data-view-component="true" class="Link--secondary Link">Privacy</a>
          </li>


            <li class="mx-2">
              <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to security&quot;,&quot;label&quot;:&quot;text:security&quot;}" href="https://github.com/security" data-view-component="true" class="Link--secondary Link">Security</a>
            </li>

            <li class="mx-2">
              <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to status&quot;,&quot;label&quot;:&quot;text:status&quot;}" href="https://www.githubstatus.com/" data-view-component="true" class="Link--secondary Link">Status</a>
            </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to community&quot;,&quot;label&quot;:&quot;text:community&quot;}" href="https://github.community/" data-view-component="true" class="Link--secondary Link">Community</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to docs&quot;,&quot;label&quot;:&quot;text:docs&quot;}" href="https://docs.github.com/" data-view-component="true" class="Link--secondary Link">Docs</a>
          </li>

          <li class="mx-2">
            <a data-analytics-event="{&quot;category&quot;:&quot;Footer&quot;,&quot;action&quot;:&quot;go to contact&quot;,&quot;label&quot;:&quot;text:contact&quot;}" href="https://support.github.com?tags=dotcom-footer" data-view-component="true" class="Link--secondary Link">Contact</a>
          </li>

          
<li class="mx-2" >
  <cookie-consent-link>
    <button
      type="button"
      class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent"
      data-action="click:cookie-consent-link#showConsentManagement"
      data-analytics-event="{&quot;location&quot;:&quot;footer&quot;,&quot;action&quot;:&quot;cookies&quot;,&quot;context&quot;:&quot;subfooter&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;cookies_link_subfooter_footer&quot;}"
    >
      Manage cookies
    </button>
  </cookie-consent-link>
</li>

  <li class="mx-2">
    <cookie-consent-link>
      <button
        type="button"
        class="Link--secondary underline-on-hover border-0 p-0 color-bg-transparent text-left"
        data-action="click:cookie-consent-link#showConsentManagement"
        data-analytics-event="{&quot;location&quot;:&quot;footer&quot;,&quot;action&quot;:&quot;dont_share_info&quot;,&quot;context&quot;:&quot;subfooter&quot;,&quot;tag&quot;:&quot;link&quot;,&quot;label&quot;:&quot;dont_share_info_link_subfooter_footer&quot;}"
      >
        Do not share my personal information
      </button>
    </cookie-consent-link>
  </li>

      </ul>
    </nav>
  </div>
</footer>



    <ghcc-consent id="ghcc" class="position-fixed bottom-0 left-0" style="z-index: 999999"
      data-locale="en"
      data-initial-cookie-consent-allowed=""
      data-cookie-consent-required="true"
    ></ghcc-consent>




  <div id="ajax-error-message" class="ajax-error-message flash flash-error" hidden>
    <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-alert">
    <path d="M6.457 1.047c.659-1.234 2.427-1.234 3.086 0l6.082 11.378A1.75 1.75 0 0 1 14.082 15H1.918a1.75 1.75 0 0 1-1.543-2.575Zm1.763.707a.25.25 0 0 0-.44 0L1.698 13.132a.25.25 0 0 0 .22.368h12.164a.25.25 0 0 0 .22-.368Zm.53 3.996v2.5a.75.75 0 0 1-1.5 0v-2.5a.75.75 0 0 1 1.5 0ZM9 11a1 1 0 1 1-2 0 1 1 0 0 1 2 0Z"></path>
</svg>
    <button type="button" class="flash-close js-ajax-error-dismiss" aria-label="Dismiss error">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
    </button>
    You can’t perform that action at this time.
  </div>

    <template id="site-details-dialog">
  <details class="details-reset details-overlay details-overlay-dark lh-default color-fg-default hx_rsm" open>
    <summary role="button" aria-label="Close dialog"></summary>
    <details-dialog class="Box Box--overlay d-flex flex-column anim-fade-in fast hx_rsm-dialog hx_rsm-modal">
      <button class="Box-btn-octicon m-0 btn-octicon position-absolute right-0 top-0" type="button" aria-label="Close dialog" data-close-dialog>
        <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-x">
    <path d="M3.72 3.72a.75.75 0 0 1 1.06 0L8 6.94l3.22-3.22a.749.749 0 0 1 1.275.326.749.749 0 0 1-.215.734L9.06 8l3.22 3.22a.749.749 0 0 1-.326 1.275.749.749 0 0 1-.734-.215L8 9.06l-3.22 3.22a.751.751 0 0 1-1.042-.018.751.751 0 0 1-.018-1.042L6.94 8 3.72 4.78a.75.75 0 0 1 0-1.06Z"></path>
</svg>
      </button>
      <div class="octocat-spinner tmp-my-6 js-details-dialog-spinner"></div>
    </details-dialog>
  </details>
</template>

    <div class="Popover js-hovercard-content position-absolute" style="display: none; outline: none;">
  <div class="Popover-message Popover-message--bottom-left Popover-message--large Box color-shadow-large" style="width:360px;">
  </div>
</div>

    <template id="snippet-clipboard-copy-button">
  <div class="zeroclipboard-container position-absolute right-0 top-0">
    <clipboard-copy aria-label="Copy code to clipboard" class="ClipboardButton btn js-clipboard-copy m-2 p-0" data-copy-feedback="Copied!" data-tooltip-direction="w">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon m-2 tmp-m-2">
    <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>
</svg>
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none m-2 tmp-m-2">
    <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path>
</svg>
    </clipboard-copy>
  </div>
</template>
<template id="snippet-clipboard-copy-button-unpositioned">
  <div class="zeroclipboard-container">
    <clipboard-copy aria-label="Copy code to clipboard" class="ClipboardButton btn btn-invisible js-clipboard-copy m-2 p-0 d-flex flex-justify-center flex-items-center" data-copy-feedback="Copied!" data-tooltip-direction="w">
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-copy js-clipboard-copy-icon">
    <path d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 0 1 0 1.5h-1.5a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-1.5a.75.75 0 0 1 1.5 0v1.5A1.75 1.75 0 0 1 9.25 16h-7.5A1.75 1.75 0 0 1 0 14.25Z"></path><path d="M5 1.75C5 .784 5.784 0 6.75 0h7.5C15.216 0 16 .784 16 1.75v7.5A1.75 1.75 0 0 1 14.25 11h-7.5A1.75 1.75 0 0 1 5 9.25Zm1.75-.25a.25.25 0 0 0-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 0 0 .25-.25v-7.5a.25.25 0 0 0-.25-.25Z"></path>
</svg>
      <svg aria-hidden="true" data-component="Octicon" height="16" viewBox="0 0 16 16" version="1.1" width="16" data-view-component="true" class="octicon octicon-check js-clipboard-check-icon color-fg-success d-none">
    <path d="M13.78 4.22a.75.75 0 0 1 0 1.06l-7.25 7.25a.75.75 0 0 1-1.06 0L2.22 9.28a.751.751 0 0 1 .018-1.042.751.751 0 0 1 1.042-.018L6 10.94l6.72-6.72a.75.75 0 0 1 1.06 0Z"></path>
</svg>
    </clipboard-copy>
  </div>
</template>




    </div>
    <div id="js-global-screen-reader-notice" class="sr-only mt-n1" aria-live="polite" aria-atomic="true" ></div>
    <div id="js-global-screen-reader-notice-assertive" class="sr-only mt-n1" aria-live="assertive" aria-atomic="true"></div>
  </body>
</html>

