desk-awake 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,107 @@
1
+ Metadata-Version: 2.4
2
+ Name: desk-awake
3
+ Version: 1.0.0
4
+ Summary: Cross-platform idle activity simulator with AnyDesk integration
5
+ Author: Abhinav Hudda
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: pynput>=1.7.0
10
+ Provides-Extra: mac
11
+ Requires-Dist: pyobjc-core>=9.0; extra == "mac"
12
+ Requires-Dist: pyobjc-framework-ApplicationServices>=9.0; extra == "mac"
13
+ Requires-Dist: pyobjc-framework-Cocoa>=9.0; extra == "mac"
14
+ Requires-Dist: pyobjc-framework-Quartz>=9.0; extra == "mac"
15
+
16
+ # Desk Awake
17
+
18
+ Cross-platform idle activity simulator. Keeps your session active by generating mouse movements and keyboard actions until a specified time.
19
+
20
+ Auto-detects the OS and uses appropriate modifier keys (`Cmd` on macOS, `Ctrl` on Linux/Windows) and system commands.
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ pip install desk-awake
26
+
27
+ # On macOS, include the optional mac dependencies
28
+ pip install "desk-awake[mac]"
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ Once installed, the `desk-awake` command is available globally:
34
+
35
+ ```bash
36
+ # Run until a specific time (24h format)
37
+ desk-awake --until "18:30"
38
+
39
+ # Run until a specific date and time
40
+ desk-awake --until "2025-01-15 17:00"
41
+
42
+ # Short flag works too
43
+ desk-awake -u "18:30"
44
+ ```
45
+
46
+ ### Multi-day mode
47
+
48
+ Run daily on a schedule until a specific end date:
49
+
50
+ ```bash
51
+ # Run every day from 09:00 to 18:30, until June 15th
52
+ desk-awake -u "18:30" --start "09:00" --end-date "2026-06-15"
53
+ ```
54
+
55
+ ### Exit behavior flags
56
+
57
+ | Flag | Description |
58
+ |------|-------------|
59
+ | `--close-anydesk` | Close AnyDesk when done (default) |
60
+ | `--no-close-anydesk` | Don't close AnyDesk when done |
61
+ | `--sleep` | Put machine to sleep when done |
62
+ | `--no-sleep` | Don't sleep when done |
63
+
64
+ ### OS-specific defaults
65
+
66
+ | OS | Close AnyDesk | Sleep |
67
+ |----|---------------|-------|
68
+ | macOS | ✅ | ✅ |
69
+ | Linux | ✅ | ❌ |
70
+ | Windows | ✅ | ✅ |
71
+
72
+ Override any default with the flags above.
73
+
74
+ ### Examples
75
+
76
+ ```bash
77
+ # Ubuntu: run until 6:30 PM, close AnyDesk, no sleep (default)
78
+ desk-awake -u "18:30"
79
+
80
+ # macOS: run until 6:30 PM, close AnyDesk, sleep (default)
81
+ desk-awake -u "18:30"
82
+
83
+ # macOS: skip sleep
84
+ desk-awake -u "18:30" --no-sleep
85
+
86
+ # Linux: force sleep too
87
+ desk-awake -u "18:30" --sleep
88
+
89
+ # Multi-day: run 09:00–18:30 daily until a date
90
+ desk-awake -u "18:30" -s "09:00" -e "2026-06-15"
91
+
92
+ # Keep everything running, don't close anything
93
+ desk-awake -u "18:30" --no-close-anydesk --no-sleep
94
+ ```
95
+
96
+ ## Running without installing
97
+
98
+ ```bash
99
+ python -m desk_awake --until "18:30"
100
+ ```
101
+
102
+ ## Requirements
103
+
104
+ - Python 3.8+
105
+ - `pynput` (installed automatically)
106
+ - On macOS: `pyobjc` packages (install with `pip install "desk-awake[mac]"`)
107
+ - On Linux: may need `xdotool` or X11 libs depending on your display server
@@ -0,0 +1,92 @@
1
+ # Desk Awake
2
+
3
+ Cross-platform idle activity simulator. Keeps your session active by generating mouse movements and keyboard actions until a specified time.
4
+
5
+ Auto-detects the OS and uses appropriate modifier keys (`Cmd` on macOS, `Ctrl` on Linux/Windows) and system commands.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ pip install desk-awake
11
+
12
+ # On macOS, include the optional mac dependencies
13
+ pip install "desk-awake[mac]"
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ Once installed, the `desk-awake` command is available globally:
19
+
20
+ ```bash
21
+ # Run until a specific time (24h format)
22
+ desk-awake --until "18:30"
23
+
24
+ # Run until a specific date and time
25
+ desk-awake --until "2025-01-15 17:00"
26
+
27
+ # Short flag works too
28
+ desk-awake -u "18:30"
29
+ ```
30
+
31
+ ### Multi-day mode
32
+
33
+ Run daily on a schedule until a specific end date:
34
+
35
+ ```bash
36
+ # Run every day from 09:00 to 18:30, until June 15th
37
+ desk-awake -u "18:30" --start "09:00" --end-date "2026-06-15"
38
+ ```
39
+
40
+ ### Exit behavior flags
41
+
42
+ | Flag | Description |
43
+ |------|-------------|
44
+ | `--close-anydesk` | Close AnyDesk when done (default) |
45
+ | `--no-close-anydesk` | Don't close AnyDesk when done |
46
+ | `--sleep` | Put machine to sleep when done |
47
+ | `--no-sleep` | Don't sleep when done |
48
+
49
+ ### OS-specific defaults
50
+
51
+ | OS | Close AnyDesk | Sleep |
52
+ |----|---------------|-------|
53
+ | macOS | ✅ | ✅ |
54
+ | Linux | ✅ | ❌ |
55
+ | Windows | ✅ | ✅ |
56
+
57
+ Override any default with the flags above.
58
+
59
+ ### Examples
60
+
61
+ ```bash
62
+ # Ubuntu: run until 6:30 PM, close AnyDesk, no sleep (default)
63
+ desk-awake -u "18:30"
64
+
65
+ # macOS: run until 6:30 PM, close AnyDesk, sleep (default)
66
+ desk-awake -u "18:30"
67
+
68
+ # macOS: skip sleep
69
+ desk-awake -u "18:30" --no-sleep
70
+
71
+ # Linux: force sleep too
72
+ desk-awake -u "18:30" --sleep
73
+
74
+ # Multi-day: run 09:00–18:30 daily until a date
75
+ desk-awake -u "18:30" -s "09:00" -e "2026-06-15"
76
+
77
+ # Keep everything running, don't close anything
78
+ desk-awake -u "18:30" --no-close-anydesk --no-sleep
79
+ ```
80
+
81
+ ## Running without installing
82
+
83
+ ```bash
84
+ python -m desk_awake --until "18:30"
85
+ ```
86
+
87
+ ## Requirements
88
+
89
+ - Python 3.8+
90
+ - `pynput` (installed automatically)
91
+ - On macOS: `pyobjc` packages (install with `pip install "desk-awake[mac]"`)
92
+ - On Linux: may need `xdotool` or X11 libs depending on your display server
@@ -0,0 +1,32 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "desk-awake"
7
+ version = "1.0.0"
8
+ description = "Cross-platform idle activity simulator with AnyDesk integration"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = "MIT"
12
+ authors = [
13
+ {name = "Abhinav Hudda"}
14
+ ]
15
+
16
+ dependencies = [
17
+ "pynput>=1.7.0",
18
+ ]
19
+
20
+ [project.optional-dependencies]
21
+ mac = [
22
+ "pyobjc-core>=9.0",
23
+ "pyobjc-framework-ApplicationServices>=9.0",
24
+ "pyobjc-framework-Cocoa>=9.0",
25
+ "pyobjc-framework-Quartz>=9.0",
26
+ ]
27
+
28
+ [project.scripts]
29
+ desk-awake = "desk_awake.cli:main"
30
+
31
+ [tool.setuptools.packages.find]
32
+ where = ["src"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ """Desk Awake - Cross-platform idle activity simulator."""
2
+
3
+ __version__ = "1.0.0"
@@ -0,0 +1,5 @@
1
+ """Allow running the package directly with: python -m desk_awake"""
2
+
3
+ from .cli import main
4
+
5
+ raise SystemExit(main())
@@ -0,0 +1,80 @@
1
+ import argparse
2
+ from datetime import datetime
3
+
4
+ from .core import CURRENT_OS, parse_datetime, parse_date, perform_actions
5
+
6
+
7
+ def main():
8
+ """CLI entry point for desk-awake."""
9
+ parser = argparse.ArgumentParser(
10
+ prog='desk-awake',
11
+ description='Simulate idle activity until a specified time. '
12
+ 'Auto-detects OS and uses appropriate keys/commands.',
13
+ epilog='Defaults: On macOS — closes AnyDesk and sleeps. '
14
+ 'On Linux — closes AnyDesk only (no sleep). '
15
+ 'Use flags to override.'
16
+ )
17
+ parser.add_argument('--until', '-u', type=str, required=True,
18
+ help='Daily stop time in format "YYYY-MM-DD HH:MM" or "HH:MM" (24h format)')
19
+ parser.add_argument('--end-date', '-e', type=str, default=None,
20
+ help='Run daily until this date (format: YYYY-MM-DD). '
21
+ 'Script repeats each day from --start to --until time.')
22
+ parser.add_argument('--start', '-s', type=str, default=None,
23
+ help='Daily start time in "HH:MM" format (used with --end-date). '
24
+ 'Defaults to now if not specified.')
25
+ parser.add_argument('--close-anydesk', action='store_true', dest='close_anydesk', default=None,
26
+ help='Close AnyDesk when done')
27
+ parser.add_argument('--no-close-anydesk', action='store_false', dest='close_anydesk',
28
+ help='Do NOT close AnyDesk when done')
29
+ parser.add_argument('--sleep', action='store_true', dest='sleep', default=None,
30
+ help='Put machine to sleep when done')
31
+ parser.add_argument('--no-sleep', action='store_false', dest='sleep',
32
+ help='Do NOT put machine to sleep when done')
33
+
34
+ args = parser.parse_args()
35
+
36
+ # Apply OS-specific defaults when user hasn't explicitly set a flag
37
+ if args.close_anydesk is None:
38
+ close_anydesk_on_exit = True # Default: always close AnyDesk
39
+ else:
40
+ close_anydesk_on_exit = args.close_anydesk
41
+
42
+ if args.sleep is None:
43
+ # macOS/Windows: sleep by default. Linux: don't sleep by default.
44
+ sleep_on_exit = CURRENT_OS != "linux"
45
+ else:
46
+ sleep_on_exit = args.sleep
47
+
48
+ # Parse end date if provided
49
+ end_date = None
50
+ if args.end_date:
51
+ try:
52
+ end_date = parse_date(args.end_date)
53
+ except ValueError as e:
54
+ print(f"Error: {e}")
55
+ return 1
56
+
57
+ from datetime import date as date_cls
58
+ if end_date < date_cls.today():
59
+ print("Error: --end-date must be today or in the future!")
60
+ return 1
61
+
62
+ try:
63
+ stop_time = parse_datetime(args.until)
64
+
65
+ # For single-run mode (no end-date), stop_time must be in the future
66
+ if not end_date and stop_time <= datetime.now():
67
+ print("Error: Stop time must be in the future!")
68
+ return 1
69
+
70
+ print(f"Starting activity simulation: ~50 keys/min, ~60 mouse movements/min")
71
+ perform_actions(stop_time, close_anydesk_on_exit, sleep_on_exit,
72
+ end_date=end_date, start_time_str=args.start)
73
+ return 0
74
+ except ValueError as e:
75
+ print(f"Error: {e}")
76
+ return 1
77
+
78
+
79
+ if __name__ == "__main__":
80
+ raise SystemExit(main())
@@ -0,0 +1,203 @@
1
+ import time
2
+ import subprocess
3
+ import random
4
+ import platform
5
+ from datetime import datetime, timedelta, date
6
+ from pynput.mouse import Controller as MouseController
7
+ from pynput.keyboard import Controller as KeyboardController, Key
8
+
9
+ # Initialize pynput controllers
10
+ mouse = MouseController()
11
+ keyboard = KeyboardController()
12
+
13
+ # Detect OS
14
+ CURRENT_OS = platform.system().lower() # 'darwin' for macOS, 'linux' for Ubuntu/Linux, 'windows' for Windows
15
+
16
+
17
+ def get_modifier_key():
18
+ """Return the appropriate modifier key for the current OS."""
19
+ if CURRENT_OS == "darwin":
20
+ return Key.cmd
21
+ else:
22
+ return Key.ctrl
23
+
24
+
25
+ def close_anydesk():
26
+ """Close AnyDesk based on the current OS."""
27
+ try:
28
+ if CURRENT_OS == "darwin":
29
+ subprocess.run(['osascript', '-e', 'tell application "AnyDesk" to quit'], check=False)
30
+ subprocess.run(['pkill', '-f', 'AnyDesk'], check=False)
31
+ elif CURRENT_OS == "linux":
32
+ subprocess.run(['pkill', '-f', 'anydesk'], check=False)
33
+ elif CURRENT_OS == "windows":
34
+ subprocess.run(['taskkill', '/F', '/IM', 'AnyDesk.exe'], check=False)
35
+ print("AnyDesk closed.")
36
+ except Exception as e:
37
+ print(f"Error closing AnyDesk: {e}")
38
+
39
+
40
+ def put_to_sleep():
41
+ """Put the machine to sleep based on the current OS."""
42
+ try:
43
+ if CURRENT_OS == "darwin":
44
+ subprocess.run(['osascript', '-e', 'tell application "System Events" to sleep'], check=False)
45
+ print("Mac is going to sleep...")
46
+ elif CURRENT_OS == "linux":
47
+ subprocess.run(['systemctl', 'suspend'], check=False)
48
+ print("Linux is going to sleep...")
49
+ elif CURRENT_OS == "windows":
50
+ subprocess.run(['rundll32.exe', 'powrprof.dll,SetSuspendState', '0,1,0'], check=False)
51
+ print("Windows is going to sleep...")
52
+ except Exception as e:
53
+ print(f"Error putting machine to sleep: {e}")
54
+
55
+
56
+ def parse_datetime(datetime_str):
57
+ """Parse datetime string in format YYYY-MM-DD HH:MM or HH:MM."""
58
+ try:
59
+ return datetime.strptime(datetime_str, '%Y-%m-%d %H:%M')
60
+ except ValueError:
61
+ try:
62
+ return datetime.strptime(datetime_str, '%H:%M').replace(
63
+ year=datetime.now().year,
64
+ month=datetime.now().month,
65
+ day=datetime.now().day
66
+ )
67
+ except ValueError:
68
+ raise ValueError("Invalid datetime format. Use 'YYYY-MM-DD HH:MM' or 'HH:MM'")
69
+
70
+
71
+ def parse_date(date_str):
72
+ """Parse date string in format YYYY-MM-DD."""
73
+ try:
74
+ return datetime.strptime(date_str, '%Y-%m-%d').date()
75
+ except ValueError:
76
+ raise ValueError("Invalid date format. Use 'YYYY-MM-DD'")
77
+
78
+
79
+ def random_mouse_movement():
80
+ """Move the mouse by a small random offset."""
81
+ dx = random.randint(-30, 30)
82
+ dy = random.randint(-30, 30)
83
+ mouse.move(dx, dy)
84
+
85
+
86
+ def random_keyboard_action():
87
+ """Press a random navigation key."""
88
+ actions = [Key.page_up, Key.page_down, Key.up, Key.down, Key.left, Key.right]
89
+ if random.random() < 0.8:
90
+ key = random.choice(actions)
91
+ keyboard.press(key)
92
+ time.sleep(random.uniform(0.02, 0.08))
93
+ keyboard.release(key)
94
+
95
+
96
+ def _run_activity_loop(stop_time):
97
+ """Core activity loop — runs until stop_time."""
98
+ actions_per_second = (50 + 60) / 60 # ~1.83 actions per second
99
+
100
+ while datetime.now() < stop_time:
101
+ start_time = time.time()
102
+
103
+ # Perform a burst of actions
104
+ actions_this_cycle = random.randint(3, 8)
105
+
106
+ for _ in range(actions_this_cycle):
107
+ if random.random() < 0.55: # Slightly favor mouse movements
108
+ random_mouse_movement()
109
+ else:
110
+ random_keyboard_action()
111
+
112
+ time.sleep(random.uniform(0.02, 0.1))
113
+
114
+ # Maintain target rate
115
+ elapsed = time.time() - start_time
116
+ target_time = actions_this_cycle / actions_per_second
117
+
118
+ if elapsed < target_time:
119
+ time.sleep(target_time - elapsed)
120
+
121
+ # Occasionally add a brief pause (10% chance)
122
+ if random.random() < 0.1:
123
+ idle_time = random.uniform(0.5, 2.0)
124
+ print(f"Brief pause for {idle_time:.2f} seconds...")
125
+ time.sleep(idle_time)
126
+
127
+
128
+ def perform_actions(stop_time, close_anydesk_on_exit, sleep_on_exit, end_date=None, start_time_str=None):
129
+ """
130
+ Run simulated activity until stop_time, then optionally close AnyDesk and sleep.
131
+
132
+ If end_date is provided, the script runs daily:
133
+ - Each day it runs from start_time_str (or now) until the --until time.
134
+ - After each day's session, it sleeps until the next day's start time.
135
+ - On the final day (end_date), it runs the last session and then exits.
136
+ """
137
+ print(f"Detected OS: {CURRENT_OS}")
138
+ print(f"Modifier key: {'Cmd' if CURRENT_OS == 'darwin' else 'Ctrl'}")
139
+ print(f"On exit: close AnyDesk={'yes' if close_anydesk_on_exit else 'no'}, "
140
+ f"sleep={'yes' if sleep_on_exit else 'no'}")
141
+
142
+ if end_date:
143
+ daily_stop_hour = stop_time.hour
144
+ daily_stop_minute = stop_time.minute
145
+ daily_start_hour = int(start_time_str.split(':')[0]) if start_time_str else datetime.now().hour
146
+ daily_start_minute = int(start_time_str.split(':')[1]) if start_time_str else datetime.now().minute
147
+
148
+ print(f"Multi-day mode: running daily {daily_start_hour:02d}:{daily_start_minute:02d} → "
149
+ f"{daily_stop_hour:02d}:{daily_stop_minute:02d} until {end_date}")
150
+ print("-" * 50)
151
+
152
+ current_date = date.today()
153
+
154
+ while current_date <= end_date:
155
+ today_start = datetime(current_date.year, current_date.month, current_date.day,
156
+ daily_start_hour, daily_start_minute)
157
+ today_stop = datetime(current_date.year, current_date.month, current_date.day,
158
+ daily_stop_hour, daily_stop_minute)
159
+
160
+ now = datetime.now()
161
+
162
+ # If we haven't reached start time yet today, wait
163
+ if now < today_start:
164
+ wait_seconds = (today_start - now).total_seconds()
165
+ print(f"[{current_date}] Waiting {wait_seconds/60:.0f} min until start time "
166
+ f"{daily_start_hour:02d}:{daily_start_minute:02d}...")
167
+ time.sleep(wait_seconds)
168
+
169
+ # If we've already passed today's stop time, skip to next day
170
+ if datetime.now() >= today_stop:
171
+ print(f"[{current_date}] Already past stop time, skipping to next day.")
172
+ current_date += timedelta(days=1)
173
+ continue
174
+
175
+ print(f"[{current_date}] Running until {today_stop.strftime('%H:%M')}...")
176
+ _run_activity_loop(today_stop)
177
+ print(f"[{current_date}] Day session complete.")
178
+
179
+ current_date += timedelta(days=1)
180
+
181
+ # If there are more days, sleep overnight (idle wait)
182
+ if current_date <= end_date:
183
+ next_start = datetime(current_date.year, current_date.month, current_date.day,
184
+ daily_start_hour, daily_start_minute)
185
+ wait_seconds = (next_start - datetime.now()).total_seconds()
186
+ if wait_seconds > 0:
187
+ print(f"Sleeping until next session: {next_start.strftime('%Y-%m-%d %H:%M')} "
188
+ f"({wait_seconds/3600:.1f} hours)")
189
+ time.sleep(wait_seconds)
190
+
191
+ print("End date reached. All sessions complete.")
192
+ else:
193
+ # Single-run mode (original behavior)
194
+ print(f"Running until {stop_time.strftime('%Y-%m-%d %H:%M')}...")
195
+ print("-" * 50)
196
+ _run_activity_loop(stop_time)
197
+ print("Stop time reached. Exiting script.")
198
+
199
+ if close_anydesk_on_exit:
200
+ close_anydesk()
201
+
202
+ if sleep_on_exit:
203
+ put_to_sleep()
@@ -0,0 +1,107 @@
1
+ Metadata-Version: 2.4
2
+ Name: desk-awake
3
+ Version: 1.0.0
4
+ Summary: Cross-platform idle activity simulator with AnyDesk integration
5
+ Author: Abhinav Hudda
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.8
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: pynput>=1.7.0
10
+ Provides-Extra: mac
11
+ Requires-Dist: pyobjc-core>=9.0; extra == "mac"
12
+ Requires-Dist: pyobjc-framework-ApplicationServices>=9.0; extra == "mac"
13
+ Requires-Dist: pyobjc-framework-Cocoa>=9.0; extra == "mac"
14
+ Requires-Dist: pyobjc-framework-Quartz>=9.0; extra == "mac"
15
+
16
+ # Desk Awake
17
+
18
+ Cross-platform idle activity simulator. Keeps your session active by generating mouse movements and keyboard actions until a specified time.
19
+
20
+ Auto-detects the OS and uses appropriate modifier keys (`Cmd` on macOS, `Ctrl` on Linux/Windows) and system commands.
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ pip install desk-awake
26
+
27
+ # On macOS, include the optional mac dependencies
28
+ pip install "desk-awake[mac]"
29
+ ```
30
+
31
+ ## Usage
32
+
33
+ Once installed, the `desk-awake` command is available globally:
34
+
35
+ ```bash
36
+ # Run until a specific time (24h format)
37
+ desk-awake --until "18:30"
38
+
39
+ # Run until a specific date and time
40
+ desk-awake --until "2025-01-15 17:00"
41
+
42
+ # Short flag works too
43
+ desk-awake -u "18:30"
44
+ ```
45
+
46
+ ### Multi-day mode
47
+
48
+ Run daily on a schedule until a specific end date:
49
+
50
+ ```bash
51
+ # Run every day from 09:00 to 18:30, until June 15th
52
+ desk-awake -u "18:30" --start "09:00" --end-date "2026-06-15"
53
+ ```
54
+
55
+ ### Exit behavior flags
56
+
57
+ | Flag | Description |
58
+ |------|-------------|
59
+ | `--close-anydesk` | Close AnyDesk when done (default) |
60
+ | `--no-close-anydesk` | Don't close AnyDesk when done |
61
+ | `--sleep` | Put machine to sleep when done |
62
+ | `--no-sleep` | Don't sleep when done |
63
+
64
+ ### OS-specific defaults
65
+
66
+ | OS | Close AnyDesk | Sleep |
67
+ |----|---------------|-------|
68
+ | macOS | ✅ | ✅ |
69
+ | Linux | ✅ | ❌ |
70
+ | Windows | ✅ | ✅ |
71
+
72
+ Override any default with the flags above.
73
+
74
+ ### Examples
75
+
76
+ ```bash
77
+ # Ubuntu: run until 6:30 PM, close AnyDesk, no sleep (default)
78
+ desk-awake -u "18:30"
79
+
80
+ # macOS: run until 6:30 PM, close AnyDesk, sleep (default)
81
+ desk-awake -u "18:30"
82
+
83
+ # macOS: skip sleep
84
+ desk-awake -u "18:30" --no-sleep
85
+
86
+ # Linux: force sleep too
87
+ desk-awake -u "18:30" --sleep
88
+
89
+ # Multi-day: run 09:00–18:30 daily until a date
90
+ desk-awake -u "18:30" -s "09:00" -e "2026-06-15"
91
+
92
+ # Keep everything running, don't close anything
93
+ desk-awake -u "18:30" --no-close-anydesk --no-sleep
94
+ ```
95
+
96
+ ## Running without installing
97
+
98
+ ```bash
99
+ python -m desk_awake --until "18:30"
100
+ ```
101
+
102
+ ## Requirements
103
+
104
+ - Python 3.8+
105
+ - `pynput` (installed automatically)
106
+ - On macOS: `pyobjc` packages (install with `pip install "desk-awake[mac]"`)
107
+ - On Linux: may need `xdotool` or X11 libs depending on your display server
@@ -0,0 +1,12 @@
1
+ README.md
2
+ pyproject.toml
3
+ src/desk_awake/__init__.py
4
+ src/desk_awake/__main__.py
5
+ src/desk_awake/cli.py
6
+ src/desk_awake/core.py
7
+ src/desk_awake.egg-info/PKG-INFO
8
+ src/desk_awake.egg-info/SOURCES.txt
9
+ src/desk_awake.egg-info/dependency_links.txt
10
+ src/desk_awake.egg-info/entry_points.txt
11
+ src/desk_awake.egg-info/requires.txt
12
+ src/desk_awake.egg-info/top_level.txt
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ desk-awake = desk_awake.cli:main
@@ -0,0 +1,7 @@
1
+ pynput>=1.7.0
2
+
3
+ [mac]
4
+ pyobjc-core>=9.0
5
+ pyobjc-framework-ApplicationServices>=9.0
6
+ pyobjc-framework-Cocoa>=9.0
7
+ pyobjc-framework-Quartz>=9.0
@@ -0,0 +1 @@
1
+ desk_awake