Direct integration with Alfred's environment, including metadata access, system icons, and debugging support. This module provides deep integration with Alfred's workflow system and macOS environment.
Access to current workflow metadata and identifiers.
/**
* Workflow metadata from Alfred environment variables
*/
meta: WorkflowMeta;
interface WorkflowMeta {
/** Workflow name */
name: string;
/** Workflow version */
version: string;
/** Workflow unique identifier */
uid: string;
/** Workflow bundle identifier */
bundleId: string;
/** Workflow type */
type: string;
}Usage Examples:
import alfy from "alfy";
// Access workflow information
console.log(`Running ${alfy.meta.name} v${alfy.meta.version}`);
console.log(`Bundle ID: ${alfy.meta.bundleId}`);
console.log(`Workflow UID: ${alfy.meta.uid}`);
// Use in error reporting or logging
alfy.log(`[${alfy.meta.name}] Processing user input: ${alfy.input}`);
// Version-specific behavior
if (alfy.meta.version >= '2.0.0') {
// Use new features...
} else {
// Fallback for older versions...
}
// Include metadata in API requests
const userAgent = `${alfy.meta.name}/${alfy.meta.version}`;
const data = await alfy.fetch('https://api.example.com/data', {
headers: { 'User-Agent': userAgent }
});Access to Alfred's runtime environment and configuration.
/**
* Alfred environment data and configuration
*/
alfred: AlfredEnvironment;
interface AlfredEnvironment {
/** Alfred version (e.g., '5.0.3') */
version: string;
/** Current theme identifier */
theme: string;
/** Theme background color */
themeBackground: string;
/** Theme selection background color */
themeSelectionBackground: string;
/** Theme subtext mode (0-3) as string */
themeSubtext: string;
/** Workflow data directory path */
data: string;
/** Workflow cache directory path */
cache: string;
/** Alfred preferences directory path */
preferences: string;
/** Local preferences hash */
preferencesLocalHash: string;
}Usage Examples:
import alfy from "alfy";
// Check Alfred version for feature compatibility
if (parseFloat(alfy.alfred.version) >= 5.0) {
// Use Alfred 5+ features
console.log('Using Alfred 5 features');
} else {
console.log('Running on older Alfred version');
}
// Adapt to user's theme
console.log(`Current theme: ${alfy.alfred.theme}`);
console.log(`Background color: ${alfy.alfred.themeBackground}`);
// Check subtext display mode
switch (alfy.alfred.themeSubtext) {
case '0':
console.log('Subtext always shown');
break;
case '1':
console.log('Subtext only for alternative actions');
break;
case '2':
console.log('Subtext only for selected item');
break;
case '3':
console.log('Subtext never shown');
break;
}
// Access data directories
console.log(`Data directory: ${alfy.alfred.data}`);
console.log(`Cache directory: ${alfy.alfred.cache}`);
// Use preference information
console.log(`Preferences: ${alfy.alfred.preferences}`);
console.log(`Local hash: ${alfy.alfred.preferencesLocalHash}`);Utilities for accessing macOS system icons in Alfred results.
/**
* System icon utilities for Alfred results
*/
icon: IconUtilities;
interface IconUtilities {
/** Get system icon path by name */
get(iconName: string): string;
/** Info icon path */
info: string;
/** Warning icon path */
warning: string;
/** Error icon path */
error: string;
/** Alert icon path */
alert: string;
/** Like/favorite icon path */
like: string;
/** Delete icon path */
delete: string;
}Usage Examples:
import alfy from "alfy";
// Use predefined system icons
const items = [
{
title: 'Information',
subtitle: 'System information',
icon: { path: alfy.icon.info }
},
{
title: 'Warning',
subtitle: 'Something needs attention',
icon: { path: alfy.icon.warning }
},
{
title: 'Error',
subtitle: 'Something went wrong',
icon: { path: alfy.icon.error }
},
{
title: 'Action Required',
subtitle: 'User action needed',
icon: { path: alfy.icon.alert }
}
];
alfy.output(items);
// Get custom system icons
const clockIcon = alfy.icon.get('Clock');
const folderIcon = alfy.icon.get('GenericFolderIcon');
const networkIcon = alfy.icon.get('Network');
const moreItems = [
{
title: 'Current Time',
subtitle: new Date().toLocaleString(),
icon: { path: clockIcon }
},
{
title: 'Open Folder',
subtitle: '~/Documents',
icon: { path: folderIcon }
},
{
title: 'Network Status',
subtitle: 'Check connection',
icon: { path: networkIcon }
}
];
alfy.output(moreItems);
// Explore available icons (development helper)
const commonIcons = [
'ApplicationsFolderIcon', 'DocumentsFolderIcon', 'DownloadsFolderIcon',
'DesktopFolderIcon', 'BookmarkIcon', 'BurnableFolderIcon',
'ClippingText', 'ClippingPicture', 'ClippingSound',
'ColorSyncProfileIcon', 'FontSuitcaseIcon', 'GenericApplicationIcon'
];
const iconItems = commonIcons.map(iconName => ({
title: iconName,
subtitle: alfy.icon.get(iconName),
icon: { path: alfy.icon.get(iconName) },
arg: iconName
}));
// System icon paths are at:
// /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/Detect whether Alfred's workflow debugger is currently active.
/**
* Whether Alfred's workflow debugger is currently open
*/
debug: boolean;Usage Examples:
import alfy from "alfy";
// Conditional debug output
if (alfy.debug) {
console.log('Debug mode active');
console.log('User input:', alfy.input);
console.log('Workflow meta:', alfy.meta);
console.log('Alfred environment:', alfy.alfred);
}
// Detailed logging in debug mode
function debugLog(message, data = null) {
if (alfy.debug) {
const timestamp = new Date().toISOString();
alfy.log(`[${timestamp}] ${message}`);
if (data) {
alfy.log(JSON.stringify(data, null, 2));
}
}
}
// Usage
debugLog('Processing API response', { count: results.length });
debugLog('Cache hit for key: userdata');
// Performance monitoring in debug mode
async function timedFetch(url, options) {
const start = Date.now();
try {
const result = await alfy.fetch(url, options);
if (alfy.debug) {
const duration = Date.now() - start;
debugLog(`Fetch completed in ${duration}ms`, { url, duration });
}
return result;
} catch (error) {
if (alfy.debug) {
const duration = Date.now() - start;
debugLog(`Fetch failed after ${duration}ms`, { url, error: error.message });
}
throw error;
}
}
// Debug-only features
if (alfy.debug) {
// Add debug commands to results
const debugItems = [
{
title: 'Debug: Clear Cache',
subtitle: 'Clear all cached data',
arg: 'debug:clear-cache',
icon: { path: alfy.icon.alert }
},
{
title: 'Debug: Show Config',
subtitle: 'Display current configuration',
arg: 'debug:show-config',
icon: { path: alfy.icon.info }
}
];
// Add to regular results in debug mode
items.push(...debugItems);
}Direct access to Alfred's environment variables for advanced use cases.
import alfy from "alfy";
// Alfred sets various environment variables that alfy uses internally:
// - alfred_workflow_name → alfy.meta.name
// - alfred_workflow_version → alfy.meta.version
// - alfred_workflow_uid → alfy.meta.uid
// - alfred_workflow_bundleid → alfy.meta.bundleId
// - alfred_version → alfy.alfred.version
// - alfred_theme → alfy.alfred.theme
// - alfred_debug → alfy.debug (converted to boolean)
// Access original environment variables if needed
const originalTheme = process.env.alfred_theme;
const originalDebug = process.env.alfred_debug;
// Custom environment variables (set in workflow configuration)
const customApiUrl = process.env.CUSTOM_API_URL;
const customTimeout = process.env.CUSTOM_TIMEOUT;
console.log('Raw environment access:', {
theme: originalTheme,
debug: originalDebug,
customUrl: customApiUrl
});Utility functions for handling Alfred version differences.
import alfy from "alfy";
function compareVersions(version1, version2) {
const v1parts = version1.split('.').map(Number);
const v2parts = version2.split('.').map(Number);
for (let i = 0; i < Math.max(v1parts.length, v2parts.length); i++) {
const v1part = v1parts[i] || 0;
const v2part = v2parts[i] || 0;
if (v1part > v2part) return 1;
if (v1part < v2part) return -1;
}
return 0;
}
// Feature detection based on Alfred version
function supportsFeature(feature) {
const version = alfy.alfred.version;
switch (feature) {
case 'rerun':
return compareVersions(version, '3.5.0') >= 0;
case 'variables':
return compareVersions(version, '3.4.0') >= 0;
case 'mods':
return compareVersions(version, '3.0.0') >= 0;
default:
return false;
}
}
// Conditional feature usage
const outputOptions = {};
if (supportsFeature('rerun')) {
outputOptions.rerunInterval = 5;
}
alfy.output(items, outputOptions);