pi-messenger 0.9.0 → 0.10.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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.10.0] - 2026-02-05
4
+
5
+ ### Fixed
6
+ - **Crew spawner applies agent definitions** — Spawned crew workers now receive the agent's system prompt (`--append-system-prompt`), tool restrictions (`--tools`), and model override from their `.md` definitions. Previously a phantom `--agent` flag was passed that pi-core silently ignored, the agent name leaked into the prompt as noise, and the system prompts (worker's 6-phase protocol, reviewer's rubric, planner's exploration workflow) were never delivered. Tool restrictions also take effect: reviewers and interview generators are now limited to `read,bash` instead of getting all default builtins including `write` and `edit`.
7
+ - **Crew spawner session cleanup** — Spawned workers now pass `--no-session` to avoid writing ephemeral session files to disk.
8
+
9
+ ### Added
10
+ - **`--crew-install` / `--crew-uninstall` CLI flags** — `npx pi-messenger --crew-install` copies crew agent `.md` files and the `pi-messenger-crew` skill to user directories. `--crew-uninstall` removes them. Reads from the npm package (not the installed extension) to avoid version skew.
11
+
12
+ ### Changed
13
+ - **README rewrite** — Installation section now shows real CLI commands instead of tool-call syntax. "How It Works" section explains pi extension API hooks (`pi.on()`, `pi.sendMessage()`, `{ block: true }`, `ctx.ui.custom()`) instead of listing directory trees.
14
+
3
15
  ## [0.9.0] - 2026-02-05
4
16
 
5
17
  ### Added
package/README.md CHANGED
@@ -6,106 +6,76 @@
6
6
 
