> ## Documentation Index
> Fetch the complete documentation index at: https://www.testmuai.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Remote Runs on the Cloud Grid

> Dispatch a suite of _test.md files to HyperExecute with kane-cli testrun run --remote: grid browsers for web suites, grid emulators and simulators for mobile suites, from any machine.

export const BrandName = ({type = 'default'}) => {
  const getBrandName = () => 'TestMu AI';
  const getBrandNameLowercase = () => 'testmu ai';
  if (type === 'lowercase') {
    return getBrandNameLowercase();
  }
  return getBrandName();
};

export const KaneCliCta = () => {
  const productType = 'Kane-CLI';
  const productList = [{
    value: 0,
    type: 'Online-Browser-Testing',
    label: 'Online Browser Testing'
  }, {
    value: 1,
    type: 'Selenium-Testing',
    label: 'Selenium Testing'
  }, {
    value: 2,
    type: 'Cypress-Testing',
    label: 'Cypress Testing'
  }, {
    value: 3,
    type: 'Hyperexecute',
    label: 'HyperExecute'
  }, {
    value: 4,
    type: 'Kane-AI',
    label: 'KaneAI'
  }, {
    value: 5,
    type: 'On-Premise-Selenium-Grid',
    label: 'On-premise Selenium Grid'
  }, {
    value: 6,
    type: 'Mobile-App-Testing',
    label: 'Native App Testing'
  }, {
    value: 7,
    type: 'Real-Device-Cloud',
    label: 'Real Device Cloud'
  }, {
    value: 8,
    type: 'Smart-Visual-Testing',
    label: 'Visual Regression Cloud'
  }, {
    value: 9,
    type: 'Appium',
    label: 'Appium'
  }, {
    value: 10,
    type: 'Enterprise',
    label: 'Enterprise'
  }, {
    value: 11,
    type: 'Test-Manager',
    label: 'Test Manager'
  }, {
    value: 12,
    type: 'Professional-Services',
    label: 'Professional Services'
  }, {
    value: 13,
    type: 'Accessibility-Testing',
    label: 'Accessibility Testing'
  }, {
    value: 14,
    type: 'Agent Testing',
    label: 'Agent Testing'
  }, {
    value: 15,
    type: 'Browser-Cloud',
    label: 'Browser Cloud'
  }, {
    value: 16,
    type: 'Kane-CLI',
    label: 'Kane CLI'
  }, {
    value: 'Other',
    type: 'Other',
    label: 'Other'
  }];
  const countryList = [{
    country_code: "US",
    value: "1",
    name: "USA (+1)"
  }, {
    country_code: "GB",
    value: "44",
    name: "UK (+44)"
  }, {
    country_code: "DZ",
    value: "213",
    name: "Algeria (+213)"
  }, {
    country_code: "AD",
    value: "376",
    name: "Andorra (+376)"
  }, {
    country_code: "AO",
    value: "244",
    name: "Angola (+244)"
  }, {
    country_code: "AI",
    value: "1264",
    name: "Anguilla (+1264)"
  }, {
    country_code: "AG",
    value: "1268",
    name: "Antigua &amp; Barbuda (+1268)"
  }, {
    country_code: "AR",
    value: "54",
    name: "Argentina (+54)"
  }, {
    country_code: "AM",
    value: "374",
    name: "Armenia (+374)"
  }, {
    country_code: "AW",
    value: "297",
    name: "Aruba (+297)"
  }, {
    country_code: "AU",
    value: "61",
    name: "Australia (+61)"
  }, {
    country_code: "AT",
    value: "43",
    name: "Austria (+43)"
  }, {
    country_code: "AZ",
    value: "994",
    name: "Azerbaijan (+994)"
  }, {
    country_code: "BS",
    value: "1242",
    name: "Bahamas (+1242)"
  }, {
    country_code: "BH",
    value: "973",
    name: "Bahrain (+973)"
  }, {
    country_code: "BD",
    value: "880",
    name: "Bangladesh (+880)"
  }, {
    country_code: "BB",
    value: "1246",
    name: "Barbados (+1246)"
  }, {
    country_code: "BY",
    value: "375",
    name: "Belarus (+375)"
  }, {
    country_code: "BE",
    value: "32",
    name: "Belgium (+32)"
  }, {
    country_code: "BZ",
    value: "501",
    name: "Belize (+501)"
  }, {
    country_code: "BJ",
    value: "229",
    name: "Benin (+229)"
  }, {
    country_code: "BM",
    value: "1441",
    name: "Bermuda (+1441)"
  }, {
    country_code: "BT",
    value: "975",
    name: "Bhutan (+975)"
  }, {
    country_code: "BO",
    value: "591",
    name: "Bolivia (+591)"
  }, {
    country_code: "BA",
    value: "387",
    name: "Bosnia Herzegovina (+387)"
  }, {
    country_code: "BW",
    value: "267",
    name: "Botswana (+267)"
  }, {
    country_code: "BR",
    value: "55",
    name: "Brazil (+55)"
  }, {
    country_code: "BN",
    value: "673",
    name: "Brunei (+673)"
  }, {
    country_code: "BG",
    value: "359",
    name: "Bulgaria (+359)"
  }, {
    country_code: "BF",
    value: "226",
    name: "Burkina Faso (+226)"
  }, {
    country_code: "BI",
    value: "257",
    name: "Burundi (+257)"
  }, {
    country_code: "KH",
    value: "855",
    name: "Cambodia (+855)"
  }, {
    country_code: "CM",
    value: "237",
    name: "Cameroon (+237)"
  }, {
    country_code: "CA",
    value: "1",
    name: "Canada (+1)"
  }, {
    country_code: "CV",
    value: "238",
    name: "Cape Verde Islands (+238)"
  }, {
    country_code: "KY",
    value: "1345",
    name: "Cayman Islands (+1345)"
  }, {
    country_code: "CF",
    value: "236",
    name: "Central African Republic (+236)"
  }, {
    country_code: "CL",
    value: "56",
    name: "Chile (+56)"
  }, {
    country_code: "CN",
    value: "86",
    name: "China (+86)"
  }, {
    country_code: "CO",
    value: "57",
    name: "Colombia (+57)"
  }, {
    country_code: "KM",
    value: "269",
    name: "Comoros (+269)"
  }, {
    country_code: "CG",
    value: "242",
    name: "Congo (+242)"
  }, {
    country_code: "CK",
    value: "682",
    name: "Cook Islands (+682)"
  }, {
    country_code: "CR",
    value: "506",
    name: "Costa Rica (+506)"
  }, {
    country_code: "HR",
    value: "385",
    name: "Croatia (+385)"
  }, {
    country_code: "CU",
    value: "53",
    name: "Cuba (+53)"
  }, {
    country_code: "CY",
    value: "90392",
    name: "Cyprus North (+90392)"
  }, {
    country_code: "CY",
    value: "357",
    name: "Cyprus South (+357)"
  }, {
    country_code: "CZ",
    value: "42",
    name: "Czech Republic (+42)"
  }, {
    country_code: "DK",
    value: "45",
    name: "Denmark (+45)"
  }, {
    country_code: "DJ",
    value: "253",
    name: "Djibouti (+253)"
  }, {
    country_code: "DM",
    value: "1809",
    name: "Dominica (+1809)"
  }, {
    country_code: "DO",
    value: "1809",
    name: "Dominican Republic (+1809)"
  }, {
    country_code: "EC",
    value: "593",
    name: "Ecuador (+593)"
  }, {
    country_code: "EG",
    value: "20",
    name: "Egypt (+20)"
  }, {
    country_code: "SV",
    value: "503",
    name: "El Salvador (+503)"
  }, {
    country_code: "GQ",
    value: "240",
    name: "Equatorial Guinea (+240)"
  }, {
    country_code: "ER",
    value: "291",
    name: "Eritrea (+291)"
  }, {
    country_code: "EE",
    value: "372",
    name: "Estonia (+372)"
  }, {
    country_code: "ET",
    value: "251",
    name: "Ethiopia (+251)"
  }, {
    country_code: "FK",
    value: "500",
    name: "Falkland Islands (+500)"
  }, {
    country_code: "FO",
    value: "298",
    name: "Faroe Islands (+298)"
  }, {
    country_code: "FJ",
    value: "679",
    name: "Fiji (+679)"
  }, {
    country_code: "FI",
    value: "358",
    name: "Finland (+358)"
  }, {
    country_code: "FR",
    value: "33",
    name: "France (+33)"
  }, {
    country_code: "GF",
    value: "594",
    name: "French Guiana (+594)"
  }, {
    country_code: "PF",
    value: "689",
    name: "French Polynesia (+689)"
  }, {
    country_code: "GA",
    value: "241",
    name: "Gabon (+241)"
  }, {
    country_code: "GM",
    value: "220",
    name: "Gambia (+220)"
  }, {
    country_code: "GE",
    value: "7880",
    name: "Georgia (+7880)"
  }, {
    country_code: "DE",
    value: "49",
    name: "Germany (+49)"
  }, {
    country_code: "GH",
    value: "233",
    name: "Ghana (+233)"
  }, {
    country_code: "GI",
    value: "350",
    name: "Gibraltar (+350)"
  }, {
    country_code: "GR",
    value: "30",
    name: "Greece (+30)"
  }, {
    country_code: "GL",
    value: "299",
    name: "Greenland (+299)"
  }, {
    country_code: "GD",
    value: "1473",
    name: "Grenada (+1473)"
  }, {
    country_code: "GP",
    value: "590",
    name: "Guadeloupe (+590)"
  }, {
    country_code: "GU",
    value: "671",
    name: "Guam (+671)"
  }, {
    country_code: "GT",
    value: "502",
    name: "Guatemala (+502)"
  }, {
    country_code: "GN",
    value: "224",
    name: "Guinea (+224)"
  }, {
    country_code: "GW",
    value: "245",
    name: "Guinea - Bissau (+245)"
  }, {
    country_code: "GY",
    value: "592",
    name: "Guyana (+592)"
  }, {
    country_code: "HT",
    value: "509",
    name: "Haiti (+509)"
  }, {
    country_code: "HN",
    value: "504",
    name: "Honduras (+504)"
  }, {
    country_code: "HK",
    value: "852",
    name: "Hong Kong (+852)"
  }, {
    country_code: "HU",
    value: "36",
    name: "Hungary (+36)"
  }, {
    country_code: "IS",
    value: "354",
    name: "Iceland (+354)"
  }, {
    country_code: "IN",
    value: "91",
    name: "India (+91)"
  }, {
    country_code: "ID",
    value: "62",
    name: "Indonesia (+62)"
  }, {
    country_code: "IR",
    value: "98",
    name: "Iran (+98)"
  }, {
    country_code: "IQ",
    value: "964",
    name: "Iraq (+964)"
  }, {
    country_code: "IE",
    value: "353",
    name: "Ireland (+353)"
  }, {
    country_code: "IL",
    value: "972",
    name: "Israel (+972)"
  }, {
    country_code: "IT",
    value: "39",
    name: "Italy (+39)"
  }, {
    country_code: "JM",
    value: "1876",
    name: "Jamaica (+1876)"
  }, {
    country_code: "JP",
    value: "81",
    name: "Japan (+81)"
  }, {
    country_code: "JO",
    value: "962",
    name: "Jordan (+962)"
  }, {
    country_code: "KZ",
    value: "7",
    name: "Kazakhstan (+7)"
  }, {
    country_code: "KE",
    value: "254",
    name: "Kenya (+254)"
  }, {
    country_code: "KI",
    value: "686",
    name: "Kiribati (+686)"
  }, {
    country_code: "KP",
    value: "850",
    name: "Korea North (+850)"
  }, {
    country_code: "KR",
    value: "82",
    name: "Korea South (+82)"
  }, {
    country_code: "KW",
    value: "965",
    name: "Kuwait (+965)"
  }, {
    country_code: "KG",
    value: "996",
    name: "Kyrgyzstan (+996)"
  }, {
    country_code: "LA",
    value: "856",
    name: "Laos (+856)"
  }, {
    country_code: "LV",
    value: "371",
    name: "Latvia (+371)"
  }, {
    country_code: "LB",
    value: "961",
    name: "Lebanon (+961)"
  }, {
    country_code: "LS",
    value: "266",
    name: "Lesotho (+266)"
  }, {
    country_code: "LR",
    value: "231",
    name: "Liberia (+231)"
  }, {
    country_code: "LY",
    value: "218",
    name: "Libya (+218)"
  }, {
    country_code: "LI",
    value: "417",
    name: "Liechtenstein (+417)"
  }, {
    country_code: "LT",
    value: "370",
    name: "Lithuania (+370)"
  }, {
    country_code: "LU",
    value: "352",
    name: "Luxembourg (+352)"
  }, {
    country_code: "MO",
    value: "853",
    name: "Macao (+853)"
  }, {
    country_code: "MK",
    value: "389",
    name: "Macedonia (+389)"
  }, {
    country_code: "MG",
    value: "261",
    name: "Madagascar (+261)"
  }, {
    country_code: "MW",
    value: "265",
    name: "Malawi (+265)"
  }, {
    country_code: "MY",
    value: "60",
    name: "Malaysia (+60)"
  }, {
    country_code: "MV",
    value: "960",
    name: "Maldives (+960)"
  }, {
    country_code: "ML",
    value: "223",
    name: "Mali (+223)"
  }, {
    country_code: "MT",
    value: "356",
    name: "Malta (+356)"
  }, {
    country_code: "MH",
    value: "692",
    name: "Marshall Islands (+692)"
  }, {
    country_code: "MQ",
    value: "596",
    name: "Martinique (+596)"
  }, {
    country_code: "MR",
    value: "222",
    name: "Mauritania (+222)"
  }, {
    country_code: "YT",
    value: "269",
    name: "Mayotte (+269)"
  }, {
    country_code: "MX",
    value: "52",
    name: "Mexico (+52)"
  }, {
    country_code: "FM",
    value: "691",
    name: "Micronesia (+691)"
  }, {
    country_code: "MD",
    value: "373",
    name: "Moldova (+373)"
  }, {
    country_code: "MC",
    value: "377",
    name: "Monaco (+377)"
  }, {
    country_code: "MN",
    value: "976",
    name: "Mongolia (+976)"
  }, {
    country_code: "MS",
    value: "1664",
    name: "Montserrat (+1664)"
  }, {
    country_code: "MA",
    value: "212",
    name: "Morocco (+212)"
  }, {
    country_code: "MZ",
    value: "258",
    name: "Mozambique (+258)"
  }, {
    country_code: "MN",
    value: "95",
    name: "Myanmar (+95)"
  }, {
    country_code: "NA",
    value: "264",
    name: "Namibia (+264)"
  }, {
    country_code: "NR",
    value: "674",
    name: "Nauru (+674)"
  }, {
    country_code: "NP",
    value: "977",
    name: "Nepal (+977)"
  }, {
    country_code: "NL",
    value: "31",
    name: "Netherlands (+31)"
  }, {
    country_code: "NC",
    value: "687",
    name: "New Caledonia (+687)"
  }, {
    country_code: "NZ",
    value: "64",
    name: "New Zealand (+64)"
  }, {
    country_code: "NI",
    value: "505",
    name: "Nicaragua (+505)"
  }, {
    country_code: "NE",
    value: "227",
    name: "Niger (+227)"
  }, {
    country_code: "NG",
    value: "234",
    name: "Nigeria (+234)"
  }, {
    country_code: "NU",
    value: "683",
    name: "Niue (+683)"
  }, {
    country_code: "NF",
    value: "672",
    name: "Norfolk Islands (+672)"
  }, {
    country_code: "NP",
    value: "670",
    name: "Northern Marianas (+670)"
  }, {
    country_code: "NO",
    value: "47",
    name: "Norway (+47)"
  }, {
    country_code: "OM",
    value: "968",
    name: "Oman (+968)"
  }, {
    country_code: "PW",
    value: "680",
    name: "Palau (+680)"
  }, {
    country_code: "PK",
    value: "+92",
    name: "Pakistan (+92)"
  }, {
    country_code: "PA",
    value: "507",
    name: "Panama (+507)"
  }, {
    country_code: "PG",
    value: "675",
    name: "Papua New Guinea (+675)"
  }, {
    country_code: "PY",
    value: "595",
    name: "Paraguay (+595)"
  }, {
    country_code: "PE",
    value: "51",
    name: "Peru (+51)"
  }, {
    country_code: "PH",
    value: "63",
    name: "Philippines (+63)"
  }, {
    country_code: "PL",
    value: "48",
    name: "Poland (+48)"
  }, {
    country_code: "PT",
    value: "351",
    name: "Portugal (+351)"
  }, {
    country_code: "PR",
    value: "1787",
    name: "Puerto Rico (+1787)"
  }, {
    country_code: "QA",
    value: "974",
    name: "Qatar (+974)"
  }, {
    country_code: "RE",
    value: "262",
    name: "Reunion (+262)"
  }, {
    country_code: "RO",
    value: "40",
    name: "Romania (+40)"
  }, {
    country_code: "RU",
    value: "7",
    name: "Russia (+7)"
  }, {
    country_code: "RW",
    value: "250",
    name: "Rwanda (+250)"
  }, {
    country_code: "SM",
    value: "378",
    name: "San Marino (+378)"
  }, {
    country_code: "ST",
    value: "239",
    name: "Sao Tome &amp; Principe (+239)"
  }, {
    country_code: "SA",
    value: "966",
    name: "Saudi Arabia (+966)"
  }, {
    country_code: "SN",
    value: "221",
    name: "Senegal (+221)"
  }, {
    country_code: "CS",
    value: "381",
    name: "Serbia (+381)"
  }, {
    country_code: "SC",
    value: "248",
    name: "Seychelles (+248)"
  }, {
    country_code: "SL",
    value: "232",
    name: "Sierra Leone (+232)"
  }, {
    country_code: "SG",
    value: "65",
    name: "Singapore (+65)"
  }, {
    country_code: "SK",
    value: "421",
    name: "Slovak Republic (+421)"
  }, {
    country_code: "SI",
    value: "386",
    name: "Slovenia (+386)"
  }, {
    country_code: "SB",
    value: "677",
    name: "Solomon Islands (+677)"
  }, {
    country_code: "SO",
    value: "252",
    name: "Somalia (+252)"
  }, {
    country_code: "ZA",
    value: "27",
    name: "South Africa (+27)"
  }, {
    country_code: "ES",
    value: "34",
    name: "Spain (+34)"
  }, {
    country_code: "LK",
    value: "94",
    name: "Sri Lanka (+94)"
  }, {
    country_code: "SH",
    value: "290",
    name: "St. Helena (+290)"
  }, {
    country_code: "KN",
    value: "1869",
    name: "St. Kitts (+1869)"
  }, {
    country_code: "SC",
    value: "1758",
    name: "St. Lucia (+1758)"
  }, {
    country_code: "SD",
    value: "249",
    name: "Sudan (+249)"
  }, {
    country_code: "SR",
    value: "597",
    name: "Suri (+597)"
  }, {
    country_code: "SZ",
    value: "268",
    name: "Swaziland (+268)"
  }, {
    country_code: "SE",
    value: "46",
    name: "Sweden (+46)"
  }, {
    country_code: "CH",
    value: "41",
    name: "Switzerland (+41)"
  }, {
    country_code: "SI",
    value: "963",
    name: "Syria (+963)"
  }, {
    country_code: "TW",
    value: "886",
    name: "Taiwan (+886)"
  }, {
    country_code: "TJ",
    value: "7",
    name: "Tajikstan (+7)"
  }, {
    country_code: "TH",
    value: "66",
    name: "Thailand (+66)"
  }, {
    country_code: "TG",
    value: "228",
    name: "Togo (+228)"
  }, {
    country_code: "TO",
    value: "676",
    name: "Tonga (+676)"
  }, {
    country_code: "TT",
    value: "1868",
    name: "Trinidad &amp; Tobago (+1868)"
  }, {
    country_code: "TN",
    value: "216",
    name: "Tunisia (+216)"
  }, {
    country_code: "TR",
    value: "90",
    name: "Turkey (+90)"
  }, {
    country_code: "TM",
    value: "7",
    name: "Turkmenistan (+7)"
  }, {
    country_code: "TM",
    value: "993",
    name: "Turkmenistan (+993)"
  }, {
    country_code: "TC",
    value: "1649",
    name: "Turks &amp; Caicos Islands (+1649)"
  }, {
    country_code: "TV",
    value: "688",
    name: "Tuvalu (+688)"
  }, {
    country_code: "UG",
    value: "256",
    name: "Uganda (+256)"
  }, {
    country_code: "UA",
    value: "380",
    name: "Ukraine (+380)"
  }, {
    country_code: "AE",
    value: "971",
    name: "United Arab Emirates (+971)"
  }, {
    country_code: "UY",
    value: "598",
    name: "Uruguay (+598)"
  }, {
    country_code: "UZ",
    value: "7",
    name: "Uzbekistan (+7)"
  }, {
    country_code: "VU",
    value: "678",
    name: "Vanuatu (+678)"
  }, {
    country_code: "VA",
    value: "379",
    name: "Vatican City (+379)"
  }, {
    country_code: "VE",
    value: "58",
    name: "Venezuela (+58)"
  }, {
    country_code: "VN",
    value: "84",
    name: "Vietnam (+84)"
  }, {
    country_code: "VG",
    value: "84",
    name: "Virgin Islands - British (+1284)"
  }, {
    country_code: "VI",
    value: "84",
    name: "Virgin Islands - US (+1340)"
  }, {
    country_code: "WF",
    value: "681",
    name: "Wallis &amp; Futuna (+681)"
  }, {
    country_code: "YE",
    value: "969",
    name: "Yemen (North)(+969)"
  }, {
    country_code: "YE",
    value: "967",
    name: "Yemen (South)(+967)"
  }, {
    country_code: "ZM",
    value: "260",
    name: "Zambia (+260)"
  }, {
    country_code: "ZW",
    value: "263",
    name: "Zimbabwe (+263)"
  }];
  const [showModal, setShowModal] = useState(false);
  const [isLoading, setLoading] = useState(false);
  const [error, setError] = useState(null);
  const [country, setCountry] = useState({});
  const [selectedCountry, setSelectedCountry] = useState(null);
  const [isCountrySelectOpen, setIsCountrySelectOpen] = useState(false);
  const [selectedProduct, setSelectedProduct] = useState(productList.find(el => el.type === productType));
  const [isProductSelectOpen, setIsProductSelectOpen] = useState(false);
  const form = useRef(null);
  const countrySelectRef = useRef(null);
  const productSelectRef = useRef(null);
  const currentFormData = useRef({});
  const getCookie = name => {
    const result = new RegExp('(?:^|; )' + encodeURIComponent(name) + '=([^;]*)').exec(document.cookie);
    return result ? result[1] : null;
  };
  const toggleModal = () => {
    const next = !showModal;
    setShowModal(next);
    document.body.style.overflow = next ? 'hidden' : 'unset';
  };
  const listenToRevenueHeroWidget = event => {
    if (event?.data?.type === 'MEETING_BOOKED') {
      window.dataLayer?.push({
        event: 'user_demo_booked'
      });
      window.sendAnalytics?.('RevenueHero: Meeting Booked', {
        product_interested_in: currentFormData.current.product_interested_in
      });
    }
    if (event?.data?.type === 'CLOSE_DIALOG') {
      window.sendAnalytics?.('RevenueHero: Pop Up Closed', {
        product_interested_in: currentFormData.current.product_interested_in
      });
      window.removeEventListener('message', listenToRevenueHeroWidget);
    }
  };
  useEffect(() => {
    if (!document.querySelector('script[src="https://app.revenuehero.io/scheduler.min.js"]')) {
      const script = document.createElement('script');
      script.type = 'text/javascript';
      script.src = 'https://app.revenuehero.io/scheduler.min.js';
      script.async = true;
      document.body.appendChild(script);
    }
    fetch('https://auth.lambdatest.com/api/country-details').then(res => res.json()).then(result => {
      setCountry(result || ({}));
      const found = countryList.find(e => e.country_code == result?.iso_code);
      if (found) {
        setSelectedCountry({
          name: found.name,
          value: result.calling_code,
          country_code: result.iso_code
        });
      }
    }, () => setError('Failed to load country data'));
    const handleClickOutside = event => {
      if (countrySelectRef.current && !countrySelectRef.current.contains(event.target)) {
        setIsCountrySelectOpen(false);
      }
      if (productSelectRef.current && !productSelectRef.current.contains(event.target)) {
        setIsProductSelectOpen(false);
      }
    };
    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
      document.body.style.overflow = 'unset';
    };
  }, []);
  const handleSubmit = async e => {
    e.preventDefault();
    setLoading(true);
    setError(null);
    const {email, mobile_no, first_name, last_name, message} = form.current.elements;
    const formdata = {
      email: email.value || '',
      mobile_no: mobile_no.value || '',
      first_name: first_name.value || '',
      product_interested_in: selectedProduct ? selectedProduct.type : productType,
      last_name: last_name.value || '',
      isd_code: selectedCountry ? selectedCountry.value : country.calling_code || '',
      message: message ? message.value || '' : '',
      source_page_url: window.location.href,
      source_page_title: document.title,
      query_type: 'Schedule a Demo',
      campaign_id: '701F9000001H1EdIAK',
      source: 'Web Submissions',
      utm: getCookie('utm'),
      gclid: getCookie('gclid')
    };
    currentFormData.current = formdata;
    try {
      const response = await fetch('https://forms.lambdatest.com/api/forms/contact', {
        method: 'POST',
        headers: {
          'Content-type': 'application/json'
        },
        body: JSON.stringify(formdata)
      });
      if (!response.ok) {
        const res = await response.json().catch(() => ({}));
        setError(res.message || 'Something went wrong. Please try again.');
        return;
      }
      form.current.reset();
      window.dataLayer?.push({
        event: 'book_a_demo_form_submitted'
      });
      if (formdata.email && formdata.email.toLowerCase().endsWith('gmail.com')) {
        window.sendAmplitudeEvents?.('Demo_Schedule_Gmail');
        window.location.href = 'https://www.testmuai.com/thank-you/';
        return;
      }
      window.sendAnalytics?.('book_a_demo_form_submitted', {
        event: 'book_a_demo_form_submitted',
        eventAction: 'success',
        eventLabel: window.location.href
      });
      window.sendAmplitudeEvents?.('Demo_Schedule');
      const hero = new window.RevenueHero({
        routerId: '630',
        showLoader: true
      });
      window.addEventListener('message', listenToRevenueHeroWidget);
      hero.submit({
        ...formdata,
        ...country
      }).then(data => {
        hero.dialog.open(data);
        setShowModal(false);
        document.body.style.overflow = 'unset';
      }).catch(err => {
        console.log(err);
        window.removeEventListener('message', listenToRevenueHeroWidget);
      });
    } catch (err) {
      setError('Something went wrong. Please try again.');
    } finally {
      setLoading(false);
    }
  };
  return <>
      <div className="kane_cli_cta not-prose">
        <div className="kane_cli_cta_box">
          <div className="kane_cli_cta_content">
            <h2>Terminal First Testing With Kane CLI</h2>
            <p>Natural language browser & mobile app tests right from terminal.</p>
            <button type="button" className="demoBtn" onClick={toggleModal}>Book a Demo</button>
          </div>
          <img loading="lazy" src="https://assets.testmu.ai/resources/images/Terminal-KaneCLIIcon.svg" alt="" aria-hidden="true" className="kane_cli_cta_icon no-zoom" />
          <img loading="lazy" src="https://assets.testmu.ai/resources/images/Terminal-KaneCLI.png" alt="Kane CLI terminal" title="Kane CLI" className="kane_cli_cta_terminal no-zoom" />
        </div>
      </div>
      <div className={'demo_popup_overlay demo_popup_header_demo not-prose ' + (showModal ? 'shown' : '')}>
        <div className="content text-left">
          <div className="demo_popup_box">
            <div className="demo_popup_form">
              <span onClick={toggleModal} className="demo_popup_close">×</span>
              <div className="demo_popup_form_title">Schedule Your Personal Demo</div>
              <form ref={form} onSubmit={handleSubmit}>
                <div className="demo_popup_grid">
                  <div>
                    <input type="text" name="first_name" placeholder="First Name" required />
                  </div>
                  <div>
                    <input type="text" name="last_name" placeholder="Last Name" required />
                  </div>
                </div>
                <div className="demo_popup_field">
                  <input type="email" name="email" placeholder="Work Email Address" pattern="^[^\s@]+@[^\s@]+\.[^\s@]+$" required />
                </div>
                <div className="demo_popup_field">
                  <div className="demo_popup_phone_row">
                    <div className="demo_popup_select_wrapper" ref={countrySelectRef}>
                      <div className={'demo_popup_select ' + (isCountrySelectOpen ? 'demo_popup_select_open' : '')} onClick={() => setIsCountrySelectOpen(!isCountrySelectOpen)}>
                        <span className="demo_popup_select_text">{selectedCountry ? selectedCountry.name : 'Select Country'}</span>
                        <span className="demo_popup_select_arrow">
                          <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M4 6L8 10L12 6" stroke="#4D4D4D" strokeWidth="1.25" strokeLinecap="square" />
              </svg>
                        </span>
                      </div>
                      {isCountrySelectOpen && <ul className="demo_popup_select_options">
                          {countryList.map((item, index) => <li key={index} className={'demo_popup_select_option ' + (selectedCountry && selectedCountry.country_code === item.country_code ? 'demo_popup_select_option_selected' : '')} onClick={() => {
    setSelectedCountry({
      name: item.name,
      value: item.value,
      country_code: item.country_code
    });
    setIsCountrySelectOpen(false);
  }}>
                              {item.name}
                            </li>)}
                        </ul>}
                    </div>
                    <input type="tel" name="mobile_no" placeholder="Phone Number" pattern="\d*" maxLength={15} required />
                  </div>
                </div>
                <div className="demo_popup_field">
                  <label>Select Product
                    <div className="demo_popup_select_wrapper" ref={productSelectRef}>
                      <div className={'demo_popup_select demo_popup_product_select ' + (isProductSelectOpen ? 'demo_popup_select_open' : '')} onClick={() => setIsProductSelectOpen(!isProductSelectOpen)}>
                        <span className="demo_popup_select_text">{selectedProduct ? selectedProduct.label : 'Select Product'}</span>
                        <span className="demo_popup_select_arrow">
                          <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path d="M4 6L8 10L12 6" stroke="#4D4D4D" strokeWidth="1.25" strokeLinecap="square" />
              </svg>
                        </span>
                      </div>
                      {isProductSelectOpen && <ul className="demo_popup_select_options">
                          {productList.map((el, index) => <li key={index} className={'demo_popup_select_option ' + (selectedProduct && selectedProduct.type === el.type ? 'demo_popup_select_option_selected' : '')} onClick={() => {
    setSelectedProduct({
      label: el.label,
      type: el.type
    });
    setIsProductSelectOpen(false);
  }}>
                              {el.label}
                            </li>)}
                        </ul>}
                    </div>
                  </label>
                </div>
                <div className="demo_popup_field">
                  <textarea name="message" className="demo_popup_message" placeholder="Your message"></textarea>
                </div>
                {error && <div className="demo_popup_error">{error}</div>}
                <div className="demo_popup_action">
                  <button type="submit" className="demo_popup_submit" disabled={isLoading}>Schedule Demo</button>
                </div>
              </form>
            </div>
          </div>
        </div>
      </div>
    </>;
};

