Extended Mind
README.md
# ✦ Extended Mind
<p align="center">
<img src="assets/banner.webp" alt="Extended Mind">
</p>
<p align="center">
<a href="LICENSE"><img src="https://img.shields.io/github/license/SnowLightPath/extended-mind" alt="License"></a>
<a href="https://github.com/SnowLightPath/extended-mind"><img src="https://img.shields.io/badge/platform-Cloudflare%20Workers-F38020?logo=cloudflare&logoColor=white" alt="Cloudflare Workers"></a>
<a href="https://modelcontextprotocol.io"><img src="https://img.shields.io/badge/protocol-MCP-5A67D8" alt="MCP"></a>
</p>
**Your context, shared across every AI platform.**
Extended Mind is a Personal Context Protocol — a single MCP server that gives Claude, ChatGPT, Codex, and any MCP-compatible AI access to the same personal context.
Two tools. That's it.
```
context_get() → returns who you are, what you're working on, what happened recently
context_log(m) → stores a message verbatim — the next AI on a different platform reads it
```
## 💡 Why
You switch between Claude Chat, Claude Code, ChatGPT, Codex. Each session starts from zero. Extended Mind fixes this: one server, one context, every platform.
```
☀️ Morning — Claude Code: "Refactored the executor to use async"
└→ context_log(summary)
🌤️ Afternoon — ChatGPT: context_get()
└→ "This morning you refactored the executor..."
🌙 Evening — Claude Chat: context_get()
└→ knows everything from today
```
## 🏗️ Architecture
```
+---------------+ +---------------+ +---------------+
| Claude Chat | | ChatGPT | | Codex |
| Claude Code | | (OAuth MCP) | | |
+-------+-------+ +-------+-------+ +-------+-------+
| | |
+-------------------+------------------+
|
POST /mcp (Streamable HTTP)
|
+---------+---------+
| Cloudflare |
| Worker |
| |
| context_get ---->| cached response (~30ms)
| context_log ---->| async write (~30ms response)
| | +-> LLM classify (async)
| | +-> GitHub backup (async)
+-------------------+
```
- **⚡ KV** — hot storage for all reads/writes
- **📦 GitHub** — async version history backup (your private data repo)
- **🔍 LLM API** — classifies logged messages, extracts priorities, detects contradictions (configurable: OpenAI / Anthropic)
- **🔑 WebAuthn** — passkey authentication (Touch ID / Face ID) on OAuth authorize
- **🔗 OAuth 2.0** — authorization code flow for ChatGPT / Claude Chat, with `/oauth/revoke` (RFC 7009)
## 🚀 Quick Start
### 1. Deploy
```bash
git clone https://github.com/SnowLightPath/extended-mind.git
cd extended-mind
npm install
# Create KV namespace
npx wrangler kv namespace create PCP
# → Copy the ID into wrangler.toml
# Set secrets
npx wrangler secret put PCP_TOKEN # your bearer token (generate any 64-char hex)
npx wrangler secret put GITHUB_TOKEN # GitHub PAT with repo scope
npx wrangler secret put OPENAI_API_KEY # or ANTHROPIC_API_KEY depending on CLASSIFY_PROVIDER
npx wrangler secret put WEBHOOK_SECRET # GitHub webhook HMAC-SHA256 secret
# Configure wrangler.toml
# - Set KV namespace ID
# - Set GITHUB_REPO to your private data repo (e.g., "yourname/my-mind")
# - Set CLASSIFY_PROVIDER to "openai" or "anthropic" (default: openai)
# - Optionally set CLASSIFY_MODEL to override (openai: gpt-5.4-mini, anthropic: claude-sonnet-4-6)
# - Optionally set CLASSIFY_REASONING_EFFORT for OpenAI reasoning models (none/low/medium/high/xhigh)
# - Optionally set CLASSIFY_MAX_TOKENS (default: 4096)
npx wrangler deploy
```
### 2. Create your data repo
Create a **private** GitHub repository for your personal context data (e.g., `yourname/my-mind`). This is where the Worker backs up `core.yaml`, `active.json`, and session logs.
Add a webhook in the data repo (Settings → Webhooks):
| Field | Value |
|-------|-------|
| Payload URL | `https://your-worker.workers.dev/webhook` |
| Content type | `application/json` |
| Secret | Same value as `WEBHOOK_SECRET` (required — webhook is rejected without it) |
| Events | Just the push event |
This enables automatic core sync: when you push changes to `seed/core.yaml`, the webhook notifies the Worker, which updates KV. A cron trigger also runs as a fallback every 5 minutes.
### 3. Seed your context
Edit `seed/core.yaml` with your identity. Copy `seed/active.template.json` to `seed/active.json` and edit with your work context. Place these in your private data repo (not this repo), then:
```bash
node seed/seed-kv.js
```
This writes 2 initial KV keys (`core`, `active`). Additional keys (`sessions`, `pending_classify`, OAuth tokens, auth sessions, WebAuthn credentials) are created at runtime. **Initial setup only** — re-running resets everything and wipes the active context that AI clients have built up.
### 4. Update core
Core is the human-owned layer — identity, ontology, interaction rules. AI clients cannot write to it.
```bash
# Edit seed/core.yaml, then:
git add seed/core.yaml
git commit -m "your change description"
git push
```
The webhook fires → Worker fetches → KV updated. No wrangler commands needed.
### 5. Connect your AI clients
**🟠 Claude Code** — add to `~/.claude/settings.json`:
```json
{
"mcpServers": {
"extended-mind": {
"url": "https://your-worker.workers.dev/mcp",
"headers": {
"Authorization": "Bearer YOUR_PCP_TOKEN"
}
}
}
}
```
Global setting — all projects get access. Add `"mcp__extended-mind"` to `permissions.allow` to auto-approve.
**🟠 Claude Chat** — Settings → Connectors → Add custom connector:
| Field | Value |
|-------|-------|
| Remote MCP Server URL | `https://your-worker.workers.dev/mcp` |
| OAuth Client ID | Your registered client ID |
| OAuth Client Secret | Your registered client secret |
**⚪ ChatGPT** — Settings → Apps → Create app (native MCP, not Custom GPT):
| Field | Value |
|-------|-------|
| MCP Server URL | `https://your-worker.workers.dev/mcp` |
| Authentication | OAuth |
| Auth URL | `https://your-worker.workers.dev/oauth/authorize` |
| Token URL | `https://your-worker.workers.dev/oauth/token` |
**⚪ Codex** — two steps:
1. Settings → MCP servers → Connect a custom MCP:
| Field | Value |
|-------|-------|
| URL | `https://your-worker.workers.dev/mcp` |
| Bearer token env var | `MCP_BEARER_TOKEN` |
2. Add to `~/.zshrc` or `~/.bashrc`:
```bash
export MCP_BEARER_TOKEN="YOUR_PCP_TOKEN"
```
Codex reads the env var from the shell, not from the MCP settings UI. Restart shell and start a new thread.
### 6. Verify
```bash
# Get context
curl -s -X POST https://your-worker.workers.dev/mcp \
-H "Authorization: Bearer $PCP_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"context_get","arguments":{}}}' \
| jq -r '.result.content[0].text'
# Log a message
curl -s -X POST https://your-worker.workers.dev/mcp \
-H "Authorization: Bearer $PCP_TOKEN" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"context_log","arguments":{"message":"Testing Extended Mind setup"}}}'
```
## 📐 How It Works
**Your context has two layers:**
| Layer | What | Who edits | How |
|-------|------|-----------|-----|
| **🔒 Core** | Identity, ontology, interaction rules | You only | Edit `seed/core.yaml` → git push → webhook → KV |
| **📝 Active** | Team, projects, priorities, recent sessions | AI clients | `context_log()` → KV + GitHub + classification |
When an AI calls `context_log`:
1. Message stored **verbatim** in KV (async via `waitUntil`, ~30ms response)
2. LLM API classifies in the background — updates priorities, flags contradictions
3. GitHub gets an async backup commit
When an AI calls `context_get`:
- Returns everything as a single YAML document (~2500-3000 tokens)
- The AI now knows who you are, what you're working on, and what happened across all platforms
## 🔐 Security
- **WebAuthn Passkeys** — Touch ID / Face ID / security key authentication on the OAuth authorize page. Register at `/passkey`, then use Conditional UI (browser auto-suggests passkey on the token input field)
- **XSS Protection** — all dynamic values in OAuth HTML are entity-encoded
- **CSRF Protection** — one-time tokens on the authorize form
- **Token TTL** — OAuth tokens expire after 90 days (re-auth required)
- **Token Revocation** — `POST /oauth/revoke` (RFC 7009) to invalidate compromised tokens
- **Webhook Signature** — HMAC-SHA256 verification required (`WEBHOOK_SECRET`)
- **Constant-time Comparison** — client secret verification resistant to timing attacks
## 🔄 Development: Design-Doc Loop
This project uses **[Design-Doc Loop (DDL)](https://github.com/SnowLightPath/DDL)** — a human-LLM collaborative development methodology where a living design document (`design.md`) serves as shared cognition between sessions.
The name "Extended Mind" comes from the [Extended Mind thesis](https://doi.org/10.1093/analys/58.1.7) (Clark & Chalmers, 1998), which argues that cognitive processes extend beyond the brain into the environment. In DDL, `design.md` functions as Otto's notebook — an external artifact that is constitutive of the design process, not merely a record of it.
**The loop:** Draft (experience first) → Realize (design → code) → Reflect (code → design)
| Command | What it does |
|---------|-------------|
| `/draft` | Design the experience before writing code |
| `/realize` | Implement what `design.md` describes |
| `/reflect` | Detect drift between code and design, reconcile |
| `/refactoring` | Audit code quality against detection targets |
| `/docs` | Audit and fix documentation |
| `/commit` | Verify, commit, push, deploy |
Each command runs through phases with `+++DETECT` targets that catch violations automatically and `+++STOP` gates that require human approval before proceeding.
> `design.md` is gitignored — it's working notes, not a deliverable. Code is the source of truth.
### References
- Clark, A. & Chalmers, D. (1998). "The Extended Mind." *Analysis*, 58(1), 7–19. [doi:10.1093/analys/58.1.7](https://doi.org/10.1093/analys/58.1.7)
- [Design-Doc Loop (DDL)](https://github.com/SnowLightPath/DDL) — Human-LLM collaborative development methodology
## 🔀 Data Separation
Extended Mind uses two repositories:
| Repo | Visibility | Purpose |
|------|-----------|---------|
| `extended-mind` | Public | Source code (this repo) |
| Your data repo | **Private** | Context data synced by the Worker (`core.yaml`, `active.json`, sessions) |
Your personal context never touches the code repository.
## ⚖️ License
[MIT](LICENSE)
This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues