Background CLI utility that copies OTPs from Gmail to clipboard on hotkey trigger
Project description
OTPilot
Press a hotkey. Your OTP is already copied.
pip install otpilot
✈ OTPilot v2.3
Background utility that fetches OTPs from Gmail and copies them to your clipboard with a single hotkey press.
GitHub • Install • Quickstart • Contributing
How It Works
- OTPilot sits in your system tray with no background polling.
- Press your hotkey or run
otpilot fetchto scan recent Gmail messages. - OTP is copied to clipboard and optionally auto-pasted.
Installation
pip install otpilot
Requirements
- Python 3.10+
- A Gmail account
Linux users must install clipboard support:
sudo apt install xclip # Debian/Ubuntu
Quickstart
1. Run Setup
otpilot setup
The wizard will:
- Open your browser for a one-time Google sign-in (read-only Gmail access)
- Let you configure hotkey, notifications, and scan preferences
- Save everything locally
2. Start OTPilot
otpilot start
OTPilot runs in the background with a system tray icon when supported.
3. Daily Use
- Receive an OTP email
- Press your hotkey (default:
Ctrl+Shift+O) - Paste
CLI Commands
| Command | Description |
|---|---|
otpilot setup |
Run or re-run the interactive setup wizard |
otpilot start |
Start the background service |
otpilot stop |
Stop the background service |
otpilot fetch |
Trigger a one-time OTP fetch from the CLI |
otpilot history |
Show recent OTP history |
otpilot history --clear |
Clear OTP history |
otpilot logs |
Tail the OTPilot log file |
otpilot status |
Show auth state, hotkey, and config |
otpilot hotkey |
View or reconfigure the global hotkey |
otpilot logout |
Clear stored auth token |
otpilot update |
Check PyPI for updates and upgrade |
otpilot version |
Print the installed version |
Configuration
OTPilot stores its configuration at ~/.otpilot/config.json:
{
"hotkey": "ctrl+shift+o",
"notify_on_copy": true,
"otp_max_age_minutes": 10,
"email_fetch_count": 10,
"otp_history_count": 10,
"auto_paste": false,
"auto_start_on_boot": false,
"notification_sound": false,
"mask_otp_in_notification": true,
"check_updates_on_start": true
}
| Field | Type | Default | Description |
|---|---|---|---|
hotkey |
string | ctrl+shift+o |
Global hotkey combination |
notify_on_copy |
bool | true |
Show desktop notification when OTP is copied |
otp_max_age_minutes |
int | 10 |
Ignore emails older than this (minutes) |
email_fetch_count |
int | 10 |
Number of recent emails to scan (max 50) |
otp_history_count |
int | 10 |
Number of OTP history entries to keep (max 50) |
auto_paste |
bool | false |
Auto-paste OTP after copying |
auto_start_on_boot |
bool | false |
Launch OTPilot on login |
notification_sound |
bool | false |
Play a sound with notifications |
mask_otp_in_notification |
bool | true |
Mask middle digits in notification (e.g. 84••93) |
check_updates_on_start |
bool | true |
Check PyPI for a newer version on startup |
Files Stored Locally
| Path | Purpose |
|---|---|
~/.otpilot/config.json |
Hotkey and runtime settings |
~/.otpilot/history.json |
OTP history entries |
~/.otpilot/otpilot.log |
Background service log |
~/.otpilot/otpilot.pid |
PID of the running background process |
System keyring (otpilot) |
Preferred OAuth token storage |
~/.otpilot/token.json |
Fallback token storage |
OTP History
Show recent entries:
otpilot history
Show only 3 entries:
otpilot history --count 3
Clear history:
otpilot history --clear
Platform Support
| Platform | Status | Notes |
|---|---|---|
| macOS | ✅ | Full support |
| Windows | ✅ | Full support |
| Linux | ✅ | Requires xclip or xsel |
How OTP Extraction Works
OTPilot scans the subject line and body of your recent emails for:
- 4–8 digit standalone numbers near context words like OTP, code, verify, one-time, passcode, authentication, 2FA
- Only emails within
otp_max_age_minutesare considered - Subject line matches are prioritized over body matches
Security & Privacy
- Read-only Gmail access
- On-demand only, no background polling
- Local storage for tokens and configuration
- No telemetry or analytics
Troubleshooting
| Issue | Solution |
|---|---|
| "Not authenticated" error | Run otpilot setup to re-authenticate |
| No OTP found | Check otp_max_age_minutes — the email might be too old |
| Clipboard not working (Linux) | Install xclip: sudo apt install xclip |
| Hotkey not working | Run otpilot hotkey to reconfigure |
| Tray icon not visible | Check your system tray / menu bar settings |
| Stop doesn’t work | Run otpilot stop again or delete ~/.otpilot/otpilot.pid |
| Log file empty | Start OTPilot and run otpilot logs after a fetch |
Contributing
Contributions are welcome. See docs/CONTRIBUTING.md for dev setup and code standards.
License
MIT License.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file otpilot-2.3.0.tar.gz.
File metadata
- Download URL: otpilot-2.3.0.tar.gz
- Upload date:
- Size: 41.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
56a9d6ecb6e16f8504bb545d5d46f3173d560cddf4ed987d25e309c223a76dd5
|
|
| MD5 |
affd665066d2517990cd72c5cf63dc21
|
|
| BLAKE2b-256 |
6ca6217457c55cfb5d54ddcff5434cab8c50396bd2c5b9a8d19882e30e6ecf13
|
File details
Details for the file otpilot-2.3.0-py3-none-any.whl.
File metadata
- Download URL: otpilot-2.3.0-py3-none-any.whl
- Upload date:
- Size: 34.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.5
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d3d45e6d812ec1670477b9b1bc1ed5339a3d48dec9632ec344b961578b444b55
|
|
| MD5 |
b1d54063b730286b74cb1ff01c375f4b
|
|
| BLAKE2b-256 |
a329dd70e6aadf87ebbbd728c1549e11704bb42448e4a7b39459805d94356b5a
|