Skip to content

Instantly share code, notes, and snippets.

@windoze95
Last active December 23, 2025 19:55
Show Gist options
  • Select an option

  • Save windoze95/18d4e792619217dd6dfd166a2f2bbdad to your computer and use it in GitHub Desktop.

Select an option

Save windoze95/18d4e792619217dd6dfd166a2f2bbdad to your computer and use it in GitHub Desktop.
A no sleep script for macOS that moves the cursor in the shape of a heart every two minutes.
/*
--------------------------------------------------------------------
No Sleep (macOS) v1.1 - 2025
- Warps the cursor in the shape of a heart every 120s of idle time.
- Pauses after a set time of true user absence to allow sleep.
- Default pause time is 2 hours, override with an argument:
osascript -l JavaScript till_brooklyn.js 1.5
- Uses only built-in macOS tools: ioreg + CoreGraphics (no installs).
--------------------------------------------------------------------
*/
ObjC.import("Foundation");
ObjC.import("CoreGraphics");
ObjC.import("stdlib");
// --- CONFIG ---
const jiggleThresholdMs = 118000; // 118s: idle time before drawing heart
const heartPoints = 60;
const traceSeconds = 2.0; // total time to trace heart
const stepDelaySeconds = traceSeconds / heartPoints;
// --- Helpers ---
function sh(cmd) {
const task = $.NSTask.alloc.init;
task.setLaunchPath("/bin/sh");
task.setArguments(["-lc", cmd]);
const pipe = $.NSPipe.pipe;
task.setStandardOutput(pipe);
task.setStandardError(pipe);
task.launch;
task.waitUntilExit;
const data = pipe.fileHandleForReading.readDataToEndOfFile;
const str = $.NSString.alloc.initWithDataEncoding(data, $.NSUTF8StringEncoding);
if (!str) return "";
return ObjC.unwrap(str).trim();
}
function getIdleSeconds() {
// HIDIdleTime is nanoseconds. Newer macOS often needs `ioreg -l` to show it. :contentReference[oaicite:2]{index=2}
const out = sh("/usr/sbin/ioreg -l -c IOHIDSystem | /usr/bin/perl -ne 'if(/HIDIdleTime[^0-9]*([0-9]+)/){print $1; exit}'");
if (!out) return NaN;
// Use BigInt for safety; convert to seconds.
let ns;
try { ns = BigInt(out); } catch (e) { return NaN; }
const s = Number(ns) / 1e9; // safe for “hours” ranges
return s;
}
function sleepSeconds(s) {
$.NSThread.sleepForTimeInterval(s);
}
function fastIdleSeconds() {
// CoreGraphics event source is fast enough to call per point.
return $.CGEventSourceSecondsSinceLastEventType(
$.kCGEventSourceStateCombinedSessionState,
$.kCGAnyInputEventType
);
}
function currentMouseLocation() {
const evt = $.CGEventCreate(null);
const loc = $.CGEventGetLocation(evt); // CoreGraphics global display coords
return { x: loc.x, y: loc.y };
}
function warpMouse(x, y) {
// Warps cursor without generating/posting events. :contentReference[oaicite:3]{index=3}
$.CGWarpMouseCursorPosition($.CGPointMake(x, y));
}
function postMouseMoved(x, y) {
// Generates a real mouse-move event to reset idle timer. :contentReference[oaicite:4]{index=4}
const pos = $.CGPointMake(x, y);
const ev = $.CGEventCreateMouseEvent(null, $.kCGEventMouseMoved, pos, $.kCGMouseButtonLeft);
$.CGEventPost($.kCGHIDEventTap, ev);
}
// --- Heart path precompute ---
function buildHeart() {
const pts = [];
for (let i = 0; i < heartPoints; i++) {
const t = 2 * Math.PI * i / heartPoints;
const x = 16 * Math.pow(Math.sin(t), 3);
const y = 13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t);
// Match your Windows behavior: scale + invert Y so the heart is upright in a "Y down" space.
pts.push({ dx: Math.round(x * 4), dy: Math.round(-y * 4) });
}
return pts;
}
// --- Entry point ---
function run(argv) {
const heart = buildHeart();
// Pause threshold (hours)
let pauseThresholdHours = 2.0;
if (argv && argv.length > 0) {
const v = parseFloat(argv[0]);
if (Number.isFinite(v) && v > 0) {
pauseThresholdHours = v;
console.log(`Override detected. Setting pause time to ${pauseThresholdHours} hours.`);
} else {
console.log(`Invalid input '${argv[0]}'. Using default pause time.`);
}
}
let pauseThresholdSecs = Math.floor(pauseThresholdHours * 3600);
const jiggleThresholdSecs = jiggleThresholdMs / 1000;
// Sanity: pause threshold must exceed jiggle threshold
if (pauseThresholdSecs <= jiggleThresholdSecs) {
console.log(`Pause time (${pauseThresholdSecs}s) can't be <= jiggle time (${jiggleThresholdSecs}s). Auto-adjusting.`);
pauseThresholdSecs = Math.floor(jiggleThresholdSecs + 2);
pauseThresholdHours = Math.round((pauseThresholdSecs / 3600) * 10000) / 10000;
console.log(`Adjusted pause time: ${pauseThresholdSecs}s (~${pauseThresholdHours}h).`);
}
console.log(`Script started. Jiggle threshold: ${jiggleThresholdSecs}s. Pause threshold: ${pauseThresholdHours}h (${pauseThresholdSecs}s).`);
// Nudge the cursor immediately to trigger permissions on first run.
const startPos = currentMouseLocation();
postMouseMoved(startPos.x + 1, startPos.y);
warpMouse(startPos.x, startPos.y);
// State
let triggered = false;
let ignoreNextUpdate = false;
let lastPhysicalActivity = Date.now();
while (true) {
const idleSecs = getIdleSeconds();
if (!Number.isFinite(idleSecs)) {
console.log("Could not read idle time (HIDIdleTime). Exiting.");
$.exit(1);
}
// If idle is very low, user is physically active — unless it was our own injected event.
if (idleSecs < 1.0) {
if (!ignoreNextUpdate) {
lastPhysicalActivity = Date.now();
}
ignoreNextUpdate = false;
}
const trueIdleSecs = (Date.now() - lastPhysicalActivity) / 1000;
// PAUSE after true-idle exceeds threshold (lets Mac sleep naturally)
if (trueIdleSecs >= pauseThresholdSecs) {
const now = new Date();
console.log(`${now.toLocaleTimeString()} - True-idle of ${Math.round(trueIdleSecs)}s exceeded pause threshold. Pausing...`);
sleepSeconds(15);
continue;
}
// JIGGLE by tracing heart if system idle exceeds jiggle threshold
if (!triggered && idleSecs * 1000 >= jiggleThresholdMs) {
const origin = currentMouseLocation();
let aborted = false;
const startMs = Date.now();
const now = new Date();
console.log(`${now.toLocaleTimeString()} - Jiggle threshold reached (${Math.round(idleSecs * 1000)}ms). Drawing heart...`);
for (let i = 0; i < heart.length; i++) {
const pt = heart[i];
warpMouse(origin.x + pt.dx, origin.y + pt.dy);
const targetMs = startMs + ((i + 1) * stepDelaySeconds * 1000);
const remainingMs = targetMs - Date.now();
if (remainingMs > 0) sleepSeconds(remainingMs / 1000.0);
// Because warps do not generate events, idle will only reset if the user actually moves/presses something.
const checkIdle = fastIdleSeconds();
if (Number.isFinite(checkIdle) && checkIdle < 1.0) {
console.log(`${new Date().toLocaleTimeString()} - User activity detected. Aborting draw.`);
aborted = true;
break;
}
}
if (!aborted) {
warpMouse(origin.x, origin.y);
// One real event to reset idle timer / prevent sleep
postMouseMoved(origin.x, origin.y);
ignoreNextUpdate = true;
triggered = true;
}
}
// Reset heart trigger once user returns to an active state (or after our injected reset)
if (triggered && idleSecs < jiggleThresholdSecs) triggered = false;
// Sleep intelligently until the next check
const msToGo = jiggleThresholdMs - (idleSecs * 1000) - 500;
const sleepMs = (msToGo > 500) ? msToGo : 500;
sleepSeconds(sleepMs / 1000.0);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment