Pplx CLI
a macOS CLI and MCP server that controls the Perplexity Desktop App via Accessibility automation, turning your existing Pro subscription into a programmable search backend for Claude, OpenCode, and any other MCP client. A direct Sonar REST API backend is also included as a fallback.
Ask AI about Pplx CLI
Powered by Claude Β· Grounded in docs
I know everything about Pplx CLI. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
pplx
Drive your Perplexity Pro subscription as an MCP tool β the Desktop App does the searching, you pay nothing extra.
pplx is a macOS CLI and MCP server that controls the Perplexity Desktop App via Accessibility automation, turning your existing Pro subscription into a programmable search backend for Claude, OpenCode, and any other MCP client. A direct Sonar REST API backend is also included as a fallback.
https://github.com/user-attachments/assets/b4b4fc53-a6bd-4778-8f25-2946c61f7860
Quick Start
# 1. Build
git clone https://github.com/toby1991/pplx-cli
cd pplx-cli
make install # builds β /usr/local/bin/pplx
# 2. Grant Accessibility permission (one-time)
# System Settings β Privacy & Security β Accessibility β add your terminal app
# 3. Verify it works
pplx "what is MCP?"
# 4. Add to Claude Desktop or OpenCode (see MCP section below)
Headless Mac (Mac mini via SSH)? One extra step:
pplx setup-caffeinate # prevents sleep + disables screen lock β run once, persists across reboots
How It Works
Two backends, one binary:
| Backend | How | Cost | Speed |
|---|---|---|---|
| UI (default) | Controls Perplexity Desktop App via macOS AXUIElement API | Free β uses your Pro subscription | 10β30 s |
| API | Calls Perplexity Sonar REST API directly | $5/month free tier + API key | 2β5 s |
Two operation modes:
| Mode | Command | Use case |
|---|---|---|
| CLI | pplx "query" | Direct terminal use, scripts, pipes |
| MCP Server | pplx mcp | Tool calls from Claude, OpenCode, etc. |
CLI Usage
# Basic search
pplx "best practices for Go error handling"
# Specify model (name prefix β matches the UI model switcher)
pplx --model "Claude Sonnet" "explain monads"
# Specify content sources
pplx --sources web,academic "recent papers on RAG"
# Pipe in, pipe out
echo "what is entropy?" | pplx
pplx "top Go CLI libraries" --json | jq '.answer'
# Quiet mode β answer only, no citations
pplx -q "capital of France"
# Interactive REPL
pplx
Subcommands
pplx status # current mode/model (reads Perplexity UserDefaults)
pplx models # list available UI models
pplx sources # list content source categories
pplx dump # dump AX tree (diagnostic)
pplx version
# Headless Mac management
pplx setup-caffeinate # install caffeinate LaunchAgent + disable screen lock
pplx remove-caffeinate # uninstall
# API backend
pplx api "query" # search via REST API
pplx api --model sonar-reasoning "explain P=NP"
pplx api models # list API models
Output Formats
TTY β colored output with spinner:
β Searching...
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Go error handling best practices include wrapping errors...
Sources:
[1] Effective Go β https://go.dev/doc/effective_go
[2] Go Blog: Error handling β https://go.dev/blog/error-handling-and-go
ββββββββββββββββββββββββββββββββββββββββββββββββββββ
Pipe β plain text, no color or spinner.
JSON (--json):
{
"answer": "Go error handling best practices...",
"citations": [
{"index": 1, "title": "Effective Go", "url": "https://go.dev/doc/effective_go"}
],
"mode": "search",
"model": "sonar_pro"
}
MCP Server
pplx mcp exposes Perplexity as MCP tools over stdio.
Tools
| Tool | Description |
|---|---|
search | Search Perplexity β optional model and sources override |
list_models | List available models for the active backend |
list_sources | List content source categories (UI backend only) |
Backend Configuration
pplx mcp # UI only (default)
pplx mcp --primary api # API only
pplx mcp --primary ui --fallback api # UI primary, API fallback
pplx mcp --primary ui --fallback api \
--primary-model "GPT-5" \
--fallback-model sonar-pro
pplx mcp --sources web,academic # default sources for UI backend
OpenClaw
OpenClaw manages MCP servers through mcporter. Add the following entry to ~/.mcporter/mcporter.json:
{
"mcpServers": {
"pplx": {
"command": "/usr/local/bin/pplx",
"args": ["mcp", "--primary", "api", "--primary-model", "sonar",
"--fallback", "ui", "--fallback-model", "GPT-5",
"--sources", "web,academic,social"],
"env": {
"PERPLEXITY_API_KEY": "pplx-...",
"PPLX_PROMPT_SUFFIX": "..."
}
}
}
}
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"perplexity": {
"type": "stdio",
"command": "/usr/local/bin/pplx",
"args": ["mcp", "--primary", "ui", "--fallback", "api"],
"env": {
"PERPLEXITY_API_KEY": "pplx-..."
}
}
}
}
OpenCode
~/.config/opencode/opencode.json:
{
"mcp": {
"perplexity": {
"type": "stdio",
"command": "/usr/local/bin/pplx",
"args": ["mcp", "--primary", "ui", "--fallback", "api", "--primary-model", "GPT-5"],
"env": {
"PERPLEXITY_API_KEY": "pplx-..."
}
}
}
}
MCP Behaviors
- Search prompt suffix: In MCP mode, a system prompt is appended to each query, instructing Perplexity to search more deeply and return authoritative sources.
- Auto-launch: If Perplexity Desktop is not running, it is started automatically.
- NavigateToHome: Before each UI search, the app returns to the home page to start a clean thread.
- Caffeinate check: At startup, if using the UI backend, warns if
caffeinateis not running and suggestspplx setup-caffeinate.
Headless Mac Setup
Running on a Mac mini without a display (SSH / remote)?
# One command handles both sleep prevention and screen lock:
pplx setup-caffeinate
This does two things:
- Installs a LaunchAgent that runs
caffeinate -dimsuat login (auto-restarts, survives reboots) - Disables screen lock via
sysadminctl(requires your login password)
Why screen lock matters: when a remote session (VNC/SSH) disconnects, macOS triggers the lock screen. This degrades WindowServer to "application" mode β all AX automation calls return empty/stale data silently. Disabling screen lock prevents this.
Additional belt-and-suspenders steps for headless:
sudo pmset -a displaysleep 0 # belt-and-suspenders: disable display sleep via pmset
Display Settings
Two System Settings tweaks prevent the display from sleeping or locking while unattended:
| Setting | Path | Value |
|---|---|---|
| Turn off display when inactive | System Settings β Displays | Never |
| Require password after screensaver / display off | System Settings β Lock Screen | Never |
Virtual Display
Perplexity requires at least one display (physical or virtual). Options:
- Apple Remote Management (try this first) β Enabling Remote Management in System Settings β Sharing automatically exposes a virtual framebuffer on Apple Silicon Mac mini. No extra hardware needed.
- HDMI Dummy Plug β Plug a cheap HDMI dummy plug into the Mac mini's HDMI port. macOS sees it as a real display. Most reliable option if Remote Management doesn't work.
- BetterDisplay β BetterDisplay can create a software virtual display without any hardware. Useful when no physical HDMI port is available (e.g., Mac mini with only USB-C).
- Accessibility permission: Grant to the process running
pplxin System Settings β Privacy & Security β Accessibility.
Architecture
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β cmd/ β
β root.go mcp.go api.go caffeinate.go ... β
β Cobra CLI + MCP Server β
βββββββββββββββββββββ¬ββββββββββββββββββββββββββββββ
β
βββββββββββ΄βββββββββββ
β driver/ β
β search.go β β Dispatcher (primary/fallback)
β perplexity.go β β UI backend (AX automation)
β api.go β β API backend (Sonar REST)
βββββββββββ¬ββββββββββββ
β
βββββββββββ΄ββββββββββββ
β automation/ β
β ax.go (CGo) β
β ax.h (C header) β
β ax.m (Obj-C impl) β
β macOS AXUIElement β
ββββββββββββββββββββββββ
Search Flow β UI Backend
NavigateToHome() β click chevron-left if on results page
SetModel(model) β open model popover, select by prefix
SetSources(sources) β open sources popover, toggle checkboxes
Search(query)
β open perplexity-app://search?q=... URL scheme triggers search
β waitForButtonWithScroll("copy") poll for generation complete
β HasButton("checkbox") generating = true while present
β GetContentLength() track answer growth
β ScrollToBottom() handle virtualized viewport
β Click(copyBtn) + ReadClipboard() extract answer
β parseClipboardContent() parse answer + citations
Search Flow β API Backend
APISearch(apiKey, model, query)
β POST https://api.perplexity.ai/chat/completions
β parse response + citations
Project Structure
pplx-cli/
βββ main.go
βββ go.mod / go.sum
βββ Makefile
βββ README.md / README.zh.md
βββ cmd/
β βββ root.go # root command, flags, search dispatch
β βββ mcp.go # MCP server subcommand
β βββ api.go # API search subcommand
β βββ caffeinate.go # setup-caffeinate / remove-caffeinate
β βββ status.go
β βββ models.go
β βββ sources.go
β βββ dump.go # AX tree dump (diagnostic)
β βββ version.go
βββ driver/
β βββ perplexity.go # UI backend: Search, SetModel, SetSources, NavigateToHome
β βββ search.go # Dispatcher: primary/fallback routing
β βββ api.go # API backend: Sonar REST client
βββ automation/
β βββ ax.go # Go/CGo bindings
β βββ ax.h # C header
β βββ ax.m # Objective-C: AXUIElement implementation
βββ output/
β βββ format.go # TTY detection, spinner, colors, JSON
βββ docs/plans/ # Design documents
Requirements
- macOS (Apple Silicon or Intel)
- Go 1.23+
- Perplexity Desktop App (for UI backend)
- Accessibility permission granted to terminal / calling process (for UI backend)
PERPLEXITY_API_KEYenvironment variable (for API backend, optional)
Known Limitations
| Limitation | Detail |
|---|---|
| macOS only | Uses AXUIElement API β no cross-platform support |
| Serial execution | One UI search at a time (Perplexity App constraint) |
| Clipboard briefly overwritten | UI backend uses clipboard to read results; original content is restored after |
| Display required | UI backend needs at least one display (physical or virtual) |
| Accessibility permission required | Grant in System Settings β Privacy & Security β Accessibility |
License
MIT
