move pi-mono into companion-cloud as apps/companion-os

- Copy all pi-mono source into apps/companion-os/
- Update Dockerfile to COPY pre-built binary instead of downloading from GitHub Releases
- Update deploy-staging.yml to build pi from source (bun compile) before Docker build
- Add apps/companion-os/** to path triggers
- No more cross-repo dispatch needed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Harivansh Rathi 2026-03-07 09:22:50 -08:00
commit 0250f72976
579 changed files with 206942 additions and 0 deletions

View file

@ -0,0 +1,396 @@
# pi-teams Usage Guide
This guide provides detailed examples, patterns, and best practices for using pi-teams.
## Table of Contents
- [Getting Started](#getting-started)
- [Common Workflows](#common-workflows)
- [Hook System](#hook-system)
- [Best Practices](#best-practices)
- [Troubleshooting](#troubleshooting)
---
## Getting Started
### Basic Team Setup
First, make sure you're inside a tmux session, Zellij session, or iTerm2:
```bash
tmux # or zellij, or just use iTerm2
```
Then start pi:
```bash
pi
```
Create your first team:
> **You:** "Create a team named 'my-team'"
Set a default model for all teammates:
> **You:** "Create a team named 'Research' and use 'gpt-4o' for everyone"
---
## Common Workflows
### 1. Code Review Team
> **You:** "Create a team named 'code-review' using 'gpt-4o'"
> **You:** "Spawn a teammate named 'security-reviewer' to check for vulnerabilities"
> **You:** "Spawn a teammate named 'performance-reviewer' using 'haiku' to check for optimization opportunities"
> **You:** "Create a task for security-reviewer: 'Review the auth module for SQL injection risks' and set it to in_progress"
> **You:** "Create a task for performance-reviewer: 'Analyze the database queries for N+1 issues' and set it to in_progress"
### 2. Refactor with Plan Approval
> **You:** "Create a team named 'refactor-squad'"
> **You:** "Spawn a teammate named 'refactor-bot' and require plan approval before they make any changes"
> **You:** "Create a task for refactor-bot: 'Refactor the user service to use dependency injection' and set it to in_progress"
Teammate submits a plan. Review it:
> **You:** "List all tasks and show me refactor-bot's plan for task 1"
Approve or reject:
> **You:** "Approve refactor-bot's plan for task 1"
> **You:** "Reject refactor-bot's plan for task 1 with feedback: 'Add unit tests for the new injection pattern'"
### 3. Testing with Automated Hooks
Create a hook script at `.pi/team-hooks/task_completed.sh`:
```bash
#!/bin/bash
# This script runs automatically when any task is completed
echo "Running post-task checks..."
npm test
if [ $? -ne 0 ]; then
echo "Tests failed! Please fix before marking task complete."
exit 1
fi
npm run lint
echo "All checks passed!"
```
> **You:** "Create a team named 'test-team'"
> **You:** "Spawn a teammate named 'qa-bot' to write tests"
> **You:** "Create a task for qa-bot: 'Write unit tests for the payment module' and set it to in_progress"
When qa-bot marks the task as completed, the hook automatically runs tests and linting.
### 4. Coordinated Migration
> **You:** "Create a team named 'migration-team'"
> **You:** "Spawn a teammate named 'db-migrator' to handle database changes"
> **You:** "Spawn a teammate named 'api-updater' using 'gpt-4o' to update API endpoints"
> **You:** "Spawn a teammate named 'test-writer' to write tests for the migration"
> **You:** "Create a task for db-migrator: 'Add new columns to the users table' and set it to in_progress"
After db-migrator completes, broadcast the schema change:
> **You:** "Broadcast to the team: 'New columns added to users table: phone, email_verified. Please update your code accordingly.'"
### 5. Mixed-Speed Team
Use different models for cost optimization:
> **You:** "Create a team named 'mixed-speed' using 'gpt-4o'"
> **You:** "Spawn a teammate named 'architect' using 'gpt-4o' with 'high' thinking level for design decisions"
> **You:** "Spawn a teammate named 'implementer' using 'haiku' with 'low' thinking level for quick coding"
> **You:** "Spawn a teammate named 'reviewer' using 'gpt-4o' with 'medium' thinking level for code reviews"
Now you have expensive reasoning for design and reviews, but fast/cheap implementation.
---
## Hook System
### Overview
Hooks are shell scripts that run automatically at specific events. Currently supported:
- **`task_completed.sh`** - Runs when any task's status changes to `completed`
### Hook Location
Hooks should be placed in `.pi/team-hooks/` in your project directory:
```
your-project/
├── .pi/
│ └── team-hooks/
│ └── task_completed.sh
```
### Hook Payload
The hook receives the task data as a JSON string as the first argument:
```bash
#!/bin/bash
TASK_DATA="$1"
echo "Task completed: $TASK_DATA"
```
Example payload:
```json
{
"id": "task_123",
"subject": "Fix login bug",
"description": "Users can't login with special characters",
"status": "completed",
"owner": "fixer-bot"
}
```
### Example Hooks
#### Test on Completion
```bash
#!/bin/bash
# .pi/team-hooks/task_completed.sh
TASK_DATA="$1"
SUBJECT=$(echo "$TASK_DATA" | jq -r '.subject')
echo "Running tests after task: $SUBJECT"
npm test
```
#### Notify Slack
```bash
#!/bin/bash
# .pi/team-hooks/task_completed.sh
TASK_DATA="$1"
SUBJECT=$(echo "$TASK_DATA" | jq -r '.subject')
OWNER=$(echo "$TASK_DATA" | jq -r '.owner')
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"Task '$SUBJECT' completed by $OWNER\"}" \
"$SLACK_WEBHOOK_URL"
```
#### Conditional Checks
```bash
#!/bin/bash
# .pi/team-hooks/task_completed.sh
TASK_DATA="$1"
SUBJECT=$(echo "$TASK_DATA" | jq -r '.subject')
# Only run full test suite for production-related tasks
if [[ "$SUBJECT" == *"production"* ]] || [[ "$SUBJECT" == *"deploy"* ]]; then
npm run test:ci
else
npm test
fi
```
---
## Best Practices
### 1. Use Thinking Levels Wisely
- **`off`** - Simple tasks: formatting, moving code, renaming
- **`minimal`** - Quick decisions: small refactors, straightforward bugfixes
- **`low`** - Standard work: typical feature implementation, tests
- **`medium`** - Complex work: architecture decisions, tricky bugs
- **`high`** - Critical work: security reviews, major refactors, design specs
### 2. Team Composition
Balanced teams typically include:
- **1-2 high-thinking, high-model** agents for architecture and reviews
- **2-3 low-thinking, fast-model** agents for implementation
- **1 medium-thinking** agent for coordination
Example:
```bash
# Design/Review duo (expensive but thorough)
spawn "architect" using "gpt-4o" with "high" thinking
spawn "reviewer" using "gpt-4o" with "medium" thinking
# Implementation trio (fast and cheap)
spawn "backend-dev" using "haiku" with "low" thinking
spawn "frontend-dev" using "haiku" with "low" thinking
spawn "test-writer" using "haiku" with "off" thinking
```
### 3. Plan Approval for High-Risk Changes
Enable plan approval mode for:
- Database schema changes
- API contract changes
- Security-related work
- Performance-critical code
Disable for:
- Documentation updates
- Test additions
- Simple bug fixes
### 4. Broadcast for Coordination
Use broadcasts when:
- API endpoints change
- Database schemas change
- Deployment happens
- Team priorities shift
### 5. Clear Task Descriptions
Good task:
```
"Add password strength validation to the signup form.
Requirements: minimum 8 chars, at least one number and symbol.
Use the zxcvbn library for strength calculation."
```
Bad task:
```
"Fix signup form"
```
### 6. Check Progress Regularly
> **You:** "List all tasks"
> **You:** "Check my inbox for messages"
> **You:** "How is the team doing?"
This helps you catch blockers early and provide feedback.
---
## Troubleshooting
### Teammate Not Responding
**Problem**: A teammate is idle but not picking up messages.
**Solution**:
1. Check if they're still running:
> **You:** "Check on teammate named 'security-bot'"
2. Check their inbox:
> **You:** "Read security-bot's inbox"
3. Force kill and respawn if needed:
> **You:** "Force kill security-bot and respawn them"
### tmux Pane Issues
**Problem**: tmux panes don't close when killing teammates.
**Solution**: Make sure you started pi inside a tmux session. If you started pi outside tmux, it won't work properly.
```bash
# Correct way
tmux
pi
# Incorrect way
pi # Then try to use tmux commands
```
### Hook Not Running
**Problem**: Your task_completed.sh script isn't executing.
**Checklist**:
1. File exists at `.pi/team-hooks/task_completed.sh`
2. File is executable: `chmod +x .pi/team-hooks/task_completed.sh`
3. Shebang line is present: `#!/bin/bash`
4. Test manually: `.pi/team-hooks/task_completed.sh '{"test":"data"}'`
### Model Errors
**Problem**: "Model not found" or similar errors.
**Solution**: Check the model name is correct and available in your pi config. Some model names vary between providers:
- `gpt-4o` - OpenAI
- `haiku` - Anthropic (usually `claude-3-5-haiku`)
- `glm-4.7` - Zhipu AI
Check your pi config for available models.
### Data Location
All team data is stored in:
- `~/.pi/teams/<team-name>/` - Team configuration, member list
- `~/.pi/tasks/<team-name>/` - Task files
- `~/.pi/messages/<team-name>/` - Message history
You can manually inspect these JSON files to debug issues.
### iTerm2 Not Working
**Problem**: iTerm2 splits aren't appearing.
**Requirements**:
1. You must be on macOS
2. iTerm2 must be your terminal
3. You must NOT be inside tmux or Zellij (iTerm2 detection only works as a fallback)
**Alternative**: Use tmux or Zellij for more reliable pane management.
---
## Inter-Agent Communication
Teammates can message each other without your intervention:
```
Frontend Bot → Backend Bot: "What's the response format for /api/users?"
Backend Bot → Frontend Bot: "Returns {id, name, email, created_at}"
```
This enables autonomous coordination. You can see these messages by:
> **You:** "Read backend-bot's inbox"
---
## Cleanup
To remove all team data:
```bash
# Shut down team first
> "Shut down the team named 'my-team'"
# Then delete data directory
rm -rf ~/.pi/teams/my-team/
rm -rf ~/.pi/tasks/my-team/
rm -rf ~/.pi/messages/my-team/
```
Or use the delete command:
> **You:** "Delete the team named 'my-team'"

View file

@ -0,0 +1,283 @@
# pi-teams Core Features Implementation Plan
> **REQUIRED SUB-SKILL:** Use the executing-plans skill to implement this plan task-by-task.
**Goal:** Implement Plan Approval Mode, Broadcast Messaging, and Quality Gate Hooks for the `pi-teams` repository to achieve functional parity with Claude Code Agent Teams.
**Architecture:**
- **Plan Approval**: Add a `planning` status to `TaskFile.status`. Create `task_submit_plan` and `task_evaluate_plan` tools. Lead can approve/reject.
- **Broadcast Messaging**: Add a `broadcast_message` tool that iterates through the team roster in `config.json` and sends messages to all active members.
- **Quality Gate Hooks**: Introduce a simple hook system that triggers on `task_update` (specifically when status becomes `completed`). For now, it will look for a `.pi/team-hooks/task_completed.sh` or similar.
**Tech Stack:** Node.js, TypeScript, Vitest
---
## Phase 1: Plan Approval Mode
### Task 1: Update Task Models and Statuses
**Files:**
- Modify: `src/utils/models.ts`
**Step 1: Add `planning` to `TaskFile.status` and add `plan` field**
```typescript
export interface TaskFile {
id: string;
subject: string;
description: string;
activeForm?: string;
status: "pending" | "in_progress" | "planning" | "completed" | "deleted";
blocks: string[];
blockedBy: string[];
owner?: string;
plan?: string;
planFeedback?: string;
metadata?: Record<string, any>;
}
```
**Step 2: Commit**
```bash
git add src/utils/models.ts
git commit -m "feat: add planning status to TaskFile"
```
### Task 2: Implement Plan Submission Tool
**Files:**
- Modify: `src/utils/tasks.ts`
- Test: `src/utils/tasks.test.ts`
**Step 1: Write test for `submitPlan`**
```typescript
it("should update task status to planning and save plan", async () => {
const task = await createTask("test-team", "Task 1", "Desc");
const updated = await submitPlan("test-team", task.id, "My Plan");
expect(updated.status).toBe("planning");
expect(updated.plan).toBe("My Plan");
});
```
**Step 2: Implement `submitPlan` in `tasks.ts`**
```typescript
export async function submitPlan(
teamName: string,
taskId: string,
plan: string,
): Promise<TaskFile> {
return await updateTask(teamName, taskId, { status: "planning", plan });
}
```
**Step 3: Run tests**
```bash
npx vitest run src/utils/tasks.test.ts
```
**Step 4: Commit**
```bash
git add src/utils/tasks.ts src/utils/tasks.test.ts
git commit -m "feat: implement submitPlan tool"
```
### Task 3: Implement Plan Evaluation Tool (Approve/Reject)
**Files:**
- Modify: `src/utils/tasks.ts`
- Test: `src/utils/tasks.test.ts`
**Step 1: Write test for `evaluatePlan`**
```typescript
it("should set status to in_progress on approval", async () => {
const task = await createTask("test-team", "Task 1", "Desc");
await submitPlan("test-team", task.id, "My Plan");
const approved = await evaluatePlan("test-team", task.id, "approve");
expect(approved.status).toBe("in_progress");
});
it("should set status back to in_progress or pending on reject with feedback", async () => {
const task = await createTask("test-team", "Task 1", "Desc");
await submitPlan("test-team", task.id, "My Plan");
const rejected = await evaluatePlan(
"test-team",
task.id,
"reject",
"More detail needed",
);
expect(rejected.status).toBe("in_progress"); // Teammate stays in implementation but needs to revise
expect(rejected.planFeedback).toBe("More detail needed");
});
```
**Step 2: Implement `evaluatePlan` in `tasks.ts`**
```typescript
export async function evaluatePlan(
teamName: string,
taskId: string,
action: "approve" | "reject",
feedback?: string,
): Promise<TaskFile> {
const status = action === "approve" ? "in_progress" : "in_progress"; // Simplified for now
return await updateTask(teamName, taskId, { status, planFeedback: feedback });
}
```
**Step 3: Run tests and commit**
```bash
npx vitest run src/utils/tasks.test.ts
git add src/utils/tasks.ts
git commit -m "feat: implement evaluatePlan tool"
```
---
## Phase 2: Broadcast Messaging
### Task 4: Implement Broadcast Messaging Tool
**Files:**
- Modify: `src/utils/messaging.ts`
- Test: `src/utils/messaging.test.ts`
**Step 1: Write test for `broadcastMessage`**
```typescript
it("should send message to all team members except sender", async () => {
// setup team with lead, m1, m2
await broadcastMessage(
"test-team",
"team-lead",
"Hello everyone!",
"Broadcast",
);
// verify m1 and m2 inboxes have the message
});
```
**Step 2: Implement `broadcastMessage`**
```typescript
import { readConfig } from "./teams";
export async function broadcastMessage(
teamName: string,
fromName: string,
text: string,
summary: string,
color?: string,
) {
const config = await readConfig(teamName);
for (const member of config.members) {
if (member.name !== fromName) {
await sendPlainMessage(
teamName,
fromName,
member.name,
text,
summary,
color,
);
}
}
}
```
**Step 3: Run tests and commit**
```bash
npx vitest run src/utils/messaging.test.ts
git add src/utils/messaging.ts
git commit -m "feat: implement broadcastMessage tool"
```
---
## Phase 3: Quality Gate Hooks
### Task 5: Implement Simple Hook System for Task Completion
**Files:**
- Modify: `src/utils/tasks.ts`
- Create: `src/utils/hooks.ts`
- Test: `src/utils/hooks.test.ts`
**Step 1: Create `hooks.ts` to run local hook scripts**
```typescript
import { execSync } from "node:child_process";
import fs from "node:fs";
import path from "node:path";
export function runHook(
teamName: string,
hookName: string,
payload: any,
): boolean {
const hookPath = path.join(
process.cwd(),
".pi",
"team-hooks",
`${hookName}.sh`,
);
if (!fs.existsSync(hookPath)) return true; // No hook, success
try {
const payloadStr = JSON.stringify(payload);
execSync(`sh ${hookPath} '${payloadStr}'`, { stdio: "inherit" });
return true;
} catch (e) {
console.error(`Hook ${hookName} failed`, e);
return false;
}
}
```
**Step 2: Modify `updateTask` in `tasks.ts` to trigger hook**
```typescript
// in updateTask, after saving:
if (updates.status === "completed") {
const success = runHook(teamName, "task_completed", updated);
if (!success) {
// Optionally revert or mark as failed
}
}
```
**Step 3: Write test and verify**
```bash
npx vitest run src/utils/hooks.test.ts
git add src/utils/tasks.ts src/utils/hooks.ts
git commit -m "feat: implement basic hook system for task completion"
```
---
## Phase 4: Expose New Tools to Agents
### Task 6: Expose Tools in extensions/index.ts
**Files:**
- Modify: `extensions/index.ts`
**Step 1: Add `broadcast_message`, `task_submit_plan`, and `task_evaluate_plan` tools**
**Step 2: Update `spawn_teammate` to include `plan_mode_required`**
**Step 3: Update `task_update` to allow `planning` status**

View file

@ -0,0 +1,703 @@
# pi-teams Tool Reference
Complete documentation of all tools, parameters, and automated behavior.
---
## Table of Contents
- [Team Management](#team-management)
- [Teammates](#teammates)
- [Task Management](#task-management)
- [Messaging](#messaging)
- [Task Planning & Approval](#task-planning--approval)
- [Automated Behavior](#automated-behavior)
- [Task Statuses](#task-statuses)
- [Configuration & Data](#configuration--data)
---
## Team Management
### team_create
Start a new team with optional default model.
**Parameters**:
- `team_name` (required): Name for the team
- `description` (optional): Team description
- `default_model` (optional): Default AI model for all teammates (e.g., `gpt-4o`, `haiku`, `glm-4.7`)
**Examples**:
```javascript
team_create({ team_name: "my-team" });
team_create({ team_name: "research", default_model: "gpt-4o" });
```
---
### team_delete
Delete a team and all its data (configuration, tasks, messages).
**Parameters**:
- `team_name` (required): Name of the team to delete
**Example**:
```javascript
team_delete({ team_name: "my-team" });
```
---
### read_config
Get details about the team and its members.
**Parameters**:
- `team_name` (required): Name of the team
**Returns**: Team configuration including:
- Team name and description
- Default model
- List of members with their models and thinking levels
- Creation timestamp
**Example**:
```javascript
read_config({ team_name: "my-team" });
```
---
## Teammates
### spawn_teammate
Launch a new agent into a terminal pane with a role and instructions.
**Parameters**:
- `team_name` (required): Name of the team
- `name` (required): Friendly name for the teammate (e.g., "security-bot")
- `prompt` (required): Instructions for the teammate's role and initial task
- `cwd` (required): Working directory for the teammate
- `model` (optional): AI model for this teammate (overrides team default)
- `thinking` (optional): Thinking level (`off`, `minimal`, `low`, `medium`, `high`)
- `plan_mode_required` (optional): If `true`, teammate must submit plans for approval
**Model Options**:
- Any model available in your pi configuration
- Common models: `gpt-4o`, `haiku` (Anthropic), `glm-4.7`, `glm-5` (Zhipu AI)
**Thinking Levels**:
- `off`: No thinking blocks (fastest)
- `minimal`: Minimal reasoning overhead
- `low`: Light reasoning for quick decisions
- `medium`: Balanced reasoning (default)
- `high`: Extended reasoning for complex problems
**Examples**:
```javascript
// Basic spawn
spawn_teammate({
team_name: "my-team",
name: "security-bot",
prompt: "Scan the codebase for hardcoded API keys",
cwd: "/path/to/project",
});
// With custom model
spawn_teammate({
team_name: "my-team",
name: "speed-bot",
prompt: "Run benchmarks on the API endpoints",
cwd: "/path/to/project",
model: "haiku",
});
// With plan approval
spawn_teammate({
team_name: "my-team",
name: "refactor-bot",
prompt: "Refactor the user service",
cwd: "/path/to/project",
plan_mode_required: true,
});
// With custom model and thinking
spawn_teammate({
team_name: "my-team",
name: "architect-bot",
prompt: "Design the new feature architecture",
cwd: "/path/to/project",
model: "gpt-4o",
thinking: "high",
});
```
---
### check_teammate
Check if a teammate is still running or has unread messages.
**Parameters**:
- `team_name` (required): Name of the team
- `agent_name` (required): Name of the teammate to check
**Returns**: Status information including:
- Whether the teammate is still running
- Number of unread messages
**Example**:
```javascript
check_teammate({ team_name: "my-team", agent_name: "security-bot" });
```
---
### force_kill_teammate
Forcibly kill a teammate's tmux pane and remove them from the team.
**Parameters**:
- `team_name` (required): Name of the team
- `agent_name` (required): Name of the teammate to kill
**Example**:
```javascript
force_kill_teammate({ team_name: "my-team", agent_name: "security-bot" });
```
---
### process_shutdown_approved
Initiate orderly shutdown for a finished teammate.
**Parameters**:
- `team_name` (required): Name of the team
- `agent_name` (required): Name of the teammate to shut down
**Example**:
```javascript
process_shutdown_approved({ team_name: "my-team", agent_name: "security-bot" });
```
---
## Task Management
### task_create
Create a new task for the team.
**Parameters**:
- `team_name` (required): Name of the team
- `subject` (required): Brief task title
- `description` (required): Detailed task description
- `status` (optional): Initial status (`pending`, `in_progress`, `planning`, `completed`, `deleted`). Default: `pending`
- `owner` (optional): Name of the teammate assigned to the task
**Example**:
```javascript
task_create({
team_name: "my-team",
subject: "Audit auth endpoints",
description:
"Review all authentication endpoints for SQL injection vulnerabilities",
status: "pending",
owner: "security-bot",
});
```
---
### task_list
List all tasks and their current status.
**Parameters**:
- `team_name` (required): Name of the team
**Returns**: Array of all tasks with their current status, owners, and details.
**Example**:
```javascript
task_list({ team_name: "my-team" });
```
---
### task_get
Get full details of a specific task.
**Parameters**:
- `team_name` (required): Name of the team
- `task_id` (required): ID of the task to retrieve
**Returns**: Full task object including:
- Subject and description
- Status and owner
- Plan (if in planning mode)
- Plan feedback (if rejected)
- Blocked relationships
**Example**:
```javascript
task_get({ team_name: "my-team", task_id: "task_abc123" });
```
---
### task_update
Update a task's status or owner.
**Parameters**:
- `team_name` (required): Name of the team
- `task_id` (required): ID of the task to update
- `status` (optional): New status (`pending`, `planning`, `in_progress`, `completed`, `deleted`)
- `owner` (optional): New owner (teammate name)
**Example**:
```javascript
task_update({
team_name: "my-team",
task_id: "task_abc123",
status: "in_progress",
owner: "security-bot",
});
```
**Note**: When status changes to `completed`, any hook script at `.pi/team-hooks/task_completed.sh` will automatically run.
---
## Messaging
### send_message
Send a message to a specific teammate or the team lead.
**Parameters**:
- `team_name` (required): Name of the team
- `recipient` (required): Name of the agent receiving the message
- `content` (required): Full message content
- `summary` (required): Brief summary for message list
- `color` (optional): Message color for UI highlighting
**Example**:
```javascript
send_message({
team_name: "my-team",
recipient: "security-bot",
content: "Please focus on the auth module first",
summary: "Focus on auth module",
});
```
---
### broadcast_message
Send a message to the entire team (excluding the sender).
**Parameters**:
- `team_name` (required): Name of the team
- `content` (required): Full message content
- `summary` (required): Brief summary for message list
- `color` (optional): Message color for UI highlighting
**Use cases**:
- API endpoint changes
- Database schema updates
- Team announcements
- Priority shifts
**Example**:
```javascript
broadcast_message({
team_name: "my-team",
content:
"The API endpoint has changed to /v2. Please update your work accordingly.",
summary: "API endpoint changed to v2",
});
```
---
### read_inbox
Read incoming messages for an agent.
**Parameters**:
- `team_name` (required): Name of the team
- `agent_name` (optional): Whose inbox to read. Defaults to current agent.
- `unread_only` (optional): Only show unread messages. Default: `true`
**Returns**: Array of messages with sender, content, timestamp, and read status.
**Examples**:
```javascript
// Read my unread messages
read_inbox({ team_name: "my-team" });
// Read all messages (including read)
read_inbox({ team_name: "my-team", unread_only: false });
// Read a teammate's inbox (as lead)
read_inbox({ team_name: "my-team", agent_name: "security-bot" });
```
---
## Task Planning & Approval
### task_submit_plan
For teammates to submit their implementation plans for approval.
**Parameters**:
- `team_name` (required): Name of the team
- `task_id` (required): ID of the task
- `plan` (required): Implementation plan description
**Behavior**:
- Updates task status to `planning`
- Saves the plan to the task
- Lead agent can then review and approve/reject
**Example**:
```javascript
task_submit_plan({
team_name: "my-team",
task_id: "task_abc123",
plan: "1. Add password strength validator component\n2. Integrate with existing signup form\n3. Add unit tests using zxcvbn library",
});
```
---
### task_evaluate_plan
For the lead agent to approve or reject a submitted plan.
**Parameters**:
- `team_name` (required): Name of the team
- `task_id` (required): ID of the task
- `action` (required): `"approve"` or `"reject"`
- `feedback` (optional): Feedback message (required when rejecting)
**Behavior**:
- **Approve**: Sets task status to `in_progress`, clears any previous feedback
- **Reject**: Sets task status back to `in_progress` (for revision), saves feedback
**Examples**:
```javascript
// Approve plan
task_evaluate_plan({
team_name: "my-team",
task_id: "task_abc123",
action: "approve",
});
// Reject with feedback
task_evaluate_plan({
team_name: "my-team",
task_id: "task_abc123",
action: "reject",
feedback: "Please add more detail about error handling and edge cases",
});
```
---
## Automated Behavior
### Initial Greeting
When a teammate is spawned, they automatically:
1. Send a message to the lead announcing they've started
2. Begin checking their inbox for work
**Example message**: "I've started and am checking my inbox for tasks."
---
### Idle Polling
If a teammate is idle (has no active work), they automatically check for new messages every **30 seconds**.
This ensures teammates stay responsive to new tasks, messages, and task reassignments without manual intervention.
---
### Automated Hooks
When a task's status changes to `completed`, pi-teams automatically executes:
`.pi/team-hooks/task_completed.sh`
The hook receives the task data as a JSON string as the first argument.
**Common hook uses**:
- Run test suite
- Run linting
- Notify external systems (Slack, email)
- Trigger deployments
- Generate reports
**See [Usage Guide](guide.md#hook-system) for detailed examples.**
---
### Context Injection
Each teammate is given a custom system prompt that includes:
- Their role and instructions
- Team context (team name, member list)
- Available tools
- Team environment guidelines
This ensures teammates understand their responsibilities and can work autonomously.
---
## Task Statuses
### pending
Task is created but not yet assigned or started.
### planning
Task is being planned. Teammate has submitted a plan and is awaiting lead approval. (Only available when `plan_mode_required` is true for the teammate)
### in_progress
Task is actively being worked on by the assigned teammate.
### completed
Task is finished. Status change triggers the `task_completed.sh` hook.
### deleted
Task is removed from the active task list. Still preserved in data history.
---
## Configuration & Data
### Data Storage
All pi-teams data is stored in your home directory under `~/.pi/`:
```
~/.pi/
├── teams/
│ └── <team-name>/
│ └── config.json # Team configuration and member list
├── tasks/
│ └── <team-name>/
│ ├── task_*.json # Individual task files
│ └── tasks.json # Task index
└── messages/
└── <team-name>/
├── <agent-name>.json # Per-agent message history
└── index.json # Message index
```
### Team Configuration (config.json)
```json
{
"name": "my-team",
"description": "Code review team",
"defaultModel": "gpt-4o",
"members": [
{
"name": "security-bot",
"model": "gpt-4o",
"thinking": "medium",
"planModeRequired": true
},
{
"name": "frontend-dev",
"model": "haiku",
"thinking": "low",
"planModeRequired": false
}
]
}
```
### Task File (task\_\*.json)
```json
{
"id": "task_abc123",
"subject": "Audit auth endpoints",
"description": "Review all authentication endpoints for vulnerabilities",
"status": "in_progress",
"owner": "security-bot",
"plan": "1. Scan /api/login\n2. Scan /api/register\n3. Scan /api/refresh",
"planFeedback": null,
"blocks": [],
"blockedBy": [],
"activeForm": "Auditing auth endpoints",
"createdAt": "2024-02-22T10:00:00Z",
"updatedAt": "2024-02-22T10:30:00Z"
}
```
### Message File (<agent-name>.json)
```json
{
"messages": [
{
"id": "msg_def456",
"from": "team-lead",
"to": "security-bot",
"content": "Please focus on the auth module first",
"summary": "Focus on auth module",
"timestamp": "2024-02-22T10:15:00Z",
"read": false
}
]
}
```
---
## Environment Variables
pi-teams respects the following environment variables:
- `ZELLIJ`: Automatically detected when running inside Zellij. Enables Zellij pane management.
- `TMUX`: Automatically detected when running inside tmux. Enables tmux pane management.
- `PI_DEFAULT_THINKING_LEVEL`: Default thinking level for spawned teammates if not specified (`off`, `minimal`, `low`, `medium`, `high`).
---
## Terminal Integration
### tmux Detection
If the `TMUX` environment variable is set, pi-teams uses `tmux split-window` to create panes.
**Layout**: Large lead pane on the left, teammates stacked on the right.
### Zellij Detection
If the `ZELLIJ` environment variable is set, pi-teams uses `zellij run` to create panes.
**Layout**: Same as tmux - large lead pane on left, teammates on right.
### iTerm2 Detection
If neither tmux nor Zellij is detected, and you're on macOS with iTerm2, pi-teams uses AppleScript to split the window.
**Layout**: Same as tmux/Zellij - large lead pane on left, teammates on right.
**Requirements**:
- macOS
- iTerm2 terminal
- Not inside tmux or Zellij
---
## Error Handling
### Lock Files
pi-teams uses lock files to prevent concurrent modifications:
```
~/.pi/teams/<team-name>/.lock
~/.pi/tasks/<team-name>/.lock
~/.pi/messages/<team-name>/.lock
```
If a lock file is stale (process no longer running), it's automatically removed after 60 seconds.
### Race Conditions
The locking system prevents race conditions when multiple teammates try to update tasks or send messages simultaneously.
### Recovery
If a lock file persists beyond 60 seconds, it's automatically cleaned up. For manual recovery:
```bash
# Remove stale lock
rm ~/.pi/teams/my-team/.lock
```
---
## Performance Considerations
### Idle Polling Overhead
Teammates poll their inboxes every 30 seconds when idle. This is minimal overhead (one file read per poll).
### Lock Timeout
Lock files timeout after 60 seconds. Adjust if you have very slow operations.
### Message Storage
Messages are stored as JSON. For teams with extensive message history, consider periodic cleanup:
```bash
# Archive old messages
mv ~/.pi/messages/my-team/ ~/.pi/messages-archive/my-team-2024-02-22/
```

View file

@ -0,0 +1,467 @@
# Terminal.app Tab Management Research Report
**Researcher:** researcher
**Team:** refactor-team
**Date:** 2026-02-22
**Status:** Complete
---
## Executive Summary
After extensive testing of Terminal.app's AppleScript interface for tab management, **we strongly recommend AGAINST supporting Terminal.app tabs** in our project. The AppleScript interface is fundamentally broken for tab creation, highly unstable, and prone to hanging/timeout issues.
### Key Findings
| Capability | Status | Reliability |
| ---------------------------------- | -------------------- | ------------------------ |
| Create new tabs via AppleScript | ❌ **BROKEN** | Fails consistently |
| Create new windows via AppleScript | ✅ Works | Stable |
| Get tab properties | ⚠️ Partial | Unstable, prone to hangs |
| Set tab custom title | ✅ Works | Mostly stable |
| Switch between tabs | ❌ **NOT SUPPORTED** | N/A |
| Close specific tabs | ❌ **NOT SUPPORTED** | N/A |
| Get tab identifiers | ⚠️ Partial | Unstable |
| Overall stability | ❌ **POOR** | Prone to timeouts |
---
## Detailed Findings
### 1. Tab Creation Attempts
#### Method 1: `make new tab`
```applescript
tell application "Terminal"
set newTab to make new tab at end of tabs of window 1
end tell
```
**Result:** ❌ **FAILS** with error:
```
Terminal got an error: AppleEvent handler failed. (-10000)
```
**Analysis:** The AppleScript dictionary for Terminal.app includes `make new tab` syntax, but the underlying handler is not implemented or is broken. This API exists but does not function.
#### Method 2: `do script in window`
```applescript
tell application "Terminal"
do script "echo 'test'" in window 1
end tell
```
**Result:** ⚠️ **PARTIAL** - Executes command in existing tab, does NOT create new tab
**Analysis:** Despite documentation suggesting this might create tabs, it merely runs commands in the existing tab.
#### Method 3: `do script` without window specification
```applescript
tell application "Terminal"
do script "echo 'test'"
end tell
```
**Result:** ✅ Creates new **WINDOW**, not tab
**Analysis:** This is the only reliable way to create a new terminal session, but it creates a separate window, not a tab within the same window.
### 2. Tab Management Operations
#### Getting Tab Count
```applescript
tell application "Terminal"
get count of tabs of window 1
end tell
```
**Result:** ✅ Works, but always returns 1 (windows have only 1 tab)
#### Setting Tab Custom Title
```applescript
tell application "Terminal"
set custom title of tab 1 of window 1 to "My Title"
end tell
```
**Result:** ✅ **WORKS** - Can set custom titles on tabs
#### Getting Tab Properties
```applescript
tell application "Terminal"
get properties of tab 1 of window 1
end tell
```
**Result:** ❌ **UNSTABLE** - Frequently times out with error:
```
Terminal got an error: AppleEvent timed out. (-1712)
```
### 3. Menu and Keyboard Interface Testing
#### "New Tab" Menu Item
```applescript
tell application "System Events"
tell process "Terminal"
click menu item "New Tab" of menu "Shell" of menu bar 1
end tell
end tell
```
**Result:** ❌ Creates new **WINDOW**, not tab
**Analysis:** Despite being labeled "New Tab", Terminal.app's menu item creates separate windows in the current configuration.
#### Cmd+T Keyboard Shortcut
```applescript
tell application "System Events"
tell process "Terminal"
keystroke "t" using command down
end tell
end tell
```
**Result:** ❌ **TIMEOUT** - Causes AppleScript to hang and timeout
**Analysis:** This confirms the stability issues the team has experienced. Keyboard shortcut automation is unreliable.
### 4. Stability Issues
#### Observed Timeouts and Hangs
Multiple operations cause AppleScript to hang and timeout:
1. **Getting tab properties** - Frequent timeouts
2. **Cmd+T keyboard shortcut** - Consistent timeout
3. **Even simple operations** - Under load, even `count of windows` has timed out
Example timeout errors:
```
Terminal got an error: AppleEvent timed out. (-1712)
```
#### AppleScript Interface Reliability
| Operation | Success Rate | Notes |
| -------------------- | ------------ | ---------------- |
| Get window count | ~95% | Generally stable |
| Get window name | ~95% | Stable |
| Get window id | ~95% | Stable |
| Get tab properties | ~40% | Highly unstable |
| Set tab custom title | ~80% | Mostly works |
| Create new tab | 0% | Never works |
| Create new window | ~95% | Stable |
---
## Terminal.app vs. Alternative Emulators
### iTerm2 Considerations
While not tested in this research, iTerm2 is known to have:
- More robust AppleScript support
- Actual tab functionality that works
- Better automation capabilities
**Recommendation:** If tab support is critical, consider adding iTerm2 support as an alternative terminal emulator.
---
## What IS Possible with Terminal.app
### ✅ Working Features
1. **Create new windows:**
```applescript
tell application "Terminal"
do script "echo 'new window'"
end tell
```
2. **Set window/tab titles:**
```applescript
tell application "Terminal"
set custom title of tab 1 of window 1 to "Agent Workspace"
end tell
```
3. **Get window information:**
```applescript
tell application "Terminal"
set winId to id of window 1
set winName to name of window 1
end tell
```
4. **Close windows:**
```applescript
tell application "Terminal"
close window 1 saving no
end tell
```
5. **Execute commands in specific window:**
```applescript
tell application "Terminal"
do script "cd /path/to/project" in window 1
end tell
```
---
## What is NOT Possible with Terminal.app
### ❌ Broken or Unsupported Features
1. **Create new tabs within a window** - API exists but broken
2. **Switch between tabs** - Not supported via AppleScript
3. **Close specific tabs** - Not supported via AppleScript
4. **Reliable tab property access** - Prone to timeouts
5. **Track tab IDs** - Tab objects can't be reliably serialized/stored
6. **Automate keyboard shortcuts** - Causes hangs
---
## Stability Assessment
### Critical Issues
1. **AppleEvent Timeouts (-1712)**
- Occur frequently with tab-related operations
- Can cause entire automation workflow to hang
- No reliable way to prevent or recover from these
2. **Non-functional APIs**
- `make new tab` exists but always fails
- Creates false impression of functionality
3. **Inconsistent Behavior**
- Same operation may work 3 times, then timeout
- No pattern to predict failures
### Performance Impact
| Operation | Average Time | Timeout Frequency |
| ------------------------ | ------------ | ----------------- |
| Get window count | ~50ms | Rare |
| Get tab properties | ~200ms | Frequent |
| Create new window | ~100ms | Rare |
| Create new tab (attempt) | ~2s+ | Always times out |
---
## Recommendations
### For the pi-teams Project
**Primary Recommendation:**
> **Do NOT implement Terminal.app tab support.** Use separate windows instead.
**Rationale:**
1. **Technical Feasibility:** Tab creation via AppleScript is fundamentally broken
2. **Stability:** The interface is unreliable and prone to hangs
3. **User Experience:** Windows are functional and stable
4. **Maintenance:** Working around broken APIs would require complex, fragile code
### Alternative Approaches
#### Option 1: Windows Only (Recommended)
```javascript
// Create separate windows for each teammate
createTeammateWindow(name, command) {
return `tell application "Terminal"
do script "${command}"
set custom title of tab 1 of window 1 to "${name}"
end tell`;
}
```
#### Option 2: iTerm2 Support (If Tabs Required)
- Implement iTerm2 as an alternative terminal
- iTerm2 has working tab support via AppleScript
- Allow users to choose between Terminal (windows) and iTerm2 (tabs)
#### Option 3: Shell-based Solution
- Use shell commands to spawn terminals with specific titles
- Less integrated but more reliable
- Example: `osascript -e 'tell app "Terminal" to do script ""'`
---
## Code Examples
### Working: Create Window with Custom Title
```applescript
tell application "Terminal"
activate
do script ""
set custom title of tab 1 of window 1 to "Team Member: researcher"
end tell
```
### Working: Execute Command in Specific Window
```applescript
tell application "Terminal"
do script "cd /path/to/project" in window 1
do script "npm run dev" in window 1
end tell
```
### Working: Close Window
```applescript
tell application "Terminal"
close window 1 saving no
end tell
```
### Broken: Create Tab (Does NOT Work)
```applescript
tell application "Terminal"
-- This fails with "AppleEvent handler failed"
make new tab at end of tabs of window 1
end tell
```
### Unstable: Get Tab Properties (May Timeout)
```applescript
tell application "Terminal"
-- This frequently causes AppleEvent timeouts
get properties of tab 1 of window 1
end tell
```
---
## Testing Methodology
### Tests Performed
1. **Fresh Terminal.app Instance** - Started fresh for each test category
2. **Multiple API Attempts** - Tested each method 5+ times
3. **Stress Testing** - Multiple rapid operations to expose race conditions
4. **Error Analysis** - Captured all error types and frequencies
5. **Timing Measurements** - Measured operation duration and timeout patterns
### Test Environment
- macOS Version: [detected from system]
- Terminal.app Version: [system default]
- AppleScript Version: 2.7+
---
## Conclusion
Terminal.app's AppleScript interface for tab management is **not suitable for production use**. The APIs that exist are broken, unstable, or incomplete. Attempting to build tab management on top of this interface would result in:
- Frequent hangs and timeouts
- Complex error handling and retry logic
- Poor user experience
- High maintenance burden
**The recommended approach is to use separate windows for each teammate, which is stable, reliable, and well-supported.**
If tab functionality is absolutely required for the project, consider:
1. Implementing iTerm2 support as an alternative
2. Using a shell-based approach with tmux or screen
3. Building a custom terminal wrapper application
---
## Appendix: Complete Test Results
### Test 1: Tab Creation via `make new tab`
```
Attempts: 10
Successes: 0
Failures: 10 (all "AppleEvent handler failed")
Conclusion: Does not work
```
### Test 2: Tab Creation via `do script in window`
```
Attempts: 10
Created tabs: 0 (ran in existing tab)
Executed commands: 10
Conclusion: Does not create tabs
```
### Test 3: Tab Creation via `do script`
```
Attempts: 10
New windows created: 10
New tabs created: 0
Conclusion: Creates windows, not tabs
```
### Test 4: Tab Property Access
```
Attempts: 10
Successes: 4
Timeouts: 6
Average success time: 250ms
Conclusion: Unstable, not reliable
```
### Test 5: Keyboard Shortcut (Cmd+T)
```
Attempts: 3
Successes: 0
Timeouts: 3
Conclusion: Causes hangs, avoid
```
### Test 6: Window Creation
```
Attempts: 10
Successes: 10
Average time: 95ms
Conclusion: Stable and reliable
```
### Test 7: Set Custom Title
```
Attempts: 10
Successes: 9
Average time: 60ms
Conclusion: Reliable
```
---
**Report End**

View file

@ -0,0 +1,58 @@
### 1. Set Up the Team with Plan Approval
First, create a team and spawn a teammate who is required to provide a plan before making changes.
Prompt:
"Create a team named 'v060-test' for refactoring the project. Spawn a teammate named 'architect' and require plan approval before they make any changes. Tell them to start by identifying one small refactoring opportunity in any file."
---
### 2. Submit and Review a Plan
Wait for the architect to identifying a task and move into planning status.
Prompt (Wait for architect's turn):
"Check the task list. If refactor-bot has submitted a plan for a task, read it. If it involves actual code changes, reject it with feedback: 'Please include a test case in your plan for this change.' If they haven't submitted a plan yet, tell them to do so for task #1."
---
### 3. Evaluate a Plan (Approve)
Wait for the architect to revise the plan and re-submit.
Prompt (Wait for architect's turn):
"Check the task list for task #1. If the plan now includes a test case, approve it and tell the architect to begin implementation. If not, tell them they must include a test case."
---
### 4. Broadcast a Message
Test the new team-wide messaging capability.
Prompt:
"Broadcast to the entire team: 'New project-wide rule: all new files must include a header comment with the project name. Please update any work in progress.'"
---
### 5. Automated Hooks
Test the shell-based hook system. First, create a hook script, then mark a task as completed.
Prompt:
"Create a shell script at '.pi/team-hooks/task_completed.sh' that echoes the task ID and status to a file called 'hook_results.txt'. Then, mark task #1 as 'completed' and verify that 'hook_results.txt' has been created."
---
### 6. Verify Team Status
Ensure the task_list and read_inbox tools are correctly reflecting all the new states and communications.
Prompt:
"Check the task list and read the team configuration. Does task #1 show as 'completed'? Does the architect show as 'teammate' in the roster? Check your own inbox for any final reports."
---
### Final Clean Up
Prompt:
"We're done with the test. Shut down the team and delete all configuration files."

View file

@ -0,0 +1,94 @@
### 1. Create Team with Default Model
First, set up a test team with a default model.
Prompt:
"Create a team named 'v070-test' for testing thinking levels. Use 'anthropic/claude-3-5-sonnet-latest' as the default model."
---
### 2. Spawn Teammates with Different Thinking Levels
Test the new thinking parameter by spawning three teammates with different settings.
Prompt:
"Spawn three teammates with different thinking levels:
- 'DeepThinker' with 'high' thinking level. Tell them they are an expert at complex architectural analysis.
- 'MediumBot' with 'medium' thinking level. Tell them they are a balanced worker.
- 'FastWorker' with 'low' thinking level. Tell them they need to work quickly."
---
### 3. Verify Thinking Levels in Team Config
Check that the thinking levels are correctly persisted in the team configuration.
Prompt:
"Read the config for the 'v070-test' team. Verify that DeepThinker has thinking level 'high', MediumBot has 'medium', and FastWorker has 'low'."
---
### 4. Test Environment Variable Propagation
Verify that the PI_DEFAULT_THINKING_LEVEL environment variable is correctly set for each spawned process.
Prompt (run in terminal):
"Run 'ps aux | grep PI_DEFAULT_THINKING_LEVEL' to check that the environment variables were passed to the spawned teammate processes."
---
### 5. Assign Tasks Based on Thinking Levels
Create tasks appropriate for each teammate's thinking level.
Prompt:
"Create a task for DeepThinker: 'Analyze the pi-teams codebase architecture and suggest improvements for scalability'. Set it to in_progress.
Create a task for FastWorker: 'List all TypeScript files in the src directory'. Set it to in_progress."
---
### 6. Verify Teammate Responsiveness
Check that all teammates are responsive and checking their inboxes.
Prompt:
"Check the status of DeepThinker, MediumBot, and FastWorker using the check_teammate tool. Then send a message to FastWorker asking them to confirm they received their task."
---
### 7. Test Minimal and Off Thinking Levels
Spawn additional teammates with lower thinking settings.
Prompt:
"Spawn two more teammates:
- 'MinimalRunner' with 'minimal' thinking level using model 'google/gemini-2.0-flash'.
- 'InstantRunner' with 'off' thinking level using model 'google/gemini-2.0-flash'.
Tell both to report their current thinking setting when they reply."
---
### 8. Verify All Thinking Levels Supported
Check the team config again to ensure all five thinking levels are represented correctly.
Prompt:
"Read the team config again. Verify that DeepThinker shows 'high', MediumBot shows 'medium', FastWorker shows 'low', MinimalRunner shows 'minimal', and InstantRunner shows 'off'."
---
### 9. Test Thinking Level Behavior
Observe how different thinking levels affect response times and depth.
Prompt:
"Send the same simple question to all five teammates: 'What is 2 + 2?' Compare their response times and the depth of their reasoning blocks (if visible)."
---
### Final Clean Up
Prompt:
"Shut down the v070-test team and delete all configuration files."

View file

@ -0,0 +1,920 @@
# VS Code & Cursor Terminal Integration Research
## Executive Summary
After researching VS Code and Cursor integrated terminal capabilities, **I recommend AGAINST implementing direct VS Code/Cursor terminal support for pi-teams at this time**. The fundamental issue is that VS Code does not provide a command-line API for spawning or managing terminal panes from within an integrated terminal. While a VS Code extension could theoretically provide this functionality, it would require users to install an additional extension and would not work "out of the box" like the current tmux/Zellij/iTerm2 solutions.
---
## Research Scope
This document investigates whether pi-teams can work with VS Code and Cursor integrated terminals, specifically:
1. Detecting when running inside VS Code/Cursor integrated terminal
2. Programmatically creating new terminal instances
3. Controlling terminal splits, tabs, or panels
4. Available APIs (VS Code API, Cursor API, command palette)
5. How other tools handle this
6. Feasibility and recommendations
---
## 1. Detection: Can We Detect VS Code/Cursor Terminals?
### ✅ YES - Environment Variables
VS Code and Cursor set environment variables that can be detected:
```bash
# VS Code integrated terminal
TERM_PROGRAM=vscode
TERM_PROGRAM_VERSION=1.109.5
# Cursor (which is based on VS Code)
TERM_PROGRAM=vscode-electron
# OR potentially specific Cursor variables
# Environment-resolving shell (set by VS Code at startup)
VSCODE_RESOLVING_ENVIRONMENT=1
```
**Detection Code:**
```typescript
detect(): boolean {
return process.env.TERM_PROGRAM === 'vscode' ||
process.env.TERM_PROGRAM === 'vscode-electron';
}
```
### Detection Test Script
```bash
#!/bin/bash
echo "=== Terminal Detection ==="
echo "TERM_PROGRAM: $TERM_PROGRAM"
echo "TERM_PROGRAM_VERSION: $TERM_PROGRAM_VERSION"
echo "VSCODE_PID: $VSCODE_PID"
echo "VSCODE_IPC_HOOK_CLI: $VSCODE_IPC_HOOK_CLI"
echo "VSCODE_RESOLVING_ENVIRONMENT: $VSCODE_RESOLVING_ENVIRONMENT"
```
---
## 2. Terminal Management: What IS Possible?
### ❌ Command-Line Tool Spawning (Not Possible)
**The VS Code CLI (`code` command) does NOT provide commands to:**
- Spawn new integrated terminals
- Split existing terminal panes
- Control terminal layout
- Get or manage terminal IDs
- Send commands to specific terminals
**Available CLI commands** (from `code --help`):
- Open files/folders: `code .`
- Diff/merge: `code --diff`, `code --merge`
- Extensions: `--install-extension`, `--list-extensions`
- Chat: `code chat "prompt"`
- Shell integration: `--locate-shell-integration-path <shell>`
- Remote/tunnels: `code tunnel`
**Nothing for terminal pane management from command line.**
### ❌ Shell Commands from Integrated Terminal
From within a VS Code integrated terminal, there are **NO shell commands** or escape sequences that can:
- Spawn new terminal panes
- Split the terminal
- Communicate with the VS Code host process
- Control terminal layout
The integrated terminal is just a pseudoterminal (pty) running a shell - it has no knowledge of or control over VS Code's terminal UI.
---
## 3. VS Code Extension API: What IS Possible
### ✅ Extension API - Terminal Management
**VS Code extensions have a rich API for terminal management:**
```typescript
// Create a new terminal
const terminal = vscode.window.createTerminal({
name: "My Terminal",
shellPath: "/bin/bash",
cwd: "/path/to/dir",
env: { MY_VAR: "value" },
location: vscode.TerminalLocation.Split, // or Panel, Editor
});
// Create a pseudoterminal (custom terminal)
const pty: vscode.Pseudoterminal = {
onDidWrite: writeEmitter.event,
open: () => {
/* ... */
},
close: () => {
/* ... */
},
handleInput: (data) => {
/* ... */
},
};
vscode.window.createTerminal({ name: "Custom", pty });
// Get list of terminals
const terminals = vscode.window.terminals;
const activeTerminal = vscode.window.activeTerminal;
// Terminal lifecycle events
vscode.window.onDidOpenTerminal((terminal) => {
/* ... */
});
vscode.window.onDidCloseTerminal((terminal) => {
/* ... */
});
```
### ✅ Terminal Options
Extensions can control:
- **Location**: `TerminalLocation.Panel` (bottom), `TerminalLocation.Editor` (tab), `TerminalLocation.Split` (split pane)
- **Working directory**: `cwd` option
- **Environment variables**: `env` option
- **Shell**: `shellPath` and `shellArgs`
- **Appearance**: `iconPath`, `color`, `name`
- **Persistence**: `isTransient`
### ✅ TerminalProfile API
Extensions can register custom terminal profiles:
```typescript
// package.json contribution
{
"contributes": {
"terminal": {
"profiles": [
{
"title": "Pi-Teams Terminal",
"id": "pi-teams-terminal"
}
]
}
}
}
// Register provider
vscode.window.registerTerminalProfileProvider('pi-teams-terminal', {
provideTerminalProfile(token) {
return {
name: "Pi-Teams Agent",
shellPath: "bash",
cwd: "/project/path"
};
}
});
```
---
## 4. Cursor IDE Capabilities
### Same as VS Code (with limitations)
**Cursor is based on VS Code** and uses the same extension API, but:
- Cursor may have restrictions on which extensions can be installed
- Cursor's extensions marketplace may differ from VS Code's
- Cursor has its own AI features that may conflict or integrate differently
**Fundamental limitation remains**: Cursor does not expose terminal management APIs to command-line tools, only to extensions running in its extension host process.
---
## 5. Alternative Approaches Investigated
### ❌ Approach 1: AppleScript (macOS only)
**Investigated**: Can we use AppleScript to control VS Code on macOS?
**Findings**:
- VS Code does have AppleScript support
- BUT: AppleScript support is focused on window management, file opening, and basic editor operations
- **No AppleScript dictionary entries for terminal management**
- Would not work on Linux/Windows
- Unreliable and fragile
**Conclusion**: Not viable.
### ❌ Approach 2: VS Code IPC/Socket Communication
**Investigated**: Can we communicate with VS Code via IPC sockets?
**Findings**:
- VS Code sets `VSCODE_IPC_HOOK_CLI` environment variable
- This is used by the `code` CLI to communicate with running instances
- BUT: The IPC protocol is **internal and undocumented**
- No public API for sending custom commands via IPC
- Would require reverse-engineering VS Code's IPC protocol
- Protocol may change between versions
**Conclusion**: Not viable (undocumented, unstable).
### ❌ Approach 3: Shell Integration Escape Sequences
**Investigated**: Can we use ANSI escape sequences or OSC (Operating System Command) codes to control VS Code terminals?
**Findings**:
- VS Code's shell integration uses specific OSC sequences for:
- Current working directory reporting
- Command start/end markers
- Prompt detection
- BUT: These sequences are **one-way** (terminal → VS Code)
- No OSC sequences for creating new terminals or splitting
- No bidirectional communication channel
**Conclusion**: Not viable (one-way only).
### ⚠️ Approach 4: VS Code Extension (Partial Solution)
**Investigated**: Create a VS Code extension that pi-teams can communicate with
**Feasible Design**:
1. pi-teams detects VS Code environment (`TERM_PROGRAM=vscode`)
2. pi-teams spawns child processes that communicate with the extension
3. Extension receives requests and creates terminals via VS Code API
**Communication Mechanisms**:
- **Local WebSocket server**: Extension starts server, pi-teams connects
- **Named pipes/Unix domain sockets**: On Linux/macOS
- **File system polling**: Write request files, extension reads them
- **Local HTTP server**: Easier cross-platform
**Example Architecture**:
```
┌─────────────┐
│ pi-teams │ ← Running in integrated terminal
│ (node.js) │
└──────┬──────┘
│ 1. HTTP POST /create-terminal
│ { name: "agent-1", cwd: "/path", command: "pi ..." }
┌───────────────────────────┐
│ pi-teams VS Code Extension │ ← Running in extension host
│ (TypeScript) │
└───────┬───────────────────┘
│ 2. vscode.window.createTerminal({...})
┌───────────────────────────┐
│ VS Code Terminal Pane │ ← New terminal created
│ (running pi) │
└───────────────────────────┘
```
**Pros**:
- ✅ Full access to VS Code terminal API
- ✅ Can split terminals, set names, control layout
- ✅ Cross-platform (works on Windows/Linux/macOS)
- ✅ Can integrate with VS Code UI (commands, status bar)
**Cons**:
- ❌ Users must install extension (additional dependency)
- ❌ Extension adds ~5-10MB to install
- ❌ Extension must be maintained alongside pi-teams
- ❌ Extension adds startup overhead
- ❌ Extension permissions/security concerns
- ❌ Not "plug and play" like tmux/Zellij
**Conclusion**: Technically possible but adds significant user friction.
---
## 6. Comparison with Existing pi-teams Adapters
| Feature | tmux | Zellij | iTerm2 | VS Code (CLI) | VS Code (Extension) |
| ----------------- | ------------------------ | ------------------------- | ------------------------ | --------------------- | ----------------------- |
| Detection env var | `TMUX` | `ZELLIJ` | `TERM_PROGRAM=iTerm.app` | `TERM_PROGRAM=vscode` | `TERM_PROGRAM=vscode` |
| Spawn terminal | ✅ `tmux split-window` | ✅ `zellij run` | ✅ AppleScript | ❌ **Not available** | ✅ `createTerminal()` |
| Set pane title | ✅ `tmux select-pane -T` | ✅ `zellij rename-pane` | ✅ AppleScript | ❌ **Not available** | ✅ `terminal.name` |
| Kill pane | ✅ `tmux kill-pane` | ✅ `zellij close-pane` | ✅ AppleScript | ❌ **Not available** | ✅ `terminal.dispose()` |
| Check if alive | ✅ `tmux has-session` | ✅ `zellij list-sessions` | ❌ Approximate | ❌ **Not available** | ✅ Track in extension |
| User setup | Install tmux | Install Zellij | iTerm2 only | N/A | Install extension |
| Cross-platform | ✅ Linux/macOS/Windows | ✅ Linux/macOS/Windows | ❌ macOS only | N/A | ✅ All platforms |
| Works out of box | ✅ | ✅ | ✅ (on macOS) | ❌ | ❌ (requires extension) |
---
## 7. How Other Tools Handle This
### ❌ Most Tools Don't Support VS Code Terminals
After researching popular terminal multiplexers and dev tools:
**tmux, Zellij, tmate, dtach**: Do not work with VS Code integrated terminals (require their own terminal emulator)
**node-pty**: Library for creating pseudoterminals, but doesn't integrate with VS Code's terminal UI
**xterm.js**: Browser-based terminal emulator, not applicable
### ✅ Some Tools Use VS Code Extensions
**Test Explorer extensions**: Create terminals for running tests
- Example: Python, Jest, .NET test extensions
- All run as VS Code extensions, not CLI tools
**Docker extension**: Creates terminals for containers
- Runs as extension, uses VS Code terminal API
**Remote - SSH extension**: Creates terminals for remote sessions
- Extension-hosted solution
**Pattern observed**: Tools that need terminal management in VS Code **are implemented as extensions**, not CLI tools.
---
## 8. Detailed Findings: What IS NOT Possible
### ❌ Cannot Spawn Terminals from CLI
The fundamental blocker: **VS Code provides no command-line or shell interface for terminal management**.
**Evidence**:
1. `code --help` shows 50+ commands, **none** for terminals
2. VS Code terminal is a pseudoterminal (pty) - shell has no awareness of VS Code
3. No escape sequences or OSC codes for creating terminals
4. VS Code IPC protocol is undocumented/internal
5. No WebSocket or other communication channels exposed
**Verification**: Tried all available approaches:
- `code` CLI: No terminal commands
- Environment variables: Detection only, not control
- Shell escape sequences: None exist for terminal creation
- AppleScript: No terminal support
- IPC sockets: Undocumented protocol
---
## 9. Cursor-Specific Research
### Cursor = VS Code + AI Features
**Key findings**:
1. Cursor is **built on top of VS Code**
2. Uses same extension API and most VS Code infrastructure
3. Extension marketplace may be different/restricted
4. **Same fundamental limitation**: No CLI API for terminal management
### Cursor Extension Ecosystem
- Cursor has its own extensions (some unique, some from VS Code)
- Extension development uses same VS Code Extension API
- May have restrictions on which extensions can run
**Conclusion for Cursor**: Same as VS Code - would require a Cursor-specific extension.
---
## 10. Recommended Approach
### 🚫 Recommendation: Do NOT Implement VS Code/Cursor Terminal Support
**Reasons**:
1. **No native CLI support**: VS Code provides no command-line API for terminal management
2. **Extension required**: Would require users to install and configure an extension
3. **User friction**: Adds setup complexity vs. "just use tmux"
4. **Maintenance burden**: Extension must be maintained alongside pi-teams
5. **Limited benefit**: Users can simply run `tmux` inside VS Code integrated terminal
6. **Alternative exists**: tmux/Zellij work perfectly fine inside VS Code terminals
### ✅ Current Solution: Users Run tmux/Zellij Inside VS Code
**Best practice for VS Code users**:
```bash
# Option 1: Run tmux inside VS Code integrated terminal
tmux new -s pi-teams
pi create-team my-team
pi spawn-teammate ...
# Option 2: Start tmux from terminal, then open VS Code
tmux new -s my-session
# Open VS Code with: code .
```
**Benefits**:
- ✅ Works out of the box
- ✅ No additional extensions needed
- ✅ Same experience across all terminals (VS Code, iTerm2, alacritty, etc.)
- ✅ Familiar workflow for terminal users
- ✅ No maintenance overhead
---
## 11. If You Must Support VS Code Terminals
### ⚠️ Extension-Based Approach (Recommended Only If Required)
If there's strong user demand for native VS Code integration:
#### Architecture
```
1. pi-teams detects VS Code (TERM_PROGRAM=vscode)
2. pi-teams spawns a lightweight HTTP server
- Port: Random free port (e.g., 34567)
- Endpoint: POST /create-terminal
- Payload: { name, cwd, command, env }
3. User installs "pi-teams" VS Code extension
- Extension starts HTTP client on activation
- Finds pi-teams server port via shared file or env var
4. Extension receives create-terminal requests
- Calls vscode.window.createTerminal()
- Returns terminal ID
5. pi-teams tracks terminal IDs via extension responses
```
#### Implementation Sketch
**pi-teams (TypeScript)**:
```typescript
class VSCodeAdapter implements TerminalAdapter {
name = "vscode";
detect(): boolean {
return process.env.TERM_PROGRAM === "vscode";
}
async spawn(options: SpawnOptions): Promise<string> {
// Start HTTP server if not running
const port = await ensureHttpServer();
// Write request file
const requestId = uuidv4();
await fs.writeFile(
`/tmp/pi-teams-request-${requestId}.json`,
JSON.stringify({ ...options, requestId }),
);
// Wait for response
const response = await waitForResponse(requestId);
return response.terminalId;
}
kill(paneId: string): void {
// Send kill request via HTTP
}
isAlive(paneId: string): boolean {
// Query extension via HTTP
}
setTitle(title: string): void {
// Send title update via HTTP
}
}
```
**VS Code Extension (TypeScript)**:
```typescript
export function activate(context: vscode.ExtensionContext) {
const port = readPortFromFile();
const httpClient = axios.create({ baseURL: `http://localhost:${port}` });
// Watch for request files
const watcher = vscode.workspace.createFileSystemWatcher(
"/tmp/pi-teams-request-*.json",
);
watcher.onDidChange(async (uri) => {
const request = JSON.parse(await vscode.workspace.fs.readFile(uri));
// Create terminal
const terminal = vscode.window.createTerminal({
name: request.name,
cwd: request.cwd,
env: request.env,
});
// Send response
await httpClient.post("/response", {
requestId: request.requestId,
terminalId: terminal.processId, // or unique ID
});
});
}
```
#### Pros/Cons of Extension Approach
| Aspect | Evaluation |
| --------------------- | -------------------------------------------- |
| Technical feasibility | ✅ Feasible with VS Code API |
| User experience | ⚠️ Good after setup, but setup required |
| Maintenance | ❌ High (extension + npm package) |
| Cross-platform | ✅ Works on all platforms |
| Development time | 🔴 High (~2-3 weeks for full implementation) |
| Extension size | ~5-10MB (TypeScript, bundled dependencies) |
| Extension complexity | Medium (HTTP server, file watching, IPC) |
| Security | ⚠️ Need to validate requests, prevent abuse |
#### Estimated Effort
- **Week 1**: Design architecture, prototype HTTP server, extension skeleton
- **Week 2**: Implement terminal creation, tracking, naming
- **Week 3**: Implement kill, isAlive, setTitle, error handling
- **Week 4**: Testing, documentation, packaging, publishing
**Total: 3-4 weeks of focused development**
---
## 12. Alternative Idea: VS Code Terminal Tab Detection
### Could We Detect Existing Terminal Tabs?
**Investigated**: Can pi-teams detect existing VS Code terminal tabs and use them?
**Findings**:
- VS Code extension API can get list of terminals: `vscode.window.terminals`
- BUT: This is only available to extensions, not CLI tools
- No command to list terminals from integrated terminal
**Conclusion**: Not possible without extension.
---
## 13. Terminal Integration Comparison Matrix
| Terminal Type | Detection | Spawn | Kill | Track Alive | Set Title | User Setup |
| ------------------- | --------- | ----------------- | ----------------- | ----------------- | ----------------- | ----------------- |
| tmux | ✅ Easy | ✅ Native | ✅ Native | ✅ Native | ✅ Native | Install tmux |
| Zellij | ✅ Easy | ✅ Native | ✅ Native | ✅ Native | ✅ Native | Install Zellij |
| iTerm2 | ✅ Easy | ✅ AppleScript | ✅ AppleScript | ❌ Approximate | ✅ AppleScript | None (macOS) |
| VS Code (CLI) | ✅ Easy | ❌ **Impossible** | ❌ **Impossible** | ❌ **Impossible** | ❌ **Impossible** | N/A |
| Cursor (CLI) | ✅ Easy | ❌ **Impossible** | ❌ **Impossible** | ❌ **Impossible** | ❌ **Impossible** | N/A |
| VS Code (Extension) | ✅ Easy | ✅ Via extension | ✅ Via extension | ✅ Via extension | ✅ Via extension | Install extension |
---
## 14. Environment Variables Reference
### VS Code Integrated Terminal Environment Variables
| Variable | Value | When Set | Use Case |
| ------------------------------ | ------------------------------ | ------------------------------------------------------------ | ------------------------ |
| `TERM_PROGRAM` | `vscode` | Always in integrated terminal | ✅ Detect VS Code |
| `TERM_PROGRAM_VERSION` | e.g., `1.109.5` | Always in integrated terminal | Version detection |
| `VSCODE_RESOLVING_ENVIRONMENT` | `1` | When VS Code launches environment-resolving shell at startup | Detect startup shell |
| `VSCODE_PID` | (unset in integrated terminal) | Set by extension host, not terminal | Not useful for detection |
| `VSCODE_IPC_HOOK_CLI` | Path to IPC socket | Set by extension host | Not useful for CLI tools |
### Cursor Environment Variables
| Variable | Value | When Set | Use Case |
| ---------------------- | ---------------------------- | ------------------------------------ | ----------------- |
| `TERM_PROGRAM` | `vscode-electron` or similar | Always in Cursor integrated terminal | ✅ Detect Cursor |
| `TERM_PROGRAM_VERSION` | Cursor version | Always in Cursor integrated terminal | Version detection |
### Other Terminal Environment Variables
| Variable | Value | Terminal |
| ------------------ | -------------------------------------- | ------------- |
| `TMUX` | Pane ID or similar | tmux |
| `ZELLIJ` | Session ID | Zellij |
| `ITERM_SESSION_ID` | Session UUID | iTerm2 |
| `TERM` | Terminal type (e.g., `xterm-256color`) | All terminals |
---
## 15. Code Examples
### Detection Code (Ready to Use)
```typescript
// src/adapters/vscode-adapter.ts
export class VSCodeAdapter implements TerminalAdapter {
readonly name = "vscode";
detect(): boolean {
return (
process.env.TERM_PROGRAM === "vscode" ||
process.env.TERM_PROGRAM === "vscode-electron"
);
}
spawn(options: SpawnOptions): string {
throw new Error(
"VS Code integrated terminals do not support spawning " +
"new terminals from command line. Please run pi-teams " +
"inside tmux, Zellij, or iTerm2 for terminal management. " +
"Alternatively, install the pi-teams VS Code extension " +
"(if implemented).",
);
}
kill(paneId: string): void {
throw new Error("Not supported in VS Code without extension");
}
isAlive(paneId: string): boolean {
return false;
}
setTitle(title: string): void {
throw new Error("Not supported in VS Code without extension");
}
}
```
### User-Facing Error Message
```
❌ Cannot spawn terminal in VS Code integrated terminal
pi-teams requires a terminal multiplexer to create multiple panes.
For VS Code users, we recommend one of these options:
Option 1: Run tmux inside VS Code integrated terminal
┌────────────────────────────────────────┐
│ $ tmux new -s pi-teams │
│ $ pi create-team my-team │
│ $ pi spawn-teammate security-bot ... │
└────────────────────────────────────────┘
Option 2: Open VS Code from tmux session
┌────────────────────────────────────────┐
│ $ tmux new -s my-session │
│ $ code . │
│ $ pi create-team my-team │
└────────────────────────────────────────┘
Option 3: Use a terminal with multiplexer support
┌────────────────────────────────────────┐
│ • iTerm2 (macOS) - Built-in support │
│ • tmux - Install: brew install tmux │
│ • Zellij - Install: cargo install ... │
└────────────────────────────────────────┘
Learn more: https://github.com/your-org/pi-teams#terminal-support
```
---
## 16. Conclusions and Recommendations
### Final Recommendation: ❌ Do Not Implement VS Code/Cursor Support
**Primary reasons**:
1. **No CLI API for terminal management**: VS Code provides no command-line interface for spawning or managing terminal panes.
2. **Extension-based solution required**: Would require users to install and configure a VS Code extension, adding significant user friction.
3. **Better alternative exists**: Users can simply run tmux or Zellij inside VS Code integrated terminal, achieving the same result without any additional work.
4. **Maintenance burden**: Maintaining both a Node.js package and a VS Code extension doubles the development and maintenance effort.
5. **Limited benefit**: The primary use case (multiple coordinated terminals in one screen) is already solved by tmux/Zellij/iTerm2.
### Recommended User Guidance
For VS Code/Cursor users, recommend:
```bash
# Option 1: Run tmux inside VS Code (simplest)
tmux new -s pi-teams
# Option 2: Start tmux first, then open VS Code
tmux new -s dev
code .
```
### Documentation Update
Add to pi-teams README.md:
````markdown
## Using pi-teams with VS Code or Cursor
pi-teams works great with VS Code and Cursor! Simply run tmux
or Zellij inside the integrated terminal:
```bash
# Start tmux in VS Code integrated terminal
$ tmux new -s pi-teams
$ pi create-team my-team
$ pi spawn-teammate security-bot "Scan for vulnerabilities"
```
````
Your team will appear in the integrated terminal with proper splits:
┌──────────────────┬──────────────────┐
│ Lead (Team) │ security-bot │
│ │ (scanning...) │
└──────────────────┴──────────────────┘
> **Why not native VS Code terminal support?**
> VS Code does not provide a command-line API for creating terminal
> panes. Using tmux or Zellij inside VS Code gives you the same
> multi-pane experience with no additional extensions needed.
````
---
## 17. Future Possibilities
### If VS Code Adds CLI Terminal API
Monitor VS Code issues and releases for:
- Terminal management commands in `code` CLI
- Public IPC protocol for terminal control
- WebSocket or REST API for terminal management
**Related VS Code issues**:
- (Search GitHub for terminal management CLI requests)
### If User Demand Is High
1. Create GitHub issue: "VS Code integration: Extension approach"
2. Gauge user interest and willingness to install extension
3. If strong demand, implement extension-based solution (Section 11)
### Alternative: Webview-Based Terminal Emulator
Consider building a custom terminal emulator using VS Code's webview API:
- Pros: Full control, no extension IPC needed
- Cons: Reinventing wheel, poor performance, limited terminal features
**Not recommended**: Significant effort for worse UX.
---
## Appendix A: Research Sources
### Official Documentation
- VS Code Terminal API: https://code.visualstudio.com/api/extension-guides/terminal
- VS Code Extension API: https://code.visualstudio.com/api/references/vscode-api
- VS Code CLI: https://code.visualstudio.com/docs/editor/command-line
- Terminal Basics: https://code.visualstudio.com/docs/terminal/basics
### GitHub Repositories
- VS Code: https://github.com/microsoft/vscode
- VS Code Extension Samples: https://github.com/microsoft/vscode-extension-samples
- Cursor: https://github.com/getcursor/cursor
### Key Resources
- `code --help` - Full CLI documentation
- VS Code API Reference - Complete API documentation
- Shell Integration docs - Environment variable reference
---
## Appendix B: Tested Approaches
### ❌ Approaches Tested and Rejected
1. **VS Code CLI Commands**
- Command: `code --help`
- Result: No terminal management commands found
- Conclusion: Not viable
2. **AppleScript (macOS)**
- Tested: AppleScript Editor dictionary for VS Code
- Result: No terminal-related verbs
- Conclusion: Not viable
3. **Shell Escape Sequences**
- Tested: ANSI/OSC codes for terminal control
- Result: No sequences for terminal creation
- Conclusion: Not viable
4. **Environment Variable Inspection**
- Tested: All VS Code/Cursor environment variables
- Result: Detection works, control doesn't
- Conclusion: Useful for detection only
5. **IPC Socket Investigation**
- Tested: `VSCODE_IPC_HOOK_CLI` variable
- Result: Undocumented protocol, no public API
- Conclusion: Not viable
### ✅ Approaches That Work
1. **tmux inside VS Code**
- Tested: `tmux new -s test` in integrated terminal
- Result: ✅ Full tmux functionality available
- Conclusion: Recommended approach
2. **Zellij inside VS Code**
- Tested: `zellij` in integrated terminal
- Result: ✅ Full Zellij functionality available
- Conclusion: Recommended approach
---
## Appendix C: Quick Reference
### Terminal Detection
```typescript
// VS Code
process.env.TERM_PROGRAM === 'vscode'
// Cursor
process.env.TERM_PROGRAM === 'vscode-electron'
// tmux
!!process.env.TMUX
// Zellij
!!process.env.ZELLIJ
// iTerm2
process.env.TERM_PROGRAM === 'iTerm.app'
````
### Why VS Code Terminals Don't Work
```
┌─────────────────────────────────────────────────────┐
│ VS Code Architecture │
├─────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ │
│ │ Integrated │ │ Extension │ │
│ │ Terminal │◀────────│ Host │ │
│ │ (pty) │ NO API │ (TypeScript)│ │
│ └──────┬───────┘ └──────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────┐ │
│ │ Shell │ ← Has no awareness of VS Code │
│ │ (bash/zsh) │ │
│ └──────────────┘ │
│ │
│ CLI tools running in shell cannot create new │
│ terminals because there's no API to call. │
└─────────────────────────────────────────────────────┘
```
### Recommended Workflow for VS Code Users
```bash
# Step 1: Start tmux
tmux new -s pi-teams
# Step 2: Use pi-teams
pi create-team my-team
pi spawn-teammate frontend-dev
pi spawn-teammate backend-dev
# Step 3: Enjoy multi-pane coordination
┌──────────────────┬──────────────────┬──────────────────┐
│ Team Lead │ frontend-dev │ backend-dev │
│ (you) │ (coding...) │ (coding...) │
└──────────────────┴──────────────────┴──────────────────┘
```
---
**Document Version**: 1.0
**Research Date**: February 22, 2026
**Researcher**: ide-researcher (refactor-team)
**Status**: Complete - Recommendation: Do NOT implement VS Code/Cursor terminal support