feat: move docs into monorepo, add deploy workflow

Consolidate documentation from the separate pocketpaw-web repo into the
main pocketpaw repo. This keeps docs and code in sync so PRs can update
both atomically.

- Remove docs/ from .gitignore
- Remove docs' own .git (was pocketpaw/pocketpaw-web)
- Add .github/workflows/deploy-docs.yml (builds from docs/ subdirectory)
- Track all 120+ MDX pages, config, landing page, and public assets

The separate pocketpaw-web repo can now be archived.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Rohit Kushwaha
2026-02-13 13:12:04 +05:30
parent 69b1f1634b
commit 4bb7313829
145 changed files with 19181 additions and 2 deletions

53
.github/workflows/deploy-docs.yml vendored Normal file
View File

@@ -0,0 +1,53 @@
name: Deploy Docs
on:
push:
branches: [main]
paths:
- "docs/**"
pull_request:
branches: [main]
paths:
- "docs/**"
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
- name: Build docs
run: npx --yes @litodocs/cli build -i ./docs
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: ./dist
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
if: github.ref == 'refs/heads/main'
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

3
.gitignore vendored
View File

@@ -46,8 +46,7 @@ htmlcov/
.tox/
.nox/
# Docs (internal/draft)
docs/
# Internal drafts
idocs/
.claude

103
docs/CLAUDE.md Normal file
View File

@@ -0,0 +1,103 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What This Is
This is the documentation site for PocketPaw, a self-hosted AI agent. The docs are 120+ MDX files consumed by an Astro-based static site generator. The built output lives in `../docs-dist/` (Astro SSG with Pagefind search and Partytown).
There is no `astro.config.*` or `package.json` in this repo — the Astro build tooling is external. The docs themselves are pure content (MDX + config JSON).
## Documentation Structure
All content is MDX (Markdown + JSX components). Every file has YAML frontmatter with `title` and `description`. API endpoint pages additionally have `api`, `baseUrl`, `layout`, and `auth` fields.
```
docs/
├── docs-config.json # Site metadata, nav, branding, search, SEO
├── _landing/ # Custom HTML/CSS/JS landing page (not MDX)
├── public/ # Static assets (logos, favicon SVGs)
├── introduction/ # 2 pages — welcome, why-pocketpaw
├── getting-started/ # 4 pages — install, quick-start, config, project structure
├── concepts/ # 6 pages — architecture, message bus, agent loop, memory, tools, security
├── channels/ # 10 pages — overview + 9 channel guides
├── backends/ # 4 pages — overview + 3 backend guides
├── tools/ # 14 pages — overview + 13 tool guides + custom tools
├── integrations/ # 9 pages — overview, OAuth, Gmail, Calendar, Drive, Docs, Spotify, Reddit, MCP
├── security/ # 6 pages — overview, Guardian AI, injection scanner, audit log/CLI/daemon
├── memory/ # 6 pages — overview, file store, mem0, sessions, context building, memory isolation
├── advanced/ # 7 pages — model router, plan mode, scheduler, skills, deep work, mission control, autonomous messaging
├── deployment/ # 3 pages — self-hosting, Docker, systemd
└── api/ # 51 pages — REST endpoint docs + WebSocket protocol + config reference
```
## MDX Components Used
The docs use custom Astro/MDX components (provided by the external build tooling, not defined here):
- `<Card>`, `<CardGroup>` — feature cards with icons and links
- `<Steps>`, `<Step>` — numbered step sequences
- `<Tabs>`, `<Tab>` — tabbed content blocks (used heavily in API docs for cURL/JS/Python examples)
- `<ResponseField>` — API response field documentation (supports nesting)
- `<RequestExample>`, `<ResponseExample>` — API example request/response blocks
- `<Callout>` — info/warning/tip callouts
Icon convention: Lucide icons referenced as `lucide:icon-name` strings.
## docs-config.json
Central configuration file controlling:
- **`metadata`** — site name, description, version
- **`branding`** — colors (primary `#0A84FF`, accent `#d49a5c`), fonts (Plus Jakarta Sans / JetBrains Mono), logos
- **`navigation.sidebar`** — 11 top-level sections defining the full sidebar tree. This is the source of truth for page ordering and hierarchy
- **`navigation.navbar`** — top nav links + Guides dropdown + GitHub star + CTA button
- **`seo`** — OG image, JSON-LD, canonical URLs, breadcrumbs
- **`search`** — local Pagefind search
- **`integrations`** — edit-on-GitHub links (`/edit/main/docs/{path}`), last-updated timestamps, feedback widget
When adding new pages, they must be added to the appropriate `navigation.sidebar` section in this file to appear in the sidebar.
## API Endpoint Pages
The endpoint pages in `api/` follow a strict pattern:
```mdx
---
title: Get Channel Status
description: ...
api: GET /api/channels/status
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
---
## Overview
...
## Response
<ResponseField name="..." type="...">...</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">...</Tab>
...
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">...</Tab>
</Tabs>
</ResponseExample>
```
## Key Conventions
- **Package name duality**: Internal Python package is `pocketclaw`, public-facing name in docs is `PocketPaw`. Import paths use `pocketclaw` (e.g., `from pocketclaw.tools.registry import ...`).
- **Channel count**: "9+" channels (Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Teams, Google Chat, Web Dashboard).
- **Tool count**: "50+" built-in tools across search, media, integrations, sessions, desktop, and coding categories.
- **Backend count**: 3 backends (Claude Agent SDK, PocketPaw Native, Open Interpreter).
- **`_images/` and `_assets/`**: Currently empty placeholder directories for future media.
- **Landing page**: `_landing/` is standalone HTML/CSS/JS, not MDX. Separate from the docs content pipeline.
- The legacy `../documentation/features/` directory has older markdown docs — the `docs/` MDX files are the canonical source.

88
docs/README.md Normal file
View File

