npm package: @porchestra/cli
Description: CLI for Porchestra - Generate LLM tool handlers
Latest version: 1.0.4

# Porchestra CLI

A powerful CLI tool for generating type-safe LLM tool handlers from Porchestra agents.

## Overview

Porchestra CLI enables developers to:
- Authenticate and manage CLI sessions with 90-day tokens
- Browse and select agents from Porchestra projects
- Generate TypeScript code with Zod schemas for tool validation
- Maintain multi-agent projects with automatic code generation
- Support on-premise deployments with custom API URLs

## Installation

```bash
# Install globally
npm install -g @porchestra/cli

# Or use with npx (no installation)
npx @porchestra/cli <command>
```

**Requirements:**
- Node.js 22+
- TypeScript 5.x project (for generated code)

## Quick Start

```bash
# 1. Login with your Porchestra account
porchestra login

# 2. Explore and select agents to track
porchestra explore

# 3. Generate tool code
porchestra pull
```

## Commands

### `login`

Authenticate with your Porchestra account and generate a CLI token (90-day expiry).

```bash
porchestra login [options]
```

**Options:**
- `--api-url <url>` - Custom API URL for on-premise deployments
- `--device-name <name>` - Name for this device (defaults to hostname + OS)
- `--skip-tls-verify` - Skip TLS certificate verification (development only)

**Interactive Prompts:**
- Email address
- Password (hidden input)
- On-premise deployment (yes/no)
- API URL (if on-premise)

**Example:**
```bash
# Standard login
porchestra login

# On-premise deployment
porchestra login --api-url https://porchestra.company.com/api/v1

# With custom device name
porchestra login --device-name "CI/CD Pipeline"
```

**Output:**
```
🔐 Porchestra CLI Login

✔ Email: user@example.com
✔ Password: ••••••••
✔ Are you using an on-premise deployment? No

✓ Authentication successful
✓ Logged in as user@example.com
  Token expires in 90 days (2025-04-30T12:00:00Z)
  Device: MacBook-Pro - darwin
  Auto-refresh: 7 days before expiry
```

---

### `logout`

Logout and revoke the CLI token.

```bash
porchestra logout [options]
```

**Options:**
- `--all` - Revoke all CLI tokens across all devices

**Example:**
```bash
# Logout current device
porchestra logout

# Logout all devices
porchestra logout --all
```

**Output:**
```
✓ Logged out successfully
```

---

### `whoami`

Display current user information and token status.

```bash
porchestra whoami
```

**Example Output:**
```
👤 User Information

  Email:    user@example.com
  Name:     John Doe
  Org:      Acme Corp

🔑 Token Information

  Device:   MacBook-Pro - darwin
  Expires:  83 days (2025-04-30T12:00:00Z)

📁 Tracked Projects

  Projects: 2
  Agents:   5
```

---

### `explore`

Interactive project and agent browser. Select which agents to track for code generation.

```bash
porchestra explore [options]
```

**Options:**
- `-p, --project <id>` - Start with specific project (skip project selection)

**Interactive Features:**
- Project list with agent counts
- Agent browser with folder paths
- Checkbox selection for agents
- Version resolution display (PRODUCTION/STAGING/DEVELOPMENT)

**Example:**
```bash
# Full explore mode
porchestra explore

# Start with specific project
porchestra explore --project customer-support
```

**Output Example:**
```
📦 Customer Support Bot

  ● Ticket Classifier
     Path: main/ticket-classifier
     Version: v2.3.1 (PRODUCTION)
     Tools: 5

  ● Response Generator
     Path: main/response-generator
     Version: v1.5.0 (PRODUCTION)
     Tools: 3

✓ Tracking 2 agents from Customer Support Bot

📊 Tracking Summary

  Projects: 2
  Agents:   5

Run `porchestra pull` to generate code for tracked agents
```

---

### `pull`

Generate TypeScript tool code for all tracked agents.

```bash
porchestra pull [options]
```

**Options:**
- `-p, --project <id>` - Pull specific project only
- `-a, --agent <id>` - Pull specific agent only
- `-e, --env <environment>` - Target environment: `production`, `staging`, or `development`
- `-o, --output <path>` - Override output directory
- `--force` - Overwrite implementation files (⚠️ may lose code)

**Environment Priority:**
If no environment specified, uses priority: PRODUCTION → STAGING → DEVELOPMENT

**Generated Files:**
For each agent, creates:
- `tool-schemas.ts` - Zod schemas (always overwritten)
- `tool-dispatcher.ts` - Switch/case dispatcher (always overwritten)
- `tool-impl.ts` - Implementation stubs (created once, never overwritten)