`kane-cli testrun run --remote` dispatches a suite of `_test.md` files to <BrandName /> **HyperExecute** instead of running it on your machine. The grid provisions the runtime, runs every member, and streams the job back to your terminal: one job, one exit code, one sealed [evidence pack](/docs/docs/kane-cli-evidence/), and the same recordings and evidence you get from a run on your own machine.

Remote runs cover both kinds of test:

* **Web suites** run on **Chrome on a HyperExecute macOS runner**, with no Chrome on your machine or CI runner, headless by construction, and `--parallel N` spreads the members across N grid runners.
* **Mobile suites** (`target: emulator` or `target: simulator`) run on a **virtual Android emulator or iOS simulator on a HyperExecute macOS host**, so you can author and run mobile tests **from any machine**: Linux, Windows, Intel Macs, or a Mac without Xcode or Android Studio. The [macOS Apple Silicon requirement](/docs/docs/kane-cli-mobile/) applies only to mobile runs on your own machine.

```bash theme={null}
kane-cli plugin install remote-execution                                          # once
kane-cli testrun run --tags smoke --remote --parallel 4                           # a web suite on 4 grid runners
kane-cli testrun run tests/app/ --remote --device-name "Pixel 7" --os-version 14  # an Android suite
kane-cli testrun run tests/ios/ --remote --device-name "iPhone 15" --os-version 17.5
```

