shipmate 0.1.0__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.
- shipmate-0.1.0/PKG-INFO +875 -0
- shipmate-0.1.0/docs/README.md +845 -0
- shipmate-0.1.0/pyproject.toml +48 -0
- shipmate-0.1.0/setup.cfg +4 -0
- shipmate-0.1.0/shipmate.egg-info/PKG-INFO +875 -0
- shipmate-0.1.0/shipmate.egg-info/SOURCES.txt +8 -0
- shipmate-0.1.0/shipmate.egg-info/dependency_links.txt +1 -0
- shipmate-0.1.0/shipmate.egg-info/entry_points.txt +2 -0
- shipmate-0.1.0/shipmate.egg-info/requires.txt +10 -0
- shipmate-0.1.0/shipmate.egg-info/top_level.txt +1 -0
shipmate-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,875 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: shipmate
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Autonomous AI dev agents as Docker containers — add to any project as a submodule
|
|
5
|
+
Author-email: Paul R <paulr978@gmail.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/paulr978/shipmate
|
|
8
|
+
Project-URL: Repository, https://github.com/paulr978/shipmate
|
|
9
|
+
Project-URL: Issues, https://github.com/paulr978/shipmate/issues
|
|
10
|
+
Keywords: ai,agents,docker,crewai,autonomous,dev-agents,ci
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Application Frameworks
|
|
17
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
18
|
+
Requires-Python: >=3.12
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
Requires-Dist: crewai>=0.108.0
|
|
21
|
+
Requires-Dist: crewai-tools>=0.38.0
|
|
22
|
+
Requires-Dist: anthropic>=0.52.0
|
|
23
|
+
Requires-Dist: gitpython>=3.1.43
|
|
24
|
+
Requires-Dist: PyGithub>=2.5.0
|
|
25
|
+
Requires-Dist: click>=8.1.7
|
|
26
|
+
Requires-Dist: docker>=7.1.0
|
|
27
|
+
Requires-Dist: pyyaml>=6.0.2
|
|
28
|
+
Requires-Dist: python-dotenv>=1.0.1
|
|
29
|
+
Requires-Dist: rich>=13.7.0
|
|
30
|
+
|
|
31
|
+
# Shipmate — Autonomous AI Development System
|
|
32
|
+
|
|
33
|
+
A reusable, project-local framework that runs autonomous dev agents as Docker containers. Each agent clones the repo, creates a branch, implements a task, validates, pushes, and opens a PR. A persistent PR monitor watches for stale branches and re-spawns agents to rebase and self-heal.
|
|
34
|
+
|
|
35
|
+
Project-agnostic. Configure for any repo via `shipmate.yml` + `.env` — no code changes needed.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Table of Contents
|
|
40
|
+
|
|
41
|
+
- [Quick Start](#quick-start)
|
|
42
|
+
- [Architecture Overview](#architecture-overview)
|
|
43
|
+
- [Directory Structure](#directory-structure)
|
|
44
|
+
- [CLI Reference](#cli-reference)
|
|
45
|
+
- [Agent Lifecycle](#agent-lifecycle)
|
|
46
|
+
- [PR Monitor](#pr-monitor)
|
|
47
|
+
- [Tools Reference](#tools-reference)
|
|
48
|
+
- [Configuration](#configuration)
|
|
49
|
+
- [PR Metadata Format](#pr-metadata-format)
|
|
50
|
+
- [Shared Services Policy](#shared-services-policy)
|
|
51
|
+
- [Conflict & Self-Healing Model](#conflict--self-healing-model)
|
|
52
|
+
- [Reusability Guide](#reusability-guide)
|
|
53
|
+
- [Security Model](#security-model)
|
|
54
|
+
- [Extending the System](#extending-the-system)
|
|
55
|
+
- [Troubleshooting](#troubleshooting)
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Quick Start
|
|
60
|
+
|
|
61
|
+
### Prerequisites
|
|
62
|
+
|
|
63
|
+
- Docker installed and running
|
|
64
|
+
- Python 3.12+
|
|
65
|
+
- `GITHUB_TOKEN` with repo + PR permissions (stored in `.env`)
|
|
66
|
+
- `ANTHROPIC_API_KEY` for Claude API access (stored in `.env`)
|
|
67
|
+
|
|
68
|
+
### The Easy Way — `launch.sh` / `launch.bat`
|
|
69
|
+
|
|
70
|
+
The launcher handles everything: creates the venv, loads secrets from `.env`, builds Docker images, checks the network, and launches agents.
|
|
71
|
+
|
|
72
|
+
**First time setup:**
|
|
73
|
+
1. Copy `.env.example` to `.env` at the project root
|
|
74
|
+
2. Add your `GITHUB_TOKEN` and `ANTHROPIC_API_KEY` to `.env`
|
|
75
|
+
3. Make sure Docker is running and shared services are up (`make up`)
|
|
76
|
+
|
|
77
|
+
**Then just run:**
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
# Linux/macOS/WSL
|
|
81
|
+
bash shipmate/launch.sh agent "Add pagination to /api/products/"
|
|
82
|
+
|
|
83
|
+
# Windows
|
|
84
|
+
shipmate\launch.bat agent "Add pagination to /api/products/"
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
The launcher will automatically:
|
|
88
|
+
- Create `shipmate/.venv` if it doesn't exist
|
|
89
|
+
- Install all shipmate dependencies
|
|
90
|
+
- Load secrets from `.env`
|
|
91
|
+
- Validate tokens are present
|
|
92
|
+
- Create the Docker network if needed
|
|
93
|
+
- Build the agent image if needed
|
|
94
|
+
- Launch the agent container
|
|
95
|
+
|
|
96
|
+
**Other launcher commands:**
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
# Launch agent in foreground (watch output live)
|
|
100
|
+
shipmate\launch.bat agent "Fix receipt parser bug" --no-detach
|
|
101
|
+
|
|
102
|
+
# Start the PR monitor
|
|
103
|
+
shipmate\launch.bat monitor
|
|
104
|
+
|
|
105
|
+
# Check running containers
|
|
106
|
+
shipmate\launch.bat status
|
|
107
|
+
|
|
108
|
+
# Stop the monitor
|
|
109
|
+
shipmate\launch.bat stop-monitor
|
|
110
|
+
|
|
111
|
+
# Rebuild Docker images
|
|
112
|
+
shipmate\launch.bat build
|
|
113
|
+
|
|
114
|
+
# Show help
|
|
115
|
+
shipmate\launch.bat help
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Manual Setup (Alternative)
|
|
119
|
+
|
|
120
|
+
If you prefer to manage things yourself:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# 1. Set up shipmate's own venv
|
|
124
|
+
cd shipmate
|
|
125
|
+
setup_venv.bat # Windows
|
|
126
|
+
bash setup_venv.sh # Linux/macOS/WSL
|
|
127
|
+
.venv\Scripts\activate # activate it
|
|
128
|
+
|
|
129
|
+
# 2. Set secrets (or source from .env)
|
|
130
|
+
export GITHUB_TOKEN=ghp_...
|
|
131
|
+
export ANTHROPIC_API_KEY=sk-ant-...
|
|
132
|
+
|
|
133
|
+
# 3. Build and run
|
|
134
|
+
python -m shipmate build
|
|
135
|
+
python -m shipmate run-agent --task "Add pagination to the /api/products/ endpoint"
|
|
136
|
+
|
|
137
|
+
# 4. (Optional) PR monitor
|
|
138
|
+
python -m shipmate build-monitor
|
|
139
|
+
python -m shipmate monitor-start
|
|
140
|
+
|
|
141
|
+
# 5. Check running agents
|
|
142
|
+
python -m shipmate list-agents
|
|
143
|
+
|
|
144
|
+
# Stop the monitor
|
|
145
|
+
python -m shipmate monitor-stop
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Architecture Overview
|
|
151
|
+
|
|
152
|
+
```
|
|
153
|
+
┌─────────────────────────────────────────────────────────┐
|
|
154
|
+
│ Your Machine (Host) │
|
|
155
|
+
│ │
|
|
156
|
+
│ python -m shipmate run-agent --task "..." │
|
|
157
|
+
│ │ │
|
|
158
|
+
│ ▼ │
|
|
159
|
+
│ ┌──────────────────┐ ┌──────────────────┐ │
|
|
160
|
+
│ │ Agent Container │ │ Agent Container │ ... │
|
|
161
|
+
│ │ (fresh clone) │ │ (fresh clone) │ │
|
|
162
|
+
│ │ shipmate/dev/task-A │ │ shipmate/dev/task-B │ │
|
|
163
|
+
│ └────────┬─────────┘ └────────┬─────────┘ │
|
|
164
|
+
│ │ │ │
|
|
165
|
+
│ └───────┬───────────────┘ │
|
|
166
|
+
│ ▼ │
|
|
167
|
+
│ ┌────────────────────────────────────────┐ │
|
|
168
|
+
│ │ project_backend_net (from shipmate.yml) │ │
|
|
169
|
+
│ │ ┌──────┐ ┌───────┐ ┌───────┐ │ │
|
|
170
|
+
│ │ │ db │ │ redis │ │ minio │ ... │ │
|
|
171
|
+
│ │ └──────┘ └───────┘ └───────┘ │ │
|
|
172
|
+
│ └────────────────────────────────────────┘ │
|
|
173
|
+
│ │
|
|
174
|
+
│ ┌──────────────────┐ │
|
|
175
|
+
│ │ PR Monitor │ (always-on, polls GitHub) │
|
|
176
|
+
│ │ re-spawns stale │ │
|
|
177
|
+
│ │ agent containers │ │
|
|
178
|
+
│ └──────────────────┘ │
|
|
179
|
+
└─────────────────────────────────────────────────────────┘
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
### Core Principles
|
|
183
|
+
|
|
184
|
+
1. **One task = one container.** Full filesystem isolation. No agent can interfere with another.
|
|
185
|
+
2. **Shared services are external.** Agents connect to the project's existing Docker network (db, redis, minio) but never own or mutate them destructively.
|
|
186
|
+
3. **Each agent gets its own branch.** Branch naming: `shipmate/dev/<agent-id>-<task-slug>-<timestamp>`.
|
|
187
|
+
4. **Each agent opens one PR.** PR body contains hidden metadata so the monitor can reconstruct the task later.
|
|
188
|
+
5. **Self-healing via PR monitor.** When master advances, the monitor detects stale AI PRs and re-spawns the original agent in rebase mode.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## Directory Structure
|
|
193
|
+
|
|
194
|
+
```
|
|
195
|
+
shipmate/
|
|
196
|
+
├── __init__.py
|
|
197
|
+
├── __main__.py # `python -m shipmate` entry point
|
|
198
|
+
├── main.py # Host-side CLI (click) — tasks, work, dashboard, agents
|
|
199
|
+
├── task_manager.py # Task queue CRUD (shipmate_tasks.yml backend)
|
|
200
|
+
├── entrypoint.py # Container lifecycle runner
|
|
201
|
+
├── Dockerfile # Agent container image
|
|
202
|
+
├── requirements.txt # Python dependencies
|
|
203
|
+
├── docker-compose.monitor.yml # Compose file for the PR monitor
|
|
204
|
+
├── setup_venv.sh # Venv setup script (Linux/macOS/WSL)
|
|
205
|
+
├── setup_venv.bat # Venv setup script (Windows)
|
|
206
|
+
├── .venv/ # shipmate's own virtual environment (gitignored)
|
|
207
|
+
│
|
|
208
|
+
├── config/
|
|
209
|
+
│ └── project.py # Loads config from env + shipmate.yml (framework code, don't edit)
|
|
210
|
+
│
|
|
211
|
+
├── context/
|
|
212
|
+
│ └── project_context.py # Reads repo files → context string for the agent
|
|
213
|
+
│
|
|
214
|
+
├── agents/
|
|
215
|
+
│ └── dev_agent.py # CrewAI Agent definition (role, tools, instructions)
|
|
216
|
+
│
|
|
217
|
+
├── tasks/
|
|
218
|
+
│ └── dev_task.py # CrewAI Task builder (normal + rebase modes)
|
|
219
|
+
│
|
|
220
|
+
├── crews/
|
|
221
|
+
│ └── dev_crew.py # Crew assembly: 1 agent, 1 task, sequential
|
|
222
|
+
│
|
|
223
|
+
├── tools/
|
|
224
|
+
│ ├── git_tools.py # 12 git tools (branch, commit, rebase, push, diff...)
|
|
225
|
+
│ ├── github_tools.py # 6 GitHub tools (create PR, comment, list AI PRs...)
|
|
226
|
+
│ ├── file_tools.py # 5 file tools (read, write, list, search, patch)
|
|
227
|
+
│ └── shell_tools.py # 3 shell tools (constrained commands, ruff check/format)
|
|
228
|
+
│
|
|
229
|
+
├── monitor/
|
|
230
|
+
│ ├── __init__.py
|
|
231
|
+
│ ├── Dockerfile # Monitor container image
|
|
232
|
+
│ └── pr_monitor.py # Polling service: detects stale PRs, re-spawns agents
|
|
233
|
+
│
|
|
234
|
+
└── docs/
|
|
235
|
+
└── README.md # This file
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
---
|
|
239
|
+
|
|
240
|
+
## CLI Reference
|
|
241
|
+
|
|
242
|
+
All commands run on the host via `python -m shipmate <command>` or `launch.sh <command>`.
|
|
243
|
+
|
|
244
|
+
### Task Management
|
|
245
|
+
|
|
246
|
+
#### `task add`
|
|
247
|
+
|
|
248
|
+
Add a task to the queue.
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
launch.sh task add "Add pagination to /api/products/" --priority high
|
|
252
|
+
launch.sh task add "Fix receipt parser bug" --priority critical --id fix-parser
|
|
253
|
+
launch.sh task add "Refactor analytics module" # defaults to normal priority
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
| Flag | Default | Description |
|
|
257
|
+
|------|---------|-------------|
|
|
258
|
+
| `--priority`, `-p` | `normal` | Priority: `critical`, `high`, `normal`, `low` |
|
|
259
|
+
| `--id` | auto-generated | Custom task ID |
|
|
260
|
+
|
|
261
|
+
#### `task list`
|
|
262
|
+
|
|
263
|
+
Show tasks in the queue.
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
launch.sh task list # pending + running only
|
|
267
|
+
launch.sh task list --all # include done/failed/cancelled
|
|
268
|
+
launch.sh task list -s pending # filter by status
|
|
269
|
+
launch.sh task list -p high # filter by priority
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
#### `task remove`
|
|
273
|
+
|
|
274
|
+
Remove a task.
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
launch.sh task remove fix-parser
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
#### `task update`
|
|
281
|
+
|
|
282
|
+
Change a task's priority, status, or description.
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
launch.sh task update fix-parser --priority critical
|
|
286
|
+
launch.sh task update fix-parser --status cancelled
|
|
287
|
+
launch.sh task update fix-parser --description "New description"
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
#### `work`
|
|
291
|
+
|
|
292
|
+
Pick up pending tasks (by priority) and launch agents.
|
|
293
|
+
|
|
294
|
+
```bash
|
|
295
|
+
launch.sh work # launch the next highest-priority task
|
|
296
|
+
launch.sh work --all # launch agents for ALL pending tasks
|
|
297
|
+
launch.sh work -n 3 # launch the top 3 tasks
|
|
298
|
+
launch.sh work --no-detach # single task, foreground (watch output)
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Tasks are picked in priority order: `critical > high > normal > low`, then FIFO within the same priority.
|
|
302
|
+
|
|
303
|
+
#### `dashboard`
|
|
304
|
+
|
|
305
|
+
Live overview of tasks, running agents, and results.
|
|
306
|
+
|
|
307
|
+
```bash
|
|
308
|
+
launch.sh dashboard # show once
|
|
309
|
+
launch.sh dashboard -w # auto-refresh every 5 seconds
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
#### `logs`
|
|
313
|
+
|
|
314
|
+
Shortcut to view agent container logs.
|
|
315
|
+
|
|
316
|
+
```bash
|
|
317
|
+
launch.sh logs dev-a1b2c3 # last 50 lines
|
|
318
|
+
launch.sh logs dev-a1b2c3 -f # follow (live)
|
|
319
|
+
launch.sh logs dev-a1b2c3 -n 200 # last 200 lines
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
### Direct Agent Control
|
|
323
|
+
|
|
324
|
+
#### `run-agent`
|
|
325
|
+
|
|
326
|
+
Launch an agent directly, bypassing the task queue.
|
|
327
|
+
|
|
328
|
+
```bash
|
|
329
|
+
launch.sh agent "Add pagination to /api/products/" --no-detach
|
|
330
|
+
launch.sh agent "Fix bug" --id my-fix --rebase
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
| Flag | Default | Description |
|
|
334
|
+
|------|---------|-------------|
|
|
335
|
+
| `--task`, `-t` | (required) | Task description |
|
|
336
|
+
| `--id` | auto | Agent identifier |
|
|
337
|
+
| `--branch`, `-b` | auto | Git branch name |
|
|
338
|
+
| `--rebase` | off | Rebase/conflict-resolution mode |
|
|
339
|
+
| `--detach/--no-detach` | detach | Background or foreground |
|
|
340
|
+
|
|
341
|
+
### Infrastructure
|
|
342
|
+
|
|
343
|
+
#### `build`
|
|
344
|
+
|
|
345
|
+
Build the agent Docker image.
|
|
346
|
+
|
|
347
|
+
```bash
|
|
348
|
+
launch.sh build [--no-cache]
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
#### `monitor` / `stop-monitor`
|
|
352
|
+
|
|
353
|
+
Start/stop the PR monitor.
|
|
354
|
+
|
|
355
|
+
```bash
|
|
356
|
+
launch.sh monitor [--interval 60]
|
|
357
|
+
launch.sh stop-monitor
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
#### `status`
|
|
361
|
+
|
|
362
|
+
Show running containers.
|
|
363
|
+
|
|
364
|
+
```bash
|
|
365
|
+
launch.sh status
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
#### `list-agents`
|
|
369
|
+
|
|
370
|
+
List running agent containers.
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
python -m shipmate list-agents
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## Agent Lifecycle
|
|
379
|
+
|
|
380
|
+
When you run `python -m shipmate run-agent --task "..."`, this is what happens:
|
|
381
|
+
|
|
382
|
+
```
|
|
383
|
+
Host: main.py
|
|
384
|
+
│
|
|
385
|
+
├── Generate agent ID, branch name
|
|
386
|
+
├── Validate GITHUB_TOKEN and ANTHROPIC_API_KEY
|
|
387
|
+
├── docker run shipmate-agent:latest with env vars
|
|
388
|
+
│
|
|
389
|
+
└── Container starts → entrypoint.py
|
|
390
|
+
│
|
|
391
|
+
├── 1. Clone repo from GitHub (authenticated via GITHUB_TOKEN)
|
|
392
|
+
├── 2. Configure git identity (shipmate-<agent-id>)
|
|
393
|
+
├── 3. Create branch (or checkout existing for rebase)
|
|
394
|
+
├── 4. Install backend requirements (pip install -r backend/requirements.txt)
|
|
395
|
+
├── 5. Build project context (reads CLAUDE.md, decisions.md, etc.)
|
|
396
|
+
├── 6. Run CrewAI dev crew
|
|
397
|
+
│ │
|
|
398
|
+
│ └── dev_agent.py executes the task:
|
|
399
|
+
│ ├── Read existing code (file_tools)
|
|
400
|
+
│ ├── Implement changes (file_tools)
|
|
401
|
+
│ ├── Run validation (shell_tools: ruff check, ruff format)
|
|
402
|
+
│ ├── Commit changes (git_tools)
|
|
403
|
+
│ ├── Push branch (git_tools)
|
|
404
|
+
│ └── Create PR with metadata (github_tools)
|
|
405
|
+
│
|
|
406
|
+
├── 7. Log result
|
|
407
|
+
└── 8. Exit (container stops)
|
|
408
|
+
```
|
|
409
|
+
|
|
410
|
+
### Rebase Mode
|
|
411
|
+
|
|
412
|
+
When `AGENT_REBASE=true` (set by the monitor or `--rebase` flag):
|
|
413
|
+
|
|
414
|
+
1. Checkout existing branch
|
|
415
|
+
2. Fetch latest from origin
|
|
416
|
+
3. Rebase onto `origin/master`
|
|
417
|
+
4. Resolve conflicts (simple ones automatically, complex ones flagged)
|
|
418
|
+
5. Re-run validation
|
|
419
|
+
6. Force-push the updated branch
|
|
420
|
+
7. Comment on the PR with a summary
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## PR Monitor
|
|
425
|
+
|
|
426
|
+
The PR monitor (`monitor/pr_monitor.py`) is a simple polling service — not a CrewAI agent.
|
|
427
|
+
|
|
428
|
+
### What It Does
|
|
429
|
+
|
|
430
|
+
```
|
|
431
|
+
Every N seconds:
|
|
432
|
+
│
|
|
433
|
+
├── Get latest master SHA from GitHub
|
|
434
|
+
├── If master hasn't changed → skip
|
|
435
|
+
├── If master advanced:
|
|
436
|
+
│ ├── List all open PRs on shipmate/* branches
|
|
437
|
+
│ ├── For each PR:
|
|
438
|
+
│ │ ├── Compare branch HEAD to master
|
|
439
|
+
│ │ ├── If stale (behind master):
|
|
440
|
+
│ │ │ ├── Comment on PR: "Re-spawning agent to rebase"
|
|
441
|
+
│ │ │ ├── docker run agent container in rebase mode
|
|
442
|
+
│ │ │ └── Track as active respawn
|
|
443
|
+
│ │ └── If up-to-date → skip
|
|
444
|
+
│ └── Clean up finished respawns
|
|
445
|
+
└── Sleep N seconds
|
|
446
|
+
```
|
|
447
|
+
|
|
448
|
+
### Running the Monitor
|
|
449
|
+
|
|
450
|
+
Option A — via CLI:
|
|
451
|
+
```bash
|
|
452
|
+
python -m shipmate monitor-start --interval 60
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
Option B — via docker-compose:
|
|
456
|
+
```bash
|
|
457
|
+
cd shipmate
|
|
458
|
+
docker-compose -f docker-compose.monitor.yml up -d
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
The monitor container mounts `/var/run/docker.sock` so it can spawn sibling agent containers.
|
|
462
|
+
|
|
463
|
+
### Environment Variables
|
|
464
|
+
|
|
465
|
+
| Variable | Default | Description |
|
|
466
|
+
|----------|---------|-------------|
|
|
467
|
+
| `GITHUB_TOKEN` | (required) | GitHub PAT |
|
|
468
|
+
| `ANTHROPIC_API_KEY` | (required) | Passed to spawned agents |
|
|
469
|
+
| `GITHUB_REPO` | (required) | Repository to watch |
|
|
470
|
+
| `BASE_BRANCH` | `master` | Branch to monitor |
|
|
471
|
+
| `POLL_INTERVAL` | `60` | Seconds between polls |
|
|
472
|
+
| `DOCKER_NETWORK` | (required) | Network agents join |
|
|
473
|
+
| `AGENT_IMAGE` | `shipmate-agent:latest` | Image for spawned agents |
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
## Tools Reference
|
|
478
|
+
|
|
479
|
+
### Git Tools (`tools/git_tools.py`)
|
|
480
|
+
|
|
481
|
+
All tools operate on the local repo clone at `/workspace`.
|
|
482
|
+
|
|
483
|
+
| Tool | Description |
|
|
484
|
+
|------|-------------|
|
|
485
|
+
| `create_branch` | Create and checkout a new branch |
|
|
486
|
+
| `checkout_branch` | Checkout an existing branch |
|
|
487
|
+
| `git_fetch` | Fetch from remote |
|
|
488
|
+
| `git_rebase` | Rebase current branch onto another |
|
|
489
|
+
| `git_rebase_continue` | Continue rebase after conflict resolution |
|
|
490
|
+
| `git_rebase_abort` | Abort a rebase |
|
|
491
|
+
| `git_commit` | Stage all changes and commit |
|
|
492
|
+
| `git_push` | Push branch to origin (supports force-with-lease) |
|
|
493
|
+
| `git_diff` | Show stat diff against a base branch |
|
|
494
|
+
| `git_changed_files` | List files changed vs a base branch |
|
|
495
|
+
| `git_status` | Show working tree status |
|
|
496
|
+
| `git_log` | Show recent log entries |
|
|
497
|
+
|
|
498
|
+
### GitHub Tools (`tools/github_tools.py`)
|
|
499
|
+
|
|
500
|
+
| Tool | Description |
|
|
501
|
+
|------|-------------|
|
|
502
|
+
| `create_pull_request` | Create a PR with optional metadata block |
|
|
503
|
+
| `update_pull_request` | Update PR title/body |
|
|
504
|
+
| `comment_on_pr` | Add a comment to a PR |
|
|
505
|
+
| `list_ai_pull_requests` | List all open PRs on `shipmate/*` branches |
|
|
506
|
+
| `get_pr_metadata` | Extract shipmate metadata from a PR body |
|
|
507
|
+
| `get_pr_changed_files` | List files changed in a PR |
|
|
508
|
+
|
|
509
|
+
### File Tools (`tools/file_tools.py`)
|
|
510
|
+
|
|
511
|
+
All paths are sandboxed to `/workspace`. Attempts to escape are rejected.
|
|
512
|
+
|
|
513
|
+
| Tool | Description |
|
|
514
|
+
|------|-------------|
|
|
515
|
+
| `read_file` | Read file contents (truncated at 50K chars) |
|
|
516
|
+
| `write_file` | Write/create a file |
|
|
517
|
+
| `list_directory` | Recursive directory listing (configurable depth) |
|
|
518
|
+
| `search_files` | Regex search across files (default: `*.py`) |
|
|
519
|
+
| `patch_file` | Find-and-replace a specific text block in a file |
|
|
520
|
+
|
|
521
|
+
### Shell Tools (`tools/shell_tools.py`)
|
|
522
|
+
|
|
523
|
+
Shell access is **constrained by an allowlist**. The agent cannot run arbitrary commands.
|
|
524
|
+
|
|
525
|
+
| Tool | Description |
|
|
526
|
+
|------|-------------|
|
|
527
|
+
| `run_shell_command` | Run an allowlisted command |
|
|
528
|
+
| `run_ruff_check` | Run `ruff check` (with optional `--fix`) |
|
|
529
|
+
| `run_ruff_format` | Run `ruff format` |
|
|
530
|
+
|
|
531
|
+
**Built-in allowed prefixes:** `ruff `, `pytest `, `pip install`, `pip list`, `pip show`, `cat `, `head `, `tail `, `wc `, `diff `, `find `, `ls `
|
|
532
|
+
|
|
533
|
+
**Built-in blocked patterns:** `rm -rf`, `rm -r /`, `DROP`, `DELETE FROM`, `TRUNCATE`, `FLUSHALL`, `FLUSHDB`
|
|
534
|
+
|
|
535
|
+
**Project-specific additions** are configured in `shipmate.yml` under `shell.allowed_prefixes` and `shell.blocked_patterns`. These are merged with the built-in lists at runtime.
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
## Configuration
|
|
540
|
+
|
|
541
|
+
shipmate is **project-agnostic**. All project-specific configuration comes from two sources:
|
|
542
|
+
|
|
543
|
+
### 1. `shipmate.yml` (project root)
|
|
544
|
+
|
|
545
|
+
This file lives at the root of your project (not inside `shipmate/`). It defines everything the agents need to know about your project: validation commands, context files, safety rules, shell allowlists, etc.
|
|
546
|
+
|
|
547
|
+
```yaml
|
|
548
|
+
github:
|
|
549
|
+
repo: your-org/your-repo
|
|
550
|
+
base_branch: main
|
|
551
|
+
branch_prefix: shipmate/dev
|
|
552
|
+
pr_title_prefix: "[AI]"
|
|
553
|
+
|
|
554
|
+
docker:
|
|
555
|
+
network: your-project_backend_net
|
|
556
|
+
|
|
557
|
+
context_files:
|
|
558
|
+
- README.md
|
|
559
|
+
- docs/architecture.md
|
|
560
|
+
|
|
561
|
+
requirements_file: requirements.txt
|
|
562
|
+
|
|
563
|
+
validation_commands:
|
|
564
|
+
- command: "npm run lint"
|
|
565
|
+
description: "Run linter"
|
|
566
|
+
- command: "npm test"
|
|
567
|
+
description: "Run tests"
|
|
568
|
+
|
|
569
|
+
shared_service_rules:
|
|
570
|
+
- "Do NOT drop or truncate database tables."
|
|
571
|
+
- "Do NOT flush Redis."
|
|
572
|
+
|
|
573
|
+
tech_stack:
|
|
574
|
+
- "Node.js 20"
|
|
575
|
+
- "PostgreSQL 16"
|
|
576
|
+
|
|
577
|
+
shell:
|
|
578
|
+
allowed_prefixes:
|
|
579
|
+
- "npm "
|
|
580
|
+
- "npx "
|
|
581
|
+
blocked_patterns:
|
|
582
|
+
- "npm run db:reset"
|
|
583
|
+
|
|
584
|
+
llm:
|
|
585
|
+
model: claude-sonnet-4-6
|
|
586
|
+
max_tokens: 8192
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
See the `shipmate.yml` at the root of this repo for a complete example.
|
|
590
|
+
|
|
591
|
+
### 2. `.env` (secrets + overrides)
|
|
592
|
+
|
|
593
|
+
Secrets and simple overrides go in your `.env` file (gitignored).
|
|
594
|
+
|
|
595
|
+
**Required:**
|
|
596
|
+
|
|
597
|
+
| Variable | Purpose |
|
|
598
|
+
|----------|---------|
|
|
599
|
+
| `GITHUB_TOKEN` | Clone, push, PR operations |
|
|
600
|
+
| `ANTHROPIC_API_KEY` | LLM calls inside agent containers |
|
|
601
|
+
|
|
602
|
+
**Optional overrides** (take precedence over `shipmate.yml`):
|
|
603
|
+
|
|
604
|
+
| Variable | Overrides |
|
|
605
|
+
|----------|-----------|
|
|
606
|
+
| `SHIPMATE_GITHUB_REPO` | `github.repo` |
|
|
607
|
+
| `SHIPMATE_BASE_BRANCH` | `github.base_branch` |
|
|
608
|
+
| `SHIPMATE_DOCKER_NETWORK` | `docker.network` |
|
|
609
|
+
| `SHIPMATE_BRANCH_PREFIX` | `github.branch_prefix` |
|
|
610
|
+
| `SHIPMATE_LLM_MODEL` | `llm.model` |
|
|
611
|
+
| `SHIPMATE_LLM_MAX_TOKENS` | `llm.max_tokens` |
|
|
612
|
+
| `SHIPMATE_POLL_INTERVAL` | `monitor.poll_interval_seconds` |
|
|
613
|
+
| `SHIPMATE_AGENT_IMAGE_NAME` | `agent.image_name` |
|
|
614
|
+
| `SHIPMATE_AGENT_IMAGE_TAG` | `agent.image_tag` |
|
|
615
|
+
|
|
616
|
+
### 3. `config/project.py` (framework code — do not edit)
|
|
617
|
+
|
|
618
|
+
This file loads values from env vars and `shipmate.yml`. It has no hardcoded project values. You should never need to modify it.
|
|
619
|
+
|
|
620
|
+
### Priority order
|
|
621
|
+
|
|
622
|
+
```
|
|
623
|
+
Environment variable > shipmate.yml > built-in default
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
---
|
|
627
|
+
|
|
628
|
+
## PR Metadata Format
|
|
629
|
+
|
|
630
|
+
Every AI-created PR contains a hidden metadata block in its body:
|
|
631
|
+
|
|
632
|
+
```html
|
|
633
|
+
<!-- SHIPMATE_META
|
|
634
|
+
{
|
|
635
|
+
"task": "Add pagination to /api/products/",
|
|
636
|
+
"agent_id": "dev-a1b2c3",
|
|
637
|
+
"branch": "shipmate/dev/dev-a1b2c3-add-pagination-20260328-143022",
|
|
638
|
+
"created_at": "2026-03-28T14:30:22.000000+00:00",
|
|
639
|
+
"rebase_count": 0
|
|
640
|
+
}
|
|
641
|
+
SHIPMATE_META -->
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
This block is invisible when viewing the PR on GitHub but parseable by the monitor. It allows the monitor to:
|
|
645
|
+
|
|
646
|
+
- Reconstruct the original task description
|
|
647
|
+
- Re-spawn the exact same agent
|
|
648
|
+
- Track how many times a branch has been rebased
|
|
649
|
+
|
|
650
|
+
The `encode_pr_metadata()` and `decode_pr_metadata()` functions in `tools/github_tools.py` handle serialization.
|
|
651
|
+
|
|
652
|
+
---
|
|
653
|
+
|
|
654
|
+
## Shared Services Policy
|
|
655
|
+
|
|
656
|
+
Agents attach to the project's Docker network and can reach shared services. Strict rules apply:
|
|
657
|
+
|
|
658
|
+
### Allowed
|
|
659
|
+
|
|
660
|
+
- Read from the running database (inspect schema, query data)
|
|
661
|
+
- Read from Redis (check keys, inspect state)
|
|
662
|
+
- Run targeted validation commands (`manage.py check`, `manage.py showmigrations`)
|
|
663
|
+
- Run linting and formatting
|
|
664
|
+
- Run isolated tests if safe (must use per-agent test DB: `test_agent_{agent_id}`)
|
|
665
|
+
|
|
666
|
+
### Not Allowed
|
|
667
|
+
|
|
668
|
+
- `manage.py migrate` — never migrate the shared development database
|
|
669
|
+
- `manage.py flush` / `manage.py loaddata` / `manage.py dumpdata`
|
|
670
|
+
- `FLUSHALL` / `FLUSHDB` on Redis
|
|
671
|
+
- Delete or overwrite objects in MinIO
|
|
672
|
+
- Any destructive operation on shared infrastructure
|
|
673
|
+
|
|
674
|
+
These rules are enforced at two levels:
|
|
675
|
+
1. **Shell allowlist** — blocked patterns in `shell_tools.py` prevent the commands from running
|
|
676
|
+
2. **Agent instructions** — safety rules are injected into the agent's backstory so the LLM avoids attempting them
|
|
677
|
+
|
|
678
|
+
---
|
|
679
|
+
|
|
680
|
+
## Conflict & Self-Healing Model
|
|
681
|
+
|
|
682
|
+
### Automatic Resolution (agent handles)
|
|
683
|
+
|
|
684
|
+
- Simple merge conflicts in different parts of a file
|
|
685
|
+
- Migration numbering conflicts (e.g., two agents both create `0005_...`)
|
|
686
|
+
- Import ordering conflicts
|
|
687
|
+
- Naming conflicts for newly added files/classes if detectable
|
|
688
|
+
- Minor upstream refactors that don't change semantics
|
|
689
|
+
|
|
690
|
+
### Escalation (agent marks PR for human review)
|
|
691
|
+
|
|
692
|
+
- Semantic conflicts in the same function/method
|
|
693
|
+
- Contradictory schema changes
|
|
694
|
+
- Cases where the task intent is no longer valid after upstream changes
|
|
695
|
+
- Risky shared-service changes
|
|
696
|
+
|
|
697
|
+
When escalating, the agent:
|
|
698
|
+
1. Updates the PR body with a warning section
|
|
699
|
+
2. Comments on the PR explaining the conflict
|
|
700
|
+
3. Leaves the branch in a clean state (rebase aborted if necessary)
|
|
701
|
+
|
|
702
|
+
---
|
|
703
|
+
|
|
704
|
+
## Reusability Guide
|
|
705
|
+
|
|
706
|
+
shipmate is designed to be dropped into any project. The `shipmate/` directory contains zero project-specific values.
|
|
707
|
+
|
|
708
|
+
### Step 1: Copy the directory
|
|
709
|
+
|
|
710
|
+
```bash
|
|
711
|
+
cp -r shipmate/ /path/to/other-project/shipmate/
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
### Step 2: Create `shipmate.yml` at your project root
|
|
715
|
+
|
|
716
|
+
```yaml
|
|
717
|
+
github:
|
|
718
|
+
repo: your-org/your-repo
|
|
719
|
+
base_branch: main
|
|
720
|
+
|
|
721
|
+
docker:
|
|
722
|
+
network: your-project_backend_net
|
|
723
|
+
|
|
724
|
+
context_files:
|
|
725
|
+
- README.md
|
|
726
|
+
|
|
727
|
+
validation_commands:
|
|
728
|
+
- command: "npm run lint"
|
|
729
|
+
description: "Lint check"
|
|
730
|
+
|
|
731
|
+
tech_stack:
|
|
732
|
+
- "Node.js 20"
|
|
733
|
+
- "Express"
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
### Step 3: Add secrets to `.env`
|
|
737
|
+
|
|
738
|
+
```
|
|
739
|
+
GITHUB_TOKEN=ghp_...
|
|
740
|
+
ANTHROPIC_API_KEY=sk-ant-...
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
### Step 4: Update the Dockerfile (if needed)
|
|
744
|
+
|
|
745
|
+
If your project uses a different language/runtime, update `shipmate/Dockerfile` to install the right system dependencies. The default image includes Python 3.12, git, and common build tools.
|
|
746
|
+
|
|
747
|
+
### What you DON'T need to change
|
|
748
|
+
|
|
749
|
+
- `config/project.py` — reads from env + `shipmate.yml` automatically
|
|
750
|
+
- `tools/shell_tools.py` — shell allowlists/blocklists are configured in `shipmate.yml`
|
|
751
|
+
- CLI, entrypoint, agent/task/crew wiring, git/github tools, PR monitor, metadata format
|
|
752
|
+
|
|
753
|
+
### Files that are project-specific (live outside `shipmate/`)
|
|
754
|
+
|
|
755
|
+
| File | Purpose |
|
|
756
|
+
|------|---------|
|
|
757
|
+
| `shipmate.yml` | Project config (repo, network, validation, rules) |
|
|
758
|
+
| `.env` | Secrets and optional overrides |
|
|
759
|
+
| `shipmate/Dockerfile` | System deps (only if your stack differs) |
|
|
760
|
+
|
|
761
|
+
---
|
|
762
|
+
|
|
763
|
+
## Security Model
|
|
764
|
+
|
|
765
|
+
### Secrets
|
|
766
|
+
|
|
767
|
+
- `GITHUB_TOKEN` and `ANTHROPIC_API_KEY` are passed as container env vars
|
|
768
|
+
- Never baked into Docker images
|
|
769
|
+
- Never committed to the repo
|
|
770
|
+
|
|
771
|
+
### GitHub Token Scopes
|
|
772
|
+
|
|
773
|
+
The token needs:
|
|
774
|
+
- `repo` — clone, push branches
|
|
775
|
+
- `pull_request` — create, update, comment on PRs
|
|
776
|
+
|
|
777
|
+
### Container Isolation
|
|
778
|
+
|
|
779
|
+
- Each agent runs in its own container with its own filesystem
|
|
780
|
+
- Workspace is sandboxed — file tools reject paths outside `/workspace`
|
|
781
|
+
- Shell access is allowlisted — only pre-approved commands run
|
|
782
|
+
- Destructive patterns are explicitly blocked
|
|
783
|
+
|
|
784
|
+
### Monitor Access
|
|
785
|
+
|
|
786
|
+
The monitor container mounts the Docker socket (`/var/run/docker.sock`) to spawn sibling containers. This is a privileged operation — the monitor should only run in trusted environments.
|
|
787
|
+
|
|
788
|
+
---
|
|
789
|
+
|
|
790
|
+
## Extending the System
|
|
791
|
+
|
|
792
|
+
### Adding a New Tool
|
|
793
|
+
|
|
794
|
+
1. Create a function in the appropriate `tools/*.py` module
|
|
795
|
+
2. Decorate with `@tool("tool_name")`
|
|
796
|
+
3. Add it to the agent's tool list in `agents/dev_agent.py`
|
|
797
|
+
|
|
798
|
+
Example:
|
|
799
|
+
|
|
800
|
+
```python
|
|
801
|
+
# tools/shell_tools.py
|
|
802
|
+
@tool("run_mypy")
|
|
803
|
+
def run_mypy(path: str = ".") -> str:
|
|
804
|
+
"""Run mypy type checker."""
|
|
805
|
+
return _run_command(f"mypy {path}")
|
|
806
|
+
```
|
|
807
|
+
|
|
808
|
+
Then add `"mypy "` to `shell.allowed_prefixes` in `shipmate.yml` and add the tool import in `dev_agent.py`.
|
|
809
|
+
|
|
810
|
+
### Adding a New Agent Type
|
|
811
|
+
|
|
812
|
+
1. Create `agents/frontend_agent.py` (or similar)
|
|
813
|
+
2. Create a corresponding task in `tasks/frontend_task.py`
|
|
814
|
+
3. Optionally create a new crew in `crews/frontend_crew.py`
|
|
815
|
+
4. Add a new CLI command in `main.py` (e.g., `run-frontend-agent`)
|
|
816
|
+
|
|
817
|
+
### Adding New Validation Commands
|
|
818
|
+
|
|
819
|
+
Update `shipmate.yml` at your project root:
|
|
820
|
+
|
|
821
|
+
```yaml
|
|
822
|
+
validation_commands:
|
|
823
|
+
- command: "ruff check --fix ."
|
|
824
|
+
description: "Lint check and auto-fix"
|
|
825
|
+
- command: "pytest backend/apps/myapp/tests/ -x"
|
|
826
|
+
description: "Run targeted tests"
|
|
827
|
+
|
|
828
|
+
shell:
|
|
829
|
+
allowed_prefixes:
|
|
830
|
+
- "pytest " # must be in the allowlist for validation to work
|
|
831
|
+
```
|
|
832
|
+
|
|
833
|
+
---
|
|
834
|
+
|
|
835
|
+
## Troubleshooting
|
|
836
|
+
|
|
837
|
+
### Agent container exits immediately
|
|
838
|
+
|
|
839
|
+
Check logs:
|
|
840
|
+
```bash
|
|
841
|
+
docker logs shipmate-<agent-id>
|
|
842
|
+
```
|
|
843
|
+
|
|
844
|
+
Common causes:
|
|
845
|
+
- Missing `GITHUB_TOKEN` or `ANTHROPIC_API_KEY`
|
|
846
|
+
- GitHub token lacks push/PR permissions
|
|
847
|
+
- Agent image not built (`python -m shipmate build`)
|
|
848
|
+
|
|
849
|
+
### Agent can't reach shared services
|
|
850
|
+
|
|
851
|
+
Make sure the project's Docker network exists and services are running:
|
|
852
|
+
```bash
|
|
853
|
+
docker network ls | grep backend_net
|
|
854
|
+
make up # from project root
|
|
855
|
+
```
|
|
856
|
+
|
|
857
|
+
### Monitor doesn't detect stale PRs
|
|
858
|
+
|
|
859
|
+
- Check monitor logs: `docker logs -f shipmate-monitor`
|
|
860
|
+
- Verify `GITHUB_REPO` and `BASE_BRANCH` are correct
|
|
861
|
+
- PRs must be on `shipmate/*` branches to be detected
|
|
862
|
+
|
|
863
|
+
### Clone fails inside container
|
|
864
|
+
|
|
865
|
+
- Verify `GITHUB_TOKEN` has `repo` scope
|
|
866
|
+
- For private repos, ensure the token has access
|
|
867
|
+
|
|
868
|
+
### Rebase fails with complex conflicts
|
|
869
|
+
|
|
870
|
+
The agent will attempt automatic resolution for simple conflicts. If it can't resolve, it will:
|
|
871
|
+
1. Abort the rebase
|
|
872
|
+
2. Comment on the PR explaining the conflict
|
|
873
|
+
3. The PR remains open for human review
|
|
874
|
+
|
|
875
|
+
Check the PR comments for details.
|