**Example:**
```bash
# Pull all tracked agents
porchestra pull

# Pull specific project
porchestra pull --project customer-support

# Pull specific agent
porchestra pull --agent ticket-classifier

# Use staging environment
porchestra pull --env staging

# Custom output directory
porchestra pull --output ./src/my-agents

# Force overwrite implementation files
porchestra pull --force
```

**Output Example:**
```
📦 Customer Support Bot

[1/2] ✓ Ticket Classifier → ./src/agents/main/ticket-classifier
[2/2] ✓ Response Generator → ./src/agents/main/response-generator

📦 Sales Assistant

[1/1] ✓ Lead Scorer → ./src/agents/sales/lead-scorer

✨ Pull Complete

  Generated: 3 / 3 agents
  Output: ./src/agents

Next steps:
  1. Implement tool functions in tool-impl.ts files
  2. Import and use the tool dispatcher in your code
```

**Auto-Trigger Explore:**
If no projects are tracked, `pull` automatically launches `explore` first.

---

### `config`

Manage CLI configuration.

```bash
porchestra config <subcommand>
```

**Subcommands:**

#### `config get <key>`
Get a configuration value.

```bash
porchestra config get api.baseUrl
porchestra config get output.baseDir
```

#### `config set <key> <value>`
Set a configuration value.

```bash
porchestra config set api.baseUrl https://api.porchestra.io/v1
porchestra config set output.baseDir ./src/agents
porchestra config set output.createIndexFiles true
```

#### `config list`
List all configuration values.

```bash
porchestra config list
```

#### `config reset`
Reset all configuration (⚠️ clears auth and tracking).

```bash
porchestra config reset
porchestra config reset --force  # Skip confirmation
```

---

### `status`

Show CLI status and tracked projects summary.

```bash
porchestra status
```

**Output Example:**
```
📊 Porchestra CLI Status

🔑 Authentication
  Status:   ✓ Logged in
  Device:   MacBook-Pro - darwin
  Expires:  83 days (2025-04-30T12:00:00Z)

🔗 API Configuration
  URL:      https://api.porchestra.io/v1

📁 Tracked Projects
  Projects: 2
  Agents:   5

  Customer Support Bot
    └─ Ticket Classifier main/ticket-classifier (2 days ago)
    └─ Response Generator main/response-generator (2 days ago)
    Last pulled: 2 days ago

  Sales Assistant
    └─ Lead Scorer sales/lead-scorer (never)

📂 Output Configuration
  Base dir: ./src/agents
  Index files: yes
```

---

### `agents`

List or remove tracked agents without running the explorer.

```bash
# List all tracked agents (default)
porchestra agents
porchestra agents list

# Filter by project id/slug
porchestra agents list --project customer-support

# Remove a tracked agent by id/slug (will prompt when ambiguous)
porchestra agents remove ticket-classifier
porchestra agents remove ticket-classifier --project customer-support

# Skip confirmation
porchestra agents remove ticket-classifier --project customer-support --force
```

**Behavior:**
- `agents` defaults to `agents list` for convenience.
- `remove` drops the agent from tracking and deletes the project entry if it was the last tracked agent.
- Use `--json` on `agents list` for scripting.

---

## Configuration

Configuration is stored in `~/.porchestra/config.json`.

### Configuration Options

| Key | Type | Default | Description |
|-----|------|---------|-------------|
| `api.baseUrl` | string | `https://api.porchestra.io/v1` | API endpoint URL |
| `api.skipTlsVerify` | boolean | `false` | Skip TLS verification (dev only) |
| `output.baseDir` | string | `./src/agents` | Base directory for generated files |
| `output.createIndexFiles` | boolean | `true` | Create index.ts files for exports |

### Environment Variables

| Variable | Description | Example |
|----------|-------------|---------|
| `PORCHESTRA_API_URL` | Override API URL | `https://porchestra.internal.company.com` |
| `PORCHESTRA_CONFIG_DIR` | Custom config directory | `/etc/porchestra` |
| `PORCHESTRA_SKIP_TLS_VERIFY` | Skip TLS verification | `true` |

---

## Multi-Agent Support

Porchestra CLI supports multiple agents organized by folder paths from your Porchestra project.

### Folder Path Resolution

Agents are organized based on their `folderPath` from the database:

| folderPath (DB) | Generated Directory |
|-----------------|---------------------|
| `/main/x-agent/` | `{baseDir}/main/x-agent/` |
| `y-agent` | `{baseDir}/y-agent/` |
| `/api/v2/customer-support` | `{baseDir}/api/v2/customer-support/` |
| `//legacy//agents//` | `{baseDir}/legacy/agents/` |

### Example Project Structure

