Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 86 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Commands

```bash
pnpm install # install all workspace dependencies
pnpm build # build all packages (tsc)
pnpm test # run all tests
pnpm lint # lint all packages
pnpm lint:fix # auto-fix lint issues
pnpm clean # remove local DB and worktrees artifacts

# run a single package's tests
pnpm --filter @parallax/orchestrator test
pnpm --filter parallax-cli test

# local development — use this entrypoint for all manual testing
pnpm parallax preflight
pnpm parallax start --server-api-port 3000 --server-ui-port 8080 --concurrency 2
pnpm parallax register ./parallax.example.yml --env-file ./.env
pnpm parallax pending
pnpm parallax stop
```

Node.js >= 23.7.0 and pnpm 10.x are required. The `--filter` flag targets individual workspace packages by their `name` in `package.json`.

## Architecture

Parallax is a plan-first AI orchestration runtime. It pulls work from Linear or GitHub, generates a plan via an AI agent, waits for human approval, then executes the approved plan in an isolated git worktree and opens a PR.

### Package layout

- **`packages/common`** — shared models, enums (`TASK_STATUS`, `TaskPlanState`, `AGENT_PROVIDER`, etc.), interfaces (`Task`, `ProjectConfig`, `AgentResult`, `PlanResult`), and the `HostExecutor` abstraction. All cross-package types live here.
- **`packages/orchestrator`** — the runtime process: polling loop, task state machine, AI adapter dispatch, Fastify REST API, Socket.io streaming, SQLite persistence.
- **`packages/cli`** — the published `parallax-cli` npm package. It is the sole entry point for users. Commands talk to the orchestrator over HTTP. The `start` command forks the orchestrator as a child process and writes `~/.parallax/running.json`.
- **`packages/ui`** — React/Vite dashboard served by the orchestrator's UI server in production.
- **`packages/marketing`** — standalone marketing site, not part of the runtime.

### Runtime state (`~/.parallax/`)

| File/Dir | Purpose |
|---|---|
| `registry.json` | Registered `parallax.yml` configs and optional env file paths |
| `running.json` | PID, ports, concurrency of the active orchestrator process |
| `parallax.db` | SQLite — tasks and task logs tables |
| `worktrees/` | Ephemeral git worktrees created per task, cleaned up after execution |

Override via `PARALLAX_DATA_DIR` env var.

### Task state machine

Tasks move through two parallel dimensions:

**`TASK_STATUS`**: `PENDING` → `IN_PROGRESS` → `COMPLETED` / `FAILED` / `CANCELED`

**`TaskPlanState`**: `PLAN_GENERATING` → `PLAN_READY` / `PLAN_REQUIRES_CLARIFICATION` → _(user approves)_ → `PLAN_APPROVED` → execution → `PLAN_APPROVED` (persisted on PR creation). `NOT_REQUIRED` is used for PR-review tasks that skip planning.

State transitions are coordinated through `taskLifecycle` (`packages/orchestrator/src/task-lifecycle.ts`) which writes to the DB and updates the in-memory log display.

### Orchestrator polling loop (`packages/orchestrator/src/index.ts`)

The `main()` function runs an infinite loop (15 s interval) calling `pollProjects()`. For each registered project it:
1. Fetches new issues from the configured provider (Linear or GitHub).
2. Creates worktrees and runs `adapter.runPlan()` for tasks needing a plan.
3. Dispatches `adapter.runTask()` for tasks with an approved plan.
4. Enforces a `pLimit` concurrency cap across all projects.

Cancellation is tracked via an in-memory `canceledTasks: Set<string>` checked at each `throwIfCancellationRequested()` call.

### AI adapters (`packages/orchestrator/src/ai-adapters/`)

`BaseAgentAdapter` defines two abstract methods: `runPlan(task, workingDir, project)` and `runTask(task, workingDir, project, approvedPlan?, outputMode?)`. Concrete implementations: `CodexAdapter`, `GeminiAdapter`, `ClaudeCodeAdapter`. The adapter is selected from `project.agent.provider` in `parallax.yml` and cached per project in an `adapterCache` map.