7
7
  **What if multiple agents in different terminals sharing a folder could talk to each other like they're in a chat room?** Join, see who's online and what they're doing. Claim tasks, reserve files, send messages. Built on [Pi's](https://github.com/badlogic/pi-mono) extension system. No daemon, no server, just files.
8
8
 
9
+ [![npm version](https://img.shields.io/npm/v/pi-messenger?style=for-the-badge)](https://www.npmjs.com/package/pi-messenger)
9
10
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg?style=for-the-badge)](LICENSE)
10
11
  [![Platform](https://img.shields.io/badge/Platform-macOS%20%7C%20Linux-blue?style=for-the-badge)]()
11
12
 
12
- > ⚠️ **Beta** - Core messaging, presence, and file reservations are stable. **Crew task orchestration** (plan/work/review) is newer and not fully tested yet. Please [open an issue](https://github.com/nicobailon/pi-messenger/issues) if you encounter problems.
13
-
14
- Pi-messenger adds a `pi_messenger` tool that **agents use** for coordination. You don't type these commands - you ask your agent to do things, and it calls `pi_messenger` behind the scenes.
15
-
16
- ## Quick Start
17
-
18
- ### Multi-Agent Coordination
19
-
20
- Once joined (manually or via auto-join config), agents can coordinate:
21
-
22
- ```typescript
23
- pi_messenger({ action: "reserve", paths: ["src/auth/"], reason: "Refactoring" })
24
- // → Reserved src/auth/ - other agents will be blocked
25
-
26
- // ... does the work ...
13
+ ## Installation
27
14
 
28
- pi_messenger({ action: "release" })
29
- // Released all reservations
15
+ ```bash
16
+ pi install npm:pi-messenger
30
17
  ```
31
18
 
32
- > **Tip:** Set `autoRegister: true` in your config to auto-join on startup. Otherwise, agents join with `pi_messenger({ action: "join" })`.
33
-
34
- ### Crew Task Orchestration
35
-
36
- Ask your agent to plan and execute from a PRD:
37
-
38
- ```typescript
39
- pi_messenger({ action: "plan" })
40
- // → Planner analyzes codebase, creates tasks
19
+ Crew agents and the `pi-messenger-crew` skill are auto-installed on first use of `plan`, `work`, or `review`. To install them ahead of time:
41
20
 
42
- pi_messenger({ action: "work", autonomous: true })
43
- // Workers execute tasks in waves until done
21
+ ```bash
22
+ npx pi-messenger --crew-install
44
23
  ```
45
24
 
46
- > **Note:** Crew agents (planner, workers, reviewers) automatically join the mesh as their first action.
25
+ This copies `crew/agents/*.md` to `~/.pi/agent/agents/` and `skills/pi-messenger-crew/` to `~/.pi/agent/skills/`.
47
26
 
48
- ## Installation
27
+ To remove the extension:
49
28
 
50
29
  ```bash
51
- pi install npm:pi-messenger
30
+ npx pi-messenger --remove
52
31
  ```
53
32
 
54
- To remove:
33
+ To also remove crew agents and skill:
55
34
 
56
35
  ```bash
57
- npx pi-messenger --remove
36
+ npx pi-messenger --crew-uninstall
58
37
  ```
59
38
 
60
- After joining, your agent name appears in the status bar:
39
+ ## Quick Start
40
+
41
+ Once joined (manually or via `autoRegister` config), agents can coordinate:
61
42
 
43
+ ```typescript
44
+ pi_messenger({ action: "join" })
45
+ pi_messenger({ action: "reserve", paths: ["src/auth/"], reason: "Refactoring" })
46
+ pi_messenger({ action: "send", to: "GoldFalcon", message: "auth is done" })
47
+ pi_messenger({ action: "release" })
62
48
  ```
63
- msg: SwiftRaven (2 peers) ●3
49
+
50
+ For multi-agent task orchestration from a PRD:
51
+
52
+ ```typescript
53
+ pi_messenger({ action: "plan" }) // Planner analyzes codebase, creates tasks
54
+ pi_messenger({ action: "work", autonomous: true }) // Workers execute tasks in waves until done
55
+ pi_messenger({ action: "review", target: "task-1" }) // Reviewer checks implementation
64
56
  ```
65
57
 
66
58
  ## Features
67
59
 
68
- **Living Presence** - Agents have rich presence with status indicators (🟢 active, 🟡 idle, 🟠 away, 🔴 stuck), tool call counts, token usage, and auto-generated status messages like "on fire 🔥" or "debugging...".
60
+ **Living Presence** - Status indicators (active, idle, away, stuck), tool call counts, token usage, and auto-generated status messages like "on fire" or "debugging...". Your agent name appears in the status bar: `msg: SwiftRaven (2 peers) ●3`
69
61
 
70
- **Activity Feed** - A unified timeline of everything happening: edits, commits, test runs, messages, task starts/completions. Crew events appear inline with a `[Crew]` prefix.
62
+ **Activity Feed** - Unified timeline of edits, commits, test runs, messages, and task events. Query with `{ action: "feed" }`.
71
63
 
72
64
  **Discovery** - Agents register with memorable themed names (SwiftRaven, LunarDust, OakTree). See who's active, what they're working on, which model and git branch they're on.
73
65
 
74
- **Messaging** - Send messages between agents. Recipients wake up immediately and see the message as a steering prompt. Great for handoffs and coordination.
66
+ **Messaging** - Send messages between agents. Recipients wake up immediately and see the message as a steering prompt.
75
67
 
76
68
  **File Reservations** - Claim files or directories. Other agents get blocked with a clear message telling them who to coordinate with. Auto-releases on exit.
77
69
 
78
- **Stuck Detection** - Agents idle too long with an open task or reservation are flagged as stuck. You get a notification so you can intervene.
79
-
80
- **Human as Participant** - Your interactive pi session appears in the agent list with `(you)`. Same activity tracking, same status messages. You can chat from the overlay.
70
+ **Stuck Detection** - Agents idle too long with an open task or reservation are flagged as stuck. Peers get a notification.
81
71
 
82
- **Swarm Coordination** - Multiple agents work on the same spec file. Claim tasks atomically, mark them complete, see who's doing what.
72
+ **Human as Participant** - Your interactive pi session appears in the agent list with `(you)`. Same activity tracking, same status messages. Chat from the overlay.
83
73
 
84
74
  ## Chat Overlay
85
75
 
86
76
  `/messenger` opens an interactive overlay with agent presence, activity feed, and chat:
87
77
 
88
- ```
89
- ╭─ Messenger ── 3 agents ── myapp ────────────────────╮
90
- │ │
91
- │ 🟢 SwiftRaven (you) │
92
- │ editing login.ts - 12 tools - 31.0k - on fire 🔥 │
93
- │ │
94
- │ 🟡 GoldFalcon idle 2m │
95
- │ 8 tools - 24.1k - 📁 src/api/ │
96
- │ │
97
- │ 🔴 IronKnight stuck │
98
- │ 3 tools - 16.4k │
99
- │ │
100
- │ Activity │
101
- │ 10:42 SwiftRaven editing login.ts │
102
- │ 10:40 GoldFalcon → SwiftRaven: "auth done?" │
103
- │ 10:38 SwiftRaven committed "feat: add OAuth" │
104
- │ 10:35 [Crew] GoldFalcon started task-03 │
105
- ├──────────────────────────────────────────────────────┤
106
- │ > @GoldFalcon almost done [Tab] [Enter]│
107
- ╰──────────────────────────────────────────────────────╯
108
- ```
78
+ <img width="722" height="351" alt="pi-messenger chat overlay" src="https://github.com/user-attachments/assets/4d0f1db7-90dd-4ffb-9463-560426edebd9" />
109
79
 
110
80
  Chat input supports `@Name msg` for DMs and `@all msg` for broadcasts. Text without `@` broadcasts from the Agents tab or DMs the selected agent tab.
111
81
 
@@ -118,120 +88,19 @@ Chat input supports `@Name msg` for DMs and `@all msg` for broadcasts. Text with
118
88
 
119
89
  ## Crew: Task Orchestration
120
90
 
121
- Crew provides multi-agent task orchestration with a simplified PRD-based workflow.
91
+ Crew turns a PRD into a dependency graph of tasks, then executes them in parallel waves.
122
92
 
123
- ### Basic Workflow
93
+ ### Workflow
124
94
 
125
- 1. **Plan** - Planner analyzes your codebase and PRD, creates tasks
126
- 2. **Work** - Workers implement tasks in parallel waves
127
- 3. **Review** - Reviewer checks each implementation
128
-
129
- ```typescript
130
- // Plan from your PRD (auto-discovers PRD.md, SPEC.md, etc.)
131
- pi_messenger({ action: "plan" })
132
-
133
- // Or specify PRD path explicitly
134
- pi_messenger({ action: "plan", prd: "docs/PRD.md" })
135
-
136
- // Execute tasks (spawns parallel workers)
137
- pi_messenger({ action: "work" })
138
-
139
- // Or run autonomously until done/blocked
140
- pi_messenger({ action: "work", autonomous: true })
141
-
142
- // Review a specific task
143
- pi_messenger({ action: "review", target: "task-1" })
144
- // → SHIP ✅ or NEEDS_WORK 🔄
145
- ```
146
-
147
- ### Crew API
148
-
149
- **Planning**
150
- | Action | Description | Example |
151
- |--------|-------------|---------|
152
- | `plan` | Create plan from PRD | `{ action: "plan" }` or `{ action: "plan", prd: "..." }` |
153
- | `status` | Show progress | `{ action: "status" }` |
154
-
155
- **Work Execution**
156
- | Action | Description | Example |
157
- |--------|-------------|---------|
158
- | `work` | Run ready tasks | `{ action: "work" }` |
159
- | `work` (auto) | Run until done/blocked | `{ action: "work", autonomous: true }` |
160
-
161
- **Task Management**
162
- | Action | Description | Example |
163
- |--------|-------------|---------|
164
- | `task.show` | Show task details | `{ action: "task.show", id: "task-1" }` |
165
- | `task.list` | List all tasks | `{ action: "task.list" }` |
166
- | `task.start` | Start task | `{ action: "task.start", id: "task-1" }` |
167
- | `task.done` | Complete task | `{ action: "task.done", id: "task-1", summary: "..." }` |
168
- | `task.block` | Block task | `{ action: "task.block", id: "task-1", reason: "..." }` |
169
- | `task.unblock` | Unblock task | `{ action: "task.unblock", id: "task-1" }` |
170
- | `task.ready` | List ready tasks | `{ action: "task.ready" }` |
171
- | `task.reset` | Reset task | `{ action: "task.reset", id: "task-1", cascade: true }` |
172
-
173
- **Review**
174
- | Action | Description | Example |
175
- |--------|-------------|---------|
176
- | `review` | Review implementation | `{ action: "review", target: "task-1" }` |
177
-
178
- **Maintenance**
179
- | Action | Description | Example |
180
- |--------|-------------|---------|
181
- | `crew.status` | Overall status | `{ action: "crew.status" }` |
182
- | `crew.validate` | Validate plan | `{ action: "crew.validate" }` |
183
- | `crew.agents` | List crew agents | `{ action: "crew.agents" }` |
184
- | `crew.install` | Install crew agents | `{ action: "crew.install" }` |
185
-
186
- ### Planning Workflow
187
-
188
- The `plan` action runs a multi-pass planning loop: the planner drafts tasks, a reviewer checks them against the PRD, and the planner refines until SHIP or `planning.maxPasses` is reached. All passes and feedback are stored in `.pi/messenger/crew/planning-progress.md`.
189
-
190
- ```
191
- ┌─────────────────────────────────────────────────────────────────┐
192
- │ Your Project │
193
- │ ├── PRD.md ◄── Planner discovers and reads these │
194
- │ ├── DESIGN.md │
195
- │ ├── src/ │
196
- │ └── ... │
197
- └─────────────────────────────────────────────────────────────────┘
198
-
199
-
200
- ┌─────────────────────────────────────────────────────────────────┐
201
- │ Planner (opus) │
202
- │ ├── Explores codebase structure and patterns │
203
- │ ├── Reads project documentation │
204
- │ ├── Identifies gaps, edge cases, security concerns │
205
- │ └── Drafts task breakdown with dependencies │
206
- └─────────────────────────────────────────────────────────────────┘
207
- │ append to
208
-
209
- ┌─────────────────────────────────────────────────────────────────┐
210
- │ planning-progress.md (history + feedback) │
211
- └─────────────────────────────────────────────────────────────────┘
212
-
213
-
214
- ┌─────────────────────────────────────────────────────────────────┐
215
- │ Reviewer (gpt-5.2-high) │
216
- │ ├── SHIP ✅ or NEEDS_WORK 🔄 │
217
- │ └── Feeds back into the next planner pass │
218
- └─────────────────────────────────────────────────────────────────┘
219
- │ SHIP
220
-
221
- ┌─────────────────────────────────────────────────────────────────┐
222
- │ Result: Tasks with Dependencies │
223
- │ ├── task-1: Setup types (no deps) │
224
- │ ├── task-2: Core logic (depends on task-1) │
225
- │ ├── task-3: API endpoints (depends on task-1) │
226
- │ └── task-4: Tests (depends on task-2, task-3) │
227
- └─────────────────────────────────────────────────────────────────┘
228
- ```
95
+ 1. **Plan** Planner explores the codebase and PRD, drafts tasks with dependencies. A reviewer checks the plan; the planner refines until SHIP or `maxPasses` is reached. History is stored in `planning-progress.md`.
96
+ 2. **Work** Workers implement ready tasks (all dependencies met) in parallel waves. A single `work` call runs one wave. `autonomous: true` runs waves back-to-back until everything is done or blocked.
97
+ 3. **Review** Reviewer checks each implementation: SHIP, NEEDS_WORK, or MAJOR_RETHINK.
229
98
 
230
- **No special format required** -- just put your docs in the project. The planner finds and reads markdown files, READMEs, and code comments.
99
+ No special PRD format required the planner auto-discovers `PRD.md`, `SPEC.md`, `DESIGN.md`, etc. in your project root and `docs/`.
231
100
 
232
- ### How Work Execution Works
101
+ ### Wave Execution
233
102
 
234
- Crew doesn't run tasks sequentially. Tasks form a dependency graph, and the work handler executes them in **waves** based on what's ready:
103
+ Tasks form a dependency graph. Independent tasks run concurrently:
235
104
 
236
105
  ```
237
106
  Wave 1: task-1 (no deps) ─┐
@@ -243,63 +112,7 @@ Wave 2: task-2 (→ task-1) ─┤── task-1 done, task-2 unblocked
243
112
  Wave 3: task-5 (→ task-2, task-4) ── both deps done
244
113
  ```
245
114
 
246
- A task is **ready** when its status is pending and all its dependencies are completed. Each wave picks all ready tasks (up to `concurrency.workers`), spawns parallel workers, waits for them to finish, then checks what's newly unblocked. Independent tasks those that don't depend on each other — run concurrently in the same wave.
247
-
248
- The planner structures tasks to maximize this parallelism. Foundation work (types, config, schemas) has no dependencies so it starts immediately. Features that don't touch each other get separate dependency chains so they can run in parallel. Tasks that need shared work done first (tests, integration, docs) depend on the tasks that produce it.
249
-
250
- A single `work` call runs one wave. Autonomous mode (`autonomous: true`) runs waves back-to-back until everything is done or blocked.
251
-
252
- ### Autonomous Mode
253
-
254
- Run tasks continuously until completion:
255
-
256
- ```typescript
257
- pi_messenger({ action: "work", autonomous: true })
258
- ```
259
-
260
- Autonomous mode:
261
- - Executes waves of parallel workers
262
- - Auto-blocks on failure
263
- - Stops when all tasks done or blocked
264
- - Respects `maxWaves` limit (default: 50)
265
-
266
- ### Crew Overlay Tab
267
-
268
- The `/messenger` overlay includes a Crew tab showing task status:
269
-
270
- ```
271
- ╭─ Messenger ── 3 agents ── myapp ──────────────────────╮
272
- │ Agents │ ▸ Crew (2/5) │ ● GoldFalcon │ + All │
273
- ├──────────────────────────────────────────────────────┤
274
- │ │
275
- │ 📋 docs/PRD.md [2/5] │
276
- │ │
277
- │ ✓ task-1 Setup OAuth config │
278
- │ ✓ task-2 Implement token storage │
279
- │ ● task-3 Add Google provider (SwiftRaven) │
280
- │ ○ task-4 Add GitHub provider → task-2 │
281
- │ ○ task-5 Write tests → task-3, task-4 │
282
- │ │
283
- ├──────────────────────────────────────────────────────┤
284
- │ ● AUTO Wave 2 │ 2/5 done │ 1 ready │ ⏱️ 3:42 │
285
- ╰──────────────────────────────────────────────────────╯
286
- ```
287
-
288
- ### Crew Data Storage
289
-
290
- ```
291
- .pi/messenger/crew/
292
- ├── plan.json # Plan metadata (PRD path, progress)
293
- ├── plan.md # Planner output
294
- ├── planning-progress.md # Planning loop history + feedback
295
- ├── tasks/
296
- │ ├── task-1.json # Task metadata
297
- │ ├── task-1.md # Task specification
298
- │ └── ...
299
- ├── blocks/ # Block context for blocked tasks
300
- ├── artifacts/ # Debug artifacts
301
- └── config.json # Project-level crew config
302
- ```
115
+ The planner structures tasks to maximize parallelism. Foundation work has no dependencies and starts immediately. Features that don't touch each other get separate chains. Autonomous mode stops when all tasks are done or blocked.
303
116
 
304
117
  ### Crew Configuration
305
118
 
@@ -316,121 +129,55 @@ Add to `~/.pi/agent/pi-messenger.json`:
316
129
  }
317
130
  ```
318
131
 
319
- | Setting | Description | Default |
320
- |---------|-------------|---------|
321
- | `concurrency.workers` | Max parallel workers during work | `2` |
322
- | `review.enabled` | Enable review functionality | `true` |
323
- | `review.maxIterations` | Max review iterations per task | `3` |
324
- | `planning.maxPasses` | Max planner passes before accepting last output | `3` |
325
- | `work.maxAttemptsPerTask` | Retries before blocking a task | `5` |
326
- | `work.maxWaves` | Max waves in autonomous mode | `50` |
327
-
328
- ### Crew Install
132
+ Crew agents (planner, worker, reviewer, interview-generator, plan-sync) are **auto-installed** on first use. Run `npx pi-messenger --crew-install` to manually install or update.
329
133
 
330
- Crew agents are **auto-installed** on first use of `plan`, `work`, or `review`. To manually install or update:
134
+ ## API Reference
331
135
 
332
- ```typescript
333
- pi_messenger({ action: "crew.install" })
334
- ```
136
+ ### Coordination
335
137
 
336
- **What gets installed:**
337
- - **5 agents** in `~/.pi/agent/agents/` (planner, worker, reviewer, interview-generator, plan-sync)
338
- - **1 skill** in `~/.pi/agent/skills/` (pi-messenger-crew quick reference)
339
-
340
- To remove:
341
- ```typescript
342
- pi_messenger({ action: "crew.uninstall" })
343
- ```
344
-
345
- ## Tool Reference
346
-
347
- ### Action-Based API (Recommended)
348
-
349
- **Coordination**
350
138
  | Action | Description |
351
139
  |--------|-------------|
352
140
  | `join` | Join the agent mesh |
353
141
  | `list` | List agents with presence info |
354
142
  | `status` | Show your status or crew progress |
355
- | `whois` | Detailed info about an agent |
356
- | `feed` | Show activity feed |
357
- | `set_status` | Set custom status message (omit `message` to clear) |
358
- | `send` | Send DM (requires `to` + `message`) |
359
- | `broadcast` | Broadcast to all (requires `message`) |
360
- | `reserve` | Reserve files (requires `paths`) |
361
- | `release` | Release reservations (optional `paths`, or releases all) |
362
- | `rename` | Change your name (requires `name`) |
363
- | `swarm` | Show swarm task status |
364
- | `claim` | Claim a swarm task (requires `taskId`) |
365
- | `unclaim` | Release a swarm claim (requires `taskId`) |
366
- | `complete` | Complete a swarm task (requires `taskId`) |
143
+ | `whois` | Detailed info about an agent (`name` required) |
144
+ | `feed` | Show activity feed (`limit` optional, default: 20) |
145
+ | `set_status` | Set custom status message (`message` optional — omit to clear) |
146
+ | `send` | Send DM (`to` + `message` required) |
147
+ | `broadcast` | Broadcast to all (`message` required) |
148
+ | `reserve` | Reserve files (`paths` required, `reason` optional) |
149
+ | `release` | Release reservations (`paths` optional omit to release all) |
150
+ | `rename` | Change your name (`name` required) |
367
151
 
368
- ```typescript
369
- pi_messenger({
370
- action: string, // Action to perform
371
-
372
- // Coordination
373
- name?: string, // For whois, rename
374
- message?: string, // For send, broadcast, set_status
375
- to?: string | string[], // For send
376
- paths?: string[], // For reserve, release
377
- reason?: string, // For reserve, claim, task.block
378
- limit?: number, // For feed (default: 20)
379
-
380
- // Plan
381
- prd?: string, // PRD file path
382
-
383
- // Task identifiers
384
- id?: string, // Task ID (task-N)
385
- taskId?: string, // Swarm task ID
386
- target?: string, // Target for review
387
-
388
- // Creation
389
- title?: string, // For task.create
390
- dependsOn?: string[], // Task dependencies
391
-
392
- // Completion
393
- summary?: string, // For task.done
394
-
395
- // Work options
396
- autonomous?: boolean, // Run continuously
397
- concurrency?: number, // Override concurrency
398
-
399
- // Reset
400
- cascade?: boolean, // Reset dependent tasks too
401
- })
402
- ```
152
+ ### Crew
403
153
 
404
- ### Legacy API
154
+ | Action | Description |
155
+ |--------|-------------|
156
+ | `plan` | Create plan from PRD (`prd` optional — auto-discovers if omitted) |
157
+ | `work` | Run ready tasks (`autonomous`, `concurrency` optional) |
158
+ | `review` | Review implementation (`target` task ID required) |
159
+ | `task.list` | List all tasks |
160
+ | `task.show` | Show task details (`id` required) |
161
+ | `task.start` | Start a task (`id` required) |
162
+ | `task.done` | Complete a task (`id` required, `summary` optional) |
163
+ | `task.block` | Block a task (`id` + `reason` required) |
164
+ | `task.unblock` | Unblock a task (`id` required) |
165
+ | `task.ready` | List tasks ready to work |
166
+ | `task.reset` | Reset a task (`id` required, `cascade` optional) |
167
+ | `crew.status` | Overall crew status |
168
+ | `crew.validate` | Validate plan dependencies |
169
+ | `crew.agents` | List available crew agents |
170
+ | `crew.install` | Install/update crew agents |
171
+ | `crew.uninstall` | Remove crew agents and skill |
172
+
173
+ ### Swarm (Spec-Based)
405
174
 
406
- ```typescript
407
- pi_messenger({
408
- // Join
409
- join?: boolean, // Join the agent mesh
410
- spec?: string, // Spec file to work on
411
-
412
- // Swarm
413
- swarm?: boolean, // Get swarm status
414
- claim?: string, // Claim a task
415
- unclaim?: string, // Release without completing
416
- complete?: string, // Mark task complete
417
- notes?: string, // Completion notes
418
-
419
- // Messaging
420
- to?: string | string[], // Recipient(s)
421
- broadcast?: boolean, // Send to all
422
- message?: string, // Message text
423
-
424
- // Reservations
425
- reserve?: string[], // Paths to reserve
426
- reason?: string, // Why reserving/claiming
427
- release?: string[] | true, // Release reservations
428
-
429
- // Other
430
- rename?: string, // Change your name
431
- list?: boolean, // List active agents
432
- })
433
- ```
175
+ | Action | Description |
176
+ |--------|-------------|
177
+ | `swarm` | Show swarm task status |
178
+ | `claim` | Claim a task (`taskId` required) |
179
+ | `unclaim` | Release a claim (`taskId` required) |
180
+ | `complete` | Complete a task (`taskId` required) |
434
181
 
435
182
  ## Configuration
436
183
 
@@ -452,32 +199,30 @@ Create `~/.pi/agent/pi-messenger.json`:
452
199
  | `autoRegister` | Join mesh on startup | `false` |
453
200
  | `autoRegisterPaths` | Folders where auto-join is enabled (supports `*` globs) | `[]` |
454
201
  | `scopeToFolder` | Only see agents in same directory | `false` |
455
- | `nameTheme` | Name generation theme: `default`, `nature`, `space`, `minimal`, `custom` | `"default"` |
202
+ | `nameTheme` | Name theme: `default`, `nature`, `space`, `minimal`, `custom` | `"default"` |
456
203
  | `nameWords` | Custom theme words: `{ adjectives: [...], nouns: [...] }` | — |
457
204
  | `feedRetention` | Max events kept in activity feed | `50` |
458
- | `stuckThreshold` | Seconds of inactivity before stuck detection | `900` (15m) |
205
+ | `stuckThreshold` | Seconds of inactivity before stuck detection | `900` |
459
206
  | `stuckNotify` | Show notification when a peer appears stuck | `true` |
460
207
  | `autoStatus` | Auto-generate status messages from activity | `true` |
461
208
  | `crewEventsInFeed` | Include crew task events in activity feed | `true` |
462
209
  | `contextMode` | Context injection level: `full`, `minimal`, `none` | `"full"` |
463
210
 
211
+ Config priority: project `.pi/pi-messenger.json` > user `~/.pi/agent/pi-messenger.json` > `~/.pi/agent/settings.json` `"messenger"` key > defaults.
212
+
464
213
  ## How It Works
465
214
 
466
- ```
467
- ~/.pi/agent/messenger/
468
- ├── registry/ # Agent registrations (PID, cwd, model, activity, tokens)
469
- ├── inbox/ # Message delivery
470
- ├── feed.jsonl # Activity feed (append-only, pruned on startup)
471
- ├── claims.json # Active task claims
472
- ├── completions.json # Completed tasks
473
- └── swarm.lock # Atomic lock for claims
474
- ```
215
+ Pi-messenger is a [pi extension](https://github.com/badlogic/pi-mono) that hooks into the agent lifecycle. It uses `pi.on("tool_call")` and `pi.on("tool_result")` to track activity — every edit, commit, and test run gets logged. `pi.on("session_start")` handles auto-registration, `pi.on("session_shutdown")` cleans up, and `pi.on("agent_end")` drives autonomous crew mode by checking for ready tasks after each agent turn.
216
+
217
+ Incoming messages wake the receiving agent via `pi.sendMessage()` with `triggerTurn: true` and `deliverAs: "steer"`, which injects the message as a steering prompt that resumes the agent. File reservations are enforced by returning `{ block: true }` from a `tool_call` hook on write/edit operations. The `/messenger` overlay uses `ctx.ui.custom()` for the chat TUI, and `ctx.ui.setStatus()` keeps the status bar updated with peer count and unread messages.
218
+
219
+ Crew workers are spawned as `pi --mode json` subprocesses with the agent's system prompt, model, and tool restrictions from their `.md` definitions. Progress is tracked via JSONL streaming. The planner and reviewer work the same way — just pi instances with different agent configs.
475
220
 
476
- File-based coordination. No daemon. Activity tracking updates the registry every 10 seconds via debounced flushes. Dead agents detected via PID and cleaned up automatically - a "leave" event is logged when stale registrations are removed.
221
+ All coordination is file-based, no daemon required. Global state (registry, inboxes, activity feed) lives in `~/.pi/agent/messenger/`. Per-project crew data (plan, tasks, artifacts) lives in `.pi/messenger/crew/` inside your project. Dead agents are detected via PID checks and cleaned up automatically.
477
222
 
478
223
  ## Credits
479
224
 
480
- - **[mcp_agent_mail](https://github.com/Dicklesworthstone/mcp_agent_mail)** by [@doodlestein](https://x.com/doodlestein) - Inspiration for agent-to-agent messaging
225
+ - **[mcp_agent_mail](https://github.com/Dicklesworthstone/mcp_agent_mail)** by [@doodlestein](https://x.com/doodlestein) Inspiration for agent-to-agent messaging
481
226
  - **[Pi coding agent](https://github.com/badlogic/pi-mono/)** by [@badlogicgames](https://x.com/badlogicgames)
482
227
 
483
228
  ## License
package/crew/agents.ts CHANGED
@@ -6,6 +6,8 @@
6
6
 
7
7
  import { spawn } from "node:child_process";
8
8
  import { randomUUID } from "node:crypto";
9
+ import * as fs from "node:fs";
10
+ import * as os from "node:os";
9
11
  import * as path from "node:path";
10
12
  import { fileURLToPath } from "node:url";
11
13
  import { discoverCrewAgents, type CrewAgentConfig } from "./utils/discover.js";
@@ -31,6 +33,7 @@ import type { AgentTask, AgentResult } from "./types.js";
31
33
  const __filename = fileURLToPath(import.meta.url);
32
34
  const __dirname = path.dirname(__filename);
33
35
  const EXTENSION_DIR = path.resolve(__dirname, "..");
36
+ const BUILTIN_TOOLS = new Set(["read", "bash", "edit", "write", "grep", "find", "ls"]);
34
37
 
35
38
  export interface SpawnOptions {
36
39
  onProgress?: (results: AgentResult[]) => void;
@@ -113,12 +116,41 @@ async function runAgent(
113
116
 
114
117
  return new Promise((resolve) => {
115
118
  // Build args for pi command
116
- const args = ["--mode", "json", "--agent", task.agent, "-p", task.task];
119
+ const args = ["--mode", "json", "--no-session", "-p"];
117
120
  if (agentConfig?.model) args.push("--model", agentConfig.model);
118
-
121
+
122
+ if (agentConfig?.tools?.length) {
123
+ const builtinTools: string[] = [];
124
+ const extensionPaths: string[] = [];
125
+ for (const tool of agentConfig.tools) {
126
+ if (tool.includes("/") || tool.endsWith(".ts") || tool.endsWith(".js")) {
127
+ extensionPaths.push(tool);
128
+ } else if (BUILTIN_TOOLS.has(tool)) {
129
+ builtinTools.push(tool);
130
+ }
131
+ }
132
+
133
+ if (builtinTools.length > 0) {
134
+ args.push("--tools", builtinTools.join(","));
135
+ }
136
+ for (const extensionPath of extensionPaths) {
137
+ args.push("--extension", extensionPath);
138
+ }
139
+ }
140
+
119
141
  // Pass extension so workers can use pi_messenger
120
142
  args.push("--extension", EXTENSION_DIR);
121
143
 
144
+ let promptTmpDir: string | null = null;
145
+ if (agentConfig?.systemPrompt) {
146
+ promptTmpDir = fs.mkdtempSync(path.join(os.tmpdir(), "pi-messenger-agent-"));
147
+ const promptPath = path.join(promptTmpDir, `${task.agent.replace(/[^\w.-]/g, "_")}.md`);
148
+ fs.writeFileSync(promptPath, agentConfig.systemPrompt, { mode: 0o600 });
149
+ args.push("--append-system-prompt", promptPath);
150
+ }
151
+
152
+ args.push(task.task);
153
+
122
154
  const proc = spawn("pi", args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
123
155
 
124
156
  let jsonlBuffer = "";
@@ -166,6 +198,10 @@ async function runAgent(
166
198
  });
167
199
  }
168
200
 
201
+ if (promptTmpDir) {
202
+ try { fs.rmSync(promptTmpDir, { recursive: true, force: true }); } catch {}
203
+ }
204
+
169
205
  resolve({
170
206
  agent: task.agent,
171
207
  exitCode: code ?? 1,
@@ -194,4 +230,3 @@ async function runAgent(
194
230
  }
195
231
  });
196
232
  }
197
-
package/install.mjs CHANGED
@@ -7,8 +7,10 @@
7
7
  * No git dependency — the npm package IS the source.
8
8
  *
9
9
  * Usage:
10
- * npx pi-messenger # Install or update
11
- * npx pi-messenger --remove # Remove the extension
10
+ * npx pi-messenger # Install or update extension
11
+ * npx pi-messenger --remove # Remove the extension
12
+ * npx pi-messenger --crew-install # Install crew agents and skills
13
+ * npx pi-messenger --crew-uninstall # Remove crew agents and skills
12
14
  */
13
15
 
14
16
  import * as fs from "node:fs";
@@ -19,12 +21,35 @@ import { fileURLToPath } from "node:url";
19
21
  const __filename = fileURLToPath(import.meta.url);
20
22
  const PACKAGE_DIR = path.dirname(__filename);
21
23
  const EXTENSION_DIR = path.join(os.homedir(), ".pi", "agent", "extensions", "pi-messenger");
24
+ const AGENTS_DIR = path.join(os.homedir(), ".pi", "agent", "agents");
25
+ const SKILLS_DIR = path.join(os.homedir(), ".pi", "agent", "skills");
26
+
27
+ const CREW_AGENTS = [
28
+ "crew-planner.md",
29
+ "crew-interview-generator.md",
30
+ "crew-plan-sync.md",
31
+ "crew-worker.md",
32
+ "crew-reviewer.md",
33
+ ];
34
+
35
+ const DEPRECATED_AGENTS = [
36
+ "crew-repo-scout.md",
37
+ "crew-practice-scout.md",
38
+ "crew-docs-scout.md",
39
+ "crew-web-scout.md",
40
+ "crew-github-scout.md",
41
+ "crew-gap-analyst.md",
42
+ ];
43
+
44
+ const CREW_SKILLS = ["pi-messenger-crew"];
22
45
 
23
46
  const pkg = JSON.parse(fs.readFileSync(path.join(PACKAGE_DIR, "package.json"), "utf-8"));
24
47
  const VERSION = pkg.version;
25
48
 
26
49
  const args = process.argv.slice(2);
27
50
  const isRemove = args.includes("--remove") || args.includes("-r");
51
+ const isCrewInstall = args.includes("--crew-install");
52
+ const isCrewUninstall = args.includes("--crew-uninstall");
28
53
  const isHelp = args.includes("--help") || args.includes("-h");
29
54
 
30
55
  if (isHelp) {
@@ -32,15 +57,103 @@ if (isHelp) {
32
57
  pi-messenger v${VERSION} - Multi-agent coordination for pi
33
58
 
34
59
  Usage:
35
- npx pi-messenger Install or update
36
- npx pi-messenger --remove Remove the extension
37
- npx pi-messenger --help Show this help
38
-
39
- Installation directory: ${EXTENSION_DIR}
60
+ npx pi-messenger Install or update extension
61
+ npx pi-messenger --remove Remove the extension
62
+ npx pi-messenger --crew-install Install crew agents and skills
63
+ npx pi-messenger --crew-uninstall Remove crew agents and skills
64
+ npx pi-messenger --help Show this help
65
+
66
+ Extension directory: ${EXTENSION_DIR}
67
+ Agents directory: ${AGENTS_DIR}
68
+ Skills directory: ${SKILLS_DIR}
40
69
  `);
41
70
  process.exit(0);
42
71
  }
43
72
 
73
+ // ─── Crew install ────────────────────────────────────────────────────────────
74
+
75
+ if (isCrewInstall) {
76
+ const sourceAgents = path.join(PACKAGE_DIR, "crew", "agents");
77
+ if (!fs.existsSync(sourceAgents)) {
78
+ console.error("Could not find crew agent files in package.");
79
+ process.exit(1);
80
+ }
81
+
82
+ fs.mkdirSync(AGENTS_DIR, { recursive: true });
83
+ fs.mkdirSync(SKILLS_DIR, { recursive: true });
84
+
85
+ let installed = 0;
86
+ let updated = 0;
87
+
88
+ for (const agent of DEPRECATED_AGENTS) {
89
+ const target = path.join(AGENTS_DIR, agent);
90
+ if (fs.existsSync(target)) {
91
+ fs.unlinkSync(target);
92
+ }
93
+ }
94
+
95
+ for (const agent of CREW_AGENTS) {
96
+ const src = path.join(sourceAgents, agent);
97
+ const dst = path.join(AGENTS_DIR, agent);
98
+ if (!fs.existsSync(src)) continue;
99
+ const existed = fs.existsSync(dst);
100
+ fs.copyFileSync(src, dst);
101
+ if (existed) updated++;
102
+ else installed++;
103
+ }
104
+
105
+ const sourceSkills = path.join(PACKAGE_DIR, "skills");
106
+ for (const skill of CREW_SKILLS) {
107
+ const srcDir = path.join(sourceSkills, skill);
108
+ const dstDir = path.join(SKILLS_DIR, skill);
109
+ if (!fs.existsSync(srcDir)) continue;
110
+ const existed = fs.existsSync(dstDir);
111
+ fs.mkdirSync(dstDir, { recursive: true });
112
+ for (const file of fs.readdirSync(srcDir)) {
113
+ const srcFile = path.join(srcDir, file);
114
+ if (fs.statSync(srcFile).isFile()) {
115
+ fs.copyFileSync(srcFile, path.join(dstDir, file));
116
+ }
117
+ }
118
+ if (existed) updated++;
119
+ else installed++;
120
+ }
121
+
122
+ console.log(`Crew installed (${installed} new, ${updated} updated)`);
123
+ console.log(` Agents: ${AGENTS_DIR}`);
124
+ console.log(` Skills: ${SKILLS_DIR}`);
125
+ process.exit(0);
126
+ }
127
+
128
+ // ─── Crew uninstall ──────────────────────────────────────────────────────────
129
+
130
+ if (isCrewUninstall) {
131
+ let removed = 0;
132
+
133
+ for (const agent of [...CREW_AGENTS, ...DEPRECATED_AGENTS]) {
134
+ const target = path.join(AGENTS_DIR, agent);
135
+ if (fs.existsSync(target)) {
136
+ fs.unlinkSync(target);
137
+ removed++;
138
+ }
139
+ }
140
+
141
+ for (const skill of CREW_SKILLS) {
142
+ const target = path.join(SKILLS_DIR, skill);
143
+ if (fs.existsSync(target)) {
144
+ fs.rmSync(target, { recursive: true });
145
+ removed++;
146
+ }
147
+ }
148
+
149
+ console.log(removed > 0
150
+ ? `Removed ${removed} crew file(s) from ${AGENTS_DIR} and ${SKILLS_DIR}`
151
+ : "Nothing to remove");
152
+ process.exit(0);
153
+ }
154
+
155
+ // ─── Extension remove ────────────────────────────────────────────────────────
156
+
44
157
  if (isRemove) {
45
158
  if (fs.existsSync(EXTENSION_DIR)) {
46
159
  fs.rmSync(EXTENSION_DIR, { recursive: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-messenger",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Inter-agent messaging and file reservation system for pi coding agent",
5
5
  "type": "module",
6
6
  "author": "Nico Bailon",