```
./src/agents/
├── main/
│   ├── ticket-classifier/
│   │   ├── tool-schemas.ts      # Zod schemas
│   │   ├── tool-dispatcher.ts   # Switch/case dispatcher
│   │   └── tool-impl.ts         # Your implementation
│   └── response-generator/
│       ├── tool-schemas.ts
│       ├── tool-dispatcher.ts
│       └── tool-impl.ts
└── sales/
    └── lead-scorer/
        ├── tool-schemas.ts
        ├── tool-dispatcher.ts
        └── tool-impl.ts
```

---

## Environment-Based Version Resolution

The CLI automatically resolves which agent version to use based on environment:

### Priority Order

1. **PRODUCTION** - Used if available
2. **STAGING** - Fallback if no production version
3. **DEVELOPMENT** - Fallback if no staging version

### Command Examples

```bash
# Use production (default priority)
porchestra pull

# Force staging environment
porchestra pull --env staging

# Force development environment
porchestra pull --env development
```

**Note:** You cannot pin to specific versions. The CLI always fetches the latest version from the requested environment (or falls back through the priority chain).

---

## Generated Code

### tool-schemas.ts

Auto-generated Zod schemas for runtime validation:

```typescript
import { z } from 'zod';

export const GetUserParamsSchema = z.object({
  id: z.string().uuid()
});

export type GetUserParams = z.infer<typeof GetUserParamsSchema>;

export type ToolName = 'getUser' | 'sendEmail';
```

### tool-dispatcher.ts

Auto-generated switch/case dispatcher:

```typescript
import { GetUserParams, getUser } from './tool-impl.js';

export async function dispatchTool(
  toolName: string,
  params: unknown
): Promise<ToolResult> {
  switch (toolName) {
    case 'getUser': {
      const result = await getUser(params as GetUserParams);
      return { success: true, data: result };
    }
    default:
      return { success: false, error: `Unknown tool: ${toolName}` };
  }
}
```

### tool-impl.ts

User implementation file (created once, never overwritten):

```typescript
import { GetUserParams } from './tool-schemas.js';

export async function getUser(params: GetUserParams): Promise<any> {
  // TODO: Implement getUser
  console.log('Called getUser with:', params);
  throw new Error('getUser not implemented');
}
```

**Important:** Never modify `tool-schemas.ts` or `tool-dispatcher.ts` manually - they are auto-generated. Only edit `tool-impl.ts` files.

---

## Usage in Your Application

```typescript
import { dispatchTool } from './src/agents/main/ticket-classifier/tool-dispatcher.js';
import { myToolLogic } from './src/agents/main/ticket-classifier/tool-impl.js';

// In your LLM loop
const toolCall = llmResponse.tool_calls[0];

try {
  const result = await dispatchTool(
    toolCall.name,
    JSON.parse(toolCall.arguments)
  );
  
  if (result.success) {
    // Send result back to LLM
  } else {
    console.error('Tool failed:', result.error);
  }
} catch (error) {
  console.error('Tool execution failed:', error);
}
```

---

## Troubleshooting

### Authentication Issues

**Problem:** "Invalid email or password"
- Ensure you're using the same credentials as the web app
- Check API URL if using on-premise deployment

**Problem:** "Token expired"
- Run `porchestra login` to generate a new token
- Tokens auto-refresh 7 days before expiry

### Connection Issues

**Problem:** "ECONNREFUSED" or "ENOTFOUND"
- Check if API server is running
- Verify API URL in config: `porchestra config get api.baseUrl`
- For on-premise: ensure correct URL format

### Code Generation Issues

**Problem:** "No projects selected for tracking"
- Run `porchestra explore` first to select agents
- Or run `porchestra pull` which auto-triggers explore

**Problem:** "tool-impl.ts already exists"
- This is expected - implementation files are created once
- Use `--force` flag to overwrite (⚠️ will lose your code)

### Version Issues

**Problem:** "Agent has no published versions"
- Agent must be published to at least one environment
- Check in Porchestra web app if agent is published

---

## API Endpoints

The CLI communicates with these API endpoints:

| Endpoint | Description | Auth |
|----------|-------------|------|
| `POST /cli/login` | Authenticate and generate CLI token | None |
| `POST /cli/token/refresh` | Refresh expiring token | CLI Token |
| `DELETE /cli/token` | Revoke token | CLI Token |
| `GET /cli/tokens` | List active tokens | CLI Token |
| `GET /cli/config` | Get CLI configuration | None |
| `GET /projects/:id/agents` | List agents | CLI Token |
| `POST /projects/:id/agents/:id/tools/export` | Export tools | CLI Token |

---

## Development

```bash
# Install dependencies
pnpm install

# Build
pnpm run build

# Run tests
pnpm run test

# Watch mode
pnpm run dev
```

---

## License

MIT