@@ -0,0 +1,88 @@
# PocketPaw Documentation
The official documentation for [PocketPaw](https://github.com/pocketpaw/pocketpaw) — a self-hosted AI agent controlled via Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Teams, Google Chat, or a web dashboard.
**Live site:** [docs.pocketpaw.xyz](https://docs.pocketpaw.xyz)
## Stack
Built with [Lito Docs](https://lito.rohitk06.in) — an open-source tool that converts Markdown/MDX into beautiful, searchable documentation sites with zero configuration. Lito provides the Astro-based SSG, Pagefind search, 20+ MDX components, and light/dark theming out of the box.
## Structure
```
docs/
├── docs-config.json # Site config (nav, branding, SEO, search)
├── _landing/ # Custom HTML/CSS landing page
├── public/ # Static assets (logos, OG images)
├── introduction/ # Welcome & overview
├── getting-started/ # Install, quick-start, config, project structure
├── concepts/ # Architecture, message bus, agent loop, memory, tools, security
├── channels/ # 9+ channel guides (Telegram, Discord, Slack, WhatsApp, etc.)
├── backends/ # Claude Agent SDK, PocketPaw Native, Open Interpreter
├── tools/ # 50+ built-in tools
├── integrations/ # OAuth, Gmail, Calendar, Drive, Docs, Spotify, Reddit, MCP
├── security/ # Guardian AI, injection scanner, audit log/CLI/daemon
├── memory/ # File store, Mem0, sessions, context building, isolation
├── advanced/ # Model router, plan mode, scheduler, skills, Deep Work, Mission Control
├── deployment/ # Self-hosting, Docker, systemd
└── api/ # 39 REST endpoint docs + WebSocket protocol
```
## Local Development
No `package.json` or Astro config needed — Lito handles everything.
### Preview
```bash
npx --yes @litodocs/cli dev -i .
```
### Build
```bash
npx --yes @litodocs/cli build -i .
```
Output goes to `./dist/`.
## Deployment
The site auto-deploys to GitHub Pages on push to `main` via the workflow in `.github/workflows/deploy-docs.yml`.
To deploy manually, build and upload the `dist/` folder to any static hosting provider (Vercel, Netlify, Cloudflare Pages, etc.).
## Adding Pages
1. Create an `.mdx` file in the appropriate directory with YAML frontmatter:
```mdx
---
title: Page Title
description: "A 150-160 character description with front-loaded keywords."
section: Section Name
ogType: article
keywords: ["keyword1", "keyword2", "keyword3"]
tags: ["tag1", "tag2"]
---
Content here...
```
2. Add the page to the `navigation.sidebar` array in `docs-config.json`.
## MDX Components
Provided by Lito — no local definitions needed:
| Component | Usage |
|---|---|
| `<Card>`, `<CardGroup>` | Feature cards with icons and links |
| `<Steps>`, `<Step>` | Numbered step sequences |
| `<Tabs>`, `<Tab>` | Tabbed content blocks |
| `<Callout>` | Info/warning/tip callouts |
| `<ResponseField>` | API field documentation |
| `<RequestExample>`, `<ResponseExample>` | API example blocks |
## License
MIT

3878
docs/_landing/index.html Normal file

File diff suppressed because it is too large Load Diff

244
docs/_landing/og-image.html Normal file
View File

@@ -0,0 +1,244 @@
<!-- OG Social Sharing Image — 2026-02-08
1200x630 screenshot target for Twitter/LinkedIn link previews.
Open in browser, screenshot the card. Matches "Denim & Honey" landing page design.
Updated: fixed logo stretch (object-fit contain), matched Pocket+Paw italic style,
added WhatsApp channel, single-color faded top accent. -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>PocketPaw OG Image</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300..900;1,9..144,300..900&family=Plus+Jakarta+Sans:wght@300;400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
background: #e0ddd8;
font-family: 'Plus Jakarta Sans', -apple-system, sans-serif;
-webkit-font-smoothing: antialiased;
}
.card {
width: 1200px;
height: 630px;
background: #f9f8f6;
position: relative;
overflow: hidden;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0;
}
/* Dot grid texture */
.card::before {
content: '';
position: absolute;
inset: 0;
background-image: radial-gradient(rgba(26,26,46,0.05) 1px, transparent 1px);
background-size: 24px 24px;
pointer-events: none;
z-index: 0;
}
.card > * { position: relative; z-index: 1; }
/* Soft faded blue top accent */
.accent-top {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 4px;
background: linear-gradient(90deg, transparent 0%, #4a6fa5 30%, #4a6fa5 70%, transparent 100%);
opacity: 0.5;
}
/* Mascot image */
.mascot {
width: auto;
height: 200px;
object-fit: contain;
margin-bottom: 16px;
filter: drop-shadow(0 12px 32px rgba(80,60,30,0.15));
}
/* Brand name — matches landing page: Pocket (regular) + Paw (italic blue) */
.brand-name {
font-family: 'Fraunces', Georgia, serif;
font-size: 64px;
font-weight: 400;
color: #1a1a2e;
letter-spacing: -0.04em;
line-height: 1;
margin-bottom: 12px;
}
.brand-name em {
font-style: italic;
color: #4a6fa5;
}
/* Tagline */
.tagline {
font-size: 20px;
font-weight: 300;
color: #5c5c7a;
letter-spacing: 0.01em;
text-align: center;
margin-bottom: 24px;
}
/* Install command pill */
.install {
display: inline-flex;
align-items: center;
gap: 10px;
background: #1a1a2e;
color: #e8eef6;
font-family: 'JetBrains Mono', monospace;
font-size: 17px;
font-weight: 400;
padding: 12px 28px;
border-radius: 100px;
letter-spacing: 0.02em;
margin-bottom: 28px;
}
.install .prompt {
color: #d49a5c;
user-select: none;
}
/* Channel row */
.channels {
display: flex;
align-items: center;
gap: 16px;
}
.channel {
display: flex;
align-items: center;
gap: 7px;
font-size: 13px;
font-weight: 500;
color: #5c5c7a;
background: #ffffff;
border: 1px solid rgba(26,26,46,0.07);
border-radius: 100px;
padding: 7px 16px;
box-shadow: 0 1px 3px rgba(26,26,46,0.04);
}
.channel svg {
width: 16px;
height: 16px;
flex-shrink: 0;
}
/* Bottom bar */
.bottom {
position: absolute;
bottom: 0;
left: 0;
right: 0;
display: flex;
align-items: center;
justify-content: space-between;
padding: 14px 40px;
background: rgba(255,255,255,0.5);
border-top: 1px solid rgba(26,26,46,0.04);
}
.bottom-left {
display: flex;
align-items: center;
gap: 18px;
font-size: 12px;
font-weight: 500;
color: #9b9bb0;
letter-spacing: 0.06em;
text-transform: uppercase;
}
.bottom-left .dot {
width: 3px;
height: 3px;
border-radius: 50%;
background: #9b9bb0;
opacity: 0.4;
}
.bottom-right {
font-size: 12px;
font-weight: 600;
color: #4a6fa5;
letter-spacing: 0.04em;
}
</style>
</head>
<body>
<div class="card">
<div class="accent-top"></div>
<img src="./paw.png" alt="PocketPaw mascot" class="mascot">
<h1 class="brand-name">Pocket<em>Paw</em></h1>
<p class="tagline">Your AI agent. Modular. Secure. Everywhere.</p>
<div class="install">
<span class="prompt">$</span> curl -fsSL https://pocketpaw.xyz/install.sh | sh
</div>
<div class="channels">
<!-- Telegram -->
<div class="channel">
<svg viewBox="0 0 24 24" fill="#4a6fa5"><path d="M11.944 0A12 12 0 000 12a12 12 0 0012 12 12 12 0 0012-12A12 12 0 0012 0a12 12 0 00-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 01.171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.479.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z"/></svg>
Telegram
</div>
<!-- Discord -->
<div class="channel">
<svg viewBox="0 0 24 24" fill="#4a6fa5"><path d="M20.317 4.37a19.791 19.791 0 00-4.885-1.515.074.074 0 00-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 00-5.487 0 12.64 12.64 0 00-.617-1.25.077.077 0 00-.079-.037A19.736 19.736 0 003.677 4.37a.07.07 0 00-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 00.031.057 19.9 19.9 0 005.993 3.03.078.078 0 00.084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 00-.041-.106 13.107 13.107 0 01-1.872-.892.077.077 0 01-.008-.128c.126-.094.252-.192.372-.292a.074.074 0 01.077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 01.078.01c.12.098.246.198.373.292a.077.077 0 01-.006.127 12.299 12.299 0 01-1.873.892.077.077 0 00-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 00.084.028 19.839 19.839 0 006.002-3.03.077.077 0 00.032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 00-.031-.03z"/></svg>
Discord
</div>
<!-- Slack -->
<div class="channel">
<svg viewBox="0 0 24 24" fill="#4a6fa5"><path d="M5.042 15.165a2.528 2.528 0 01-2.52 2.523A2.528 2.528 0 010 15.165a2.527 2.527 0 012.522-2.52h2.52v2.52zm1.271 0a2.527 2.527 0 012.521-2.52 2.527 2.527 0 012.521 2.52v6.313A2.528 2.528 0 018.834 24a2.528 2.528 0 01-2.521-2.522v-6.313zM8.834 5.042a2.528 2.528 0 01-2.521-2.52A2.528 2.528 0 018.834 0a2.528 2.528 0 012.521 2.522v2.52H8.834zm0 1.271a2.528 2.528 0 012.521 2.521 2.528 2.528 0 01-2.521 2.521H2.522A2.528 2.528 0 010 8.834a2.528 2.528 0 012.522-2.521h6.312zm10.122 2.521a2.528 2.528 0 012.522-2.521A2.528 2.528 0 0124 8.834a2.528 2.528 0 01-2.522 2.521h-2.522V8.834zm-1.268 0a2.528 2.528 0 01-2.523 2.521 2.527 2.527 0 01-2.52-2.521V2.522A2.527 2.527 0 0115.165 0a2.528 2.528 0 012.523 2.522v6.312zm-2.523 10.122a2.528 2.528 0 012.523 2.522A2.528 2.528 0 0115.165 24a2.527 2.527 0 01-2.52-2.522v-2.522h2.52zm0-1.268a2.527 2.527 0 01-2.52-2.523 2.526 2.526 0 012.52-2.52h6.313A2.527 2.527 0 0124 15.165a2.528 2.528 0 01-2.522 2.523h-6.313z"/></svg>
Slack
</div>
<!-- WhatsApp -->
<div class="channel">
<svg viewBox="0 0 24 24" fill="#4a6fa5"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/></svg>
WhatsApp
</div>
<!-- Web -->
<div class="channel">
<svg viewBox="0 0 24 24" fill="none" stroke="#4a6fa5" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="14" rx="2" ry="2"/><line x1="8" y1="21" x2="16" y2="21"/><line x1="12" y1="17" x2="12" y2="21"/></svg>
Web
</div>
</div>
<div class="bottom">
<div class="bottom-left">
<span>Open Source</span>
<span class="dot"></span>
<span>MIT Licensed</span>
<span class="dot"></span>
<span>Python 3.11+</span>
<span class="dot"></span>
<span>30-Second Install</span>
</div>
<div class="bottom-right">github.com/pocketpaw</div>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 KiB

14
docs/_landing/robots.txt Normal file
View File

@@ -0,0 +1,14 @@
# robots.txt — PocketPaw landing page (pocketpaw.xyz)
# Allow legitimate crawlers, block common scanner paths
User-agent: *
Allow: /
Disallow: /wp-admin/
Disallow: /wp-login.php
Disallow: /wordpress/
Disallow: /.env
Disallow: /admin/
Disallow: /cmd_sco
Disallow: /serverConfig.json
Sitemap: https://pocketpaw.xyz/sitemap.xml

View File

@@ -0,0 +1,140 @@
---
title: Autonomous Messaging
description: "PocketPaw can send messages proactively using scheduled intentions with cron triggers. The Proactive Daemon orchestrates agent behaviors and delivers results to any configured notification channel."
section: Advanced
ogType: article
keywords: ["autonomous messaging", "proactive daemon", "scheduled intentions", "cron triggers", "notifications"]
tags: ["advanced", "automation", "notifications"]
---
# Autonomous Messaging
PocketPaw can send messages proactively — without waiting for user input. This is powered by three components: the **Proactive Daemon** (orchestrator), **Intentions** (scheduled behaviors), and the **Channel Notifier** (delivery).
## How It Works
```
┌─────────────────────────────────┐
│ Proactive Daemon │
│ (orchestrates intentions) │
├──────────┬──────────────────────┤
│ Trigger │ Intention │
│ Engine │ Executor │
│ (cron) │ (runs agent) │
└────┬─────┴──────────┬───────────┘
│ │
▼ ▼
APScheduler Channel Notifier
fires trigger → delivers to channels
```
## Intentions
An intention is a scheduled agent behavior — a prompt that runs on a trigger.
### Intention Schema
| Field | Type | Description |
|-------|------|-------------|
| `name` | string | Human-readable name (e.g., "Morning Standup") |
| `prompt` | string | The prompt to send to the agent |
| `trigger` | object | When to fire (cron schedule) |
| `context_sources` | array | Additional context to inject (e.g., `system_status`) |
| `enabled` | boolean | Whether the intention is active |
### Creating Intentions
```
User: Every weekday at 8 AM, check my calendar and summarize today's meetings
Agent: Created intention "Daily Calendar Brief" — triggers Mon-Fri at 8:00 AM
```
### Trigger Types
Currently supports cron triggers with standard 5-field expressions:
```
minute hour day month day_of_week
0 8 * * 1-5 (weekdays at 8 AM)
```
Common presets are available:
| Preset | Schedule |
|--------|----------|
| `every_minute` | `* * * * *` |
| `every_5_minutes` | `*/5 * * * *` |
| `every_hour` | `0 * * * *` |
| `every_morning_8am` | `0 8 * * *` |
| `weekday_morning_8am` | `0 8 * * 1-5` |
| `daily_noon` | `0 12 * * *` |
| `weekly_monday_9am` | `0 9 * * 1` |
| `monthly_first_9am` | `0 9 1 * *` |
### Intention Lifecycle
1. **Create** — Define name, prompt, trigger, and context sources
2. **Schedule** — Trigger engine registers the cron job
3. **Fire** — When the trigger fires, the executor runs the agent with the prompt
4. **Deliver** — Results are streamed to the dashboard and optionally pushed to channels
5. **Repeat** — The trigger re-schedules for the next occurrence
## Channel Notifier
The notifier delivers messages to any configured channel without user interaction.
### Configuration
Set notification targets in settings as `"channel:chat_id"` strings:
```bash
export POCKETCLAW_NOTIFICATION_CHANNELS='["telegram:123456789","discord:987654321","slack:C0A1B2C3D"]'
```
Supported channel formats:
| Format | Example |
|--------|---------|
| `telegram:{chat_id}` | `telegram:123456789` |
| `discord:{channel_id}` | `discord:987654321` |
| `slack:{channel_id}` | `slack:C0A1B2C3D` |
| `whatsapp:{phone}` | `whatsapp:+1234567890` |
| `signal:{phone}` | `signal:+1234567890` |
| `matrix:{room_id}` | `matrix:!abc:matrix.org` |
| `teams:{conversation_id}` | `teams:19:abc@thread.v2` |
| `gchat:{space}` | `gchat:spaces/abc123` |
### Usage Points
The notifier is called by:
- **Scheduler** — When reminders trigger
- **Proactive Daemon** — When intentions execute
- **Deep Work** — Human task notifications and project completion alerts
- **Dashboard** — Broadcast messages
## Owner ID
Set the `owner_id` to identify yourself. This enables the memory system to distinguish between your messages and those from other users on shared channels.
```bash
export POCKETCLAW_OWNER_ID="your_telegram_user_id"
```
## Persistence
- Intentions are stored in `~/.pocketclaw/intentions.json`
- Notification channel targets are stored in config
- The daemon reloads all intentions on startup and re-schedules triggers
## Dashboard Integration
The web dashboard provides:
- View and manage all intentions
- Toggle intentions on/off
- Trigger an intention manually
- See next scheduled run time
- Stream execution results in real time
<Callout type="tip">
Combine autonomous messaging with [Gmail](/integrations/gmail) and [Calendar](/integrations/calendar) tools for powerful automated workflows. For example: "Every morning at 8 AM, check my calendar and email, then send a Telegram summary."
</Callout>

172
docs/advanced/deep-work.mdx Normal file
View File

@@ -0,0 +1,172 @@
---
title: Deep Work
description: "Deep Work is PocketPaw's AI-powered project orchestrator: describe a project and it researches the domain, writes a PRD, decomposes tasks with dependencies, assembles an agent team, and executes autonomously."
section: Advanced
ogType: article
keywords: ["deep work", "project planning", "task decomposition", "multi-agent", "autonomous execution", "prd"]
tags: ["advanced", "orchestration", "multi-agent"]
---
# Deep Work
Deep Work is PocketPaw's orchestration system for complex, multi-step projects. Describe what you want to build, and PocketPaw researches the domain, writes a product requirements document, breaks it into tasks with dependencies, assembles an agent team, and executes everything autonomously.
## How It Works
<Steps>
<Step title="Describe Your Project">
Provide a natural-language description of what you want to build or accomplish.
</Step>
<Step title="AI Research & Planning">
The planner agent researches the domain, writes a PRD, decomposes the project into atomic tasks, and recommends an agent team.
</Step>
<Step title="Review & Approve">
Review the generated plan — tasks, dependencies, time estimates, and team — in the dashboard. Approve when ready.
</Step>
<Step title="Autonomous Execution">
Tasks execute in dependency order. Agent tasks run via Claude, human tasks notify you for manual completion. Progress streams in real time.
</Step>
<Step title="Completion">
When all tasks finish, the project is marked complete and deliverables are saved to disk.
</Step>
</Steps>
## Project Lifecycle
| Status | Description |
|--------|-------------|
| `DRAFT` | Project created, not yet planned |
| `PLANNING` | Planner agent is researching and decomposing tasks |
| `AWAITING_APPROVAL` | Plan ready for user review |
| `APPROVED` | User approved, ready to execute |
| `EXECUTING` | Tasks are running |
| `PAUSED` | Execution paused by user |
| `COMPLETED` | All tasks finished |
| `FAILED` | Planning or execution error |
## Planning Phases
The planner runs four sequential phases, each broadcasting progress events to the dashboard:
### 1. Research
Gathers domain knowledge before planning. Controlled by `research_depth`:
| Depth | Behavior |
|-------|----------|
| `none` | Skip research entirely |
| `quick` | Minimal analysis from existing knowledge, no web search |
| `standard` | Balanced research, may use web search |
| `deep` | Thorough research with extensive web searching |
### 2. Product Requirements Document (PRD)
Generates a structured PRD with:
- Problem statement
- Scope (in/out)
- Functional requirements
- Non-goals
- Technical constraints
### 3. Task Breakdown
Decomposes the PRD into atomic tasks. Each task includes:
| Field | Description |
|-------|-------------|
| `key` | Short unique identifier (e.g., `t1`, `t2`) |
| `title` | Human-readable name |
| `description` | Full description with acceptance criteria |
| `task_type` | `agent`, `human`, or `review` |
| `priority` | `low`, `medium`, `high`, or `urgent` |
| `estimated_minutes` | Time estimate (15-120 min range) |
| `required_specialties` | Skills needed (e.g., `backend`, `frontend`) |
| `blocked_by_keys` | Dependencies on other tasks |
### 4. Team Assembly
Recommends the minimal set of AI agents needed. Each agent has a name, role, specialties, and backend. Agents are auto-assigned to tasks based on specialty overlap.
## Dependency Scheduling
Tasks execute in dependency order using a topological sort (Kahn's algorithm):
- Tasks with no blockers run first (concurrently)
- When a task completes, newly unblocked tasks dispatch automatically
- The scheduler validates the dependency graph for cycles and missing references before execution
```
Level 0: [t1, t2] ← no dependencies, run in parallel
Level 1: [t3, t4] ← depend only on level 0
Level 2: [t5] ← depends on level 1
```
## Task Types
| Type | Execution |
|------|-----------|
| `agent` | Runs via the agent backend (Claude Agent SDK). Output saved as deliverable document. |
| `human` | Notification sent to your channels. You complete it manually and mark done in the dashboard. |
| `review` | Quality gate — agent output is ready for your review before dependents proceed. |
## Usage
### Starting a Project
```
User: Start a deep work project to build a REST API for a recipe management app
Agent: Starting Deep Work project... researching domain, writing PRD, decomposing tasks.
```
Or via the REST API:
```bash
curl -X POST http://localhost:8000/api/deep-work/start \
-H "Content-Type: application/json" \
-d '{"description": "Build a REST API for recipe management", "research_depth": "standard"}'
```
### Reviewing the Plan
The dashboard shows:
- The generated PRD
- Task list with dependencies visualized as execution levels
- Estimated total time
- Recommended agent team
### Controlling Execution
| Action | API Endpoint |
|--------|-------------|
| Approve plan | `POST /api/deep-work/projects/{id}/approve` |
| Pause execution | `POST /api/deep-work/projects/{id}/pause` |
| Resume execution | `POST /api/deep-work/projects/{id}/resume` |
| Skip a task | `POST /api/deep-work/projects/{id}/tasks/{task_id}/skip` |
Skipping a task marks it as `SKIPPED` and unblocks dependents.
## Project Directories
Each project gets a working directory at `~/pocketpaw-projects/{project_id}/`. Agent tasks execute within this directory, and deliverables are saved there.
## Recovery
If the server restarts during execution:
- Projects stuck in `PLANNING` are marked `FAILED`
- Projects in `EXECUTING` have their in-progress tasks reset and re-dispatched
## WebSocket Events
The dashboard receives real-time updates:
| Event | When |
|-------|------|
| `dw_planning_phase` | Each planning phase starts (research, prd, tasks, team) |
| `dw_planning_complete` | Planning finishes or fails |
| `mc_task_started` | A task begins executing |
| `mc_task_output` | Agent produces output (streamed) |
| `mc_task_completed` | A task finishes |
<Callout type="info">
Deep Work builds on top of [Mission Control](/advanced/mission-control) for task storage, agent management, and the execution engine. The two systems are designed to work together.
</Callout>

View File

@@ -0,0 +1,159 @@
---
title: Mission Control
description: "Mission Control is PocketPaw's multi-agent task management framework: create AI agent teams, assign tasks with dependencies, track progress via activity feeds, and stream execution results in real time."
section: Advanced
ogType: article
keywords: ["mission control", "multi-agent", "task management", "agent orchestration", "team management"]
tags: ["advanced", "orchestration", "multi-agent"]
---
# Mission Control
Mission Control is PocketPaw's internal framework for managing AI agents, tasks, documents, and activities. It provides the execution backbone for [Deep Work](/advanced/deep-work) and can also be used directly via the REST API for custom multi-agent workflows.
## Core Concepts
### Agents
An `AgentProfile` represents a virtual team member with a name, role, specialties, and backend configuration.
| Field | Description |
|-------|-------------|
| `name` | Agent name (e.g., `backend-dev`) |
| `role` | Job title (e.g., `Backend Engineer`) |
| `specialties` | Skills like `["backend", "database", "api"]` |
| `backend` | Agent backend (default: `claude_agent_sdk`) |
| `status` | `IDLE`, `ACTIVE`, `BLOCKED`, or `OFFLINE` |
| `level` | `INTERN` (needs approval), `SPECIALIST` (independent), `LEAD` (full autonomy) |
### Tasks
Tasks track units of work with status, priority, dependencies, and assignees.
| Status | Description |
|--------|-------------|
| `INBOX` | New, unassigned |
| `ASSIGNED` | Has owner(s), not yet started |
| `IN_PROGRESS` | Being worked on |
| `REVIEW` | Done, awaiting approval |
| `DONE` | Completed |
| `BLOCKED` | Waiting on something |
| `SKIPPED` | Manually skipped |
Tasks support dependency chains via `blocked_by` (IDs of tasks that must complete first) and `blocks` (IDs of tasks waiting on this one).
### Documents
Documents store deliverables, research notes, and protocols. Types: `DELIVERABLE`, `RESEARCH`, `PROTOCOL`, `TEMPLATE`, `DRAFT`. Documents are auto-versioned on update.
### Messages & Notifications
Tasks have threaded message boards. Messages support `@mentions` — mentioning an agent by name (e.g., `@backend-dev`) creates a notification for that agent. Use `@all` to notify everyone.
### Activity Feed
All changes (task creation, status updates, messages, heartbeats) generate activity entries for a full audit trail.
## Task Execution
When a task is dispatched for execution:
1. A dedicated `AgentRouter` is created with the assigned agent's backend
2. The task prompt is built with agent identity, project context, PRD, and upstream deliverables
3. The agent streams output via the router
4. Output is broadcast as `mc_task_output` WebSocket events
5. On completion, the output is saved as a `DELIVERABLE` document
6. The scheduler callback fires to unblock dependent tasks
Up to 5 tasks can run concurrently. Double-dispatch is prevented by a background launch guard.
## Heartbeat System
The `HeartbeatDaemon` periodically checks agent status using APScheduler:
- Default interval: 15 minutes
- Checks for unread notifications and assigned tasks
- Updates agent status (`ACTIVE` if urgent work, `IDLE` otherwise)
- Agents are woken up with 2-second stagger to avoid thundering herd
## REST API
Mission Control exposes a full CRUD API at `/api/mission-control`.
### Agent Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/agents` | List agents (filter by status) |
| `POST` | `/agents` | Create agent |
| `GET` | `/agents/{id}` | Get agent details |
| `PATCH` | `/agents/{id}` | Update agent |
| `DELETE` | `/agents/{id}` | Delete agent |
| `POST` | `/agents/{id}/heartbeat` | Record heartbeat |
### Task Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/tasks` | List tasks (filter by status, assignee, tags) |
| `POST` | `/tasks` | Create task |
| `GET` | `/tasks/{id}` | Get task with messages |
| `PATCH` | `/tasks/{id}` | Update task |
| `DELETE` | `/tasks/{id}` | Delete task |
| `POST` | `/tasks/{id}/assign` | Assign to agents |
| `POST` | `/tasks/{id}/status` | Update status |
| `POST` | `/tasks/{id}/run` | Execute with agent (background) |
| `POST` | `/tasks/{id}/stop` | Stop running task |
| `GET` | `/tasks/running` | List currently executing tasks |
### Message & Document Endpoints
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/tasks/{id}/messages` | Get task messages |
| `POST` | `/tasks/{id}/messages` | Post message (auto-detects @mentions) |
| `GET` | `/tasks/{id}/documents` | Get task documents |
| `GET` | `/documents` | List all documents |
| `POST` | `/documents` | Create document |
| `PATCH` | `/documents/{id}` | Update document (auto-increments version) |
### Activity & Reports
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/activity` | Activity feed (filter by agent/task) |
| `GET` | `/stats` | Counts by status for all entities |
| `GET` | `/standup` | Generated standup report (markdown) |
| `GET` | `/notifications` | List notifications |
## Storage
Mission Control uses file-based JSON storage at `~/.pocketclaw/mission_control/`:
```
mission_control/
├── agents.json
├── tasks.json
├── messages.json
├── activities.json
├── documents.json
├── notifications.json
└── projects.json
```
All writes use atomic temp-file-then-rename for crash safety. The storage backend is protocol-based (`MissionControlStoreProtocol`), so it can be swapped for SQLite, Postgres, or any other backend.
## WebSocket Events
Real-time updates for the dashboard:
| Event | Payload |
|-------|---------|
| `mc_task_started` | `task_id`, `agent_id`, `agent_name`, `task_title` |
| `mc_task_output` | `task_id`, `content`, `output_type` (message/tool_use/tool_result) |
| `mc_task_completed` | `task_id`, `agent_id`, `status`, `error` |
| `mc_activity_created` | Full activity object |
<Callout type="info">
Mission Control is the execution engine behind [Deep Work](/advanced/deep-work). Deep Work adds the planning layer (research, PRD, task breakdown, team assembly) on top of Mission Control's task management.
</Callout>

View File

@@ -0,0 +1,56 @@
---
title: Model Router
description: "PocketPaw's model router automatically classifies message complexity as SIMPLE, MODERATE, or COMPLEX using heuristic signals, then selects the optimal model size to balance cost and capability."
section: Advanced
ogType: article
keywords: ["model router", "automatic model selection", "complexity classification", "cost optimization"]
tags: ["advanced", "optimization"]
---
# Model Router
The Model Router automatically selects the appropriate model size based on message complexity, optimizing cost and latency.
## How It Works
The router classifies each message into one of three complexity levels:
| Level | Description | Typical Model |
|-------|-------------|---------------|
| `SIMPLE` | Greetings, simple questions, short responses | Smaller/faster model |
| `MODERATE` | Multi-step tasks, moderate reasoning | Default model |
| `COMPLEX` | Coding, deep analysis, multi-tool chains | Largest model |
## Classification Heuristics
The router uses several signals to determine complexity:
1. **Message length** — Longer messages tend to be more complex
2. **Keyword detection** — Certain words indicate complexity:
- Code-related: "write code", "debug", "refactor", "implement"
- Analysis: "analyze", "compare", "explain in detail"
- Multi-step: "step by step", "plan", "research"
3. **Tool mentions** — References to specific tools suggest higher complexity
4. **Question depth** — Follow-up questions in a chain indicate growing complexity
### Threshold
A message is classified as COMPLEX if it has at least 1 complex signal AND is longer than 30 characters.
## Configuration
The model router is used automatically when enabled. It works with the Claude Agent SDK and PocketPaw Native backends.
## Example Classifications
| Message | Classification |
|---------|---------------|
| "Hi!" | SIMPLE |
| "What time is it?" | SIMPLE |
| "Write a Python web scraper that handles pagination" | COMPLEX |
| "Analyze the performance of my database queries" | COMPLEX |
| "Search for news about AI" | MODERATE |
<Callout type="info">
The model router is a heuristic system. For most users, the default model selection works well without the router. Enable it if you want to optimize API costs.
</Callout>

View File

@@ -0,0 +1,75 @@
---
title: Plan Mode
description: "Plan Mode adds a structured approval workflow to PocketPaw: the agent proposes a multi-step plan, you review it in the dashboard, approve or modify, then the agent executes with full transparency."
section: Advanced
ogType: article
keywords: ["plan mode", "approval workflow", "structured planning", "user consent", "step-by-step"]
tags: ["advanced", "workflow"]
---
# Plan Mode
Plan Mode enables a structured planning workflow where the agent creates a plan and waits for user approval before executing.
## How It Works
<Steps>
<Step title="User requests a complex task">
The agent determines the task requires planning (multiple steps, significant changes).
</Step>
<Step title="Agent creates a plan">
A structured plan is generated with numbered steps, estimated actions, and any risks.
</Step>
<Step title="Plan is presented for approval">
The plan is displayed in a modal in the web dashboard, or as a formatted message in other channels.
</Step>
<Step title="User approves or modifies">
The user can approve the plan, request changes, or reject it entirely.
</Step>
<Step title="Agent executes">
Once approved, the agent executes the plan step by step, reporting progress.
</Step>
</Steps>
## Dashboard Integration
In the web dashboard, Plan Mode uses a dedicated modal:
- **Plan display** — Formatted markdown with steps
- **Approve button** — Green button to approve and start execution
- **Reject button** — Red button to cancel
- **Modify** — Text input to request changes
## WebSocket Protocol
Plan Mode uses WebSocket messages:
```json
// Agent sends plan for approval
{"type": "plan_created", "plan": "## Plan\n1. Step one\n2. Step two"}
// User approves
{"type": "plan_response", "action": "approve"}
// User rejects
{"type": "plan_response", "action": "reject", "reason": "Too risky"}
// User requests modification
{"type": "plan_response", "action": "modify", "feedback": "Add error handling"}
```
## When Plan Mode Activates
Plan Mode is triggered for tasks that:
- Involve multiple file modifications
- Require irreversible system changes
- Include complex multi-step workflows
- The agent determines would benefit from user review
## Use Cases
- **Refactoring code** — Review planned changes before execution
- **System administration** — Approve infrastructure changes
- **Multi-file edits** — Verify scope before modifying many files
- **Research workflows** — Approve the research strategy

View File

@@ -0,0 +1,75 @@
---
title: Cron Scheduler
description: "PocketPaw's built-in cron scheduler handles recurring tasks and one-time reminders with APScheduler. Tasks persist across restarts, support natural language time parsing, and auto-reschedule after execution."
section: Advanced
ogType: article
keywords: ["cron scheduler", "recurring tasks", "reminders", "apscheduler", "task scheduling"]
tags: ["advanced", "automation"]
---
# Cron Scheduler
PocketPaw includes a built-in task scheduler for recurring reminders and scheduled actions.
## Features
- **Recurring tasks** — Schedule tasks with cron-like expressions
- **Persistence** — Recurring tasks survive restarts
- **Re-scheduling** — Tasks automatically re-schedule after execution
- **Management** — Add and delete recurring tasks via tools
## How It Works
The scheduler is built on APScheduler and manages two types of tasks:
### One-time Reminders
```
User: Remind me to check the build in 30 minutes
Agent: Set a reminder for 2:30 PM — "Check the build"
```
### Recurring Tasks
```
User: Every Monday at 9 AM, summarize my calendar for the week
Agent: Created recurring task: "Weekly calendar summary" — Every Monday at 9:00 AM
```
## API
The scheduler provides two main functions:
### add_recurring
```python
from pocketclaw.scheduler import scheduler
scheduler.add_recurring(
task_id="weekly-summary",
cron_expression="0 9 * * 1", # Every Monday at 9 AM
callback=async_function,
kwargs={"session_id": "..."},
)
```
### delete_recurring
```python
scheduler.delete_recurring("weekly-summary")
```
## Persistence
Recurring tasks are persisted to the config and re-loaded on startup. One-time reminders are stored in memory and lost on restart.
## Cron Expression Format
Standard cron format: `minute hour day_of_month month day_of_week`
| Expression | Description |
|------------|-------------|
| `0 9 * * 1` | Every Monday at 9:00 AM |
| `*/30 * * * *` | Every 30 minutes |
| `0 8,17 * * 1-5` | 8 AM and 5 PM on weekdays |
| `0 0 1 * *` | First day of every month at midnight |

89
docs/advanced/skills.mdx Normal file
View File

@@ -0,0 +1,89 @@
---
title: Skills System
description: "Skills are persistent SKILL.md files that teach PocketPaw how to handle specific task types. Define triggers, step-by-step instructions, tool chains, and output formats that load into every interaction."
section: Advanced
ogType: article
keywords: ["skills system", "skill.md", "agent training", "persistent skills", "task templates"]
tags: ["advanced", "skills"]
---
# Skills System
Skills are persistent markdown files that teach PocketPaw how to handle specific types of tasks. They're loaded into the agent's context on every interaction.
## What is a Skill?
A skill is a SKILL.md file stored in `~/.pocketclaw/skills/`. Each skill defines:
- **When to activate** — Trigger phrases or conditions
- **How to execute** — Step-by-step instructions
- **What tools to use** — Tool chains and sequences
- **Output format** — Expected response structure
## Creating Skills
### Via the Skill Generator Tool
The agent can create skills using the `skill_gen` tool:
```
User: Create a skill for writing daily standup summaries
Agent: [uses skill_gen] → Created skill: daily-standup.md
```
### Manually
Create a markdown file in `~/.pocketclaw/skills/`:
```markdown
# Code Review Skill
## Trigger
When the user asks to review code, a PR, or a diff.
## Steps
1. Read the file or diff provided
2. Analyze for:
- Bug risks
- Performance issues
- Security concerns
- Code style
3. Provide structured feedback
## Output Format
### Summary
Brief overall assessment.
### Issues Found
- **[severity]** Description of issue (line X)
### Suggestions
- Improvement suggestions
```
## Skill Loading
Skills are loaded by the `AgentContextBuilder`:
1. On startup, all `*.md` files in `~/.pocketclaw/skills/` are read
2. Skill content is injected into the system prompt
3. The agent uses skills as reference when handling matching requests
4. After creating a new skill via `skill_gen`, the loader is reloaded
## Skill Directory
```
~/.pocketclaw/skills/
├── daily-standup.md
├── code-review.md
├── meeting-notes.md
└── git-workflow.md
```
## Best Practices
1. **Keep skills focused** — One skill per task type
2. **Be specific** — Clear trigger conditions prevent false matches
3. **Include examples** — Show the expected output format
4. **Reference tools** — Specify which tools to use
5. **Test and iterate** — Try the skill and refine it

View File

@@ -0,0 +1,151 @@
---
title: Configuration Reference
description: "Complete reference of all PocketPaw configuration options: environment variables with POCKETCLAW_ prefix, JSON config fields, channel tokens, API keys, tool profiles, and memory backend settings."
section: API Reference
ogType: article
keywords: ["configuration", "environment variables", "settings reference", "config options"]
tags: ["api", "configuration"]
---
# Configuration Reference
Complete reference of all configuration settings. All environment variables use the `POCKETCLAW_` prefix.
## Core Settings
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `anthropic_api_key` | `POCKETCLAW_ANTHROPIC_API_KEY` | — | Anthropic API key |
| `openai_api_key` | `POCKETCLAW_OPENAI_API_KEY` | — | OpenAI API key |
| `agent_backend` | `POCKETCLAW_AGENT_BACKEND` | `claude_agent_sdk` | Agent backend |
| `dashboard_host` | `POCKETCLAW_DASHBOARD_HOST` | `0.0.0.0` | Dashboard bind address |
| `dashboard_port` | `POCKETCLAW_DASHBOARD_PORT` | `8000` | Dashboard port |
## Tool Policy
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `tool_profile` | `POCKETCLAW_TOOL_PROFILE` | `coding` | Tool profile |
| `tools_allow` | `POCKETCLAW_TOOLS_ALLOW` | `[]` | Allowed tools |
| `tools_deny` | `POCKETCLAW_TOOLS_DENY` | `[]` | Denied tools |
## Telegram
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `telegram_token` | `POCKETCLAW_TELEGRAM_TOKEN` | — | Bot token |
| `allowed_telegram_ids` | `POCKETCLAW_ALLOWED_TELEGRAM_IDS` | `[]` | Allowed user IDs |
## Discord
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `discord_bot_token` | `POCKETCLAW_DISCORD_BOT_TOKEN` | — | Bot token |
| `discord_allowed_guild_ids` | `POCKETCLAW_DISCORD_ALLOWED_GUILD_IDS` | `[]` | Allowed guilds |
| `discord_allowed_user_ids` | `POCKETCLAW_DISCORD_ALLOWED_USER_IDS` | `[]` | Allowed users |
## Slack
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `slack_bot_token` | `POCKETCLAW_SLACK_BOT_TOKEN` | — | Bot token (xoxb-) |
| `slack_app_token` | `POCKETCLAW_SLACK_APP_TOKEN` | — | App token (xapp-) |
| `slack_allowed_channel_ids` | `POCKETCLAW_SLACK_ALLOWED_CHANNEL_IDS` | `[]` | Allowed channels |
## WhatsApp
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `whatsapp_mode` | `POCKETCLAW_WHATSAPP_MODE` | `business` | Mode (personal/business) |
| `whatsapp_access_token` | `POCKETCLAW_WHATSAPP_ACCESS_TOKEN` | — | Business API token |
| `whatsapp_phone_number_id` | `POCKETCLAW_WHATSAPP_PHONE_NUMBER_ID` | — | Phone number ID |
| `whatsapp_verify_token` | `POCKETCLAW_WHATSAPP_VERIFY_TOKEN` | — | Webhook verify token |
| `whatsapp_allowed_phone_numbers` | `POCKETCLAW_WHATSAPP_ALLOWED_PHONE_NUMBERS` | `[]` | Allowed numbers |
| `whatsapp_neonize_db` | `POCKETCLAW_WHATSAPP_NEONIZE_DB` | `~/.pocketclaw/neonize.db` | Neonize DB path |
## Signal
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `signal_api_url` | `POCKETCLAW_SIGNAL_API_URL` | — | signal-cli REST API URL |
| `signal_phone_number` | `POCKETCLAW_SIGNAL_PHONE_NUMBER` | — | Registered number |
| `signal_allowed_numbers` | `POCKETCLAW_SIGNAL_ALLOWED_NUMBERS` | `[]` | Allowed numbers |
## Matrix
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `matrix_homeserver` | `POCKETCLAW_MATRIX_HOMESERVER` | — | Homeserver URL |
| `matrix_user_id` | `POCKETCLAW_MATRIX_USER_ID` | — | Bot user ID |
| `matrix_access_token` | `POCKETCLAW_MATRIX_ACCESS_TOKEN` | — | Auth token |
| `matrix_device_id` | `POCKETCLAW_MATRIX_DEVICE_ID` | — | Device ID |
| `matrix_allowed_room_ids` | `POCKETCLAW_MATRIX_ALLOWED_ROOM_IDS` | `[]` | Allowed rooms |
| `matrix_display_name` | `POCKETCLAW_MATRIX_DISPLAY_NAME` | — | Display name |
## Microsoft Teams
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `teams_app_id` | `POCKETCLAW_TEAMS_APP_ID` | — | Bot Framework App ID |
| `teams_app_password` | `POCKETCLAW_TEAMS_APP_PASSWORD` | — | App password |
| `teams_tenant_id` | `POCKETCLAW_TEAMS_TENANT_ID` | — | Azure tenant ID |
| `teams_allowed_team_ids` | `POCKETCLAW_TEAMS_ALLOWED_TEAM_IDS` | `[]` | Allowed teams |
## Google Chat
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `gchat_project_id` | `POCKETCLAW_GCHAT_PROJECT_ID` | — | GCP project ID |
| `gchat_service_account_key` | `POCKETCLAW_GCHAT_SERVICE_ACCOUNT_KEY` | — | SA key path |
| `gchat_mode` | `POCKETCLAW_GCHAT_MODE` | `webhook` | Connection mode |
| `gchat_subscription` | `POCKETCLAW_GCHAT_SUBSCRIPTION` | — | Pub/Sub subscription |
| `gchat_allowed_space_ids` | `POCKETCLAW_GCHAT_ALLOWED_SPACE_IDS` | `[]` | Allowed spaces |
## Web Search
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `web_search_provider` | `POCKETCLAW_WEB_SEARCH_PROVIDER` | `tavily` | Search provider |
| `tavily_api_key` | `POCKETCLAW_TAVILY_API_KEY` | — | Tavily API key |
| `brave_search_api_key` | `POCKETCLAW_BRAVE_SEARCH_API_KEY` | — | Brave Search key |
## Image Generation
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `google_api_key` | `POCKETCLAW_GOOGLE_API_KEY` | — | Google AI API key |
| `image_model` | `POCKETCLAW_IMAGE_MODEL` | `gemini-2.0-flash` | Model |
## Voice & STT
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `tts_provider` | `POCKETCLAW_TTS_PROVIDER` | `openai` | TTS provider |
| `tts_voice` | `POCKETCLAW_TTS_VOICE` | `alloy` | Voice ID |
| `elevenlabs_api_key` | `POCKETCLAW_ELEVENLABS_API_KEY` | — | ElevenLabs key |
| `stt_model` | `POCKETCLAW_STT_MODEL` | `whisper-1` | STT model |
## Google Integration
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `google_client_id` | `POCKETCLAW_GOOGLE_CLIENT_ID` | — | OAuth client ID |
| `google_client_secret` | `POCKETCLAW_GOOGLE_CLIENT_SECRET` | — | OAuth secret |
## Spotify
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `spotify_client_id` | `POCKETCLAW_SPOTIFY_CLIENT_ID` | — | Spotify client ID |
| `spotify_client_secret` | `POCKETCLAW_SPOTIFY_CLIENT_SECRET` | — | Spotify secret |
## Memory (Mem0)
| Setting | Env Variable | Default | Description |
|---------|-------------|---------|-------------|
| `mem0_auto_learn` | `POCKETCLAW_MEM0_AUTO_LEARN` | `false` | Enable auto-learn |
| `mem0_llm_provider` | `POCKETCLAW_MEM0_LLM_PROVIDER` | `ollama` | LLM provider |
| `mem0_llm_model` | `POCKETCLAW_MEM0_LLM_MODEL` | `llama3.2` | LLM model |
| `mem0_embedder_provider` | `POCKETCLAW_MEM0_EMBEDDER_PROVIDER` | `ollama` | Embedder provider |
| `mem0_embedder_model` | `POCKETCLAW_MEM0_EMBEDDER_MODEL` | `nomic-embed-text` | Embedder model |
| `mem0_vector_store` | `POCKETCLAW_MEM0_VECTOR_STORE` | `qdrant` | Vector store |

View File

@@ -0,0 +1,85 @@
---
title: Delete Memory Entry
description: "Delete a specific long-term memory entry from PocketPaw's memory store. Use this to remove outdated or incorrect facts that the auto-learn system extracted from conversations."
api: DELETE /api/memory/long_term/{entry_id}
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["delete memory", "remove fact", "memory management"]
tags: ["api", "memory"]
---
## Overview
Permanently deletes a long-term memory entry. This is useful for removing outdated or incorrect learned facts.
## Parameters
<ParamTable type="path">
<Param name="entry_id" type="string" required>
The unique identifier of the memory entry to delete.
</Param>
</ParamTable>
## Response
<ResponseField name="ok" type="boolean">`true` on successful deletion</ResponseField>
## Error Responses
| Status | Description |
|--------|-------------|
| 404 | Memory entry not found |
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X DELETE "http://localhost:8000/api/memory/long_term/mem_001" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/memory/long_term/mem_001", {
method: "DELETE",
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.delete(
"http://localhost:8000/api/memory/long_term/mem_001",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200", "404"]}>
<Tab title="200">
```json
{
"ok": true
}
```
</Tab>
<Tab title="404">
```json
{
"detail": "Memory entry not found"
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,79 @@
---
title: Delete Session
description: "Permanently delete a PocketPaw chat session and all its associated messages. This action is irreversible and removes the session from the index and storage."
api: DELETE /api/sessions/{session_id}
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["delete session", "remove conversation", "permanent delete"]
tags: ["api", "sessions"]
---
## Overview
Permanently deletes a session and all its associated messages from the file store. This action cannot be undone.
## Parameters
<ParamTable type="path">
<Param name="session_id" type="string" required>
The unique identifier of the session to delete.
</Param>
</ParamTable>
## Response
<ResponseField name="status" type="string">
`"ok"` on successful deletion.
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X DELETE "http://localhost:8000/api/sessions/session_abc123" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const sessionId = "session_abc123";
const response = await fetch(`http://localhost:8000/api/sessions/${sessionId}`, {
method: "DELETE",
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
session_id = "session_abc123"
response = requests.delete(
f"http://localhost:8000/api/sessions/{session_id}",
headers={"Authorization": "Bearer <token>"},
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200", "404"]}>
<Tab title="200">
```json
{ "status": "ok" }
```
</Tab>
<Tab title="404">
```json
{ "detail": "Session not found" }
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,94 @@
---
title: Get Audit Logs
description: "Retrieve the append-only security audit log entries from PocketPaw. Returns timestamped security events with severity levels (INFO, WARNING, CRITICAL, ALERT) and structured metadata."
api: GET /api/audit
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["audit logs", "security events", "audit trail"]
tags: ["api", "security"]
---
## Overview
Returns recent entries from the append-only audit log (`~/.pocketclaw/audit.jsonl`). The audit log records tool executions, security events, and Guardian AI decisions.
## Parameters
<ParamTable type="query">
<Param name="limit" type="integer" default="50">
Maximum number of audit entries to return (most recent first).
</Param>
</ParamTable>
## Response
Returns an array of audit entry objects:
<ResponseField name="timestamp" type="string">ISO 8601 timestamp of the event</ResponseField>
<ResponseField name="event" type="string">Event type (e.g., `tool_executed`, `threat_detected`, `command_blocked`)</ResponseField>
<ResponseField name="tool" type="string" nullable>Tool name if applicable</ResponseField>
<ResponseField name="input" type="string" nullable>Tool input or command that was executed</ResponseField>
<ResponseField name="result" type="string" nullable>Execution result or outcome</ResponseField>
<ResponseField name="threat_level" type="string" nullable>Threat level if a security check was triggered</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/audit?limit=50" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/audit?limit=50", {
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/audit",
params={"limit": 50},
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
[
{
"timestamp": "2024-01-15T11:45:00Z",
"event": "tool_executed",
"tool": "shell",
"input": "python script.py",
"result": "success",
"threat_level": null
},
{
"timestamp": "2024-01-15T11:44:55Z",
"event": "command_blocked",
"tool": "shell",
"input": "rm -rf /",
"result": "blocked by Guardian AI",
"threat_level": "critical"
}
]
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,110 @@
---
title: Get Channel Status
description: "Retrieve the running status, configuration state, and adapter details of all channel adapters connected to PocketPaw. Returns which channels are active and their current configuration."
api: GET /api/channels/status
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["channel status", "adapter status", "running channels"]
tags: ["api", "channels"]
---
## Overview
Returns the current status of all 8 supported channel adapters, including whether each is configured (has required tokens/credentials) and whether it is currently running.
## Response
<ResponseField name="discord" type="object">
<ResponseField name="configured" type="boolean">Whether the Discord bot token is set</ResponseField>
<ResponseField name="running" type="boolean">Whether the Discord adapter is currently active</ResponseField>
<ResponseField name="mode" type="string">Connection mode (always `bot`)</ResponseField>
</ResponseField>
<ResponseField name="slack" type="object">
<ResponseField name="configured" type="boolean">Whether both Slack bot and app tokens are set</ResponseField>
<ResponseField name="running" type="boolean">Whether the Slack adapter is currently active</ResponseField>
</ResponseField>
<ResponseField name="whatsapp" type="object">
<ResponseField name="configured" type="boolean">Whether WhatsApp credentials are set (always true for personal mode)</ResponseField>
<ResponseField name="running" type="boolean">Whether the WhatsApp adapter is currently active</ResponseField>
<ResponseField name="mode" type="string">Either `personal` or `business`</ResponseField>
</ResponseField>
<ResponseField name="telegram" type="object">
<ResponseField name="configured" type="boolean">Whether the Telegram bot token is set</ResponseField>
<ResponseField name="running" type="boolean">Whether the Telegram adapter is currently active</ResponseField>
</ResponseField>
<ResponseField name="signal" type="object">
<ResponseField name="configured" type="boolean">Whether the Signal API URL and phone number are set</ResponseField>
<ResponseField name="running" type="boolean">Whether the Signal adapter is currently active</ResponseField>
</ResponseField>
<ResponseField name="matrix" type="object">
<ResponseField name="configured" type="boolean">Whether Matrix homeserver and credentials are set</ResponseField>
<ResponseField name="running" type="boolean">Whether the Matrix adapter is currently active</ResponseField>
</ResponseField>
<ResponseField name="teams" type="object">
<ResponseField name="configured" type="boolean">Whether Teams App ID and password are set</ResponseField>
<ResponseField name="running" type="boolean">Whether the Teams adapter is currently active</ResponseField>
</ResponseField>
<ResponseField name="gchat" type="object">
<ResponseField name="configured" type="boolean">Whether Google Chat project ID and service account key are set</ResponseField>
<ResponseField name="running" type="boolean">Whether the Google Chat adapter is currently active</ResponseField>
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/channels/status" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/channels/status", {
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/channels/status",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"discord": {"configured": true, "running": true, "mode": "bot"},
"slack": {"configured": true, "running": false},
"whatsapp": {"configured": true, "running": true, "mode": "personal"},
"telegram": {"configured": false, "running": false},
"signal": {"configured": false, "running": false},
"matrix": {"configured": false, "running": false},
"teams": {"configured": false, "running": false},
"gchat": {"configured": false, "running": false}
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,124 @@
---
title: Get Deep Work Plan
description: "Retrieve the generated plan for a Deep Work project including the PRD document, task list with dependencies, execution levels for DAG visualization, and overall progress metrics."
api: GET /api/deep-work/projects/{project_id}/plan
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["get plan", "project plan", "task dependencies", "prd"]
tags: ["api", "deep-work"]
---
## Overview
Returns the full plan for a Deep Work project including the PRD, task list with dependencies, execution levels, and progress.
## Path Parameters
<ResponseField name="project_id" type="string" required>
The project ID.
</ResponseField>
## Response
<ResponseField name="project" type="object">
The project object with all fields.
</ResponseField>
<ResponseField name="tasks" type="array">
List of all tasks in the project with status, priority, assignees, and dependencies.
</ResponseField>
<ResponseField name="progress" type="object">
Progress summary.
<ResponseField name="total" type="integer">Total task count.</ResponseField>
<ResponseField name="completed" type="integer">Done tasks.</ResponseField>
<ResponseField name="in_progress" type="integer">Currently executing.</ResponseField>
<ResponseField name="blocked" type="integer">Blocked tasks.</ResponseField>
<ResponseField name="percent" type="number">Completion percentage.</ResponseField>
</ResponseField>
<ResponseField name="prd" type="object">
The PRD document (title, content, type) or null if not yet generated.
</ResponseField>
<ResponseField name="execution_levels" type="array">
Task IDs grouped by dependency level for DAG visualization.
</ResponseField>
<ResponseField name="task_level_map" type="object">
Mapping of task ID to its dependency level index.
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl http://localhost:8000/api/deep-work/projects/PROJECT_ID/plan \
-H "Authorization: Bearer YOUR_TOKEN"
```
</Tab>
<Tab title="JavaScript">
```javascript
const res = await fetch(`http://localhost:8000/api/deep-work/projects/${projectId}/plan`, {
headers: { 'Authorization': 'Bearer YOUR_TOKEN' },
});
const data = await res.json();
```
</Tab>
<Tab title="Python">
```python
import httpx
res = httpx.get(
f"http://localhost:8000/api/deep-work/projects/{project_id}/plan",
headers={"Authorization": "Bearer YOUR_TOKEN"},
)
data = res.json()
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"project": {
"id": "a1b2c3d4...",
"title": "Recipe Management API",
"status": "awaiting_approval"
},
"tasks": [
{
"id": "task-1",
"title": "Set up project structure",
"status": "inbox",
"priority": "high",
"blocked_by": [],
"task_type": "agent",
"estimated_minutes": 30
}
],
"progress": {
"total": 8,
"completed": 0,
"in_progress": 0,
"blocked": 0,
"percent": 0
},
"prd": {
"title": "PRD: Recipe Management API",
"content": "## Problem Statement\n...",
"type": "protocol"
},
"execution_levels": [["task-1", "task-2"], ["task-3"]],
"task_level_map": {"task-1": 0, "task-2": 0, "task-3": 1}
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,91 @@
---
title: List Mission Control Agents
description: "List all AI agents registered in PocketPaw's Mission Control system. Filter by status (idle, active, blocked, offline) and view each agent's name, role, specialties, and last heartbeat."
api: GET /api/mission-control/agents
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["list agents", "agent status", "mission control agents"]
tags: ["api", "mission-control"]
---
## Overview
Returns all agents registered in Mission Control. Optionally filter by status.
## Query Parameters
<ResponseField name="status" type="string">
Filter by agent status: `idle`, `active`, `blocked`, or `offline`.
</ResponseField>
<ResponseField name="limit" type="integer" default="100">
Maximum number of agents to return.
</ResponseField>
## Response
<ResponseField name="agents" type="array">
List of agent profiles.
<ResponseField name="id" type="string">Agent UUID.</ResponseField>
<ResponseField name="name" type="string">Agent name (e.g., `backend-dev`).</ResponseField>
<ResponseField name="role" type="string">Agent role (e.g., `Backend Engineer`).</ResponseField>
<ResponseField name="status" type="string">Current status.</ResponseField>
<ResponseField name="specialties" type="array">List of skill domains.</ResponseField>
<ResponseField name="last_heartbeat" type="string">ISO 8601 timestamp of last heartbeat.</ResponseField>
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl http://localhost:8000/api/mission-control/agents \
-H "Authorization: Bearer YOUR_TOKEN"
```
</Tab>
<Tab title="JavaScript">
```javascript
const res = await fetch('http://localhost:8000/api/mission-control/agents', {
headers: { 'Authorization': 'Bearer YOUR_TOKEN' },
});
const data = await res.json();
```
</Tab>
<Tab title="Python">
```python
import httpx
res = httpx.get(
"http://localhost:8000/api/mission-control/agents",
headers={"Authorization": "Bearer YOUR_TOKEN"},
)
data = res.json()
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"agents": [
{
"id": "agent-uuid-1",
"name": "backend-dev",
"role": "Backend Engineer",
"status": "idle",
"specialties": ["backend", "database", "api"],
"backend": "claude_agent_sdk",
"level": "specialist",
"last_heartbeat": "2024-01-15T14:30:00Z"
}
]
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,45 @@
---
title: Get Standup Report
description: "Generate a daily standup report summarizing Mission Control activity: completed tasks, in-progress work, blocked items, and agent status across all projects in markdown format."
api: GET /api/mission-control/standup
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["standup report", "daily summary", "project status"]
tags: ["api", "mission-control"]
---
## Overview
Generates a markdown standup report summarizing completed tasks, in-progress work, blocked items, and agent status across all projects.
## Response
<ResponseField name="standup" type="string">
Markdown-formatted standup report.
</ResponseField>
<RequestExample>
<Tabs items={["cURL"]}>
<Tab title="cURL">
```bash
curl http://localhost:8000/api/mission-control/standup \
-H "Authorization: Bearer YOUR_TOKEN"
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"standup": "# Daily Standup\n\n## Completed\n- Set up project structure (backend-dev)\n\n## In Progress\n- Implement auth (backend-dev)\n\n## Blocked\n- None\n\n## Agent Status\n- backend-dev: active\n- frontend-dev: idle"
}
```
</Tab>
</Tabs>
</ResponseExample>

82
docs/api/get-mc-tasks.mdx Normal file
View File

@@ -0,0 +1,82 @@
---
title: List Mission Control Tasks
description: "List all tasks managed by PocketPaw's Mission Control. Filter by status, assigned agent, or tags. Returns task details including priority, dependencies, project association, and execution state."
api: GET /api/mission-control/tasks
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["list tasks", "task management", "task filtering"]
tags: ["api", "mission-control"]
---
## Overview
Returns all tasks managed by Mission Control. Filter by status, assignee, or tags.
## Query Parameters
<ResponseField name="status" type="string">
Filter by task status: `inbox`, `assigned`, `in_progress`, `review`, `done`, `blocked`, `skipped`.
</ResponseField>
<ResponseField name="assignee_id" type="string">
Filter tasks assigned to a specific agent.
</ResponseField>
<ResponseField name="tags" type="string">
Comma-separated list of tags to filter by.
</ResponseField>
<ResponseField name="limit" type="integer" default="100">
Maximum number of tasks to return.
</ResponseField>
## Response
<ResponseField name="tasks" type="array">
List of task objects.
<ResponseField name="id" type="string">Task UUID.</ResponseField>
<ResponseField name="title" type="string">Task title.</ResponseField>
<ResponseField name="status" type="string">Current status.</ResponseField>
<ResponseField name="priority" type="string">Priority level.</ResponseField>
<ResponseField name="assignee_ids" type="array">Assigned agent IDs.</ResponseField>
<ResponseField name="blocked_by" type="array">IDs of blocking tasks.</ResponseField>
<ResponseField name="project_id" type="string">Associated Deep Work project ID.</ResponseField>
</ResponseField>
<RequestExample>
<Tabs items={["cURL"]}>
<Tab title="cURL">
```bash
curl "http://localhost:8000/api/mission-control/tasks?status=in_progress" \
-H "Authorization: Bearer YOUR_TOKEN"
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"tasks": [
{
"id": "task-uuid-1",
"title": "Set up project structure",
"status": "in_progress",
"priority": "high",
"assignee_ids": ["agent-uuid-1"],
"blocked_by": [],
"project_id": "project-uuid-1",
"task_type": "agent",
"estimated_minutes": 30
}
]
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,88 @@
---
title: List MCP Presets
description: "Get all available MCP server presets with their installation status. Presets are pre-configured server templates that can be installed with a single click from the dashboard."
api: GET /api/mcp/presets
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["mcp presets", "server templates", "quick install"]
tags: ["api", "mcp"]
---
## Overview
Returns all available MCP server presets (pre-configured server templates). Each preset includes metadata, required environment variables, and whether it's already installed.
## Response
Returns an array of preset objects:
<ResponseField name="id" type="string">Unique preset identifier (e.g., `filesystem`, `github`)</ResponseField>
<ResponseField name="name" type="string">Human-readable display name</ResponseField>
<ResponseField name="description" type="string">Description of what the server provides</ResponseField>
<ResponseField name="icon" type="string">Lucide icon name for the preset</ResponseField>
<ResponseField name="category" type="string">Category grouping (e.g., `filesystem`, `developer`, `data`)</ResponseField>
<ResponseField name="installed" type="boolean">Whether this preset is already configured</ResponseField>
<ResponseField name="env_keys" type="array">List of environment variable names the preset requires</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/mcp/presets" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/mcp/presets", {
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/mcp/presets",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
[
{
"id": "filesystem",
"name": "Filesystem",
"description": "Read, write, and manage files on the local filesystem",
"icon": "lucide:folder",
"category": "filesystem",
"installed": true,
"env_keys": []
},
{
"id": "github",
"name": "GitHub",
"description": "Interact with GitHub repositories, issues, and pull requests",
"icon": "lucide:github",
"category": "developer",
"installed": false,
"env_keys": ["GITHUB_TOKEN"]
}
]
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,84 @@
---
title: Get MCP Status
description: "Retrieve the status of all configured MCP servers in PocketPaw: running state, transport type (stdio/HTTP), available tools count, and last connection timestamp."
api: GET /api/mcp/status
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["mcp status", "server status", "mcp servers"]
tags: ["api", "mcp"]
---
## Overview
Returns the current status of all configured MCP (Model Context Protocol) servers, including their connection state, transport type, and available tools.
## Response
Returns an object keyed by server name:
<ResponseField name="{server_name}" type="object">
<ResponseField name="enabled" type="boolean">Whether the server is enabled in configuration</ResponseField>
<ResponseField name="connected" type="boolean">Whether the server is currently connected</ResponseField>
<ResponseField name="transport" type="string">Transport type: `stdio` or `http`</ResponseField>
<ResponseField name="tools" type="array">List of tool names available from this server</ResponseField>
<ResponseField name="error" type="string" nullable>Error message if the server failed to connect</ResponseField>
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/mcp/status" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/mcp/status", {
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/mcp/status",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"filesystem": {
"enabled": true,
"connected": true,
"transport": "stdio",
"tools": ["read_file", "write_file", "list_directory"],
"error": null
},
"github": {
"enabled": false,
"connected": false,
"transport": "stdio",
"tools": [],
"error": null
}
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,88 @@
---
title: List Long-Term Memories
description: "Retrieve stored long-term memory entries from PocketPaw's memory backend. Returns facts, preferences, and knowledge extracted from past conversations via auto-learning."
api: GET /api/memory/long_term
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["long-term memory", "stored facts", "memory entries"]
tags: ["api", "memory"]
---
## Overview
Returns all long-term memory entries stored by the agent. These are facts, preferences, and knowledge that the agent has learned from conversations (either manually or via mem0 auto-learn).
## Parameters
<ParamTable type="query">
<Param name="limit" type="integer" default="50">
Maximum number of memory entries to return.
</Param>
</ParamTable>
## Response
Returns an array of memory entry objects:
<ResponseField name="id" type="string">Unique identifier for the memory entry</ResponseField>
<ResponseField name="content" type="string">The memory content text</ResponseField>
<ResponseField name="timestamp" type="string">ISO 8601 timestamp when the memory was created</ResponseField>
<ResponseField name="tags" type="array">Optional tags categorizing the memory</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/memory/long_term?limit=50" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/memory/long_term?limit=50", {
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/memory/long_term",
params={"limit": 50},
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
[
{
"id": "mem_001",
"content": "User prefers Python over JavaScript for backend work",
"timestamp": "2024-01-15T10:30:00Z",
"tags": ["preference", "programming"]
},
{
"id": "mem_002",
"content": "User's project uses PostgreSQL with SQLAlchemy ORM",
"timestamp": "2024-01-14T08:00:00Z",
"tags": ["project", "database"]
}
]
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,77 @@
---
title: Get Memory Settings
description: "Retrieve the current memory backend configuration including the active provider (file store or Mem0), LLM and embedder settings, vector store configuration, and auto-learn status."
api: GET /api/memory/settings
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["memory settings", "backend config", "mem0 settings"]
tags: ["api", "memory"]
---
## Overview
Returns the current memory backend configuration, including the active backend, mem0 provider settings, and auto-learn status.
## Response
<ResponseField name="memory_backend" type="string">Active memory backend (`file` or `mem0`)</ResponseField>
<ResponseField name="mem0_llm_provider" type="string">LLM provider for mem0 (`ollama`, `openai`, `anthropic`)</ResponseField>
<ResponseField name="mem0_llm_model" type="string">LLM model name (e.g., `llama3.2`)</ResponseField>
<ResponseField name="mem0_embedder_provider" type="string">Embedding provider (`ollama`, `openai`)</ResponseField>
<ResponseField name="mem0_embedder_model" type="string">Embedding model name (e.g., `nomic-embed-text`)</ResponseField>
<ResponseField name="mem0_vector_store" type="string">Vector store backend (`qdrant`)</ResponseField>
<ResponseField name="mem0_ollama_base_url" type="string">Ollama server URL</ResponseField>
<ResponseField name="mem0_auto_learn" type="boolean">Whether auto-learn is enabled</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/memory/settings" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/memory/settings", {
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/memory/settings",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"memory_backend": "mem0",
"mem0_llm_provider": "ollama",
"mem0_llm_model": "llama3.2",
"mem0_embedder_provider": "ollama",
"mem0_embedder_model": "nomic-embed-text",
"mem0_vector_store": "qdrant",
"mem0_ollama_base_url": "http://localhost:11434",
"mem0_auto_learn": true
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,65 @@
---
title: Get Memory Stats
description: "Retrieve memory backend statistics including total entries stored, storage size, last auto-learn timestamp, and provider-specific metrics for monitoring memory system health."
api: GET /api/memory/stats
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["memory stats", "storage metrics", "memory health"]
tags: ["api", "memory"]
---
## Overview
Returns statistics about the current memory backend, including the number of stored memories and the active backend type.
## Response
<ResponseField name="backend" type="string">Active memory backend (`file` or `mem0`)</ResponseField>
<ResponseField name="total_memories" type="integer">Total number of long-term memory entries</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/memory/stats" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/memory/stats", {
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/memory/stats",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"backend": "mem0",
"total_memories": 47
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,85 @@
---
title: Start OAuth Flow
description: "Initiate an OAuth 2.0 authorization flow for connecting third-party services like Google Workspace or Spotify. Redirects to the provider's consent screen and handles the callback."
api: GET /api/oauth/authorize
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["oauth flow", "authorization", "google oauth", "spotify oauth"]
tags: ["api", "authentication"]
---
## Overview
Starts an OAuth 2.0 authorization code flow by redirecting the user to the provider's consent screen. After the user grants permission, they are redirected back to `/oauth/callback` where the authorization code is exchanged for access and refresh tokens.
## Parameters
<ParamTable type="query">
<Param name="service" type="string" required enum={["google_gmail", "google_calendar", "google_drive", "google_docs", "spotify"]}>
The service to authorize. Each service requests the appropriate OAuth scopes.
</Param>
</ParamTable>
## Response
Returns an HTTP 302 redirect to the provider's consent screen.
## Supported Services
| Service | Provider | Scopes |
|---------|----------|--------|
| `google_gmail` | Google | Gmail read, send, modify |
| `google_calendar` | Google | Calendar read/write |
| `google_drive` | Google | Drive file access |
| `google_docs` | Google | Docs read/write |
| `spotify` | Spotify | Playback, playlists, user info |
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/oauth/authorize?service=google_gmail" \
-H "Authorization: Bearer <token>" \
-L
```
</Tab>
<Tab title="JavaScript">
```javascript
// Redirect the browser to the OAuth consent screen
window.location.href =
"http://localhost:8000/api/oauth/authorize?service=google_gmail";
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/oauth/authorize",
params={"service": "google_gmail"},
headers={"Authorization": "Bearer <token>"},
allow_redirects=False
)
print("Redirect URL:", response.headers["Location"])
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["302"]}>
<Tab title="302">
```
HTTP/1.1 302 Found
Location: https://accounts.google.com/o/oauth2/v2/auth?client_id=...&redirect_uri=...&scope=...
```
</Tab>
</Tabs>
</ResponseExample>
<Callout type="info">
Requires `google_client_id` and `google_client_secret` (or `spotify_client_id`/`spotify_client_secret`) to be configured first.
</Callout>

61
docs/api/get-qr-code.mdx Normal file
View File

@@ -0,0 +1,61 @@
---
title: Generate QR Login Code
description: "Generate a QR code for mobile device login to the PocketPaw dashboard. Scan the QR code with your phone to authenticate without manually entering credentials or tokens."
api: GET /api/qr
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: none
section: API Reference
ogType: article
keywords: ["qr code login", "mobile auth", "qr authentication"]
tags: ["api", "authentication"]
---
## Overview
Generates a QR code PNG image that encodes the dashboard URL with an embedded access token. Scanning this QR code on a mobile device automatically authenticates the user.
This endpoint is **auth-exempt** — it can be accessed without a token (intended for the initial login flow).
## Response
Returns a PNG image (`image/png` content type) as a streaming response.
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/qr" -o login-qr.png
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/qr");
const blob = await response.blob();
const url = URL.createObjectURL(blob);
// Use url in an <img> tag or download link
console.log("QR code blob URL:", url);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get("http://localhost:8000/api/qr")
with open("login-qr.png", "wb") as f:
f.write(response.content)
print("QR code saved to login-qr.png")
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```
Binary PNG image (content-type: image/png)
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,102 @@
---
title: Get Self-Audit Report
description: "Retrieve a specific self-audit daemon report by date. Contains detailed results from 12 automated security and operational checks including pass/fail status and remediation suggestions."
api: GET /api/self-audit/reports/{date}
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["audit report detail", "security report", "check results"]
tags: ["api", "security"]
---
## Overview
Returns the full self-audit report for a specific date. The report contains 12 check results covering configuration, security, and system health.
## Parameters
<ParamTable type="path">
<Param name="date" type="string" required>
Report date in `YYYY-MM-DD` format.
</Param>
</ParamTable>
## Response
<ResponseField name="date" type="string">Report date</ResponseField>
<ResponseField name="total" type="integer">Total checks executed</ResponseField>
<ResponseField name="passed" type="integer">Checks passed</ResponseField>
<ResponseField name="issues" type="integer">Issues found</ResponseField>
<ResponseField name="checks" type="array">
Detailed results for each of the 12 checks.
<ResponseField name="name" type="string">Check identifier</ResponseField>
<ResponseField name="passed" type="boolean">Whether the check passed</ResponseField>
<ResponseField name="message" type="string">Description of findings</ResponseField>
<ResponseField name="severity" type="string">Issue severity (`info`, `warning`, `critical`)</ResponseField>
</ResponseField>
## Error Responses
| Status | Description |
|--------|-------------|
| 404 | No report found for the given date |
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/self-audit/reports/2024-01-15" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/self-audit/reports/2024-01-15", {
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/self-audit/reports/2024-01-15",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200", "404"]}>
<Tab title="200">
```json
{
"date": "2024-01-15",
"total": 12,
"passed": 10,
"issues": 2,
"checks": [
{"name": "config_permissions", "passed": true, "message": "OK", "severity": "info"},
{"name": "audit_log_integrity", "passed": true, "message": "OK", "severity": "info"},
{"name": "memory_store_health", "passed": false, "message": "Qdrant unreachable", "severity": "warning"}
]
}
```
</Tab>
<Tab title="404">
```json
{
"detail": "No report found for the given date"
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,79 @@
---
title: List Self-Audit Reports
description: "List recent self-audit daemon reports generated by PocketPaw's background security monitoring. Each report contains results from 12 automated checks with timestamps and findings."
api: GET /api/self-audit/reports
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["audit reports", "self-audit", "security monitoring"]
tags: ["api", "security"]
---
## Overview
Returns a list of recent self-audit reports generated by the self-audit daemon. Reports are stored as JSON files and sorted by date (most recent first).
## Response
Returns an array of report summary objects:
<ResponseField name="date" type="string">Report date in `YYYY-MM-DD` format</ResponseField>
<ResponseField name="total" type="integer">Total number of checks in the report</ResponseField>
<ResponseField name="passed" type="integer">Number of passing checks</ResponseField>
<ResponseField name="issues" type="integer">Number of issues found</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/self-audit/reports" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/self-audit/reports", {
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/self-audit/reports",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
[
{
"date": "2024-01-15",
"total": 12,
"passed": 10,
"issues": 2
},
{
"date": "2024-01-14",
"total": 12,
"passed": 12,
"issues": 0
}
]
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,96 @@
---
title: Get Session History
description: "Retrieve the complete message history for a specific PocketPaw session. Returns all user and agent messages in chronological order with timestamps and metadata."
api: GET /api/memory/session
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["session history", "message history", "chat log"]
tags: ["api", "sessions"]
---
## Overview
Returns the message history for a specific session. Messages are returned in chronological order with role, content, and timestamp.
## Parameters
<ParamTable type="query">
<Param name="id" type="string" required>
The session identifier to retrieve messages for.
</Param>
<Param name="limit" type="integer" default="50">
Maximum number of messages to return.
</Param>
</ParamTable>
## Response
Returns an array of message objects:
<ResponseField name="role" type="string">
Message role: `user` or `assistant`.
</ResponseField>
<ResponseField name="content" type="string">
The message content (may contain markdown).
</ResponseField>
<ResponseField name="timestamp" type="string">
ISO 8601 timestamp when the message was recorded.
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/memory/session?id=session_abc123" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/memory/session?id=session_abc123", {
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/memory/session",
params={"id": "session_abc123"},
headers={"Authorization": "Bearer <token>"},
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
[
{
"role": "user",
"content": "How do I check if a number is prime in Python?",
"timestamp": "2024-01-15T10:30:00Z"
},
{
"role": "assistant",
"content": "Here's a function to check if a number is prime...",
"timestamp": "2024-01-15T10:30:05Z"
}
]
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,92 @@
---
title: Search Sessions
description: "Perform full-text search across all PocketPaw session messages. Returns matching sessions with highlighted excerpts, enabling quick retrieval of past conversations by content or keyword."
api: GET /api/sessions/search
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["search sessions", "full-text search", "conversation search"]
tags: ["api", "sessions"]
---
## Overview
Searches session message content for a query string. Returns matching sessions with the specific message that matched and its role.
## Parameters
<ParamTable type="query">
<Param name="q" type="string" required>
Search query string. Matches against message content.
</Param>
<Param name="limit" type="integer" default="20">
Maximum number of matching sessions to return.
</Param>
</ParamTable>
## Response
<ResponseField name="sessions" type="array">
Array of matching sessions with match context.
<ResponseField name="id" type="string">Session identifier</ResponseField>
<ResponseField name="title" type="string">Session title</ResponseField>
<ResponseField name="channel" type="string">Origin channel</ResponseField>
<ResponseField name="match" type="string">The matched message content (truncated)</ResponseField>
<ResponseField name="match_role" type="string">Role of the matched message (`user` or `assistant`)</ResponseField>
<ResponseField name="last_activity" type="string">ISO 8601 last activity timestamp</ResponseField>
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/sessions/search?q=prime&limit=20" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/sessions/search?q=prime&limit=20", {
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/sessions/search",
params={"q": "prime", "limit": 20},
headers={"Authorization": "Bearer <token>"},
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"sessions": [
{
"id": "session_abc123",
"title": "Python prime numbers",
"channel": "web",
"match": "Here's a function to check if a number is prime...",
"match_role": "assistant",
"last_activity": "2024-01-15T11:45:00Z"
}
]
}
```
</Tab>
</Tabs>
</ResponseExample>

102
docs/api/get-sessions.mdx Normal file
View File

@@ -0,0 +1,102 @@
---
title: List Sessions
description: "Retrieve all chat sessions with metadata including titles, message counts, creation dates, and active status. Sessions are returned sorted by most recent activity for easy navigation."
api: GET /api/sessions
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["list sessions", "session metadata", "chat history"]
tags: ["api", "sessions"]
---
## Overview
Returns a paginated list of all chat sessions with their metadata. Uses the fast session index for efficient retrieval.
## Parameters
<ParamTable type="query">
<Param name="limit" type="integer" default="50">
Maximum number of sessions to return.
</Param>
</ParamTable>
## Response
<ResponseField name="sessions" type="array">
Array of session objects, sorted by last activity (most recent first).
<ResponseField name="id" type="string">Unique session identifier</ResponseField>
<ResponseField name="title" type="string">Session title (auto-generated or user-set)</ResponseField>
<ResponseField name="created_at" type="string">ISO 8601 creation timestamp</ResponseField>
<ResponseField name="updated_at" type="string">ISO 8601 last activity timestamp</ResponseField>
<ResponseField name="message_count" type="integer">Number of messages in the session</ResponseField>
<ResponseField name="channel" type="string">Origin channel (web, telegram, discord, etc.)</ResponseField>
</ResponseField>
<ResponseField name="total" type="integer">
Total number of sessions available.
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/sessions?limit=50" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/sessions?limit=50", {
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/sessions",
params={"limit": 50},
headers={"Authorization": "Bearer <token>"},
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"sessions": [
{
"id": "session_abc123",
"title": "Python prime numbers",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T11:45:00Z",
"message_count": 12,
"channel": "web"
},
{
"id": "session_def456",
"title": "Docker deployment help",
"created_at": "2024-01-14T08:00:00Z",
"updated_at": "2024-01-14T09:30:00Z",
"message_count": 8,
"channel": "telegram"
}
],
"total": 42
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,73 @@
---
title: Get Tunnel Status
description: "Check if a Cloudflare tunnel is currently active and retrieve its public URL. Tunnels provide HTTPS access to PocketPaw's local server for WhatsApp webhooks and remote access."
api: GET /api/remote/status
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["tunnel status", "cloudflare tunnel", "public url"]
tags: ["api", "tunnel"]
---
## Overview
Returns the current status of the Cloudflare tunnel (used for remote access to the dashboard without port forwarding).
## Response
<ResponseField name="active" type="boolean">Whether a tunnel is currently running</ResponseField>
<ResponseField name="url" type="string" nullable>The public tunnel URL (e.g., `https://abc-xyz.trycloudflare.com`)</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/remote/status" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/remote/status", {
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/remote/status",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200 (Active)", "200 (Inactive)"]}>
<Tab title="200 (Active)">
```json
{
"active": true,
"url": "https://steep-mountain-abc123.trycloudflare.com"
}
```
</Tab>
<Tab title="200 (Inactive)">
```json
{
"active": false,
"url": null
}
```
</Tab>
</Tabs>
</ResponseExample>

82
docs/api/get-webhooks.mdx Normal file
View File

@@ -0,0 +1,82 @@
---
title: List Webhooks
description: "List all configured inbound webhook slots in PocketPaw. Each webhook has a unique ID, auto-generated secret for authentication, and a URL for receiving external payloads."
api: GET /api/webhooks
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["list webhooks", "inbound webhooks", "webhook slots"]
tags: ["api", "webhooks"]
---
## Overview
Returns all configured inbound webhook slots. Each webhook slot provides a unique URL and secret for receiving external payloads that are forwarded to the agent.
## Response
<ResponseField name="webhooks" type="array">
Array of webhook slot objects.
<ResponseField name="name" type="string">Webhook slot name (URL slug)</ResponseField>
<ResponseField name="description" type="string">Human-readable description</ResponseField>
<ResponseField name="secret" type="string">Webhook verification secret</ResponseField>
<ResponseField name="url" type="string">Full webhook URL</ResponseField>
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X GET "http://localhost:8000/api/webhooks" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/webhooks", {
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.get(
"http://localhost:8000/api/webhooks",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"webhooks": [
{
"name": "github-events",
"description": "GitHub repository webhooks",
"secret": "whsec_a1b2c3d4e5f6...",
"url": "http://localhost:8000/webhook/inbound/github-events"
},
{
"name": "stripe-payments",
"description": "Stripe payment notifications",
"secret": "whsec_x7y8z9w0...",
"url": "http://localhost:8000/webhook/inbound/stripe-payments"
}
]
}
```
</Tab>
</Tabs>
</ResponseExample>

157
docs/api/index.mdx Normal file
View File

@@ -0,0 +1,157 @@
---
title: API Reference
description: "Complete REST API reference for the PocketPaw web dashboard: channels, sessions, MCP servers, memory, security, authentication, webhooks, tunnel, Deep Work, and Mission Control endpoints."
section: API Reference
ogType: article
keywords: ["rest api", "api reference", "dashboard api", "endpoints", "http api"]
tags: ["api", "reference"]
---
# API Reference
The PocketPaw web dashboard exposes a comprehensive REST API for managing channels, sessions, MCP servers, memory, security, and more. All endpoints are served by the FastAPI backend.
<Card title="Base URL" icon="lucide:globe">
```
http://localhost:8000
```
</Card>
## Endpoint Groups
<CardGroup cols={3}>
<Card title="Channels" icon="lucide:radio" href="/api/get-channels-status">
Start, stop, and configure messaging channels (Discord, Slack, WhatsApp, Telegram, etc.)
</Card>
<Card title="Sessions" icon="lucide:history" href="/api/get-sessions">
List, search, rename, and delete chat sessions.
</Card>
<Card title="MCP Servers" icon="lucide:server" href="/api/get-mcp-status">
Add, remove, toggle, and test Model Context Protocol servers.
</Card>
<Card title="Memory" icon="lucide:brain" href="/api/get-memory-long-term">
Manage long-term memories, memory settings, and backend statistics.
</Card>
<Card title="Security" icon="lucide:shield" href="/api/get-audit-logs">
View audit logs, run security audits, and manage self-audit reports.
</Card>
<Card title="Authentication" icon="lucide:key" href="/api/post-auth-session">
Session tokens, QR login, OAuth flows, and token management.
</Card>
<Card title="Webhooks" icon="lucide:webhook" href="/api/get-webhooks">
Manage inbound webhook slots and external platform webhooks.
</Card>
<Card title="Tunnel" icon="lucide:cloud" href="/api/get-tunnel-status">
Start and stop Cloudflare tunnels for remote access.
</Card>
</CardGroup>
## Authentication
Most API endpoints require authentication. PocketPaw supports multiple auth methods:
<Tabs>
<Tab title="Bearer Token">
```bash
curl http://localhost:8000/api/sessions \
-H "Authorization: Bearer your-access-token"
```
</Tab>
<Tab title="Query Parameter">
```bash
curl "http://localhost:8000/api/sessions?token=your-access-token"
```
</Tab>
<Tab title="Localhost Bypass">
Requests from `127.0.0.1` or `::1` bypass auth automatically (unless a Cloudflare tunnel is active).
</Tab>
</Tabs>
<Callout type="info">
Auth-exempt paths: `/webhook/*`, `/oauth/callback`, `/api/qr`, `/static/*`, `/favicon.ico`
</Callout>
## Quick Reference
### Channels
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [/api/channels/status](/api/get-channels-status) | Get all channel statuses |
| `POST` | [/api/channels/save](/api/post-channels-save) | Save channel configuration |
| `POST` | [/api/channels/toggle](/api/post-channels-toggle) | Start or stop a channel |
### Sessions
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [/api/sessions](/api/get-sessions) | List all sessions |
| `GET` | [/api/sessions/search](/api/get-sessions-search) | Search sessions |
| `DELETE` | [/api/sessions/\{id\}](/api/delete-session) | Delete a session |
| `POST` | [/api/sessions/\{id\}/title](/api/post-session-title) | Rename a session |
| `GET` | [/api/memory/session](/api/get-session-history) | Get session messages |
### MCP Servers
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [/api/mcp/status](/api/get-mcp-status) | Get MCP server statuses |
| `POST` | [/api/mcp/add](/api/post-mcp-add) | Add an MCP server |
| `POST` | [/api/mcp/remove](/api/post-mcp-remove) | Remove an MCP server |
| `POST` | [/api/mcp/toggle](/api/post-mcp-toggle) | Enable/disable MCP server |
| `POST` | [/api/mcp/test](/api/post-mcp-test) | Test server connection |
| `GET` | [/api/mcp/presets](/api/get-mcp-presets) | List available presets |
| `POST` | [/api/mcp/presets/install](/api/post-mcp-preset-install) | Install a preset |
### Memory
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [/api/memory/long_term](/api/get-memory-long-term) | List long-term memories |
| `DELETE` | [/api/memory/long_term/\{id\}](/api/delete-memory-entry) | Delete a memory entry |
| `GET` | [/api/memory/settings](/api/get-memory-settings) | Get memory config |
| `POST` | [/api/memory/settings](/api/post-memory-settings) | Update memory config |
| `GET` | [/api/memory/stats](/api/get-memory-stats) | Get memory statistics |
### Security & Audit
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [/api/audit](/api/get-audit-logs) | Get audit log entries |
| `POST` | [/api/security-audit](/api/post-security-audit) | Run security audit |
| `GET` | [/api/self-audit/reports](/api/get-self-audit-reports) | List audit reports |
| `GET` | [/api/self-audit/reports/\{date\}](/api/get-self-audit-report) | Get specific report |
| `POST` | [/api/self-audit/run](/api/post-self-audit-run) | Trigger self-audit |
### Authentication & OAuth
| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | [/api/auth/session](/api/post-auth-session) | Get session token |
| `GET` | [/api/qr](/api/get-qr-code) | Generate QR login code |
| `POST` | [/api/token/regenerate](/api/post-token-regenerate) | Regenerate access token |
| `GET` | [/api/oauth/authorize](/api/get-oauth-authorize) | Start OAuth flow |
### Webhooks
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [/api/webhooks](/api/get-webhooks) | List webhook slots |
| `POST` | [/api/webhooks/add](/api/post-webhooks-add) | Create webhook slot |
| `POST` | [/api/webhooks/remove](/api/post-webhooks-remove) | Remove webhook slot |
| `POST` | [/webhook/inbound/\{name\}](/api/post-webhook-inbound) | Receive webhook payload |
### Tunnel
| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | [/api/remote/status](/api/get-tunnel-status) | Get tunnel status |
| `POST` | [/api/remote/start](/api/post-tunnel-start) | Start Cloudflare tunnel |
| `POST` | [/api/remote/stop](/api/post-tunnel-stop) | Stop tunnel |

View File

@@ -0,0 +1,74 @@
---
title: Create Session Token
description: "Exchange a master access token for a time-limited session token. Session tokens provide temporary authenticated access to the PocketPaw dashboard API with automatic expiration."
api: POST /api/auth/session
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["session token", "authentication", "token exchange"]
tags: ["api", "authentication"]
---
## Overview
Exchanges the master access token for a time-limited session token. Session tokens are useful for browser-based access where storing the master token is undesirable.
## Request Headers
<ParamTable type="header">
<Param name="Authorization" type="string" required>
`Bearer {master_token}` — the master access token.
</Param>
</ParamTable>
## Response
<ResponseField name="session_token" type="string">A time-limited HMAC-signed session token</ResponseField>
<ResponseField name="expires_in_hours" type="integer">Token validity period in hours</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/auth/session" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/auth/session", {
method: "POST",
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/auth/session",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"session_token": "session:1705312200:a1b2c3d4e5f6...",
"expires_in_hours": 24
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,116 @@
---
title: Save Channel Config
description: "Save configuration credentials and settings for a PocketPaw channel adapter. Supports Discord, Slack, WhatsApp, Signal, Matrix, Teams, and Google Chat configuration fields."
api: POST /api/channels/save
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["save channel config", "channel credentials", "adapter configuration"]
tags: ["api", "channels"]
---
## Overview
Saves the configuration (tokens, IDs, credentials) for a specific channel adapter. The config keys are mapped to internal Settings fields automatically.
## Request Body
<ParamTable type="body">
<Param name="channel" type="string" required>
Channel identifier. One of: `discord`, `slack`, `whatsapp`, `telegram`, `signal`, `matrix`, `teams`, `gchat`.
</Param>
<Param name="config" type="object" required>
Key-value pairs of configuration fields specific to the channel. See examples below.
</Param>
</ParamTable>
## Response
<ResponseField name="status" type="string">
Always `"ok"` on success.
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/channels/save" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"channel": "discord",
"config": {
"bot_token": "MTIzNDU2Nzg5.abc.xyz",
"allowed_guild_ids": "111222333,444555666",
"allowed_user_ids": "999888777"
}
}'
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/channels/save", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({
channel: "discord",
config: {
bot_token: "MTIzNDU2Nzg5.abc.xyz",
allowed_guild_ids: "111222333,444555666",
allowed_user_ids: "999888777"
}
})
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/channels/save",
headers={"Authorization": "Bearer <token>"},
json={
"channel": "discord",
"config": {
"bot_token": "MTIzNDU2Nzg5.abc.xyz",
"allowed_guild_ids": "111222333,444555666",
"allowed_user_ids": "999888777",
},
},
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{ "status": "ok" }
```
</Tab>
</Tabs>
</ResponseExample>
## Channel Config Keys
| Channel | Config Keys |
|---------|-------------|
| Discord | `bot_token`, `allowed_guild_ids`, `allowed_user_ids` |
| Slack | `bot_token`, `app_token`, `allowed_channel_ids` |
| WhatsApp | `mode`, `access_token`, `phone_number_id`, `verify_token`, `allowed_phone_numbers`, `neonize_db` |
| Telegram | `bot_token`, `allowed_user_id` |
| Signal | `api_url`, `phone_number`, `allowed_phone_numbers` |
| Matrix | `homeserver`, `user_id`, `access_token`, `password`, `allowed_room_ids`, `device_id` |
| Teams | `app_id`, `app_password`, `allowed_tenant_ids`, `webhook_port` |
| Google Chat | `mode`, `service_account_key`, `project_id`, `subscription_id`, `allowed_space_ids` |

View File

@@ -0,0 +1,102 @@
---
title: Toggle Channel
description: "Start or stop a PocketPaw channel adapter dynamically without restarting the server. Toggle channels on and off from the dashboard or via API calls for runtime channel management."
api: POST /api/channels/toggle
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["toggle channel", "start stop adapter", "dynamic channel control"]
tags: ["api", "channels"]
---
## Overview
Starts or stops a channel adapter at runtime without restarting the server. The channel must be configured (have valid credentials) before it can be started.
## Request Body
<ParamTable type="body">
<Param name="channel" type="string" required>
Channel identifier. One of: `discord`, `slack`, `whatsapp`, `telegram`, `signal`, `matrix`, `teams`, `gchat`.
</Param>
<Param name="action" type="string" required enum={["start", "stop"]}>
Whether to start or stop the adapter.
</Param>
</ParamTable>
## Response
<ResponseField name="channel" type="string">The channel that was toggled</ResponseField>
<ResponseField name="configured" type="boolean">Whether the channel has valid credentials</ResponseField>
<ResponseField name="running" type="boolean">Whether the channel is now running after the toggle</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/channels/toggle" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"channel": "discord",
"action": "start"
}'
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/channels/toggle", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({
channel: "discord",
action: "start"
})
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/channels/toggle",
headers={"Authorization": "Bearer <token>"},
json={"channel": "discord", "action": "start"},
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200", "400", "500"]}>
<Tab title="200">
```json
{
"channel": "discord",
"configured": true,
"running": true
}
```
</Tab>
<Tab title="400">
```json
{ "detail": "Channel is not configured (missing credentials)" }
```
</Tab>
<Tab title="500">
```json
{ "detail": "Adapter failed to start" }
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,85 @@
---
title: Approve Deep Work Plan
description: "Approve a Deep Work project plan and transition it to autonomous execution. All tasks with no blockers are dispatched immediately to their assigned agents for parallel processing."
api: POST /api/deep-work/projects/{project_id}/approve
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["approve plan", "start execution", "project approval"]
tags: ["api", "deep-work"]
---
## Overview
Approves a Deep Work project plan and transitions it to `EXECUTING` status. All tasks with no blockers are dispatched immediately.
## Path Parameters
<ResponseField name="project_id" type="string" required>
The project ID. Project must be in `awaiting_approval` status.
</ResponseField>
## Response
<ResponseField name="success" type="boolean">
Whether the project was approved and execution started.
</ResponseField>
<ResponseField name="project" type="object">
The updated project object with `status: "executing"`.
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST http://localhost:8000/api/deep-work/projects/PROJECT_ID/approve \
-H "Authorization: Bearer YOUR_TOKEN"
```
</Tab>
<Tab title="JavaScript">
```javascript
const res = await fetch(`http://localhost:8000/api/deep-work/projects/${projectId}/approve`, {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_TOKEN' },
});
```
</Tab>
<Tab title="Python">
```python
import httpx
res = httpx.post(
f"http://localhost:8000/api/deep-work/projects/{project_id}/approve",
headers={"Authorization": "Bearer YOUR_TOKEN"},
)
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200", "400"]}>
<Tab title="200">
```json
{
"success": true,
"project": {
"id": "a1b2c3d4...",
"status": "executing",
"started_at": "2024-01-15T14:35:00Z"
}
}
```
</Tab>
<Tab title="400">
```json
{
"detail": "Project status is not awaiting_approval"
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,59 @@
---
title: Pause Deep Work Project
description: "Pause a running Deep Work project and stop all currently executing agent tasks. The project can be resumed later with all progress preserved and ready tasks re-dispatched."
api: POST /api/deep-work/projects/{project_id}/pause
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["pause project", "stop execution", "suspend work"]
tags: ["api", "deep-work"]
---
## Overview
Pauses a running Deep Work project. All currently executing tasks are stopped. The project can be resumed later.
## Path Parameters
<ResponseField name="project_id" type="string" required>
The project ID. Project must be in `executing` status.
</ResponseField>
## Response
<ResponseField name="success" type="boolean">
Whether the project was paused.
</ResponseField>
<ResponseField name="project" type="object">
The updated project with `status: "paused"`.
</ResponseField>
<RequestExample>
<Tabs items={["cURL"]}>
<Tab title="cURL">
```bash
curl -X POST http://localhost:8000/api/deep-work/projects/PROJECT_ID/pause \
-H "Authorization: Bearer YOUR_TOKEN"
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"success": true,
"project": {
"id": "a1b2c3d4...",
"status": "paused"
}
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,59 @@
---
title: Resume Deep Work Project
description: "Resume a paused Deep Work project and re-dispatch all ready tasks. Tasks whose blockers have been resolved during the pause are included in the next execution wave."
api: POST /api/deep-work/projects/{project_id}/resume
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["resume project", "continue execution", "restart work"]
tags: ["api", "deep-work"]
---
## Overview
Resumes a paused Deep Work project. All ready tasks (with no unresolved blockers) are dispatched for execution.
## Path Parameters
<ResponseField name="project_id" type="string" required>
The project ID. Project must be in `paused` status.
</ResponseField>
## Response
<ResponseField name="success" type="boolean">
Whether the project was resumed.
</ResponseField>
<ResponseField name="project" type="object">
The updated project with `status: "executing"`.
</ResponseField>
<RequestExample>
<Tabs items={["cURL"]}>
<Tab title="cURL">
```bash
curl -X POST http://localhost:8000/api/deep-work/projects/PROJECT_ID/resume \
-H "Authorization: Bearer YOUR_TOKEN"
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"success": true,
"project": {
"id": "a1b2c3d4...",
"status": "executing"
}
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,82 @@
---
title: Skip Deep Work Task
description: "Skip a task in a Deep Work project without executing it. The task is marked as SKIPPED, its dependents are unblocked, and project progress is recalculated to reflect the change."
api: POST /api/deep-work/projects/{project_id}/tasks/{task_id}/skip
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["skip task", "bypass task", "unblock dependents"]
tags: ["api", "deep-work"]
---
## Overview
Skips a task without running it. The task is marked as `SKIPPED` and dependent tasks are unblocked, allowing execution to continue.
## Path Parameters
<ResponseField name="project_id" type="string" required>
The project ID.
</ResponseField>
<ResponseField name="task_id" type="string" required>
The task ID to skip. Must belong to the project and not already be done, skipped, or in progress.
</ResponseField>
## Response
<ResponseField name="success" type="boolean">
Whether the task was skipped.
</ResponseField>
<ResponseField name="task" type="object">
The updated task with `status: "skipped"`.
</ResponseField>
<ResponseField name="progress" type="object">
Updated project progress after the skip.
</ResponseField>
<RequestExample>
<Tabs items={["cURL"]}>
<Tab title="cURL">
```bash
curl -X POST http://localhost:8000/api/deep-work/projects/PROJECT_ID/tasks/TASK_ID/skip \
-H "Authorization: Bearer YOUR_TOKEN"
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200", "400"]}>
<Tab title="200">
```json
{
"success": true,
"task": {
"id": "task-3",
"title": "Write unit tests",
"status": "skipped",
"completed_at": "2024-01-15T15:00:00Z"
},
"progress": {
"total": 8,
"completed": 3,
"skipped": 1,
"percent": 50
}
}
```
</Tab>
<Tab title="400">
```json
{
"detail": "Task is already done or in progress"
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,111 @@
---
title: Start Deep Work Project
description: "Create a new Deep Work project and start the AI-powered planning pipeline in the background. Returns the project immediately while research, PRD generation, and task breakdown run asynchronously."
api: POST /api/deep-work/start
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["start project", "deep work", "ai planning", "project creation"]
tags: ["api", "deep-work"]
---
## Overview
Creates a new Deep Work project and starts the planning pipeline in the background. The project is returned immediately in `PLANNING` status. Track progress via WebSocket events (`dw_planning_phase`, `dw_planning_complete`).
## Request Body
<ResponseField name="description" type="string" required>
Natural-language description of the project to plan and execute. Min 10, max 5000 characters.
</ResponseField>
<ResponseField name="research_depth" type="string" default="standard">
How deeply to research before planning. One of: `none`, `quick`, `standard`, `deep`.
</ResponseField>
## Response
<ResponseField name="success" type="boolean">
Whether the project was created successfully.
</ResponseField>
<ResponseField name="project" type="object">
The created project object.
<ResponseField name="id" type="string">Unique project ID.</ResponseField>
<ResponseField name="title" type="string">Project title (extracted from PRD after planning).</ResponseField>
<ResponseField name="status" type="string">Current status — will be `planning` initially.</ResponseField>
<ResponseField name="created_at" type="string">ISO 8601 timestamp.</ResponseField>
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST http://localhost:8000/api/deep-work/start \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"description": "Build a REST API for recipe management with user auth and search",
"research_depth": "standard"
}'
```
</Tab>
<Tab title="JavaScript">
```javascript
const res = await fetch('http://localhost:8000/api/deep-work/start', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
description: 'Build a REST API for recipe management with user auth and search',
research_depth: 'standard',
}),
});
const data = await res.json();
```
</Tab>
<Tab title="Python">
```python
import httpx
res = httpx.post(
"http://localhost:8000/api/deep-work/start",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={
"description": "Build a REST API for recipe management with user auth and search",
"research_depth": "standard",
},
)
data = res.json()
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"success": true,
"project": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"title": "",
"description": "Build a REST API for recipe management with user auth and search",
"status": "planning",
"creator_id": "human",
"task_ids": [],
"team_agent_ids": [],
"tags": [],
"created_at": "2024-01-15T14:30:00Z",
"updated_at": "2024-01-15T14:30:00Z"
}
}
```
</Tab>
</Tabs>
</ResponseExample>

112
docs/api/post-mc-agent.mdx Normal file
View File

@@ -0,0 +1,112 @@
---
title: Create Mission Control Agent
description: "Register a new AI agent in PocketPaw's Mission Control with a name, role, specialties, backend configuration, and autonomy level. Agents can be assigned to tasks for autonomous execution."
api: POST /api/mission-control/agents
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["create agent", "register agent", "agent profile"]
tags: ["api", "mission-control"]
---
## Overview
Creates a new agent profile in Mission Control. Agents can be assigned to tasks and execute them autonomously.
## Request Body
<ResponseField name="name" type="string" required>
Agent name (lowercase-hyphenated, e.g., `backend-dev`).
</ResponseField>
<ResponseField name="role" type="string" required>
Job title (e.g., `Backend Engineer`).
</ResponseField>
<ResponseField name="description" type="string">
What this agent is responsible for.
</ResponseField>
<ResponseField name="specialties" type="array">
List of skill domains (e.g., `["backend", "database"]`).
</ResponseField>
<ResponseField name="backend" type="string" default="claude_agent_sdk">
Agent backend to use.
</ResponseField>
<ResponseField name="level" type="string" default="specialist">
Autonomy level: `intern`, `specialist`, or `lead`.
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST http://localhost:8000/api/mission-control/agents \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "backend-dev",
"role": "Backend Engineer",
"description": "Handles API and database work",
"specialties": ["backend", "database", "api"]
}'
```
</Tab>
<Tab title="JavaScript">
```javascript
const res = await fetch('http://localhost:8000/api/mission-control/agents', {
method: 'POST',
headers: {
'Authorization': 'Bearer YOUR_TOKEN',
'Content-Type': 'application/json',
},
body: JSON.stringify({
name: 'backend-dev',
role: 'Backend Engineer',
specialties: ['backend', 'database', 'api'],
}),
});
```
</Tab>
<Tab title="Python">
```python
import httpx
res = httpx.post(
"http://localhost:8000/api/mission-control/agents",
headers={"Authorization": "Bearer YOUR_TOKEN"},
json={
"name": "backend-dev",
"role": "Backend Engineer",
"specialties": ["backend", "database", "api"],
},
)
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"agent": {
"id": "agent-uuid-1",
"name": "backend-dev",
"role": "Backend Engineer",
"status": "idle",
"specialties": ["backend", "database", "api"],
"backend": "claude_agent_sdk",
"level": "specialist",
"created_at": "2024-01-15T14:30:00Z"
}
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,73 @@
---
title: Run Mission Control Task
description: "Execute a Mission Control task with a specified AI agent in the background. The agent receives the task description, project context, and upstream deliverables. Output streams via WebSocket events."
api: POST /api/mission-control/tasks/{task_id}/run
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["run task", "execute task", "agent execution"]
tags: ["api", "mission-control"]
---
## Overview
Starts background execution of a task with a specified agent. The agent receives the task description, project context, and upstream deliverables as its prompt. Output streams via WebSocket events (`mc_task_output`).
Up to 5 tasks can run concurrently.
## Path Parameters
<ResponseField name="task_id" type="string" required>
The task ID to execute.
</ResponseField>
## Request Body
<ResponseField name="agent_id" type="string" required>
The agent ID to execute the task. Must be a valid UUID.
</ResponseField>
## Response
<ResponseField name="success" type="boolean">
Whether the task was launched.
</ResponseField>
<ResponseField name="message" type="string">
Status message.
</ResponseField>
<RequestExample>
<Tabs items={["cURL"]}>
<Tab title="cURL">
```bash
curl -X POST http://localhost:8000/api/mission-control/tasks/TASK_ID/run \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"agent_id": "AGENT_UUID"}'
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200", "429"]}>
<Tab title="200">
```json
{
"success": true,
"message": "Task execution started"
}
```
</Tab>
<Tab title="429">
```json
{
"detail": "Maximum concurrent tasks (5) reached"
}
```
</Tab>
</Tabs>
</ResponseExample>

81
docs/api/post-mc-task.mdx Normal file
View File

@@ -0,0 +1,81 @@
---
title: Create Mission Control Task
description: "Create a new task in PocketPaw's Mission Control with title, description, priority, tags, and optional agent assignment. Tasks can be linked to Deep Work projects for orchestrated execution."
api: POST /api/mission-control/tasks
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["create task", "task creation", "assign task"]
tags: ["api", "mission-control"]
---
## Overview
Creates a new task. Optionally link it to a Deep Work project and assign it to agents.
## Request Body
<ResponseField name="title" type="string" required>
Task title.
</ResponseField>
<ResponseField name="description" type="string">
Full task description with acceptance criteria.
</ResponseField>
<ResponseField name="priority" type="string" default="medium">
Priority: `low`, `medium`, `high`, or `urgent`.
</ResponseField>
<ResponseField name="tags" type="array">
List of categorization tags.
</ResponseField>
<ResponseField name="assignee_ids" type="array">
Agent IDs to assign the task to.
</ResponseField>
<ResponseField name="project_id" type="string">
Deep Work project to associate with.
</ResponseField>
<RequestExample>
<Tabs items={["cURL"]}>
<Tab title="cURL">
```bash
curl -X POST http://localhost:8000/api/mission-control/tasks \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Implement user authentication",
"description": "Add JWT-based auth with login/register endpoints",
"priority": "high",
"tags": ["backend", "security"],
"assignee_ids": ["agent-uuid-1"]
}'
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"task": {
"id": "task-uuid-2",
"title": "Implement user authentication",
"status": "assigned",
"priority": "high",
"assignee_ids": ["agent-uuid-1"],
"tags": ["backend", "security"],
"created_at": "2024-01-15T14:32:00Z"
}
}
```
</Tab>
</Tabs>
</ResponseExample>

116
docs/api/post-mcp-add.mdx Normal file
View File

@@ -0,0 +1,116 @@
---
title: Add MCP Server
description: "Add a new MCP server configuration to PocketPaw. Specify the server name, command, arguments, environment variables, and transport type for stdio or HTTP-based MCP servers."
api: POST /api/mcp/add
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["add mcp server", "mcp configuration", "server setup"]
tags: ["api", "mcp"]
---
## Overview
Adds a new MCP server to the configuration. The server can use either `stdio` transport (local process) or `http` transport (remote URL).
## Request Body
<ParamTable type="body">
<Param name="name" type="string" required>
Unique identifier for the server. Used as the key in config and tool naming (`mcp_<name>__<tool>`).
</Param>
<Param name="transport" type="string" required enum={["stdio", "http"]}>
Transport protocol. Use `stdio` for local processes or `http` for remote servers.
</Param>
<Param name="command" type="string">
Command to execute for `stdio` transport (e.g., `npx`, `python`).
</Param>
<Param name="args" type="array">
Command arguments for `stdio` transport.
</Param>
<Param name="url" type="string">
Server URL for `http` transport.
</Param>
<Param name="env" type="object">
Environment variables to pass to the server process.
</Param>
<Param name="enabled" type="boolean" default="true">
Whether to enable the server immediately.
</Param>
</ParamTable>
## Response
<ResponseField name="status" type="string">`"ok"` on success</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/mcp/add" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "filesystem",
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"],
"env": {},
"enabled": true
}'
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/mcp/add", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "filesystem",
transport: "stdio",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"],
env: {},
enabled: true
})
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/mcp/add",
headers={"Authorization": "Bearer <token>"},
json={
"name": "filesystem",
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"],
"env": {},
"enabled": True
}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{ "status": "ok" }
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,98 @@
---
title: Install MCP Preset
description: "Install an MCP server from a preset template with a single API call. The preset provides pre-configured command, arguments, and environment variables for popular MCP servers."
api: POST /api/mcp/presets/install
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["install preset", "mcp template", "quick setup"]
tags: ["api", "mcp"]
---
## Overview
Installs an MCP server from a preset template. Automatically configures the server with the correct command, args, and transport. Optionally tests the connection after installation.
## Request Body
<ParamTable type="body">
<Param name="preset_id" type="string" required>
The preset identifier to install (from the presets list).
</Param>
<Param name="env" type="object">
Environment variables required by the preset (e.g., API keys).
</Param>
<Param name="extra_args" type="array">
Additional command-line arguments to append to the preset defaults.
</Param>
</ParamTable>
## Response
<ResponseField name="status" type="string">`"ok"` on success</ResponseField>
<ResponseField name="connected" type="boolean">Whether the server connected successfully after installation</ResponseField>
<ResponseField name="tools" type="array">Tools discovered from the newly installed server</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/mcp/presets/install" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"preset_id": "github",
"env": {"GITHUB_TOKEN": "ghp_xxxxxxxxxxxx"}
}'
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/mcp/presets/install", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({
preset_id: "github",
env: { GITHUB_TOKEN: "ghp_xxxxxxxxxxxx" }
})
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/mcp/presets/install",
headers={"Authorization": "Bearer <token>"},
json={
"preset_id": "github",
"env": {"GITHUB_TOKEN": "ghp_xxxxxxxxxxxx"}
}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"status": "ok",
"connected": true,
"tools": ["create_issue", "list_repos", "create_pull_request", "search_code"]
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,82 @@
---
title: Remove MCP Server
description: "Remove an MCP server configuration from PocketPaw. If the server is currently running, it will be stopped before removal. The server's tools become unavailable immediately."
api: POST /api/mcp/remove
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["remove mcp server", "uninstall server", "delete mcp"]
tags: ["api", "mcp"]
---
## Overview
Removes an MCP server from the configuration. If the server is currently running, it will be stopped first.
## Request Body
<ParamTable type="body">
<Param name="name" type="string" required>
The name of the MCP server to remove.
</Param>
</ParamTable>
## Response
<ResponseField name="status" type="string">`"ok"` on success</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/mcp/remove" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"name": "filesystem"}'
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/mcp/remove", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({ name: "filesystem" })
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/mcp/remove",
headers={"Authorization": "Bearer <token>"},
json={"name": "filesystem"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200", "404"]}>
<Tab title="200">
```json
{ "status": "ok" }
```
</Tab>
<Tab title="404">
```json
{ "detail": "Server not found in configuration" }
```
</Tab>
</Tabs>
</ResponseExample>

125
docs/api/post-mcp-test.mdx Normal file
View File

@@ -0,0 +1,125 @@
---
title: Test MCP Server
description: "Test an MCP server connection by starting it temporarily and listing its available tools. Returns the tool count and tool names to verify the server is working correctly."
api: POST /api/mcp/test
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["test mcp", "server connection test", "tool discovery"]
tags: ["api", "mcp"]
---
## Overview
Tests connectivity to an MCP server without persisting it to configuration. Useful for validating server settings before adding them. Returns the connection status and list of available tools.
## Request Body
<ParamTable type="body">
<Param name="name" type="string" required>
A temporary name for the test connection.
</Param>
<Param name="transport" type="string" required enum={["stdio", "http"]}>
Transport protocol to test.
</Param>
<Param name="command" type="string">
Command for `stdio` transport.
</Param>
<Param name="args" type="array">
Arguments for `stdio` transport.
</Param>
<Param name="url" type="string">
Server URL for `http` transport.
</Param>
<Param name="env" type="object">
Environment variables to pass.
</Param>
</ParamTable>
## Response
<ResponseField name="connected" type="boolean">Whether the connection succeeded</ResponseField>
<ResponseField name="error" type="string" nullable>Error message if connection failed</ResponseField>
<ResponseField name="tools" type="array">List of tool names discovered from the server</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/mcp/test" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "filesystem",
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"],
"env": {}
}'
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/mcp/test", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "filesystem",
transport: "stdio",
command: "npx",
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"],
env: {}
})
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/mcp/test",
headers={"Authorization": "Bearer <token>"},
json={
"name": "filesystem",
"transport": "stdio",
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"],
"env": {}
}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200 (Success)", "200 (Failure)"]}>
<Tab title="200 (Success)">
```json
{
"connected": true,
"error": null,
"tools": ["read_file", "write_file", "list_directory", "search_files"]
}
```
</Tab>
<Tab title="200 (Failure)">
```json
{
"connected": false,
"error": "Connection timed out after 10s",
"tools": []
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,81 @@
---
title: Toggle MCP Server
description: "Enable or disable an MCP server in PocketPaw without removing its configuration. Disabled servers retain their settings but their tools are not available to the agent."
api: POST /api/mcp/toggle
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["toggle mcp", "enable disable server", "mcp control"]
tags: ["api", "mcp"]
---
## Overview
Enables or disables an MCP server. Disabling a server stops its process and removes its tools from the agent. Enabling starts the server and makes its tools available.
## Request Body
<ParamTable type="body">
<Param name="name" type="string" required>
The name of the MCP server to toggle.
</Param>
</ParamTable>
## Response
<ResponseField name="status" type="string">`"ok"` on success</ResponseField>
<ResponseField name="enabled" type="boolean">The new enabled state of the server</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/mcp/toggle" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"name": "filesystem"}'
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/mcp/toggle", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({ name: "filesystem" })
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/mcp/toggle",
headers={"Authorization": "Bearer <token>"},
json={"name": "filesystem"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"status": "ok",
"enabled": true
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,124 @@
---
title: Update Memory Settings
description: "Update PocketPaw's memory backend configuration: switch between file store and Mem0, configure LLM and embedder providers, set vector store options, and toggle auto-learning."
api: POST /api/memory/settings
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["update memory settings", "memory configuration", "backend switch"]
tags: ["api", "memory"]
---
## Overview
Updates the memory backend configuration. Changes take effect immediately — the memory manager is reloaded with the new settings.
## Request Body
<ParamTable type="body">
<Param name="memory_backend" type="string" enum={["file", "mem0"]}>
Memory backend to use. `file` is the default file-based store, `mem0` enables semantic memory with auto-learn.
</Param>
<Param name="mem0_llm_provider" type="string" enum={["ollama", "openai", "anthropic"]}>
LLM provider for mem0's extraction and summarization.
</Param>
<Param name="mem0_llm_model" type="string">
LLM model name (e.g., `llama3.2`, `gpt-4o-mini`).
</Param>
<Param name="mem0_embedder_provider" type="string" enum={["ollama", "openai"]}>
Embedding provider for semantic search.
</Param>
<Param name="mem0_embedder_model" type="string">
Embedding model name (e.g., `nomic-embed-text`, `text-embedding-3-small`).
</Param>
<Param name="mem0_vector_store" type="string" enum={["qdrant"]}>
Vector store backend.
</Param>
<Param name="mem0_ollama_base_url" type="string">
Ollama server URL (default: `http://localhost:11434`).
</Param>
<Param name="mem0_auto_learn" type="boolean">
Enable automatic memory extraction from conversations.
</Param>
</ParamTable>
## Response
<ResponseField name="status" type="string">`"ok"` on success</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/memory/settings" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"memory_backend": "mem0",
"mem0_llm_provider": "ollama",
"mem0_llm_model": "llama3.2",
"mem0_embedder_provider": "ollama",
"mem0_embedder_model": "nomic-embed-text",
"mem0_vector_store": "qdrant",
"mem0_auto_learn": true
}'
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/memory/settings", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({
memory_backend: "mem0",
mem0_llm_provider: "ollama",
mem0_llm_model: "llama3.2",
mem0_embedder_provider: "ollama",
mem0_embedder_model: "nomic-embed-text",
mem0_vector_store: "qdrant",
mem0_auto_learn: true
})
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/memory/settings",
headers={"Authorization": "Bearer <token>"},
json={
"memory_backend": "mem0",
"mem0_llm_provider": "ollama",
"mem0_llm_model": "llama3.2",
"mem0_embedder_provider": "ollama",
"mem0_embedder_model": "nomic-embed-text",
"mem0_vector_store": "qdrant",
"mem0_auto_learn": True
}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"status": "ok"
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,89 @@
---
title: Run Security Audit
description: "Execute PocketPaw's 7 built-in security audit checks on demand and return detailed results. Detects misconfigurations in permissions, tokens, API keys, and security settings."
api: POST /api/security-audit
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["run security audit", "security checks", "misconfiguration detection"]
tags: ["api", "security"]
---
## Overview
Runs the 7 built-in security audit checks against the current configuration and returns detailed results. This is the API equivalent of `pocketpaw --security-audit`.
## Response
<ResponseField name="total" type="integer">Total number of checks executed</ResponseField>
<ResponseField name="passed" type="integer">Number of checks that passed</ResponseField>
<ResponseField name="issues" type="integer">Number of checks that found issues</ResponseField>
<ResponseField name="results" type="array">
Detailed results for each check.
<ResponseField name="check" type="string">Check name (e.g., `file_permissions`, `api_key_exposure`)</ResponseField>
<ResponseField name="passed" type="boolean">Whether the check passed</ResponseField>
<ResponseField name="message" type="string">Description of what was found</ResponseField>
<ResponseField name="fixable" type="boolean">Whether the issue can be auto-fixed with `--fix`</ResponseField>
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/security-audit" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/security-audit", {
method: "POST",
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/security-audit",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"total": 7,
"passed": 5,
"issues": 2,
"results": [
{
"check": "file_permissions",
"passed": true,
"message": "Config directory permissions are correct (700)",
"fixable": false
},
{
"check": "api_key_exposure",
"passed": false,
"message": "API key found in environment variable without restricted permissions",
"fixable": true
}
]
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,78 @@
---
title: Trigger Self-Audit
description: "Trigger an immediate run of PocketPaw's self-audit daemon. Executes all 12 background security and operational checks and saves a new report accessible via the audit reports endpoint."
api: POST /api/self-audit/run
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["trigger audit", "run daemon", "immediate check"]
tags: ["api", "security"]
---
## Overview
Triggers an immediate run of the self-audit daemon's 12 checks and returns the full report. The report is also saved to disk for future retrieval via the reports endpoint.
## Response
Returns the full audit report (same format as the individual report endpoint):
<ResponseField name="date" type="string">Today's date</ResponseField>
<ResponseField name="total" type="integer">Total checks executed (always 12)</ResponseField>
<ResponseField name="passed" type="integer">Number of passing checks</ResponseField>
<ResponseField name="issues" type="integer">Number of issues found</ResponseField>
<ResponseField name="checks" type="array">Detailed results array</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/self-audit/run" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/self-audit/run", {
method: "POST",
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/self-audit/run",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"date": "2024-01-15",
"total": 12,
"passed": 11,
"issues": 1,
"checks": [
{"name": "config_permissions", "passed": true, "message": "OK", "severity": "info"},
{"name": "audit_log_integrity", "passed": true, "message": "OK", "severity": "info"},
{"name": "memory_store_health", "passed": false, "message": "Qdrant unreachable", "severity": "warning"}
]
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,94 @@
---
title: Rename Session
description: "Update the display title of an existing PocketPaw session. Useful for organizing conversations with descriptive names that appear in the sidebar session list."
api: POST /api/sessions/{session_id}/title
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["rename session", "session title", "update title"]
tags: ["api", "sessions"]
---
## Overview
Updates the display title of a session. By default, sessions are auto-titled based on the first message. Use this endpoint to set a custom title.
## Parameters
<ParamTable type="path">
<Param name="session_id" type="string" required>
The unique identifier of the session to rename.
</Param>
</ParamTable>
## Request Body
<ParamTable type="body">
<Param name="title" type="string" required>
The new title for the session.
</Param>
</ParamTable>
## Response
<ResponseField name="status" type="string">
`"ok"` on successful update.
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/sessions/session_abc123/title" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"title": "Docker deployment guide"}'
```
</Tab>
<Tab title="JavaScript">
```javascript
const sessionId = "session_abc123";
const response = await fetch(`http://localhost:8000/api/sessions/${sessionId}/title`, {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({ title: "Docker deployment guide" })
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
session_id = "session_abc123"
response = requests.post(
f"http://localhost:8000/api/sessions/{session_id}/title",
headers={"Authorization": "Bearer <token>"},
json={"title": "Docker deployment guide"},
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200", "404"]}>
<Tab title="200">
```json
{ "status": "ok" }
```
</Tab>
<Tab title="404">
```json
{ "detail": "Session not found" }
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,68 @@
---
title: Regenerate Access Token
description: "Generate a new PocketPaw access token and invalidate all existing session tokens. Use this to rotate credentials or revoke access after a security incident or personnel change."
api: POST /api/token/regenerate
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["token regeneration", "credential rotation", "revoke access"]
tags: ["api", "authentication"]
---
## Overview
Generates a new master access token and invalidates all existing session tokens. Use this if you suspect the token has been compromised.
<Callout type="warning">
This invalidates **all** active sessions. Every connected client will need to re-authenticate with the new token.
</Callout>
## Response
<ResponseField name="token" type="string">The newly generated access token</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/token/regenerate" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/token/regenerate", {
method: "POST",
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/token/regenerate",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"token": "pk_a1b2c3d4e5f6g7h8i9j0..."
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,79 @@
---
title: Start Tunnel
description: "Start a Cloudflare tunnel to expose PocketPaw's local server with a public HTTPS URL. Required for WhatsApp Business webhooks and remote dashboard access without port forwarding."
api: POST /api/remote/start
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["start tunnel", "cloudflare", "public access", "https tunnel"]
tags: ["api", "tunnel"]
---
## Overview
Starts a Cloudflare quick tunnel that exposes the local dashboard to the internet. No Cloudflare account is required — uses the free `trycloudflare.com` domain.
<Callout type="warning">
When a tunnel is active, localhost auth bypass is disabled. All requests must include a valid token.
</Callout>
## Response (Success)
<ResponseField name="url" type="string">The public tunnel URL</ResponseField>
<ResponseField name="active" type="boolean">`true`</ResponseField>
## Response (Failure)
<ResponseField name="error" type="string">Error message</ResponseField>
<ResponseField name="active" type="boolean">`false`</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/remote/start" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/remote/start", {
method: "POST",
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/remote/start",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"url": "https://steep-mountain-abc123.trycloudflare.com",
"active": true
}
```
</Tab>
</Tabs>
</ResponseExample>
<Callout type="info">
Requires `cloudflared` to be installed on the system. Install via `brew install cloudflared` or `apt install cloudflared`.
</Callout>

View File

@@ -0,0 +1,64 @@
---
title: Stop Tunnel
description: "Stop the active Cloudflare tunnel and revoke the public URL. The PocketPaw server remains accessible locally but is no longer reachable from the internet."
api: POST /api/remote/stop
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["stop tunnel", "revoke url", "disable remote access"]
tags: ["api", "tunnel"]
---
## Overview
Stops the currently running Cloudflare tunnel, removing remote access. The public URL becomes unreachable immediately.
## Response
<ResponseField name="active" type="boolean">`false` after stopping</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/remote/stop" \
-H "Authorization: Bearer <token>"
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/remote/stop", {
method: "POST",
headers: { "Authorization": "Bearer <token>" }
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/remote/stop",
headers={"Authorization": "Bearer <token>"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"active": false
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,112 @@
---
title: Receive Webhook Payload
description: "Receive an inbound webhook payload and forward it to the PocketPaw agent for processing. Validates the webhook secret, parses the payload, and publishes it to the message bus."
api: POST /webhook/inbound/{webhook_name}
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: none
section: API Reference
ogType: article
keywords: ["receive payload", "webhook handler", "inbound data"]
tags: ["api", "webhooks"]
---
## Overview
Receives an external webhook payload and forwards it to the agent as an inbound message. Supports both async (fire-and-forget) and synchronous (wait for agent response) modes.
Authentication is via webhook secret header, not the standard Bearer token.
## Parameters
<ParamTable type="path">
<Param name="webhook_name" type="string" required>
The webhook slot name to receive the payload on.
</Param>
</ParamTable>
<ParamTable type="query">
<Param name="wait" type="boolean" default="false">
If `true`, waits for the agent to process the payload and returns the response synchronously.
</Param>
</ParamTable>
<ParamTable type="header">
<Param name="X-Webhook-Secret" type="string">
Webhook verification secret (must match the slot's secret).
</Param>
<Param name="X-Webhook-Signature" type="string">
Alternative: HMAC-SHA256 signature of the request body using the slot's secret.
</Param>
</ParamTable>
## Response (Async)
<ResponseField name="status" type="string">`"accepted"`</ResponseField>
<ResponseField name="request_id" type="string">Unique ID for tracking the webhook delivery</ResponseField>
## Response (Sync — `?wait=true`)
<ResponseField name="status" type="string">`"ok"`</ResponseField>
<ResponseField name="response" type="string">The agent's response to the webhook payload</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/webhook/inbound/github-events" \
-H "X-Webhook-Secret: whsec_a1b2c3d4e5f6..." \
-H "Content-Type: application/json" \
-d '{"action": "opened", "issue": {"title": "Bug report"}}'
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch(
"http://localhost:8000/webhook/inbound/github-events",
{
method: "POST",
headers: {
"X-Webhook-Secret": "whsec_a1b2c3d4e5f6...",
"Content-Type": "application/json"
},
body: JSON.stringify({
action: "opened",
issue: { title: "Bug report" }
})
}
);
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/webhook/inbound/github-events",
headers={"X-Webhook-Secret": "whsec_a1b2c3d4e5f6..."},
json={
"action": "opened",
"issue": {"title": "Bug report"}
}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["202"]}>
<Tab title="202">
```json
{
"status": "accepted",
"request_id": "wh_abc123"
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,98 @@
---
title: Create Webhook Slot
description: "Create a new inbound webhook slot with an auto-generated secret for authenticating incoming payloads. Webhooks forward external data to the PocketPaw agent for processing."
api: POST /api/webhooks/add
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["create webhook", "webhook secret", "inbound webhook"]
tags: ["api", "webhooks"]
---
## Overview
Creates a new inbound webhook slot. A unique secret is auto-generated for signature verification. The webhook URL follows the pattern `/webhook/inbound/{name}`.
## Request Body
<ParamTable type="body">
<Param name="name" type="string" required>
Webhook slug name (used in the URL). Must be URL-safe.
</Param>
<Param name="description" type="string">
Human-readable description of what this webhook receives.
</Param>
</ParamTable>
## Response
<ResponseField name="status" type="string">`"ok"` on success</ResponseField>
<ResponseField name="webhook" type="object">
<ResponseField name="name" type="string">Webhook name</ResponseField>
<ResponseField name="secret" type="string">Auto-generated verification secret</ResponseField>
<ResponseField name="description" type="string">Webhook description</ResponseField>
</ResponseField>
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/webhooks/add" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"name": "github-events", "description": "GitHub repository webhooks"}'
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/webhooks/add", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({
name: "github-events",
description: "GitHub repository webhooks"
})
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/webhooks/add",
headers={"Authorization": "Bearer <token>"},
json={
"name": "github-events",
"description": "GitHub repository webhooks"
}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200"]}>
<Tab title="200">
```json
{
"status": "ok",
"webhook": {
"name": "github-events",
"secret": "whsec_a1b2c3d4e5f6...",
"description": "GitHub repository webhooks"
}
}
```
</Tab>
</Tabs>
</ResponseExample>

View File

@@ -0,0 +1,92 @@
---
title: Remove Webhook Slot
description: "Delete an inbound webhook slot from PocketPaw. The webhook URL and secret are immediately invalidated and any future payloads sent to it will be rejected."
api: POST /api/webhooks/remove
baseUrl: http://localhost:8000
layout: '@/layouts/APIEndpointLayout.astro'
auth: bearer
section: API Reference
ogType: article
keywords: ["remove webhook", "delete webhook", "revoke webhook"]
tags: ["api", "webhooks"]
---
## Overview
Removes an inbound webhook slot by name. Any future requests to the webhook URL will return 404.
## Request Body
<ParamTable type="body">
<Param name="name" type="string" required>
The name of the webhook slot to remove.
</Param>
</ParamTable>
## Response
<ResponseField name="status" type="string">`"ok"` on success</ResponseField>
## Error Responses
| Status | Description |
|--------|-------------|
| 404 | Webhook slot not found |
<RequestExample>
<Tabs items={["cURL", "JavaScript", "Python"]}>
<Tab title="cURL">
```bash
curl -X POST "http://localhost:8000/api/webhooks/remove" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"name": "github-events"}'
```
</Tab>
<Tab title="JavaScript">
```javascript
const response = await fetch("http://localhost:8000/api/webhooks/remove", {
method: "POST",
headers: {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
},
body: JSON.stringify({ name: "github-events" })
});
const data = await response.json();
console.log(data);
```
</Tab>
<Tab title="Python">
```python
import requests
response = requests.post(
"http://localhost:8000/api/webhooks/remove",
headers={"Authorization": "Bearer <token>"},
json={"name": "github-events"}
)
print(response.json())
```
</Tab>
</Tabs>
</RequestExample>
<ResponseExample>
<Tabs items={["200", "404"]}>
<Tab title="200">
```json
{
"status": "ok"
}
```
</Tab>
<Tab title="404">
```json
{
"detail": "Webhook slot not found"
}
```
</Tab>
</Tabs>
</ResponseExample>

165
docs/api/websocket.mdx Normal file
View File

@@ -0,0 +1,165 @@
---
title: WebSocket Protocol
description: "PocketPaw's WebSocket protocol enables real-time bidirectional communication between the dashboard and backend: session switching, message streaming, tool events, and Deep Work progress updates."
section: API Reference
ogType: article
keywords: ["websocket", "real-time", "streaming", "bidirectional", "ws protocol"]
tags: ["api", "websocket"]
---
# WebSocket Protocol
The web dashboard communicates with the PocketPaw backend over WebSocket for real-time streaming.
## Connection
```
ws://localhost:8000/ws
ws://localhost:8000/ws?resume_session=session_abc123
```
The `resume_session` query parameter automatically loads a previous session on connect.
## Message Format
All messages are JSON objects with a `type` or `action` field.
## Client → Server Messages
### Send Message
```json
{
"action": "message",
"content": "Hello, what can you do?",
"session_id": "session_abc123"
}
```
### Switch Session
```json
{
"action": "switch_session",
"session_id": "session_def456"
}
```
### New Session
```json
{
"action": "new_session"
}
```
### Plan Response
```json
{
"action": "plan_response",
"response": "approve"
}
```
## Server → Client Messages
### Response Chunk (Streaming)
```json
{
"type": "response_chunk",
"content": "Here is the ",
"session_id": "session_abc123"
}
```
### Stream End
```json
{
"type": "stream_end",
"session_id": "session_abc123"
}
```
### Tool Start
```json
{
"type": "tool_start",
"tool": "web_search",
"input": {"query": "Python 3.13 release date"},
"session_id": "session_abc123"
}
```
### Tool Result
```json
{
"type": "tool_result",
"tool": "web_search",
"result": "Python 3.13 was released on...",
"session_id": "session_abc123"
}
```
### Thinking
```json
{
"type": "thinking",
"content": "Let me search for that...",
"session_id": "session_abc123"
}
```
### Error
```json
{
"type": "error",
"message": "Failed to execute tool",
"session_id": "session_abc123"
}
```
### Plan Created
```json
{
"type": "plan_created",
"plan": "## Plan\n1. Read the file\n2. Modify the function\n3. Run tests",
"session_id": "session_abc123"
}
```
### Session Switched
```json
{
"type": "session_switched",
"session_id": "session_def456",
"messages": [...]
}
```
### Inbox Update
```json
{
"type": "inbox_update",
"channel": "telegram",
"message": "New message from Telegram user",
"session_id": "telegram_123"
}
```
## Connection Lifecycle
1. Client connects to `/ws` (optionally with `resume_session`)
2. Server sends session history if resuming
3. Client sends messages, server streams responses
4. Client can switch sessions at any time
5. Connection stays alive with WebSocket keep-alive

View File

@@ -0,0 +1,100 @@
---
title: Claude Agent SDK
description: "The Claude Agent SDK backend is the recommended choice: official Anthropic SDK with built-in Bash, Read, Write, and Edit tools, PreToolUse safety hooks, and MCP server integration."
section: Agent Backends
ogType: article
keywords: ["claude agent sdk", "anthropic sdk", "pretooluse hooks", "mcp integration", "recommended"]
tags: ["backends", "claude"]
---
# Claude Agent SDK
The Claude Agent SDK backend is the **recommended** choice for PocketPaw. It uses Anthropic's official SDK with built-in tools and native MCP support.
## Overview
This backend leverages the `claude-agent-sdk` package, which provides:
- **Built-in tools**: Bash, Read, Write, Edit — managed by the SDK
- **Tool execution hooks**: `PreToolUse` hooks for dangerous command blocking
- **MCP integration**: Native Model Context Protocol server support
- **Streaming**: Real-time token-by-token response streaming
## Configuration
```bash
export POCKETCLAW_AGENT_BACKEND="claude_agent_sdk"
export POCKETCLAW_ANTHROPIC_API_KEY="sk-ant-..."
```
## Built-in Tools
The Claude Agent SDK provides these tools natively:
| SDK Tool | Description |
|----------|-------------|
| `Bash` | Execute shell commands |
| `Read` | Read files from the filesystem |
| `Write` | Write/create files |
| `Edit` | Edit existing files with search/replace |
### Tool Name Mapping
The SDK uses capitalized tool names internally. PocketPaw maps these to the policy system's snake_case names:
| SDK Name | Policy Name |
|----------|------------|
| `Bash` | `shell` |
| `Read` | `read_file` |
| `Write` | `write_file` |
| `Edit` | `edit_file` |
This mapping is handled by `_SDK_TO_POLICY` in `claude_sdk.py`.
## Safety Hooks
The backend uses `PreToolUse` hooks to intercept and block dangerous commands before execution:
```python
# Example: Blocking destructive shell commands
async def pre_tool_use(tool_name, tool_input):
if tool_name == "Bash":
command = tool_input.get("command", "")
if is_dangerous_command(command):
return BlockedResponse("This command has been blocked for safety.")
```
## MCP Server Integration
The Claude Agent SDK has native MCP support. PocketPaw's `_get_mcp_servers()` function translates MCP server configurations into the SDK's expected format:
```python
# MCP servers are loaded from ~/.pocketclaw/mcp.json
# and passed to the SDK during initialization
servers = _get_mcp_servers()
```
MCP tools are subject to the tool policy system. Use `mcp:<server>:*` patterns in allow/deny lists:
```bash
# Allow all tools from a specific MCP server
export POCKETCLAW_TOOLS_ALLOW="mcp:filesystem:*"
# Deny all MCP tools
export POCKETCLAW_TOOLS_DENY="group:mcp"
```
## Custom Tools
In addition to the SDK's built-in tools, PocketPaw registers its own tools (web_search, image_gen, etc.) as custom tool definitions passed to the SDK.
## Response Format
The backend yields standardized response chunks:
```python
{"type": "message", "content": "Here's the result..."}
{"type": "tool_use", "content": "", "metadata": {"tool": "Bash", "input": {"command": "ls"}}}
{"type": "tool_result", "content": "file1.txt\nfile2.txt", "metadata": {"tool": "Bash"}}
{"type": "done", "content": ""}
```

52
docs/backends/index.mdx Normal file
View File

@@ -0,0 +1,52 @@
---
title: Agent Backends
description: "Choose between three agent backends: Claude Agent SDK (recommended) for production-grade tool use, PocketPaw Native for custom orchestration, or Open Interpreter for local models."
section: Agent Backends
ogType: article
keywords: ["agent backend", "backend selection", "claude sdk", "pocketpaw native", "open interpreter"]
tags: ["backends", "configuration"]
---
# Agent Backends
PocketPaw supports three agent backends. Each provides different capabilities and trade-offs.
## Backend Comparison
| Feature | Claude Agent SDK | PocketPaw Native | Open Interpreter |
|---------|-----------------|-------------------|------------------|
| Provider | Anthropic Claude | Anthropic + OI | Ollama/OpenAI/Anthropic |
| Built-in tools | Bash, Read, Write, Edit | Custom + OI execution | OI tools |
| Local models | No | No | Yes (Ollama) |
| Code execution | Claude tools | Open Interpreter | Open Interpreter |
| Streaming | Yes | Yes | Yes |
| MCP support | Native | Via tool registry | Via tool registry |
| Recommended for | Coding, complex tasks | Balanced workflows | Local/offline use |
## Switching Backends
Set the backend via environment variable or config:
```bash
export POCKETCLAW_AGENT_BACKEND="claude_agent_sdk" # default
# or
export POCKETCLAW_AGENT_BACKEND="pocketpaw_native"
# or
export POCKETCLAW_AGENT_BACKEND="open_interpreter"
```
Or change it in the web dashboard's Settings panel.
## Backend Details
<CardGroup>
<Card title="Claude Agent SDK" icon="lucide:sparkles" href="/backends/claude-sdk">
The recommended backend with native Claude tools and MCP support.
</Card>
<Card title="PocketPaw Native" icon="lucide:bot" href="/backends/pocketpaw-native">
Custom orchestrator combining Anthropic SDK with Open Interpreter.
</Card>
<Card title="Open Interpreter" icon="lucide:terminal" href="/backends/open-interpreter">
Standalone engine with Ollama support for fully local operation.
</Card>
</CardGroup>

View File

@@ -0,0 +1,94 @@
---
title: Open Interpreter
description: "The Open Interpreter backend provides standalone code execution with support for local models via Ollama, plus OpenAI and Anthropic APIs. Ideal for offline or air-gapped deployments."
section: Agent Backends
ogType: article
keywords: ["open interpreter", "ollama", "local models", "offline ai", "code execution"]
tags: ["backends", "open-interpreter"]
---
# Open Interpreter
The Open Interpreter backend is a standalone execution engine that supports multiple LLM providers, including **Ollama for fully local operation**.
## Overview
Open Interpreter provides:
- **Multi-provider support**: Ollama, OpenAI, Anthropic
- **Local models**: Run with Ollama for completely local, offline operation
- **Code execution**: Built-in code interpreter for Python, JavaScript, and shell
- **Streaming**: Real-time response streaming
## Configuration
```bash
export POCKETCLAW_AGENT_BACKEND="open_interpreter"
# For Ollama (local)
export POCKETCLAW_OI_MODEL="ollama/llama3.2"
# For OpenAI
export POCKETCLAW_OI_MODEL="gpt-4o"
export POCKETCLAW_OPENAI_API_KEY="sk-..."
# For Anthropic
export POCKETCLAW_OI_MODEL="claude-sonnet-4-5-20250929"
export POCKETCLAW_ANTHROPIC_API_KEY="sk-ant-..."
```
## Local Operation with Ollama
For a completely self-contained setup with no external API calls:
<Steps>
<Step title="Install Ollama">
```bash
curl -fsSL https://ollama.com/install.sh | sh
```
</Step>
<Step title="Pull a model">
```bash
ollama pull llama3.2
```
</Step>
<Step title="Configure PocketPaw">
```bash
export POCKETCLAW_AGENT_BACKEND="open_interpreter"
export POCKETCLAW_OI_MODEL="ollama/llama3.2"
```
</Step>
<Step title="Start">
```bash
pocketpaw
```
</Step>
</Steps>
## When to Use
Choose Open Interpreter when:
- You want **fully local operation** with no external API calls
- You're running on hardware with a capable GPU for local model inference
- You want to use **open-source models** like Llama, Mistral, or Phi
- You need **offline capability**
## Limitations
Compared to the Claude Agent SDK backend:
- No native MCP support (tools registered via tool registry)
- Tool calling depends on the model's capabilities
- Smaller models may not reliably use complex tool chains
- No built-in safety hooks (relies on PocketPaw's Guardian AI)
## Installation
Open Interpreter is included in the core installation:
```bash
curl -fsSL https://pocketpaw.xyz/install.sh | sh
```
For Ollama, install it separately from [ollama.com](https://ollama.com).

View File

@@ -0,0 +1,75 @@
---
title: PocketPaw Native
description: "PocketPaw Native is a custom orchestrator that pairs Anthropic's SDK for reasoning with Open Interpreter for code execution. Offers fine-grained control over the agent pipeline."
section: Agent Backends
ogType: article
keywords: ["pocketpaw native", "custom orchestrator", "anthropic sdk", "code execution", "hybrid"]
tags: ["backends", "native"]
---
# PocketPaw Native
The PocketPaw Native backend is a custom orchestrator that combines Anthropic's SDK for reasoning with Open Interpreter for code execution.
## Overview
This backend provides a balanced approach:
- **Anthropic SDK** handles conversation, reasoning, and tool selection
- **Open Interpreter** handles actual code execution
- **Custom tools** are registered through PocketPaw's tool registry
- **MCP tools** are loaded via `_get_mcp_tools()` and registered with the tool registry
## Configuration
```bash
export POCKETCLAW_AGENT_BACKEND="pocketpaw_native"
export POCKETCLAW_ANTHROPIC_API_KEY="sk-ant-..."
```
## How It Works
1. The user message is sent to Claude via the Anthropic SDK
2. Claude decides which tools to call based on the available tool definitions
3. Tool calls are routed through PocketPaw's `ToolRegistry`
4. Code execution tools are delegated to Open Interpreter
5. Results are sent back to Claude for the next reasoning step
6. The cycle continues until Claude produces a final response
## Tool Registration
The native backend registers all tools from PocketPaw's tool registry:
```python
# Built-in tools (web_search, image_gen, etc.)
tools = registry.get_tool_definitions(format="anthropic")
# MCP tools (loaded from configured MCP servers)
mcp_tools = await _get_mcp_tools()
tools.extend(mcp_tools)
```
MCP tools are named with the pattern `mcp_<server>__<tool>` to avoid naming conflicts.
## Tool Policy
The tool policy system filters available tools. The native backend respects the same profiles and allow/deny lists as the Claude Agent SDK backend.
## When to Use
Choose PocketPaw Native when:
- You want more control over the tool execution pipeline
- You need to customize how tools are registered and executed
- You want to combine Anthropic's reasoning with Open Interpreter's execution capabilities
## Installation
```bash
curl -fsSL https://pocketpaw.xyz/install.sh | sh
# Or add the native extra manually
pip install pocketpaw[native]
```
This installs Open Interpreter as an optional dependency.

89
docs/channels/discord.mdx Normal file
View File

@@ -0,0 +1,89 @@
---
title: Discord
description: "Run PocketPaw as a Discord bot with /paw slash commands, DM and mention support, streaming responses with edit-in-place, and configurable guild and user allow-lists."
section: Channels
ogType: article
keywords: ["discord bot", "slash commands", "discord.py", "dm support", "streaming"]
tags: ["channels", "discord"]
---
# Discord
PocketPaw integrates with Discord via `discord.py`. It supports slash commands, direct messages, and @mention in channels.
## Setup
<Steps>
<Step title="Create a Discord application">
1. Go to the [Discord Developer Portal](https://discord.com/developers/applications)
2. Click "New Application" and name it
3. Go to the "Bot" section and create a bot
4. Copy the bot token
</Step>
<Step title="Set permissions">
Under OAuth2 → URL Generator, select:
- Scopes: `bot`, `applications.commands`
- Permissions: `Send Messages`, `Read Message History`, `Use Slash Commands`
</Step>
<Step title="Invite to server">
Use the generated URL to invite the bot to your Discord server.
</Step>
<Step title="Configure">
```bash
export POCKETCLAW_DISCORD_BOT_TOKEN="your-discord-token"
```
</Step>
<Step title="Start">
```bash
pocketpaw --discord
```
</Step>
</Steps>
## Configuration
| Setting | Env Variable | Description |
|---------|-------------|-------------|
| Bot token | `POCKETCLAW_DISCORD_BOT_TOKEN` | Discord bot token |
| Allowed guilds | `POCKETCLAW_DISCORD_ALLOWED_GUILD_IDS` | Comma-separated guild IDs |
| Allowed users | `POCKETCLAW_DISCORD_ALLOWED_USER_IDS` | Comma-separated user IDs |
## Features
### Slash Command
The bot registers a `/paw` slash command. Users can interact with:
```
/paw What files are in the home directory?
```
### DM and Mention Support
- **Direct messages** — Send a DM to the bot for private conversations
- **@mention** — Mention the bot in any channel where it's present
### Streaming
Discord supports edit-in-place streaming with a 1.5-second rate limit. The bot sends an initial message and edits it as tokens arrive, batching updates to respect Discord's rate limits.
### Access Control
```bash
# Restrict to specific servers
export POCKETCLAW_DISCORD_ALLOWED_GUILD_IDS="111222333,444555666"
# Restrict to specific users
export POCKETCLAW_DISCORD_ALLOWED_USER_IDS="777888999"
```
## Installation
```bash
curl -fsSL https://pocketpaw.xyz/install.sh | sh
# Or add the Discord extra manually
pip install pocketpaw[discord]
```
This installs `discord.py` as an optional dependency.

View File

@@ -0,0 +1,83 @@
---
title: Google Chat
description: "Connect PocketPaw to Google Chat for Workspace integration. Supports both webhook mode and Pub/Sub mode for real-time messaging via the Google Chat API v1."
section: Channels
ogType: article
keywords: ["google chat bot", "workspace integration", "pub/sub", "chat api", "google workspace"]
tags: ["channels", "google-chat"]
---
# Google Chat
PocketPaw integrates with Google Chat via the **Chat API v1**, supporting both webhook and Pub/Sub modes.
## Setup
<Steps>
<Step title="Create a Google Cloud project">
1. Go to [console.cloud.google.com](https://console.cloud.google.com)
2. Create a new project or select an existing one
3. Enable the Google Chat API
</Step>
<Step title="Create a service account">
1. Go to IAM & Admin → Service Accounts
2. Create a new service account
3. Download the JSON key file
</Step>
<Step title="Configure the Chat app">
1. Go to the [Google Chat API configuration](https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat)
2. Configure the app with either webhook or Pub/Sub connection
</Step>
<Step title="Configure PocketPaw">
```bash
export POCKETCLAW_GCHAT_PROJECT_ID="your-project-id"
export POCKETCLAW_GCHAT_SERVICE_ACCOUNT_KEY="/path/to/service-account-key.json"
```
</Step>
<Step title="Start">
```bash
pocketpaw --gchat
```
</Step>
</Steps>
## Configuration
| Setting | Env Variable | Description |
|---------|-------------|-------------|
| Project ID | `POCKETCLAW_GCHAT_PROJECT_ID` | Google Cloud project ID |
| Service account key | `POCKETCLAW_GCHAT_SERVICE_ACCOUNT_KEY` | Path to JSON key file |
| Mode | `POCKETCLAW_GCHAT_MODE` | `webhook` or `pubsub` |
| Subscription | `POCKETCLAW_GCHAT_SUBSCRIPTION` | Pub/Sub subscription name |
| Allowed spaces | `POCKETCLAW_GCHAT_ALLOWED_SPACE_IDS` | Comma-separated space IDs |
## Connection Modes
### Webhook Mode
In webhook mode, Google Chat sends HTTP requests to your server. The dashboard exposes a webhook endpoint that handles these requests.
### Pub/Sub Mode
In Pub/Sub mode, PocketPaw subscribes to a Google Cloud Pub/Sub topic. This doesn't require a public URL — the connection is outbound.
## Features
### No Streaming
Google Chat messages are accumulated and sent as a complete response.
### Session Keys
Each space gets a unique session: `gchat:{space_name}`
## Installation
```bash
curl -fsSL https://pocketpaw.xyz/install.sh | sh
# Or add the Google Chat extra manually
pip install pocketpaw[gchat]
```
This installs `google-api-python-client` as an optional dependency.

131
docs/channels/index.mdx Normal file
View File

@@ -0,0 +1,131 @@
---
title: Channels Overview
description: "Connect PocketPaw to 9+ messaging platforms simultaneously: Telegram, Discord, Slack, WhatsApp, Signal, Matrix, Teams, Google Chat, and the built-in web dashboard."
section: Channels
ogType: article
keywords: ["messaging platforms", "telegram", "discord", "slack", "whatsapp", "signal", "matrix"]
tags: ["channels", "integration"]
---
# Channels
PocketPaw connects to multiple messaging platforms through **channel adapters**. Each adapter translates between the platform's native protocol and PocketPaw's internal message bus.
## Supported Channels
<CardGroup>
<Card title="Web Dashboard" icon="lucide:layout-dashboard" href="/channels/web-dashboard">
Built-in real-time web interface with streaming, sessions, and tool activity.
</Card>
<Card title="Telegram" icon="lucide:send" href="/channels/telegram">
Full bot API with topic support, inline keyboards, and streaming via edit-in-place.
</Card>
<Card title="Discord" icon="lucide:gamepad-2" href="/channels/discord">
Slash commands, DM and mention support, streaming with edit-in-place.
</Card>
<Card title="Slack" icon="lucide:hash" href="/channels/slack">
Socket Mode (no public URL needed), thread support, app_mention events.
</Card>
<Card title="WhatsApp" icon="lucide:message-circle" href="/channels/whatsapp">
Business API or Personal mode via QR scan. No Meta account needed for personal.
</Card>
<Card title="Signal" icon="lucide:lock" href="/channels/signal">
Privacy-focused messaging via signal-cli REST API.
</Card>
<Card title="Matrix" icon="lucide:grid-3x3" href="/channels/matrix">
Decentralized, federated protocol via matrix-nio.
</Card>
<Card title="Microsoft Teams" icon="lucide:users" href="/channels/teams">
Bot Framework SDK integration for enterprise collaboration.
</Card>
<Card title="Google Chat" icon="lucide:message-square" href="/channels/google-chat">
Webhook and Pub/Sub modes via Google Chat API.
</Card>
</CardGroup>
## Running Channels
### Web Dashboard (Default)
The web dashboard is the default mode. Simply run:
```bash
pocketpaw
```
The dashboard auto-starts all configured channel adapters on startup. You can manage channels from the Channels modal in the sidebar.
### Headless Mode
Run specific channels without the web dashboard:
```bash
# Single channel
pocketpaw --telegram
pocketpaw --discord
pocketpaw --slack
# Multiple channels
pocketpaw --discord --slack --whatsapp
# All channel flags
pocketpaw --telegram --discord --slack --whatsapp --signal --matrix --teams --gchat
```
### Channel Management API
The web dashboard exposes REST endpoints for channel management:
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/channels/status` | GET | Get status of all channels |
| `/api/channels/save` | POST | Save channel configuration |
| `/api/channels/toggle` | POST | Start or stop a channel |
## Streaming Behavior
Each channel handles streaming differently based on platform limitations:
| Channel | Streaming Method |
|---------|-----------------|
| Web Dashboard | Real-time WebSocket chunks |
| Telegram | Edit-in-place (message updates) |
| Discord | Edit-in-place (1.5s rate limit) |
| Slack | Thread message updates |
| WhatsApp | Accumulate + send on completion |
| Signal | Accumulate + send on completion |
| Matrix | Edit-in-place (m.replace) |
| Teams | Accumulate + send on completion |
| Google Chat | Accumulate + send on completion |
## Channel-Specific Session Keys
Each channel generates unique session keys to maintain separate conversations:
- **Telegram**: `{chat_id}` or `{chat_id}:topic:{topic_id}`
- **Discord**: `{channel_id}` or `dm:{user_id}`
- **Slack**: `{channel_id}:{thread_ts}`
- **WhatsApp**: `{phone_number}`
- **Signal**: `{phone_number}`
- **Matrix**: `{room_id}`
- **Teams**: `{conversation_id}`
- **Google Chat**: `{space_name}`
## Access Control
Each channel supports allow-listing to restrict who can interact with your agent:
```bash
# Telegram
export POCKETCLAW_ALLOWED_TELEGRAM_IDS="123456,789012"
# Discord
export POCKETCLAW_DISCORD_ALLOWED_GUILD_IDS="111,222"
export POCKETCLAW_DISCORD_ALLOWED_USER_IDS="333,444"
# Slack
export POCKETCLAW_SLACK_ALLOWED_CHANNEL_IDS="C01,C02"
# WhatsApp
export POCKETCLAW_WHATSAPP_ALLOWED_PHONE_NUMBERS="+1234567890"
```

80
docs/channels/matrix.mdx Normal file
View File

@@ -0,0 +1,80 @@
---
title: Matrix
description: "Connect PocketPaw to Matrix for decentralized, federated AI messaging. Uses matrix-nio async client with sync_forever, message edit support via m.replace, and room-based sessions."
section: Channels
ogType: article
keywords: ["matrix bot", "matrix-nio", "federated messaging", "decentralized", "element"]
tags: ["channels", "matrix"]
---
# Matrix
PocketPaw connects to the [Matrix](https://matrix.org) protocol via `matrix-nio`. Matrix is an open, decentralized communication protocol ideal for self-hosting enthusiasts.
## Setup
<Steps>
<Step title="Create a Matrix account">
Create a bot account on your Matrix homeserver (e.g., matrix.org, your own Synapse server).
</Step>
<Step title="Get an access token">
Log in with the bot account to get an access token. You can use Element or curl:
```bash
curl -X POST "https://matrix.org/_matrix/client/r0/login" \
-H "Content-Type: application/json" \
-d '{"type":"m.login.password","user":"@bot:matrix.org","password":"..."}'
```
</Step>
<Step title="Configure">
```bash
export POCKETCLAW_MATRIX_HOMESERVER="https://matrix.org"
export POCKETCLAW_MATRIX_USER_ID="@bot:matrix.org"
export POCKETCLAW_MATRIX_ACCESS_TOKEN="your-access-token"
```
</Step>
<Step title="Start">
```bash
pocketpaw --matrix
```
</Step>
</Steps>
## Configuration
| Setting | Env Variable | Description |
|---------|-------------|-------------|
| Homeserver | `POCKETCLAW_MATRIX_HOMESERVER` | Matrix homeserver URL |
| User ID | `POCKETCLAW_MATRIX_USER_ID` | Bot's Matrix user ID |
| Access token | `POCKETCLAW_MATRIX_ACCESS_TOKEN` | Authentication token |
| Device ID | `POCKETCLAW_MATRIX_DEVICE_ID` | Device ID (auto-generated) |
| Allowed rooms | `POCKETCLAW_MATRIX_ALLOWED_ROOM_IDS` | Comma-separated room IDs |
| Display name | `POCKETCLAW_MATRIX_DISPLAY_NAME` | Bot display name |
## Features
### Sync-Based
The adapter uses `nio.AsyncClient.sync_forever()` for real-time message delivery. No polling needed.
### Edit-in-Place Streaming
Matrix supports message editing via `m.replace` events. PocketPaw uses this for streaming — sending an initial message and then editing it as tokens arrive.
### Room Support
The bot responds to messages in any room it's invited to. Use `POCKETCLAW_MATRIX_ALLOWED_ROOM_IDS` to restrict access to specific rooms.
### Session Keys
Each room gets a unique session: `matrix:{room_id}`
## Installation
```bash
curl -fsSL https://pocketpaw.xyz/install.sh | sh
# Or add the Matrix extra manually
pip install pocketpaw[matrix]
```
This installs `matrix-nio` as an optional dependency.

73
docs/channels/signal.mdx Normal file
View File

@@ -0,0 +1,73 @@
---
title: Signal
description: "Connect PocketPaw to Signal for privacy-focused AI assistance. Uses signal-cli REST API with HTTP polling every 2 seconds. End-to-end encrypted messaging with your AI agent."
section: Channels
ogType: article
keywords: ["signal bot", "signal-cli", "privacy", "encrypted messaging", "e2ee"]
tags: ["channels", "signal"]
---
# Signal
PocketPaw connects to Signal via the `signal-cli` REST API. Signal is ideal for users who prioritize privacy and end-to-end encryption.
## Prerequisites
You need a running [signal-cli-rest-api](https://github.com/bbernhard/signal-cli-rest-api) instance. This provides the HTTP API that PocketPaw communicates with.
```bash
# Run signal-cli REST API via Docker
docker run -d --name signal-api \
-p 8080:8080 \
-v ./signal-cli:/home/.local/share/signal-cli \
bbernhard/signal-cli-rest-api
```
Register your phone number with signal-cli before using it with PocketPaw.
## Setup
<Steps>
<Step title="Start signal-cli REST API">
Ensure signal-cli-rest-api is running and your number is registered.
</Step>
<Step title="Configure">
```bash
export POCKETCLAW_SIGNAL_API_URL="http://localhost:8080"
export POCKETCLAW_SIGNAL_PHONE_NUMBER="+1234567890"
```
</Step>
<Step title="Start">
```bash
pocketpaw --signal
```
</Step>
</Steps>
## Configuration
| Setting | Env Variable | Description |
|---------|-------------|-------------|
| API URL | `POCKETCLAW_SIGNAL_API_URL` | signal-cli REST API URL |
| Phone number | `POCKETCLAW_SIGNAL_PHONE_NUMBER` | Your registered Signal number |
| Allowed numbers | `POCKETCLAW_SIGNAL_ALLOWED_NUMBERS` | Comma-separated allowed numbers |
## How It Works
The Signal adapter uses HTTP polling:
1. Every 2 seconds, it sends `GET /v1/receive/{number}` to the signal-cli API
2. New messages are converted to `InboundMessage` events
3. Responses are sent via `POST /v2/send` to the signal-cli API
### No Streaming
Signal doesn't support message editing, so responses are accumulated and sent as a complete message.
## Installation
Signal support uses `httpx` (a core dependency), so no extra installation is needed:
```bash
curl -fsSL https://pocketpaw.xyz/install.sh | sh
```

90
docs/channels/slack.mdx Normal file
View File

@@ -0,0 +1,90 @@
---
title: Slack
description: "Connect PocketPaw to Slack using Socket Mode — no public URL needed. Supports app_mention events, direct messages, and threaded conversations with thread_ts tracking."
section: Channels
ogType: article
keywords: ["slack bot", "socket mode", "slack-bolt", "app mention", "thread support"]
tags: ["channels", "slack"]
---
# Slack
PocketPaw integrates with Slack via `slack-bolt` using **Socket Mode**. No public URL or ngrok tunnel needed — the connection is initiated from your machine.
## Setup
<Steps>
<Step title="Create a Slack app">
1. Go to [api.slack.com/apps](https://api.slack.com/apps) and create a new app
2. Enable **Socket Mode** under Settings
3. Generate an **App-Level Token** with `connections:write` scope
</Step>
<Step title="Configure bot permissions">
Under OAuth & Permissions, add these Bot Token Scopes:
- `app_mentions:read`
- `chat:write`
- `im:history`
- `im:read`
- `im:write`
</Step>
<Step title="Enable events">
Under Event Subscriptions, subscribe to:
- `app_mention`
- `message.im`
</Step>
<Step title="Install to workspace">
Install the app to your workspace and copy the Bot User OAuth Token.
</Step>
<Step title="Configure PocketPaw">
```bash
export POCKETCLAW_SLACK_BOT_TOKEN="xoxb-..."
export POCKETCLAW_SLACK_APP_TOKEN="xapp-..."
```
</Step>
<Step title="Start">
```bash
pocketpaw --slack
```
</Step>
</Steps>
## Configuration
| Setting | Env Variable | Description |
|---------|-------------|-------------|
| Bot token | `POCKETCLAW_SLACK_BOT_TOKEN` | Bot User OAuth Token (xoxb-) |
| App token | `POCKETCLAW_SLACK_APP_TOKEN` | App-Level Token (xapp-) |
| Allowed channels | `POCKETCLAW_SLACK_ALLOWED_CHANNEL_IDS` | Comma-separated channel IDs |
## Features
### Socket Mode
Socket Mode means:
- **No public URL needed** — Works behind firewalls and NAT
- **No webhook server** — Connection is outbound from your machine
- **Low latency** — WebSocket-based real-time events
### Thread Support
Responses are sent as thread replies using `thread_ts` metadata. This keeps conversations organized in Slack channels.
### Interaction Types
- **@mention** — Mention the bot in any channel: `@PocketPaw what time is it?`
- **Direct message** — Send a DM to the bot for private conversations
### Streaming
Slack responses are buffered and the thread message is updated as tokens arrive.
## Installation
```bash
curl -fsSL https://pocketpaw.xyz/install.sh | sh
# Or add the Slack extra manually
pip install pocketpaw[slack]
```
This installs `slack-bolt` as an optional dependency.

78
docs/channels/teams.mdx Normal file
View File

@@ -0,0 +1,78 @@
---
title: Microsoft Teams
description: "Connect PocketPaw to Microsoft Teams using the Bot Framework SDK. Receives messages via webhook at /api/messages/teams with enterprise-grade authentication and conversation support."
section: Channels
ogType: article
keywords: ["microsoft teams bot", "bot framework", "enterprise", "teams integration", "webhook"]
tags: ["channels", "teams"]
---
# Microsoft Teams
PocketPaw integrates with Microsoft Teams via the **Bot Framework SDK**. This is ideal for enterprise environments that use Teams as their primary collaboration tool.
## Setup
<Steps>
<Step title="Register a bot">
1. Go to the [Azure Portal](https://portal.azure.com)
2. Create a new Bot Channels Registration
3. Note the App ID and generate a password
</Step>
<Step title="Configure messaging endpoint">
Set the messaging endpoint to your server's public URL:
```
https://your-server.com/api/messages/teams
```
</Step>
<Step title="Configure PocketPaw">
```bash
export POCKETCLAW_TEAMS_APP_ID="your-app-id"
export POCKETCLAW_TEAMS_APP_PASSWORD="your-app-password"
```
</Step>
<Step title="Start">
```bash
pocketpaw --teams
```
Or start via the web dashboard's Channels modal.
</Step>
</Steps>
## Configuration
| Setting | Env Variable | Description |
|---------|-------------|-------------|
| App ID | `POCKETCLAW_TEAMS_APP_ID` | Bot Framework App ID |
| App password | `POCKETCLAW_TEAMS_APP_PASSWORD` | Bot Framework password |
| Tenant ID | `POCKETCLAW_TEAMS_TENANT_ID` | Azure tenant ID (optional) |
| Allowed teams | `POCKETCLAW_TEAMS_ALLOWED_TEAM_IDS` | Comma-separated team IDs |
## Features
### Webhook-Based
The Teams adapter exposes a webhook endpoint at `/api/messages/teams`. The Bot Framework sends activities to this endpoint when users interact with the bot.
### No Streaming
Teams messages are accumulated and sent as a complete response when the agent finishes processing.
### Session Keys
Each conversation gets a unique session: `teams:{conversation_id}`
## Installation
```bash
curl -fsSL https://pocketpaw.xyz/install.sh | sh
# Or add the Teams extra manually
pip install pocketpaw[teams]
```
This installs the `botbuilder-core` SDK as an optional dependency.
<Callout type="info">
Microsoft Teams integration requires a public URL for the webhook endpoint. Use the web dashboard or set up a reverse proxy with a public domain.
</Callout>

View File

@@ -0,0 +1,81 @@
---
title: Telegram
description: "Connect PocketPaw to Telegram as a bot with topic-aware conversations, inline keyboards, and streaming responses. Supports group chats and private messages with session isolation."
section: Channels
ogType: article
keywords: ["telegram bot", "telegram integration", "topic support", "group chat", "bot api"]
tags: ["channels", "telegram"]
---
# Telegram
PocketPaw supports Telegram via the `python-telegram-bot` library. It works as a standard Telegram bot with support for topics, inline keyboards, and streaming.
## Setup
<Steps>
<Step title="Create a bot">
1. Open Telegram and search for `@BotFather`
2. Send `/newbot` and follow the prompts
3. Copy the bot token
</Step>
<Step title="Configure">
```bash
export POCKETCLAW_TELEGRAM_TOKEN="your-bot-token"
```
</Step>
<Step title="Start">
```bash
# Telegram-only mode
pocketpaw --telegram
# Or via web dashboard (configure in Channels modal)
pocketpaw
```
</Step>
</Steps>
## Configuration
| Setting | Env Variable | Description |
|---------|-------------|-------------|
| Bot token | `POCKETCLAW_TELEGRAM_TOKEN` | Bot token from BotFather |
| Allowed user IDs | `POCKETCLAW_ALLOWED_TELEGRAM_IDS` | Comma-separated user IDs |
## Features
### Streaming
Telegram supports edit-in-place streaming. The bot sends an initial message and then edits it as more tokens arrive, giving a real-time typing effect.
### Topic Support
PocketPaw supports Telegram's topic feature (available in groups with topics enabled). Each topic gets its own session:
- Session key format: `{chat_id}:topic:{topic_id}`
- Messages in different topics maintain separate conversation histories
### Access Control
Restrict access by specifying allowed Telegram user IDs:
```bash
export POCKETCLAW_ALLOWED_TELEGRAM_IDS="123456,789012"
```
Only users with these IDs can interact with the bot. If not set, anyone can use the bot.
### Commands
The bot responds to direct messages and can be configured with custom commands via BotFather's `/setcommands`.
## Installation
```bash
curl -fsSL https://pocketpaw.xyz/install.sh | sh
# Or add the Telegram extra manually
pip install pocketpaw[telegram]
```
This installs `python-telegram-bot` as a dependency.

View File

@@ -0,0 +1,109 @@
---
title: Web Dashboard
description: "PocketPaw's built-in web dashboard provides real-time streaming chat, session management, channel configuration, MCP server controls, and memory settings in a single interface."
section: Channels
ogType: article
keywords: ["web dashboard", "real-time chat", "session management", "admin panel", "websocket"]
tags: ["channels", "dashboard"]
---
# Web Dashboard
The web dashboard is PocketPaw's default interface. It provides a real-time chat experience with session management, tool activity monitoring, and full configuration capabilities.
## Starting the Dashboard
```bash
# Default mode — starts the web dashboard
pocketpaw
# Specify host and port
export POCKETCLAW_DASHBOARD_HOST="0.0.0.0"
export POCKETCLAW_DASHBOARD_PORT=8000
pocketpaw
```
The dashboard opens at `http://localhost:8000`.
## Features
### Real-Time Chat
- **Streaming responses** — See the agent's response as it's generated, token by token
- **Markdown rendering** — Full markdown support with syntax highlighting
- **Code blocks** — Copy-to-clipboard for code blocks
- **Session persistence** — Conversations are saved and can be resumed
### Session Management
- **Session list** — Sidebar shows all sessions grouped by time (Today, Yesterday, This Week, etc.)
- **Search** — Full-text search across all sessions
- **New session** — Create a new conversation at any time
- **Delete session** — Remove individual sessions
- **Title editing** — Rename sessions for easy identification
### Tool Activity Panel
- **Real-time tool tracking** — See which tools are being called
- **Tool inputs and outputs** — Inspect what data flows through each tool
- **Timing** — See how long each tool execution takes
### Channel Management
- **Configure channels** — Set tokens and API keys for each channel
- **Toggle channels** — Start and stop channels without restarting PocketPaw
- **Status monitoring** — See which channels are running
- **Running count badge** — Sidebar shows how many channels are active
### Settings Panel
- **Agent backend** — Switch between Claude SDK, Native, and Open Interpreter
- **API keys** — Configure all API keys
- **Tool policy** — Set profiles and allow/deny lists
- **Memory** — Configure Mem0 settings
### MCP Server Management
- **Add servers** — Configure MCP servers with stdio or HTTP transport
- **Toggle servers** — Enable and disable individual servers
- **Tool discovery** — See which tools each MCP server provides
## Architecture
The dashboard is built with:
- **Backend**: FastAPI + Jinja2 templates
- **Frontend**: Vanilla JS/CSS/HTML (no build step)
- **Communication**: WebSocket for real-time streaming
- **State**: `StateManager` with localStorage + LRU cache
### WebSocket Protocol
The dashboard communicates with the backend over WebSocket. Key message types:
| Action | Direction | Description |
|--------|-----------|-------------|
| `message` | Client → Server | Send a chat message |
| `response_chunk` | Server → Client | Streaming response chunk |
| `stream_end` | Server → Client | End of streaming response |
| `tool_start` | Server → Client | Tool execution started |
| `tool_result` | Server → Client | Tool execution completed |
| `switch_session` | Client → Server | Switch to a different session |
| `new_session` | Client → Server | Create a new session |
### Feature Module System
The frontend uses a feature module auto-discovery system:
```javascript
// feature-loader.js discovers and loads all feature modules
// Each module registers itself with:
window.featureModules = window.featureModules || [];
window.featureModules.push({
name: 'channels',
init: () => initChannels(),
cleanup: () => cleanupChannels()
});
```
This makes it easy to add new frontend features without modifying the core application code.

100
docs/channels/whatsapp.mdx Normal file
View File

@@ -0,0 +1,100 @@
---
title: WhatsApp
description: "Connect PocketPaw to WhatsApp via the Business Cloud API or Personal QR pairing mode with neonize. No Meta developer account needed for personal mode — just scan a QR code."
section: Channels
ogType: article
keywords: ["whatsapp bot", "whatsapp business api", "qr pairing", "neonize", "personal mode"]
tags: ["channels", "whatsapp"]
---
# WhatsApp
PocketPaw supports WhatsApp through two modes: **Business API** (requires Meta account) and **Personal Mode** (QR code scan, no Meta account needed).
## Personal Mode (Recommended)
Personal mode uses the `neonize` library to connect via WhatsApp Web's multi-device protocol. Just scan a QR code — no Meta Business account, webhooks, or tunnels required.
<Steps>
<Step title="Install">
```bash
curl -fsSL https://pocketpaw.xyz/install.sh | sh
# Or add the WhatsApp extra manually
pip install pocketpaw[whatsapp-personal]
```
</Step>
<Step title="Configure mode">
```bash
export POCKETCLAW_WHATSAPP_MODE="personal"
```
</Step>
<Step title="Start and scan QR">
Start PocketPaw with the web dashboard:
```bash
pocketpaw
```
Open the Channels modal, go to WhatsApp, and scan the QR code with your phone.
</Step>
</Steps>
### QR Code Pairing
When using Personal mode through the web dashboard:
1. Open the Channels modal → WhatsApp tab
2. Select "Personal (QR)" mode
3. Click "Start"
4. A QR code appears — scan it with WhatsApp on your phone
5. The bot connects to your WhatsApp account
The QR code endpoint is available at `GET /api/whatsapp/qr`. The frontend polls every 2 seconds until pairing completes.
## Business API Mode
Business mode uses the WhatsApp Business Cloud API via Meta.
<Steps>
<Step title="Set up Meta Business">
1. Create a Meta Business account
2. Set up a WhatsApp Business API app
3. Get your access token and phone number ID
</Step>
<Step title="Configure">
```bash
export POCKETCLAW_WHATSAPP_MODE="business"
export POCKETCLAW_WHATSAPP_ACCESS_TOKEN="your-token"
export POCKETCLAW_WHATSAPP_PHONE_NUMBER_ID="123456"
export POCKETCLAW_WHATSAPP_VERIFY_TOKEN="your-verify-token"
```
</Step>
<Step title="Set up webhook">
The dashboard exposes a webhook at `/webhook/whatsapp` (auth-exempt). Point Meta's webhook configuration to your server's public URL.
</Step>
</Steps>
## Configuration
| Setting | Env Variable | Description |
|---------|-------------|-------------|
| Mode | `POCKETCLAW_WHATSAPP_MODE` | `personal` or `business` |
| Access token | `POCKETCLAW_WHATSAPP_ACCESS_TOKEN` | Business API token |
| Phone number ID | `POCKETCLAW_WHATSAPP_PHONE_NUMBER_ID` | Business phone number ID |
| Verify token | `POCKETCLAW_WHATSAPP_VERIFY_TOKEN` | Webhook verification token |
| Allowed numbers | `POCKETCLAW_WHATSAPP_ALLOWED_PHONE_NUMBERS` | Comma-separated phone numbers |
## Features
### No Streaming
WhatsApp doesn't support message editing, so responses are accumulated and sent as a complete message when the agent finishes.
### Access Control
```bash
export POCKETCLAW_WHATSAPP_ALLOWED_PHONE_NUMBERS="+1234567890,+0987654321"
```
### Session Keys
Each phone number gets a unique session: `whatsapp:{phone_number}`

View File

@@ -0,0 +1,104 @@
---
title: Agent Loop
description: "The Agent Loop is PocketPaw's central orchestrator: it consumes messages from the bus, builds context from memory, delegates to the agent backend, and streams responses back."
section: Core Concepts
ogType: article
keywords: ["agent loop", "orchestrator", "message processing", "context building", "streaming"]
tags: ["architecture", "agent"]
---
# Agent Loop
The `AgentLoop` is the central orchestrator in PocketPaw. It consumes messages from the bus, builds context, delegates to the agent backend, and streams responses back.
## Responsibilities
The AgentLoop handles:
1. **Message consumption** — Subscribes to `InboundMessage` events from the bus
2. **Security checks** — Runs Guardian AI and injection scanner on incoming messages
3. **Context building** — Assembles system prompt with identity, memory, and state
4. **Backend delegation** — Routes to the configured agent backend via `AgentRouter`
5. **Response streaming** — Publishes `OutboundMessage` chunks back to the bus
6. **Memory updates** — Saves conversation history and triggers Mem0 auto-learn
7. **System events** — Emits tool activity events for the web dashboard
8. **Inbox updates** — Publishes cross-channel inbox events
## Processing Flow
```python
# Simplified AgentLoop flow
async def handle_message(self, message: InboundMessage):
# 1. Security check
threat = await self.guardian.check(message.content)
if threat.level >= ThreatLevel.HIGH:
await self.bus.publish(OutboundMessage(
content="Message blocked by safety check",
...
))
return
# 2. Injection scan
if await self.scanner.scan(message.content):
return # Block injected messages
# 3. Build context
context = await self.context_builder.build(
session_id=message.session_id,
user_query=message.content,
)
# 4. Delegate to backend
async for chunk in self.router.process(context, message.content):
if chunk["type"] == "message":
await self.bus.publish(OutboundMessage(
content=chunk["content"],
is_stream_chunk=True,
...
))
elif chunk["type"] == "tool_use":
await self.bus.publish(SystemEvent(
event_type="tool_start",
data=chunk["metadata"],
))
# 5. Save to memory
await self.memory.save(message.session_id, message.content, response)
# 6. Trigger Mem0 auto-learn (background task)
if settings.mem0_auto_learn:
asyncio.create_task(self.mem0.learn(message.content, response))
```
## Agent Router
The `AgentRouter` selects and delegates to one of three backends:
| Backend | Setting Value | Best For |
|---------|--------------|----------|
| Claude Agent SDK | `claude_agent_sdk` | Coding, complex reasoning, built-in tools |
| PocketPaw Native | `pocketpaw_native` | Balanced capability and control |
| Open Interpreter | `open_interpreter` | Local models via Ollama |
The router lazily imports the selected backend to avoid loading unused dependencies.
## Response Standardization
All backends yield standardized dictionaries:
```python
{
"type": "message", # message, tool_use, tool_result, error, done
"content": "...", # Text content
"metadata": { # Backend-specific metadata
"tool_name": "...",
"tool_input": {...},
}
}
```
This ensures consistent behavior regardless of which backend is active.
## Concurrency
The AgentLoop processes one message per session at a time. If a new message arrives while processing, it's queued. Different sessions can be processed concurrently.

View File

@@ -0,0 +1,78 @@
---
title: Architecture
description: "PocketPaw uses an event-driven architecture with a central message bus, pluggable agent backends, and protocol-based interfaces for tools, memory, and channel adapters."
section: Core Concepts
ogType: article
keywords: ["event-driven architecture", "message bus pattern", "protocol-oriented", "async"]
tags: ["architecture", "design"]
---
# Architecture
PocketPaw is built on an **event-driven message bus** architecture. This design decouples channels from agent backends, making it easy to add new channels and swap backends without touching the core pipeline.
## High-Level Overview
<img src="/pocketpaw-system-architecture.webp" alt="PocketPaw system architecture: event-driven MessageBus connecting 10+ channel adapters, agent processing pipeline with injection scanning, memory-augmented context building, three swappable LLM backends, and real-time streaming delivery." />
## Processing Pipeline
When a user sends a message from any channel, it follows this path:
<Steps>
<Step title="Channel Adapter receives message">
The channel-specific adapter (Telegram, Discord, etc.) translates the platform's message format into a standardized `InboundMessage` event and publishes it to the message bus.
</Step>
<Step title="AgentLoop consumes the message">
The `AgentLoop` subscribes to `InboundMessage` events. It loads the session context, builds the system prompt with memory and identity, and prepares the request for the agent backend.
</Step>
<Step title="AgentRouter selects the backend">
Based on the `agent_backend` setting, the router delegates to one of three backends: Claude Agent SDK, PocketPaw Native, or Open Interpreter.
</Step>
<Step title="Backend processes and streams">
The selected backend processes the message, executes any tool calls, and yields a stream of response chunks back to the AgentLoop.
</Step>
<Step title="AgentLoop publishes responses">
Response chunks are published as `OutboundMessage` events (with `is_stream_chunk=True` for intermediate chunks and `is_stream_end=True` for the final chunk). Tool executions emit `SystemEvent` events.
</Step>
<Step title="Channel Adapters deliver">
Each channel adapter subscribed to `OutboundMessage` events translates and delivers the response in the appropriate format for its platform (e.g., Telegram messages, Discord embeds, Slack thread replies).
</Step>
</Steps>
## Key Design Principles
### Protocol-Oriented
Core interfaces are Python `Protocol` classes, enabling swappable implementations:
- **`AgentProtocol`** — Agent backend interface
- **`ToolProtocol`** — Tool interface with schema export
- **`MemoryStoreProtocol`** — Memory backend interface
- **`BaseChannelAdapter`** — Channel adapter interface
### Async Everywhere
All agent, bus, memory, and tool interfaces are async. PocketPaw uses `asyncio` throughout, with `pytest-asyncio` for testing.
### Lazy Imports
Agent backends and optional dependencies are imported lazily inside their initialization methods. This avoids loading unused dependencies and keeps startup time fast.
### Event Types
The message bus uses three event types:
| Event | Purpose | Consumers |
|-------|---------|-----------|
| `InboundMessage` | User input from any channel | AgentLoop |
| `OutboundMessage` | Agent responses back to channels | Channel adapters, WebSocket |
| `SystemEvent` | Internal events (tool_start, tool_result, thinking, error) | Web dashboard Activity panel |
## Subsystem Interactions
The AgentLoop is the central coordinator:
- **Security** — Guardian AI and injection scanner check every message before processing
- **Memory** — Context builder assembles session history, long-term facts, and semantic search results
- **Tools** — The tool registry provides available tools filtered by the policy system
- **Backends** — The router delegates to the selected agent backend

View File

@@ -0,0 +1,126 @@
---
title: Memory System
description: "PocketPaw's two-tier memory system combines file-based session storage for conversation history with optional Mem0 semantic memory for auto-learned long-term knowledge."
section: Core Concepts
ogType: article
keywords: ["memory architecture", "session storage", "semantic memory", "mem0", "knowledge base"]
tags: ["memory", "architecture"]
---
# Memory System
PocketPaw has a two-tier memory system: **file-based session storage** for conversation history, and optional **Mem0 semantic memory** for long-term recall.
## Session Storage (File Store)
The default memory backend stores sessions as JSON files in `~/.pocketclaw/memory/`:
```
~/.pocketclaw/memory/
├── _index.json # Session index (titles, timestamps)
├── session_abc123.json # Individual session files
├── session_def456.json
└── ...
```
### Session Index
The `_index.json` file provides fast lookups without reading every session file:
```json
{
"session_abc123": {
"title": "Python script for prime numbers",
"created_at": "2024-01-15T10:30:00Z",
"updated_at": "2024-01-15T11:45:00Z",
"message_count": 12,
"channel": "web"
}
}
```
The index supports:
- **Searching** sessions by title or content
- **Listing** recent sessions
- **Grouping** sessions by time (Today, Yesterday, This Week, etc.)
- **Auto-rebuild** if the index is missing or corrupted
### Session Files
Each session file contains the full conversation history:
```json
{
"session_id": "session_abc123",
"messages": [
{
"role": "user",
"content": "Write a Python script for prime numbers",
"timestamp": "2024-01-15T10:30:00Z"
},
{
"role": "assistant",
"content": "Here's a Python script...",
"timestamp": "2024-01-15T10:30:15Z"
}
],
"facts": ["User prefers Python", "Uses Linux"],
"metadata": {
"channel": "web",
"agent_backend": "claude_agent_sdk"
}
}
```
## Mem0 Semantic Memory
For long-term recall, PocketPaw integrates with [Mem0](https://mem0.ai) — a semantic memory layer that learns from conversations.
### How It Works
1. **Auto-learn**: After each agent response, PocketPaw feeds the conversation to Mem0 in a background task
2. **Semantic search**: When building context for a new message, Mem0 is queried to find relevant memories
3. **Context injection**: Matching memories are injected into the system prompt
### Configuration
```bash
# Enable auto-learning
export POCKETCLAW_MEM0_AUTO_LEARN=true
# LLM provider for Mem0's processing
export POCKETCLAW_MEM0_LLM_PROVIDER="ollama"
export POCKETCLAW_MEM0_LLM_MODEL="llama3.2"
# Embedder for semantic search
export POCKETCLAW_MEM0_EMBEDDER_PROVIDER="ollama"
export POCKETCLAW_MEM0_EMBEDDER_MODEL="nomic-embed-text"
# Vector store
export POCKETCLAW_MEM0_VECTOR_STORE="qdrant"
```
### Supported Providers
| Component | Providers |
|-----------|-----------|
| LLM | Ollama, Anthropic, OpenAI |
| Embedder | Ollama, OpenAI |
| Vector Store | Qdrant (default), Chroma |
<Callout type="info">
If using Ollama as the LLM provider for Mem0, no API key is needed. This is the recommended setup for fully local operation.
</Callout>
## Context Building
The `AgentContextBuilder` assembles the agent's context from multiple sources:
1. **Identity** — System prompt with agent personality and capabilities
2. **User profile** — From `~/.pocketclaw/identity/USER.md`
3. **Session history** — Recent messages from the current session
4. **Long-term facts** — Extracted facts from previous sessions
5. **Semantic memories** — Relevant memories from Mem0 (based on the current query)
6. **Skills** — Loaded skill definitions from `~/.pocketclaw/skills/`
The context builder ensures the total context fits within the model's context window by truncating older messages first.

View File

@@ -0,0 +1,95 @@
---
title: Message Bus
description: "The message bus is PocketPaw's communication backbone: async pub/sub for InboundMessage, OutboundMessage, and SystemEvent types flowing between channels and the agent loop."
section: Core Concepts
ogType: article
keywords: ["pub/sub", "async messaging", "event types", "inbound message", "outbound message"]
tags: ["architecture", "messaging"]
---
# Message Bus
The message bus is the backbone of PocketPaw's architecture. All communication between channels, the agent loop, and the web dashboard flows through it.
## Overview
The message bus implements a simple **publish/subscribe** pattern. Publishers emit events, and subscribers receive them asynchronously. This decouples components so they don't need to know about each other.
```python
from pocketclaw.bus.message_bus import MessageBus
from pocketclaw.bus.events import InboundMessage, OutboundMessage
bus = MessageBus()
# Subscribe to events
bus.subscribe(InboundMessage, handler_function)
# Publish events
await bus.publish(InboundMessage(
content="Hello!",
channel="telegram",
session_id="user_123",
metadata={"chat_id": 123456}
))
```
## Event Types
### InboundMessage
Represents user input from any channel:
| Field | Type | Description |
|-------|------|-------------|
| `content` | `str` | The message text |
| `channel` | `str` | Source channel (telegram, discord, slack, etc.) |
| `session_id` | `str` | Unique session identifier |
| `metadata` | `dict` | Channel-specific metadata (chat_id, thread_ts, etc.) |
### OutboundMessage
Agent responses sent back to channels:
| Field | Type | Description |
|-------|------|-------------|
| `content` | `str` | Response text |
| `channel` | `str` | Target channel |
| `session_id` | `str` | Session identifier |
| `is_stream_chunk` | `bool` | Whether this is a streaming chunk |
| `is_stream_end` | `bool` | Whether this is the final chunk |
| `metadata` | `dict` | Channel-specific metadata |
### SystemEvent
Internal events consumed by the web dashboard:
| Field | Type | Description |
|-------|------|-------------|
| `event_type` | `str` | Event type (tool_start, tool_result, thinking, error, inbox_update) |
| `data` | `dict` | Event-specific data |
| `session_id` | `str` | Session identifier |
## Streaming Protocol
PocketPaw supports real-time streaming of agent responses:
1. The agent backend yields response chunks
2. Each chunk is published as an `OutboundMessage` with `is_stream_chunk=True`
3. The final message includes `is_stream_end=True`
4. Channel adapters handle streaming differently per platform:
- **WebSocket** — Sends each chunk immediately
- **Discord** — Buffers chunks and edits messages (1.5s rate limit)
- **Slack** — Buffers and updates thread messages
- **WhatsApp/Signal** — Accumulates all chunks, sends on stream end
- **Telegram** — Edit-in-place streaming
## Tool Events
When the agent uses a tool, `SystemEvent` events are emitted:
```
SystemEvent(event_type="tool_start", data={"tool": "web_search", "input": {...}})
SystemEvent(event_type="tool_result", data={"tool": "web_search", "result": "..."})
```
These events power the Activity panel in the web dashboard, giving users visibility into what tools are being used.

View File

@@ -0,0 +1,105 @@
---
title: Security Model
description: "PocketPaw's defense-in-depth security model combines Guardian AI safety checks, prompt injection scanning, append-only audit logging, and configurable tool policies."
section: Core Concepts
ogType: article
keywords: ["defense in depth", "guardian ai", "prompt injection", "audit log", "safety"]
tags: ["security", "architecture"]
---
# Security Model
PocketPaw implements multiple layers of security to protect against misuse, prompt injection, and unauthorized actions.
## Security Layers
<img src="/pocketpaw-security-architecture.webp" alt="PocketPaw defense-in-depth security architecture: seven layers covering credential encryption, injection scanning, tool policy enforcement, Guardian AI review, dangerous command blocking, append-only audit logging, and rate-limited session management." />
## Guardian AI
The Guardian AI is a secondary LLM that evaluates every incoming message for safety concerns before the main agent processes it.
- Uses `AsyncAnthropic` directly (not the main agent's LLM)
- Classifies messages into threat levels: `NONE`, `LOW`, `MEDIUM`, `HIGH`, `CRITICAL`
- Messages at `HIGH` or above are blocked with an explanation
- Runs before any tool execution or code generation
## Injection Scanner
The injection scanner detects prompt injection attempts using a two-tier approach:
1. **Regex tier** — Fast pattern matching for common injection patterns (e.g., "ignore previous instructions", "system prompt override")
2. **LLM tier** — Secondary LLM analysis for sophisticated injection attempts that bypass regex
Both tiers are applied to:
- Incoming user messages (in AgentLoop)
- Tool outputs (in ToolRegistry) to catch indirect injection via web content or file contents
## Tool Policy
The tool policy system controls which tools are available:
- **Profiles**: `minimal` (memory only), `coding` (fs + shell + memory), `full` (all tools)
- **Allow list**: Explicitly permit specific tools or groups
- **Deny list**: Explicitly block specific tools or groups (takes precedence)
- **Precedence**: deny > allow > profile
See [Tool Policy](/tools/tool-policy) for detailed documentation.
## Audit Log
Every significant action is recorded in an append-only JSONL log at `~/.pocketclaw/audit.jsonl`:
```json
{"timestamp": "2024-01-15T10:30:00Z", "action": "tool_execute", "tool": "shell", "input": "ls -la", "result": "...", "session_id": "abc123"}
{"timestamp": "2024-01-15T10:30:05Z", "action": "message_blocked", "reason": "injection_detected", "content": "...", "session_id": "abc123"}
```
The audit log is:
- **Append-only** — Previous entries cannot be modified
- **Machine-readable** — JSONL format for easy parsing
- **Comprehensive** — Records tool executions, blocked messages, security events
## Security Audit CLI
Run automated security checks:
```bash
pocketpaw --security-audit # Run all 7 checks
pocketpaw --security-audit --fix # Auto-fix issues where possible
```
Checks include:
1. Config file permissions (should be 600)
2. API key exposure in environment
3. Audit log integrity
4. Token storage security
5. MCP server configuration
6. Tool policy validation
7. Guardian AI status
## Self-Audit Daemon
The self-audit daemon runs 12 continuous checks in the background:
- Memory usage monitoring
- Disk space checks
- API key rotation reminders
- Session cleanup
- Audit log rotation
- And more
Reports are saved as JSON in `~/.pocketclaw/audit/`.
## Dangerous Command Blocking
The Claude Agent SDK backend uses `PreToolUse` hooks to block dangerous shell commands before execution:
- Commands that could destroy data (`rm -rf /`, `mkfs`, etc.)
- Network scanning tools without explicit permission
- Privilege escalation attempts
- System modification commands
<Callout type="warning">
PocketPaw's security features are designed for self-hosted, single-user deployments. If exposing PocketPaw to multiple users, additional authentication and authorization layers should be added.
</Callout>

View File

@@ -0,0 +1,148 @@
---
title: Tool System
description: "PocketPaw's extensible tool system uses ToolProtocol interfaces with dual-schema export (Anthropic and OpenAI), a policy engine with deny-wins precedence, and 50+ built-in tools."
section: Core Concepts
ogType: article
keywords: ["tool protocol", "tool registry", "policy engine", "anthropic schema", "openai schema"]
tags: ["tools", "architecture"]
---
# Tool System
PocketPaw's tool system provides 30+ built-in tools and supports custom tool creation. Tools are governed by a policy system that controls which tools are available.
<img src="/Tool-system-architecture-and-policy-system.webp" alt="Tool system architecture: 21 built-in tools across eight categories, ToolProtocol interface with dual-schema export, and three-tier policy engine (profiles, groups, allow/deny lists) with strict deny-wins precedence." />
## Tool Protocol
Every tool implements the `ToolProtocol`:
```python
class ToolProtocol(Protocol):
@property
def name(self) -> str: ...
@property
def description(self) -> str: ...
@property
def definition(self) -> ToolDefinition: ...
async def execute(self, **kwargs) -> str: ...
```
The `ToolDefinition` provides schema export for both Anthropic and OpenAI formats, enabling tools to work with any backend.
## Tool Registry
The `ToolRegistry` is the central registry for all tools:
```python
from pocketclaw.tools.registry import ToolRegistry
registry = ToolRegistry()
registry.register(MyCustomTool())
# Get tool definitions for the agent
tools = registry.get_tool_definitions(format="anthropic")
# Execute a tool by name
result = await registry.execute("my_tool", param1="value")
```
The registry automatically filters tools based on the active [tool policy](/tools/tool-policy).
## Built-in Tools
PocketPaw ships with these built-in tools:
### Core Tools (Claude Agent SDK)
- **Bash** — Execute shell commands
- **Read** — Read files from the filesystem
- **Write** — Write files to the filesystem
- **Edit** — Edit existing files
### Search & Research
- **web_search** — Search the web via Tavily or Brave
- **research** — Multi-step web research chains
### Media
- **image_gen** — Generate images with Google Gemini
- **voice** — Text-to-speech (OpenAI, ElevenLabs)
- **stt** — Speech-to-text (OpenAI Whisper)
- **ocr** — Extract text from images (GPT-4o Vision + pytesseract)
### Productivity
- **gmail** — Search, read, and send emails
- **calendar** — List, create, and search calendar events
- **gdrive** — List, download, upload, and share files
- **gdocs** — Read, create, and search documents
### Entertainment
- **spotify** — Search, playback, playlists, now playing
- **reddit** — Search, read threads, trending content
### Agent Tools
- **delegate** — Spawn sub-agents for parallel work
- **skill_gen** — Generate custom skill definitions
### Browser
- **browser** — Playwright-based web automation using accessibility tree snapshots
## Tool Groups
Tools are organized into groups for policy management:
| Group | Tools |
|-------|-------|
| `group:filesystem` | read_file, write_file, list_dir |
| `group:shell` | shell |
| `group:memory` | save_memory, recall_memory |
| `group:search` | web_search |
| `group:media` | image_gen, voice, stt, ocr |
| `group:gmail` | gmail_search, gmail_read, gmail_send |
| `group:calendar` | calendar_list, calendar_create, calendar_search |
| `group:drive` | gdrive_list, gdrive_download, gdrive_upload, gdrive_share |
| `group:docs` | gdocs_read, gdocs_create, gdocs_search |
| `group:spotify` | spotify_search, spotify_now_playing, spotify_playback, spotify_playlist |
| `group:reddit` | reddit_search, reddit_read, reddit_trending |
| `group:voice` | voice, stt |
| `group:research` | research |
| `group:delegation` | delegate |
| `group:skills` | skill_gen |
| `group:mcp` | All MCP server tools |
## Schema Export
Tools can export their definitions in both Anthropic and OpenAI formats:
```python
# Anthropic format (used by Claude Agent SDK)
{
"name": "web_search",
"description": "Search the web for information",
"input_schema": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"}
},
"required": ["query"]
}
}
# OpenAI format (used by Open Interpreter)
{
"type": "function",
"function": {
"name": "web_search",
"description": "Search the web for information",
"parameters": {
"type": "object",
"properties": {
"query": {"type": "string", "description": "Search query"}
},
"required": ["query"]
}
}
}
```

152
docs/deployment/docker.mdx Normal file
View File

@@ -0,0 +1,152 @@
---
title: Docker
description: "Run PocketPaw in Docker with the official Dockerfile and docker-compose configuration. Includes persistent volume mounts for config and memory, environment variable passthrough, and health checks."
section: Deployment
ogType: article
keywords: ["docker", "container", "docker-compose", "dockerfile", "containerized ai"]
tags: ["deployment", "docker"]
---
# Docker Deployment
PocketPaw can be containerized with Docker for easy deployment and isolation.
## Dockerfile
```dockerfile
FROM python:3.11-slim
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y \
git \
&& rm -rf /var/lib/apt/lists/*
# Install PocketPaw
RUN pip install pocketpaw[recommended]
# Or: RUN curl -fsSL https://pocketpaw.xyz/install.sh | sh
# Create data directory
RUN mkdir -p /root/.pocketclaw
# Expose dashboard port
EXPOSE 8000
# Start PocketPaw
CMD ["pocketpaw"]
```
## Docker Compose
```yaml
version: '3.8'
services:
pocketpaw:
build: .
ports:
- "8000:8000"
volumes:
- pocketpaw-data:/root/.pocketclaw
environment:
- POCKETCLAW_ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- POCKETCLAW_DASHBOARD_HOST=0.0.0.0
- POCKETCLAW_DASHBOARD_PORT=8000
- POCKETCLAW_TOOL_PROFILE=coding
restart: unless-stopped
volumes:
pocketpaw-data:
```
## With Ollama
To use Ollama for local models alongside PocketPaw:
```yaml
version: '3.8'
services:
pocketpaw:
build: .
ports:
- "8000:8000"
volumes:
- pocketpaw-data:/root/.pocketclaw
environment:
- POCKETCLAW_ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
- POCKETCLAW_MEM0_AUTO_LEARN=true
- POCKETCLAW_MEM0_LLM_PROVIDER=ollama
- POCKETCLAW_MEM0_LLM_MODEL=llama3.2
- POCKETCLAW_MEM0_EMBEDDER_PROVIDER=ollama
- POCKETCLAW_MEM0_EMBEDDER_MODEL=nomic-embed-text
- OLLAMA_HOST=http://ollama:11434
depends_on:
- ollama
restart: unless-stopped
ollama:
image: ollama/ollama
volumes:
- ollama-data:/root/.ollama
ports:
- "11434:11434"
restart: unless-stopped
volumes:
pocketpaw-data:
ollama-data:
```
After starting, pull the required models:
```bash
docker compose exec ollama ollama pull llama3.2
docker compose exec ollama ollama pull nomic-embed-text
```
## Running
```bash
# Build and start
docker compose up -d
# View logs
docker compose logs -f pocketpaw
# Stop
docker compose down
```
## Persistent Data
Mount the `~/.pocketclaw` directory as a volume to persist:
- Configuration
- Session history
- Memory data
- OAuth tokens
- Audit logs
- MCP server configs
## Browser Automation in Docker
For browser automation, add Playwright dependencies:
```dockerfile
FROM python:3.11-slim
# Install Playwright dependencies
RUN apt-get update && apt-get install -y \
libnss3 libnspr4 libdbus-1-3 libatk1.0-0 \
libatk-bridge2.0-0 libcups2 libdrm2 libxkbcommon0 \
libxcomposite1 libxdamage1 libxrandr2 libgbm1 \
libasound2 libpango-1.0-0 libcairo2 \
&& rm -rf /var/lib/apt/lists/*
RUN pip install pocketpaw[recommended,browser]
RUN playwright install chromium
EXPOSE 8000
CMD ["pocketpaw"]
```

View File

@@ -0,0 +1,128 @@
---
title: Self-Hosting
description: "Deploy PocketPaw on your own server: system requirements, Python 3.11+ setup, reverse proxy configuration with Nginx, SSL certificates, and production hardening recommendations for self-hosted AI."
section: Deployment
ogType: article
keywords: ["self-hosting", "server deployment", "nginx", "ssl", "production", "ubuntu"]
tags: ["deployment", "self-hosting"]
---
# Self-Hosting
PocketPaw is designed to be self-hosted. Here's how to deploy it on your own server.
## Requirements
- **Python 3.11+**
- **2GB RAM** minimum (4GB recommended with Mem0)
- **Linux, macOS, or Windows** (Linux recommended for servers)
- **Anthropic API key** (for Claude Agent SDK backend)
## Basic Deployment
### Install
```bash
# Create a dedicated user (optional)
sudo useradd -m -s /bin/bash pocketpaw
# Install PocketPaw
curl -fsSL https://pocketpaw.xyz/install.sh | sh
```
### Configure
Create the config file:
```bash
mkdir -p ~/.pocketclaw
cat > ~/.pocketclaw/config.json << 'EOF'
{
"anthropic_api_key": "sk-ant-your-key",
"agent_backend": "claude_agent_sdk",
"tool_profile": "coding"
}
EOF
chmod 600 ~/.pocketclaw/config.json
```
### Run
```bash
pocketpaw
```
The dashboard starts on `http://0.0.0.0:8000`.
## Production Deployment
### Behind a Reverse Proxy
For production, put PocketPaw behind nginx or Caddy:
**Caddy (recommended)**:
```
pocketpaw.example.com {
reverse_proxy localhost:8000
}
```
**nginx**:
```nginx
server {
listen 443 ssl;
server_name pocketpaw.example.com;
ssl_certificate /etc/ssl/certs/pocketpaw.crt;
ssl_certificate_key /etc/ssl/private/pocketpaw.key;
location / {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
```
<Callout type="warning">
The WebSocket connection requires `Upgrade` and `Connection` headers to be properly proxied. Without these, real-time streaming won't work.
</Callout>
### Environment Variables
Set environment variables in a `.env` file or your system's environment:
```bash
# /etc/pocketpaw/env
POCKETCLAW_ANTHROPIC_API_KEY=sk-ant-...
POCKETCLAW_DASHBOARD_HOST=127.0.0.1
POCKETCLAW_DASHBOARD_PORT=8000
POCKETCLAW_TOOL_PROFILE=coding
```
### Security Hardening
1. **Run as a dedicated user** — Don't run as root
2. **Restrict file permissions** — Config files should be 600
3. **Use a firewall** — Only expose the reverse proxy port
4. **Enable Guardian AI** — Active by default with Anthropic key
5. **Set allowed IDs** — Restrict channel access to specific users
6. **Run security audit** — `pocketpaw --security-audit`
## Resource Planning
| Component | RAM | CPU | Notes |
|-----------|-----|-----|-------|
| PocketPaw core | ~100MB | Minimal | FastAPI + agent loop |
| Mem0 + Qdrant | ~500MB | Minimal | Embedded vector store |
| Ollama (local) | 4-16GB | GPU recommended | Depends on model size |
| Playwright | ~200MB | Moderate | Browser automation |
For a typical deployment with Claude Agent SDK (cloud) and Mem0 with Ollama:
- **Minimum**: 4GB RAM, 2 CPU cores
- **Recommended**: 8GB RAM, 4 CPU cores

148
docs/deployment/systemd.mdx Normal file
View File

@@ -0,0 +1,148 @@
---
title: Systemd Service
description: "Run PocketPaw as a systemd service on Linux for automatic startup, restart on failure, and clean shutdown. Includes a complete unit file with security hardening and journal logging configuration."
section: Deployment
ogType: article
keywords: ["systemd", "linux service", "auto-start", "daemon", "unit file"]
tags: ["deployment", "systemd", "linux"]
---
# Systemd Service
Run PocketPaw as a background service on Linux with systemd for automatic startup and restart.
## Service File
Create `/etc/systemd/system/pocketpaw.service`:
```ini
[Unit]
Description=PocketPaw AI Agent
After=network.target
[Service]
Type=simple
User=pocketpaw
Group=pocketpaw
WorkingDirectory=/home/pocketpaw
ExecStart=/usr/local/bin/pocketpaw
Restart=on-failure
RestartSec=10
# Environment
EnvironmentFile=/etc/pocketpaw/env
# Security hardening
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=read-only
ReadWritePaths=/home/pocketpaw/.pocketclaw
PrivateTmp=yes
[Install]
WantedBy=multi-user.target
```
## Environment File
Create `/etc/pocketpaw/env`:
```bash
POCKETCLAW_ANTHROPIC_API_KEY=sk-ant-your-key
POCKETCLAW_DASHBOARD_HOST=127.0.0.1
POCKETCLAW_DASHBOARD_PORT=8000
POCKETCLAW_AGENT_BACKEND=claude_agent_sdk
POCKETCLAW_TOOL_PROFILE=coding
```
Set permissions:
```bash
sudo chmod 600 /etc/pocketpaw/env
sudo chown pocketpaw:pocketpaw /etc/pocketpaw/env
```
## Setup
```bash
# Create dedicated user
sudo useradd -m -s /bin/bash pocketpaw
# Install PocketPaw
sudo -u pocketpaw pip install --user pocketpaw[recommended]
# Create config directory
sudo mkdir -p /etc/pocketpaw
sudo chown pocketpaw:pocketpaw /etc/pocketpaw
# Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable pocketpaw
sudo systemctl start pocketpaw
```
## Managing the Service
```bash
# Start
sudo systemctl start pocketpaw
# Stop
sudo systemctl stop pocketpaw
# Restart
sudo systemctl restart pocketpaw
# Check status
sudo systemctl status pocketpaw
# View logs
sudo journalctl -u pocketpaw -f
# View recent logs
sudo journalctl -u pocketpaw --since "1 hour ago"
```
## Log Rotation
Systemd handles log rotation via journald. For the audit log, add a logrotate config:
```
/home/pocketpaw/.pocketclaw/audit.jsonl {
weekly
rotate 12
compress
missingok
notifempty
copytruncate
}
```
## Auto-Updates
Create a timer for periodic updates:
```ini
# /etc/systemd/system/pocketpaw-update.timer
[Unit]
Description=Update PocketPaw weekly
[Timer]
OnCalendar=weekly
Persistent=true
[Install]
WantedBy=timers.target
```
```ini
# /etc/systemd/system/pocketpaw-update.service
[Unit]
Description=Update PocketPaw
[Service]
Type=oneshot
User=pocketpaw
ExecStart=/usr/local/bin/pip install --upgrade pocketpaw[recommended]
ExecStartPost=/bin/systemctl restart pocketpaw
```

721
docs/docs-config.json Normal file
View File

@@ -0,0 +1,721 @@
{
"metadata": {
"name": "PocketPaw",
"description": "Self-hosted AI agent controlled via Telegram, Discord, Slack, WhatsApp, or a web dashboard",
"version": "1.0.0"
},
"branding": {
"favicon": "/paw.webp",
"logo": {
"light": "/paw.webp",
"dark": "/paw.webp",
"href": "/"
},
"colors": {
"primary": "#0A84FF",
"secondary": "#4a6fa5",
"accent": "#d49a5c",
"background": "#f9f8f6",
"text": "#1a1a2e"
},
"fonts": {
"body": "Plus Jakarta Sans",
"code": "JetBrains Mono"
}
},
"theme": {
"mode": "auto",
"defaultDark": false,
"primaryColor": "#0A84FF",
"accentColor": "#d49a5c"
},
"navigation": {
"navbar": {
"links": [
{
"label": "Docs",
"href": "/introduction"
},
{
"label": "Guides",
"type": "dropdown",
"items": [
{
"label": "Channels",
"href": "/channels",
"description": "Connect to 9+ messaging platforms"
},
{
"label": "Integrations",
"href": "/integrations",
"description": "Gmail, Calendar, Drive, Spotify, and more"
},
{
"label": "Tools",
"href": "/tools",
"description": "50+ built-in tools and custom tool creation"
},
{
"label": "API Reference",
"href": "/api",
"description": "REST and WebSocket APIs"
}
]
}
],
"social": {
"github": {
"href": "https://github.com/pocketpaw/pocketpaw",
"showStars": true
}
},
"cta": {
"label": "Get Started",
"href": "/getting-started/installation"
}
},
"anchors": [
{
"label": "Documentation",
"href": "/introduction",
"icon": "lucide:book-open",
"groups": ["Introduction", "Getting Started", "Core Concepts", "Channels", "Agent Backends", "Tools", "Integrations", "Security", "Memory", "Advanced", "Deployment"]
},
{
"label": "API Reference",
"href": "/api",
"icon": "lucide:code",
"color": "#3b82f6",
"groups": ["API Reference"]
}
],
"sidebar": [
{
"label": "Introduction",
"items": [
{
"label": "Welcome",
"href": "/introduction",
"icon": "lucide:home"
},
{
"label": "Why PocketPaw?",
"href": "/introduction/why-pocketpaw",
"icon": "lucide:sparkles"
}
]
},
{
"label": "Getting Started",
"items": [
{
"label": "Installation",
"href": "/getting-started/installation",
"icon": "lucide:download"
},
{
"label": "Quick Start",
"href": "/getting-started/quick-start",
"icon": "lucide:rocket"
},
{
"label": "Configuration",
"href": "/getting-started/configuration",
"icon": "lucide:settings"
},
{
"label": "Project Structure",
"href": "/getting-started/project-structure",
"icon": "lucide:folder-tree"
}
]
},
{
"label": "Core Concepts",
"items": [
{
"label": "Architecture",
"href": "/concepts/architecture",
"icon": "lucide:layers"
},
{
"label": "Message Bus",
"href": "/concepts/message-bus",
"icon": "lucide:arrow-left-right"
},
{
"label": "Agent Loop",
"href": "/concepts/agent-loop",
"icon": "lucide:repeat"
},
{
"label": "Memory System",
"href": "/concepts/memory-system",
"icon": "lucide:brain"
},
{
"label": "Tool System",
"href": "/concepts/tool-system",
"icon": "lucide:wrench"
},
{
"label": "Security Model",
"href": "/concepts/security-model",
"icon": "lucide:shield"
}
]
},
{
"label": "Channels",
"items": [
{
"label": "Overview",
"href": "/channels",
"icon": "lucide:radio"
},
{
"label": "Web Dashboard",
"href": "/channels/web-dashboard",
"icon": "lucide:layout-dashboard"
},
{
"label": "Telegram",
"href": "/channels/telegram",
"icon": "lucide:send"
},
{
"label": "Discord",
"href": "/channels/discord",
"icon": "lucide:gamepad-2"
},
{
"label": "Slack",
"href": "/channels/slack",
"icon": "lucide:hash"
},
{
"label": "WhatsApp",
"href": "/channels/whatsapp",
"icon": "lucide:message-circle"
},
{
"label": "Signal",
"href": "/channels/signal",
"icon": "lucide:lock"
},
{
"label": "Matrix",
"href": "/channels/matrix",
"icon": "lucide:grid-3x3"
},
{
"label": "Microsoft Teams",
"href": "/channels/teams",
"icon": "lucide:users"
},
{
"label": "Google Chat",
"href": "/channels/google-chat",
"icon": "lucide:message-square"
}
]
},
{
"label": "Agent Backends",
"items": [
{
"label": "Overview",
"href": "/backends",
"icon": "lucide:cpu"
},
{
"label": "Claude Agent SDK",
"href": "/backends/claude-sdk",
"icon": "lucide:sparkles"
},
{
"label": "PocketPaw Native",
"href": "/backends/pocketpaw-native",
"icon": "lucide:bot"
},
{
"label": "Open Interpreter",
"href": "/backends/open-interpreter",
"icon": "lucide:terminal"
}
]
},
{
"label": "Tools",
"items": [
{
"label": "Overview",
"href": "/tools",
"icon": "lucide:wrench"
},
{
"label": "Web Search",
"href": "/tools/web-search",
"icon": "lucide:search"
},
{
"label": "Image Generation",
"href": "/tools/image-generation",
"icon": "lucide:image"
},
{
"label": "Voice & TTS",
"href": "/tools/voice-tts",
"icon": "lucide:volume-2"
},
{
"label": "Speech to Text",
"href": "/tools/speech-to-text",
"icon": "lucide:mic"
},
{
"label": "Research",
"href": "/tools/research",
"icon": "lucide:book-open"
},
{
"label": "OCR",
"href": "/tools/ocr",
"icon": "lucide:scan"
},
{
"label": "Browser Automation",
"href": "/tools/browser",
"icon": "lucide:globe"
},
{
"label": "Delegation",
"href": "/tools/delegation",
"icon": "lucide:git-branch"
},
{
"label": "Skill Generator",
"href": "/tools/skill-generator",
"icon": "lucide:wand-2"
},
{
"label": "Desktop",
"href": "/tools/desktop",
"icon": "lucide:monitor"
},
{
"label": "Session Tools",
"href": "/tools/sessions",
"icon": "lucide:history"
},
{
"label": "Tool Policy",
"href": "/tools/tool-policy",
"icon": "lucide:shield-check"
},
{
"label": "Custom Tools",
"href": "/tools/custom-tools",
"icon": "lucide:puzzle"
}
]
},
{
"label": "Integrations",
"items": [
{
"label": "Overview",
"href": "/integrations",
"icon": "lucide:plug"
},
{
"label": "OAuth Framework",
"href": "/integrations/oauth",
"icon": "lucide:key"
},
{
"label": "Gmail",
"href": "/integrations/gmail",
"icon": "lucide:mail"
},
{
"label": "Google Calendar",
"href": "/integrations/calendar",
"icon": "lucide:calendar"
},
{
"label": "Google Drive",
"href": "/integrations/google-drive",
"icon": "lucide:hard-drive"
},
{
"label": "Google Docs",
"href": "/integrations/google-docs",
"icon": "lucide:file-text"
},
{
"label": "Spotify",
"href": "/integrations/spotify",
"icon": "lucide:music"
},
{
"label": "Reddit",
"href": "/integrations/reddit",
"icon": "lucide:message-circle"
},
{
"label": "MCP Servers",
"href": "/integrations/mcp-servers",
"icon": "lucide:server"
}
]
},
{
"label": "Security",
"items": [
{
"label": "Overview",
"href": "/security",
"icon": "lucide:shield"
},
{
"label": "Guardian AI",
"href": "/security/guardian-ai",
"icon": "lucide:shield-alert"
},
{
"label": "Injection Scanner",
"href": "/security/injection-scanner",
"icon": "lucide:scan-line"
},
{
"label": "Audit Log",
"href": "/security/audit-log",
"icon": "lucide:file-check"
},
{
"label": "Security Audit CLI",
"href": "/security/audit-cli",
"icon": "lucide:terminal"
},
{
"label": "Self-Audit Daemon",
"href": "/security/self-audit-daemon",
"icon": "lucide:activity"
}
]
},
{
"label": "Memory",
"items": [
{
"label": "Overview",
"href": "/memory",
"icon": "lucide:brain"
},
{
"label": "File Store",
"href": "/memory/file-store",
"icon": "lucide:database"
},
{
"label": "Mem0 Integration",
"href": "/memory/mem0",
"icon": "lucide:sparkles"
},
{
"label": "Sessions",
"href": "/memory/sessions",
"icon": "lucide:history"
},
{
"label": "Context Building",
"href": "/memory/context-building",
"icon": "lucide:layers"
},
{
"label": "Memory Isolation",
"href": "/memory/memory-isolation",
"icon": "lucide:shield"
}
]
},
{
"label": "Advanced",
"items": [
{
"label": "Model Router",
"href": "/advanced/model-router",
"icon": "lucide:route"
},
{
"label": "Plan Mode",
"href": "/advanced/plan-mode",
"icon": "lucide:list-checks"
},
{
"label": "Cron Scheduler",
"href": "/advanced/scheduler",
"icon": "lucide:clock"
},
{
"label": "Skills System",
"href": "/advanced/skills",
"icon": "lucide:wand-2"
},
{
"label": "Deep Work",
"href": "/advanced/deep-work",
"icon": "lucide:brain"
},
{
"label": "Mission Control",
"href": "/advanced/mission-control",
"icon": "lucide:radar"
},
{
"label": "Autonomous Messaging",
"href": "/advanced/autonomous-messaging",
"icon": "lucide:bell"
}
]
},
{
"label": "API Reference",
"items": [
{
"label": "Overview",
"href": "/api",
"icon": "lucide:server"
},
{
"label": "Channels",
"items": [
{ "label": "Get Channel Status", "href": "/api/get-channels-status", "method": "GET" },
{ "label": "Save Channel Config", "href": "/api/post-channels-save", "method": "POST" },
{ "label": "Toggle Channel", "href": "/api/post-channels-toggle", "method": "POST" }
]
},
{
"label": "Sessions",
"items": [
{ "label": "List Sessions", "href": "/api/get-sessions", "method": "GET" },
{ "label": "Search Sessions", "href": "/api/get-sessions-search", "method": "GET" },
{ "label": "Delete Session", "href": "/api/delete-session", "method": "DELETE" },
{ "label": "Rename Session", "href": "/api/post-session-title", "method": "POST" },
{ "label": "Get Session History", "href": "/api/get-session-history", "method": "GET" }
]
},
{
"label": "MCP Servers",
"items": [
{ "label": "Get MCP Status", "href": "/api/get-mcp-status", "method": "GET" },
{ "label": "Add MCP Server", "href": "/api/post-mcp-add", "method": "POST" },
{ "label": "Remove MCP Server", "href": "/api/post-mcp-remove", "method": "POST" },
{ "label": "Toggle MCP Server", "href": "/api/post-mcp-toggle", "method": "POST" },
{ "label": "Test MCP Server", "href": "/api/post-mcp-test", "method": "POST" },
{ "label": "List MCP Presets", "href": "/api/get-mcp-presets", "method": "GET" },
{ "label": "Install MCP Preset", "href": "/api/post-mcp-preset-install", "method": "POST" }
]
},
{
"label": "Memory",
"items": [
{ "label": "List Memories", "href": "/api/get-memory-long-term", "method": "GET" },
{ "label": "Delete Memory", "href": "/api/delete-memory-entry", "method": "DELETE" },
{ "label": "Get Memory Settings", "href": "/api/get-memory-settings", "method": "GET" },
{ "label": "Update Memory Settings", "href": "/api/post-memory-settings", "method": "POST" },
{ "label": "Get Memory Stats", "href": "/api/get-memory-stats", "method": "GET" }
]
},
{
"label": "Security & Audit",
"items": [
{ "label": "Get Audit Logs", "href": "/api/get-audit-logs", "method": "GET" },
{ "label": "Run Security Audit", "href": "/api/post-security-audit", "method": "POST" },
{ "label": "List Audit Reports", "href": "/api/get-self-audit-reports", "method": "GET" },
{ "label": "Get Audit Report", "href": "/api/get-self-audit-report", "method": "GET" },
{ "label": "Trigger Self-Audit", "href": "/api/post-self-audit-run", "method": "POST" }
]
},
{
"label": "Authentication",
"items": [
{ "label": "Create Session Token", "href": "/api/post-auth-session", "method": "POST" },
{ "label": "Generate QR Code", "href": "/api/get-qr-code", "method": "GET" },
{ "label": "Regenerate Token", "href": "/api/post-token-regenerate", "method": "POST" },
{ "label": "Start OAuth Flow", "href": "/api/get-oauth-authorize", "method": "GET" }
]
},
{
"label": "Webhooks",
"items": [
{ "label": "List Webhooks", "href": "/api/get-webhooks", "method": "GET" },
{ "label": "Create Webhook", "href": "/api/post-webhooks-add", "method": "POST" },
{ "label": "Remove Webhook", "href": "/api/post-webhooks-remove", "method": "POST" },
{ "label": "Receive Payload", "href": "/api/post-webhook-inbound", "method": "POST" }
]
},
{
"label": "Deep Work",
"items": [
{ "label": "Start Project", "href": "/api/post-deep-work-start", "method": "POST" },
{ "label": "Get Plan", "href": "/api/get-deep-work-plan", "method": "GET" },
{ "label": "Approve Plan", "href": "/api/post-deep-work-approve", "method": "POST" },
{ "label": "Pause Project", "href": "/api/post-deep-work-pause", "method": "POST" },
{ "label": "Resume Project", "href": "/api/post-deep-work-resume", "method": "POST" },
{ "label": "Skip Task", "href": "/api/post-deep-work-skip-task", "method": "POST" }
]
},
{
"label": "Mission Control",
"items": [
{ "label": "List Agents", "href": "/api/get-mc-agents", "method": "GET" },
{ "label": "Create Agent", "href": "/api/post-mc-agent", "method": "POST" },
{ "label": "List Tasks", "href": "/api/get-mc-tasks", "method": "GET" },
{ "label": "Create Task", "href": "/api/post-mc-task", "method": "POST" },
{ "label": "Run Task", "href": "/api/post-mc-run-task", "method": "POST" },
{ "label": "Get Standup", "href": "/api/get-mc-standup", "method": "GET" }
]
},
{
"label": "Tunnel",
"items": [
{ "label": "Get Tunnel Status", "href": "/api/get-tunnel-status", "method": "GET" },
{ "label": "Start Tunnel", "href": "/api/post-tunnel-start", "method": "POST" },
{ "label": "Stop Tunnel", "href": "/api/post-tunnel-stop", "method": "POST" }
]
},
{
"label": "WebSocket Protocol",
"href": "/api/websocket",
"icon": "lucide:radio"
},
{
"label": "Configuration Reference",
"href": "/api/configuration-reference",
"icon": "lucide:settings"
}
]
},
{
"label": "Deployment",
"items": [
{
"label": "Self-Hosting",
"href": "/deployment/self-hosting",
"icon": "lucide:server"
},
{
"label": "Docker",
"href": "/deployment/docker",
"icon": "lucide:container"
},
{
"label": "Systemd Service",
"href": "/deployment/systemd",
"icon": "lucide:cog"
}
]
}
]
},
"seo": {
"ogImage": "/pocket-paw-og.webp",
"defaultAuthor": "PocketPaw Team",
"defaultKeywords": [
"ai agent",
"self-hosted ai",
"local ai assistant",
"multi-channel ai bot",
"telegram ai bot",
"discord ai bot",
"slack ai bot",
"whatsapp ai bot",
"claude agent sdk",
"open interpreter",
"mcp servers",
"ai automation",
"pocketpaw",
"private ai",
"ai tools",
"multi-agent orchestration"
],
"enableJsonLd": true,
"organizationName": "PocketPaw",
"organizationLogo": "/paw.webp",
"articleType": "TechArticle",
"autoCanonical": true,
"enableBreadcrumbs": true,
"twitterHandle": "@pocketpaw_ai",
"twitterSite": "@pocketpaw_ai"
},
"search": {
"enabled": true,
"provider": "local",
"placeholder": "Search PocketPaw docs..."
},
"integrations": {
"editPage": {
"enabled": true,
"pattern": "https://github.com/pocketpaw/pocketpaw/edit/main/docs/{path}"
},
"lastUpdated": {
"enabled": true,
"format": "long"
},
"feedback": {
"enabled": true
},
"copyPage": {
"enabled": true
}
},
"assets": {
"images": "_images",
"static": "_assets"
},
"landing": {
"type": "custom",
"source": "_landing",
"navbar": false,
"footer": false
},
"footer": {
"layout": "full",
"tagline": "Your AI agent, your rules. Self-hosted, multi-channel, infinitely extensible.",
"copyright": "\u00a9 {year} PocketPaw. All rights reserved.",
"showBranding": true,
"showVersion": true,
"socials": {
"github": "https://github.com/pocketpaw/pocketpaw"
},
"links": [
{
"title": "Documentation",
"items": [
{ "label": "Getting Started", "href": "/getting-started/installation" },
{ "label": "Architecture", "href": "/concepts/architecture" },
{ "label": "Channels", "href": "/channels" },
{ "label": "API Reference", "href": "/api" }
]
},
{
"title": "Features",
"items": [
{ "label": "Tools", "href": "/tools" },
{ "label": "Integrations", "href": "/integrations" },
{ "label": "Security", "href": "/security" },
{ "label": "Memory", "href": "/memory" }
]
},
{
"title": "Community",
"items": [
{ "label": "GitHub", "href": "https://github.com/pocketpaw/pocketpaw", "external": true },
{ "label": "Issues", "href": "https://github.com/pocketpaw/pocketpaw/issues", "external": true }
]
}
]
}
}

View File

@@ -0,0 +1,157 @@
---
title: Configuration
description: "Complete guide to configuring PocketPaw: environment variables with POCKETCLAW_ prefix, JSON config file, API keys, channel tokens, tool profiles, and memory settings."
section: Getting Started
ogType: article
keywords: ["environment variables", "config file", "settings", "api keys", "pocketclaw prefix"]
tags: ["configuration", "settings"]
---
# Configuration
PocketPaw uses a layered configuration system built on Pydantic Settings.
## Configuration Sources
Configuration is loaded from these sources (in order of precedence):
1. **Environment variables** — Prefixed with `POCKETCLAW_`
2. **Config file** — `~/.pocketclaw/config.json`
3. **Web dashboard** — Settings saved through the UI
## Environment Variables
All settings use the `POCKETCLAW_` prefix:
```bash
# Core
export POCKETCLAW_ANTHROPIC_API_KEY="sk-ant-..."
export POCKETCLAW_OPENAI_API_KEY="sk-..."
export POCKETCLAW_AGENT_BACKEND="claude_agent_sdk" # or pocketpaw_native, open_interpreter
# Web Dashboard
export POCKETCLAW_DASHBOARD_PORT=8000
export POCKETCLAW_DASHBOARD_HOST="0.0.0.0"
# Telegram
export POCKETCLAW_TELEGRAM_TOKEN="your-bot-token"
export POCKETCLAW_ALLOWED_TELEGRAM_IDS="123456,789012"
# Discord
export POCKETCLAW_DISCORD_BOT_TOKEN="your-discord-token"
export POCKETCLAW_DISCORD_ALLOWED_GUILD_IDS="111,222"
export POCKETCLAW_DISCORD_ALLOWED_USER_IDS="333,444"
# Slack
export POCKETCLAW_SLACK_BOT_TOKEN="xoxb-..."
export POCKETCLAW_SLACK_APP_TOKEN="xapp-..."
export POCKETCLAW_SLACK_ALLOWED_CHANNEL_IDS="C01,C02"
# WhatsApp Business
export POCKETCLAW_WHATSAPP_ACCESS_TOKEN="your-token"
export POCKETCLAW_WHATSAPP_PHONE_NUMBER_ID="123456"
export POCKETCLAW_WHATSAPP_VERIFY_TOKEN="your-verify-token"
export POCKETCLAW_WHATSAPP_ALLOWED_PHONE_NUMBERS="+1234567890"
# WhatsApp Personal
export POCKETCLAW_WHATSAPP_MODE="personal" # or "business"
# Signal
export POCKETCLAW_SIGNAL_API_URL="http://localhost:8080"
export POCKETCLAW_SIGNAL_PHONE_NUMBER="+1234567890"
# Matrix
export POCKETCLAW_MATRIX_HOMESERVER="https://matrix.org"
export POCKETCLAW_MATRIX_USER_ID="@bot:matrix.org"
export POCKETCLAW_MATRIX_ACCESS_TOKEN="your-token"
# Microsoft Teams
export POCKETCLAW_TEAMS_APP_ID="your-app-id"
export POCKETCLAW_TEAMS_APP_PASSWORD="your-password"
# Google Chat
export POCKETCLAW_GCHAT_PROJECT_ID="your-project-id"
export POCKETCLAW_GCHAT_SERVICE_ACCOUNT_KEY="/path/to/key.json"
```
## Config File
The JSON config file at `~/.pocketclaw/config.json` stores all settings:
```json
{
"anthropic_api_key": "sk-ant-...",
"agent_backend": "claude_agent_sdk",
"tool_profile": "coding",
"tools_allow": [],
"tools_deny": [],
"web_search_provider": "tavily",
"tavily_api_key": "tvly-...",
"mem0_auto_learn": true,
"mem0_llm_provider": "ollama",
"mem0_llm_model": "llama3.2"
}
```
## Tool Policy Configuration
Control which tools are available via profiles and allow/deny lists:
```bash
# Profile: minimal, coding, or full
export POCKETCLAW_TOOL_PROFILE="coding"
# Allow specific tools (comma-separated)
export POCKETCLAW_TOOLS_ALLOW="web_search,image_gen"
# Deny specific tools (takes precedence over allow)
export POCKETCLAW_TOOLS_DENY="shell,write_file"
```
See [Tool Policy](/tools/tool-policy) for detailed documentation.
## Memory Configuration
```bash
# Mem0 semantic memory
export POCKETCLAW_MEM0_AUTO_LEARN=true
export POCKETCLAW_MEM0_LLM_PROVIDER="ollama" # or anthropic, openai
export POCKETCLAW_MEM0_LLM_MODEL="llama3.2"
export POCKETCLAW_MEM0_EMBEDDER_PROVIDER="ollama" # or openai
export POCKETCLAW_MEM0_EMBEDDER_MODEL="nomic-embed-text"
export POCKETCLAW_MEM0_VECTOR_STORE="qdrant"
```
## Google Integration
For Gmail, Calendar, Drive, and Docs:
```bash
export POCKETCLAW_GOOGLE_CLIENT_ID="your-client-id"
export POCKETCLAW_GOOGLE_CLIENT_SECRET="your-secret"
```
OAuth tokens are stored in `~/.pocketclaw/tokens/`.
## Spotify Integration
```bash
export POCKETCLAW_SPOTIFY_CLIENT_ID="your-client-id"
export POCKETCLAW_SPOTIFY_CLIENT_SECRET="your-secret"
```
## Data Directory
PocketPaw stores all data in `~/.pocketclaw/`:
```
~/.pocketclaw/
├── config.json # Configuration file
├── memory/ # Session history and facts
├── identity/
│ └── USER.md # User profile (auto-created)
├── skills/ # Custom skill definitions
├── tokens/ # OAuth tokens
├── audit.jsonl # Security audit log
└── mcp.json # MCP server configuration
```

View File

@@ -0,0 +1,137 @@
---
title: Installation
description: "Install PocketPaw with pip or uv in under a minute. Supports Python 3.11+, optional extras for channels, tools, and integrations. Works on Linux, macOS, and Windows."
section: Getting Started
ogType: article
keywords: ["install", "pip install", "uv sync", "python package", "dependencies"]
tags: ["setup", "installation"]
---
# Installation
PocketPaw requires **Python 3.11+** and can be installed via pip or uv.
## Prerequisites
- **Python 3.11** or higher
- **pip**, **uv**, or **pipx** package manager
- An **Anthropic API key** (for the default Claude Agent SDK backend)
## Quick Install
The fastest way to get started — the interactive installer handles Python, uv, and feature selection:
```bash
curl -fsSL https://pocketpaw.xyz/install.sh | sh
```
Or install directly with pip:
```bash
pip install pocketpaw
```
This installs the core package with minimal dependencies (~10 packages). To add specific features, use extras.
## Using uv (Recommended)
[uv](https://docs.astral.sh/uv/) is the recommended package manager for faster installs:
```bash
# Install uv if you haven't
curl -LsSf https://astral.sh/uv/install.sh | sh
# Clone and install for development
git clone https://github.com/pocketpaw/pocketpaw.git
cd pocketpaw
uv sync --dev
```
## Package Extras
PocketPaw uses a modular extras system. Install only what you need:
### Channel Extras
```bash
# Individual channels
pip install pocketpaw[telegram]
pip install pocketpaw[discord]
pip install pocketpaw[slack]
pip install pocketpaw[whatsapp-personal] # QR-code pairing
# All channels
pip install pocketpaw[all-channels]
```
### Tool Extras
```bash
# Specific tools
pip install pocketpaw[browser] # Playwright browser automation
pip install pocketpaw[image] # Google Gemini image generation
pip install pocketpaw[memory] # Mem0 semantic memory
# All tools
pip install pocketpaw[all-tools]
```
### Backend Extras
```bash
pip install pocketpaw[native] # PocketPaw Native backend
pip install pocketpaw[desktop] # Desktop automation tools
```
### Composite Extras
```bash
# Recommended setup (dashboard + common tools)
pip install pocketpaw[recommended]
# Everything included
pip install pocketpaw[all]
# Development (includes test and lint tools)
pip install pocketpaw[dev]
```
## Environment Variables
Set your API keys as environment variables. All PocketPaw settings use the `POCKETCLAW_` prefix:
```bash
# Required: Anthropic API key for Claude
export POCKETCLAW_ANTHROPIC_API_KEY="sk-ant-..."
# Optional: Other API keys
export POCKETCLAW_OPENAI_API_KEY="sk-..." # For voice/TTS/STT
export POCKETCLAW_TAVILY_API_KEY="tvly-..." # For web search
export POCKETCLAW_GOOGLE_API_KEY="..." # For image generation
export POCKETCLAW_BRAVE_SEARCH_API_KEY="..." # For Brave Search
```
Alternatively, you can configure these through the web dashboard's settings panel.
## Verify Installation
```bash
# Run PocketPaw (starts web dashboard)
pocketpaw
# Or with uv
uv run pocketpaw
```
The web dashboard will start at `http://localhost:8000`. Open it in your browser to verify everything is working.
## Next Steps
<CardGroup>
<Card title="Quick Start" icon="lucide:rocket" href="/getting-started/quick-start">
Set up your first channel and send your first message.
</Card>
<Card title="Configuration" icon="lucide:settings" href="/getting-started/configuration">
Learn about all configuration options.
</Card>
</CardGroup>

View File

@@ -0,0 +1,162 @@
---
title: Project Structure
description: "Explore the PocketPaw codebase layout: src/pocketclaw package structure, bus adapters, agent backends, tool registry, memory stores, and frontend dashboard files."
section: Getting Started
ogType: article
keywords: ["codebase", "directory layout", "source code", "package structure"]
tags: ["architecture", "development"]
---
# Project Structure
PocketPaw's codebase follows a modular architecture. Here's how it's organized.
## Top-Level Layout
```
pocketpaw/
├── src/pocketclaw/ # Main Python package
│ ├── __main__.py # CLI entry point
│ ├── config.py # Pydantic Settings configuration
│ ├── scheduler.py # Cron/recurring task scheduler
│ ├── _compat.py # Optional dependency helpers
│ │
│ ├── agents/ # Agent backends and orchestration
│ │ ├── loop.py # Main AgentLoop (message bus consumer)
│ │ ├── router.py # AgentRouter (backend selector)
│ │ ├── claude_sdk.py # Claude Agent SDK backend
│ │ ├── pocketpaw_native.py # Native backend
│ │ ├── open_interpreter.py # Open Interpreter backend
│ │ ├── model_router.py # Complexity-based model selection
│ │ ├── plan_mode.py # Plan approval workflow
│ │ └── delegation.py # Sub-agent delegation
│ │
│ ├── bus/ # Event-driven message bus
│ │ ├── events.py # InboundMessage, OutboundMessage, SystemEvent
│ │ ├── message_bus.py # Pub/sub message bus
│ │ └── adapters/ # Channel adapters
│ │ ├── base.py # BaseChannelAdapter protocol
│ │ ├── websocket_adapter.py
│ │ ├── telegram_adapter.py
│ │ ├── discord_adapter.py
│ │ ├── slack_adapter.py
│ │ ├── whatsapp_adapter.py
│ │ ├── neonize_adapter.py # WhatsApp Personal
│ │ ├── signal_adapter.py
│ │ ├── matrix_adapter.py
│ │ ├── teams_adapter.py
│ │ └── gchat_adapter.py
│ │
│ ├── tools/ # Tool system
│ │ ├── registry.py # ToolRegistry
│ │ ├── policy.py # Tool policy (profiles, allow/deny)
│ │ └── builtin/ # Built-in tools
│ │ ├── web_search.py
│ │ ├── image_gen.py
│ │ ├── voice.py
│ │ ├── stt.py
│ │ ├── research.py
│ │ ├── ocr.py
│ │ ├── gmail.py
│ │ ├── calendar.py
│ │ ├── gdrive.py
│ │ ├── gdocs.py
│ │ ├── spotify.py
│ │ ├── reddit.py
│ │ ├── skill_gen.py
│ │ └── delegate.py
│ │
│ ├── memory/ # Memory subsystem
│ │ ├── manager.py # MemoryManager factory
│ │ ├── file_store.py # File-based session storage
│ │ ├── mem0_store.py # Mem0 semantic memory
│ │ └── context_builder.py # Context assembly
│ │
│ ├── security/ # Security subsystem
│ │ ├── guardian.py # Guardian AI safety check
│ │ ├── injection_scanner.py # Prompt injection detection
│ │ ├── audit.py # Append-only audit log
│ │ ├── audit_cli.py # CLI security audit
│ │ └── self_audit.py # Self-audit daemon (12 checks)
│ │
│ ├── browser/ # Browser automation
│ │ ├── driver.py # BrowserDriver (Playwright)
│ │ └── context.py # Navigation context
│ │
│ ├── bootstrap/ # System prompt assembly
│ │ ├── context.py # AgentContextBuilder
│ │ └── default_provider.py # Default identity + USER.md
│ │
│ ├── integrations/ # Third-party integrations
│ │ ├── oauth.py # OAuth framework (Google, Spotify)
│ │ ├── token_store.py # Token persistence
│ │ ├── gmail.py # Gmail API client
│ │ ├── gcalendar.py # Google Calendar client
│ │ ├── gdrive.py # Google Drive client
│ │ ├── gdocs.py # Google Docs client
│ │ ├── spotify.py # Spotify API client
│ │ └── reddit.py # Reddit client (no auth)
│ │
│ ├── mcp/ # Model Context Protocol
│ │ ├── config.py # MCPServerConfig, load_mcp_config
│ │ └── manager.py # MCPManager (stdio/HTTP transport)
│ │
│ ├── daemon/ # Background services
│ │ └── self_audit.py # Self-audit daemon
│ │
│ ├── llm/ # LLM utilities
│ │ └── router.py # LLMRouter (standalone chat)
│ │
│ └── frontend/ # Web dashboard
│ ├── templates/ # Jinja2 HTML templates
│ ├── static/
│ │ ├── js/
│ │ │ ├── app.js # Main application
│ │ │ ├── state.js # StateManager
│ │ │ ├── sessions.js # Session management
│ │ │ ├── channels.js # Channel management
│ │ │ ├── mcp.js # MCP server management
│ │ │ └── feature-loader.js # Feature auto-discovery
│ │ └── css/
│ │ └── style.css
│ ├── dashboard.py # FastAPI dashboard server
│ └── web_server.py # Static file serving
├── tests/ # Test suite (1000+ tests)
│ ├── test_bus.py
│ ├── test_tool_policy.py
│ ├── test_discord_adapter.py
│ ├── test_slack_adapter.py
│ ├── test_whatsapp_adapter.py
│ └── ...
├── pyproject.toml # Package configuration
├── CLAUDE.md # AI coding assistant instructions
└── README.md # Project README
```
## Key Directories
### `agents/` — Agent Backends
Contains the core agent loop and all backend implementations. The `AgentRouter` selects which backend to use based on configuration.
### `bus/` — Message Bus
The heart of PocketPaw. All communication flows through the message bus using three event types: `InboundMessage`, `OutboundMessage`, and `SystemEvent`.
### `tools/` — Tool System
Built-in tools and the tool registry. Each tool implements the `ToolProtocol` and provides both Anthropic and OpenAI schema exports.
### `memory/` — Memory System
Session history (file-based) and long-term semantic memory (Mem0). The context builder assembles memory into the agent's context window.
### `security/` — Security Layer
Multiple security subsystems including Guardian AI, injection scanning, and audit logging.
### `frontend/` — Web Dashboard
Vanilla JS/CSS/HTML served via FastAPI + Jinja2. No build step required. Communicates with the backend over WebSocket.

View File

@@ -0,0 +1,134 @@
---
title: Quick Start
description: "Get PocketPaw running in 5 minutes: install the package, set your API key, launch the web dashboard, and send your first message to your self-hosted AI agent."
section: Getting Started
ogType: article
keywords: ["quick start", "first run", "tutorial", "beginner guide", "web dashboard"]
tags: ["tutorial", "getting-started"]
---
# Quick Start
This guide gets you from zero to a working AI agent in under 5 minutes.
## Step 1: Install
```bash
curl -fsSL https://pocketpaw.xyz/install.sh | sh
```
## Step 2: Set Your API Key
```bash
export POCKETCLAW_ANTHROPIC_API_KEY="sk-ant-your-key-here"
```
## Step 3: Launch
```bash
pocketpaw
```
This starts the **web dashboard** at `http://localhost:8000`. Open it in your browser.
## Step 4: Chat
Type a message in the chat input and press Enter. PocketPaw will process it through the Claude Agent SDK and stream the response back in real-time.
Try these example prompts:
- "What files are in my home directory?"
- "Write a Python script that calculates prime numbers"
- "Search the web for the latest news about AI"
## Running Headless Channels
You can also run PocketPaw as a headless bot on specific channels:
```bash
# Telegram only (legacy pairing flow)
pocketpaw --telegram
# Discord only
pocketpaw --discord
# Slack only
pocketpaw --slack
# Multiple channels
pocketpaw --discord --slack --whatsapp
# All configured channels
pocketpaw # Default web dashboard auto-starts configured adapters
```
## Configuring a Telegram Bot
<Steps>
<Step title="Create a bot with BotFather">
Open Telegram, search for `@BotFather`, send `/newbot`, and follow the prompts. Copy the token.
</Step>
<Step title="Set the token">
```bash
export POCKETCLAW_TELEGRAM_TOKEN="your-bot-token"
```
</Step>
<Step title="Start in Telegram mode">
```bash
pocketpaw --telegram
```
</Step>
<Step title="Chat with your bot">
Open Telegram, find your bot, and start chatting.
</Step>
</Steps>
## Configuring Discord
<Steps>
<Step title="Create a Discord application">
Go to the [Discord Developer Portal](https://discord.com/developers/applications), create a new application, and add a bot.
</Step>
<Step title="Set the token">
```bash
export POCKETCLAW_DISCORD_BOT_TOKEN="your-discord-token"
```
</Step>
<Step title="Invite the bot">
Generate an invite URL with the `bot` and `applications.commands` scopes. Add it to your server.
</Step>
<Step title="Start">
```bash
pocketpaw --discord
```
</Step>
</Steps>
## Using the Web Dashboard
The web dashboard is the default mode and provides:
- **Real-time chat** with streaming responses
- **Session management** with history and search
- **Tool activity panel** showing tool calls in real-time
- **Channel management** to configure and toggle channels
- **Settings panel** for all configuration options
- **MCP server management** to add and configure MCP servers
- **Memory settings** for configuring Mem0 and session storage
## What's Next?
<CardGroup>
<Card title="Configuration" icon="lucide:settings" href="/getting-started/configuration">
Explore all configuration options and environment variables.
</Card>
<Card title="Channels" icon="lucide:radio" href="/channels">
Set up additional messaging platforms.
</Card>
<Card title="Tools" icon="lucide:wrench" href="/tools">
Discover all 30+ built-in tools.
</Card>
<Card title="Security" icon="lucide:shield" href="/security">
Learn about PocketPaw's security model.
</Card>
</CardGroup>

View File

@@ -0,0 +1,60 @@
---
title: Google Calendar
description: "Manage Google Calendar events with PocketPaw: list upcoming events, create new ones with attendees and reminders, and search across all your calendars using natural language queries."
section: Integrations
ogType: article
keywords: ["google calendar", "calendar events", "scheduling", "calendar api", "event management"]
tags: ["integrations", "calendar", "google"]
---
# Google Calendar
PocketPaw can manage your Google Calendar with three tools: list, create, and search.
## Setup
1. Set up [Google OAuth](/integrations/oauth) credentials
2. Enable the Google Calendar API in your Google Cloud project
3. Authorize PocketPaw to access your calendar
## Tools
### calendar_list
List upcoming calendar events:
```
User: What's on my calendar for today?
Agent: [uses calendar_list] → You have 3 events today:
- 9:00 AM: Team standup (30 min)
- 11:00 AM: Design review (1 hr)
- 2:00 PM: Client call (45 min)
```
### calendar_create
Create a new calendar event:
```
User: Schedule a meeting with Sarah tomorrow at 3pm for 1 hour
Agent: [uses calendar_create] → Created event:
"Meeting with Sarah" — Tomorrow 3:00 PM - 4:00 PM
```
### calendar_search
Search for events by keyword or date range:
```
User: When is my next dentist appointment?
Agent: [uses calendar_search] → Found: "Dentist appointment" on Feb 20 at 10:00 AM
```
## Policy Group
All Calendar tools belong to `group:calendar`.
## Required Scopes
- `calendar.readonly` — For listing and searching
- `calendar.events` — For creating events

130
docs/integrations/gmail.mdx Normal file
View File

@@ -0,0 +1,130 @@
---
title: Gmail
description: "Full Gmail management with PocketPaw: 9 tools for searching, reading, sending emails, managing labels, trashing messages, and bulk operations. Requires Google OAuth with gmail.modify scope."
section: Integrations
ogType: article
keywords: ["gmail integration", "email management", "gmail api", "send email", "label management"]
tags: ["integrations", "gmail", "google"]
---
# Gmail
PocketPaw provides 9 tools for comprehensive Gmail management: search, read, send, label management, trash, and bulk operations.
## Setup
1. Set up [Google OAuth](/integrations/oauth) credentials
2. Enable the Gmail API in your Google Cloud project
3. Authorize PocketPaw to access your Gmail
## Tools
### gmail_search
Search your inbox using Gmail search syntax (`from:`, `subject:`, `is:unread`, `newer_than:1d`, etc.):
```
User: Find emails from John about the project deadline
Agent: [uses gmail_search] → Found 3 emails:
1. "Re: Project deadline" from john@example.com (Jan 15)
2. "Deadline update" from john@example.com (Jan 12)
3. "Project timeline" from john@example.com (Jan 8)
```
Supports a `max_results` parameter (default: 5, max: 20).
### gmail_read
Read the full content of a specific email by message ID:
```
User: Read the first email
Agent: [uses gmail_read] → Subject: "Re: Project deadline"
From: john@example.com
Date: Jan 15, 2024
Content: "Hi, the deadline has been moved to..."
```
### gmail_send
Send an email (plain text):
```
User: Reply to John saying we'll meet the deadline
Agent: [uses gmail_send] → Email sent to john@example.com
```
### gmail_list_labels
List all Gmail labels with their IDs and types:
```
User: Show me my Gmail labels
Agent: [uses gmail_list_labels] →
- INBOX (system)
- SENT (system)
- Work/Projects (user) — Label_42
- Newsletters (user) — Label_15
```
### gmail_create_label
Create a new Gmail label. Use `/` for nested labels:
```
User: Create a label called "Work/Urgent"
Agent: [uses gmail_create_label] → Created label "Work/Urgent" (Label_53)
```
### gmail_modify
Add or remove labels on a single email. Common label IDs: `INBOX`, `SPAM`, `TRASH`, `UNREAD`, `STARRED`, `IMPORTANT`.
```
User: Star that email and mark it as important
Agent: [uses gmail_modify] → Added STARRED, IMPORTANT to message
```
### gmail_trash
Move a message to trash:
```
User: Trash the spam email
Agent: [uses gmail_trash] → Message moved to trash
```
### gmail_batch_modify
Bulk label operations on multiple messages at once:
```
User: Mark all 5 newsletters as read and archive them
Agent: [uses gmail_batch_modify] → Modified 5 messages: removed UNREAD, INBOX
```
## Configuration
| Setting | Env Variable | Description |
|---------|-------------|-------------|
| Client ID | `POCKETCLAW_GOOGLE_CLIENT_ID` | Google OAuth client ID |
| Client secret | `POCKETCLAW_GOOGLE_CLIENT_SECRET` | Google OAuth client secret |
## Policy Group
All Gmail tools belong to `group:gmail`.
```bash
# Enable Gmail tools
export POCKETCLAW_TOOLS_ALLOW="group:gmail"
# Or disable
export POCKETCLAW_TOOLS_DENY="group:gmail"
```
## Required Scopes
PocketPaw requests these Gmail scopes:
- `gmail.readonly` — For search, read, and label listing
- `gmail.send` — For sending emails
- `gmail.modify` — For label management, trash, and bulk operations

View File

@@ -0,0 +1,56 @@
---
title: Google Docs
description: "Read, create, and search Google Docs with PocketPaw. Extract document content as plain text, create new documents with formatted content, and search across your Docs library by title or content."
section: Integrations
ogType: article
keywords: ["google docs", "document management", "docs api", "document creation", "text extraction"]
tags: ["integrations", "docs", "google"]
---
# Google Docs
PocketPaw can interact with Google Docs for reading, creating, and searching documents.
## Setup
1. Set up [Google OAuth](/integrations/oauth) credentials
2. Enable the Google Docs API in your Google Cloud project
3. Authorize PocketPaw to access your Docs
## Tools
### gdocs_read
Read the content of a Google Doc:
```
User: Read the meeting notes from last week
Agent: [uses gdocs_read] → Meeting Notes - Jan 15:
- Discussed project timeline
- Assigned tasks to team members
- Next meeting scheduled for Jan 22
```
### gdocs_create
Create a new Google Doc:
```
User: Create a new document called "Sprint Planning" with today's agenda
Agent: [uses gdocs_create] → Created "Sprint Planning" document
```
### gdocs_search
Search for documents by title or content:
```
User: Find all docs about the budget
Agent: [uses gdocs_search] → Found 2 documents:
1. "Q1 Budget Review" (last modified Jan 10)
2. "Budget Proposal 2024" (last modified Dec 15)
```
## Policy Group
All Docs tools belong to `group:docs`.

View File

@@ -0,0 +1,70 @@
---
title: Google Drive
description: "Access Google Drive from PocketPaw with 4 tools: list files and folders, download documents, upload new files, and share with collaborators. Supports all file types and MIME type filtering."
section: Integrations
ogType: article
keywords: ["google drive", "file management", "cloud storage", "drive api", "file sharing"]
tags: ["integrations", "drive", "google"]
---
# Google Drive
PocketPaw can manage your Google Drive files with four tools: list, download, upload, and share.
## Setup
1. Set up [Google OAuth](/integrations/oauth) credentials
2. Enable the Google Drive API in your Google Cloud project
3. Authorize PocketPaw to access your Drive
## Tools
### gdrive_list
List files in your Drive or a specific folder:
```
User: What files are in my Drive's project folder?
Agent: [uses gdrive_list] → Found 5 files:
1. Project Plan.docx (Google Doc)
2. Budget.xlsx (Google Sheet)
3. Logo.png (Image)
4. Meeting Notes/ (Folder)
5. Presentation.pptx (Google Slides)
```
### gdrive_download
Download a file from Drive to local filesystem:
```
User: Download the Budget.xlsx file
Agent: [uses gdrive_download] → Downloaded to ~/Downloads/Budget.xlsx
```
### gdrive_upload
Upload a local file to Drive:
```
User: Upload report.pdf to the project folder
Agent: [uses gdrive_upload] → Uploaded report.pdf to "Project" folder
```
### gdrive_share
Share a file with someone:
```
User: Share the project plan with sarah@example.com
Agent: [uses gdrive_share] → Shared "Project Plan" with sarah@example.com (editor)
```
## Policy Group
All Drive tools belong to `group:drive`.
## Required Scopes
- `drive.readonly` — For listing and downloading
- `drive.file` — For uploading and sharing

View File

@@ -0,0 +1,82 @@
---
title: Integrations Overview
description: "PocketPaw integrates with Google Workspace (Gmail, Calendar, Drive, Docs), Spotify, Reddit, and any MCP server. All integrations use OAuth 2.0 for secure authentication."
section: Integrations
ogType: article
keywords: ["integrations", "google workspace", "spotify", "reddit", "mcp", "oauth"]
tags: ["integrations", "overview"]
---
# Integrations
PocketPaw integrates with popular services to extend its capabilities beyond chat.
## Available Integrations
<CardGroup>
<Card title="OAuth Framework" icon="lucide:key" href="/integrations/oauth">
Built-in OAuth 2.0 framework for secure authentication with Google and Spotify.
</Card>
<Card title="Gmail" icon="lucide:mail" href="/integrations/gmail">
Search, read, and send emails through your Gmail account.
</Card>
<Card title="Google Calendar" icon="lucide:calendar" href="/integrations/calendar">
List, create, and search calendar events.
</Card>
<Card title="Google Drive" icon="lucide:hard-drive" href="/integrations/google-drive">
List, download, upload, and share files in Google Drive.
</Card>
<Card title="Google Docs" icon="lucide:file-text" href="/integrations/google-docs">
Read, create, and search Google Docs.
</Card>
<Card title="Spotify" icon="lucide:music" href="/integrations/spotify">
Search music, control playback, and manage playlists.
</Card>
<Card title="Reddit" icon="lucide:message-circle" href="/integrations/reddit">
Search posts, read threads, and browse trending content. No auth needed.
</Card>
<Card title="MCP Servers" icon="lucide:server" href="/integrations/mcp-servers">
Connect Model Context Protocol servers to extend capabilities infinitely.
</Card>
</CardGroup>
## Google Integrations Setup
All Google integrations (Gmail, Calendar, Drive, Docs) share the same OAuth framework:
<Steps>
<Step title="Create Google Cloud project">
Go to [console.cloud.google.com](https://console.cloud.google.com) and create a project.
</Step>
<Step title="Enable APIs">
Enable the Gmail API, Calendar API, Drive API, and Docs API.
</Step>
<Step title="Create OAuth credentials">
Create OAuth 2.0 client credentials (Desktop app type).
</Step>
<Step title="Configure PocketPaw">
```bash
export POCKETCLAW_GOOGLE_CLIENT_ID="your-client-id"
export POCKETCLAW_GOOGLE_CLIENT_SECRET="your-secret"
```
</Step>
<Step title="Authorize">
The first time you use a Google tool, PocketPaw will open a browser window for authorization.
</Step>
</Steps>
## Integration Architecture
```
┌──────────────────┐
│ OAuth Framework │ ← Token management, refresh, multi-provider
├──────────────────┤
│ Token Store │ ← ~/.pocketclaw/tokens/
├──────────────────┤
│ API Clients │ ← gmail.py, gcalendar.py, gdrive.py, etc.
├──────────────────┤
│ Tool Layer │ ← tools/builtin/gmail.py, calendar.py, etc.
├──────────────────┤
│ Tool Registry │ ← Registered with policy system
└──────────────────┘
```

View File

@@ -0,0 +1,127 @@
---
title: MCP Servers
description: "Extend PocketPaw with Model Context Protocol (MCP) servers for unlimited tool expansion. Add servers via stdio or HTTP transport, manage from the dashboard, and use preset templates for quick setup."
section: Integrations
ogType: article
keywords: ["mcp servers", "model context protocol", "tool extension", "stdio transport", "mcp presets"]
tags: ["integrations", "mcp"]
---
# MCP Servers
PocketPaw has first-class support for the [Model Context Protocol (MCP)](https://modelcontextprotocol.io). Connect any MCP server to extend your agent's capabilities.
## What is MCP?
MCP is an open protocol that allows AI agents to connect to external tools and data sources. MCP servers provide tools that the agent can call, similar to built-in tools but running as separate processes.
## Configuration
MCP servers are configured in `~/.pocketclaw/mcp.json`:
```json
{
"servers": {
"filesystem": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/home/user"],
"transport": "stdio"
},
"github": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-github"],
"env": {
"GITHUB_TOKEN": "ghp_..."
},
"transport": "stdio"
},
"remote-api": {
"url": "http://localhost:3000/mcp",
"transport": "http"
}
}
}
```
## Transport Types
### stdio
The most common transport. PocketPaw spawns the MCP server as a subprocess and communicates via stdin/stdout:
```json
{
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path"],
"transport": "stdio"
}
```
### HTTP
For remote MCP servers accessible via HTTP:
```json
{
"url": "http://localhost:3000/mcp",
"transport": "http"
}
```
## Backend Integration
### Claude Agent SDK
The Claude Agent SDK has native MCP support. PocketPaw translates `mcp.json` configurations into the SDK's expected format and passes them during initialization.
### PocketPaw Native
The native backend loads MCP tools via `_get_mcp_tools()` and registers them with the tool registry using the naming convention `mcp_<server>__<tool>`.
## Dashboard Management
The web dashboard provides a visual interface for managing MCP servers:
1. Open the MCP modal from the sidebar
2. Add new servers with command, args, and environment variables
3. Toggle individual servers on/off
4. View discovered tools from each server
### REST API
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/mcp/servers` | GET | List configured servers |
| `/api/mcp/servers` | POST | Add a new server |
| `/api/mcp/servers/{name}` | PUT | Update a server |
| `/api/mcp/servers/{name}` | DELETE | Remove a server |
| `/api/mcp/servers/{name}/toggle` | POST | Enable/disable a server |
## Tool Policy
MCP tools are subject to the tool policy system:
```bash
# Allow all MCP tools
export POCKETCLAW_TOOLS_ALLOW="group:mcp"
# Allow specific server's tools
export POCKETCLAW_TOOLS_ALLOW="mcp:filesystem:*"
# Deny a specific tool
export POCKETCLAW_TOOLS_DENY="mcp:github:delete_repo"
```
## Popular MCP Servers
| Server | Package | Description |
|--------|---------|-------------|
| Filesystem | `@modelcontextprotocol/server-filesystem` | File read/write/search |
| GitHub | `@modelcontextprotocol/server-github` | Issues, PRs, repos |
| PostgreSQL | `@modelcontextprotocol/server-postgres` | Database queries |
| Brave Search | `@modelcontextprotocol/server-brave-search` | Web search |
| Puppeteer | `@modelcontextprotocol/server-puppeteer` | Browser automation |
<Callout type="info">
MCP is an open ecosystem. Browse available servers at [modelcontextprotocol.io/servers](https://modelcontextprotocol.io).
</Callout>

Some files were not shown because too many files have changed in this diff Show More