### Configuration flow

`parallax register ./parallax.yml` writes the config path to `~/.parallax/registry.json`. At runtime, `loadConfig()` reads and merges all registered YAML files. Required fields per project entry: `id`, `workspaceDir`, `pullFrom.provider`, `pullFrom.filters`, `agent.provider`.

## Key conventions

- **Fail fast**: missing required config or malformed input throws immediately — no silent fallbacks.
- **Strict parsing**: all CLI arg and request parsing goes through dedicated parser functions in `args.ts` and `runtime/api/request-parsers.ts`; never parse inline.
- **`pnpm parallax <command>`** is the canonical local testing entrypoint — do not invoke package-level scripts directly for runtime flows.
- **Docs updates belong in the same commit** as behavior changes.
- Tests live in `packages/<name>/test/` and mirror the `src/` structure.
36 changes: 33 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ It pulls work from Linear or GitHub, creates isolated worktrees, runs an agent i
- Global runtime state under `~/.parallax`.
- CLI control plane plus dashboard UI.
- Codex, Gemini, and Claude Code adapters (configurable per project).
- Named agents with system prompts and per-label routing.
- Slack bot for plan approvals and task notifications (Socket Mode, no public URL needed).

## Requirements

Expand Down Expand Up @@ -49,9 +51,28 @@ pnpm parallax start --server-api-port 3000 --server-ui-port 8080 --concurrency 2
pnpm parallax register ./parallax.yml --env-file ./.env
```

`parallax.yml` is a YAML array of project entries:
`parallax.yml` is a YAML array. Items are distinguished by key — you can define named agents, a Slack integration, and one or more project entries:

```yaml
# Optional: named agent personalities
- agents:
- name: developer
provider: claude-code
model: claude-opus-4-5
systemPrompt: |
You are a senior backend engineer. Prioritize correctness and minimal diffs.
Always run existing tests before submitting.
- name: reviewer
provider: codex
model: o3

# Optional: Slack bot integration
- slack:
botToken: xoxb-your-bot-token
appToken: xapp-your-app-level-token
channel: "#ai-tasks"

# Project entries
- id: example-repo
workspaceDir: /absolute/path/to/your/repo
pullFrom:
Expand All @@ -62,10 +83,19 @@ pnpm parallax register ./parallax.yml --env-file ./.env
state: open
labels: [ai-ready]
agent:
provider: codex
model: gpt-5.4
name: developer
agentLabels:
ai-frontend: reviewer
```

Projects that do not use named agents can still specify `agent.provider` directly — the old format continues to work unchanged.

## Slack bot

Parallax can connect to a Slack workspace using Bolt Socket Mode. When configured, it posts plan-ready notifications with Approve and Reject buttons directly in Slack, posts PR and failure events, and responds to a `/parallax` slash command for retry, cancel, status, and pr-review. Because Socket Mode uses an outbound WebSocket, no public URL is required — it works on localhost and behind NAT.

See [docs/slack-bot.md](docs/slack-bot.md) for the full setup guide.

## CLI

```bash
Expand Down
2 changes: 2 additions & 0 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ This documentation is for people trying Parallax for the first time and running
- [Getting Started](./getting-started.md): install Parallax, start it, register your repo, and open the dashboard.
- [Configuration Reference](./configuration.md): what goes in `parallax.yml` and how to register it.
- [CLI Reference](./cli-reference.md): the day-to-day commands you will actually run.
- [Task Lifecycle](./task-lifecycle.md): how Parallax processes tasks from pull to PR.
- [Slack Bot](./slack-bot.md): connect Parallax to Slack for plan approvals and task notifications.
- [Troubleshooting](./troubleshooting.md): fixes for common setup and runtime problems.

