Automate your digital life with natural language. PAI lets you create automations by describing what you want in plain English.
# Clone and install
git clone https://github.com/mhattingpete/personal-ai-os.git
cd personal-ai-os
uv sync# Initialize PAI (creates config and database)
uv run pai init
# Parse a natural language intent
uv run pai intent "Label emails from clients as Important"
# Connect to Gmail
uv run pai connect google
# Search your emails
uv run pai emails "has:attachment newer_than:7d"
# Discover clients from your emails
uv run pai entities --discoverInitialize PAI - creates configuration directory and database.
uv run pai initParse natural language into automation specs. This is the core of PAI - describe what you want and it figures out the trigger, conditions, and actions.
# Basic usage
uv run pai intent "When a client emails me with an invoice, save it to their folder"
# Generate full automation spec
uv run pai intent "Label emails from acme.com as Client" --plan
# Use local LLM (llama.cpp) instead of Claude
uv run pai intent "Archive newsletters older than 30 days" --local
# Save the automation to database
uv run pai intent "Forward urgent emails to Slack" --plan --saveOptions:
--plan, -p- Generate full automation specification--save, -s- Save automation to database--local, -l- Use local LLM (requires llama.cpp server)
Connect to external services via OAuth.
# Connect to Gmail
uv run pai connect google
# Force re-authentication
uv run pai connect google --forceGmail Setup:
- Go to Google Cloud Console
- Create a new project (or select existing)
- Enable the Gmail API
- Create OAuth 2.0 Client ID (Desktop application)
- Download the JSON file
- Save as
~/.config/pai/gmail_credentials.json - Run
pai connect google
Search emails using Gmail query syntax.
# Search by sender
uv run pai emails "from:client@example.com"
# Search with attachments
uv run pai emails "has:attachment filename:pdf"
# Recent emails with keyword
uv run pai emails "newer_than:7d subject:invoice"
# Show more results
uv run pai emails "is:unread" --max 20
# Include email body in output
uv run pai emails "from:boss@company.com" --bodyOptions:
--max, -m- Maximum results (default: 10)--body, -b- Show email body preview
Common Gmail Query Operators:
from:- Sender email or nameto:- Recipientsubject:- Subject line containshas:attachment- Has attachmentsfilename:- Attachment filenamenewer_than:Nd- Within last N daysolder_than:Nd- Older than N daysis:unread- Unread emailslabel:- Has specific label
Manage entities (clients, people, projects) discovered from your data.
# List all entities
uv run pai entities
# Filter by type
uv run pai entities --type client
uv run pai entities --type person
# Discover entities from recent emails
uv run pai entities --discover
# Limit results
uv run pai entities --limit 50Options:
--type, -t- Filter by type (client, person, project)--discover, -d- Scan recent emails to find new entities--limit, -l- Maximum results (default: 20)
List all automations.
# List all
uv run pai list
# Filter by status
uv run pai list --status active
uv run pai list --status draftShow PAI status (database, automations, connectors).
uv run pai statusView configuration.
# Show config directory
uv run pai config
# Show all settings
uv run pai config --showManage MCP (Model Context Protocol) servers. PAI uses MCP to connect to external services like Gmail.
# List configured MCP servers
uv run pai mcp list
# List servers with their available tools
uv run pai mcp list --tools
# Show details for a specific server
uv run pai mcp list --server gmail
# Call an MCP tool directly
uv run pai mcp call gmail search_emails --args '{"query": "is:unread", "max_results": 5}'Options for mcp list:
--tools, -t- Show available tools for each server--server, -s- Show details for a specific server
Options for mcp call:
--args, -a- JSON arguments for the tool
PAI stores configuration in ~/.config/pai/:
~/.config/pai/
├── config.yaml # Settings (optional)
├── mcp.json # MCP server configuration
├── gmail_credentials.json # Gmail OAuth client (from Google)
└── gmail_token.json # Gmail OAuth token (auto-generated)
ANTHROPIC_API_KEY- Claude API key (required for cloud LLM)
llm:
default: claude # or "local"
claude:
model: claude-sonnet-4-20250514
local:
url: http://localhost:8080
routing:
force_local: false
sensitive_domains:
- health
- finance
debug: falseConfigure MCP servers that PAI connects to for external services:
{
"servers": {
"gmail": {
"command": "uv",
"args": ["run", "--directory", "/path/to/personal-ai-os", "pai-gmail-mcp"],
"env": {}
},
"outlook": {
"command": "uv",
"args": ["run", "--directory", "/path/to/outlook-mcp", "python", "mcp_server.py"],
"env": {}
}
}
}Each server needs:
command- The executable to runargs- Command line argumentsenv- Environment variables (optional)
PAI supports local LLMs via llama.cpp's OpenAI-compatible API.
-
Start llama.cpp server:
./llama-server -m your-model.gguf --port 8080
-
Use
--localflag:uv run pai intent "Label emails from clients" --local
# 1. Connect Gmail
uv run pai connect google
# 2. Discover your clients
uv run pai entities --discover
# 3. Create automation
uv run pai intent "When acme.com emails me with an invoice PDF, label it as 'Acme Invoice'" --plan
# 4. Check the automation
uv run pai list# Find invoices from last month
uv run pai emails "subject:invoice newer_than:30d has:attachment"
# Find unread from specific sender
uv run pai emails "from:important@client.com is:unread"# Install with dev dependencies
uv sync --extra dev
# Run tests
uv run pytest
# Run specific test file
uv run pytest tests/test_gmail.py -vMIT