repowire 0.1.1__tar.gz
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.
- repowire-0.1.1/.cursorignore +1 -0
- repowire-0.1.1/.gemini-clipboard/clipboard-1768777598464.png +0 -0
- repowire-0.1.1/.gitignore +12 -0
- repowire-0.1.1/CLAUDE.md +327 -0
- repowire-0.1.1/PKG-INFO +256 -0
- repowire-0.1.1/README.md +217 -0
- repowire-0.1.1/deploy/Dockerfile +14 -0
- repowire-0.1.1/deploy/relay.yaml +84 -0
- repowire-0.1.1/images/logo-dark.webp +0 -0
- repowire-0.1.1/images/logo-light.webp +0 -0
- repowire-0.1.1/pyproject.toml +76 -0
- repowire-0.1.1/repowire/__init__.py +1 -0
- repowire-0.1.1/repowire/backends/__init__.py +35 -0
- repowire-0.1.1/repowire/backends/base.py +54 -0
- repowire-0.1.1/repowire/backends/claudemux/__init__.py +5 -0
- repowire-0.1.1/repowire/backends/claudemux/backend.py +178 -0
- repowire-0.1.1/repowire/backends/claudemux/installer.py +103 -0
- repowire-0.1.1/repowire/backends/opencode/__init__.py +5 -0
- repowire-0.1.1/repowire/backends/opencode/backend.py +112 -0
- repowire-0.1.1/repowire/backends/opencode/installer.py +143 -0
- repowire-0.1.1/repowire/cli.py +698 -0
- repowire-0.1.1/repowire/config/__init__.py +1 -0
- repowire-0.1.1/repowire/config/models.py +171 -0
- repowire-0.1.1/repowire/daemon/__init__.py +4 -0
- repowire-0.1.1/repowire/daemon/app.py +170 -0
- repowire-0.1.1/repowire/daemon/auth.py +72 -0
- repowire-0.1.1/repowire/daemon/core.py +230 -0
- repowire-0.1.1/repowire/daemon/deps.py +56 -0
- repowire-0.1.1/repowire/daemon/routes/__init__.py +1 -0
- repowire-0.1.1/repowire/daemon/routes/health.py +39 -0
- repowire-0.1.1/repowire/daemon/routes/messages.py +179 -0
- repowire-0.1.1/repowire/daemon/routes/peers.py +179 -0
- repowire-0.1.1/repowire/hooks/__init__.py +1 -0
- repowire-0.1.1/repowire/hooks/_tmux.py +28 -0
- repowire-0.1.1/repowire/hooks/installer.py +84 -0
- repowire-0.1.1/repowire/hooks/session_handler.py +153 -0
- repowire-0.1.1/repowire/hooks/stop_handler.py +96 -0
- repowire-0.1.1/repowire/mcp/__init__.py +1 -0
- repowire-0.1.1/repowire/mcp/server.py +133 -0
- repowire-0.1.1/repowire/protocol/__init__.py +1 -0
- repowire-0.1.1/repowire/protocol/messages.py +117 -0
- repowire-0.1.1/repowire/protocol/peers.py +76 -0
- repowire-0.1.1/repowire/relay/__init__.py +1 -0
- repowire-0.1.1/repowire/relay/auth.py +87 -0
- repowire-0.1.1/repowire/relay/server.py +233 -0
- repowire-0.1.1/repowire/session/__init__.py +1 -0
- repowire-0.1.1/repowire/session/transcript.py +74 -0
- repowire-0.1.1/repowire.yaml.example +31 -0
- repowire-0.1.1/session-logs.md +354 -0
- repowire-0.1.1/tests/__init__.py +1 -0
- repowire-0.1.1/tests/test_config.py +57 -0
- repowire-0.1.1/tests/test_protocol.py +116 -0
- repowire-0.1.1/tests/test_relay.py +50 -0
- repowire-0.1.1/tests/test_transcript.py +95 -0
- repowire-0.1.1/uv.lock +1603 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv)
|
|
Binary file
|
repowire-0.1.1/CLAUDE.md
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Build & Development Commands
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Install dependencies (use --all for both backends)
|
|
9
|
+
pip install -e ".[all]" # claudemux + opencode
|
|
10
|
+
pip install -e ".[claudemux]" # tmux backend only
|
|
11
|
+
pip install -e ".[opencode]" # opencode backend only
|
|
12
|
+
pip install -e ".[dev]" # dev tools (pytest, ruff, mypy)
|
|
13
|
+
|
|
14
|
+
# Run tests
|
|
15
|
+
pytest # all tests
|
|
16
|
+
pytest tests/test_config.py # single test file
|
|
17
|
+
pytest -k "test_add_peer" # single test by name
|
|
18
|
+
|
|
19
|
+
# Linting and type checking
|
|
20
|
+
ruff check repowire/ # lint
|
|
21
|
+
ruff format repowire/ # format
|
|
22
|
+
mypy repowire/ # type check
|
|
23
|
+
|
|
24
|
+
# Start daemon
|
|
25
|
+
repowire serve # default: 127.0.0.1:8377
|
|
26
|
+
repowire serve --backend opencode --port 8080
|
|
27
|
+
|
|
28
|
+
# Setup (installs hooks + MCP server)
|
|
29
|
+
repowire setup --dev # dev mode (uses local code)
|
|
30
|
+
repowire setup --backend claudemux
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Architecture Overview
|
|
34
|
+
|
|
35
|
+
Repowire is a mesh network enabling Claude Code sessions to communicate. It has a **pluggable backend architecture** supporting both local (tmux) and remote (OpenCode SDK) message delivery.
|
|
36
|
+
|
|
37
|
+
### Core Components
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
41
|
+
│ MCP Server (mcp/server.py) │
|
|
42
|
+
│ Thin HTTP client exposing list_peers, ask_peer, notify_peer│
|
|
43
|
+
│ broadcast tools. Delegates all work to daemon via HTTP. │
|
|
44
|
+
└─────────────────────────────────────────────────────────────┘
|
|
45
|
+
│
|
|
46
|
+
▼
|
|
47
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
48
|
+
│ HTTP Daemon (daemon/app.py) │
|
|
49
|
+
│ FastAPI server with /query, /notify, /broadcast, /peers │
|
|
50
|
+
│ endpoints. Uses PeerManager for routing. │
|
|
51
|
+
└─────────────────────────────────────────────────────────────┘
|
|
52
|
+
│
|
|
53
|
+
▼
|
|
54
|
+
┌─────────────────────────────────────────────────────────────┐
|
|
55
|
+
│ PeerManager (daemon/core.py) │
|
|
56
|
+
│ Central routing. Validates backend requirements, formats │
|
|
57
|
+
│ messages, delegates to configured backend. │
|
|
58
|
+
└─────────────────────────────────────────────────────────────┘
|
|
59
|
+
│
|
|
60
|
+
┌───────────────┴───────────────┐
|
|
61
|
+
▼ ▼
|
|
62
|
+
┌─────────────────────────┐ ┌─────────────────────────┐
|
|
63
|
+
│ ClaudemuxBackend │ │ OpencodeBackend │
|
|
64
|
+
│ (backends/claudemux/) │ │ (backends/opencode/) │
|
|
65
|
+
│ │ │ │
|
|
66
|
+
│ - Uses libtmux │ │ - Uses opencode-ai SDK │
|
|
67
|
+
│ - Requires tmux_session │ │ - Requires opencode_url │
|
|
68
|
+
│ - Response via hooks │ │ - Direct SDK response │
|
|
69
|
+
└─────────────────────────┘ └─────────────────────────┘
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Backend Interface (backends/base.py)
|
|
73
|
+
|
|
74
|
+
All backends implement:
|
|
75
|
+
- `send_message(peer, text)` - Fire-and-forget
|
|
76
|
+
- `send_query(peer, text, timeout)` - Wait for response
|
|
77
|
+
- `get_peer_status(peer)` - Check online/offline
|
|
78
|
+
- `install()` / `uninstall()` / `check_installed()`
|
|
79
|
+
|
|
80
|
+
### Message Flow: Query with Claudemux Backend
|
|
81
|
+
|
|
82
|
+
```
|
|
83
|
+
1. MCP tool ask_peer() → HTTP POST /query
|
|
84
|
+
2. PeerManager formats: "@{from_peer} asks: {text}"
|
|
85
|
+
3. Backend creates pending file: ~/.repowire/pending/{tmux_session}.json
|
|
86
|
+
4. Backend sends to tmux pane via libtmux
|
|
87
|
+
5. Claude processes, responds
|
|
88
|
+
6. Stop hook fires → reads transcript → extracts last assistant response
|
|
89
|
+
7. Stop hook sends to daemon via HTTP POST /hook/response
|
|
90
|
+
8. Backend resolves asyncio.Future with response
|
|
91
|
+
9. Response returned to caller
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Hooks System (claudemux only)
|
|
95
|
+
|
|
96
|
+
Hooks in `~/.claude/settings.json` auto-register peers and capture responses:
|
|
97
|
+
|
|
98
|
+
- **SessionStart** → `repowire hook session` → Registers peer (name = folder name, git branch in metadata), outputs `additionalContext` with peer list
|
|
99
|
+
- **SessionEnd** → `repowire hook session` → Clears session_id
|
|
100
|
+
- **Stop** → `repowire hook stop` → Extracts last assistant response from transcript, sends via HTTP POST `/hook/response`
|
|
101
|
+
|
|
102
|
+
Key files:
|
|
103
|
+
- `hooks/installer.py` - Installs/uninstalls hooks in `~/.claude/settings.json`
|
|
104
|
+
- `hooks/session_handler.py` - Handles both SessionStart and SessionEnd events
|
|
105
|
+
- `hooks/stop_handler.py` - Captures response from transcript JSONL, sends to daemon
|
|
106
|
+
|
|
107
|
+
### Configuration
|
|
108
|
+
|
|
109
|
+
File: `~/.repowire/config.yaml`
|
|
110
|
+
|
|
111
|
+
```yaml
|
|
112
|
+
daemon:
|
|
113
|
+
host: "127.0.0.1"
|
|
114
|
+
port: 8377
|
|
115
|
+
backend: "claudemux" # or "opencode"
|
|
116
|
+
|
|
117
|
+
relay:
|
|
118
|
+
enabled: false
|
|
119
|
+
url: "wss://relay.repowire.io"
|
|
120
|
+
api_key: null
|
|
121
|
+
|
|
122
|
+
opencode:
|
|
123
|
+
default_url: "http://localhost:4096"
|
|
124
|
+
|
|
125
|
+
peers:
|
|
126
|
+
frontend:
|
|
127
|
+
name: frontend
|
|
128
|
+
path: "/path/to/frontend"
|
|
129
|
+
tmux_session: "0:frontend" # for claudemux backend
|
|
130
|
+
opencode_url: "http://..." # for opencode backend
|
|
131
|
+
session_id: "..." # Claude session ID (set by hooks)
|
|
132
|
+
metadata:
|
|
133
|
+
branch: "main" # git branch (auto-populated by SessionStart hook)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Environment overrides: `REPOWIRE_RELAY_URL`, `REPOWIRE_API_KEY`
|
|
137
|
+
|
|
138
|
+
### Protocol (protocol/)
|
|
139
|
+
|
|
140
|
+
Message types: `QUERY`, `RESPONSE`, `NOTIFICATION`, `BROADCAST`
|
|
141
|
+
|
|
142
|
+
All messages have: `id`, `type`, `from_peer`, `to_peer`, `payload`, `correlation_id`, `timestamp`
|
|
143
|
+
|
|
144
|
+
Peer status: `ONLINE`, `BUSY`, `OFFLINE`
|
|
145
|
+
|
|
146
|
+
### HTTP API Endpoints
|
|
147
|
+
|
|
148
|
+
| Endpoint | Method | Purpose |
|
|
149
|
+
|----------|--------|---------|
|
|
150
|
+
| `/health` | GET | Health check with backend info |
|
|
151
|
+
| `/peers` | GET | List all peers |
|
|
152
|
+
| `/peers` | POST | Register peer |
|
|
153
|
+
| `/peers/{name}` | DELETE | Unregister peer |
|
|
154
|
+
| `/query` | POST | Send query, wait for response |
|
|
155
|
+
| `/notify` | POST | Send notification (fire-and-forget) |
|
|
156
|
+
| `/broadcast` | POST | Send to all peers |
|
|
157
|
+
| `/session/update` | POST | Update peer session status |
|
|
158
|
+
| `/hook/response` | POST | Receive response from Stop hook (claudemux) |
|
|
159
|
+
|
|
160
|
+
## Key Design Decisions
|
|
161
|
+
|
|
162
|
+
1. **Peer name = folder name** - Auto-derived from cwd in SessionStart hook
|
|
163
|
+
2. **Correlation IDs** - UUID-based request/response matching via pending files
|
|
164
|
+
3. **Config reloaded per request** - Fresh peer discovery without daemon restart
|
|
165
|
+
4. **Backend validation** - Claudemux requires `tmux_session`, OpenCode requires `opencode_url`
|
|
166
|
+
5. **HTTP hooks** - Stop hook sends responses via HTTP POST to daemon's `/hook/response` endpoint
|
|
167
|
+
6. **Peer metadata** - Includes git branch info, auto-populated by SessionStart hook
|
|
168
|
+
7. **Context injection** - SessionStart hook outputs `additionalContext` with peer list for Claude
|
|
169
|
+
|
|
170
|
+
## Testing
|
|
171
|
+
|
|
172
|
+
- Framework: pytest with pytest-asyncio (auto mode)
|
|
173
|
+
- Tests use `tempfile` and `unittest.mock` extensively
|
|
174
|
+
- No integration tests yet (directory exists at `tests/integration/`)
|
|
175
|
+
|
|
176
|
+
## Dev Workflow: Integration Testing (Claudemux)
|
|
177
|
+
|
|
178
|
+
This workflow tests the **claudemux backend** - tmux-based peer communication for Claude Code sessions. This is the primary local development workflow.
|
|
179
|
+
|
|
180
|
+
> **Note:** The opencode backend has a simpler flow since the SDK returns responses directly (no hooks/tmux needed). For opencode testing, peers just need `opencode_url` configured and an OpenCode server running.
|
|
181
|
+
|
|
182
|
+
### Prerequisites
|
|
183
|
+
|
|
184
|
+
1. **Ask the user for two test projects** - Need two separate git repos/folders to use as test peers. Example prompt:
|
|
185
|
+
> "I need two project directories to test repowire peer communication. Which two folders should I use? (They'll each run a Claude Code session that can talk to each other)"
|
|
186
|
+
|
|
187
|
+
2. **Ensure claudemux backend is set up**:
|
|
188
|
+
```bash
|
|
189
|
+
repowire setup --dev --backend claudemux
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Step-by-Step Workflow
|
|
193
|
+
|
|
194
|
+
#### 1. Check/Create tmux Session
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
# Check if tmux is running
|
|
198
|
+
tmux list-sessions 2>/dev/null || echo "No tmux sessions"
|
|
199
|
+
|
|
200
|
+
# If no session exists, create one
|
|
201
|
+
tmux new-session -d -s repowire-test
|
|
202
|
+
|
|
203
|
+
# Attach to existing or new session
|
|
204
|
+
tmux attach -t repowire-test
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
#### 2. Create Test Windows
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# Create two windows for test peers (from within tmux or using tmux commands)
|
|
211
|
+
tmux new-window -t repowire-test -n alice
|
|
212
|
+
tmux new-window -t repowire-test -n bob
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
#### 3. Start the Daemon
|
|
216
|
+
|
|
217
|
+
In a separate terminal or tmux pane:
|
|
218
|
+
```bash
|
|
219
|
+
repowire serve
|
|
220
|
+
# or for dev: uv run repowire serve
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Verify it's running:
|
|
224
|
+
```bash
|
|
225
|
+
curl -s http://127.0.0.1:8377/health
|
|
226
|
+
# Should return: {"status":"ok","version":"0.1.0","backend":"claudemux",...}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
#### 4. Launch Claude Sessions in Each Window
|
|
230
|
+
|
|
231
|
+
**Window "alice":**
|
|
232
|
+
```bash
|
|
233
|
+
tmux send-keys -t repowire-test:alice "cd /path/to/project-a && claude" Enter
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
**Window "bob":**
|
|
237
|
+
```bash
|
|
238
|
+
tmux send-keys -t repowire-test:bob "cd /path/to/project-b && claude" Enter
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
The SessionStart hook will auto-register each peer using the folder name.
|
|
242
|
+
|
|
243
|
+
#### 5. Verify Peer Registration
|
|
244
|
+
|
|
245
|
+
```bash
|
|
246
|
+
repowire peer list
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
Expected output shows both peers with status "online":
|
|
250
|
+
```
|
|
251
|
+
┌─────────────────────────────────────────────────┐
|
|
252
|
+
│ Name │ Status │ Tmux Session │ Path │
|
|
253
|
+
├─────────────────────────────────────────────────┤
|
|
254
|
+
│ project-a │ online │ repowire-test:alice│ ... │
|
|
255
|
+
│ project-b │ online │ repowire-test:bob │ ... │
|
|
256
|
+
└─────────────────────────────────────────────────┘
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
#### 6. Test Communication
|
|
260
|
+
|
|
261
|
+
**Option A: CLI test**
|
|
262
|
+
```bash
|
|
263
|
+
repowire peer ask project-b "What is this project about?"
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Option B: From within a Claude session**
|
|
267
|
+
In alice's Claude session, type:
|
|
268
|
+
> "Ask project-b what their main API endpoints are"
|
|
269
|
+
|
|
270
|
+
Claude will use the `ask_peer` MCP tool to query the other session.
|
|
271
|
+
|
|
272
|
+
#### 7. Collaboration Test
|
|
273
|
+
|
|
274
|
+
Give both sessions a shared task to verify bidirectional communication:
|
|
275
|
+
|
|
276
|
+
In alice's session:
|
|
277
|
+
> "You're working with a peer called 'project-b'. Ask them what dependencies they use, then tell them what dependencies you use. Coordinate to identify any shared libraries."
|
|
278
|
+
|
|
279
|
+
### Cleanup
|
|
280
|
+
|
|
281
|
+
**Important:** Use `tmux kill-window` or `tmux kill-pane` to quit Claude sessions. Sending Ctrl+C via `tmux send-keys` is unreliable and often doesn't work properly.
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
# Kill test windows (preferred method to quit Claude sessions)
|
|
285
|
+
tmux kill-window -t repowire-test:alice
|
|
286
|
+
tmux kill-window -t repowire-test:bob
|
|
287
|
+
|
|
288
|
+
# Alternative: kill just the pane if window has multiple panes
|
|
289
|
+
# tmux kill-pane -t repowire-test:alice
|
|
290
|
+
|
|
291
|
+
# Stop daemon
|
|
292
|
+
repowire daemon stop
|
|
293
|
+
# or: curl -X POST http://127.0.0.1:8377/shutdown
|
|
294
|
+
|
|
295
|
+
# Unregister peers (optional - they'll be cleaned up automatically)
|
|
296
|
+
repowire peer unregister project-a
|
|
297
|
+
repowire peer unregister project-b
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Troubleshooting (Claudemux)
|
|
301
|
+
|
|
302
|
+
| Issue | Check |
|
|
303
|
+
|-------|-------|
|
|
304
|
+
| Peers not showing up | Verify hooks installed: `repowire claudemux status` |
|
|
305
|
+
| "No tmux session" error | Claude must run inside tmux, not a regular terminal |
|
|
306
|
+
| Query timeout | Check daemon running: `curl http://127.0.0.1:8377/health` |
|
|
307
|
+
| Wrong peer name | Peer name = folder name, not tmux window name |
|
|
308
|
+
| Hook not firing | Check `~/.claude/settings.json` has repowire hooks |
|
|
309
|
+
|
|
310
|
+
### Quick Verification Script (Claudemux)
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
#!/bin/bash
|
|
314
|
+
# quick-test-claudemux.sh - Verifies claudemux backend functionality
|
|
315
|
+
|
|
316
|
+
echo "=== Checking daemon ==="
|
|
317
|
+
curl -s http://127.0.0.1:8377/health | jq . || echo "ERROR: Daemon not running!"
|
|
318
|
+
|
|
319
|
+
echo "=== Checking hooks ==="
|
|
320
|
+
repowire claudemux status
|
|
321
|
+
|
|
322
|
+
echo "=== Listing peers ==="
|
|
323
|
+
repowire peer list
|
|
324
|
+
|
|
325
|
+
echo "=== Checking pending queries ==="
|
|
326
|
+
ls -la ~/.repowire/pending/ 2>/dev/null || echo "No pending queries"
|
|
327
|
+
```
|
repowire-0.1.1/PKG-INFO
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: repowire
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Mesh network for AI coding agents - enables Claude Code and OpenCode sessions to communicate
|
|
5
|
+
Author: Prassanna Ravishankar
|
|
6
|
+
License: MIT
|
|
7
|
+
Keywords: agents,ai,claude,mcp,mesh,opencode
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Requires-Python: >=3.10
|
|
16
|
+
Requires-Dist: click>=8.1.7
|
|
17
|
+
Requires-Dist: fastapi>=0.109.0
|
|
18
|
+
Requires-Dist: httpx>=0.26.0
|
|
19
|
+
Requires-Dist: mcp>=1.0.0
|
|
20
|
+
Requires-Dist: pydantic-settings>=2.1.0
|
|
21
|
+
Requires-Dist: pydantic>=2.5.0
|
|
22
|
+
Requires-Dist: pyyaml>=6.0.1
|
|
23
|
+
Requires-Dist: rich>=13.7.0
|
|
24
|
+
Requires-Dist: uvicorn[standard]>=0.27.0
|
|
25
|
+
Provides-Extra: all
|
|
26
|
+
Requires-Dist: libtmux>=0.37.0; extra == 'all'
|
|
27
|
+
Provides-Extra: claudemux
|
|
28
|
+
Requires-Dist: libtmux>=0.37.0; extra == 'claudemux'
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: mypy>=1.0.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
32
|
+
Requires-Dist: pytest-httpx>=0.30.0; extra == 'dev'
|
|
33
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
34
|
+
Requires-Dist: ruff>=0.1.0; extra == 'dev'
|
|
35
|
+
Provides-Extra: relay
|
|
36
|
+
Requires-Dist: python-socketio>=5.10.0; extra == 'relay'
|
|
37
|
+
Requires-Dist: redis>=5.0.1; extra == 'relay'
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+
<div align="center">
|
|
41
|
+
<picture>
|
|
42
|
+
<source srcset="https://raw.githubusercontent.com/prassanna-ravishankar/repowire/main/images/logo-dark.webp" media="(prefers-color-scheme: dark)" width="150" height="150" />
|
|
43
|
+
<img src="https://raw.githubusercontent.com/prassanna-ravishankar/repowire/main/images/logo-light.webp" alt="Repowire Logo" width="150" height="150" />
|
|
44
|
+
</picture>
|
|
45
|
+
|
|
46
|
+
<h1>Repowire</h1>
|
|
47
|
+
<p>Mesh network for AI coding agents (Claude Code, OpenCode) - enables sessions to communicate.</p>
|
|
48
|
+
</div>
|
|
49
|
+
|
|
50
|
+
## Quick Start
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
# One-time setup (installs hooks + MCP server)
|
|
54
|
+
repowire setup --dev # use --dev for local development
|
|
55
|
+
|
|
56
|
+
# Start daemon
|
|
57
|
+
repowire serve
|
|
58
|
+
|
|
59
|
+
# Start Claude in tmux windows - peers auto-register via SessionStart hook
|
|
60
|
+
tmux new-window -n alice
|
|
61
|
+
cd ~/projects/frontend && claude
|
|
62
|
+
|
|
63
|
+
tmux new-window -n bob
|
|
64
|
+
cd ~/projects/backend && claude
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Alice and Bob can now talk:
|
|
68
|
+
```
|
|
69
|
+
# In Alice's Claude session:
|
|
70
|
+
"Ask bob what API endpoints they have"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## How It Works
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
┌─────────────┐ ┌─────────────┐
|
|
77
|
+
│ Alice │ ask_peer("bob", ...) │ Bob │
|
|
78
|
+
│ (claude) │ ───────────────────► │ (claude) │
|
|
79
|
+
│ │ │ │
|
|
80
|
+
│ │ ◄───────────────── │ │
|
|
81
|
+
│ │ Stop hook captures │ │
|
|
82
|
+
└─────────────┘ response & returns └─────────────┘
|
|
83
|
+
│ │
|
|
84
|
+
└──────────┐ ┌──────────────┘
|
|
85
|
+
▼ ▼
|
|
86
|
+
┌─────────────────────┐
|
|
87
|
+
│ HTTP Daemon │
|
|
88
|
+
│ 127.0.0.1:8377 │
|
|
89
|
+
│ │
|
|
90
|
+
│ - routes queries │
|
|
91
|
+
│ - tracks pending │
|
|
92
|
+
│ - receives hooks │
|
|
93
|
+
└─────────────────────┘
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
1. **SessionStart hook** registers peer with metadata (name = folder name, git branch)
|
|
97
|
+
2. **SessionStart hook** injects peer context into Claude (lists available peers)
|
|
98
|
+
3. **ask_peer** sends query to daemon, daemon injects into target's tmux pane
|
|
99
|
+
4. **Target Claude** responds naturally
|
|
100
|
+
5. **Stop hook** fires at end of turn, captures response from transcript
|
|
101
|
+
6. **Response** routes back to caller via daemon
|
|
102
|
+
|
|
103
|
+
## Backends
|
|
104
|
+
|
|
105
|
+
Repowire supports two backends for different AI coding environments:
|
|
106
|
+
|
|
107
|
+
### claudemux (default)
|
|
108
|
+
For **Claude Code** sessions running in tmux.
|
|
109
|
+
- Peers auto-register via SessionStart hook
|
|
110
|
+
- Responses captured via Stop hook reading transcript
|
|
111
|
+
- Requires: tmux, Claude Code with hooks support
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
repowire setup --backend claudemux
|
|
115
|
+
repowire serve --backend claudemux
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### opencode
|
|
119
|
+
For **OpenCode** sessions using the opencode-ai SDK.
|
|
120
|
+
- Responses returned directly from SDK (no hooks needed)
|
|
121
|
+
- Requires: OpenCode server running
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
repowire setup --backend opencode
|
|
125
|
+
repowire serve --backend opencode
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Set default backend in config: `daemon.backend: "claudemux"` or `"opencode"`
|
|
129
|
+
|
|
130
|
+
## MCP Tools
|
|
131
|
+
|
|
132
|
+
| Tool | Description |
|
|
133
|
+
|------|-------------|
|
|
134
|
+
| `list_peers()` | List all registered peers and their status |
|
|
135
|
+
| `ask_peer(peer_name, query)` | Ask a peer a question, wait for response |
|
|
136
|
+
| `notify_peer(peer_name, message)` | Proactively share info (don't use for responses) |
|
|
137
|
+
| `broadcast(message)` | Send message to all peers (announcements only) |
|
|
138
|
+
|
|
139
|
+
Note: Peers auto-register via SessionStart hook. Your response to `ask_peer` queries is captured automatically - don't use `notify_peer` to respond.
|
|
140
|
+
|
|
141
|
+
## CLI Commands
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
# Peer management
|
|
145
|
+
repowire peer list # List peers and status
|
|
146
|
+
repowire peer register NAME -t TMUX -p PATH # Register a peer (claudemux)
|
|
147
|
+
repowire peer register NAME -u URL -p PATH # Register a peer (opencode)
|
|
148
|
+
repowire peer unregister NAME # Remove a peer
|
|
149
|
+
repowire peer ask NAME "query" # Test: ask a peer
|
|
150
|
+
|
|
151
|
+
# Backend-specific hook/plugin management
|
|
152
|
+
repowire claudemux install # Install Claude Code hooks
|
|
153
|
+
repowire claudemux uninstall # Remove hooks
|
|
154
|
+
repowire claudemux status # Check installation
|
|
155
|
+
repowire opencode install # Install OpenCode plugin
|
|
156
|
+
repowire opencode status # Check installation
|
|
157
|
+
|
|
158
|
+
# Daemon
|
|
159
|
+
repowire serve # Start daemon (default backend)
|
|
160
|
+
repowire serve --backend claudemux # Start with specific backend
|
|
161
|
+
repowire serve --backend opencode # Start with OpenCode backend
|
|
162
|
+
|
|
163
|
+
# Relay server (self-hosted)
|
|
164
|
+
repowire relay start --port 8000 # Start relay server
|
|
165
|
+
repowire relay generate-key # Generate API key
|
|
166
|
+
|
|
167
|
+
# Configuration
|
|
168
|
+
repowire config show # Show current config
|
|
169
|
+
repowire config path # Show config file path
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Multi-Machine Setup
|
|
173
|
+
|
|
174
|
+
For Claude sessions on different machines, use the relay server:
|
|
175
|
+
|
|
176
|
+
### 1. Deploy relay (or use repowire.io)
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# Self-hosted
|
|
180
|
+
repowire relay start --port 8000
|
|
181
|
+
|
|
182
|
+
# Or use hosted relay at relay.repowire.io
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
### 2. Generate API key
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
repowire relay generate-key --user-id myuser
|
|
189
|
+
# Save the generated key
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### 3. Start daemon on each machine
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
# Configure relay in ~/.repowire/config.yaml, then:
|
|
196
|
+
repowire serve
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Configuration
|
|
200
|
+
|
|
201
|
+
Config file: `~/.repowire/config.yaml`
|
|
202
|
+
|
|
203
|
+
```yaml
|
|
204
|
+
daemon:
|
|
205
|
+
host: "127.0.0.1"
|
|
206
|
+
port: 8377
|
|
207
|
+
backend: "claudemux" # or "opencode"
|
|
208
|
+
auto_reconnect: true
|
|
209
|
+
heartbeat_interval: 30
|
|
210
|
+
|
|
211
|
+
relay:
|
|
212
|
+
enabled: false
|
|
213
|
+
url: "wss://relay.repowire.io"
|
|
214
|
+
api_key: null
|
|
215
|
+
|
|
216
|
+
# Peers auto-populate via SessionStart hook
|
|
217
|
+
peers:
|
|
218
|
+
frontend:
|
|
219
|
+
name: frontend
|
|
220
|
+
path: "/Users/you/app/frontend"
|
|
221
|
+
tmux_session: "0:frontend" # claudemux backend
|
|
222
|
+
session_id: "abc123..." # set by hook
|
|
223
|
+
metadata:
|
|
224
|
+
branch: "feat/new-ui" # git branch, auto-detected
|
|
225
|
+
backend:
|
|
226
|
+
name: backend
|
|
227
|
+
path: "/Users/you/app/backend"
|
|
228
|
+
opencode_url: "http://localhost:4096" # opencode backend
|
|
229
|
+
session_id: "def456..."
|
|
230
|
+
metadata:
|
|
231
|
+
branch: "main"
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## Testing the Flow
|
|
235
|
+
|
|
236
|
+
Use tmux MCP to set up test peers:
|
|
237
|
+
|
|
238
|
+
1. Start daemon: `repowire serve &`
|
|
239
|
+
2. Create windows for alice and bob via `tmux-mcp create-window`
|
|
240
|
+
3. In each window, run: `cd ~/development/projects/<some-project> && claude`
|
|
241
|
+
4. Verify with `repowire peer list` - peers show as folder names (e.g., `a2a-chat`)
|
|
242
|
+
5. In alice's session: "Ask a2a-chat what this project does"
|
|
243
|
+
6. Clean up: kill the tmux windows via `tmux-mcp kill-window`
|
|
244
|
+
|
|
245
|
+
Note: Peer name = folder name, not tmux window name.
|
|
246
|
+
|
|
247
|
+
## Requirements
|
|
248
|
+
|
|
249
|
+
- Python 3.10+
|
|
250
|
+
- tmux (for claudemux backend)
|
|
251
|
+
- Claude Code with hooks support (for claudemux backend)
|
|
252
|
+
- OpenCode (for opencode backend)
|
|
253
|
+
|
|
254
|
+
## License
|
|
255
|
+
|
|
256
|
+
MIT
|