Cross-platform activity simulator that keeps your computer looking busy.
Realistic mouse movements β’ Keyboard activity β’ Scrolling β’ App switching β’ Browser tabs
Stealth mode β’ System tray β’ TUI dashboard β’ Global hotkeys β’ Fully configurable
- How it Works
- Features
- Installation
- Usage
- Platform Setup
- Configuration
- Architecture
- Building
- Testing
- Contributing
- License
graph LR
A[Phantom App] --> B[Scheduler]
B --> C{Weighted Random<br/>Selection}
C --> D[π±οΈ Mouse]
C --> E[β¨οΈ Keyboard]
C --> F[π Scroll]
C --> G[π App Switcher]
C --> H[π Browser Tabs]
D --> I[Bezier Curve<br/>Movement]
E --> J[Modifier Keys<br/>Only]
B --> K[Anti-Detection]
K -->|blocks repeats| C
B --> L[Gaussian Timing<br/>+ Random Idle]
Phantom's scheduler runs in a daemon thread, picking a random simulator on each cycle. The selection is weighted β higher weight means chosen more often. Timing follows a normal distribution with configurable mean/stddev, plus random idle periods that mimic natural breaks. An anti-detection system prevents repetitive patterns (e.g., same action 4+ times in a row, or alternating A-B-A-B sequences).
mindmap
root((Phantom))
Simulators
Mouse β Bezier curves + micro-corrections
Keyboard β modifier keys only, no visible output
Scroll β vertical + horizontal
App Switcher β Cmd+Tab / Alt+Tab
Browser Tabs β context-aware shortcuts
Stealth
Process name masking
Tray icon hiding
Anti-detection timing
Pattern variation
Cross-Platform
macOS
Windows
Linux X11
Interface
System tray icon
TUI dashboard
Rich colored logging
Global hotkeys
CLI flags
JSON config
| Simulator | What it does | Default Weight |
|---|---|---|
| Mouse | Moves cursor along randomized cubic Bezier curves with 30% chance of micro-correction jitter at the end | 40 |
| Keyboard | Presses modifier keys (Shift, Ctrl, Alt) + CapsLock double-tap β produces no visible output | 30 |
| Scroll | Vertical scrolling (90%) or horizontal scrolling (10%), random direction and amount | 15 |
| App Switcher | Simulates Cmd+Tab (macOS) or Alt+Tab (Windows/Linux) to switch 1-3 apps | 10 |
| Browser Tabs | Context-aware tab switching β detects the active app and sends the correct shortcut (e.g. Cmd+Shift+] for browsers on macOS, Ctrl+Tab for VS Code). Falls back to Ctrl+Tab when detection is unavailable | 5 |
# PyPI (all platforms)
pipx install go-phantom
# Homebrew (macOS)
brew install hammadxcm/go-phantom/phantom
# Snap (Linux)
sudo snap install go-phantom
# Chocolatey (Windows)
choco install go-phantom
# WinGet (Windows)
winget install hammadxcm.go-phantom
# Scoop (Windows)
scoop bucket add phantom https://github.com/hammadxcm/scoop-phantom
scoop install go-phantom
# Download binary from GitHub Releases
# macOS: phantom-macos-arm64
# Linux: phantom-linux-x86_64 or phantom_0.0.2_amd64.deb
# Windows: phantom-windows.exe| Platform | Method | Install | Run |
|---|---|---|---|
| All | PyPI | pipx install go-phantom |
phantom |
| macOS | Homebrew | brew install hammadxcm/go-phantom/phantom |
phantom |
| Linux | Snap | sudo snap install go-phantom |
phantom |
| Linux | .deb | sudo dpkg -i phantom_*.deb |
phantom |
| Windows | Chocolatey | choco install go-phantom |
phantom |
| Windows | WinGet | winget install hammadxcm.go-phantom |
phantom |
| Windows | Scoop | scoop install go-phantom |
phantom |
| Any | Binary | Download from Releases | ./phantom |
Both installers are fully cross-platform β use whichever you prefer on any OS:
| Method | Command | Works on |
|---|---|---|
| Bash |
git clone https://github.com/hammadxcm/go-phantom.git && cd phantom && ./install.sh |
macOS, Linux, Windows (Git Bash / WSL / MSYS2) |
| PowerShell |
git clone https://github.com/hammadxcm/go-phantom.git; cd phantom; .\install.ps1 |
Windows, macOS (pwsh), Linux (pwsh) |
| CMD |
git clone https://github.com/hammadxcm/go-phantom.git && cd phantom && install.bat |
Windows (Command Prompt) |
| Make |
git clone https://github.com/hammadxcm/go-phantom.git && cd phantom && make setup |
macOS, Linux, Windows (Git Bash / MSYS2) |
graph TD
A[Run installer] --> B{Detect OS}
B -->|macOS| C[Check Python 3.8+]
B -->|Linux| D[Check Python 3.8+ & X11]
B -->|Windows| E[Check Python 3.8+]
B -->|WSL| F[Check Python 3.8+ & DISPLAY]
C --> G[Create venv at ~/.phantom]
D --> G
E --> G
F --> G
G --> H[pip install dependencies]
H --> I[Create phantom command in ~/.local/bin]
I --> J{OS-specific notes}
J -->|macOS| K[Grant Accessibility permission]
J -->|Windows| L[Add AV exclusion]
J -->|Linux| M[Ensure X11 + tray support]
J -->|WSL| N[Configure X11 display server]
style A fill:#4CAF50,color:#fff
style J fill:#FF9800,color:#fff
The installer automatically:
- Detects your OS and checks prerequisites (Python 3.8+, X11 on Linux, DISPLAY on WSL)
- Creates an isolated virtual environment at
~/.phantom/ - Installs all dependencies
- Creates OS-appropriate launcher scripts:
- macOS / Linux:
~/.local/bin/phantom(bash) - Windows:
phantom.cmd(CMD) +phantom.ps1(PowerShell) - Git Bash on Windows: all three launchers
- macOS / Linux:
- Checks PATH and shows how to add it if needed
After install, just run:
phantom # start with defaults
phantom -v # start with debug logginggit clone https://github.com/hammadxcm/go-phantom.git
cd phantom
python3 -m venv .venv
source .venv/bin/activate # macOS/Linux
# .venv\Scripts\activate # Windows
pip install -e .
python -m phantompip install -e ".[dev]" # Install PyInstaller
make build # Outputs: dist/phantom
./dist/phantom # Run standalone (no Python needed)make uninstall # Removes ~/.phantom and phantom commandAll installed automatically β no manual setup needed:
| Package | Purpose |
|---|---|
pynput |
Global hotkeys and keyboard control |
pyautogui |
Mouse movement and scrolling |
pystray |
System tray icon |
Pillow |
Tray icon image generation |
setproctitle |
Process name masking |
rich |
TUI dashboard and colored logging |
phantom # run with defaults (mouse + keyboard + scroll)
phantom --tui # TUI dashboard mode
phantom -v # debug logging
phantom -c ~/config.json # custom config file# Single simulator
phantom --mouse-only # mouse movement only
phantom --keyboard-only # keyboard modifier keys only
phantom --scroll-only # scroll wheel only
# Pick exactly which simulators to run
phantom --only mouse,scroll # mouse + scroll, nothing else
phantom --only keyboard,browser_tabs # keyboard + tab switching
phantom --only app_switcher # app switching only (Cmd/Alt+Tab)
# Add to defaults (mouse + keyboard + scroll are on by default)
phantom --enable app_switcher # add app switching
phantom --enable app_switcher,browser_tabs # add both
# Remove from defaults
phantom --disable scroll # no scrolling
phantom --disable mouse,keyboard # scroll only
# Enable everything
phantom --all # all 5 simulators active# Fast mode β action every ~3 seconds
phantom --interval 3.0
# Slow mode β action every ~20 seconds with high variance
phantom --interval 20.0 --interval-stddev 10.0
# No idle pauses (continuous activity)
phantom --idle-chance 0
# Lots of idle pauses (25% chance each cycle)
phantom --idle-chance 0.25# Mouse: small, smooth movements
phantom --mouse-only --mouse-distance 20 100 --mouse-speed 150
# Mouse: large, fast movements
phantom --mouse-only --mouse-distance 200 800 --mouse-speed 30
# Keyboard: single key press per action
phantom --keyboard-only --key-presses 1
# Scroll: gentle scrolling (1-2 clicks)
phantom --scroll-only --scroll-clicks 1 2
# Scroll: aggressive scrolling (5-10 clicks)
phantom --scroll-only --scroll-clicks 5 10Weights control how often each simulator is picked. Higher = more frequent.
# Mouse-heavy (80% mouse, 20% keyboard)
phantom --only mouse,keyboard --mouse-weight 80 --keyboard-weight 20
# Equal distribution across all simulators
phantom --all --mouse-weight 20 --keyboard-weight 20 --scroll-weight 20 \
--app-switcher-weight 20 --browser-tabs-weight 20
# Mostly scrolling with some mouse
phantom --only mouse,scroll --scroll-weight 70 --mouse-weight 30# Maximum stealth (rename process + hide tray icon)
phantom --stealth
# Custom process name
phantom --process-name "WindowServer"
# No stealth at all
phantom --no-stealth# Change toggle and quit hotkeys
phantom --hotkey-toggle "<ctrl>+<shift>+f9" --hotkey-quit "<ctrl>+<shift>+f10"
# Change all hotkeys
phantom --hotkey-toggle "<ctrl>+<alt>+p" \
--hotkey-quit "<ctrl>+<alt>+x" \
--hotkey-hide "<ctrl>+<alt>+i"# Presentation mode: subtle mouse + no idle + stealth + TUI
phantom --mouse-only --mouse-distance 20 200 --interval 5.0 \
--idle-chance 0 --stealth --tui
# Work simulation: all simulators, relaxed timing, custom hotkeys
phantom --all --interval 15.0 --idle-chance 0.20 \
--hotkey-toggle "<ctrl>+<shift>+s"
# Quick test: fast keyboard + scroll, verbose logging
phantom --only keyboard,scroll --interval 2.0 -v
# Screen-lock prevention: minimal mouse movement every 30 seconds
phantom --mouse-only --interval 30.0 --interval-stddev 5.0 \
--mouse-distance 10 50 --idle-chance 0 --no-stealthmake run # tray mode (defaults)
make tui # TUI dashboard
make run-verbose # debug loggingThe --tui flag launches a rich terminal dashboard instead of the system tray:
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
β PHANTOM RUNNING Uptime: 00:14:32 β
βββββββββββββββββββββββ¬βββββββββββββββββββββββββββββ€
β Stats β Live Logs β
β βββββββββββββ β 17:04:50 Mouse β (694β¦ β
β Mouse 12 β 17:04:55 Keyboard 2 β¦ β
β Keyboard 8 β 17:04:58 Scroll 3 clβ¦ β
β Scroll 5 β 17:05:03 Mouse β (12β¦ β
β App Switch 3 β 17:05:10 Idle 23.4s β
β Browser 1 β 17:05:33 Mouse β (45β¦ β
β βββββββββββββ β β
β Total 29 β β
β Last: Mouse β β
βββββββββββββββββββββββ΄βββββββββββββββββββββββββββββ€
β [S] Toggle [Q] Quit β
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Note: TUI mode and system tray are mutually exclusive. The
--tuiflag runs the dashboard on the main thread; without it, the system tray runs instead.
Run phantom --help to see all options. Key flags:
| Flag | Description |
|---|---|
-c, --config |
Path to config.json |
-v, --verbose |
Debug logging |
--tui |
TUI dashboard mode |
--mouse-only |
Mouse simulator only |
--keyboard-only |
Keyboard simulator only |
--scroll-only |
Scroll simulator only |
--only SIMS |
Comma-separated simulators |
--enable SIMS |
Add simulators to defaults |
--disable SIMS |
Remove simulators |
--all |
Enable all 5 simulators |
--interval SEC |
Mean action interval |
--idle-chance P |
Idle probability (0-1) |
--mouse-distance MIN MAX |
Movement range (px) |
--mouse-speed STEPS |
Bezier smoothness |
--key-presses MAX |
Max keys per action |
--scroll-clicks MIN MAX |
Scroll range |
--mouse-weight W |
Mouse frequency weight |
--stealth |
Max stealth mode |
--no-stealth |
Disable stealth |
--process-name NAME |
Custom process name |
--hotkey-toggle KEYS |
Toggle hotkey |
--hotkey-quit KEYS |
Quit hotkey |
| Hotkey | Action | Description |
|---|---|---|
| Ctrl+Alt+S | Toggle | Start or pause simulation |
| Ctrl+Alt+Q | Quit | Gracefully exit Phantom |
| Ctrl+Alt+H | Hide | Toggle tray icon visibility |
When running, Phantom shows a system tray icon with a right-click menu:
βββββββββββββββββββ
β βΆ Start/Pause β
β βββββββββββββββ β
β β Quit β
βββββββββββββββββββ
$ python -m phantom -v
14:13:44 [INFO] phantom.config.manager: No config file found, using defaults
14:13:44 [WARNING] phantom.core.platform: macOS requires Accessibility permission...
14:13:45 [INFO] phantom.stealth.process: Process renamed to 'system_service'
14:13:45 [INFO] phantom.hotkeys.manager: Hotkeys registered: toggle=<ctrl>+<alt>+s, quit=<ctrl>+<alt>+q
14:13:45 [INFO] phantom.core.scheduler: Simulation loop started
14:13:45 [INFO] phantom.app: Phantom started. Press <ctrl>+<alt>+s to toggle.
14:13:47 [DEBUG] MouseSimulator: Mouse moved to (1474, 829)
14:13:52 [DEBUG] KeyboardSimulator: Keyboard: 2 modifier presses
14:13:58 [DEBUG] ScrollSimulator: Scroll: 3 clicks, direction=1
14:14:05 [DEBUG] MouseSimulator: Mouse moved to (892, 341)
14:14:13 [DEBUG] Idle period: 23.4sClick to expand macOS setup instructions
- macOS 10.15+ (Catalina or later)
- Python 3.8+
Phantom needs Accessibility access to control mouse and keyboard input. Without it, simulators will fail silently.
System Settings β Privacy & Security β Accessibility
Step by step:
- Open System Settings (or System Preferences on older macOS)
- Navigate to Privacy & Security β Accessibility
- Click the π lock icon and authenticate
- Click + and add your terminal app:
Terminal.appβ if using default terminaliTerm.appβ if using iTerm2Visual Studio Code.appβ if running from VS Code terminal
- If running the built binary, add
phantomdirectly
# Create venv and install
python3 -m venv .venv && source .venv/bin/activate
pip install -e .
# Run with verbose logging β watch for mouse movement logs
python -m phantom -v
# Expected output:
# [INFO] phantom.stealth.process: Process renamed to 'system_service'
# [INFO] phantom.core.scheduler: Simulation loop started
# [DEBUG] MouseSimulator: Mouse moved to (x, y) β confirms Accessibility works| Behavior | Details |
|---|---|
| Main thread | pystray requires the main thread on macOS β Phantom handles this automatically (tray runs on main, scheduler on daemon thread) |
| App Switcher | Uses Cmd+Tab (not Alt+Tab) |
| Process masking | Uses setproctitle with libc.dylib fallback |
| Gatekeeper | Built binary may need: right-click β Open β confirm |
# Check if Accessibility is working
python3 -c "import pyautogui; print(pyautogui.position())"
# Should print current mouse coordinates, not throw an error
# If pystray crashes on startup
# Ensure you're NOT running in a headless/SSH session
echo $DISPLAY # Should not be empty if using XQuartzClick to expand Windows setup instructions
- Windows 10/11
- Python 3.8+ (python.org β check "Add to PATH" during install)
# Clone and install
git clone https://github.com/hammadxcm/go-phantom.git
cd phantom
python -m venv .venv
.venv\Scripts\activate
pip install -e .Some AV software flags Phantom because it simulates input. To add an exclusion in Windows Defender:
Windows Security β Virus & threat protection β Manage settings
β Exclusions β Add or remove exclusions β Add an exclusion
Add either:
- The
phantomdirectory (folder exclusion) - The built
phantom.exe(file exclusion)
# Run with verbose logging
python -m phantom -v
# Expected output:
# [INFO] phantom.stealth.process: Console title set to 'system_service'
# [INFO] phantom.core.scheduler: Simulation loop started
# [DEBUG] MouseSimulator: Mouse moved to (x, y)| Behavior | Details |
|---|---|
| Process masking | Uses SetConsoleTitleW via ctypes β changes console window title, limited effect on modern Windows Terminal |
| App Switcher | Uses Alt+Tab |
| UAC | No elevation required β runs as standard user |
| Startup | To run at login, add a shortcut to shell:startup |
# Option 1: pythonw (no console window)
pythonw -m phantom
# Option 2: Start minimized
start /min python -m phantom
# Option 3: Built executable
dist\phantom.exe# Verify Python is on PATH
python --version
# Verify pyautogui works
python -c "import pyautogui; print(pyautogui.position())"
# If hotkeys don't register, check for conflicts with other apps
# Try changing hotkeys in config.json:
# "hotkeys": { "toggle": "<ctrl>+<alt>+p", ... }Click to expand Linux setup instructions
- Linux with X11 (Ubuntu, Fedora, Arch, etc.)
- Python 3.8+
- Wayland is NOT supported β
pyautoguiandpynputrequire X11 APIs
echo $XDG_SESSION_TYPE
# β
x11 β supported
# β wayland β NOT supported β switch to X11 session at login screenGNOME (Ubuntu 22.04+):
- Log out
- Click your username on the login screen
- Click the βοΈ gear icon (bottom-right)
- Select "GNOME on Xorg" or "Ubuntu on Xorg"
- Log in
KDE Plasma:
- Log out β select "Plasma (X11)" at login
# Install system dependencies (Debian/Ubuntu)
sudo apt install python3-venv python3-dev python3-tk
# Install system dependencies (Fedora)
sudo dnf install python3-devel python3-tkinter
# Install system dependencies (Arch)
sudo pacman -S python tk
# Clone and install
git clone https://github.com/hammadxcm/go-phantom.git
cd phantom
python3 -m venv .venv
source .venv/bin/activate
pip install -e .# Confirm X11 session
echo $XDG_SESSION_TYPE # must output: x11
# Run with verbose logging
python -m phantom -v
# Expected output:
# [INFO] phantom.stealth.process: Process renamed to 'system_service' (setproctitle)
# [INFO] phantom.core.scheduler: Simulation loop started
# [DEBUG] MouseSimulator: Mouse moved to (x, y)| Behavior | Details |
|---|---|
| Display server | X11 only β Wayland will fail at runtime |
| Process masking | Uses setproctitle β fully renames the process (visible in ps, top, htop) |
| App Switcher | Uses Alt+Tab |
| Tray icon | Requires a system tray (GNOME needs the AppIndicator extension) |
| Permissions | No special permissions needed (X11 apps can send input to other X11 apps) |
# Option 1: nohup
nohup python -m phantom &
# Option 2: systemd user service
mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/phantom.service << 'EOF'
[Unit]
Description=Phantom Activity Simulator
After=graphical-session.target
[Service]
Type=simple
ExecStart=/path/to/phantom/.venv/bin/python -m phantom
Restart=on-failure
Environment=DISPLAY=:0
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload
systemctl --user enable --now phantom.service
systemctl --user status phantom.service# In another terminal, after starting Phantom:
ps aux | grep system_service
# Should show the phantom process with name 'system_service'
# Or use htop β search for 'system_service'# If mouse simulation fails
python3 -c "import pyautogui; print(pyautogui.position())"
# Error? β You're probably on Wayland
# If tray icon doesn't appear (GNOME)
# Install AppIndicator support:
sudo apt install gnome-shell-extension-appindicator
# Then enable it in GNOME Extensions app
# If hotkeys don't work
# Check for conflicts: some DEs grab Ctrl+Alt combos globally
# Change hotkeys in config.json to avoid conflictsPhantom looks for config.json in this order:
graph LR
A[1. CLI flag<br/><code>-c path</code>] -->|not provided| B[2. Beside executable<br/><i>PyInstaller only</i>]
B -->|not found| C[3. Current directory<br/><code>./config.json</code>]
C -->|not found| D[4. Home directory<br/><code>~/.phantom/config.json</code>]
D -->|not found| E[5. Built-in defaults]
style A fill:#4CAF50,color:#fff
style E fill:#2196F3,color:#fff
# Create config directory
mkdir -p ~/.phantom
# Generate a starter config (copy and modify)
cat > ~/.phantom/config.json << 'EOF'
{
"timing": {
"interval_mean": 8.0,
"interval_stddev": 4.0,
"interval_min": 0.5,
"idle_chance": 0.10,
"idle_min": 15.0,
"idle_max": 120.0
},
"mouse": {
"enabled": true,
"weight": 40.0,
"min_distance": 50,
"max_distance": 500,
"bezier_steps": 50
},
"keyboard": {
"enabled": true,
"weight": 30.0,
"max_presses": 3
},
"scroll": {
"enabled": true,
"weight": 15.0,
"min_clicks": 1,
"max_clicks": 5
},
"app_switcher": {
"enabled": false,
"weight": 10.0
},
"browser_tabs": {
"enabled": false,
"weight": 5.0,
"context_aware": true,
"backward_chance": 0.3
},
"hotkeys": {
"toggle": "<ctrl>+<alt>+s",
"quit": "<ctrl>+<alt>+q",
"hide_tray": "<ctrl>+<alt>+h"
},
"stealth": {
"rename_process": true,
"process_name": "system_service",
"hide_tray": false
}
}
EOFtiming β Action interval and idle behavior
| Key | Type | Default | Description |
|---|---|---|---|
interval_mean |
float |
8.0 |
Average seconds between actions (normal distribution center) |
interval_stddev |
float |
4.0 |
Standard deviation β higher = more variation |
interval_min |
float |
0.5 |
Floor β actions never fire faster than this |
idle_chance |
float |
0.10 |
Probability (0-1) of entering an idle period per cycle |
idle_min |
float |
15.0 |
Minimum idle pause in seconds |
idle_max |
float |
120.0 |
Maximum idle pause in seconds |
Tuning tips:
mouse β Bezier curve mouse movement
| Key | Type | Default | Description |
|---|---|---|---|
enabled |
bool |
true |
Enable/disable mouse simulator |
weight |
float |
40.0 |
Selection probability (relative to other simulators) |
min_distance |
int |
50 |
Minimum pixels to move per action |
max_distance |
int |
500 |
Maximum pixels to move per action |
bezier_steps |
int |
50 |
Number of points on the curve β higher = smoother |
graph LR
A((Start)) -->|"Bezier curve<br/>50 steps"| B((End))
A -.->|"Control Point 1<br/>(random offset)"| CP1(( ))
CP1 -.-> B
A -.->|"Control Point 2<br/>(random offset)"| CP2(( ))
CP2 -.-> B
B -->|"30% chance"| C((Micro-correction<br/>Β±3px jitter))
keyboard β Modifier key simulation
| Key | Type | Default | Description |
|---|---|---|---|
enabled |
bool |
true |
Enable/disable keyboard simulator |
weight |
float |
30.0 |
Selection probability weight |
max_presses |
int |
3 |
Maximum key presses per action (1 to N) |
Safe keys used: Shift, Ctrl, Alt + CapsLock double-tap (15% chance, toggles on then off immediately).
These keys produce no visible output β they won't type into your active application.
scroll β Scroll wheel simulation
| Key | Type | Default | Description |
|---|---|---|---|
enabled |
bool |
true |
Enable/disable scroll simulator |
weight |
float |
15.0 |
Selection probability weight |
min_clicks |
int |
1 |
Minimum scroll clicks per action |
max_clicks |
int |
5 |
Maximum scroll clicks per action |
90% vertical scroll, 10% horizontal scroll. Direction is random (up/down or left/right).
app_switcher β Application switching
| Key | Type | Default | Description |
|---|---|---|---|
enabled |
bool |
false |
Disabled by default β will switch your active window |
weight |
float |
10.0 |
Selection probability weight |
Uses Cmd+Tab on macOS, Alt+Tab on Windows/Linux. Switches 1-3 applications per action.
β οΈ Warning: This will change your focused application. Only enable if you want realistic app-switching behavior.
browser_tabs β Context-aware tab switching
| Key | Type | Default | Description |
|---|---|---|---|
enabled |
bool |
false |
Disabled by default β will switch browser tabs |
weight |
float |
5.0 |
Selection probability weight |
context_aware |
bool |
true |
Detect active window and send the correct shortcut for that app/OS |
backward_chance |
float |
0.3 |
Probability of switching to the previous tab (vs. next tab) |
When context_aware is enabled, Phantom detects the foreground application and sends the correct tab-switching shortcut:
| App | macOS | Windows / Linux |
|---|---|---|
| Browsers (Chrome, Firefox, Safari, Edge, Brave, Arc) | Cmd+Shift+] / Cmd+Shift+[ | Ctrl+Tab / Ctrl+Shift+Tab |
| VS Code / Cursor | Ctrl+Tab / Ctrl+Shift+Tab | Ctrl+Tab / Ctrl+Shift+Tab |
| iTerm2, Terminal.app | Cmd+Shift+] / Cmd+Shift+[ | β |
| kitty | Ctrl+Shift+Right / Ctrl+Shift+Left | Ctrl+Shift+Right / Ctrl+Shift+Left |
| GNOME Terminal, Konsole | β | Ctrl+PageDown / Ctrl+PageUp |
| Unknown app (fallback) | Ctrl+Tab / Ctrl+Shift+Tab | Ctrl+Tab / Ctrl+Shift+Tab |
Set context_aware: false to restore the original blind Ctrl+Tab behavior.
β οΈ Warning: Only effective when a tabbed application is the active window. Enable alongsideapp_switcherfor realistic browsing simulation.Note: Active window detection is not supported on Wayland β falls back to Ctrl+Tab.
hotkeys β Global hotkey bindings
| Key | Type | Default | Description |
|---|---|---|---|
toggle |
str |
<ctrl>+<alt>+s |
Start / pause simulation |
quit |
str |
<ctrl>+<alt>+q |
Exit Phantom |
hide_tray |
str |
<ctrl>+<alt>+h |
Toggle tray icon visibility |
Uses pynput key format. Examples:
// Custom hotkeys
{
"toggle": "<ctrl>+<shift>+f9",
"quit": "<ctrl>+<shift>+f10",
"hide_tray": "<ctrl>+<shift>+f11"
}stealth β Anti-detection features
| Key | Type | Default | Description |
|---|---|---|---|
rename_process |
bool |
true |
Mask the process name in task manager / ps |
process_name |
str |
system_service |
What to rename the process to |
hide_tray |
bool |
false |
Start with tray icon hidden (toggle with hotkey) |
// Maximum stealth
{
"rename_process": true,
"process_name": "windowserver",
"hide_tray": true
}Mouse-only mode
{
"mouse": { "enabled": true, "weight": 100.0 },
"keyboard": { "enabled": false },
"scroll": { "enabled": false }
}Aggressive mode β fast actions, all simulators
{
"timing": {
"interval_mean": 3.0,
"interval_stddev": 1.0,
"idle_chance": 0.02
},
"mouse": { "enabled": true, "weight": 30.0 },
"keyboard": { "enabled": true, "weight": 25.0 },
"scroll": { "enabled": true, "weight": 20.0 },
"app_switcher": { "enabled": true, "weight": 15.0 },
"browser_tabs": { "enabled": true, "weight": 10.0 }
}Minimal footprint β slow and subtle
{
"timing": {
"interval_mean": 20.0,
"interval_stddev": 10.0,
"idle_chance": 0.25,
"idle_max": 300.0
},
"mouse": {
"enabled": true,
"weight": 80.0,
"min_distance": 20,
"max_distance": 200,
"bezier_steps": 80
},
"keyboard": { "enabled": true, "weight": 20.0, "max_presses": 1 },
"scroll": { "enabled": false },
"stealth": { "rename_process": true, "hide_tray": true }
}graph TB
subgraph "Main Thread"
TRAY[π₯οΈ System Tray<br/><code>ui/tray.py</code>]
DASH[π TUI Dashboard<br/><code>ui/dashboard.py</code>]
end
subgraph "Daemon Threads"
HK[πΉ Hotkey Listener<br/><code>hotkeys/manager.py</code>]
SCHED[β±οΈ Scheduler<br/><code>core/scheduler.py</code>]
end
subgraph "Simulators"
MOUSE[π±οΈ Mouse<br/><code>simulators/mouse.py</code>]
KB[β¨οΈ Keyboard<br/><code>simulators/keyboard.py</code>]
SCROLL[π Scroll<br/><code>simulators/scroll.py</code>]
APP[π App Switcher<br/><code>simulators/app_switcher.py</code>]
TABS[π Browser Tabs<br/><code>simulators/browser_tabs.py</code>]
end
subgraph "Support"
CFG[βοΈ Config Manager<br/><code>config/manager.py</code>]
RAND[π² Randomizer<br/><code>core/randomization.py</code>]
AD[π‘οΈ Anti-Detection<br/><code>stealth/anti_detection.py</code>]
PROC[π» Process Mask<br/><code>stealth/process.py</code>]
PLAT[π» Platform<br/><code>core/platform.py</code>]
STATS[π Stats<br/><code>core/stats.py</code>]
end
APP_PY[π PhantomApp<br/><code>app.py</code>] --> TRAY
APP_PY -->|"--tui"| DASH
APP_PY --> HK
APP_PY --> SCHED
APP_PY --> CFG
APP_PY --> PROC
SCHED --> STATS
DASH --> STATS
SCHED --> RAND
SCHED --> AD
SCHED --> MOUSE
SCHED --> KB
SCHED --> SCROLL
SCHED --> APP
SCHED --> TABS
HK -->|toggle/quit/hide| APP_PY
TRAY -->|menu actions| APP_PY
MOUSE --> RAND
APP --> PLAT
TABS --> PLAT
phantom/
βββ __init__.py # Package version (__version__ = "0.0.1")
βββ __main__.py # CLI entry point β argparse, logging setup
βββ app.py # Orchestrator β wires all components
β
βββ config/
β βββ defaults.json # Default values for all settings
β βββ manager.py # Load/save config, resolution order
β βββ schema.py # Dataclass definitions (PhantomConfig, etc.)
β
βββ core/
β βββ active_window.py # Cross-platform active window detection (macOS/Win/Linux)
β βββ platform.py # OS detection, Wayland check, permission warnings
β βββ randomization.py # Bezier curves, gaussian timing, weighted choice
β βββ scheduler.py # Main loop β weighted selection, idle, anti-detection
β βββ stats.py # Thread-safe metrics collector for TUI dashboard
β βββ tab_shortcuts.py # App-to-shortcut mapping registry for tab switching
β
βββ hotkeys/
β βββ manager.py # Global hotkey registration via pynput
β
βββ simulators/
β βββ base.py # Abstract BaseSimulator β all simulators extend this
β βββ mouse.py # Bezier curve movement + micro-corrections
β βββ keyboard.py # Modifier-key-only presses (Shift, Ctrl, Alt, CapsLock)
β βββ scroll.py # Vertical/horizontal scroll wheel
β βββ app_switcher.py # Cmd+Tab (macOS) / Alt+Tab (Windows/Linux)
β βββ browser_tabs.py # Context-aware tab switching (detects active app)
β
βββ stealth/
β βββ anti_detection.py # History tracking, pattern blocking
β βββ process.py # Process name masking (per-OS implementation)
β
βββ ui/
βββ dashboard.py # Rich TUI dashboard (--tui mode)
βββ icons.py # Tray icon image generation (Pillow)
βββ log_handler.py # Bounded deque log handler for TUI
βββ tray.py # System tray integration (pystray)
sequenceDiagram
participant Main as Main Thread
participant Tray as Tray (Main)
participant HK as Hotkey (Daemon)
participant Sched as Scheduler (Daemon)
Main->>Main: Parse args, load config
Main->>Main: Check platform, mask process
Main->>HK: Start hotkey listener
Main->>Sched: Start scheduler
Main->>Tray: Run tray event loop (blocks)
loop Every ~8s (gaussian)
Sched->>Sched: Pick weighted random simulator
Sched->>Sched: Anti-detection check
Sched->>Sched: Execute simulator
Sched->>Sched: Wait (gaussian interval)
end
HK-->>Main: Ctrl+Alt+S (toggle)
Main->>Sched: toggle()
Main->>Tray: update_status()
HK-->>Main: Ctrl+Alt+Q (quit)
Main->>Sched: shutdown()
Main->>HK: stop()
Main->>Tray: stop()
# Install dev dependencies
pip install -e ".[dev]"
# Build (uses PyInstaller spec in build/phantom.spec)
make build
# Output
ls -la dist/phantom
# -rwxr-xr-x 1 user staff 12345678 phantom| Target | Command | Description |
|---|---|---|
make install |
pip install -e . |
Install in editable mode |
make dev |
pip install -e ".[dev]" |
Install with dev tools (ruff, pyinstaller) |
make lint |
ruff check phantom/ |
Check code style |
make format |
ruff format phantom/ |
Auto-format code |
make run |
python -m phantom |
Run normally |
make run-verbose |
python -m phantom -v |
Run with debug logging |
make tui |
python -m phantom --tui |
Run with TUI dashboard |
make release |
git tag v* && git push --tags |
Create release tag |
make build |
pyinstaller build/phantom.spec ... |
Build single executable |
make clean |
rm -rf dist/ build/tmp/ ... |
Remove build artifacts |
# Install test dependencies
pip install -e ".[dev]"
pip install pytest pytest-cov
# Run all tests
pytest
# Run with short traceback
pytest --tb=short
# Run with coverage report
pytest --cov=phantom
# Run a specific test file
pytest tests/test_simulators.py
# Run a specific test
pytest tests/test_simulators.py::test_mouse_clamp -vtests/
βββ test_active_window.py 9 tests β cross-platform window detection, cache
βββ test_anti_detection.py 10 tests β pattern blocking, history tracking
βββ test_app.py 10 tests β orchestrator wiring, lifecycle
βββ test_config_manager.py 14 tests β loading, saving, resolution
βββ test_config_schema.py 14 tests β dataclass defaults, weights
βββ test_dashboard.py 17 tests β TUI layout, panels, key handling
βββ test_hotkeys.py 7 tests β hotkey registration, callbacks
βββ test_icons.py 5 tests β tray icon generation
βββ test_log_handler.py 9 tests β DequeHandler capture, maxlen
βββ test_main.py 6 tests β CLI entry point, --tui, RichHandler
βββ test_platform.py 15 tests β OS detection, Wayland check
βββ test_process.py 11 tests β process masking per OS
βββ test_randomization.py 25 tests β Bezier, timing, distributions
βββ test_scheduler.py 12 tests β loop, weighted selection, idle
βββ test_simulators.py 22 tests β all 5 simulators + context-aware tabs
βββ test_stats.py 14 tests β metrics, thread safety, snapshots
βββ test_tab_shortcuts.py 13 tests β app-to-shortcut registry lookups
βββ test_tray.py 15 tests β tray menu, status updates
βββ
298 tests β 99% coverage
See CONTRIBUTING.md for development workflow, code style, and pull request guidelines.