Skip to main content

human-presence

Keep your computer "in use" with pointer motion that actually looks human.

macOS · Windows · Linux (X11)

Inspired by keep-presence by carrot69 — https://github.com/carrot69/keep-presence

Most keep-awake tools jump the cursor one pixel and call it a day. That is a teleport: no path, no acceleration, always the same direction. This one generates real trajectories instead.

human-presence -g 25 90
--------------------------------------------------------------
human-presence   gap 25-90s   speed x1
  display 0: 1512x982 at (0,0)
  display 1: 1920x1080 at (1512,-459)
  Ctrl-C to stop.
--------------------------------------------------------------
10:54:52  micro    20px -> (1185,452)
10:55:33  hop      79px -> (1257,518)
10:55:33  scrolled 4 notches up
10:56:41  travel  612px -> (410,244)

What makes the motion human

Property How it is modelled
Path shape Cubic Bézier with a randomised bow. ~75% single arc, ~25% lazy S. Never a straight line.
Speed Minimum-jerk profile — zero velocity at both ends, so it eases in and eases out.
Duration Fitts's law, MT = a + b·log2(D/W + 1), with per-move noise. 50 px ≈ 280 ms, 1200 px ≈ 730 ms.
Precision Per-step tremor, plus overshoot and a corrective submovement on ~35% of long reaches.
Hesitation Occasional mid-flight pause on long travels, like a person re-aiming.
Timing Log-uniform gaps, so short pauses outnumber long ones. Sometimes a burst of 2–4 quick actions.
Target choice ~45% micro-drift (2–25 px), ~35% short hop (60–350 px), ~20% long travel across the screen.
Scrolling Bursts of 2–6 notches in one direction, each weaker than the last.

Supported systems

System Status How it injects input Extra install
macOS supported Quartz event tap pyobjc (automatic)
Windows 10/11 supported SendInput none — ctypes is built in
Linux on Xorg supported XTest system X libraries
Linux on Wayland not possible

Every supported system is checked in CI on each push, and not only for "does it import". One test injects a real pointer move and asserts the operating system's own idle clock resets — the single behaviour the whole tool depends on. If that ever stops being true on a platform, the build fails.

Wayland users, read this. Ubuntu has shipped Wayland as the default desktop since 22.04, and Wayland blocks programs from injecting input. That is a security decision, not a missing feature, and no version of this tool can work around it. To use human-presence on Ubuntu: log out, click the gear icon on the login screen, choose "Ubuntu on Xorg", and log back in. Run echo $XDG_SESSION_TYPE to check — it should print x11. If you launch under Wayland the tool tells you this and exits, rather than running forever with no effect.

Install

Requires Python 3.9+.

pip install human-presence

On Ubuntu, the X libraries are usually already present. If not:

sudo apt install libx11-6 libxtst6 libxss1 libxinerama1

From a checkout:

git clone https://github.com/agn-7/human-presence.git
cd human-presence
pip install -e '.[dev]'

Permissions

macOS will not deliver synthetic pointer events until you allow it. Open System Settings → Privacy & Security → Accessibility and enable whichever app runs the command — Terminal, iTerm, or your IDE. Without permission the events are silently dropped.

Windows and Linux/Xorg need no special permission.

On any system, use --verify to check it is working: if the idle clock does not reset to 0.0s after an action, the events are not landing.

Usage

human-presence [-g MIN MAX] [--speed X] [--hours HH:MM-HH:MM] [--display N]
               [--margin PX] [--no-scroll] [--keys] [--yield-seconds S]
               [--dry-run] [--verify] [--seed N] [-q]
Flag Meaning
-g, --gap MIN MAX Seconds of real inactivity before acting. A fresh random value in this range every time. Default 25 90.
--speed X Movement speed multiplier. 0.7 is slower and calmer. Default 1.0.
--hours HH:MM-HH:MM Only run inside this daily window. Overnight wrap works: 22:00-06:00.
--display N Pin to one display. Default: whichever screen holds the cursor.
--margin PX Pixels to keep clear of every screen edge. Default 60.
--no-scroll Never scroll.
--keys Also tap shift occasionally. Off by default.
--yield-seconds S How long to stand down after you touch the mouse. Default 120.
--dry-run Print the plan, never touch the cursor.
--verify Print the system idle clock before and after each action.
--seed N Fix the RNG, for reproducible tests.
-q, --quiet Only log actions.

Choosing a gap

Keep the maximum below your screen-sleep setting (System Settings → Lock Screen).

Command Behaviour
-g 25 90 Good default.
-g 60 240 Calmer. Use when screen sleep is 5 minutes or more.
-g 10 30 Busy. Only when something needs very frequent activity.

Preview before the real run

human-presence --dry-run -g 3 6

Nothing moves. You only see what it would do.

