Configuration (v4) - johnste/finicky GitHub Wiki
âšī¸ 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.
Table of Contents
- General options
- Matching urls
- Selecting a browser
- Rewriting urls
- Type checking
- Function Parameters
- Utility Functions
- Complete Example Configuration
General options
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",
},
],
};
Matching urls
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:
Matching Methods
- 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"),
];
Selecting a browser
Finicky provides multiple ways to specify which browser should handle a URL:
1. Simple Browser Selection
export default {
defaultBrowser: "Safari",
handlers: [
{
match: (url) => url.host.endsWith("example.org"),
browser: "Firefox",
},
],
};
2. Browser Selection Methods
A. Using browser names or bundle IDs:
browser: "Google Chrome"; // By app name
browser: "com.google.Chrome"; // By bundle ID
browser: "/Applications/Firefox.app"; // By app path
B. Using browser profiles (Chromium browsers):
browser: "Google Chrome:Personal" // Profile name after colon
browser: {
name: "Google Chrome",
profile: "Personal"
}
C. Advanced browser configuration:
browser: {
name: "Google Chrome",
appType: "appName", // Force name type: "appName", "bundleId" or "appPath"
openInBackground: true, // Open in background instead of foreground
profile: "Work",
}
D. Dynamic browser selection:
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"),
});
Rewriting urls
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;
},
},
],
};
Type checking
If your text editor / IDE supports type checking, you can enable it like this.
JavaScript
// @ts-check
/**
* @typedef {import('/Applications/Finicky.app/Contents/Resources/finicky.d.ts').FinickyConfig} FinickyConfig
*/
/**
* @type {FinickyConfig}
*/
export default {
// ... your configuration here
};
TypeScript
// ~/.finicky.ts
import type { FinickyConfig } from "/Applications/Finicky.app/Contents/Resources/finicky.d.ts";
export default {
// ... your configuration here
} satisfies FinickyConfig;
Function Parameters
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;
};
};
Utility Functions
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
Complete Example Configuration
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",
},
],
};