Metadata-Version: 2.4
Name: mixmail
Version: 2.0.0
Summary: A natural-language CLI agent for Gmail, powered by any OpenAI-compatible LLM (local or hosted).
License-Expression: MIT
Project-URL: Homepage, https://pypi.org/project/mixmail/
Project-URL: Source, https://github.com/your-org/MixMail
Project-URL: Issues, https://github.com/your-org/MixMail/issues
Keywords: gmail,email,llm,agent,cli,assistant,openai,tool-calling
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Communications :: Email
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: google-auth>=2.23.0
Requires-Dist: google-auth-oauthlib>=1.1.0
Requires-Dist: google-auth-httplib2>=0.1.1
Requires-Dist: google-api-python-client>=2.100.0
Requires-Dist: python-dotenv>=1.0.0
Requires-Dist: rich>=13.7.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: build>=1.0; extra == "dev"
Dynamic: license-file

# 📧 MixMail

**Talk to your Gmail in plain English.** MixMail is a command-line agent that
turns natural-language requests — "summarize the visa thread", "draft a reply
saying I'm available Friday", "archive this month's promotions" — into real
Gmail actions. It runs on **any OpenAI-compatible LLM**, local or hosted.

```bash
pip install mixmail
mixmail
```

```text
You ❯ what came in from recruiters this week, and star anything urgent
· Searching Gmail…
MixMail ▸
You have 3 recruiter emails this week:
  1. Amazon Recruiting — "ML Engineer, Seattle" (Tue) ★ starred
  2. Deloitte Talent — "Interview scheduling" (Mon)
  3. Stealth Startup — "Founding engineer" (Mon)
```

---

## What it can do

| Read | Organise | Compose |
|------|----------|---------|
| Natural-language search | Mark read / unread | Draft emails |
| Read full messages & bodies | Star / unstar | Send email *(confirmed)* |
| Summarise whole threads | Archive | Reply / reply-all *(confirmed)* |
| List labels | Move to Trash *(confirmed)* | |
| Download attachments | | |

- **Safety first.** Sending, replying, and trashing always show a preview and
  ask for confirmation. Gmail access defaults to **read-only** until you opt in
  to `full`.
- **Streaming.** Answers stream as they're generated, with live progress for
  each tool the agent runs.
- **Bring your own model.** Local (LM Studio, llama.cpp, Ollama, vLLM) or
  hosted (OpenAI, Groq, Together, OpenRouter). Use OpenRouter to run Claude or
  Gemini through the same interface.

## Install

```bash
pip install mixmail        # from PyPI
mixmail                    # first run launches a guided setup wizard
```

Or from source:

```bash
git clone <your-fork> && cd MixMail
pip install -e ".[dev]"
```

## Setup

On first launch MixMail walks you through setup. You can re-run it anytime with
`/wizard`. You'll need two things:

### 1. A language model

MixMail talks to an **OpenAI-compatible Chat Completions** endpoint.

- **Local** (no API key): start your server and use its base URL, e.g.
  `http://localhost:1200/v1`.
- **Hosted**: set the base URL and an API key, e.g. OpenAI
  (`https://api.openai.com/v1`), Groq, Together, or OpenRouter. For **Claude or
  Gemini**, use OpenRouter's base URL and a model id like
  `anthropic/claude-3.5-sonnet`.

Configure inside the app with `/llm_url`, `/model`, and `/api_key`.

### 2. Gmail credentials

1. In the [Google Cloud Console](https://console.cloud.google.com/), create a
   project and **enable the Gmail API**.
2. Configure the **OAuth consent screen** (add your address as a test user).
3. Create an **OAuth client ID** of type **Desktop app** and download the JSON.
4. In MixMail, run `/mail_creds` and paste the JSON or its file path.

On your first query MixMail opens a browser for Google sign-in and stores the
token automatically.

### Choosing access level

```text
/scope
```

- `readonly` *(default)* — search and read only.
- `full` — also send, reply, draft, label, archive, and trash.

Switching scope requires re-authenticating: delete the token shown in `/setup`
and sign in again.

## Commands

| Command | Action |
|---------|--------|
| *(plain text)* | Ask anything about your email |
| `help` | Show usage tips |
| `reset` | Clear conversation history |
| `/wizard` | Re-run guided setup |
| `/llm_url` · `/model` · `/api_key` | Configure the LLM |
| `/mail_creds` | Paste or import Google OAuth JSON |
| `/scope` | Switch between `readonly` and `full` |
| `/setup` | Show current config locations |
| `quit` | Exit |

## Configuration

All settings live in `~/.mixmail/.env` (or a `.env` in the working directory).
See [`.env.example`](.env.example). Key variables:

| Variable | Default | Purpose |
|----------|---------|---------|
| `LLM_BASE_URL` | `http://localhost:1200/v1` | OpenAI-compatible endpoint |
| `LLM_MODEL` | `qwen2.5-coder-1.5b-instruct` | Model id |
| `LLM_API_KEY` | *(empty)* | Key for hosted providers |
| `GMAIL_SCOPE_MODE` | `readonly` | `readonly` or `full` |
| `MAX_RESULTS` | `10` | Emails per search |

## How it works

```
You ──▶ mixmail CLI ──▶ EmailAgent ──▶ LLM (tool-calling)
                              │              │
                              │     tool calls (search, send, …)
                              ▼              ▼
                        confirmation     Gmail API
```

The agent sends your message plus tool descriptions to the model, runs whatever
tools the model requests (asking you first for destructive ones), feeds results
back, and repeats until it has a final answer — which it streams to you.

## Development

```bash
pip install -e ".[dev]"
python -m unittest discover -s tests -t .   # or: pytest
python -m build                              # build a wheel + sdist
```

The test suite stubs out Google and network access, so it runs anywhere without
touching your real inbox.

## Security notes

- MixMail runs entirely on your machine; your email and API key never leave it
  except to the LLM endpoint and Gmail you configure.
- `.env`, `token.json`, and `client_secret*.json` are git-ignored. Don't commit
  them. If you ever did, rotate the credentials.
- Read-only is the default. Grant `full` access only when you want MixMail to
  send or modify mail.

## License

MIT — see [LICENSE](LICENSE).