How idle is detected

Each platform reads the same clock its own screensaver reads, so keyboard activity counts as presence, not just the mouse. The tool stays quiet while you are genuinely working, and only acts once you actually stop.

System Idle clock
macOS CGEventSourceSecondsSinceLastEventType
Windows GetLastInputInfo
Linux/Xorg XScreenSaverQueryInfo

Because that clock is also reset by the tool's own events, a gap is measured from whichever came last: you, or it.

Staying out of the way

  • You always win. Touch the mouse and it stands down for --yield-seconds. It also aborts a move mid-flight if the cursor stops tracking the path.
  • Off the furniture. Every point is clamped into a safe box, inset from all edges. On macOS that also means below the menu bar and clear of the hot corners that trigger Mission Control. On Windows and Linux the tool uses the work area the system reports, so the taskbar, dock and panel are already excluded wherever you keep them.
  • Multi-display aware on all three systems, including stacked or offset monitor layouts and screens positioned left of the origin.

Run it at login

macOS

The repository ships a ready template at packaging/com.agn7.human-presence.plist. Copy it to ~/Library/LaunchAgents/, edit the paths and flags inside, then:

launchctl load ~/Library/LaunchAgents/com.agn7.human-presence.plist
launchctl list | grep human-presence          # confirm it is running
launchctl unload ~/Library/LaunchAgents/com.agn7.human-presence.plist   # stop

Logs go to /tmp/human-presence.log and /tmp/human-presence.err.log. launchd does not expand ~, so use absolute paths if you change them.

Grant Accessibility permission to /usr/local/bin/python3 (or whichever interpreter the plist points at), not to Terminal.

Windows

Press Win+R, run shell:startup, and put a shortcut there pointing at:

pythonw -m human_presence --gap 25 90 --quiet

pythonw runs it without a console window.

Linux (Xorg)

Add it to your desktop's Startup Applications, with the command:

human-presence --gap 25 90 --quiet

Development

pip install -e '.[dev]'
pytest
ruff check .

Tests cover the movement model, the safe-area maths, the platform arithmetic (absolute-coordinate mapping, tick-counter wrap, Wayland detection) and the CLI. They all run on every operating system, because the movement model is driven through an in-memory fake pointer rather than a real cursor.

The layout:

src/human_presence/
    cli.py              movement model + CLI — no OS calls at all
    backends/
        base.py         the Pointer interface, and the fake used by tests
        darwin.py       Quartz
        win32.py        SendInput via ctypes
        x11.py          XTest via ctypes

Adding a platform means writing one file in backends/. Nothing in cli.py changes.

Credits and prior art

This project was inspired by keep-presence by carrot69, released under CC0:

https://github.com/carrot69/keep-presence

That project supplied the idea — a small program that keeps a machine looking occupied while you are away — and the shape of the command-line interface. Thanks to its author.

human-presence is an independent implementation rather than a fork. No code was copied. The differences:

keep-presence human-presence
Movement one-pixel teleport, 4 fixed directions Bézier path, minimum-jerk speed, Fitts timing
Idle detection compares cursor position between loops system idle clock, so typing counts too
Randomness the wait interval only wait, distance, direction, duration, curvature
Platform library pynput direct system calls, no pynput
Platforms macOS, Windows, Linux macOS, Windows, Linux/Xorg

License

MIT. The full text is in the LICENSE file of the source distribution.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

human_presence-0.2.0.tar.gz (29.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

human_presence-0.2.0-py3-none-any.whl (25.5 kB view details)

Uploaded Python 3

File details

Details for the file human_presence-0.2.0.tar.gz.

File metadata

  • Download URL: human_presence-0.2.0.tar.gz
  • Upload date:
  • Size: 29.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for human_presence-0.2.0.tar.gz
Algorithm Hash digest
SHA256 dcb4d281fe909b678304473a1df36b0928827e360c9ccd647e3343ec8a681f9e
MD5 7512de18e33f34b41390d52a1db443bf
BLAKE2b-256 b3352f070485bad08916430395552f09cde1c2aa174c5d0886f39a17b81cd795

See more details on using hashes here.

Provenance

The following attestation bundles were made for human_presence-0.2.0.tar.gz:

Publisher: publish.yml on agn-7/human-presence

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file human_presence-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: human_presence-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 25.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for human_presence-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8d3c94f86e29b58d7c5cbbee60dd632cdafc2dc9a0c6a78e289a90e7bf0036ec
MD5 9eb4b038b2e106266f2293f3815cb298
BLAKE2b-256 99d68d7b730394070572d397d2995941ce626b5f4527719e48fa924da221007a

See more details on using hashes here.

Provenance

The following attestation bundles were made for human_presence-0.2.0-py3-none-any.whl:

Publisher: publish.yml on agn-7/human-presence

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page