<Note>
  `--remote` is not the same as `--ws-endpoint` or `--cdp-endpoint`. Those attach a **remote browser** to a run that still executes on your machine (`kane-cli run`, `kane-cli testmd run`). `--remote` moves the **whole suite** to the grid: kane-cli itself runs there, and nothing but Node and the plugin is needed locally.
</Note>

## Prerequisites

| You need                                                                                                                                  | Why                                                                                                                                                                                      | How to check                                                                               |
| ----------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
| A <BrandName /> plan that includes **HyperExecute**, with **macOS runner concurrency** (web and mobile members both run on macOS runners) | Every remote run is a HyperExecute job                                                                                                                                                   | Ask your account owner, or open the HyperExecute dashboard for your organisation           |
| The `remote-execution` plugin                                                                                                             | It owns the HyperExecute binary kane-cli dispatches with                                                                                                                                 | `kane-cli plugin install remote-execution`, then `kane-cli plugin doctor remote-execution` |
| A <BrandName /> **username and access key**                                                                                               | HyperExecute authenticates with basic auth. An OAuth profile is exchanged for them automatically; otherwise pass `--username` and `--access-key`                                         | `kane-cli whoami`                                                                          |
| A project directory that **contains the tests**                                                                                           | The current directory is zipped and shipped as the job payload                                                                                                                           | Run from the repository root, or any parent of the tests                                   |
| Recordings **not gitignored**                                                                                                             | The payload respects `.gitignore`, and an ignored `output-<stem>/` never reaches the grid. Builds are not payload, see [The app under test on the grid](#the-app-under-test-on-the-grid) | `--dry-run` reports `gitignored_inputs`; un-ignore with, for example, `!output-*/`         |

The project and folder the run uploads to are the ones configured on your profile (`kane-cli config project` and `kane-cli config folder`); they are passed to the grid's login.

## How a remote run works

1. **Preflight, then remote preflight.** The normal `testrun` plan is built (one organisation, one project, see [Preflight](/docs/docs/kane-cli-testrun/#preflight)); then kane-cli checks the selection can be **one grid job** ([What one job can hold](#what-one-job-can-hold)) and, for mobile, resolves the device against the grid catalog. Anything wrong stops here, nothing is dispatched, exit `2`.
2. **Payload.** The current directory is zipped (respecting `.gitignore`) and uploaded with a generated job definition. The dispatch leaves `.hyperexecute/`, `hyperexecute-cli.log` and `.updatedhyperexecute.yaml` in that directory: add them to `.gitignore`, they are not inputs.
3. **On the grid** (a macOS runner): a pre-step installs kane-cli and logs in with your credentials and project; for mobile it installs the device tooling and boots the device. Then **each member runs as its own `kane-cli testmd run`**, headless, exactly as it would on your machine. A member with recordings replays them, a member without authors on the grid.
4. **Back to you.** The job streams progress and the dashboard link to your terminal. When it ends, the members' `output-<stem>/` recordings and the sealed evidence pack are downloaded into your project, the pack is published to Test Manager, and the suite summary and exit code are the same as a local `testrun`.

Allow a few minutes on top of the tests' own time: in practice about 15 seconds of setup for a web job, and a minute or more for a mobile job (device boot, app install). A wall-clock timeout of 10 minutes is a safe starting point in CI.

## Dispatching a run

`--remote` takes the normal `testrun` selection (paths, `--match`, `--tags`).

```bash theme={null}
kane-cli testrun run --tags smoke --remote --dry-run          # both preflights, nothing dispatched
kane-cli testrun run --tags smoke --remote --parallel 4
```

`--dry-run` runs both preflights and resolves any device **without creating a job**. Use it before every new selection; it costs nothing.

A real run prints the job id and dashboard link, then tracks the job until it completes:

```
job 24fc58b2-… dispatched → https://hyperexecute.lambdatest.com/hyperexecute/task?jobId=24fc58b2-…
```

| Flag                                                                          | On the grid                                                                                                                                                                                                      |
| ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--parallel <n>`                                                              | Becomes the job's concurrency: the members are auto-split across `n` grid runners, each running its share one member at a time. Device suites parallelize the same way, and every task has its own VM and device |
| `--headless`                                                                  | Not needed, every member runs headless on the grid                                                                                                                                                               |
| `--on-failure`, `--name`, `--bug-detection`, `--author`, `--no-adaptive-heal` | Forwarded to the members on the grid                                                                                                                                                                             |
| `--username`, `--access-key`                                                  | Used for the grid login and the Test Manager upload                                                                                                                                                              |

## Web suites on the grid

A web suite needs nothing beyond the prerequisites: the grid runner has Chrome, kane-cli finds it and runs each member headless. Use it when the runner cannot have Chrome, when you want the suite off your laptop, or when you want more parallelism than one machine gives you.

```bash theme={null}
kane-cli plugin install remote-execution
kane-cli testrun run tests/web/ --remote --parallel 4 --on-failure fail-fast
```

What you see back is a normal `testrun` summary; the only extra lines are the dispatch and the job link. A member that authors on the grid comes back with its `output-<stem>/` recordings, so the next run, on the grid or on your machine, replays them. Commit those recordings as you would after a local run.

A web selection cannot share a job with device members (`mobile_remote_mixed`). Run the two suites separately.

## Choosing a grid device

Remote devices come from the **grid catalog**, not from the AVDs or simulators on your machine. List what the grid can provision:

```bash theme={null}
kane-cli devices list --target emulator --remote                    # Android emulators
kane-cli devices list --target simulator --remote                   # iOS simulators
kane-cli devices list --target simulator --remote --os-version 17.5 # only that OS version
```

Each row is a device **name** plus the **OS versions** it ships with. Address one with both:

| Flag or key                                     | Purpose                                                                                                      |
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `--device-name "<name>"`                        | The name exactly as the catalog prints it (`"Pixel 7"`, `"iPhone 15"`). Validated before dispatch            |
| `--os-version <v>`                              | The OS version (`14`, `17.5`). On its own, it means any catalog device running that version                  |
| `device_name:` or `os_version:` in a `_test.md` | Per-test defaults, used when the flags are absent. See [Mobile target](/docs/docs/kane-cli-testmd/#mobile-target) |

If you pass neither, kane-cli picks a catalog default for the platform and prints it on the device line. Read it before relying on it.

The two platforms bind the device differently:

* **Emulator**: the job allocates **one device for all its members**, so they must agree on one Android version (`mobile_os_version_split` otherwise, or force one with `--os-version`). An AVD name from your own machine is ignored in a member (you get a `device_name_ignored` note), because a remote job's device is named by the catalog.
* **Simulator**: each task boots a simulator inside its own VM, so **each member binds its own `device_name:` and `os_version:`** (validated against the catalog). `--device-name` and `--os-version`, when passed, apply to every member. Members may ask for different iOS versions as long as their iOS majors map to one HyperExecute pool, which the catalog decides (today 17 and 18 share one, 26 is another); otherwise `mobile_pool_split`.

## The app under test on the grid

The grid machine has to *obtain* the app. A build never rides the payload, it reaches the grid by id:

| `app:` in the test                                                                               | What happens                                                                                                                                                                                                                                       |
| ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| A local build, `.apk` for `emulator` or a `.zip` of the `.app` for `simulator`, anywhere on disk | **Uploaded from your machine at preflight**, once per distinct file (a per-machine cache skips a build your account already has), and handed to the grid as `--app <id>`. It may be gitignored or outside the project. `--dry-run` uploads nothing |
| An uploaded `APP…` id                                                                            | Used as is, and the grid downloads it                                                                                                                                                                                                              |

Each member gets its own id, so a run may hold members that name different builds. A `.ipa` is refused up front: it is a device build, and the emulator and simulator upload does not take it. Every upload is reported (`app: <file> → APP… (uploaded)`, or the `remote_app` event for agents).

`kane-cli apps list --target emulator|simulator` shows the uploaded builds your account can use, and the **APP ID** column is what `app:` takes. There is no upload subcommand: any run with a local build, on the grid or on your machine, uploads it and prints the `APP…` id. Uploads belong to an organisation, so `apps list` for the current profile is the authority on which ids a run can use.

## What one job can hold

One remote run is one HyperExecute job, which allocates **one kind of runtime**. The remote preflight refuses a selection that needs more than one, and tells you how to split it (`--match` or `--tags`):

| Reason                         | Meaning                                                                                  | Fix                                                                        |
| ------------------------------ | ---------------------------------------------------------------------------------------- | -------------------------------------------------------------------------- |
| `mobile_remote_mixed`          | Web and device tests in one selection                                                    | Two runs: one for the device tests, one for the rest                       |
| `mobile_remote_mixed_platform` | Emulator and simulator tests in one selection                                            | Two runs, one per platform                                                 |
| `mobile_os_version_split`      | Emulator tests asking for different Android versions                                     | One run per version, or `--os-version` to force one                        |
| `mobile_pool_split`            | Simulator tests whose iOS versions need different HyperExecute pools                     | One run per pool, or `--os-version` to force one                           |
| `mobile_remote_unsupported`    | A device target the grid cannot provide                                                  | Run it on your own machine, or deselect it                                 |
| `mobile_app_missing`           | A device test names a local build that is not on this machine                            | Fix the path, or use an `APP…` id                                          |
| `mobile_app_not_uploadable`    | The build is not one the cloud takes (a `.ipa`, or the wrong extension for the platform) | `.apk` for emulator, a `.zip` of the `.app` for simulator, or an `APP…` id |
| `mobile_app_upload_failed`     | Uploading the build from your machine failed                                             | Fix the upload (network, auth), or use an `APP…` id                        |
| `member_outside_payload`       | A test lives outside the dispatched directory                                            | Run from a directory that contains it                                      |
| `gitignored_inputs`            | Required recordings are gitignored                                                       | Un-ignore them (for example `!output-*/`) or commit them                   |
| `on_grid`                      | Already running on a HyperExecute grid                                                   | `--remote` cannot re-dispatch from inside a job                            |

Every reason arrives with the offending paths, both in the terminal and as a `remote_error` event for agents.

## What comes back

* **Recordings**: authored members' `output-<stem>/` directories land in your project exactly as a run on your machine would leave them, so the next run replays from cache.
* **Evidence**: one sealed pack for the suite in `.testmuai/evidence/`, published to your project's execution history in Test Manager.
* **Job logs**: the per-member session logs under `~/.testmuai/kaneai/sessions/remote/<job-id>/`, and the full stage logs on the HyperExecute dashboard at the printed job link.
* **Exit code**: the same as a local `testrun`. `0` all passed, `1` a member failed or broke, `2` preflight, auth or usage (nothing dispatched), `3` cancelled.

## When a remote run fails

* **A member failed or broke** (exit `1`): read it like any other failure. `output-<stem>/Result.md` names the failing step and reason, and the evidence pack has the screenshots and logs. See [Debugging with a pack](/docs/docs/kane-cli-troubleshooting/#debugging-a-failed-run-with-its-evidence-pack).
* **A member is `broken` with no steps** and nothing was published: the grid-side kane-cli refused before launching. Open the job link and read the scenario stage log. For mobile, the usual cause is an `APP…` id that belongs to a different organisation than the account running the job.
* **Nothing was dispatched** (exit `2`): the printed reason is one of the preflight codes above, or `kane-cli plugin doctor remote-execution` shows what is missing (plugin, binary, login).

## In CI

A remote run needs no Chrome, Xcode or Android Studio on the runner, only Node and the plugin:

```bash theme={null}
npm install -g @testmuai/kane-cli
kane-cli plugin install remote-execution

# a web suite
kane-cli testrun run tests/web/ --remote --parallel 4 \
  --username "$LT_USERNAME" --access-key "$LT_ACCESS_KEY" --on-failure fail-fast

# a mobile suite
kane-cli testrun run tests/app/ --remote \
  --device-name "Pixel 7" --os-version 14 \
  --username "$LT_USERNAME" --access-key "$LT_ACCESS_KEY" --on-failure fail-fast
```

Archive `.testmuai/evidence/*.evidence` as the build artifact. More pipeline shapes are in [CI/CD](/docs/docs/kane-cli-cicd/).

## For agents: NDJSON events

In agent or non-TTY mode a remote run adds typed events around the normal `testrun_*` stream (see [For agents](/docs/docs/kane-cli-testrun/#for-agents-ndjson-events)):

| `type`                                | Payload                                                      | Notes                                                                                                                                                                                |
| ------------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `remote_start`                        | `backend`, `env`                                             | Dispatch begins                                                                                                                                                                      |
| `remote_device`                       | `platform`, `slug`, `name`, `os_version`, `avd_id?`, `pool?` | The resolved grid device, mobile only. A web run has no device line                                                                                                                  |
| `remote_device_hint`                  | `reason`, `detail`                                           | `device_name_ignored` (emulator only, a local AVD name was dropped) or `catalog_stale`                                                                                               |
| `remote_app`                          | `path`, `app_id`, `source`                                   | One per distinct local build uploaded from your machine, mobile only. `source` is `uploaded`, `cache` (already uploaded by this machine) or `dry-run` (`app_id` empty, nothing sent) |
| `remote_dispatched`                   | `job_id`, `job_url`                                          | The HyperExecute job exists, and the link opens the dashboard                                                                                                                        |
| `remote_error`                        | `code`, `detail`                                             | Remote preflight refused the selection (codes above), followed by `testrun_done` and exit `2`                                                                                        |
| `remote_exec_sync`, `remote_coverage` | `status`, `reason`, `detail?`                                | Informational: assurance graph sync and coverage, skipped when the project has no `.context` store                                                                                   |
| `remote_done`                         | `status`, `exit`, `job_id`, `sessions_path`                  | Terminal for the remote wrapper, and follows `testrun_done`                                                                                                                          |

`testrun_summary` also carries a `remote` object (`backend`, `jobId`, `jobUrl`, `sessionsPath`).

## Next Steps

* [Batch Runs (testrun)](/docs/docs/kane-cli-testrun/) for selection, preflight, flags and exit codes
* [Mobile Testing](/docs/docs/kane-cli-mobile/) for setup on your own machine, or skip it with `--remote`
* [Writing test.md files](/docs/docs/kane-cli-testmd/#mobile-target) for `target:`, `app:`, `device_name:` and `os_version:`
* [Evidence Packs](/docs/docs/kane-cli-evidence/) for what comes back and how to view it
* [CI/CD](/docs/docs/kane-cli-cicd/) for pipeline patterns, including runners with no Chrome

<KaneCliCta />
