A terminal-based Gmail client written in Python. Read, write, and manage your emails inside your terminal.
- Features
- Commands Reference
- Requirements
- Installation
- Directory Tree
- Gmail App Password Setup
- Getting Started
- Demo Mode
- Multi-Account Support
- Settings and Aliases
- AI Usage
- License
- Inbox & Labels: Browse emails by labels (on the sidebar).
- Email Viewing: Read full email threads, with HTML-to-text conversion for HTML emails.
- Open in Browser: Render any email or thread as a proper HTML page in your browser with the
opencommand. - Compose: Write emails with a cli text editor (Ctrl+S to send, Ctrl+C to cancel/draft).
- Reply & Forward: Reply to emails with auto-quoted content, or forward with full original message.
- Drafts: Save compositions as drafts and come back to edit and send them later.
- Attachments: View attachment listings and download them.
- Search: Search emails in the current label.
- Labels: Create, delete, rename, and apply/remove labels on any email.
- Email Actions: Star, unstar, mark as read/unread, delete (to trash), and archive emails.
- Multi-Account: Store and switch between multiple Gmail accounts, with credentials saved securely in the system keychain.
- Settings: Customise emails per page, download folder, email signature, auto-mark-read behavior and default label (on startup).
- Aliases: Create command shortcuts for any command.
- Demo Mode: Try the interface without a Gmail account using some demo data.
| Command | Description | Usage |
|---|---|---|
| inbox | Fetch and display emails in the inbox | inbox |
| view | View the full content of an email | view <email_id> |
| open | Open email in browser | open <email_id> |
| next | Go to the next page | next |
| prev | Go to the previous page | prev |
| page | Jump to a specific page | page <page_number> |
| label | Switch to a different label | label <label_name_or_number> |
| search | Search emails in the current label | search <query> |
| download | Download an attachment from an email | download <email_id> <attachment_number> |
| Command | Description | Usage |
|---|---|---|
| write | Compose and send a new email | write |
| reply | Reply to an email | reply <email_id> |
| forward | Forward an email | forward <email_id> |
| edit | Edit a draft email | edit <email_id> |
| Command | Description | Usage |
|---|---|---|
| star | Star an email | star <email_id> |
| unstar | Remove star from an email | unstar <email_id> |
| unread | Mark an email as unread | unread <email_id> |
| delete | Move an email to trash | delete <email_id> |
| untrash | Move an email back to inbox from trash | untrash <email_id> |
| archive | Archive an email (remove from inbox) | archive <email_id> |
| Command | Description | Usage |
|---|---|---|
| newlabel | Create a new label | newlabel <n> |
| deletelabel | Delete a label | deletelabel <n> |
| renamelabel | Rename a label | renamelabel <old_name> <new_name> |
| setlabel | Apply a label to an email | setlabel <email_id> <label> |
| unsetlabel | Remove a label from an email | unsetlabel <email_id> <label> |
| Command | Description | Usage |
|---|---|---|
| settings | View current settings | settings |
| setting | Change a specific setting | setting <n> <value> |
| alias | Create or view a command alias | alias [<alias> [<command>]] |
| unalias | Remove a command alias | unalias <alias> |
| accounts | List saved accounts | accounts |
| addaccount | Add a new account | addaccount |
| switchaccount | Switch to a different account | switchaccount <email> |
| removeaccount | Remove a saved account | removeaccount <email> |
| help | Show the help message | help |
| version | Show application version | version |
| exit / quit | Exit the application | exit / quit |
- Python: 3.7 or higher
- Dependencies: Install via
requirements.txt- rich
- prompt_toolkit
- keyring
- html2text
-
Clone the repository and navigate to the project folder:
git clone https://github.com/artur3333/CLI-Inbox.git cd CLI-Inbox -
Install the required Python packages:
pip install -r requirements.txt
CLI-Inbox/
├── main.py # Entry point and command loop
├── mail.py # IMAP/SMTP backend (Gmail)
├── demo.py # Demo mode
├── auth.py # Account & credential management (keyring)
├── ui.py # Terminal UI rendering (rich + prompt_toolkit)
├── settings.py # Settings load/save (JSON)
├── utils.py # Utility helpers (date formatting, color printing)
└── __init__.py # Package initializer
CLI-Inbox connects to Gmail using IMAP and SMTP. Since Google no longer allows sign-in with your regular password for third-party apps, you need to generate an App Password:
- Go to your Google Account: https://myaccount.google.com/apppasswords
- Generate a new app password (YOU WILL NEED TO HAVE THE 2-FACTOR AUTHENTICATION ENABLED) and name it something like "CLI-Inbox".
- Copy the generated password.
- Use this password when CLI-Inbox prompts for your password, NOT your regular Google password.
Your credentials are stored securely in your system's native keychain (via the
keyringlibrary) and never saved in plain text.
-
Start the application:
python main.py
or you can lunch in demo mode with:
python main.py --demo
Using the .exe release: Double-clicking the executable will launch it normally. To start in demo mode, open a terminal inside the folder where
cli-inbox.exeis located and run:cli-inbox.exe --demo
-
On first normal launch, you'll be prompted to enter your Gmail address and App Password. These are saved to your system keychain for future sessions.
-
Browse your inbox it loads automatically on startup.
-
View an email:
view 3 -
Compose a new email:
writeUse Ctrl+S to send or Ctrl+C to cancel (you'll be asked if you want to save as a draft).
-
Switch labels:
label Sent Mailor by counting from the sidebar:
label 2 -
See all commands:
help
You can try CLI-Inbox without a Gmail account using the demo mode. It comes preloaded with sample emails and an in-memory backend:
python main.py --demoThe demo email is:
demo@hackclub.com
CLI-Inbox supports multiple Gmail accounts stored in your keychain. The active account is remembered between sessions.
addaccount # Add a new account
accounts # List all saved accounts
switchaccount blablabla@gmail.com # Switch active account
removeaccount old@gmail.com # Remove an account| Setting | Default | Description |
|---|---|---|
emails_per_page |
20 |
Number of emails shown per page |
download_folder |
~/Downloads |
Default folder for downloaded attachments |
signature |
(empty) | Signature appended to composed emails |
auto_mark_read |
true |
Automatically mark emails as read when viewed |
default_label |
INBOX |
Label loaded on startup |
Access settings with:
settings # View all settings
setting <setting_name> <new_value> # Change a settingCreate your own command shortcuts for existing commands:
alias [alias] [command] # Create an alias
unalias <alias> # Remove an aliasAliases are saved to ~/.cli_inbox_settings.json and persist between sessions.
This project was developed with selective use of AI assistance. Most of the implementation was done independently, with AI mainly used for:
-
resolve_label function (
main.py) When implementing threaded conversation support, there was an issue with message IDs and IMAP label targeting that was hard to reason through. ID problems were very common in this project :/ -
Demo mode (
demo.py) The demo mode ended up being significantly harder than expected. AI was asked for a suggestion on how to approach the problem, and it suggested using a 'monkey patching' technique. Additional help was needed for thread handling inside demo mode. -
Minor bug fixes Some other minor bugs and not working stuff was debugged with AI assistance, there were some issues with attachments, labels, and email rendering, and some more that I don't remember.
-
Documentation This README was partially generated by AI and then modified to ensure accuracy.
This project is licensed under the MIT License. See the LICENSE file for details.
