https://x.com/didiercatz/status/2037593968800592359
#!/usr/bin/env node
// Required parameters:
// @raycast.schemaVersion 1
// @raycast.title Timer
// @raycast.mode silent
// Optional parameters:
// @raycast.icon https://cdn-icons-png.flaticon.com/512/5387/5387915.png
// @raycast.argument1 { "type": "text", "placeholder": "Time (e.g. 30s, 5m, 1h)", "optional": false }
// @raycast.argument2 { "type": "text", "placeholder": "Message", "optional": true }
// @raycast.packageName Timer
// Documentation:
// @raycast.description Show a macOS notification after a delay
// @raycast.author abstractalgo
import { execSync } from "child_process";
function parseTime(input) {
const match = input.match(
/^(\d+(?:\.\d+)?)\s*(s|sec|secs|seconds?|m|min|mins|minutes?|h|hr|hrs|hours?)$/i,
);
if (!match) {
console.error(`Invalid time format: "${input}". Use e.g. 30s, 5m, 1h`);
process.exit(1);
}
const value = parseFloat(match[1]);
const unit = match[2].toLowerCase();
if (unit.startsWith("h")) return value * 3600;
if (unit.startsWith("m")) return value * 60;
return value;
}
const seconds = parseTime(process.argv[2]);
const message = process.argv[3] || "Timer done!";
const title = "Timer";
console.log(`Notification in ${process.argv[2]}...`);
setTimeout(() => {
execSync(
`osascript -e 'display notification "${message}" with title "${title}" sound name "Glass"'`,
);
}, seconds * 1000);