Hi @amandaswtz.
This is achievable using AppleScript as well as using JavaScript For Automation (JXA). I prefer scripting in JXA.
Here's a JXA script that when run will activate the (unpinned) Arc tab whose URL contains folivora
:
(() => {
"use strict";
// Define the search query string to filter tab URLs.
// This value can be modified to search for a different string.
const queryString = "folivora";
// This variable represents the location of the tab in the sidebar.
// It can be 'topApp', 'pinned', or 'unpinned'.
const tabLocation = "unpinned";
// Get a reference to the Arc browser application.
// This allows interaction with Arc's scripting interface as described in its sdef.
const arc = Application("Arc");
// Access the first (frontmost) window of Arc and filter its tabs.
// Only include tabs where:
// 1. The tab's URL contains the specified query string.
// 2. The tab's location matches the defined tabLocation.
const frontWindowTabs = arc.windows.at(0).tabs.where({
_and: [
{ url: { _contains: queryString } }, // Tab's URL includes the query string
{ location: tabLocation } // Tab's location is as specified (e.g., 'unpinned')
],
});
// Retrieve the first matching tab.
const firstMatchingTab = frontWindowTabs[0];
// Send the "select" command to the matching tab to make it active.
firstMatchingTab.select();
})();
Likewise, here's a script that will activate the Arc tab whose title contains BetterTouchTool Community
:
(() => {
"use strict";
// Define the search query string to filter tab titles.
// This value can be modified to search for a different string.
const queryString = "BetterTouchTool Community";
// This variable represents the location of the tab in the sidebar.
// It can be 'topApp', 'pinned', or 'unpinned'.
const tabLocation = "unpinned";
// Get a reference to the Arc browser application.
// This allows interaction with Arc's scripting interface as described in its sdef.
const arc = Application("Arc");
// Access the first (frontmost) window of Arc and filter its tabs.
// Only include tabs where:
// 1. The tab's title contains the specified query string.
// 2. The tab's location matches the defined tabLocation.
const frontWindowTabs = arc.windows.at(0).tabs.where({
_and: [
{ title: { _contains: queryString } }, // Tab's title includes the query string
{ location: tabLocation } // Tab's location is as specified (e.g., 'unpinned')
],
});
// Retrieve the first matching tab.
const firstMatchingTab = frontWindowTabs[0];
// Send the "select" command to the matching tab to make it active.
firstMatchingTab.select();
})();
Finally, here's a complete BTT configuration JSON that includes a key sequences trigger (specifically, qq
) connected with a Run Apple Script (async in background) Action (configured using Apple JavaScript for Automation (JAX)). If you copy and then paste this JSON into the BTT configuration GUI then you'll replicate my exact setup.
[
{
"BTTActionCategory" : 0,
"BTTLastUpdatedAt" : 1744741028.1389461,
"BTTTriggerType" : 624,
"BTTTriggerTypeDescriptionReadOnly" : "Please Select a Trigger ",
"BTTTriggerClass" : "BTTTriggerTypeKeySequence",
"BTTUUID" : "DB12DDAE-906C-4D6B-8F30-74A6BFB3CCFC",
"BTTPredefinedActionType" : 366,
"BTTPredefinedActionName" : "Empty Placeholder",
"BTTEnabled" : 1,
"BTTEnabled2" : 1,
"BTTOrder" : 0,
"BTTAdditionalActions" : [
{
"BTTActionCategory" : 0,
"BTTLastUpdatedAt" : 1744746624.383714,
"BTTTriggerParentUUID" : "DB12DDAE-906C-4D6B-8F30-74A6BFB3CCFC",
"BTTIsPureAction" : true,
"BTTTriggerClass" : "BTTTriggerTypeKeySequence",
"BTTUUID" : "C99211E8-633A-49A6-880E-C3D0E3B0EAD8",
"BTTPredefinedActionType" : 252,
"BTTPredefinedActionName" : "Run JavaScript for Automation (async in background)",
"BTTAdditionalActionData" : {
"BTTScriptType" : 1,
"BTTAppleScriptString" : "(() => {\n \"use strict\";\n\n \/\/ Define the search query string to filter tab titles.\n \/\/ This value can be modified to search for a different string.\n const queryString = \"BetterTouchTool Community\";\n\n \/\/ This variable represents the location of the tab in the sidebar.\n \/\/ It can be 'topApp', 'pinned', or 'unpinned'.\n const tabLocation = \"unpinned\";\n\n \/\/ Get a reference to the Arc browser application.\n \/\/ This allows interaction with Arc's scripting interface as described in its sdef.\n const arc = Application(\"Arc\");\n\n \/\/ Access the first (frontmost) window of Arc and filter its tabs.\n \/\/ Only include tabs where:\n \/\/ 1. The tab's title contains the specified query string.\n \/\/ 2. The tab's location matches the defined tabLocation.\n const frontWindowTabs = arc.windows.at(0).tabs.where({\n _and: [\n { title: { _contains: queryString } }, \/\/ Tab's title includes the query string\n { location: tabLocation } \/\/ Tab's location is as specified (e.g., 'unpinned')\n ],\n });\n\n \/\/ Retrieve the first matching tab.\n const firstMatchingTab = frontWindowTabs[0];\n\n \/\/ Send the \"select\" command to the matching tab to make it active.\n firstMatchingTab.select();\n})();",
"BTTAppleScriptUsePath" : false,
"BTTAppleScriptRunInBackground" : true,
"SelectedAction" : 195,
"BTTScriptLocation" : 0
},
"BTTInlineAppleScript" : "(() => {\n \"use strict\";\n\n \/\/ Define the search query string to filter tab titles.\n \/\/ This value can be modified to search for a different string.\n const queryString = \"BetterTouchTool Community\";\n\n \/\/ This variable represents the location of the tab in the sidebar.\n \/\/ It can be 'topApp', 'pinned', or 'unpinned'.\n const tabLocation = \"unpinned\";\n\n \/\/ Get a reference to the Arc browser application.\n \/\/ This allows interaction with Arc's scripting interface as described in its sdef.\n const arc = Application(\"Arc\");\n\n \/\/ Access the first (frontmost) window of Arc and filter its tabs.\n \/\/ Only include tabs where:\n \/\/ 1. The tab's title contains the specified query string.\n \/\/ 2. The tab's location matches the defined tabLocation.\n const frontWindowTabs = arc.windows.at(0).tabs.where({\n _and: [\n { title: { _contains: queryString } }, \/\/ Tab's title includes the query string\n { location: tabLocation } \/\/ Tab's location is as specified (e.g., 'unpinned')\n ],\n });\n\n \/\/ Retrieve the first matching tab.\n const firstMatchingTab = frontWindowTabs[0];\n\n \/\/ Send the \"select\" command to the matching tab to make it active.\n firstMatchingTab.select();\n})();",
"BTTEnabled" : 1,
"BTTEnabled2" : 1,
"BTTOrder" : 766
}
],
"BTTKeySequence" : {
"BTTPauseBetween" : 0.29999999999999999,
"BTTCharactersToDeleteAfterwards" : 2,
"BTTKeyCount" : 4,
"BTTKeySequenceDownKeys" : [
{
"BTTKEYCharacter" : " Q",
"BTTKEYCode" : 12,
"BTTKEYDown" : 1,
"BTTKEYOrderRelevant" : 1,
"BTTKEYRequired" : 1,
"BTTKEYTime" : 766433280
},
{
"BTTKEYCharacter" : " Q",
"BTTKEYCode" : 12,
"BTTKEYDown" : 1,
"BTTKEYOrderRelevant" : 1,
"BTTKEYRequired" : 1,
"BTTKEYTime" : 766433280
}
],
"BTTKeySequenceMixedKeys" : [
{
"BTTKEYCharacter" : " Q",
"BTTKEYCode" : 12,
"BTTKEYDown" : 1,
"BTTKEYOrderRelevant" : 1,
"BTTKEYRequired" : 1,
"BTTKEYTime" : 766433280
},
{
"BTTKEYCharacter" : " Q",
"BTTKEYCode" : 12,
"BTTKEYRequired" : 1,
"BTTKEYTime" : 766433280
},
{
"BTTKEYCharacter" : " Q",
"BTTKEYCode" : 12,
"BTTKEYDown" : 1,
"BTTKEYOrderRelevant" : 1,
"BTTKEYRequired" : 1,
"BTTKEYTime" : 766433280
},
{
"BTTKEYCharacter" : " Q",
"BTTKEYCode" : 12,
"BTTKEYRequired" : 1,
"BTTKEYTime" : 766433280
}
],
"BTTKeySequenceUpKeys" : [
{
"BTTKEYCharacter" : " Q",
"BTTKEYCode" : 12,
"BTTKEYRequired" : 1,
"BTTKEYTime" : 766433280
},
{
"BTTKEYCharacter" : " Q",
"BTTKEYCode" : 12,
"BTTKEYRequired" : 1,
"BTTKEYTime" : 766433280
}
]
}
}
]
I hope this is helpful.