-
-
Notifications
You must be signed in to change notification settings - Fork 155
Configuration (v4)
ℹ️ Finicky v4 is new, and this page might contain mistakes. If you notice one, please edit the page or let the developer know by opening an issue, creating a discussion or reaching out in other ways.
- General options
- Matching urls
- Selecting a browser
- Rewriting urls
- Type checking
- Function Parameters
- Utility Functions
- Complete Example Configuration
export default {
defaultBrowser: "Google Chrome",
options: {
// Check for updates. Default: true
checkForUpdates: true,
// Log every request to file. Default: false
logRequests: false,
},
rewrite: [
{
match: "example.org/*",
url: "http://example.com",
},
],
handlers: [
{
match: "apple.com/*",
browser: "Safari",
},
],
};
URL matching is a core feature of Finicky that allows you to route different URLs to different browsers or rewrite them. Here are the different ways to match URLs:
- String matching with wildcards:
match: "http://example.com/*"; // Matches any path after example.com
match: "*.example.com/*"; // Matches any subdomain of example.com
- Regular Expression matching:
More powerful than wildcard string matching, but also more complex to read and write.
match: /^https?:\/\/example\.com/.*$/ // Matches http or https URLs from example.com
match: /\.(dev|test)\.example\.com$/ // Matches specific subdomains
- Function-based matching:
match: (url) => url.host === "example.com";
match: (url) => url.pathname.startsWith("/api/");
- Combined matching:
match: [
"https://example.com",
/^http:\/\/example.(org|com)\/.*/,
(url) => url.pathname.includes("/hello"),
];
Finicky provides multiple ways to specify which browser should handle a URL:
export default {
defaultBrowser: "Safari",
handlers: [
{
match: (url) => url.host.endsWith("example.org"),
browser: "Firefox",
},
],
};
browser: "Google Chrome"; // By app name
browser: "com.google.Chrome"; // By bundle ID
browser: "/Applications/Firefox.app"; // By app path
browser: "Google Chrome:Personal" // Profile name after colon
browser: {
name: "Google Chrome",
profile: "Personal"
}
browser: {
name: "Google Chrome",
appType: "appName", // Force name type: "appName", "bundleId" or "appPath"
openInBackground: true, // Open in background instead of foreground
profile: "Work",
}
browser: (url) => {
if (url.host === "example.com") return "Google Chrome";
if (url.host === "work.example.com") return "Firefox";
return "Safari";
};
// Or with dynamic background opening:
browser: (url) => ({
name: "Google Chrome",
openInBackground: url.href.includes("facebook"),
});
URL rewriting allows you to modify URLs before they are opened. Here are the different ways to rewrite URLs:
export default {
rewrite: [
// Simple string replacement
{
match: "example.org/*",
url: "https://gitlab.com",
},
// Using URL instance
{
match: "example.org/*",
url: new URL("https://example.com"),
},
// Dynamic URL modification
{
match: "example.org/*",
url: (url) => {
url.pathname = "/hello";
return url;
},
},
// Complex URL transformation
{
match: /^https?:\/\/old\.example\.com\/(.*)/,
url: (url) => {
const newUrl = new URL("https://new.example.com");
newUrl.pathname = url.pathname;
newUrl.search = url.search;
return newUrl;
},
},
],
};
If your text editor / IDE supports type checking, you can enable it like this.
// @ts-check
/**
* @typedef {import('/Applications/Finicky.app/Contents/Resources/finicky.d.ts').FinickyConfig} FinickyConfig
*/
/**
* @type {FinickyConfig}
*/
export default {
// ... your configuration here
};
// ~/.finicky.ts
import type { FinickyConfig } from "/Applications/Finicky.app/Contents/Resources/finicky.d.ts";
export default {
// ... your configuration here
} satisfies FinickyConfig;
All function callbacks (matcher, browser, and url) receive the same parameters:
type CallbackParams = {
url: URL; // The URL to be handled
options: {
opener: {
name: string; // Name of the app that opened the URL
bundleId: string; // Bundle ID of the opener
path: string; // Path to the opener app
} | null;
};
};
Finicky provides several utility functions to help with configuration:
// Logging
console.log("Log message to console");
console.warn("Log warning message to console");
console.error("Log error message to console");
// URL matching
finicky.matchHostnames(["example.com", "*.example.org"]);
// System information
const modifiers = finicky.getModifierKeys(); // Get current modifier key states
// Returns: {
// shift: boolean, // Is shift key pressed?
// option: boolean, // Is option/alt key pressed?
// command: boolean, // Is command key pressed?
// control: boolean, // Is control key pressed?
// capsLock: boolean, // Is caps lock on?
// fn: boolean // Is fn key pressed?
// }
const systemInfo = finicky.getSystemInfo(); // Get system information
// Returns: {
// localizedName: string, // Localized system name
// name: string // System name
// }
const powerInfo = finicky.getPowerInfo(); // Get power/battery information
// Returns: {
// isCharging: boolean, // Is device charging?
// isConnected: boolean, // Is power connected?
// percentage: number | null // Battery percentage (null if not available)
// }
// App state
const isRunning = finicky.isAppRunning("Google Chrome"); // Check if an app is running
// Returns: boolean // true if the app is running, false otherwise
Here's a comprehensive example showing various Finicky features:
export default {
defaultBrowser: "Google Chrome",
options: {
checkForUpdates: true,
logRequests: true,
},
// URL rewriting rules
rewrite: [
{
match: "old.example.com/*",
url: "https://new.example.com",
},
{
match: /^https?:\/\/redirect\.example\.com\/(.*)/,
url: (url) => {
const newUrl = new URL("https://target.example.com");
newUrl.pathname = url.pathname;
return newUrl;
},
},
],
// Browser selection rules
handlers: [
{
match: "work.example.com/*",
browser: {
name: "Google Chrome",
profile: "Work",
openInBackground: true,
},
},
{
match: "personal.example.com/*",
browser: "Google Chrome:Personal",
},
{
match: "safari.example.com/*",
browser: "Safari",
},
{
match: (url) => url.host.endsWith(".dev"),
browser: "Firefox",
},
],
};