You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CLAUDE.md
+29-4Lines changed: 29 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,6 +1,6 @@
1
1
# Phantom
2
2
3
-
Phantom is an autonomous AI co-worker that runs as a persistent Bun process on a VM. It wraps the Claude Agent SDK as a subprocess (Anthropic by default, swappable via a `provider:` config block to Z.AI/GLM-5.1, OpenRouter, Ollama, vLLM, LiteLLM, or any Anthropic Messages API compatible endpoint). It maintains vector-backed memory across sessions, rewrites its own configuration through a validated self-evolution engine, communicates via Slack/Telegram/Email/Webhook, and exposes all capabilities as an MCP server. 27,000+ lines of TypeScript, 875 tests, v0.18.2. Apache 2.0, repo at ghostwright/phantom.
3
+
Phantom is an autonomous AI co-worker that runs as a persistent Bun process on a VM. It wraps the Claude Agent SDK as a subprocess (Anthropic by default, swappable via a `provider:` config block to Z.AI/GLM-5.1, OpenRouter, Ollama, vLLM, LiteLLM, or any Anthropic Messages API compatible endpoint). It maintains vector-backed memory across sessions, rewrites its own configuration through a validated self-evolution engine, communicates via Slack/Web Chat/Telegram/Email/Webhook, and exposes all capabilities as an MCP server. 30,000+ lines of TypeScript, 1,584 tests, v0.19.0. Apache 2.0, repo at ghostwright/phantom.
4
4
5
5
## Tech Stack
6
6
@@ -10,7 +10,8 @@ Phantom is an autonomous AI co-worker that runs as a persistent Bun process on a
10
10
| Agent | Claude Agent SDK (`@anthropic-ai/claude-agent-sdk`) subprocess. Provider is configurable via `src/config/providers.ts`: Anthropic (default), Z.AI, OpenRouter, Ollama, vLLM, LiteLLM, custom. |
Message flow: Slack message -> SlackChannel adapter -> ChannelRouter -> SessionManager (find/create session) -> PromptAssembler (base + role + evolved config + memory context) -> AgentRuntime.query() (Opus 4.6 with full tools) -> response -> ChannelRouter -> Slack thread reply. Web chat uses the same flow: POST /chat/sessions/:id/message -> SSE stream of wire frames -> React client renders in real time. Two separate transcripts (wire-format message store for the client, SDK conversation for the agent) are kept in sync.
128
152
129
153
After each session: EvolutionEngine runs 6-step reflection pipeline -> 5-gate validation -> approved changes applied to phantom-config/ -> version bumped.
130
154
@@ -193,6 +217,7 @@ Production deployments are managed internally. Do NOT modify production deployme
@@ -27,7 +27,7 @@ AI agents today are disposable. You open a chat, get an answer, close the tab, a
27
27
28
28
Phantom takes a different approach: **give the AI its own computer.** A dedicated machine where it installs software, spins up databases, builds dashboards, remembers what you told it last week, and gets measurably better at your job every day. Your laptop stays yours. The agent's workspace is its own.
29
29
30
-
This is not a chatbot. It is a co-worker that runs on Slack, has its own email address, creates its own tools, and builds infrastructure without asking for permission. Don't take our word for it - scroll down to see what production Phantoms have actually built.
30
+
This is not a chatbot. It is a co-worker that runs on Slack, has a web chat interface at `/chat`, has its own email address, creates its own tools, and builds infrastructure without asking for permission. Don't take our word for it - scroll down to see what production Phantoms have actually built.
31
31
32
32
## What This Actually Looks Like
33
33
@@ -220,6 +220,7 @@ Because the agent that can only use pre-built tools hits a ceiling. Phantom buil
220
220
| **Dynamic tools** | Creates and registers its own MCP tools at runtime. Tools survive restarts and work across sessions. |
221
221
| **Encrypted secrets** | AES-256-GCM encrypted forms with magic-link auth. No plain-text credentials in config files. |
222
222
| **Email identity** | Every Phantom has its own email address. Send reports to people outside your Slack workspace. |
223
+
| **Web chat** | A full browser-based chat client at `/chat` with SSE streaming, file attachments, and Web Push notifications. No Slack required. |
223
224
| **Shareable pages** | Generates dashboards and tools on a public URL with auth. Share a link, anyone can see it. |
224
225
| **MCP server** | Claude Code connects to your Phantom. Other Phantoms connect to your Phantom. It is an API, not a dead end. |
225
226
@@ -238,10 +239,10 @@ Because the agent that can only use pre-built tools hits a ceiling. Phantom buil
Copy file name to clipboardExpand all lines: docs/architecture.md
+18-4Lines changed: 18 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -58,16 +58,26 @@ Phantom is a single Bun process that runs on a VM. It combines an agent runtime,
58
58
59
59
### HTTP Server
60
60
61
-
`src/core/server.ts` - Bun.serve() on port 3100. Three routes:
61
+
`src/core/server.ts` - Bun.serve() on port 3100. Key routes:
62
62
-`/health` - JSON health status (status, uptime, version, channels, memory, evolution)
63
63
-`/mcp` - MCP Streamable HTTP endpoint
64
64
-`/webhook` - Inbound webhook receiver
65
+
-`/chat/*` - Web chat API (SSE streaming, sessions, attachments, push subscriptions)
66
+
-`/ui/*` - Static pages and login (magic link auth)
65
67
66
68
### Channel Router
67
69
68
70
`src/channels/router.ts` - Multiplexes messages from all connected channels. Each channel implements the `Channel` interface: `connect()`, `disconnect()`, `send()`, `onMessage()`.
Channels: Slack (Socket Mode), Web Chat (SSE streaming at `/chat`), Telegram (long polling), Email (IMAP/SMTP), Webhook (HTTP), CLI (readline).
73
+
74
+
### Web Chat Channel
75
+
76
+
`src/chat/` - A full browser-based chat channel with a React 19 SPA at `/chat`. The backend uses Server-Sent Events (SSE) to stream a 32-event wire format from the Agent SDK to the client in real time. Two independent transcripts are maintained: the wire-format message store (what the client sees) and the SDK conversation (what the agent sees). This two-transcript invariant means the client can render markdown, tool calls, thinking blocks, and subagent progress without coupling to SDK internals.
77
+
78
+
Auth uses cookie-based sessions with magic link login. On first run without Slack, a login email is sent via Resend (or a bootstrap token is printed to stdout). Web Push notifications (VAPID) alert users when the agent responds while the tab is in the background.
79
+
80
+
File attachments (images, PDFs, text files) are uploaded via multipart POST and passed to the agent as context. Type allowlist and size limits are enforced server-side.
71
81
72
82
### Agent Runtime
73
83
@@ -114,7 +124,7 @@ Embeddings via Ollama (nomic-embed-text, 768d vectors). Hybrid search using dens
114
124
115
125
## Data Flow
116
126
117
-
1. Message arrives via channel (Slack mention, webhook POST, etc.)
127
+
1. Message arrives via channel (Slack mention, webhook POST, web chat, etc.)
118
128
2. Channel router normalizes to `InboundMessage`
119
129
3. Session manager finds or creates a session
120
130
4. Prompt assembler builds the full system prompt
@@ -123,6 +133,8 @@ Embeddings via Ollama (nomic-embed-text, 768d vectors). Hybrid search using dens
123
133
7. Memory consolidation runs (non-blocking)
124
134
8. Evolution pipeline runs (non-blocking)
125
135
136
+
For web chat specifically: the client sends `POST /chat/sessions/:id/message`, the server starts an Agent SDK `query()`, and SDK events are translated to wire frames and pushed to all connected SSE streams for that session (supporting multi-tab). The wire format includes session lifecycle, text streaming, thinking blocks, tool calls with input streaming, and subagent progress.
137
+
126
138
## Technology Stack
127
139
128
140
| Component | Technology |
@@ -132,7 +144,8 @@ Embeddings via Ollama (nomic-embed-text, 768d vectors). Hybrid search using dens
Copy file name to clipboardExpand all lines: docs/channels.md
+45-1Lines changed: 45 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,9 +2,53 @@
2
2
3
3
Phantom communicates through pluggable channel adapters. Each channel implements a standard interface, and the agent does not care where messages originate.
4
4
5
+
## Web Chat
6
+
7
+
A browser-based chat interface at `/chat`. No Slack required. This is the simplest way to talk to a Phantom - open the URL in a browser and start typing.
8
+
9
+
### Access
10
+
11
+
Navigate to `https://your-phantom-host/chat`. On first visit, you will be prompted to log in.
12
+
13
+
### Authentication
14
+
15
+
Cookie-based sessions with magic link login:
16
+
17
+
1. Enter your email address on the login page
18
+
2. Phantom sends a magic link via Resend (requires `RESEND_API_KEY` in `.env`)
19
+
3. Click the link to authenticate. The session cookie lasts 30 days.
20
+
21
+
On first run without Slack configured, Phantom sends a login email to `OWNER_EMAIL` automatically. If Resend is not configured, a bootstrap token is printed to stdout instead.
22
+
23
+
### Configuration
24
+
25
+
Set these in `.env`:
26
+
27
+
```
28
+
OWNER_EMAIL=you@example.com # Required for email-based login
29
+
RESEND_API_KEY=re_... # Required for magic link emails
30
+
```
31
+
32
+
No channel YAML configuration is needed. The chat channel is always available when the HTTP server is running.
33
+
34
+
### Features
35
+
36
+
-**SSE streaming** - responses stream token-by-token via Server-Sent Events
-**Multi-tab support** - open the same session in multiple tabs, all stay in sync
39
+
-**File attachments** - upload images (JPEG, PNG, GIF, WebP up to 10 MB), PDFs (up to 32 MB), and text/code files (up to 1 MB). Up to 10 files per message.
40
+
-**Web Push notifications** - get notified when the agent responds while the tab is in the background. Uses VAPID keys stored in SQLite.
41
+
-**Session management** - create, rename, archive, and delete sessions from the sidebar
42
+
-**Markdown rendering** - full markdown with code syntax highlighting, tables, and lists
43
+
-**Auto-rename** - sessions are automatically titled based on the first exchange
44
+
45
+
### Tech Stack
46
+
47
+
The chat client is a React 19 SPA built with Vite, shadcn/ui, and Tailwind v4. The production build lives at `public/chat/` and is served as static files. The Dockerfile includes a dedicated build stage for the chat client.
48
+
5
49
## Slack
6
50
7
-
The primary channel. Uses Socket Mode (no public URL required).
0 commit comments