POMLOCK v4.0.1
░▒▓ POMLOCK_SYS_001 ▓▒░ // BOOT SEQUENCE COMPLETE
ACTIVE 00:25:00
POMLOCK

POMLOCK

LINUX EVDEV INPUT BLOCKER // ZERO-WILLPOWER REST
░▒▓ PORTAL ENTRANCE TERMINAL TROVE (SOON)
TARGET: LINUX_x86_64 ▓▒░
[01 // PROBLEM & RESOLUTION] +---+

A Linux Pomodoro timer for developers who ignore break alerts.

When your break starts, pomlock locks your keyboard and mouse through evdev and covers your screen with a countdown. You cannot dismiss a banner or keep typing.

"I built pomlock because desktop notifications never worked on me. I would dismiss the popup and type until my wrists hurt. pomlock removes the choice so you actually step away from your desk."

SYSTEM SPECIFICATION ARCHIVE: 09-10-26
INPUT BLOCKevdev hardware grab (/dev/input)
INTERFACEShell TUI (Textual, no Electron)
FAILSAFESIGINT (Ctrl+C) / power button hard reset during lock
[02 // INSTALLATION & USAGE] SYS: ARMED

Install pomlock via your preferred Python tool manager (AUR package coming soon):

$ uv tool install pomlock
COMMON CLI RUNTIME FLAGS:
pomlock -t ultradian # 90m work / 20m break
pomlock --no-block-input # disable evdev grab
pomlock -a coding # track activity goal
[03 // TERMINAL WORKSTATION & TELEMETRY]
PID: 18420 STATE: PAUSED EVDEV_GRAB: ARMED
7-Segment Countdown (WORK)
25:00
[ WORK INTERVAL: FOCUS ]
CYCLE: 1 / 4
PRESET: standard (25/5)
INPUT LOCK: ARMED
STATUS FILE: /tmp/pomlock.json
TEXTUAL INTERFACE SCREENSHOT // REAL RUNTIME SNAPSHOT HOMEPAGE & STATS GRAPH VIEW
pomlock terminal user interface demo
[1] HOME [2-5] STATS [6] SETTINGS [Q] QUIT
PYTHON • TEXTUAL • EVDEV • LINUX
[04 // ARCHITECTURAL FEATURES]

Hard breaks. No dismiss button.

HARDWARE INTERRUPT MODEL
[DEVICE LOCK] +---+

Zero-willpower breaks

When your break starts, pomlock grabs keyboard and mouse devices directly via evdev. You cannot dismiss a popup or keep typing.

MODULE_ID: 01 ARMED
[FULLSCREEN] +---+

Screen-filling countdown

An unmissable countdown overlay blocks your desktop during rest intervals so you actually step away from your monitor.

MODULE_ID: 02 ARMED
[TERMINAL TUI] +---+

Built entirely for your terminal

No Electron bloat. The timer, calendar stats, streak trackers, and configuration menus run right inside your shell.

MODULE_ID: 03 ARMED
[PRESETS] +---+

Preset & custom rhythms

Switch between standard 25/5, 90/20 ultradian cycles, 50/10 sessions, or define custom intervals like "45 10 20 3".

MODULE_ID: 04 ARMED
[BAR INTEGRATION] +---+

Status bar JSON output & script callbacks

Writes live state to /tmp/pomlock.json for Waybar/Polybar. Executes custom scripts on phase changes with JSON event data.

MODULE_ID: 05 ARMED
[ACTIVITIES & STREAKS] +---+

Activity setup & daily streaks

Categorize sessions under custom activities and track consistency with gap-respecting daily streaks across days and weeks.

MODULE_ID: 06 ARMED
[05 // KEYBOARD MATRIX]

Single-keypress terminal controls.

STDIN KEY EVENT DISPATCH
KEY MAPPINGS // IN-APP NAVIGATION ACTIVE LISTENER: TERMINAL STDIN
[ KEY ]ACTION PERFORMED
SpacePause or resume active timer
sSkip current interval
rReset current interval
zToggle zen view
gCycle activity goals
aCycle chart activity filter
1Switch to home screen
2 - 5Today, Week, Month, and Year stats
6Settings screen
qQuit application
INPUT RECOVERY: DEVICES AUTO-RELEASE ON TIMER FINISH OR APP EXIT DURING LOCKDOWN: HARD RESTART (POWER BUTTON)
[06 // CONFIGURATION & EXTENSIBILITY]

Plain text configuration, native shell hooks.

~/.config/pomlock/pomlock.conf
~/.config/pomlock/pomlock.conf INI FORMAT

Edit directly in your text editor or inside the TUI app by pressing 6.

[general]
block_input = true
notify = true
break_notify_msg = Time for a break!
long_break_notify_msg = Time for a long break!
pomo_notify_msg = Time for a pomodoro!
callback = 
timer = standard

[presets]
standard = 25 5 20 4
ultradian = 90 20 20 1
fifty_ten = 50 10 10 1

[overlay]
enabled = true
font_size = 48
color = white
bg_color = black
opacity = 0.8

[activities]
auto_calc = false
daily = 4h
weekly = 30h

[streak]
allowed_gap = 1
indicator_style = icon

[localization]
week_start_day = monday
locale = en_US
SECTIONS: [general], [presets], [overlay]
WAYBAR & POLYBAR HOOK /tmp/pomlock.json

Pomlock writes live state to /tmp/pomlock.json every second while running:

{
  "action": "pomodoro",
  "time": 1500,
  "start_time": 1725580800.0,
  "crr-cycle": 1,
  "total-cycles": 4,
  "state": "running"
}

Add this custom module to your Waybar configuration to display timer status in your bar:

"custom/pomodoro": {
  "exec": "/path/to/waybar.py",
  "interval": 1,
  "return-type": "json",
  "on-click": "/path/to/waybar.py left",
  "on-click-right": "/path/to/waybar.py right"
}
SCRIPT CALLBACK pomlock.conf

Set a callback command and pomlock runs it on every phase change, passing a JSON object as the last argument:

{
  "action": "pomodoro|short_break|long_break",
  "time": 1500,
  "start_time": 1725580800.0,
  "crr-cycle": 1,
  "total-cycles": 4,
  "crr-session": 1
}

Example callback in your pomlock.conf:

callback = uv run /home/luisca/p/scripts/pomlock_brainfm.py

Or pass a script directly at launch:

pomlock --callback /path/to/script.sh