## What Parallax does
Expand Down
171 changes: 171 additions & 0 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,177 @@ Parallax always runs supported agents in a sandbox. Approval behavior and MCP/ru
model: gemini-2.5-pro
```

## Named agents

### The `agents:` top-level item

`parallax.yml` supports an optional top-level `agents:` item that defines reusable agent personalities. Projects reference them by name instead of specifying a provider directly.

```yaml
- agents:
- name: developer
provider: claude-code
model: claude-opus-4-5
systemPrompt: |
You are a senior backend engineer. Prioritize correctness and minimal diffs.
Always run existing tests before submitting.
- name: reviewer
provider: codex
model: o3
systemPrompt: |
You are a strict code reviewer. Focus on security, edge cases, and regressions.
```

#### Agent fields

##### name (required)

- non-empty string
- must be unique across the `agents:` list
- used to reference this agent from project entries

##### provider (required)

- allowed values: `codex`, `gemini`, `claude-code`

##### model (optional)

- model string forwarded to the selected agent provider

##### systemPrompt (optional)

- multi-line string prepended to every prompt sent to this agent
- use it to encode team conventions, preferred patterns, or persona instructions

### Referencing a named agent from a project entry

Use `agent.name` instead of `agent.provider` on a project entry:

```yaml
- id: my-repo
workspaceDir: /path/to/repo
pullFrom:
provider: github
filters:
owner: myorg
repo: my-repo
labels: [ai-ready]
agent:
name: developer
```

`agent.provider` continues to work as before for projects that do not need a named agent.

### Per-label agent routing (`agentLabels`)

`agentLabels` is an optional map on a project entry. It routes tickets with specific labels to a named agent, overriding the project's default agent for those tickets.

```yaml
- id: my-repo
workspaceDir: /path/to/repo
pullFrom:
provider: github
filters:
owner: myorg
repo: my-repo
labels: [ai-ready]
agent:
name: developer
agentLabels:
ai-frontend: reviewer
ai-security: reviewer
```

In this example, tickets labeled `ai-frontend` or `ai-security` are handled by the `reviewer` agent; all other tickets go to `developer`.

## Slack bot integration

### The `slack:` top-level item

Add a `slack:` item to `parallax.yml` to enable the Slack bot integration:

```yaml
- slack:
botToken: xoxb-your-bot-token
appToken: xapp-your-app-level-token
channel: "#ai-tasks"
```

#### Slack fields

##### botToken (required)

- Bot User OAuth Token from your Slack app
- starts with `xoxb-`
- requires `chat:write` and `commands` bot token scopes

##### appToken (required)

- App-Level Token from your Slack app
- starts with `xapp-`
- requires `connections:write` scope
- used for Socket Mode (outbound WebSocket; no public URL needed)

##### channel (required)

- the Slack channel name where notifications are posted (e.g. `"#ai-tasks"`)
- the bot must be invited to this channel before it can post

See [Slack Bot](./slack-bot.md) for the full setup guide.

## Complete example

The following shows all three item types in a single `parallax.yml`:

```yaml
# Named agent personalities
- agents:
- name: developer
provider: claude-code
model: claude-opus-4-5
systemPrompt: |
You are a senior backend engineer. Prioritize correctness and minimal diffs.
Always run existing tests before submitting.
- name: reviewer
provider: codex
model: o3
systemPrompt: |
You are a strict code reviewer. Focus on security, edge cases, and regressions.

# Slack bot integration
- slack:
botToken: xoxb-your-bot-token
appToken: xapp-your-app-level-token
channel: "#ai-tasks"

# Project entries
- id: my-repo
workspaceDir: /path/to/repo
pullFrom:
provider: github
filters:
owner: myorg
repo: my-repo
state: open
labels: [ai-ready]
agent:
name: developer
agentLabels:
ai-frontend: reviewer
ai-security: reviewer

- id: platform-api
workspaceDir: /Users/you/src/platform-api
pullFrom:
provider: linear
filters:
team: API
state: Todo
agent:
provider: gemini
model: gemini-2.5-pro
```

## Validation failures you may see

- `Invalid parallax config`
Expand Down
Loading
Loading