the-campfire 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +2388 -0
- package/dist/assets/{MermaidDiagram-D_MwUXi3.js → MermaidDiagram-Cas1Ngze.js} +2 -2
- package/dist/assets/{_basePickBy-DsMRBmhy.js → _basePickBy-D1h3RRT9.js} +1 -1
- package/dist/assets/{_baseUniq-CZ0BR5Mx.js → _baseUniq-Z9p6uaM9.js} +1 -1
- package/dist/assets/{arc-D6Y0ooDg.js → arc-DJLNkmre.js} +1 -1
- package/dist/assets/{architectureDiagram-VXUJARFQ-3T5ZoEn1.js → architectureDiagram-VXUJARFQ-CBHHYg8R.js} +1 -1
- package/dist/assets/{blockDiagram-VD42YOAC-CvOCnB8f.js → blockDiagram-VD42YOAC-DMtvAHPO.js} +1 -1
- package/dist/assets/{c4Diagram-YG6GDRKO-DPXJvInm.js → c4Diagram-YG6GDRKO-G9Zj2LWB.js} +1 -1
- package/dist/assets/channel-CcCVj0rn.js +1 -0
- package/dist/assets/{chunk-4BX2VUAB-DPHGuPB4.js → chunk-4BX2VUAB-s3svQOtk.js} +1 -1
- package/dist/assets/{chunk-55IACEB6-BbI83gIK.js → chunk-55IACEB6-C6fhtS_L.js} +1 -1
- package/dist/assets/{chunk-B4BG7PRW-DGvVY1Y_.js → chunk-B4BG7PRW-CpePj3eQ.js} +1 -1
- package/dist/assets/{chunk-DI55MBZ5-2YN0FhPB.js → chunk-DI55MBZ5-Dq9AChBD.js} +1 -1
- package/dist/assets/{chunk-FMBD7UC4-Ctqs0bWj.js → chunk-FMBD7UC4-DSOMddvX.js} +1 -1
- package/dist/assets/{chunk-QN33PNHL-CfvfTLi4.js → chunk-QN33PNHL-ZrdWE4nY.js} +1 -1
- package/dist/assets/{chunk-QZHKN3VN-C-dG1NiD.js → chunk-QZHKN3VN-BqLE4kwR.js} +1 -1
- package/dist/assets/{chunk-TZMSLE5B-Bh07YiOi.js → chunk-TZMSLE5B-DY7GliuX.js} +1 -1
- package/dist/assets/classDiagram-2ON5EDUG-8I6xWkSV.js +1 -0
- package/dist/assets/classDiagram-v2-WZHVMYZB-8I6xWkSV.js +1 -0
- package/dist/assets/clone-zAvPgvOP.js +1 -0
- package/dist/assets/{cose-bilkent-S5V4N54A-CTC2n8Hd.js → cose-bilkent-S5V4N54A-DmRYvz2l.js} +1 -1
- package/dist/assets/{dagre-6UL2VRFP-CAgGZKYt.js → dagre-6UL2VRFP-D4IfaYgb.js} +1 -1
- package/dist/assets/{diagram-PSM6KHXK-DymwxXvC.js → diagram-PSM6KHXK-ClfgeCpw.js} +1 -1
- package/dist/assets/{diagram-QEK2KX5R-CAEL5_ej.js → diagram-QEK2KX5R-BaBfarh-.js} +1 -1
- package/dist/assets/{diagram-S2PKOQOG-B6onWI1I.js → diagram-S2PKOQOG-DT1eYmOM.js} +1 -1
- package/dist/assets/{erDiagram-Q2GNP2WA-DP-dbxgu.js → erDiagram-Q2GNP2WA-C5ZVoHhn.js} +1 -1
- package/dist/assets/{flowDiagram-NV44I4VS-OMmA9Rvb.js → flowDiagram-NV44I4VS-C9MYAakn.js} +1 -1
- package/dist/assets/{ganttDiagram-JELNMOA3-B2oAHD8b.js → ganttDiagram-JELNMOA3-HHt6rJj9.js} +1 -1
- package/dist/assets/{gitGraphDiagram-V2S2FVAM-CAZO9ISt.js → gitGraphDiagram-V2S2FVAM-CfA3qwoT.js} +1 -1
- package/dist/assets/{graph-CeeDmBlM.js → graph-BLJloKEi.js} +1 -1
- package/dist/assets/index-CvOAfVHK.css +32 -0
- package/dist/assets/{index-CAGJQXdJ.js → index-CxNtY8EJ.js} +82 -82
- package/dist/assets/{infoDiagram-HS3SLOUP-m0CP23H-.js → infoDiagram-HS3SLOUP-ASXl-hwl.js} +1 -1
- package/dist/assets/{journeyDiagram-XKPGCS4Q-C9WvzT-H.js → journeyDiagram-XKPGCS4Q-B-wDjjzW.js} +1 -1
- package/dist/assets/{kanban-definition-3W4ZIXB7-KIEeugzr.js → kanban-definition-3W4ZIXB7-BNWLVKm2.js} +1 -1
- package/dist/assets/{layout-P-20nhx7.js → layout-cpBTqNBI.js} +1 -1
- package/dist/assets/{linear-CMM5aRIM.js → linear-DAonGknK.js} +1 -1
- package/dist/assets/{mermaid.core-Z9YQUdi5.js → mermaid.core-BdetWGOO.js} +4 -4
- package/dist/assets/{mindmap-definition-VGOIOE7T-B-NyLDuB.js → mindmap-definition-VGOIOE7T-CJOEqJKm.js} +1 -1
- package/dist/assets/{pieDiagram-ADFJNKIX-Dp8zgF7X.js → pieDiagram-ADFJNKIX-Dnc1ekZC.js} +1 -1
- package/dist/assets/{quadrantDiagram-AYHSOK5B-Cs07PJ50.js → quadrantDiagram-AYHSOK5B-Dr56Xspi.js} +1 -1
- package/dist/assets/{requirementDiagram-UZGBJVZJ-CWMm228C.js → requirementDiagram-UZGBJVZJ-z-G-ThCz.js} +1 -1
- package/dist/assets/{sankeyDiagram-TZEHDZUN-Cf7zGgTA.js → sankeyDiagram-TZEHDZUN-D_4p6Me1.js} +1 -1
- package/dist/assets/{sequenceDiagram-WL72ISMW-TzZvjAhX.js → sequenceDiagram-WL72ISMW-DD1K4OoS.js} +1 -1
- package/dist/assets/{stateDiagram-FKZM4ZOC-CH45r52Y.js → stateDiagram-FKZM4ZOC-ENIvCriI.js} +1 -1
- package/dist/assets/stateDiagram-v2-4FDKWEC3-BgJoZY9E.js +1 -0
- package/dist/assets/{timeline-definition-IT6M3QCI-CLaDCX_H.js → timeline-definition-IT6M3QCI-V8I1MBPc.js} +1 -1
- package/dist/assets/{treemap-GDKQZRPO-BNNAKE7E.js → treemap-GDKQZRPO-1lnlvkR3.js} +1 -1
- package/dist/assets/{xychartDiagram-PRI3JC2R-BG_0_QvU.js → xychartDiagram-PRI3JC2R-CrSrN3UV.js} +1 -1
- package/dist/index.html +2 -2
- package/package.json +2 -2
- package/server/collective-intelligence.ts +125 -43
- package/server/embedding.ts +12 -3
- package/server/memory-consolidation.ts +703 -0
- package/server/memory-migration.ts +468 -0
- package/server/routes/ci-routes.ts +68 -10
- package/server/routes/settings-routes.ts +10 -2
- package/server/semantic-memory.ts +1127 -187
- package/server/session-types.ts +15 -0
- package/server/settings-manager.ts +122 -3
- package/server/ws-bridge.ts +207 -26
- package/dist/assets/channel-D6cof2B8.js +0 -1
- package/dist/assets/classDiagram-2ON5EDUG-BG_dxrC_.js +0 -1
- package/dist/assets/classDiagram-v2-WZHVMYZB-BG_dxrC_.js +0 -1
- package/dist/assets/clone-vuZ4vhTG.js +0 -1
- package/dist/assets/index-Byjg9zgI.css +0 -32
- package/dist/assets/stateDiagram-v2-4FDKWEC3-DaPUshfK.js +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,2388 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="https://raw.githubusercontent.com/stretchcloud/campfire/main/.github/og-image.png" alt="Campfire — Seven agents. One Campfire." width="100%" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">Campfire</h1>
|
|
6
|
+
<p align="center"><strong>The collaborative web platform for AI coding agents.</strong></p>
|
|
7
|
+
<p align="center">A collaborative web platform for AI coding agents. Run Claude Code, Codex, Goose, Aider, OpenHands, OpenClaw, and OpenCode sessions side by side — with real-time collaboration, multi-agent orchestration, permission voting, session replay, scheduled tasks, and 30+ integrations.</p>
|
|
8
|
+
|
|
9
|
+
<p align="center">
|
|
10
|
+
<a href="https://www.npmjs.com/package/the-campfire"><img src="https://img.shields.io/npm/v/the-campfire" alt="npm version" /></a>
|
|
11
|
+
<a href="https://www.npmjs.com/package/the-campfire"><img src="https://img.shields.io/npm/dt/the-campfire" alt="npm downloads" /></a>
|
|
12
|
+
<a href="https://github.com/stretchcloud/campfire/actions/workflows/ci.yml"><img src="https://img.shields.io/github/actions/workflow/status/stretchcloud/campfire/ci.yml?branch=main&label=CI" alt="CI status" /></a>
|
|
13
|
+
<a href="https://github.com/stretchcloud/campfire/stargazers"><img src="https://img.shields.io/github/stars/stretchcloud/campfire" alt="GitHub stars" /></a>
|
|
14
|
+
<a href="https://github.com/stretchcloud/campfire/pkgs/container/campfire"><img src="https://img.shields.io/badge/ghcr.io-campfire-2496ED?logo=docker&logoColor=white" alt="ghcr.io image" /></a>
|
|
15
|
+
<a href="LICENSE"><img src="https://img.shields.io/github/license/stretchcloud/campfire" alt="MIT License" /></a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<a href="https://the-campfire.dev"><strong>the-campfire.dev</strong></a>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Table of Contents
|
|
25
|
+
|
|
26
|
+
- [Quick Start](#quick-start)
|
|
27
|
+
- [Features](#features)
|
|
28
|
+
- [Multi-Agent Sessions](#multi-agent-sessions)
|
|
29
|
+
- [Real-Time Collaboration](#real-time-collaboration)
|
|
30
|
+
- [Permission Control & Voting](#permission-control--voting)
|
|
31
|
+
- [Session Replay](#session-replay)
|
|
32
|
+
- [Fork & Branch](#fork--branch)
|
|
33
|
+
- [Session Gallery](#session-gallery)
|
|
34
|
+
- [Prompt Library](#prompt-library)
|
|
35
|
+
- [Linear Integration](#linear-integration)
|
|
36
|
+
- [Webhooks](#webhooks)
|
|
37
|
+
- [Scheduled Tasks (Cron)](#scheduled-tasks-cron)
|
|
38
|
+
- [Adapter Registry](#adapter-registry)
|
|
39
|
+
- [Cost Dashboard](#cost-dashboard)
|
|
40
|
+
- [Environment Profiles](#environment-profiles)
|
|
41
|
+
- [Git Integration](#git-integration)
|
|
42
|
+
- [Embedded Terminal](#embedded-terminal)
|
|
43
|
+
- [Protocol Recording](#protocol-recording)
|
|
44
|
+
- [Docker Containers](#docker-containers)
|
|
45
|
+
- [PWA & Mobile](#pwa--mobile)
|
|
46
|
+
- [Auto-Naming](#auto-naming)
|
|
47
|
+
- [Collective Intelligence](#collective-intelligence)
|
|
48
|
+
- [Copy Output Button](#copy-output-button)
|
|
49
|
+
- [Voice Input](#voice-input)
|
|
50
|
+
- [Workspace File Tree](#workspace-file-tree)
|
|
51
|
+
- [Mermaid Diagram Rendering](#mermaid-diagram-rendering)
|
|
52
|
+
- [Orchestrator Pipelines](#orchestrator-pipelines)
|
|
53
|
+
- [Multi-Agent Orchestration](#multi-agent-orchestration)
|
|
54
|
+
- [Message Queue](#message-queue)
|
|
55
|
+
- [Kanban Task Board](#kanban-task-board)
|
|
56
|
+
- [Authentication](#authentication)
|
|
57
|
+
- [Thinking Effort (Codex)](#thinking-effort-codex)
|
|
58
|
+
- [Skills & Plugins Management](#skills--plugins-management)
|
|
59
|
+
- [Drag & Drop Upload](#drag--drop-upload)
|
|
60
|
+
- [Session Folders](#session-folders)
|
|
61
|
+
- [Permission Mode Selector](#permission-mode-selector)
|
|
62
|
+
- [Session Pulse (Background Activity)](#session-pulse-background-activity)
|
|
63
|
+
- [Agent System](#agent-system)
|
|
64
|
+
- [Provider Settings](#provider-settings)
|
|
65
|
+
- [Model & Provider Switcher](#model--provider-switcher)
|
|
66
|
+
- [Session Launch Progress](#session-launch-progress)
|
|
67
|
+
- [Onboarding Wizard](#onboarding-wizard)
|
|
68
|
+
- [Monaco Code Editor](#monaco-code-editor)
|
|
69
|
+
- [Files Panel](#files-panel)
|
|
70
|
+
- [Recording Hub](#recording-hub)
|
|
71
|
+
- [Protocol Monitor](#protocol-monitor)
|
|
72
|
+
- [Commands Discovery](#commands-discovery)
|
|
73
|
+
- [Proactive Keepalive](#proactive-keepalive)
|
|
74
|
+
- [Security Headers & Rate Limiting](#security-headers--rate-limiting)
|
|
75
|
+
- [WebSocket Authentication](#websocket-authentication)
|
|
76
|
+
- [Architecture](#architecture)
|
|
77
|
+
- [Docker Deployment](#docker-deployment)
|
|
78
|
+
- [CLI Reference](#cli-reference)
|
|
79
|
+
- [REST API Reference](#rest-api-reference)
|
|
80
|
+
- [WebSocket Protocol](#websocket-protocol)
|
|
81
|
+
- [Development](#development)
|
|
82
|
+
- [License](#license)
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Quick Start
|
|
87
|
+
|
|
88
|
+
There are three ways to run Campfire: from npm, from source, or with Docker.
|
|
89
|
+
|
|
90
|
+
### Option 1: npm (fastest)
|
|
91
|
+
|
|
92
|
+
If you just want to run Campfire without cloning the repo:
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Install Bun if you don't have it
|
|
96
|
+
curl -fsSL https://bun.sh/install | bash
|
|
97
|
+
|
|
98
|
+
# Run Campfire (downloads and starts automatically)
|
|
99
|
+
bunx the-campfire
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Open [http://localhost:4567](http://localhost:4567). That's it.
|
|
103
|
+
|
|
104
|
+
To run on a different port:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
bunx the-campfire --port 8080
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Option 2: Run from source (native)
|
|
111
|
+
|
|
112
|
+
Clone the repository and run directly with Bun:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
# 1. Clone the repo
|
|
116
|
+
git clone https://github.com/stretchcloud/campfire.git
|
|
117
|
+
cd campfire
|
|
118
|
+
|
|
119
|
+
# 2. Install dependencies
|
|
120
|
+
cd web
|
|
121
|
+
bun install
|
|
122
|
+
|
|
123
|
+
# 3. Build and start
|
|
124
|
+
bun run build
|
|
125
|
+
bun run start
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Open [http://localhost:4567](http://localhost:4567). That's it.
|
|
129
|
+
|
|
130
|
+
> **Contributing?** Use `bun run dev` for hot reload during frontend development. See the [Development](#development) section for details.
|
|
131
|
+
|
|
132
|
+
### Option 3: Docker
|
|
133
|
+
|
|
134
|
+
Pull the pre-built image from the GitHub Container Registry (no clone, no build):
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
docker run -d \
|
|
138
|
+
--name campfire \
|
|
139
|
+
-p 4567:4567 \
|
|
140
|
+
-v campfire-data:/home/campfire/.campfire \
|
|
141
|
+
--restart unless-stopped \
|
|
142
|
+
ghcr.io/stretchcloud/campfire:latest
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Open [http://localhost:4567](http://localhost:4567). Pin a specific version by tag instead of `latest`, e.g. `ghcr.io/stretchcloud/campfire:0.2.1`.
|
|
146
|
+
|
|
147
|
+
Or build and run from source with Docker Compose (no Bun installation needed):
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# 1. Clone the repo
|
|
151
|
+
git clone https://github.com/stretchcloud/campfire.git
|
|
152
|
+
cd campfire
|
|
153
|
+
|
|
154
|
+
# 2. Build and start the container
|
|
155
|
+
docker compose up
|
|
156
|
+
|
|
157
|
+
# Or build and run in the background
|
|
158
|
+
docker compose up -d
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Open [http://localhost:4567](http://localhost:4567).
|
|
162
|
+
|
|
163
|
+
To build the Docker image manually without Compose:
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# Build the image
|
|
167
|
+
docker build -t campfire:latest .
|
|
168
|
+
|
|
169
|
+
# Run the container
|
|
170
|
+
docker run -d \
|
|
171
|
+
--name campfire \
|
|
172
|
+
-p 4567:4567 \
|
|
173
|
+
-v campfire-data:/home/campfire/.campfire \
|
|
174
|
+
--restart unless-stopped \
|
|
175
|
+
campfire:latest
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
To stop and remove:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Docker Compose
|
|
182
|
+
docker compose down
|
|
183
|
+
|
|
184
|
+
# Or manual
|
|
185
|
+
docker stop campfire && docker rm campfire
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
See [Docker Deployment](#docker-deployment) for advanced configuration (mounting agent CLIs, reverse proxy, environment variables).
|
|
189
|
+
|
|
190
|
+
### Requirements
|
|
191
|
+
|
|
192
|
+
**For native (npm or source):**
|
|
193
|
+
- [Bun](https://bun.sh) >= 1.0
|
|
194
|
+
- At least one agent CLI installed and on your `PATH`:
|
|
195
|
+
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code) — `npm install -g @anthropic-ai/claude-code`
|
|
196
|
+
- [Codex](https://github.com/openai/codex) — `npm install -g @openai/codex`
|
|
197
|
+
- [Goose](https://github.com/block/goose) — `brew install goose` or see [docs](https://github.com/block/goose)
|
|
198
|
+
- [Aider](https://aider.chat) — `pip install aider-chat`
|
|
199
|
+
- [OpenHands](https://github.com/All-Hands-AI/OpenHands) — see [docs](https://github.com/All-Hands-AI/OpenHands)
|
|
200
|
+
- [OpenClaw](https://github.com/anomalyco/openclaw) — `openclaw` binary on `PATH`, set `OPENCLAW_GATEWAY_TOKEN` and `OPENCLAW_GATEWAY_URL`
|
|
201
|
+
- [OpenCode](https://github.com/anomalyco/opencode) — `opencode` binary on `PATH`
|
|
202
|
+
|
|
203
|
+
**For Docker:**
|
|
204
|
+
- [Docker](https://docs.docker.com/get-docker/) >= 20.0
|
|
205
|
+
- Agent CLIs are **not** included in the Docker image — see [Running with Agent CLIs](#running-with-agent-CLIs) for how to mount or install them
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## Features
|
|
210
|
+
|
|
211
|
+
### Multi-Agent Sessions
|
|
212
|
+
|
|
213
|
+
Run parallel sessions across seven agent backends from a single browser tab. Each session streams output, tool calls, and results in a unified timeline. The frontend is completely backend-agnostic — it renders the same UI regardless of which agent is running.
|
|
214
|
+
|
|
215
|
+
**Supported backends:**
|
|
216
|
+
|
|
217
|
+
| Backend | Protocol | How it connects |
|
|
218
|
+
|---------|----------|-----------------|
|
|
219
|
+
| Claude Code | NDJSON over WebSocket | Spawned with `--sdk-url` flag |
|
|
220
|
+
| Codex | JSON-RPC over stdio | Spawned as `codex app-server` |
|
|
221
|
+
| Goose | JSON-RPC 2.0 (ACP) over stdio | Spawned as `goose acp --with-builtin developer --with-builtin memory` |
|
|
222
|
+
| Aider | stdout parsing over stdio | Spawned as `aider --no-pretty --yes --no-auto-commits` |
|
|
223
|
+
| OpenHands | JSON-RPC 2.0 (ACP) over stdio | Spawned as `openhands acp` |
|
|
224
|
+
| OpenClaw | JSON-RPC 2.0 (ACP) over stdio | Spawned as `openclaw acp`; requires `OPENCLAW_GATEWAY_TOKEN` + `OPENCLAW_GATEWAY_URL` |
|
|
225
|
+
| OpenCode | JSON-RPC 2.0 (ACP) over stdio | Spawned as `opencode acp`; model set via `OPENCODE_MODEL` |
|
|
226
|
+
|
|
227
|
+
**Creating a session:**
|
|
228
|
+
|
|
229
|
+
1. Click **New Session** in the sidebar
|
|
230
|
+
2. Choose a backend (Claude Code, Codex, Goose, Aider, OpenHands, OpenClaw, or OpenCode)
|
|
231
|
+
3. Select a model (backend-specific model lists)
|
|
232
|
+
4. Set the working directory for the session
|
|
233
|
+
5. Optionally choose a permission mode, environment profile, or git branch
|
|
234
|
+
6. Click **Create**
|
|
235
|
+
|
|
236
|
+
**Session options:**
|
|
237
|
+
|
|
238
|
+
| Option | Description |
|
|
239
|
+
|--------|-------------|
|
|
240
|
+
| Backend | Which agent CLI to use |
|
|
241
|
+
| Model | AI model to run (e.g. `claude-sonnet-4-5-20250929`, `o3`, `gpt-4.1`) |
|
|
242
|
+
| Permission mode | `default`, `bypassPermissions`, `oneTouchApprovals`, `manualApprovals` |
|
|
243
|
+
| Working directory | Folder the agent operates in |
|
|
244
|
+
| Environment profile | Pre-saved set of environment variables to inject |
|
|
245
|
+
| Git branch | Check out a specific branch before starting |
|
|
246
|
+
| Use worktree | Create an isolated git worktree (keeps branches separate) |
|
|
247
|
+
| Create branch | Create the branch if it doesn't exist |
|
|
248
|
+
| Docker container | Run the session inside a Docker container (Claude only) |
|
|
249
|
+
| Internet access | Enable web search for Codex |
|
|
250
|
+
| Allowed tools | Restrict which tools the agent can use |
|
|
251
|
+
|
|
252
|
+
**Session lifecycle:**
|
|
253
|
+
|
|
254
|
+
- **Running** — agent is processing, streaming output
|
|
255
|
+
- **Idle** — agent is waiting for input
|
|
256
|
+
- **Compacting** — agent is compacting context (Claude Code)
|
|
257
|
+
- **Exited** — agent process has stopped
|
|
258
|
+
|
|
259
|
+
Sessions persist to disk and survive server restarts. When the server restarts, running CLI processes are detected by PID and given a grace period to reconnect. If they don't, they're killed and relaunched with `--resume`.
|
|
260
|
+
|
|
261
|
+
**Managing sessions:**
|
|
262
|
+
|
|
263
|
+
- **Rename** — click the session name in the sidebar to edit inline
|
|
264
|
+
- **Kill** — stop the running agent process
|
|
265
|
+
- **Relaunch** — restart a stopped session (uses `--resume` for Claude Code)
|
|
266
|
+
- **Archive** — hide the session from the active list while preserving history
|
|
267
|
+
- **Delete** — permanently remove the session (also cleans up worktrees and containers)
|
|
268
|
+
|
|
269
|
+
---
|
|
270
|
+
|
|
271
|
+
### Real-Time Collaboration
|
|
272
|
+
|
|
273
|
+
Share any session with teammates using invite links. Multiple people can watch and interact with the same session simultaneously.
|
|
274
|
+
|
|
275
|
+
**How to share a session:**
|
|
276
|
+
|
|
277
|
+
1. Open a running session
|
|
278
|
+
2. Click the **Share** button in the top bar
|
|
279
|
+
3. Choose a role for the invited user:
|
|
280
|
+
- **Collaborator** — can send messages and vote on permissions
|
|
281
|
+
- **Spectator** — watch-only (cannot send messages or vote)
|
|
282
|
+
4. Copy the generated link and share it
|
|
283
|
+
|
|
284
|
+
The invite link looks like `http://localhost:4567/#/join/<token>`. When someone opens it, they join the session with the assigned role. **Invite links expire after 24 hours** — they are bearer credentials that bypass password auth, so generate a fresh one when you need to re-share.
|
|
285
|
+
|
|
286
|
+
**Presence indicators:**
|
|
287
|
+
|
|
288
|
+
Connected users appear as colored avatars in the top bar:
|
|
289
|
+
- **Blue** — Owner (the person who created the session)
|
|
290
|
+
- **Green** — Collaborator (can interact)
|
|
291
|
+
- **Gray** — Spectator (watch-only)
|
|
292
|
+
|
|
293
|
+
Presence updates are broadcast in real time — you see when someone joins or leaves.
|
|
294
|
+
|
|
295
|
+
**Roles and permissions:**
|
|
296
|
+
|
|
297
|
+
| Capability | Owner | Collaborator | Spectator |
|
|
298
|
+
|-----------|-------|--------------|-----------|
|
|
299
|
+
| View session output | Yes | Yes | Yes |
|
|
300
|
+
| Send messages | Yes | Yes | No |
|
|
301
|
+
| Approve/deny permissions | Yes | Yes | No |
|
|
302
|
+
| Vote on tool calls | Yes | Yes | No |
|
|
303
|
+
| Interrupt the agent | Yes | Yes | No |
|
|
304
|
+
| Change model or mode | Yes | Yes | No |
|
|
305
|
+
| Configure MCP servers | Yes | Yes | No |
|
|
306
|
+
|
|
307
|
+
The first browser to connect to a session becomes the **Owner**. Subsequent connections default to **Collaborator** unless they join via a spectator invite link.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
### Permission Control & Voting
|
|
312
|
+
|
|
313
|
+
Every risky tool call (file writes, bash commands, etc.) surfaces a permission banner at the top of the chat. The banner shows what the agent wants to do and lets you approve, deny, or apply a permission rule.
|
|
314
|
+
|
|
315
|
+
**Permission banner displays:**
|
|
316
|
+
|
|
317
|
+
| Tool | What you see |
|
|
318
|
+
|------|-------------|
|
|
319
|
+
| Bash | The exact command with `$` prefix |
|
|
320
|
+
| Edit | Side-by-side diff showing old vs new content |
|
|
321
|
+
| Write | The full file content being written |
|
|
322
|
+
| Read | The file path being read |
|
|
323
|
+
| Glob / Grep | The search pattern and path |
|
|
324
|
+
| AskUserQuestion | Multiple-choice options with a custom text input |
|
|
325
|
+
|
|
326
|
+
**Actions available:**
|
|
327
|
+
|
|
328
|
+
- **Allow** — approve this specific tool call
|
|
329
|
+
- **Deny** — reject this tool call
|
|
330
|
+
- **Permission suggestions** — apply a broader rule (e.g. "Allow for session", "Allow always", "Trust directory")
|
|
331
|
+
|
|
332
|
+
**Voting (collaborative sessions):**
|
|
333
|
+
|
|
334
|
+
When multiple viewers are connected, permission requests become votes. The voting behavior is configurable:
|
|
335
|
+
|
|
336
|
+
| Policy | How it works |
|
|
337
|
+
|--------|-------------|
|
|
338
|
+
| `majority-rules` | Action is allowed if more than half vote "allow" (default) |
|
|
339
|
+
| `any-deny-blocks` | A single "deny" vote blocks the action |
|
|
340
|
+
| `owner-decides` | Only the owner's vote counts |
|
|
341
|
+
|
|
342
|
+
Configure the voting policy via the UI or API:
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
# Get current policy
|
|
346
|
+
curl http://localhost:4567/api/voting-policy
|
|
347
|
+
|
|
348
|
+
# Change policy
|
|
349
|
+
curl -X PUT http://localhost:4567/api/voting-policy \
|
|
350
|
+
-H "Content-Type: application/json" \
|
|
351
|
+
-d '{"policy": "any-deny-blocks"}'
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
Votes have a **30-second deadline**. If the deadline passes, the vote resolves based on collected votes. The UI shows a countdown timer, current vote tally, and voter avatars.
|
|
355
|
+
|
|
356
|
+
---
|
|
357
|
+
|
|
358
|
+
### Session Replay
|
|
359
|
+
|
|
360
|
+
Scrub through completed sessions at 1x / 2x / 4x / 8x speed. Every tool call, permission decision, and streaming token is preserved in protocol recordings.
|
|
361
|
+
|
|
362
|
+
**How to use replay:**
|
|
363
|
+
|
|
364
|
+
1. Open a completed session from the sidebar
|
|
365
|
+
2. Click the **Recordings** section to see available recording files
|
|
366
|
+
3. Click a recording to open the replay player
|
|
367
|
+
4. Use the playback controls to play, pause, and change speed
|
|
368
|
+
|
|
369
|
+
**Replay controls:**
|
|
370
|
+
- Play / Pause toggle
|
|
371
|
+
- Speed selector: 1x, 2x, 4x, 8x
|
|
372
|
+
- Progress scrubber for seeking
|
|
373
|
+
|
|
374
|
+
**Recording format:**
|
|
375
|
+
|
|
376
|
+
Recordings are stored as JSONL (newline-delimited JSON) files in `~/.campfire/recordings/`. Each line captures the exact raw message as it was sent or received:
|
|
377
|
+
|
|
378
|
+
```json
|
|
379
|
+
{"ts": 1771153996875, "dir": "in", "raw": "{\"type\":\"system\",...}", "ch": "cli"}
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
- `ts` — Unix timestamp in milliseconds
|
|
383
|
+
- `dir` — `"in"` (received by server) or `"out"` (sent by server)
|
|
384
|
+
- `ch` — `"cli"` (agent process) or `"browser"` (frontend)
|
|
385
|
+
- `raw` — exact original message string, never re-serialized
|
|
386
|
+
|
|
387
|
+
**Recording management:**
|
|
388
|
+
|
|
389
|
+
```bash
|
|
390
|
+
# List all recordings
|
|
391
|
+
curl http://localhost:4567/api/recordings
|
|
392
|
+
|
|
393
|
+
# Check if a session is being recorded
|
|
394
|
+
curl http://localhost:4567/api/sessions/:id/recording/status
|
|
395
|
+
|
|
396
|
+
# Start/stop recording for a specific session
|
|
397
|
+
curl -X POST http://localhost:4567/api/sessions/:id/recording/start
|
|
398
|
+
curl -X POST http://localhost:4567/api/sessions/:id/recording/stop
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
Recording is enabled by default. Disable globally with `CAMPFIRE_RECORD=0`. Files auto-rotate when total lines exceed 100,000 (configurable with `CAMPFIRE_RECORDINGS_MAX_LINES`).
|
|
402
|
+
|
|
403
|
+
---
|
|
404
|
+
|
|
405
|
+
### Fork & Branch
|
|
406
|
+
|
|
407
|
+
Fork any session at any point in its conversation to explore a different path. Forks create a new session with the message history up to the fork point, optionally on a new git worktree.
|
|
408
|
+
|
|
409
|
+
**How to fork:**
|
|
410
|
+
|
|
411
|
+
1. **From the top bar** — click the **Fork** button to fork at the current point
|
|
412
|
+
2. **From any message** — hover over a message and click the fork icon to fork from that specific point
|
|
413
|
+
|
|
414
|
+
**What happens when you fork:**
|
|
415
|
+
|
|
416
|
+
1. The message history is copied up to the selected point
|
|
417
|
+
2. If the session is in a git repository, a new worktree is created for isolation
|
|
418
|
+
3. A new session is launched with the copied history
|
|
419
|
+
4. The forked session shows a "forked from" indicator linking back to the original
|
|
420
|
+
|
|
421
|
+
**Fork options:**
|
|
422
|
+
|
|
423
|
+
```bash
|
|
424
|
+
curl -X POST http://localhost:4567/api/sessions/:id/fork \
|
|
425
|
+
-H "Content-Type: application/json" \
|
|
426
|
+
-d '{
|
|
427
|
+
"messageIndex": 5,
|
|
428
|
+
"model": "claude-sonnet-4-5-20250929",
|
|
429
|
+
"permissionMode": "bypassPermissions",
|
|
430
|
+
"branch": "experiment/new-approach"
|
|
431
|
+
}'
|
|
432
|
+
```
|
|
433
|
+
|
|
434
|
+
| Field | Description |
|
|
435
|
+
|-------|-------------|
|
|
436
|
+
| `messageIndex` | Fork after this message (0-indexed). Omit to fork at the end. |
|
|
437
|
+
| `model` | Override the model for the forked session |
|
|
438
|
+
| `permissionMode` | Override permission mode |
|
|
439
|
+
| `branch` | Git branch name for the worktree |
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
### Session Gallery
|
|
444
|
+
|
|
445
|
+
Publish your best sessions to a gallery that anyone on your Campfire instance can browse. Gallery entries include session metadata, cost, duration, and a direct link to replay.
|
|
446
|
+
|
|
447
|
+
**How to publish:**
|
|
448
|
+
|
|
449
|
+
1. Navigate to the **Gallery** page from the sidebar
|
|
450
|
+
2. Click **Add to Gallery**
|
|
451
|
+
3. Select a completed session
|
|
452
|
+
4. Add a name, description, and tags
|
|
453
|
+
5. Click **Publish**
|
|
454
|
+
|
|
455
|
+
**Browsing the gallery:**
|
|
456
|
+
|
|
457
|
+
The gallery supports filtering and sorting:
|
|
458
|
+
|
|
459
|
+
| Filter | Example |
|
|
460
|
+
|--------|---------|
|
|
461
|
+
| Backend | Show only Claude Code sessions |
|
|
462
|
+
| Cost range | Sessions between $0.01 and $1.00 |
|
|
463
|
+
| Tags | Filter by `migration`, `refactor`, `bugfix`, etc. |
|
|
464
|
+
| Featured only | Show only featured entries |
|
|
465
|
+
|
|
466
|
+
| Sort by | Description |
|
|
467
|
+
|---------|-------------|
|
|
468
|
+
| Votes | Most upvoted first |
|
|
469
|
+
| Recent | Newest first |
|
|
470
|
+
| Cost | Cheapest or most expensive first |
|
|
471
|
+
| Duration | Shortest or longest first |
|
|
472
|
+
|
|
473
|
+
**Voting and featuring:**
|
|
474
|
+
|
|
475
|
+
- Click the up/down arrows on any gallery card to vote (anonymous, IP-deduplicated)
|
|
476
|
+
- Admins can toggle the **Featured** star to highlight exceptional sessions
|
|
477
|
+
|
|
478
|
+
**Gallery entry metadata:**
|
|
479
|
+
|
|
480
|
+
Each entry captures a snapshot of the session at publish time: backend type, model, total cost, duration, lines added/removed, and number of turns. Click **View Replay** on any card to watch the session.
|
|
481
|
+
|
|
482
|
+
**Public share links:**
|
|
483
|
+
|
|
484
|
+
Generate a tokenized public replay link for any gallery entry (`POST /api/gallery/:id/public-link`). Anyone with the link can watch the session replay at `#/public-replay/<token>` — no login required, no app chrome, read-only.
|
|
485
|
+
|
|
486
|
+
**ClawHub export:**
|
|
487
|
+
|
|
488
|
+
Gallery entries can be exported as ClawHub-compatible skills (`SKILL.md` with stats and a replay link) and published via the `clawhub` CLI. Browse and install shared skills from the **ClawHub** page (`#/clawhub`) in the sidebar.
|
|
489
|
+
|
|
490
|
+
**Moltbook posting:**
|
|
491
|
+
|
|
492
|
+
Entries can also be posted as "molts" to [Moltbook](https://moltbook.com), a social network for AI agents (`POST /api/gallery/:id/post-moltbook`; configure the agent account in Settings).
|
|
493
|
+
|
|
494
|
+
```bash
|
|
495
|
+
# List gallery entries with filters
|
|
496
|
+
curl "http://localhost:4567/api/gallery?backend=claude&sortBy=votes&featured=true"
|
|
497
|
+
|
|
498
|
+
# Publish a session
|
|
499
|
+
curl -X POST http://localhost:4567/api/gallery \
|
|
500
|
+
-H "Content-Type: application/json" \
|
|
501
|
+
-d '{
|
|
502
|
+
"sessionId": "abc-123",
|
|
503
|
+
"name": "Migrated auth to OAuth2",
|
|
504
|
+
"description": "Full migration from session-based auth to OAuth2 with PKCE",
|
|
505
|
+
"tags": ["migration", "auth", "oauth"]
|
|
506
|
+
}'
|
|
507
|
+
|
|
508
|
+
# Vote on an entry
|
|
509
|
+
curl -X POST http://localhost:4567/api/gallery/:id/vote \
|
|
510
|
+
-H "Content-Type: application/json" \
|
|
511
|
+
-d '{"direction": 1}'
|
|
512
|
+
|
|
513
|
+
# Toggle featured status
|
|
514
|
+
curl -X POST http://localhost:4567/api/gallery/:id/feature
|
|
515
|
+
```
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
### Prompt Library
|
|
520
|
+
|
|
521
|
+
Save reusable prompt snippets and insert them into any message with `@` in the composer. Prompts can be scoped globally or to a specific project directory.
|
|
522
|
+
|
|
523
|
+
**How to create a prompt:**
|
|
524
|
+
|
|
525
|
+
1. Navigate to the **Prompts** page from the sidebar
|
|
526
|
+
2. Click **+ New Prompt**
|
|
527
|
+
3. Enter a name and the prompt text
|
|
528
|
+
4. Choose scope: **Global** (available everywhere) or **Project** (scoped to a path prefix)
|
|
529
|
+
5. Click **Save**
|
|
530
|
+
|
|
531
|
+
**Inserting prompts in the composer:**
|
|
532
|
+
|
|
533
|
+
Type `@` in the message box to open the prompt picker. Start typing to filter by name or content. Use Arrow keys to navigate, Tab or Enter to insert.
|
|
534
|
+
|
|
535
|
+
The full content of the selected prompt replaces the `@query` in your message, so you can mix prompt snippets with your own text.
|
|
536
|
+
|
|
537
|
+
**CWD-scoped loading:**
|
|
538
|
+
|
|
539
|
+
The prompt picker automatically filters prompts based on the current session's working directory. When you switch sessions with different working directories, the prompt list refreshes to show only prompts relevant to that project. Global prompts are always available regardless of the working directory.
|
|
540
|
+
|
|
541
|
+
**REST API:**
|
|
542
|
+
|
|
543
|
+
```bash
|
|
544
|
+
# List prompts (optionally filtered by cwd)
|
|
545
|
+
curl "http://localhost:4567/api/prompts?cwd=/home/user/my-project"
|
|
546
|
+
|
|
547
|
+
# Create a prompt
|
|
548
|
+
curl -X POST http://localhost:4567/api/prompts \
|
|
549
|
+
-H "Content-Type: application/json" \
|
|
550
|
+
-d '{
|
|
551
|
+
"name": "Code review checklist",
|
|
552
|
+
"content": "Please review for: 1) correctness, 2) edge cases, 3) performance, 4) test coverage",
|
|
553
|
+
"scope": "global"
|
|
554
|
+
}'
|
|
555
|
+
|
|
556
|
+
# Update a prompt
|
|
557
|
+
curl -X PUT http://localhost:4567/api/prompts/:id \
|
|
558
|
+
-H "Content-Type: application/json" \
|
|
559
|
+
-d '{"name": "Updated name", "content": "Updated content"}'
|
|
560
|
+
|
|
561
|
+
# Delete a prompt
|
|
562
|
+
curl -X DELETE http://localhost:4567/api/prompts/:id
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
Prompts are stored at `~/.campfire/prompts.json`.
|
|
566
|
+
|
|
567
|
+
---
|
|
568
|
+
|
|
569
|
+
### Linear Integration
|
|
570
|
+
|
|
571
|
+
Connect your Linear workspace to manage issues end-to-end: browse and search issues, link them to sessions, auto-generate branch names, map projects to repositories, and auto-transition issue state when work begins.
|
|
572
|
+
|
|
573
|
+
**Setup:**
|
|
574
|
+
|
|
575
|
+
1. Navigate to **Integrations** → **Linear** from the sidebar
|
|
576
|
+
2. Create a personal API key at `linear.app/settings/api`
|
|
577
|
+
3. Paste your key and click **Connect**
|
|
578
|
+
|
|
579
|
+
**What it enables:**
|
|
580
|
+
|
|
581
|
+
- Browse and search Linear issues when creating a new session
|
|
582
|
+
- Auto-generate a recommended git branch name from the issue (e.g. `feat/eng-123-add-auth`)
|
|
583
|
+
- Link issues to sessions — track which issue each session is working on
|
|
584
|
+
- Map Linear teams/projects to git repositories for automatic filtering
|
|
585
|
+
- Auto-transition issues to "In Progress" when a linked session starts
|
|
586
|
+
|
|
587
|
+
**Project-repo mapping:**
|
|
588
|
+
|
|
589
|
+
When you first use Linear in a git repository, Campfire prompts you to link the repo to a Linear team. Once linked, issue searches are automatically filtered to that team. Mappings are stored in `~/.campfire/linear-projects.json`.
|
|
590
|
+
|
|
591
|
+
**Issue-session workflow:**
|
|
592
|
+
|
|
593
|
+
1. Open the **New Session** page in a git repo with a linked Linear team
|
|
594
|
+
2. The **Linear Issues** section appears automatically
|
|
595
|
+
3. Search for an issue by title or identifier
|
|
596
|
+
4. Select an issue — a branch name is auto-generated (e.g. `feat/ENG-123-add-oauth-flow`)
|
|
597
|
+
5. The worktree toggle activates with the generated branch name
|
|
598
|
+
6. Create the session — the issue is linked and transitions to "In Progress"
|
|
599
|
+
|
|
600
|
+
**REST API:**
|
|
601
|
+
|
|
602
|
+
```bash
|
|
603
|
+
# Check connection status
|
|
604
|
+
curl http://localhost:4567/api/linear/connection
|
|
605
|
+
# → {"connected": true, "viewer": {"name": "...", "email": "..."}, "teams": [...]}
|
|
606
|
+
|
|
607
|
+
# Search issues (cached, deduplicated)
|
|
608
|
+
curl "http://localhost:4567/api/linear/issues?query=auth&limit=10"
|
|
609
|
+
|
|
610
|
+
# List teams
|
|
611
|
+
curl http://localhost:4567/api/linear/teams
|
|
612
|
+
|
|
613
|
+
# Get workflow states for a team
|
|
614
|
+
curl http://localhost:4567/api/linear/team/:teamId/states
|
|
615
|
+
|
|
616
|
+
# Project-repo mapping
|
|
617
|
+
curl http://localhost:4567/api/linear/project-mapping?repoRoot=/path/to/repo
|
|
618
|
+
curl -X POST http://localhost:4567/api/linear/project-mapping \
|
|
619
|
+
-H "Content-Type: application/json" \
|
|
620
|
+
-d '{"repoRoot": "/path/to/repo", "teamId": "...", "teamKey": "ENG", "teamName": "Engineering"}'
|
|
621
|
+
curl -X DELETE http://localhost:4567/api/linear/project-mapping \
|
|
622
|
+
-H "Content-Type: application/json" \
|
|
623
|
+
-d '{"repoRoot": "/path/to/repo"}'
|
|
624
|
+
|
|
625
|
+
# Link an issue to a session
|
|
626
|
+
curl -X POST http://localhost:4567/api/linear/session/:sessionId/link-issue \
|
|
627
|
+
-H "Content-Type: application/json" \
|
|
628
|
+
-d '{"issueId": "...", "identifier": "ENG-123", "title": "Add OAuth", "url": "...", "state": "Todo", "teamKey": "ENG"}'
|
|
629
|
+
|
|
630
|
+
# Get linked issue for a session
|
|
631
|
+
curl http://localhost:4567/api/linear/session/:sessionId/issue
|
|
632
|
+
|
|
633
|
+
# Transition an issue's state
|
|
634
|
+
curl -X POST http://localhost:4567/api/linear/issues/:issueId/transition \
|
|
635
|
+
-H "Content-Type: application/json" \
|
|
636
|
+
-d '{"stateId": "..."}'
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
**Caching:**
|
|
640
|
+
|
|
641
|
+
Linear API responses are cached with a 60-second TTL to reduce API calls. Concurrent identical requests are deduplicated — only one GraphQL call is made, and all callers receive the same result.
|
|
642
|
+
|
|
643
|
+
**Data storage:**
|
|
644
|
+
|
|
645
|
+
| File | Contents |
|
|
646
|
+
|------|----------|
|
|
647
|
+
| `~/.campfire/settings.json` | Linear API key (never exposed via GET) |
|
|
648
|
+
| `~/.campfire/linear-projects.json` | Repo → team/project mappings |
|
|
649
|
+
| `~/.campfire/linear-session-issues.json` | Session → issue links |
|
|
650
|
+
|
|
651
|
+
---
|
|
652
|
+
|
|
653
|
+
### Webhooks
|
|
654
|
+
|
|
655
|
+
Receive HTTP POST notifications when events happen in your sessions. Configure webhooks with event filters, HMAC-SHA256 signing, and automatic retries.
|
|
656
|
+
|
|
657
|
+
**Inbound (OpenClaw):** Campfire also accepts inbound calls — `POST /api/webhooks/openclaw` (token-guarded) spawns an OpenClaw session from an external trigger, and `POST /api/openclaw/inbound` delivers agent messages from the OpenClaw channel plugin into an existing session.
|
|
658
|
+
|
|
659
|
+
**How to set up a webhook:**
|
|
660
|
+
|
|
661
|
+
1. Navigate to the **Webhooks** page from the sidebar
|
|
662
|
+
2. Click **Create Webhook**
|
|
663
|
+
3. Enter the destination URL
|
|
664
|
+
4. Select which events to subscribe to
|
|
665
|
+
5. Optionally add a signing secret and session filters
|
|
666
|
+
6. Click **Create**
|
|
667
|
+
|
|
668
|
+
**Available events:**
|
|
669
|
+
|
|
670
|
+
| Event | When it fires |
|
|
671
|
+
|-------|---------------|
|
|
672
|
+
| `session.created` | A new session starts |
|
|
673
|
+
| `session.completed` | A session finishes successfully |
|
|
674
|
+
| `session.failed` | A session exits with an error |
|
|
675
|
+
| `permission.requested` | An agent requests permission for a tool call |
|
|
676
|
+
| `permission.resolved` | A permission request is approved or denied |
|
|
677
|
+
| `turn.completed` | An agent completes a turn (each back-and-forth) |
|
|
678
|
+
| `cost.threshold` | Session cost crosses a threshold |
|
|
679
|
+
|
|
680
|
+
**Payload format:**
|
|
681
|
+
|
|
682
|
+
```json
|
|
683
|
+
{
|
|
684
|
+
"event": "session.completed",
|
|
685
|
+
"timestamp": 1771153996875,
|
|
686
|
+
"sessionId": "abc-123",
|
|
687
|
+
"data": {
|
|
688
|
+
"backendType": "claude",
|
|
689
|
+
"model": "claude-sonnet-4-5-20250929",
|
|
690
|
+
"totalCostUsd": 0.42,
|
|
691
|
+
"numTurns": 12,
|
|
692
|
+
"durationMs": 180000
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
**HMAC-SHA256 signing:**
|
|
698
|
+
|
|
699
|
+
If you provide a `secret`, every delivery includes an `X-Campfire-Signature` header:
|
|
700
|
+
|
|
701
|
+
```
|
|
702
|
+
X-Campfire-Signature: sha256=<hex-encoded-hmac>
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
Verify the signature on your server by computing `HMAC-SHA256(secret, request_body)` and comparing.
|
|
706
|
+
|
|
707
|
+
**Retry behavior:**
|
|
708
|
+
|
|
709
|
+
Failed deliveries are retried 3 times with exponential backoff: 1s, 5s, 15s. Delivery stats (total, failed, last delivery time) are tracked per webhook.
|
|
710
|
+
|
|
711
|
+
**Session filters:**
|
|
712
|
+
|
|
713
|
+
Narrow a webhook to specific sessions by backend type or working directory:
|
|
714
|
+
|
|
715
|
+
```json
|
|
716
|
+
{
|
|
717
|
+
"sessionFilter": {
|
|
718
|
+
"backendType": "claude",
|
|
719
|
+
"cwd": "/home/user/my-project"
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
```
|
|
723
|
+
|
|
724
|
+
**Slack integration:**
|
|
725
|
+
|
|
726
|
+
Webhook payloads include Slack-compatible formatting. Point a webhook at a Slack incoming webhook URL and events will render as formatted messages.
|
|
727
|
+
|
|
728
|
+
**Testing:**
|
|
729
|
+
|
|
730
|
+
Click the **Test** button on any webhook to send a test payload and verify your endpoint is receiving events correctly.
|
|
731
|
+
|
|
732
|
+
```bash
|
|
733
|
+
# Create a webhook
|
|
734
|
+
curl -X POST http://localhost:4567/api/webhooks \
|
|
735
|
+
-H "Content-Type: application/json" \
|
|
736
|
+
-d '{
|
|
737
|
+
"name": "Slack Alerts",
|
|
738
|
+
"url": "https://hooks.slack.com/services/...",
|
|
739
|
+
"events": ["session.completed", "session.failed", "cost.threshold"],
|
|
740
|
+
"secret": "my-signing-secret",
|
|
741
|
+
"enabled": true
|
|
742
|
+
}'
|
|
743
|
+
|
|
744
|
+
# Test delivery
|
|
745
|
+
curl -X POST http://localhost:4567/api/webhooks/:id/test
|
|
746
|
+
|
|
747
|
+
# Toggle enable/disable
|
|
748
|
+
curl -X POST http://localhost:4567/api/webhooks/:id/toggle
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
---
|
|
752
|
+
|
|
753
|
+
### Scheduled Tasks (Cron)
|
|
754
|
+
|
|
755
|
+
Run autonomous agent sessions on a schedule — daily test suites, nightly code reviews, weekly dependency updates, or one-shot migration scripts.
|
|
756
|
+
|
|
757
|
+
**How to create a scheduled task:**
|
|
758
|
+
|
|
759
|
+
1. Navigate to the **Scheduled** page from the sidebar
|
|
760
|
+
2. Click **Create Job**
|
|
761
|
+
3. Fill in the form:
|
|
762
|
+
- **Name** — human-readable label (e.g. "Nightly Test Suite")
|
|
763
|
+
- **Prompt** — the instruction to send to the agent
|
|
764
|
+
- **Schedule** — cron expression (`0 2 * * *`) or ISO datetime for one-shot
|
|
765
|
+
- **Backend** — which agent to use
|
|
766
|
+
- **Model** — which model to run
|
|
767
|
+
- **Working directory** — where to run
|
|
768
|
+
- **Permission mode** — typically `bypassPermissions` for autonomous execution
|
|
769
|
+
- **Environment profile** — optional API keys and variables
|
|
770
|
+
4. Click **Create**
|
|
771
|
+
|
|
772
|
+
**Cron expression examples:**
|
|
773
|
+
|
|
774
|
+
| Expression | Meaning |
|
|
775
|
+
|-----------|---------|
|
|
776
|
+
| `0 2 * * *` | Every day at 2:00 AM |
|
|
777
|
+
| `0 9 * * 1` | Every Monday at 9:00 AM |
|
|
778
|
+
| `*/30 * * * *` | Every 30 minutes |
|
|
779
|
+
| `0 0 1 * *` | First day of every month at midnight |
|
|
780
|
+
|
|
781
|
+
**One-shot tasks:**
|
|
782
|
+
|
|
783
|
+
Set `recurring: false` and provide an ISO datetime as the schedule (e.g. `2025-12-31T23:59:00Z`). The job runs once at that time and auto-disables.
|
|
784
|
+
|
|
785
|
+
**Execution tracking:**
|
|
786
|
+
|
|
787
|
+
Each execution creates a session and tracks:
|
|
788
|
+
- Start time and completion time
|
|
789
|
+
- Success or failure status
|
|
790
|
+
- Cost incurred
|
|
791
|
+
- Link to the session for full replay
|
|
792
|
+
|
|
793
|
+
Jobs auto-disable after repeated consecutive failures to prevent runaway costs.
|
|
794
|
+
|
|
795
|
+
**Managing jobs:**
|
|
796
|
+
|
|
797
|
+
```bash
|
|
798
|
+
# List all jobs
|
|
799
|
+
curl http://localhost:4567/api/cron/jobs
|
|
800
|
+
|
|
801
|
+
# Create a recurring job
|
|
802
|
+
curl -X POST http://localhost:4567/api/cron/jobs \
|
|
803
|
+
-H "Content-Type: application/json" \
|
|
804
|
+
-d '{
|
|
805
|
+
"name": "Nightly Tests",
|
|
806
|
+
"prompt": "Run the full test suite and fix any failures",
|
|
807
|
+
"schedule": "0 2 * * *",
|
|
808
|
+
"recurring": true,
|
|
809
|
+
"backendType": "claude",
|
|
810
|
+
"model": "claude-sonnet-4-5-20250929",
|
|
811
|
+
"cwd": "/home/user/my-project",
|
|
812
|
+
"permissionMode": "bypassPermissions"
|
|
813
|
+
}'
|
|
814
|
+
|
|
815
|
+
# Manually trigger a job
|
|
816
|
+
curl -X POST http://localhost:4567/api/cron/jobs/:id/run
|
|
817
|
+
|
|
818
|
+
# Enable/disable
|
|
819
|
+
curl -X POST http://localhost:4567/api/cron/jobs/:id/toggle
|
|
820
|
+
|
|
821
|
+
# View execution history
|
|
822
|
+
curl http://localhost:4567/api/cron/jobs/:id/executions
|
|
823
|
+
```
|
|
824
|
+
|
|
825
|
+
---
|
|
826
|
+
|
|
827
|
+
### Adapter Registry
|
|
828
|
+
|
|
829
|
+
Install community agent adapters from npm to add new backends to Campfire. Adapters are npm packages with a `campfireAdapter` field in their `package.json`.
|
|
830
|
+
|
|
831
|
+
> **Related:** you can also run [MetaHarness](https://github.com/ruvnet/metaharness)-generated agent harnesses inside Campfire sessions — their MCP servers attach at runtime and their tool calls go through Campfire's permission-voting UI. See [docs/integrations/metaharness.md](docs/integrations/metaharness.md).
|
|
832
|
+
|
|
833
|
+
**Installing an adapter:**
|
|
834
|
+
|
|
835
|
+
```bash
|
|
836
|
+
# Via CLI
|
|
837
|
+
the-campfire install-adapter @campfire/example-adapter
|
|
838
|
+
|
|
839
|
+
# Via API
|
|
840
|
+
curl -X POST http://localhost:4567/api/adapters/install \
|
|
841
|
+
-H "Content-Type: application/json" \
|
|
842
|
+
-d '{"npmPackage": "@campfire/example-adapter"}'
|
|
843
|
+
```
|
|
844
|
+
|
|
845
|
+
Once installed, the adapter appears as a new backend option when creating sessions.
|
|
846
|
+
|
|
847
|
+
**Managing adapters in the UI:**
|
|
848
|
+
|
|
849
|
+
1. Navigate to the **Adapters** page from the sidebar
|
|
850
|
+
2. View installed adapters with their metadata (name, version, protocol, models)
|
|
851
|
+
3. Install new adapters by entering the npm package name
|
|
852
|
+
4. Uninstall adapters with the remove button
|
|
853
|
+
|
|
854
|
+
**Adapter metadata:**
|
|
855
|
+
|
|
856
|
+
Each adapter's `package.json` must include:
|
|
857
|
+
|
|
858
|
+
```json
|
|
859
|
+
{
|
|
860
|
+
"campfireAdapter": {
|
|
861
|
+
"name": "my-agent",
|
|
862
|
+
"displayName": "My Agent",
|
|
863
|
+
"binaryName": "my-agent-cli",
|
|
864
|
+
"protocol": "stdio",
|
|
865
|
+
"models": [
|
|
866
|
+
{ "value": "model-v1", "label": "Model V1" }
|
|
867
|
+
],
|
|
868
|
+
"modes": [
|
|
869
|
+
{ "value": "default", "label": "Default" }
|
|
870
|
+
]
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
**Writing your own adapter:**
|
|
876
|
+
|
|
877
|
+
See [`web/server/ADAPTERS.md`](web/server/ADAPTERS.md) for a step-by-step guide. Adapters implement the `AgentAdapter` interface with methods for sending/receiving messages, session metadata, and disconnection handling.
|
|
878
|
+
|
|
879
|
+
```bash
|
|
880
|
+
# List installed adapters
|
|
881
|
+
curl http://localhost:4567/api/adapters
|
|
882
|
+
|
|
883
|
+
# Uninstall
|
|
884
|
+
curl -X DELETE http://localhost:4567/api/adapters/my-agent
|
|
885
|
+
```
|
|
886
|
+
|
|
887
|
+
---
|
|
888
|
+
|
|
889
|
+
### Cost Dashboard
|
|
890
|
+
|
|
891
|
+
Every session tracks API costs in real time. The cost is displayed in the top bar during a session and in the session details panel.
|
|
892
|
+
|
|
893
|
+
**What's tracked:**
|
|
894
|
+
|
|
895
|
+
- Total cost in USD per session
|
|
896
|
+
- Number of turns (back-and-forth exchanges)
|
|
897
|
+
- Context usage percentage (how much of the context window is used)
|
|
898
|
+
- Lines added and removed
|
|
899
|
+
- Session duration
|
|
900
|
+
|
|
901
|
+
**Shareable cost cards:**
|
|
902
|
+
|
|
903
|
+
When a session completes, a cost card is generated as a downloadable PNG image containing the session name, cost, duration, turns, model, and backend type — with Campfire branding. Share these cards to show off your results.
|
|
904
|
+
|
|
905
|
+
**Cost information in the UI:**
|
|
906
|
+
|
|
907
|
+
- **Top bar** — live cost ticker during active sessions
|
|
908
|
+
- **Task panel** — detailed stats (cost, turns, context %, lines changed, duration)
|
|
909
|
+
- **Gallery cards** — cost displayed on each published session
|
|
910
|
+
|
|
911
|
+
---
|
|
912
|
+
|
|
913
|
+
### Environment Profiles
|
|
914
|
+
|
|
915
|
+
Save named sets of environment variables and inject them into agent sessions. This is useful for managing API keys, database URLs, and other secrets across different projects.
|
|
916
|
+
|
|
917
|
+
**How to use:**
|
|
918
|
+
|
|
919
|
+
1. Navigate to the **Environments** page from the sidebar
|
|
920
|
+
2. Click **Create Profile**
|
|
921
|
+
3. Enter a name (e.g. "Production", "Staging")
|
|
922
|
+
4. Add key-value pairs for your environment variables
|
|
923
|
+
5. Click **Save**
|
|
924
|
+
|
|
925
|
+
When creating a session, select an environment profile from the dropdown. All variables from that profile are injected into the agent's environment.
|
|
926
|
+
|
|
927
|
+
**Profile structure:**
|
|
928
|
+
|
|
929
|
+
```json
|
|
930
|
+
{
|
|
931
|
+
"name": "Production",
|
|
932
|
+
"slug": "production",
|
|
933
|
+
"variables": {
|
|
934
|
+
"ANTHROPIC_API_KEY": "sk-ant-...",
|
|
935
|
+
"DATABASE_URL": "postgres://prod-host/db",
|
|
936
|
+
"REDIS_URL": "redis://prod-redis:6379"
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
```
|
|
940
|
+
|
|
941
|
+
Profiles are stored as individual JSON files in `~/.campfire/envs/`.
|
|
942
|
+
|
|
943
|
+
```bash
|
|
944
|
+
# List profiles
|
|
945
|
+
curl http://localhost:4567/api/envs
|
|
946
|
+
|
|
947
|
+
# Create a profile
|
|
948
|
+
curl -X POST http://localhost:4567/api/envs \
|
|
949
|
+
-H "Content-Type: application/json" \
|
|
950
|
+
-d '{
|
|
951
|
+
"name": "Staging",
|
|
952
|
+
"variables": {
|
|
953
|
+
"API_KEY": "sk-staging-...",
|
|
954
|
+
"DEBUG": "true"
|
|
955
|
+
}
|
|
956
|
+
}'
|
|
957
|
+
|
|
958
|
+
# Update a profile
|
|
959
|
+
curl -X PUT http://localhost:4567/api/envs/staging \
|
|
960
|
+
-H "Content-Type: application/json" \
|
|
961
|
+
-d '{"variables": {"API_KEY": "sk-new-key", "DEBUG": "false"}}'
|
|
962
|
+
|
|
963
|
+
# Delete a profile
|
|
964
|
+
curl -X DELETE http://localhost:4567/api/envs/staging
|
|
965
|
+
```
|
|
966
|
+
|
|
967
|
+
---
|
|
968
|
+
|
|
969
|
+
### Git Integration
|
|
970
|
+
|
|
971
|
+
Campfire tracks git state for every session and provides tools for branch and worktree management.
|
|
972
|
+
|
|
973
|
+
**What's tracked per session:**
|
|
974
|
+
|
|
975
|
+
- Current branch name
|
|
976
|
+
- Ahead/behind counts relative to the remote
|
|
977
|
+
- Whether the session is in a worktree
|
|
978
|
+
- Total lines added and removed (from tool calls)
|
|
979
|
+
- Repository root path
|
|
980
|
+
|
|
981
|
+
This information is displayed in the sidebar next to each session and updated in real time.
|
|
982
|
+
|
|
983
|
+
**Worktrees:**
|
|
984
|
+
|
|
985
|
+
Worktrees let you run multiple sessions on different branches without switching branches in your main repo. Each worktree is a separate checkout of your repository.
|
|
986
|
+
|
|
987
|
+
When creating a session with "Use worktree" enabled:
|
|
988
|
+
1. A new worktree is created for the selected branch
|
|
989
|
+
2. The session runs in the worktree directory
|
|
990
|
+
3. A `CLAUDE.md` file is injected with guardrails (e.g. "Stay on this branch")
|
|
991
|
+
4. When the session is deleted, the worktree is cleaned up if there are no uncommitted changes
|
|
992
|
+
|
|
993
|
+
**GitHub PR status:**
|
|
994
|
+
|
|
995
|
+
If the `gh` CLI is installed and authenticated, Campfire polls for PR metadata on the session's branch:
|
|
996
|
+
|
|
997
|
+
- PR title, number, state (open/closed/merged)
|
|
998
|
+
- Draft status
|
|
999
|
+
- Review decision (approved/changes requested/pending)
|
|
1000
|
+
- CI check status (passing/failing/pending)
|
|
1001
|
+
- Review thread counts (resolved/unresolved)
|
|
1002
|
+
|
|
1003
|
+
PR status is displayed in the task panel and updates automatically.
|
|
1004
|
+
|
|
1005
|
+
```bash
|
|
1006
|
+
# Get repository info
|
|
1007
|
+
curl "http://localhost:4567/api/git/repo-info?path=/home/user/project"
|
|
1008
|
+
|
|
1009
|
+
# List branches
|
|
1010
|
+
curl "http://localhost:4567/api/git/branches?repoRoot=/home/user/project"
|
|
1011
|
+
|
|
1012
|
+
# Create a worktree
|
|
1013
|
+
curl -X POST http://localhost:4567/api/git/worktree \
|
|
1014
|
+
-H "Content-Type: application/json" \
|
|
1015
|
+
-d '{
|
|
1016
|
+
"repoRoot": "/home/user/project",
|
|
1017
|
+
"branch": "feature/new-feature",
|
|
1018
|
+
"createBranch": true
|
|
1019
|
+
}'
|
|
1020
|
+
|
|
1021
|
+
# Fetch and pull
|
|
1022
|
+
curl -X POST http://localhost:4567/api/git/fetch \
|
|
1023
|
+
-H "Content-Type: application/json" \
|
|
1024
|
+
-d '{"repoRoot": "/home/user/project"}'
|
|
1025
|
+
```
|
|
1026
|
+
|
|
1027
|
+
---
|
|
1028
|
+
|
|
1029
|
+
### Embedded Terminal
|
|
1030
|
+
|
|
1031
|
+
A full PTY terminal is available alongside your sessions. Use it for git operations, running tests, or any other command-line tasks without leaving Campfire.
|
|
1032
|
+
|
|
1033
|
+
**How to use:**
|
|
1034
|
+
|
|
1035
|
+
1. Click **Terminal** in the sidebar footer
|
|
1036
|
+
2. A terminal spawns in the configured working directory
|
|
1037
|
+
3. Type commands as you would in any terminal
|
|
1038
|
+
4. The terminal supports full ANSI colors, cursor movement, and resize
|
|
1039
|
+
|
|
1040
|
+
The terminal connects via WebSocket (`/ws/terminal/:id`) and supports all standard terminal operations.
|
|
1041
|
+
|
|
1042
|
+
```bash
|
|
1043
|
+
# Spawn a terminal
|
|
1044
|
+
curl -X POST http://localhost:4567/api/terminal/spawn \
|
|
1045
|
+
-H "Content-Type: application/json" \
|
|
1046
|
+
-d '{"cwd": "/home/user/project", "cols": 120, "rows": 40}'
|
|
1047
|
+
|
|
1048
|
+
# Kill the terminal
|
|
1049
|
+
curl -X POST http://localhost:4567/api/terminal/kill
|
|
1050
|
+
```
|
|
1051
|
+
|
|
1052
|
+
---
|
|
1053
|
+
|
|
1054
|
+
### Protocol Recording
|
|
1055
|
+
|
|
1056
|
+
The server automatically records all raw protocol messages to JSONL files. This captures the exact bytes exchanged between the agent CLI and the server, and between the server and browser clients.
|
|
1057
|
+
|
|
1058
|
+
**Configuration:**
|
|
1059
|
+
|
|
1060
|
+
| Variable | Default | Description |
|
|
1061
|
+
|----------|---------|-------------|
|
|
1062
|
+
| `CAMPFIRE_RECORD` | `1` | Set to `0` or `false` to disable |
|
|
1063
|
+
| `CAMPFIRE_RECORDINGS_DIR` | `~/.campfire/recordings` | Output directory |
|
|
1064
|
+
| `CAMPFIRE_RECORDINGS_MAX_LINES` | `100000` | Auto-rotation threshold |
|
|
1065
|
+
|
|
1066
|
+
**File format:**
|
|
1067
|
+
|
|
1068
|
+
File naming: `{sessionId}_{backendType}_{ISO-timestamp}_{randomSuffix}.jsonl`
|
|
1069
|
+
|
|
1070
|
+
```jsonl
|
|
1071
|
+
{"ts":1771153996875,"dir":"in","raw":"{\"type\":\"system\",\"subtype\":\"init\",...}","ch":"cli"}
|
|
1072
|
+
{"ts":1771153996900,"dir":"out","raw":"{\"type\":\"session_init\",...}","ch":"browser"}
|
|
1073
|
+
```
|
|
1074
|
+
|
|
1075
|
+
Recordings are useful for debugging protocol issues, building replay-based tests, and understanding how agents communicate.
|
|
1076
|
+
|
|
1077
|
+
---
|
|
1078
|
+
|
|
1079
|
+
### Docker Containers
|
|
1080
|
+
|
|
1081
|
+
Optionally sandbox sessions inside Docker containers for isolation. When enabled, the agent runs inside a container with the working directory mounted at `/workspace`.
|
|
1082
|
+
|
|
1083
|
+
**How it works:**
|
|
1084
|
+
|
|
1085
|
+
1. When creating a session, click the **Container** toggle in the toolbar
|
|
1086
|
+
2. Choose a Docker image (default: `campfire-dev:latest`) in the text field that appears
|
|
1087
|
+
3. Click **Create** — a progress overlay appears showing each step
|
|
1088
|
+
4. The session runs inside the container with authentication automatically seeded
|
|
1089
|
+
|
|
1090
|
+
**Creation progress overlay:**
|
|
1091
|
+
|
|
1092
|
+
When launching a container session, a step-by-step progress modal appears:
|
|
1093
|
+
|
|
1094
|
+
| Step | What happens |
|
|
1095
|
+
|------|-------------|
|
|
1096
|
+
| Checking image | Verifies if the Docker image exists locally |
|
|
1097
|
+
| Pulling image | Downloads the image if not found (with progress bar showing layer download %) |
|
|
1098
|
+
| Creating container | Creates and starts the Docker container with mounted volumes |
|
|
1099
|
+
| Seeding authentication | Copies `~/.claude/` (for Claude Code) or `~/.codex/` (for Codex) into the container |
|
|
1100
|
+
| Launching agent | Starts the agent process inside the container |
|
|
1101
|
+
|
|
1102
|
+
If any step fails, the overlay shows an error with **Retry** and **Cancel** buttons.
|
|
1103
|
+
|
|
1104
|
+
**Authentication seeding:**
|
|
1105
|
+
|
|
1106
|
+
Campfire automatically copies authentication credentials into containers so agents can authenticate without manual setup:
|
|
1107
|
+
|
|
1108
|
+
- **Claude Code sessions**: `~/.claude/` is copied to `/root/.claude/` inside the container
|
|
1109
|
+
- **Codex sessions**: `~/.codex/` is copied to `/root/.codex/` inside the container
|
|
1110
|
+
|
|
1111
|
+
**Image pull management:**
|
|
1112
|
+
|
|
1113
|
+
Images are checked locally before pulling. Recently pulled images are cached for 30 minutes to skip redundant checks. During a pull, the progress overlay shows per-layer download progress with a percentage bar.
|
|
1114
|
+
|
|
1115
|
+
**Git info inside containers:**
|
|
1116
|
+
|
|
1117
|
+
Campfire resolves git information (branch, ahead/behind, worktree status) from inside the container via `docker exec`, so sidebar session metadata stays accurate even for containerized sessions.
|
|
1118
|
+
|
|
1119
|
+
**SSE creation endpoint:**
|
|
1120
|
+
|
|
1121
|
+
Container session creation uses Server-Sent Events (SSE) for real-time progress reporting:
|
|
1122
|
+
|
|
1123
|
+
```bash
|
|
1124
|
+
# Create a container session with progress (returns text/event-stream)
|
|
1125
|
+
curl -N -X POST http://localhost:4567/api/sessions/create-with-progress \
|
|
1126
|
+
-H "Content-Type: application/json" \
|
|
1127
|
+
-d '{
|
|
1128
|
+
"backend": "claude",
|
|
1129
|
+
"model": "claude-sonnet-4-5-20250929",
|
|
1130
|
+
"cwd": "/home/user/project",
|
|
1131
|
+
"container": {"image": "campfire-dev:latest"}
|
|
1132
|
+
}'
|
|
1133
|
+
# event: step
|
|
1134
|
+
# data: {"step":"checking_image","message":"Checking image campfire-dev:latest..."}
|
|
1135
|
+
# event: step
|
|
1136
|
+
# data: {"step":"pulling_image","message":"Pulling campfire-dev:latest...","percent":45}
|
|
1137
|
+
# event: done
|
|
1138
|
+
# data: {"sessionId":"abc-123","session":{...}}
|
|
1139
|
+
```
|
|
1140
|
+
|
|
1141
|
+
**Requirements:**
|
|
1142
|
+
|
|
1143
|
+
- Docker must be installed and running on the host
|
|
1144
|
+
- The Docker socket must be accessible to the Campfire process
|
|
1145
|
+
|
|
1146
|
+
```bash
|
|
1147
|
+
# Check Docker availability
|
|
1148
|
+
curl http://localhost:4567/api/containers/status
|
|
1149
|
+
# → {"available": true, "version": "24.0.7"}
|
|
1150
|
+
|
|
1151
|
+
# List available images
|
|
1152
|
+
curl http://localhost:4567/api/containers/images
|
|
1153
|
+
```
|
|
1154
|
+
|
|
1155
|
+
---
|
|
1156
|
+
|
|
1157
|
+
### PWA & Mobile
|
|
1158
|
+
|
|
1159
|
+
Campfire is a Progressive Web App (PWA) — installable on mobile devices with push notifications for permission requests.
|
|
1160
|
+
|
|
1161
|
+
**To install on mobile:**
|
|
1162
|
+
|
|
1163
|
+
1. Open Campfire in your mobile browser
|
|
1164
|
+
2. Tap "Add to Home Screen" (or the browser's install prompt)
|
|
1165
|
+
3. The app launches in standalone mode with its own window
|
|
1166
|
+
|
|
1167
|
+
**Push notifications:**
|
|
1168
|
+
|
|
1169
|
+
When a permission request arrives and you're not actively viewing the tab, a push notification appears with the tool name and action buttons to allow or deny directly from the notification.
|
|
1170
|
+
|
|
1171
|
+
**Touch optimization:**
|
|
1172
|
+
|
|
1173
|
+
Permission buttons are enlarged on mobile (`min-height: 36px`) for easy tap targets. Tool blocks default to collapsed on small screens.
|
|
1174
|
+
|
|
1175
|
+
---
|
|
1176
|
+
|
|
1177
|
+
### Auto-Naming
|
|
1178
|
+
|
|
1179
|
+
Sessions automatically receive descriptive names after their first turn completes. This uses [OpenRouter](https://openrouter.ai/) to generate a short title based on the user's first message.
|
|
1180
|
+
|
|
1181
|
+
**Setup:**
|
|
1182
|
+
|
|
1183
|
+
1. Go to **Settings** in the sidebar
|
|
1184
|
+
2. Enter your OpenRouter API key
|
|
1185
|
+
3. Optionally choose a model (default: `openrouter/free`)
|
|
1186
|
+
|
|
1187
|
+
Auto-naming only runs if:
|
|
1188
|
+
- An OpenRouter API key is configured
|
|
1189
|
+
- The session doesn't already have a manual name
|
|
1190
|
+
- A first turn has completed
|
|
1191
|
+
|
|
1192
|
+
Manual renames always take precedence. You can rename any session by clicking its name in the sidebar.
|
|
1193
|
+
|
|
1194
|
+
---
|
|
1195
|
+
|
|
1196
|
+
### Collective Intelligence
|
|
1197
|
+
|
|
1198
|
+
When multiple agent sessions are running simultaneously, Campfire's Collective Intelligence layer lets them share knowledge, coordinate decisions, and route tasks to the best-suited agent — without changing how agents communicate with each other.
|
|
1199
|
+
|
|
1200
|
+
It operates as a non-blocking observer: no agent message is ever delayed by it, and no existing behavior changes if the feature is unused.
|
|
1201
|
+
|
|
1202
|
+
**Four layers:**
|
|
1203
|
+
|
|
1204
|
+
| Layer | What it does |
|
|
1205
|
+
|-------|-------------|
|
|
1206
|
+
| **Semantic Memory** | Stores observations, decisions, and patterns from each agent session as vector embeddings in a local LanceDB database. Any session can query this shared knowledge base for relevant context before starting a task. |
|
|
1207
|
+
| **Deliberation Engine** | Proposes structured decisions across sessions (e.g. "which approach should we use?"). Connected viewers and agents can respond; the engine aggregates votes with role-weighted majority and resolves to `approved`, `rejected`, or `synthesized`. |
|
|
1208
|
+
| **Capability Discovery** | Each session self-reports its strengths, available tools, and context usage. When routing a task, the engine scores all connected sessions and picks the best fit. Confidence probes can be sent to agents in real time to verify self-reported capabilities. |
|
|
1209
|
+
| **Shared Context Stream** | A live think-aloud stream where agents can inject thoughts and observations. The engine detects semantic links (agrees, disagrees, builds on, contradicts) between fragments and tracks consensus scores across the session group. |
|
|
1210
|
+
|
|
1211
|
+
**How it works end-to-end:**
|
|
1212
|
+
|
|
1213
|
+
1. When an agent produces output, the CI layer silently extracts observations and stores them as `MemoryFragment` records (with vector embeddings if an embedding provider is configured).
|
|
1214
|
+
2. When a user sends a message, the CI layer queries the memory store for relevant context and prepends it to the message — giving agents access to knowledge from past sessions.
|
|
1215
|
+
3. Browser clients can send `memory_query`, `memory_store`, `deliberation_respond`, `route_task`, and `inject_thought` messages over WebSocket. The server handles them and broadcasts results back to all connected viewers.
|
|
1216
|
+
4. Sessions consolidate their episodic memories into distilled `ConsolidatedKnowledge` entries when they end.
|
|
1217
|
+
|
|
1218
|
+
**Embedding providers:**
|
|
1219
|
+
|
|
1220
|
+
Vector search requires an embedding provider. Configure one in **Settings**:
|
|
1221
|
+
|
|
1222
|
+
| Provider | Model | Dimensions | Notes |
|
|
1223
|
+
|----------|-------|-----------|-------|
|
|
1224
|
+
| `openai` | `text-embedding-3-small` (default) | 1536 | Requires OpenAI API key |
|
|
1225
|
+
| `ollama` | `nomic-embed-text` (default) | 768 | Requires local Ollama instance |
|
|
1226
|
+
| `none` | — | — | Fragments stored without embeddings; metadata-only search |
|
|
1227
|
+
|
|
1228
|
+
Without an embedding provider, memory still works — queries fall back to a full scan filtered by session, repo root, tags, and type.
|
|
1229
|
+
|
|
1230
|
+
**Storage:**
|
|
1231
|
+
|
|
1232
|
+
All CI data is stored locally under `~/.campfire/memory/lancedb/` — no external service required.
|
|
1233
|
+
|
|
1234
|
+
| Table | Purpose |
|
|
1235
|
+
|-------|---------|
|
|
1236
|
+
| `fragments.lance` | Episodic memory fragments with embeddings |
|
|
1237
|
+
| `consolidated.lance` | Distilled knowledge synthesized from sessions |
|
|
1238
|
+
|
|
1239
|
+
Capability data is stored as JSON in `~/.campfire/capabilities/` and learning history is appended to `~/.campfire/capability-learning.jsonl`.
|
|
1240
|
+
|
|
1241
|
+
**Quick setup:**
|
|
1242
|
+
|
|
1243
|
+
```bash
|
|
1244
|
+
# 1. Configure an embedding provider in Settings (optional but recommended)
|
|
1245
|
+
# OpenAI: enter your API key, set provider = "openai"
|
|
1246
|
+
# Ollama: ensure ollama is running, set provider = "ollama"
|
|
1247
|
+
|
|
1248
|
+
# 2. Start multiple sessions — CI activates automatically
|
|
1249
|
+
|
|
1250
|
+
# 3. Query shared memory via the REST API
|
|
1251
|
+
curl "http://localhost:4567/api/sessions/:id/memory/query?q=authentication+pattern&limit=5"
|
|
1252
|
+
|
|
1253
|
+
# 4. Route a task to the best agent
|
|
1254
|
+
curl -X POST http://localhost:4567/api/sessions/route-task \
|
|
1255
|
+
-H "Content-Type: application/json" \
|
|
1256
|
+
-d '{"taskDescription": "Refactor the TypeScript authentication module"}'
|
|
1257
|
+
```
|
|
1258
|
+
|
|
1259
|
+
**REST API summary:**
|
|
1260
|
+
|
|
1261
|
+
| Group | Endpoints |
|
|
1262
|
+
|-------|-----------|
|
|
1263
|
+
| Memory | `GET/POST /sessions/:id/memory`, `GET /sessions/:id/memory/query`, `POST /sessions/:id/memory/consolidate`, `GET /memory/global` |
|
|
1264
|
+
| Deliberation | `GET /sessions/:id/deliberations`, `GET /sessions/:id/deliberations/:proposalId`, `POST .../respond`, `POST .../resolve` |
|
|
1265
|
+
| Capabilities | `POST /sessions/route-task`, `GET /capabilities`, `GET /capabilities/history`, `POST /capabilities/feedback` |
|
|
1266
|
+
| Shared Context | `GET /sessions/:id/context/stream`, `GET /sessions/:id/context/consensus`, `GET /sessions/:id/context/thread/:fragmentId` |
|
|
1267
|
+
|
|
1268
|
+
Architecture details are documented in [`CLAUDE.md`](CLAUDE.md). A design study for the next iteration of the memory layer lives at [`docs/design/semantic-memory-v2.md`](docs/design/semantic-memory-v2.md).
|
|
1269
|
+
|
|
1270
|
+
---
|
|
1271
|
+
|
|
1272
|
+
### Copy Output Button
|
|
1273
|
+
|
|
1274
|
+
Hover over any user or assistant message to reveal a copy button. Copies the full text content to your clipboard with a checkmark confirmation animation. Uses the Clipboard API with a textarea fallback for insecure contexts (e.g. HTTP without TLS).
|
|
1275
|
+
|
|
1276
|
+
### Voice Input
|
|
1277
|
+
|
|
1278
|
+
Dictate messages using the Web Speech API. Click the microphone button in the composer or press **Ctrl+Shift+M** (Cmd+Shift+M on macOS) to toggle voice input. Features include:
|
|
1279
|
+
|
|
1280
|
+
- Real-time interim text display while speaking
|
|
1281
|
+
- Auto-restart on silence for continuous dictation
|
|
1282
|
+
- Pulsing red indicator when active
|
|
1283
|
+
- Transcript is appended to the composer textarea so you can edit before sending
|
|
1284
|
+
|
|
1285
|
+
> **Note:** Requires a browser that supports the Web Speech API (Chrome, Edge, Safari).
|
|
1286
|
+
|
|
1287
|
+
### Workspace File Tree
|
|
1288
|
+
|
|
1289
|
+
A collapsible file tree in the right-side TaskPanel showing the session's working directory. Features include:
|
|
1290
|
+
|
|
1291
|
+
- **Lazy-loading** — subdirectories load on expand, keeping the initial render fast
|
|
1292
|
+
- **File preview** — click a file to see its contents inline (up to 10KB)
|
|
1293
|
+
- **Hidden files toggle** — show/hide dotfiles and system directories
|
|
1294
|
+
- **Refresh** — re-scan the directory tree on demand
|
|
1295
|
+
|
|
1296
|
+
Powered by the `GET /api/fs/list-entries` endpoint which filters out `.git`, `node_modules`, and `__pycache__` by default.
|
|
1297
|
+
|
|
1298
|
+
### Mermaid Diagram Rendering
|
|
1299
|
+
|
|
1300
|
+
When an assistant returns a fenced code block with the `mermaid` language tag, Campfire renders it as an interactive SVG diagram instead of raw text. Supports all Mermaid diagram types: flowcharts, sequence diagrams, class diagrams, state diagrams, ER diagrams, Gantt charts, and more.
|
|
1301
|
+
|
|
1302
|
+
- Toggle between **diagram** and **source code** views
|
|
1303
|
+
- Error handling with automatic fallback to source display
|
|
1304
|
+
- Lazy-loaded via `React.lazy()` to avoid impacting initial bundle size
|
|
1305
|
+
|
|
1306
|
+
### Orchestrator Pipelines
|
|
1307
|
+
|
|
1308
|
+
A multi-stage automation engine for chaining sequential AI sessions into workflows. Access it at `#/orchestrator` in the sidebar.
|
|
1309
|
+
|
|
1310
|
+
**How it works:**
|
|
1311
|
+
|
|
1312
|
+
1. **Create a pipeline** — define a name, working directory, and a series of stages
|
|
1313
|
+
2. **Each stage** has a prompt, backend (Claude/Codex), and model selection
|
|
1314
|
+
3. **Run the pipeline** — stages execute sequentially, each creating a real agent session
|
|
1315
|
+
4. **Context passing** — output from one stage feeds into the next via `{{previous_output}}`
|
|
1316
|
+
5. **Monitor** — real-time status timeline with per-stage duration and cost tracking
|
|
1317
|
+
|
|
1318
|
+
**Example use cases:**
|
|
1319
|
+
- Analyze → Review → Write Tests → Create PR
|
|
1320
|
+
- Scaffold → Implement → Lint → Deploy
|
|
1321
|
+
- Research → Plan → Execute → Verify
|
|
1322
|
+
|
|
1323
|
+
**REST API:**
|
|
1324
|
+
|
|
1325
|
+
| Method | Endpoint | Purpose |
|
|
1326
|
+
|--------|----------|---------|
|
|
1327
|
+
| `GET` | `/api/orchestrator/pipelines` | List all pipelines |
|
|
1328
|
+
| `POST` | `/api/orchestrator/pipelines` | Create a new pipeline |
|
|
1329
|
+
| `PUT` | `/api/orchestrator/pipelines/:id` | Update a pipeline |
|
|
1330
|
+
| `DELETE` | `/api/orchestrator/pipelines/:id` | Delete a pipeline |
|
|
1331
|
+
| `POST` | `/api/orchestrator/pipelines/:id/run` | Execute a pipeline |
|
|
1332
|
+
| `GET` | `/api/orchestrator/runs` | List all runs |
|
|
1333
|
+
| `GET` | `/api/orchestrator/runs/:id` | Get run status and details |
|
|
1334
|
+
| `POST` | `/api/orchestrator/runs/:id/cancel` | Cancel a running pipeline |
|
|
1335
|
+
|
|
1336
|
+
Pipeline and run data is persisted to `~/.campfire/orchestrator/`.
|
|
1337
|
+
|
|
1338
|
+
### Multi-Agent Orchestration
|
|
1339
|
+
|
|
1340
|
+
Campfire can now coordinate agents as a group instead of only running independent sessions. The orchestration layer lets lead agents delegate one-turn subtasks to other backends, runs parallel "agent races" in isolated worktrees, and detects project environment integrations before a session starts.
|
|
1341
|
+
|
|
1342
|
+
**Agent-to-agent delegation:**
|
|
1343
|
+
|
|
1344
|
+
- Lead Claude Code and Codex sessions can receive an internal `campfire_agents` MCP server.
|
|
1345
|
+
- The MCP server exposes `ask_codex`, `ask_goose`, `ask_aider`, `ask_openhands`, and `ask_claude` tools, excluding the lead session's own backend.
|
|
1346
|
+
- Each `ask_*` tool launches a temporary sub-session in the same working directory, injects the subtask prompt, waits for the result, collects changed files and cost, then returns the result to the lead agent.
|
|
1347
|
+
- Sub-agent progress is streamed back to the parent session through `sub_agent_update` events and appears in the session activity UI.
|
|
1348
|
+
- Set `CAMPFIRE_ENABLE_AGENT_MCP=0` to disable automatic agent MCP injection.
|
|
1349
|
+
|
|
1350
|
+
**Agent races:**
|
|
1351
|
+
|
|
1352
|
+
Open **Agent Races** at `#/races` from the sidebar to run the same prompt across multiple backends in parallel.
|
|
1353
|
+
|
|
1354
|
+
1. Choose a repository root and task prompt.
|
|
1355
|
+
2. Select at least two backends. The UI currently offers Claude, Codex, Goose, Aider, and OpenHands; the REST API also accepts OpenClaw and OpenCode.
|
|
1356
|
+
3. Campfire creates one git worktree and branch per backend, launches a session in each worktree, and sends the same prompt to every agent.
|
|
1357
|
+
4. The comparison view shows status, wall-clock time, cost, changed file count, line changes, output summary, and a loadable diff for each entry.
|
|
1358
|
+
5. Click **Merge** on the winning entry to merge its race branch into the repository root and clean up the other race worktrees.
|
|
1359
|
+
|
|
1360
|
+
**Cost cascade mode:** check **"Cost cascade — run backends in order, stop at first success"** to run the selected backends *sequentially* in the order you listed them (put the cheapest first) instead of in parallel. The race stops at the first entry that completes with a non-empty change set; failures, timeouts, and empty patches escalate to the next backend, and never-started entries are marked `skipped`. Pass `cascade: true` in the REST payload for the same behavior.
|
|
1361
|
+
|
|
1362
|
+
Race results are saved to `~/.campfire/races/` so completed comparisons remain available after a server restart.
|
|
1363
|
+
|
|
1364
|
+
**Environment detection:**
|
|
1365
|
+
|
|
1366
|
+
Every launched session scans its working directory for project signals such as Supabase, Stripe, Vercel/Next.js, Prisma, Docker, Fly.io, GitHub Actions, and database configuration. Detected rules appear in the TaskPanel environment card with required environment variables marked as configured or missing. For Claude and Codex sessions, detected MCP servers are injected automatically unless `CAMPFIRE_AUTO_INJECT_ENV_MCP=0` is set.
|
|
1367
|
+
|
|
1368
|
+
**MCP injection policy:** auto-injected servers are governed by a default-deny policy (`web/server/mcp-policy.ts`) — only servers that exactly match Campfire's curated environment-rules catalog and pass a static scan (shell metacharacters, inline-eval flags, plaintext `http://` URLs to non-local hosts) are admitted; everything else is blocked and logged. Servers you add explicitly through the MCP panel are never blocked, but the same scan runs in warn-only mode for visibility. Set `CAMPFIRE_MCP_AUTO_INJECT_POLICY=permissive` to restore scan-free auto-injection (findings are still logged).
|
|
1369
|
+
|
|
1370
|
+
**REST API:**
|
|
1371
|
+
|
|
1372
|
+
| Method | Endpoint | Purpose |
|
|
1373
|
+
|--------|----------|---------|
|
|
1374
|
+
| `POST` | `/api/races` | Start a race with `{ prompt, repoRoot, backends, baseBranch?, modelByBackend?, cascade? }` |
|
|
1375
|
+
| `GET` | `/api/races` | List saved races |
|
|
1376
|
+
| `GET` | `/api/races/:id` | Get race status and entries |
|
|
1377
|
+
| `GET` | `/api/races/:id/entries/:entryId/diff` | Load a race entry's git diff |
|
|
1378
|
+
| `POST` | `/api/races/:id/pick` | Merge the winning entry by `sessionId` |
|
|
1379
|
+
| `POST` | `/api/races/:id/cancel` | Cancel a running race and clean up worktrees |
|
|
1380
|
+
| `DELETE` | `/api/races/:id` | Delete a saved race record |
|
|
1381
|
+
|
|
1382
|
+
### Message Queue
|
|
1383
|
+
|
|
1384
|
+
When the agent is busy processing a request (status "running"), new messages are queued instead of being dropped. Features include:
|
|
1385
|
+
|
|
1386
|
+
- **Queue indicator** — a badge shows the number of queued messages with a clear button
|
|
1387
|
+
- **Auto-send** — queued messages are sent one at a time when the agent becomes idle
|
|
1388
|
+
- **System notification** — a "Queued: ..." message appears in the chat timeline so you know the message was captured
|
|
1389
|
+
- Works seamlessly with all backends (Claude Code, Codex, Goose, Aider, OpenHands, OpenClaw, OpenCode)
|
|
1390
|
+
|
|
1391
|
+
### Kanban Task Board
|
|
1392
|
+
|
|
1393
|
+
A full-page Kanban board at `#/kanban` (also accessible via the sidebar or the "board" button in the TaskPanel) that visualizes tasks extracted from agent tool calls (`TaskCreate`, `TaskUpdate`, `TodoWrite`).
|
|
1394
|
+
|
|
1395
|
+
**Three columns:**
|
|
1396
|
+
- **To Do** — pending tasks
|
|
1397
|
+
- **In Progress** — tasks the agent is actively working on (with animated pulse indicator)
|
|
1398
|
+
- **Done** — completed tasks
|
|
1399
|
+
|
|
1400
|
+
**Task cards show:**
|
|
1401
|
+
- Subject and description
|
|
1402
|
+
- Owner (agent name)
|
|
1403
|
+
- Active form (what the agent is currently doing)
|
|
1404
|
+
- Blocked status with warning badge
|
|
1405
|
+
- Task ID for reference
|
|
1406
|
+
|
|
1407
|
+
A progress bar at the top shows overall completion percentage.
|
|
1408
|
+
|
|
1409
|
+
---
|
|
1410
|
+
|
|
1411
|
+
### Authentication
|
|
1412
|
+
|
|
1413
|
+
Token-based authentication to protect your Campfire instance. When enabled, all API routes and WebSocket connections require a valid session token.
|
|
1414
|
+
|
|
1415
|
+
**Setup:**
|
|
1416
|
+
|
|
1417
|
+
```bash
|
|
1418
|
+
# Set a password via environment variable
|
|
1419
|
+
CAMPFIRE_PASSWORD=your-secret bunx the-campfire
|
|
1420
|
+
|
|
1421
|
+
# Or configure through the UI on first visit
|
|
1422
|
+
```
|
|
1423
|
+
|
|
1424
|
+
**Features:**
|
|
1425
|
+
- Password-based login with salted scrypt hashing (legacy unsalted SHA-256 hashes are migrated automatically on the next successful login)
|
|
1426
|
+
- 7-day rotating session tokens stored in `~/.campfire/auth.json`
|
|
1427
|
+
- Auth middleware protects all `/api/*` routes
|
|
1428
|
+
- WebSocket connections validated on upgrade
|
|
1429
|
+
- Environment variable override for headless/CI deployments
|
|
1430
|
+
|
|
1431
|
+
**API endpoints:**
|
|
1432
|
+
- `GET /api/auth/status` — Check if auth is enabled and user is logged in
|
|
1433
|
+
- `POST /api/auth/login` — Authenticate with password
|
|
1434
|
+
- `POST /api/auth/logout` — Invalidate session token
|
|
1435
|
+
- `POST /api/auth/setup` — Initial password setup
|
|
1436
|
+
- `POST /api/auth/disable` — Remove authentication
|
|
1437
|
+
|
|
1438
|
+
---
|
|
1439
|
+
|
|
1440
|
+
### Thinking Effort (Codex)
|
|
1441
|
+
|
|
1442
|
+
Control the reasoning effort level for Codex o-series models. This maps to Codex's `reasoningEffort` parameter on `thread/start` and `thread/resume` calls.
|
|
1443
|
+
|
|
1444
|
+
**Three levels:**
|
|
1445
|
+
- **Low** — Faster responses, less deliberation
|
|
1446
|
+
- **Medium** — Balanced (default)
|
|
1447
|
+
- **High** — Maximum reasoning depth
|
|
1448
|
+
|
|
1449
|
+
**Usage:** When creating a new session with the Codex backend, a segmented control appears on the Home page. Your selection persists in localStorage across page reloads.
|
|
1450
|
+
|
|
1451
|
+
---
|
|
1452
|
+
|
|
1453
|
+
### Skills & Plugins Management
|
|
1454
|
+
|
|
1455
|
+
Browse and manage Claude Code plugins and skills from a dedicated UI page at `#/skills` (accessible via the sparkle icon in the sidebar).
|
|
1456
|
+
|
|
1457
|
+
**Features:**
|
|
1458
|
+
- Lists all installed plugins from `~/.claude/plugins/installed_plugins.json`
|
|
1459
|
+
- Expandable cards showing each plugin's skills, commands, install path, version, and author
|
|
1460
|
+
- View SKILL.md content for any skill by clicking its name
|
|
1461
|
+
- Enable/disable plugins in Campfire without uninstalling them (stored in `~/.campfire/skills-config.json`)
|
|
1462
|
+
- Blocked plugin detection from `~/.claude/plugins/blocklist.json`
|
|
1463
|
+
|
|
1464
|
+
**API endpoints:**
|
|
1465
|
+
- `GET /api/skills` — List all plugins with enriched status
|
|
1466
|
+
- `GET /api/skills/:id` — Get a single plugin's details
|
|
1467
|
+
- `GET /api/skills/:id/skill/:name` — Read a skill's SKILL.md content
|
|
1468
|
+
- `GET /api/skills/:id/command/:name` — Read a command's content
|
|
1469
|
+
- `POST /api/skills/:id/toggle` — Enable/disable a plugin in Campfire
|
|
1470
|
+
|
|
1471
|
+
---
|
|
1472
|
+
|
|
1473
|
+
### Drag & Drop Upload
|
|
1474
|
+
|
|
1475
|
+
Drag image files directly onto the Composer to attach them to your message. A visual overlay with a dashed border appears when dragging over the input area, confirming the drop target.
|
|
1476
|
+
|
|
1477
|
+
**Supported:** Any image format (PNG, JPG, GIF, WebP, etc.). Images are converted to base64 and sent as attachments with your message.
|
|
1478
|
+
|
|
1479
|
+
---
|
|
1480
|
+
|
|
1481
|
+
### Session Folders
|
|
1482
|
+
|
|
1483
|
+
Organize sessions into named, color-coded folders in the sidebar.
|
|
1484
|
+
|
|
1485
|
+
**Features:**
|
|
1486
|
+
- Create folders with a name and optional color
|
|
1487
|
+
- Move sessions into folders via context menu
|
|
1488
|
+
- Collapse/expand folders (state persists in localStorage)
|
|
1489
|
+
- Remove sessions from folders
|
|
1490
|
+
- Delete empty folders
|
|
1491
|
+
|
|
1492
|
+
**Storage:** Folder data persists in `~/.campfire/session-folders.json`.
|
|
1493
|
+
|
|
1494
|
+
**API endpoints:**
|
|
1495
|
+
- `GET /api/folders` — List all folders
|
|
1496
|
+
- `POST /api/folders` — Create a folder
|
|
1497
|
+
- `PATCH /api/folders/:id` — Update folder name/color
|
|
1498
|
+
- `DELETE /api/folders/:id` — Delete a folder
|
|
1499
|
+
- `POST /api/folders/:folderId/sessions/:sessionId` — Add session to folder
|
|
1500
|
+
- `DELETE /api/folders/sessions/:sessionId` — Remove session from folder
|
|
1501
|
+
|
|
1502
|
+
---
|
|
1503
|
+
|
|
1504
|
+
### Permission Mode Selector
|
|
1505
|
+
|
|
1506
|
+
A dropdown in the Composer lets you switch between Claude Code permission modes in real-time, without restarting the session.
|
|
1507
|
+
|
|
1508
|
+
**Four modes:**
|
|
1509
|
+
| Mode | Behavior |
|
|
1510
|
+
|------|----------|
|
|
1511
|
+
| **Agent (auto-approve)** | Uses `--dangerously-skip-permissions` — all tool calls approved automatically |
|
|
1512
|
+
| **Accept Edits** | File edits approved automatically, other tools require approval |
|
|
1513
|
+
| **Ask Every Time** | Every tool call requires explicit approval |
|
|
1514
|
+
| **Plan** | Planning mode only — no code execution |
|
|
1515
|
+
|
|
1516
|
+
Switching sends a `set_permission_mode` control message to the CLI. The current mode is displayed as a badge on the mode button. Use `Shift+Tab` in the Composer as a keyboard shortcut to toggle between Plan and your previous mode.
|
|
1517
|
+
|
|
1518
|
+
---
|
|
1519
|
+
|
|
1520
|
+
### Session Pulse (Background Activity)
|
|
1521
|
+
|
|
1522
|
+
A floating widget in the bottom-right corner of the chat view that provides real-time awareness of background activity. Two tabs:
|
|
1523
|
+
|
|
1524
|
+
**Activity tab** — shows what's happening in the current session:
|
|
1525
|
+
- Background agents spawned with `run_in_background` (Claude Code)
|
|
1526
|
+
- Active tool calls with elapsed timers (all backends)
|
|
1527
|
+
- Task progress from TodoWrite/TaskCreate
|
|
1528
|
+
|
|
1529
|
+
**Sessions tab** — shows other sessions running in the background:
|
|
1530
|
+
- Which sessions are running or compacting
|
|
1531
|
+
- Pending permission counts with warning badges
|
|
1532
|
+
- Click any row to jump to that session
|
|
1533
|
+
|
|
1534
|
+
Auto-hides when all activity completes. Appears automatically when agents or sessions are active.
|
|
1535
|
+
|
|
1536
|
+
### Agent System
|
|
1537
|
+
|
|
1538
|
+
Persistent agent profiles with automated triggers. Navigate to **Config > Agents** (`#/agents`).
|
|
1539
|
+
|
|
1540
|
+
**Creating an agent:**
|
|
1541
|
+
1. Click **Create Agent**
|
|
1542
|
+
2. Fill in: name, description, backend (all 7 supported), model, permission mode, working directory
|
|
1543
|
+
3. Write a prompt template — use `{{input}}` as a placeholder for trigger input
|
|
1544
|
+
4. Select an environment profile (important for Codex — provides `OPENAI_API_KEY`)
|
|
1545
|
+
5. Optionally enable triggers: webhook or cron schedule
|
|
1546
|
+
|
|
1547
|
+
**Running an agent:**
|
|
1548
|
+
- Click the play button on any agent card
|
|
1549
|
+
- If the prompt contains `{{input}}`, a modal asks for the input value
|
|
1550
|
+
- The agent creates a new session, injects the resolved prompt, and runs autonomously
|
|
1551
|
+
- Agent sessions are named with the agent's icon (e.g., `🔬 Analyser`)
|
|
1552
|
+
|
|
1553
|
+
**Triggers:**
|
|
1554
|
+
| Trigger | How it works |
|
|
1555
|
+
|---------|-------------|
|
|
1556
|
+
| Manual | Click the play button |
|
|
1557
|
+
| Webhook | `POST /api/agents/{id}/webhook` with `{ "input": "..." }` |
|
|
1558
|
+
| Schedule | Cron expression (e.g., `0 8 * * *` for daily at 8am) |
|
|
1559
|
+
|
|
1560
|
+
**Safety:** Auto-disables after 5 consecutive failures. Overlap prevention skips execution if previous run is still alive.
|
|
1561
|
+
|
|
1562
|
+
**Import/Export:** Agents can be exported as JSON and imported on another Campfire instance.
|
|
1563
|
+
|
|
1564
|
+
### Provider Settings
|
|
1565
|
+
|
|
1566
|
+
Configure AI provider authentication tokens. Navigate to **Settings > Providers**.
|
|
1567
|
+
|
|
1568
|
+
Three token types, auto-injected into sessions for matching backends:
|
|
1569
|
+
|
|
1570
|
+
| Token | Environment Variable | Used By |
|
|
1571
|
+
|-------|---------------------|---------|
|
|
1572
|
+
| Claude Code OAuth | `CLAUDE_CODE_OAUTH_TOKEN` | Claude sessions |
|
|
1573
|
+
| OpenAI API Key | `OPENAI_API_KEY` | Codex sessions |
|
|
1574
|
+
| Anthropic API Key | `ANTHROPIC_API_KEY` | All sessions (Goose, Aider, etc.) |
|
|
1575
|
+
|
|
1576
|
+
**Precedence:** Environment profiles override global provider tokens. If your env profile sets `OPENAI_API_KEY`, the global setting is skipped for that session.
|
|
1577
|
+
|
|
1578
|
+
**Auth detection:** `GET /api/settings/auth-status` checks for existing authentication:
|
|
1579
|
+
- `~/.claude/.credentials.json` (Claude subscription login)
|
|
1580
|
+
- `~/.codex/auth.json` (ChatGPT plan login)
|
|
1581
|
+
- Environment variables and stored tokens
|
|
1582
|
+
|
|
1583
|
+
### Model & Provider Switcher
|
|
1584
|
+
|
|
1585
|
+
Two compact dropdowns in the TopBar for switching models and providers mid-session:
|
|
1586
|
+
|
|
1587
|
+
**Model Switcher** — click the model name (e.g., `◕ Sonnet`) to see all available models for the current backend. Selecting a different model sends a `set_model` WebSocket message. Works for all backends.
|
|
1588
|
+
|
|
1589
|
+
**Provider Switcher** — click the backend name (e.g., `✨ Claude`) to see all 7 backends with availability status. Selecting a different provider creates a new session with the same working directory (since backends can't be swapped mid-session).
|
|
1590
|
+
|
|
1591
|
+
### Session Launch Progress
|
|
1592
|
+
|
|
1593
|
+
A non-blocking floating toast (bottom-left) that shows real-time progress when any session is being created:
|
|
1594
|
+
|
|
1595
|
+
- **Standard sessions:** Spawning process → Waiting for connection → Ready
|
|
1596
|
+
- **Auto-detects** new sessions by monitoring the `sdkSessions` store
|
|
1597
|
+
- **Auto-dismisses** after 2 seconds once all steps complete
|
|
1598
|
+
- Works globally — triggers from HomePage, ProviderSwitcher, Agent execution, or Cron jobs
|
|
1599
|
+
|
|
1600
|
+
### Onboarding Wizard
|
|
1601
|
+
|
|
1602
|
+
A 5-step first-run experience shown on first launch. Navigate through:
|
|
1603
|
+
|
|
1604
|
+
1. **Welcome** — explains what Campfire is
|
|
1605
|
+
2. **Providers** — dual-path auth for Claude (subscription via `claude auth login` OR API key) and Codex (ChatGPT login via `codex login` OR API key). Auto-detects existing auth.
|
|
1606
|
+
3. **Workspace** — pick a default working directory
|
|
1607
|
+
4. **Tour** — key features overview
|
|
1608
|
+
5. **Launch** — sends user to create their first session
|
|
1609
|
+
|
|
1610
|
+
Skip at any point. Tracked via `onboardingCompleted` in `~/.campfire/settings.json`. Reset with:
|
|
1611
|
+
```bash
|
|
1612
|
+
curl -X PUT http://localhost:4567/api/settings -H 'Content-Type: application/json' -d '{"onboardingCompleted": false}'
|
|
1613
|
+
```
|
|
1614
|
+
|
|
1615
|
+
### Monaco Code Editor
|
|
1616
|
+
|
|
1617
|
+
VS Code's editor engine integrated into Campfire for code editing. Lazy-loaded — only downloaded when an editor opens.
|
|
1618
|
+
|
|
1619
|
+
**Where it's used:**
|
|
1620
|
+
- **CLAUDE.md Editor** — edit project instructions with Markdown syntax highlighting
|
|
1621
|
+
- **Diff Panel "Edit" mode** — click Diff > Edit to modify any file the agent changed
|
|
1622
|
+
- **Files Panel** — full file browser with editing (see below)
|
|
1623
|
+
- **Agent prompt editor** — write agent prompts with line numbers
|
|
1624
|
+
- **Cron prompt editor** — same for scheduled tasks
|
|
1625
|
+
|
|
1626
|
+
**Features:** IntelliSense (TS/JS/CSS/JSON), minimap, find/replace (Ctrl+H), multi-cursor, code folding, bracket pair colorization, command palette (Ctrl+Shift+P), custom Campfire themes (light + dark).
|
|
1627
|
+
|
|
1628
|
+
### Files Panel
|
|
1629
|
+
|
|
1630
|
+
A full workspace file browser with Monaco editor. Click the **Files** tab in the TopBar (next to Log and Diff).
|
|
1631
|
+
|
|
1632
|
+
**Features:**
|
|
1633
|
+
- **Lazy-loaded directory tree** — expands on click, shows folders and files
|
|
1634
|
+
- **File search** — filter by filename
|
|
1635
|
+
- **Syntax-highlighted editing** — open any file in Monaco with auto-detected language (40+ extensions)
|
|
1636
|
+
- **Save/Cancel** — save edits to disk or discard changes
|
|
1637
|
+
- **Changed file indicators** — files modified by the agent show a warning dot
|
|
1638
|
+
- **Image preview** — renders PNG/JPG/SVG inline
|
|
1639
|
+
- **Show/hide dotfiles** — toggle hidden files visibility
|
|
1640
|
+
- **Responsive** — sidebar collapses on mobile
|
|
1641
|
+
|
|
1642
|
+
### Recording Hub
|
|
1643
|
+
|
|
1644
|
+
Browse, validate, and diagnose session recordings. Navigate to **Data > Recordings** (`#/hub`).
|
|
1645
|
+
|
|
1646
|
+
**Getting started:**
|
|
1647
|
+
1. Click **Index Recordings** to import all existing auto-recordings
|
|
1648
|
+
2. Browse recordings with backend filter pills, playable/metadata filter, and sort options
|
|
1649
|
+
|
|
1650
|
+
**Per-recording analysis** (click the details icon):
|
|
1651
|
+
- **Protocol Validation** — checks message format compatibility across all 7 backends
|
|
1652
|
+
- **Health Report** — duration, message rate, disconnections, data gaps, permission response times, anomaly patterns
|
|
1653
|
+
|
|
1654
|
+
**Filter/Sort options:**
|
|
1655
|
+
- By backend: Claude, Codex, Goose, etc.
|
|
1656
|
+
- By type: Playable (has chat content), Metadata only
|
|
1657
|
+
- By sort: Newest, Oldest, Longest duration, Most messages
|
|
1658
|
+
|
|
1659
|
+
### Protocol Monitor
|
|
1660
|
+
|
|
1661
|
+
Real-time WebSocket message flow dashboard. Navigate to **Tools > Monitor** (`#/monitor`).
|
|
1662
|
+
|
|
1663
|
+
**Metrics (auto-refreshes every 3 seconds):**
|
|
1664
|
+
- Total messages, messages/minute, active sessions, errors
|
|
1665
|
+
- Backend breakdown with per-backend message/error counts
|
|
1666
|
+
- Message type distribution (5-minute rolling window)
|
|
1667
|
+
- Per-session stats with name, backend, rate, last activity
|
|
1668
|
+
|
|
1669
|
+
**Protocol drift alerts** — visual warnings when unexpected message formats are detected, with deduplication.
|
|
1670
|
+
|
|
1671
|
+
### Commands Discovery
|
|
1672
|
+
|
|
1673
|
+
Browse all available slash commands and skills. Navigate to **Config > Commands** (`#/commands`).
|
|
1674
|
+
|
|
1675
|
+
**Dynamic command list** — fetched from the CLI itself (not hardcoded). If no sessions are connected, Campfire spins up a temporary session to discover available commands, caches the result, and kills the session.
|
|
1676
|
+
|
|
1677
|
+
**Three sections:**
|
|
1678
|
+
- **Built-in Commands** — all CLI slash commands (e.g., `/help`, `/compact`, `/cost`, `/memory`)
|
|
1679
|
+
- **Custom Commands** — `.md` files from `~/.claude/commands/` and `{cwd}/.claude/commands/`
|
|
1680
|
+
- **Skills** — directories with `SKILL.md` from `~/.claude/skills/`
|
|
1681
|
+
|
|
1682
|
+
Custom commands and skills show expandable content preview and source badges (user vs project).
|
|
1683
|
+
|
|
1684
|
+
**Slash autocomplete on HomePage** — type `/` in the new session textarea to see the autocomplete dropdown with all available commands.
|
|
1685
|
+
|
|
1686
|
+
### Proactive Keepalive
|
|
1687
|
+
|
|
1688
|
+
Auto-relaunches crashed CLI sessions with exponential backoff. Ensures autonomous sessions (agents, cron jobs) stay alive even without a browser connected.
|
|
1689
|
+
|
|
1690
|
+
| Setting | Default | Environment Variable |
|
|
1691
|
+
|---------|---------|---------------------|
|
|
1692
|
+
| Base delay | 3 seconds | `CAMPFIRE_KEEPALIVE_DELAY_MS` |
|
|
1693
|
+
| Max attempts | 3 | `CAMPFIRE_KEEPALIVE_MAX_ATTEMPTS` |
|
|
1694
|
+
|
|
1695
|
+
**Backoff schedule:** 3s → 6s → 12s. Resets on successful relaunch.
|
|
1696
|
+
|
|
1697
|
+
**Excluded from relaunch:** Intentional kills (user clicked kill/delete), archived sessions, clean exits (exit code 0).
|
|
1698
|
+
|
|
1699
|
+
**WebSocket config:** Bun's built-in ping timeout is disabled (`idleTimeout: 0, sendPings: false`) to prevent idle CLI connections from being killed with code 1006.
|
|
1700
|
+
|
|
1701
|
+
### Security Headers & Rate Limiting
|
|
1702
|
+
|
|
1703
|
+
**Security headers** applied to all responses:
|
|
1704
|
+
|
|
1705
|
+
| Header | Value |
|
|
1706
|
+
|--------|-------|
|
|
1707
|
+
| `X-Content-Type-Options` | `nosniff` |
|
|
1708
|
+
| `X-Frame-Options` | `SAMEORIGIN` |
|
|
1709
|
+
| `Referrer-Policy` | `strict-origin-when-cross-origin` |
|
|
1710
|
+
| `X-XSS-Protection` | `1; mode=block` |
|
|
1711
|
+
| `Permissions-Policy` | `camera=(), microphone=(), geolocation=()` |
|
|
1712
|
+
| `Strict-Transport-Security` | `max-age=31536000; includeSubDomains` (HTTPS only) |
|
|
1713
|
+
|
|
1714
|
+
**Rate limiting** on `/api/*` endpoints:
|
|
1715
|
+
|
|
1716
|
+
| Setting | Default | Environment Variable |
|
|
1717
|
+
|---------|---------|---------------------|
|
|
1718
|
+
| Window | 60 seconds | `CAMPFIRE_RATE_LIMIT_WINDOW_MS` |
|
|
1719
|
+
| Max requests | 120 per window | `CAMPFIRE_RATE_LIMIT_MAX` |
|
|
1720
|
+
|
|
1721
|
+
Rate limit headers included in every API response: `X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`. Returns `429 Too Many Requests` with `Retry-After` header when exceeded.
|
|
1722
|
+
|
|
1723
|
+
### WebSocket Authentication
|
|
1724
|
+
|
|
1725
|
+
When authentication is enabled, all WebSocket upgrade endpoints are protected — not just the REST API. This prevents unauthorized users from connecting directly to WebSocket endpoints and bypassing the login.
|
|
1726
|
+
|
|
1727
|
+
**Protected endpoints:**
|
|
1728
|
+
|
|
1729
|
+
| Endpoint | What it does | Auth behavior |
|
|
1730
|
+
|----------|-------------|---------------|
|
|
1731
|
+
| `/ws/cli/:sessionId` | Agent CLI connection | Allowed from localhost without token (CLI is spawned locally). Requires token from remote connections. |
|
|
1732
|
+
| `/ws/browser/:sessionId` | Browser session connection | Requires auth token. Valid invite tokens bypass auth (for collaboration). |
|
|
1733
|
+
| `/ws/terminal/:terminalId` | Embedded terminal PTY | Requires auth token. |
|
|
1734
|
+
|
|
1735
|
+
**How tokens are passed:**
|
|
1736
|
+
- Query parameter: `?auth_token=<session_token>` (auto-appended by the frontend)
|
|
1737
|
+
- HTTP header: `Authorization: Bearer <session_token>`
|
|
1738
|
+
|
|
1739
|
+
**When auth is disabled (default):** All WebSocket connections work without tokens — zero friction for local development.
|
|
1740
|
+
|
|
1741
|
+
**Enabling auth:**
|
|
1742
|
+
|
|
1743
|
+
```bash
|
|
1744
|
+
# Option 1: Set password via environment variable
|
|
1745
|
+
CAMPFIRE_PASSWORD=mypassword bunx the-campfire
|
|
1746
|
+
|
|
1747
|
+
# Option 2: Set password via API
|
|
1748
|
+
curl -X POST http://localhost:4567/api/auth/setup \
|
|
1749
|
+
-H 'Content-Type: application/json' \
|
|
1750
|
+
-d '{"password": "mypassword"}'
|
|
1751
|
+
```
|
|
1752
|
+
|
|
1753
|
+
**Login flow:**
|
|
1754
|
+
|
|
1755
|
+
```bash
|
|
1756
|
+
# Get a session token
|
|
1757
|
+
curl -X POST http://localhost:4567/api/auth/login \
|
|
1758
|
+
-H 'Content-Type: application/json' \
|
|
1759
|
+
-d '{"password": "mypassword"}'
|
|
1760
|
+
# Returns: { "token": "abc123..." }
|
|
1761
|
+
```
|
|
1762
|
+
|
|
1763
|
+
The frontend stores this token in `localStorage` and automatically includes it in all API requests (via `Authorization` header) and WebSocket connections (via `?auth_token=` query parameter).
|
|
1764
|
+
|
|
1765
|
+
**Collaboration:** Invite tokens (generated via the Share menu) still work when auth is enabled. A valid invite token grants the specified role (collaborator/spectator) without requiring a session auth token. Invite tokens expire 24 hours after creation.
|
|
1766
|
+
|
|
1767
|
+
---
|
|
1768
|
+
|
|
1769
|
+
## Architecture
|
|
1770
|
+
|
|
1771
|
+
```
|
|
1772
|
+
Browser (React 19)
|
|
1773
|
+
<-> WebSocket <-> Campfire Server (Bun + Hono)
|
|
1774
|
+
|-- /ws/browser/:id (browser connections)
|
|
1775
|
+
|-- /ws/cli/:id (agent CLI connections)
|
|
1776
|
+
\-- /ws/terminal/:id (embedded PTY)
|
|
1777
|
+
|
|
|
1778
|
+
Claude Code CLI (NDJSON over WebSocket)
|
|
1779
|
+
Codex CLI (JSON-RPC over stdio)
|
|
1780
|
+
Goose CLI (JSON-RPC over stdio)
|
|
1781
|
+
Aider CLI (stdout parsing)
|
|
1782
|
+
OpenHands CLI (JSON-RPC over stdio)
|
|
1783
|
+
OpenClaw CLI (JSON-RPC over stdio)
|
|
1784
|
+
OpenCode CLI (JSON-RPC over stdio)
|
|
1785
|
+
```
|
|
1786
|
+
|
|
1787
|
+
The server bridges the undocumented `--sdk-url` WebSocket protocol from Claude Code (and equivalent protocols from other agents) to a normalized browser message format. The frontend is completely backend-agnostic — it renders the same UI regardless of which agent is running.
|
|
1788
|
+
|
|
1789
|
+
### Key Components
|
|
1790
|
+
|
|
1791
|
+
| Layer | Technology | Description |
|
|
1792
|
+
|-------|-----------|-------------|
|
|
1793
|
+
| **Runtime** | [Bun](https://bun.sh) | JavaScript/TypeScript runtime and package manager |
|
|
1794
|
+
| **Backend** | [Hono](https://hono.dev) | Lightweight web framework with WebSocket support |
|
|
1795
|
+
| **Frontend** | [React 19](https://react.dev) | UI with streaming, tool blocks, permission banners |
|
|
1796
|
+
| **State** | [Zustand](https://zustand.docs.pmnd.rs) | Session-scoped state keyed by session ID |
|
|
1797
|
+
| **Styling** | [Tailwind CSS 4](https://tailwindcss.com) | Utility-first CSS |
|
|
1798
|
+
| **Build** | [Vite 6](https://vite.dev) | Frontend bundler with HMR |
|
|
1799
|
+
| **Testing** | [Vitest](https://vitest.dev) | 900+ tests across backend and frontend |
|
|
1800
|
+
| **Scheduling** | [Croner](https://github.com/Hexagon/croner) | Cron expression parser for scheduled sessions |
|
|
1801
|
+
| **Vector DB** | [LanceDB](https://lancedb.github.io/lancedb/) | Embedded TypeScript-native vector database for CI semantic memory |
|
|
1802
|
+
|
|
1803
|
+
### Data Persistence
|
|
1804
|
+
|
|
1805
|
+
All state is file-based — no database required:
|
|
1806
|
+
|
|
1807
|
+
| Data | Location | Format |
|
|
1808
|
+
|------|----------|--------|
|
|
1809
|
+
| Sessions | `~/.campfire/sessions/` | JSON per session |
|
|
1810
|
+
| Recordings | `~/.campfire/recordings/` | JSONL per session |
|
|
1811
|
+
| Environments | `~/.campfire/envs/` | JSON per profile |
|
|
1812
|
+
| Cron jobs | `~/.campfire/cron/` | JSON per job |
|
|
1813
|
+
| Gallery entries | `~/.campfire/gallery/` | JSON per entry |
|
|
1814
|
+
| Agent races | `~/.campfire/races/` | JSON per race |
|
|
1815
|
+
| Webhooks | `~/.campfire/webhooks/` | JSON per webhook |
|
|
1816
|
+
| Adapters | `~/.campfire/adapters/` | npm packages |
|
|
1817
|
+
| Settings | `~/.campfire/settings.json` | Single JSON file |
|
|
1818
|
+
| Prompts | `~/.campfire/prompts.json` | Single JSON array |
|
|
1819
|
+
| Session names | `~/.campfire/session-names.json` | Single JSON file |
|
|
1820
|
+
| Linear project mappings | `~/.campfire/linear-projects.json` | Single JSON file |
|
|
1821
|
+
| Linear session issues | `~/.campfire/linear-session-issues.json` | Single JSON file |
|
|
1822
|
+
| **CI Memory** | `~/.campfire/memory/lancedb/` | LanceDB vector tables |
|
|
1823
|
+
| **CI Capabilities** | `~/.campfire/capabilities/` | JSON per session |
|
|
1824
|
+
| **CI Learning log** | `~/.campfire/capability-learning.jsonl` | JSONL append-only |
|
|
1825
|
+
|
|
1826
|
+
---
|
|
1827
|
+
|
|
1828
|
+
## Docker Deployment
|
|
1829
|
+
|
|
1830
|
+
### Building the Image
|
|
1831
|
+
|
|
1832
|
+
The included `Dockerfile` uses a multi-stage build:
|
|
1833
|
+
1. **Builder stage** — installs all dependencies and builds the frontend with Vite
|
|
1834
|
+
2. **Production stage** — copies only production dependencies, server code, and built frontend (~100MB final image)
|
|
1835
|
+
|
|
1836
|
+
```bash
|
|
1837
|
+
# Build the image
|
|
1838
|
+
docker build -t campfire:latest .
|
|
1839
|
+
|
|
1840
|
+
# Verify it works
|
|
1841
|
+
docker run --rm -p 4567:4567 campfire:latest
|
|
1842
|
+
```
|
|
1843
|
+
|
|
1844
|
+
### Using Docker Compose
|
|
1845
|
+
|
|
1846
|
+
The included `docker-compose.yml` is the easiest way to run with persistent data:
|
|
1847
|
+
|
|
1848
|
+
```bash
|
|
1849
|
+
# Start (builds if needed)
|
|
1850
|
+
docker compose up
|
|
1851
|
+
|
|
1852
|
+
# Start in background
|
|
1853
|
+
docker compose up -d
|
|
1854
|
+
|
|
1855
|
+
# Rebuild after code changes
|
|
1856
|
+
docker compose up --build
|
|
1857
|
+
|
|
1858
|
+
# Stop
|
|
1859
|
+
docker compose down
|
|
1860
|
+
|
|
1861
|
+
# Stop and remove volumes (deletes all data)
|
|
1862
|
+
docker compose down -v
|
|
1863
|
+
```
|
|
1864
|
+
|
|
1865
|
+
Open [http://localhost:4567](http://localhost:4567).
|
|
1866
|
+
|
|
1867
|
+
### docker-compose.yml
|
|
1868
|
+
|
|
1869
|
+
The included `docker-compose.yml` provides a ready-to-run configuration:
|
|
1870
|
+
|
|
1871
|
+
```yaml
|
|
1872
|
+
services:
|
|
1873
|
+
campfire:
|
|
1874
|
+
build: .
|
|
1875
|
+
ports:
|
|
1876
|
+
- "4567:4567"
|
|
1877
|
+
volumes:
|
|
1878
|
+
- campfire-data:/home/campfire/.campfire
|
|
1879
|
+
environment:
|
|
1880
|
+
- NODE_ENV=production
|
|
1881
|
+
- PORT=4567
|
|
1882
|
+
restart: unless-stopped
|
|
1883
|
+
|
|
1884
|
+
volumes:
|
|
1885
|
+
campfire-data:
|
|
1886
|
+
campfire-data:
|
|
1887
|
+
```
|
|
1888
|
+
|
|
1889
|
+
### Environment Variables
|
|
1890
|
+
|
|
1891
|
+
| Variable | Default | Description |
|
|
1892
|
+
|----------|---------|-------------|
|
|
1893
|
+
| `PORT` | `4567` | Server port |
|
|
1894
|
+
| `NODE_ENV` | `production` | Environment mode |
|
|
1895
|
+
| `CAMPFIRE_RECORD` | `1` | Enable protocol recording (`0` to disable) |
|
|
1896
|
+
| `CAMPFIRE_RECORDINGS_DIR` | `~/.campfire/recordings` | Recording output directory |
|
|
1897
|
+
| `CAMPFIRE_RECORDINGS_MAX_LINES` | `100000` | Auto-rotation threshold |
|
|
1898
|
+
| `CAMPFIRE_SESSION_DIR` | `~/.campfire/sessions` | Override session persistence directory |
|
|
1899
|
+
|
|
1900
|
+
### Volumes
|
|
1901
|
+
|
|
1902
|
+
| Path | Purpose |
|
|
1903
|
+
|------|---------|
|
|
1904
|
+
| `/home/campfire/.campfire` | All persistent data (sessions, settings, envs, agents, recordings, webhooks, gallery) |
|
|
1905
|
+
|
|
1906
|
+
### Running with Agent CLIs
|
|
1907
|
+
|
|
1908
|
+
The Docker image includes Bun but **not** the agent CLIs themselves. To use agents inside Docker, mount your host binaries or extend the image:
|
|
1909
|
+
|
|
1910
|
+
**Option 1: Mount host binaries (simplest)**
|
|
1911
|
+
|
|
1912
|
+
```yaml
|
|
1913
|
+
services:
|
|
1914
|
+
campfire:
|
|
1915
|
+
build: .
|
|
1916
|
+
ports:
|
|
1917
|
+
- "4567:4567"
|
|
1918
|
+
volumes:
|
|
1919
|
+
- campfire-data:/home/campfire/.campfire
|
|
1920
|
+
# Mount agent CLIs from host
|
|
1921
|
+
- /usr/local/bin/claude:/usr/local/bin/claude:ro
|
|
1922
|
+
- /usr/local/bin/codex:/usr/local/bin/codex:ro
|
|
1923
|
+
# Mount authentication
|
|
1924
|
+
# Writable — Claude Code updates its own config at runtime. Prefer
|
|
1925
|
+
# copying a snapshot (docker cp) if you don't want the container
|
|
1926
|
+
# touching your host ~/.claude.
|
|
1927
|
+
- ~/.claude:/home/campfire/.claude
|
|
1928
|
+
environment:
|
|
1929
|
+
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY}
|
|
1930
|
+
```
|
|
1931
|
+
|
|
1932
|
+
**Option 2: Extend the Dockerfile**
|
|
1933
|
+
|
|
1934
|
+
```dockerfile
|
|
1935
|
+
FROM campfire:latest
|
|
1936
|
+
|
|
1937
|
+
# Install Claude Code
|
|
1938
|
+
RUN bun install -g @anthropic-ai/claude-code
|
|
1939
|
+
|
|
1940
|
+
# Install Codex
|
|
1941
|
+
RUN bun install -g @openai/codex
|
|
1942
|
+
|
|
1943
|
+
# OpenClaw and OpenCode ship as standalone binaries — copy from host or download separately
|
|
1944
|
+
# COPY --from=host /usr/local/bin/openclaw /usr/local/bin/openclaw
|
|
1945
|
+
# COPY --from=host /usr/local/bin/opencode /usr/local/bin/opencode
|
|
1946
|
+
```
|
|
1947
|
+
|
|
1948
|
+
**Option 3: Network mode (connect to host CLIs)**
|
|
1949
|
+
|
|
1950
|
+
```yaml
|
|
1951
|
+
services:
|
|
1952
|
+
campfire:
|
|
1953
|
+
build: .
|
|
1954
|
+
network_mode: host
|
|
1955
|
+
volumes:
|
|
1956
|
+
- campfire-data:/home/campfire/.campfire
|
|
1957
|
+
```
|
|
1958
|
+
|
|
1959
|
+
This lets Campfire spawn agent processes on the host directly.
|
|
1960
|
+
|
|
1961
|
+
### Production Deployment
|
|
1962
|
+
|
|
1963
|
+
For production deployments behind a reverse proxy:
|
|
1964
|
+
|
|
1965
|
+
```nginx
|
|
1966
|
+
# nginx.conf
|
|
1967
|
+
server {
|
|
1968
|
+
listen 80;
|
|
1969
|
+
server_name campfire.example.com;
|
|
1970
|
+
|
|
1971
|
+
location / {
|
|
1972
|
+
proxy_pass http://localhost:4567;
|
|
1973
|
+
proxy_http_version 1.1;
|
|
1974
|
+
proxy_set_header Upgrade $http_upgrade;
|
|
1975
|
+
proxy_set_header Connection "upgrade";
|
|
1976
|
+
proxy_set_header Host $host;
|
|
1977
|
+
proxy_set_header X-Real-IP $remote_addr;
|
|
1978
|
+
proxy_read_timeout 86400; # WebSocket keep-alive
|
|
1979
|
+
}
|
|
1980
|
+
}
|
|
1981
|
+
```
|
|
1982
|
+
|
|
1983
|
+
### Health Check
|
|
1984
|
+
|
|
1985
|
+
The Docker image includes a health check:
|
|
1986
|
+
|
|
1987
|
+
```bash
|
|
1988
|
+
curl -f http://localhost:4567/api/sessions || exit 1
|
|
1989
|
+
```
|
|
1990
|
+
|
|
1991
|
+
---
|
|
1992
|
+
|
|
1993
|
+
## CLI Reference
|
|
1994
|
+
|
|
1995
|
+
```
|
|
1996
|
+
the-campfire [command] [options]
|
|
1997
|
+
|
|
1998
|
+
Commands:
|
|
1999
|
+
(none) Start server in foreground (default)
|
|
2000
|
+
serve Start server in foreground
|
|
2001
|
+
start Start as background service
|
|
2002
|
+
install Install as system service (launchd/systemd)
|
|
2003
|
+
stop Stop background service
|
|
2004
|
+
restart Restart background service
|
|
2005
|
+
uninstall Remove system service
|
|
2006
|
+
status Show service status
|
|
2007
|
+
logs Tail service log files
|
|
2008
|
+
install-adapter <package> Install a community adapter from npm
|
|
2009
|
+
uninstall-adapter <name> Remove an installed adapter
|
|
2010
|
+
help Show help
|
|
2011
|
+
|
|
2012
|
+
Options:
|
|
2013
|
+
--port <n> Override default port (default: 4567)
|
|
2014
|
+
```
|
|
2015
|
+
|
|
2016
|
+
### Examples
|
|
2017
|
+
|
|
2018
|
+
```bash
|
|
2019
|
+
# Start on a custom port
|
|
2020
|
+
the-campfire --port 8080
|
|
2021
|
+
|
|
2022
|
+
# Install as a background service
|
|
2023
|
+
the-campfire install
|
|
2024
|
+
the-campfire start
|
|
2025
|
+
the-campfire status
|
|
2026
|
+
|
|
2027
|
+
# Manage adapters
|
|
2028
|
+
the-campfire install-adapter @campfire/my-agent
|
|
2029
|
+
the-campfire uninstall-adapter my-agent
|
|
2030
|
+
```
|
|
2031
|
+
|
|
2032
|
+
---
|
|
2033
|
+
|
|
2034
|
+
## REST API Reference
|
|
2035
|
+
|
|
2036
|
+
All endpoints are under `/api`.
|
|
2037
|
+
|
|
2038
|
+
### Sessions
|
|
2039
|
+
|
|
2040
|
+
| Method | Path | Description |
|
|
2041
|
+
|--------|------|-------------|
|
|
2042
|
+
| `POST` | `/api/sessions/create` | Create a new session |
|
|
2043
|
+
| `GET` | `/api/sessions` | List all sessions |
|
|
2044
|
+
| `GET` | `/api/sessions/:id` | Get session details |
|
|
2045
|
+
| `PATCH` | `/api/sessions/:id/name` | Rename a session |
|
|
2046
|
+
| `DELETE` | `/api/sessions/:id` | Delete a session |
|
|
2047
|
+
| `POST` | `/api/sessions/:id/kill` | Kill a running session |
|
|
2048
|
+
| `POST` | `/api/sessions/:id/relaunch` | Relaunch a stopped session |
|
|
2049
|
+
| `POST` | `/api/sessions/:id/archive` | Archive a session |
|
|
2050
|
+
| `POST` | `/api/sessions/:id/unarchive` | Unarchive a session |
|
|
2051
|
+
| `POST` | `/api/sessions/:id/fork` | Fork a session at a specific point |
|
|
2052
|
+
| `POST` | `/api/sessions/:id/invite` | Create a shareable invite link |
|
|
2053
|
+
| `GET` | `/api/sessions/join/:token` | Resolve an invite token |
|
|
2054
|
+
| `POST` | `/api/sessions/create-with-progress` | Create a container session with SSE progress (returns `text/event-stream`) |
|
|
2055
|
+
|
|
2056
|
+
### Agents (autonomous profiles)
|
|
2057
|
+
|
|
2058
|
+
| Method | Path | Description |
|
|
2059
|
+
|--------|------|-------------|
|
|
2060
|
+
| `GET` | `/api/agents` | List agent profiles |
|
|
2061
|
+
| `GET` | `/api/agents/:id` | Get a profile |
|
|
2062
|
+
| `POST` | `/api/agents` | Create a profile |
|
|
2063
|
+
| `PUT` | `/api/agents/:id` | Update a profile |
|
|
2064
|
+
| `DELETE` | `/api/agents/:id` | Delete a profile |
|
|
2065
|
+
| `POST` | `/api/agents/:id/toggle` | Enable/disable a profile |
|
|
2066
|
+
| `POST` | `/api/agents/:id/run` | Trigger a manual run |
|
|
2067
|
+
| `POST` | `/api/agents/:id/webhook` | Trigger via webhook (requires webhook trigger enabled) |
|
|
2068
|
+
| `GET` | `/api/agents/:id/executions` | Execution history |
|
|
2069
|
+
| `GET` | `/api/agents/:id/export` | Export a portable profile |
|
|
2070
|
+
| `POST` | `/api/agents/import` | Import a profile (created disabled) |
|
|
2071
|
+
|
|
2072
|
+
### Agent Races
|
|
2073
|
+
|
|
2074
|
+
| Method | Path | Description |
|
|
2075
|
+
|--------|------|-------------|
|
|
2076
|
+
| `POST` | `/api/races` | Start a race across two or more agent backends |
|
|
2077
|
+
| `GET` | `/api/races` | List saved race results |
|
|
2078
|
+
| `GET` | `/api/races/:id` | Get race status and entries |
|
|
2079
|
+
| `GET` | `/api/races/:id/entries/:entryId/diff` | Load the git diff for one race entry |
|
|
2080
|
+
| `POST` | `/api/races/:id/pick` | Merge the selected winner by `sessionId` |
|
|
2081
|
+
| `POST` | `/api/races/:id/cancel` | Cancel a running race |
|
|
2082
|
+
| `DELETE` | `/api/races/:id` | Delete a saved race record |
|
|
2083
|
+
|
|
2084
|
+
### Authentication
|
|
2085
|
+
|
|
2086
|
+
| Method | Path | Description |
|
|
2087
|
+
|--------|------|-------------|
|
|
2088
|
+
| `GET` | `/api/auth/status` | Check if auth is enabled and user is logged in |
|
|
2089
|
+
| `POST` | `/api/auth/login` | Authenticate with password |
|
|
2090
|
+
| `POST` | `/api/auth/logout` | Invalidate session token |
|
|
2091
|
+
| `POST` | `/api/auth/setup` | Initial password setup |
|
|
2092
|
+
| `POST` | `/api/auth/disable` | Remove authentication |
|
|
2093
|
+
|
|
2094
|
+
### Skills & Plugins
|
|
2095
|
+
|
|
2096
|
+
| Method | Path | Description |
|
|
2097
|
+
|--------|------|-------------|
|
|
2098
|
+
| `GET` | `/api/skills` | List all plugins with status |
|
|
2099
|
+
| `GET` | `/api/skills/:id` | Get a single plugin |
|
|
2100
|
+
| `GET` | `/api/skills/:id/skill/:name` | Read a skill's SKILL.md content |
|
|
2101
|
+
| `GET` | `/api/skills/:id/command/:name` | Read a command's content |
|
|
2102
|
+
| `POST` | `/api/skills/:id/toggle` | Enable/disable a plugin in Campfire |
|
|
2103
|
+
|
|
2104
|
+
### Session Folders
|
|
2105
|
+
|
|
2106
|
+
| Method | Path | Description |
|
|
2107
|
+
|--------|------|-------------|
|
|
2108
|
+
| `GET` | `/api/folders` | List all folders |
|
|
2109
|
+
| `POST` | `/api/folders` | Create a folder (`{"name": "...", "color": "..."}`) |
|
|
2110
|
+
| `PATCH` | `/api/folders/:id` | Update folder name/color |
|
|
2111
|
+
| `DELETE` | `/api/folders/:id` | Delete a folder |
|
|
2112
|
+
| `POST` | `/api/folders/:folderId/sessions/:sessionId` | Add session to folder |
|
|
2113
|
+
| `DELETE` | `/api/folders/sessions/:sessionId` | Remove session from folder |
|
|
2114
|
+
|
|
2115
|
+
### Session Recording
|
|
2116
|
+
|
|
2117
|
+
| Method | Path | Description |
|
|
2118
|
+
|--------|------|-------------|
|
|
2119
|
+
| `GET` | `/api/recordings` | List all recording files |
|
|
2120
|
+
| `GET` | `/api/recordings/:filename` | Load a recording for replay |
|
|
2121
|
+
| `GET` | `/api/sessions/:id/recording/status` | Check recording status |
|
|
2122
|
+
| `POST` | `/api/sessions/:id/recording/start` | Start recording a session |
|
|
2123
|
+
| `POST` | `/api/sessions/:id/recording/stop` | Stop recording a session |
|
|
2124
|
+
| `GET` | `/api/sessions/:id/history` | Get session message history |
|
|
2125
|
+
|
|
2126
|
+
### Gallery
|
|
2127
|
+
|
|
2128
|
+
| Method | Path | Description |
|
|
2129
|
+
|--------|------|-------------|
|
|
2130
|
+
| `GET` | `/api/gallery` | List entries (filters: `backend`, `minCost`, `maxCost`, `tags`, `featured`, `sortBy`, `sortOrder`) |
|
|
2131
|
+
| `GET` | `/api/gallery/:id` | Get a single entry |
|
|
2132
|
+
| `POST` | `/api/gallery` | Publish a session to the gallery |
|
|
2133
|
+
| `PUT` | `/api/gallery/:id` | Update an entry |
|
|
2134
|
+
| `DELETE` | `/api/gallery/:id` | Delete an entry |
|
|
2135
|
+
| `POST` | `/api/gallery/:id/vote` | Vote on an entry (`{"direction": 1}` or `{"direction": -1}`) |
|
|
2136
|
+
| `POST` | `/api/gallery/:id/feature` | Toggle featured status |
|
|
2137
|
+
| `POST` | `/api/gallery/:id/public-link` | Create a tokenized public replay link |
|
|
2138
|
+
| `GET` | `/api/public-replay/:token` | Resolve a public replay (unauthenticated) |
|
|
2139
|
+
| `GET` | `/api/gallery/:id/skill-preview` | Preview the ClawHub SKILL.md export |
|
|
2140
|
+
| `POST` | `/api/gallery/:id/export-clawhub` | Publish the entry to ClawHub |
|
|
2141
|
+
| `GET` | `/api/clawhub/search` | Search ClawHub skills |
|
|
2142
|
+
| `GET` | `/api/clawhub/status` | Check clawhub CLI availability |
|
|
2143
|
+
| `POST` | `/api/clawhub/install` | Install a ClawHub skill |
|
|
2144
|
+
| `GET` | `/api/moltbook/status` | Check Moltbook agent registration |
|
|
2145
|
+
| `POST` | `/api/gallery/:id/post-moltbook` | Post the entry to Moltbook |
|
|
2146
|
+
|
|
2147
|
+
### Webhooks
|
|
2148
|
+
|
|
2149
|
+
| Method | Path | Description |
|
|
2150
|
+
|--------|------|-------------|
|
|
2151
|
+
| `GET` | `/api/webhooks` | List all webhooks |
|
|
2152
|
+
| `GET` | `/api/webhooks/:id` | Get a single webhook |
|
|
2153
|
+
| `POST` | `/api/webhooks` | Create a webhook |
|
|
2154
|
+
| `PUT` | `/api/webhooks/:id` | Update a webhook |
|
|
2155
|
+
| `DELETE` | `/api/webhooks/:id` | Delete a webhook |
|
|
2156
|
+
| `POST` | `/api/webhooks/:id/toggle` | Enable/disable a webhook |
|
|
2157
|
+
| `POST` | `/api/webhooks/:id/test` | Send a test event |
|
|
2158
|
+
| `POST` | `/api/webhooks/openclaw` | Inbound: spawn an OpenClaw session (token-guarded) |
|
|
2159
|
+
| `POST` | `/api/openclaw/inbound` | Inbound: deliver an OpenClaw channel message to a session |
|
|
2160
|
+
|
|
2161
|
+
### Adapters
|
|
2162
|
+
|
|
2163
|
+
| Method | Path | Description |
|
|
2164
|
+
|--------|------|-------------|
|
|
2165
|
+
| `GET` | `/api/adapters` | List installed adapters |
|
|
2166
|
+
| `POST` | `/api/adapters/install` | Install an adapter from npm (`{"npmPackage": "..."}`) |
|
|
2167
|
+
| `DELETE` | `/api/adapters/:name` | Uninstall an adapter |
|
|
2168
|
+
|
|
2169
|
+
### Backends & Models
|
|
2170
|
+
|
|
2171
|
+
| Method | Path | Description |
|
|
2172
|
+
|--------|------|-------------|
|
|
2173
|
+
| `GET` | `/api/backends` | List available agent backends (with availability status) |
|
|
2174
|
+
| `GET` | `/api/backends/:id/models` | Get available models for a backend |
|
|
2175
|
+
|
|
2176
|
+
### Cron Jobs
|
|
2177
|
+
|
|
2178
|
+
| Method | Path | Description |
|
|
2179
|
+
|--------|------|-------------|
|
|
2180
|
+
| `GET` | `/api/cron/jobs` | List all jobs (with computed `nextRunAt`) |
|
|
2181
|
+
| `GET` | `/api/cron/jobs/:id` | Get a single job |
|
|
2182
|
+
| `POST` | `/api/cron/jobs` | Create a new job |
|
|
2183
|
+
| `PUT` | `/api/cron/jobs/:id` | Update a job |
|
|
2184
|
+
| `DELETE` | `/api/cron/jobs/:id` | Delete a job |
|
|
2185
|
+
| `POST` | `/api/cron/jobs/:id/toggle` | Enable/disable a job |
|
|
2186
|
+
| `POST` | `/api/cron/jobs/:id/run` | Manually trigger a job |
|
|
2187
|
+
| `GET` | `/api/cron/jobs/:id/executions` | Get execution history |
|
|
2188
|
+
|
|
2189
|
+
### Environments
|
|
2190
|
+
|
|
2191
|
+
| Method | Path | Description |
|
|
2192
|
+
|--------|------|-------------|
|
|
2193
|
+
| `GET` | `/api/envs` | List all environment profiles |
|
|
2194
|
+
| `GET` | `/api/envs/:slug` | Get a single profile |
|
|
2195
|
+
| `POST` | `/api/envs` | Create a profile (`{"name": "...", "variables": {...}}`) |
|
|
2196
|
+
| `PUT` | `/api/envs/:slug` | Update a profile |
|
|
2197
|
+
| `DELETE` | `/api/envs/:slug` | Delete a profile |
|
|
2198
|
+
|
|
2199
|
+
### Collaboration
|
|
2200
|
+
|
|
2201
|
+
| Method | Path | Description |
|
|
2202
|
+
|--------|------|-------------|
|
|
2203
|
+
| `GET` | `/api/voting-policy` | Get current voting policy |
|
|
2204
|
+
| `PUT` | `/api/voting-policy` | Set voting policy (`majority-rules`, `any-deny-blocks`, `owner-decides`) |
|
|
2205
|
+
|
|
2206
|
+
### Git
|
|
2207
|
+
|
|
2208
|
+
| Method | Path | Description |
|
|
2209
|
+
|--------|------|-------------|
|
|
2210
|
+
| `GET` | `/api/git/repo-info` | Get repo info (root, branch, default branch) |
|
|
2211
|
+
| `GET` | `/api/git/branches` | List branches (with ahead/behind counts) |
|
|
2212
|
+
| `GET` | `/api/git/worktrees` | List worktrees |
|
|
2213
|
+
| `POST` | `/api/git/worktree` | Create a worktree |
|
|
2214
|
+
| `DELETE` | `/api/git/worktree` | Remove a worktree |
|
|
2215
|
+
| `POST` | `/api/git/fetch` | Git fetch |
|
|
2216
|
+
| `POST` | `/api/git/pull` | Git pull (returns ahead/behind counts) |
|
|
2217
|
+
| `GET` | `/api/git/pr-status` | Get GitHub PR status for a branch |
|
|
2218
|
+
|
|
2219
|
+
### Filesystem
|
|
2220
|
+
|
|
2221
|
+
| Method | Path | Description |
|
|
2222
|
+
|--------|------|-------------|
|
|
2223
|
+
| `GET` | `/api/fs/list` | List directories in a path |
|
|
2224
|
+
| `GET` | `/api/fs/home` | Get home directory and current working directory |
|
|
2225
|
+
| `GET` | `/api/fs/tree` | Get recursive directory tree |
|
|
2226
|
+
| `GET` | `/api/fs/read` | Read a file (max 2MB) |
|
|
2227
|
+
| `PUT` | `/api/fs/write` | Write a file |
|
|
2228
|
+
| `GET` | `/api/fs/diff` | Git diff for a single file |
|
|
2229
|
+
| `GET` | `/api/fs/claude-md` | Find CLAUDE.md files |
|
|
2230
|
+
| `PUT` | `/api/fs/claude-md` | Create or update CLAUDE.md |
|
|
2231
|
+
|
|
2232
|
+
### Collective Intelligence
|
|
2233
|
+
|
|
2234
|
+
| Method | Path | Description |
|
|
2235
|
+
|--------|------|-------------|
|
|
2236
|
+
| `GET` | `/api/sessions/:id/memory` | List memory fragments for a session |
|
|
2237
|
+
| `POST` | `/api/sessions/:id/memory` | Store a new memory fragment |
|
|
2238
|
+
| `GET` | `/api/sessions/:id/memory/query` | Semantic search (`?q=...&limit=10`) |
|
|
2239
|
+
| `POST` | `/api/sessions/:id/memory/consolidate` | Consolidate session memory into knowledge |
|
|
2240
|
+
| `GET` | `/api/memory/global` | Query all memory across sessions (`?q=...`) |
|
|
2241
|
+
| `GET` | `/api/sessions/:id/deliberations` | List active deliberation proposals |
|
|
2242
|
+
| `GET` | `/api/sessions/:id/deliberations/:proposalId` | Get a deliberation proposal |
|
|
2243
|
+
| `POST` | `/api/sessions/:id/deliberations/:proposalId/respond` | Respond to a proposal |
|
|
2244
|
+
| `POST` | `/api/sessions/:id/deliberations/:proposalId/resolve` | Force-resolve a proposal |
|
|
2245
|
+
| `POST` | `/api/sessions/route-task` | Route a task to the best-suited session |
|
|
2246
|
+
| `GET` | `/api/capabilities` | List all registered agent capabilities |
|
|
2247
|
+
| `GET` | `/api/capabilities/history` | Get task execution history |
|
|
2248
|
+
| `POST` | `/api/capabilities/feedback` | Submit outcome feedback for a task |
|
|
2249
|
+
| `GET` | `/api/sessions/:id/context/stream` | Get shared context thread for a session |
|
|
2250
|
+
| `GET` | `/api/sessions/:id/context/consensus` | Get consensus state for a session |
|
|
2251
|
+
| `GET` | `/api/sessions/:id/context/thread/:fragmentId` | Get semantic thread from a fragment |
|
|
2252
|
+
|
|
2253
|
+
### Prompt Library
|
|
2254
|
+
|
|
2255
|
+
| Method | Path | Description |
|
|
2256
|
+
|--------|------|-------------|
|
|
2257
|
+
| `GET` | `/api/prompts` | List prompts (optional `?cwd=` to filter by project path) |
|
|
2258
|
+
| `POST` | `/api/prompts` | Create a prompt (`{"name", "content", "scope", "projectPath?"}`) |
|
|
2259
|
+
| `PUT` | `/api/prompts/:id` | Update a prompt |
|
|
2260
|
+
| `DELETE` | `/api/prompts/:id` | Delete a prompt |
|
|
2261
|
+
|
|
2262
|
+
### Linear Integration
|
|
2263
|
+
|
|
2264
|
+
| Method | Path | Description |
|
|
2265
|
+
|--------|------|-------------|
|
|
2266
|
+
| `GET` | `/api/linear/connection` | Check connection status and list teams |
|
|
2267
|
+
| `GET` | `/api/linear/issues` | Search issues (`?query=&limit=`) |
|
|
2268
|
+
| `GET` | `/api/linear/teams` | List all Linear teams |
|
|
2269
|
+
| `GET` | `/api/linear/team/:id/states` | Get workflow states for a team |
|
|
2270
|
+
| `GET` | `/api/linear/projects` | List all Linear projects |
|
|
2271
|
+
| `GET` | `/api/linear/project-mapping` | Get project-repo mapping (`?repoRoot=`) |
|
|
2272
|
+
| `POST` | `/api/linear/project-mapping` | Create or update a project-repo mapping |
|
|
2273
|
+
| `DELETE` | `/api/linear/project-mapping` | Remove a project-repo mapping |
|
|
2274
|
+
| `POST` | `/api/linear/session/:id/link-issue` | Link a Linear issue to a session |
|
|
2275
|
+
| `GET` | `/api/linear/session/:id/issue` | Get the linked issue for a session |
|
|
2276
|
+
| `POST` | `/api/linear/issues/:id/transition` | Transition an issue to a new state |
|
|
2277
|
+
|
|
2278
|
+
### Settings & System
|
|
2279
|
+
|
|
2280
|
+
| Method | Path | Description |
|
|
2281
|
+
|--------|------|-------------|
|
|
2282
|
+
| `GET` | `/api/settings` | Get application settings |
|
|
2283
|
+
| `PUT` | `/api/settings` | Update settings (OpenRouter key/model, Linear API key, embedding provider) |
|
|
2284
|
+
| `GET` | `/api/containers/status` | Check Docker availability |
|
|
2285
|
+
| `GET` | `/api/containers/images` | List Docker images |
|
|
2286
|
+
| `GET` | `/api/usage-limits` | Get account usage limits |
|
|
2287
|
+
| `GET` | `/api/sessions/:id/usage-limits` | Get session-specific usage limits |
|
|
2288
|
+
| `GET` | `/api/update-check` | Check for updates |
|
|
2289
|
+
| `POST` | `/api/update-check` | Force update check |
|
|
2290
|
+
| `POST` | `/api/update` | Install update and restart (service mode only) |
|
|
2291
|
+
| `GET` | `/api/terminal` | Get terminal status |
|
|
2292
|
+
| `POST` | `/api/terminal/spawn` | Spawn embedded terminal |
|
|
2293
|
+
| `POST` | `/api/terminal/kill` | Kill embedded terminal |
|
|
2294
|
+
|
|
2295
|
+
---
|
|
2296
|
+
|
|
2297
|
+
## WebSocket Protocol
|
|
2298
|
+
|
|
2299
|
+
### Browser Connection
|
|
2300
|
+
|
|
2301
|
+
Connect to `ws://localhost:4567/ws/browser/:sessionId` to receive real-time session events.
|
|
2302
|
+
|
|
2303
|
+
**Messages from server:**
|
|
2304
|
+
|
|
2305
|
+
```json
|
|
2306
|
+
{"type": "session_init", "session": {"session_id": "...", "model": "...", "cwd": "...", ...}}
|
|
2307
|
+
{"type": "assistant", "message": {"id": "msg_01...", "content": [{"type": "text", "text": "..."}]}}
|
|
2308
|
+
{"type": "stream_event", "event": {"type": "content_block_delta", ...}}
|
|
2309
|
+
{"type": "result", "data": {"total_cost_usd": 0.42, "num_turns": 5, ...}}
|
|
2310
|
+
{"type": "permission_request", "request": {"tool_name": "Bash", "input": {"command": "rm -rf /"}, ...}}
|
|
2311
|
+
{"type": "permission_cancelled", "request_id": "pr_01..."}
|
|
2312
|
+
{"type": "tool_progress", "tool_use_id": "tu_01...", "tool_name": "Bash", "elapsed_time_seconds": 5}
|
|
2313
|
+
{"type": "status_change", "status": "running"}
|
|
2314
|
+
{"type": "cli_connected"}
|
|
2315
|
+
{"type": "cli_disconnected"}
|
|
2316
|
+
{"type": "presence_update", "viewers": [{"id": "abc", "name": "Viewer 1", "role": "owner"}]}
|
|
2317
|
+
{"type": "role_assigned", "role": "owner", "viewerId": "abc"}
|
|
2318
|
+
{"type": "vote_update", "request_id": "...", "votes": {"allow": 2, "deny": 0}, "total": 3, "deadline": 1771154026}
|
|
2319
|
+
{"type": "vote_resolved", "request_id": "...", "allowed": true, "policy": "majority-rules"}
|
|
2320
|
+
{"type": "session_name_update", "name": "Fix auth bug"}
|
|
2321
|
+
{"type": "pr_status_update", "pr": {...}, "available": true}
|
|
2322
|
+
{"type": "mcp_status", "servers": [...]}
|
|
2323
|
+
{"type": "message_history", "messages": [...]}
|
|
2324
|
+
{"type": "event_replay", "events": [{"seq": 1, "message": {...}}]}
|
|
2325
|
+
```
|
|
2326
|
+
|
|
2327
|
+
**Messages from browser:**
|
|
2328
|
+
|
|
2329
|
+
```json
|
|
2330
|
+
{"type": "user_message", "content": "Fix the bug in auth.ts", "client_msg_id": "..."}
|
|
2331
|
+
{"type": "permission_response", "request_id": "pr_01...", "behavior": "allow"}
|
|
2332
|
+
{"type": "interrupt", "client_msg_id": "..."}
|
|
2333
|
+
{"type": "set_model", "model": "claude-sonnet-4-5-20250929", "client_msg_id": "..."}
|
|
2334
|
+
{"type": "set_permission_mode", "mode": "bypassPermissions", "client_msg_id": "..."}
|
|
2335
|
+
{"type": "session_subscribe", "last_seq": 42}
|
|
2336
|
+
{"type": "session_ack", "last_seq": 50}
|
|
2337
|
+
{"type": "mcp_get_status", "client_msg_id": "..."}
|
|
2338
|
+
{"type": "mcp_toggle", "serverName": "filesystem", "enabled": true}
|
|
2339
|
+
{"type": "mcp_set_servers", "servers": {"my-server": {"type": "stdio", "command": "node", "args": ["server.js"]}}}
|
|
2340
|
+
```
|
|
2341
|
+
|
|
2342
|
+
**Collective Intelligence messages (browser → server):**
|
|
2343
|
+
|
|
2344
|
+
```json
|
|
2345
|
+
{"type": "memory_query", "query": "authentication pattern", "limit": 5}
|
|
2346
|
+
{"type": "memory_store", "content": "...", "memoryType": "observation", "tags": ["auth"]}
|
|
2347
|
+
{"type": "deliberation_respond", "proposalId": "...", "stance": "approve", "reasoning": "..."}
|
|
2348
|
+
{"type": "deliberation_resolve", "proposalId": "..."}
|
|
2349
|
+
{"type": "capability_probe_response", "probeId": "...", "confidence": 0.9, "reasoning": "..."}
|
|
2350
|
+
{"type": "route_task", "taskDescription": "Refactor auth module", "availableSessions": ["s1", "s2"]}
|
|
2351
|
+
{"type": "inject_thought", "content": "...", "thoughtType": "observation", "parentId": "..."}
|
|
2352
|
+
```
|
|
2353
|
+
|
|
2354
|
+
**Collective Intelligence messages (server → browser):**
|
|
2355
|
+
|
|
2356
|
+
```json
|
|
2357
|
+
{"type": "memory_stored", "fragment": {"id": "...", "content": "...", "tags": ["auth"], ...}}
|
|
2358
|
+
{"type": "memory_query_result", "query": "auth pattern", "results": [...]}
|
|
2359
|
+
{"type": "memory_consolidated", "tag": "auth", "knowledge": {"summary": "...", ...}}
|
|
2360
|
+
{"type": "deliberation_proposal", "proposal": {"id": "...", "question": "...", ...}}
|
|
2361
|
+
{"type": "deliberation_resolved", "resolution": {"proposalId": "...", "outcome": "approved", ...}}
|
|
2362
|
+
{"type": "capability_probe", "probeId": "...", "taskDescription": "...", "instruction": "..."}
|
|
2363
|
+
{"type": "route_result", "result": {"sessionId": "...", "confidence": 0.85, "reasoning": "...", ...}}
|
|
2364
|
+
{"type": "shared_thought", "fragment": {"id": "...", "content": "...", "semanticLinks": [...], ...}}
|
|
2365
|
+
{"type": "consensus_update", "state": {"consensusScore": 0.8, "isControversial": false, ...}}
|
|
2366
|
+
```
|
|
2367
|
+
|
|
2368
|
+
**Reconnection:**
|
|
2369
|
+
|
|
2370
|
+
The browser tracks a sequence number (`seq`) for each message. On reconnect, it sends `session_subscribe` with the last received `seq`. The server replies with `event_replay` containing all events since that point, so the browser catches up without missing anything.
|
|
2371
|
+
|
|
2372
|
+
Protocol details are documented in [`CLAUDE.md`](CLAUDE.md).
|
|
2373
|
+
|
|
2374
|
+
---
|
|
2375
|
+
|
|
2376
|
+
## Development
|
|
2377
|
+
|
|
2378
|
+
See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, dev mode, project structure, testing, and how to write adapters.
|
|
2379
|
+
|
|
2380
|
+
---
|
|
2381
|
+
|
|
2382
|
+
## Security
|
|
2383
|
+
|
|
2384
|
+
Found a vulnerability? Please report it privately — see [SECURITY.md](SECURITY.md). The same document covers hardening notes for self-hosters (auth, invite-link semantics, MCP injection policy).
|
|
2385
|
+
|
|
2386
|
+
## License
|
|
2387
|
+
|
|
2388
|
+
MIT
|