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
28 changes: 0 additions & 28 deletions .codex/skills/add-tests/SKILL.md

This file was deleted.

31 changes: 0 additions & 31 deletions .codex/skills/update-docs/SKILL.md

This file was deleted.

30 changes: 22 additions & 8 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ 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 init
pnpm parallax start --server-api-port 9371 --server-ui-port 9372 --concurrency 2
pnpm parallax status
pnpm parallax open
pnpm parallax stop
```

Expand All @@ -32,23 +33,28 @@ Parallax is a plan-first AI orchestration runtime. It pulls work from Linear or

### 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/common`** — shared models, enums (`TASK_STATUS`, `TaskPlanState`, `AGENT_PROVIDER`, etc.), interfaces (`Task`, `ProjectConfig`, `StoredConfig`, `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/slack`** — optional Slack bot (`SlackBot`) that posts task lifecycle notifications and handles interactive commands (approve, reject, cancel). Integrated at runtime via `setSlackBot()` / `getSlackBot()` in `slack-integration.ts`.
- **`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 |
| `config.json` | All project, agent, Slack, and secrets config (managed by `parallax init` and dashboard) |
| `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.

### Configuration flow

`~/.parallax/config.json` is the single source of truth. `loadConfig()` in `packages/orchestrator/src/config-loader.ts` reads it via `config-store.ts`, injects `secrets` into `process.env`, validates the structure via `config-validation.ts`, and returns `AppConfig`. Agent processes inherit secrets through `process.env`. No YAML files.

### Task state machine

Tasks move through two parallel dimensions:
Expand All @@ -71,11 +77,19 @@ Cancellation is tracked via an in-memory `canceledTasks: Set<string>` checked at

### 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.
`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` and cached per project in an `adapterCache` map. Secrets are available in `process.env` (injected by `loadConfig()`).

### Configuration flow
### Dashboard layout

Three-column layout: icon nav (left, 52px) | list panel (280px) | main content (fills remainder).

- **NavBar** (`NavBar.tsx`) — icon-only vertical navigation for Tasks / Projects / Integrations
- **ListPanel** (`ListPanel.tsx`) — scrollable list for the active section
- **Main content** — `LogViewer`, `ProjectEditor`, `IntegrationDetail`, or `EmptyState`

### API server (`packages/orchestrator/src/runtime/api-server.ts`)

`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`.
The `mutateConfig(updater)` helper reads `config.json`, applies an updater, writes back atomically, reloads the runtime, and emits `config_updated` over Socket.io. All CRUD endpoints for projects, agents, Slack, and secrets use it.

## Key conventions

Expand Down
157 changes: 52 additions & 105 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@ It pulls work from Linear or GitHub, creates isolated worktrees, runs an agent i
- Plan-first task lifecycle with explicit approval/rejection.
- Issue intake from Linear and GitHub.
- Global runtime state under `~/.parallax`.
- CLI control plane plus dashboard UI.
- CLI onboarding wizard 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 All @@ -24,7 +23,6 @@ It pulls work from Linear or GitHub, creates isolated worktrees, runs an agent i
- `git`
- `gh`
- at least one supported agent CLI (`codex`, `gemini`, or `claude`)
- Provider credentials in your shell environment (optional per-project `.env` via `parallax register --env-file`)

## Local development setup

Expand All @@ -42,113 +40,72 @@ npm i -g parallax-cli
parallax preflight
```

## Configuration (`parallax.yml`)
## First-time setup

Repository config is stored per repo, then registered into the global Parallax runtime:
Run the interactive setup wizard:

```bash
pnpm parallax start --server-api-port 3000 --server-ui-port 8080 --concurrency 2
pnpm parallax register ./parallax.yml --env-file ./.env
parallax init
```

`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:
provider: github
filters:
owner: your-github-org-or-user
repo: your-repo
state: open
labels: [ai-ready]
agent:
name: developer
agentLabels:
ai-frontend: reviewer
The wizard collects:
- Project ID and path to your local git repository
- Issue source (GitHub or Linear) and filter settings
- AI agent (Claude Code, Codex, or Gemini)
- Slack notifications (optional)
- API secrets (Linear key if needed)

Configuration is stored in `~/.parallax/config.json`. Projects and integrations can also be managed from the dashboard UI.

## Starting Parallax

```bash
parallax start
parallax open # opens the dashboard in your browser
parallax status # check health + running projects
parallax stop
```

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

```bash
parallax --version
parallax init # first-time setup wizard
parallax start [--server-api-port <port>] [--server-ui-port <port>] [--concurrency <count>]
parallax stop
parallax status
parallax open
parallax preflight
parallax pr-review <task-id>
parallax retry <task-id>
parallax cancel <task-id>
parallax logs [--task <id>]
```

## 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.
Configure Slack during `parallax init` or via the **Integrations** tab in the dashboard.

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

```bash
pnpm parallax --version
pnpm parallax start --server-api-port 3000 --server-ui-port 8080 --concurrency 2
pnpm parallax register ./parallax.yml --env-file ./.env
pnpm parallax unregister ./parallax.yml
pnpm parallax stop
pnpm parallax preflight
pnpm parallax status
pnpm parallax pending
pnpm parallax pr-review <task-id>
pnpm parallax retry <task-id>
pnpm parallax cancel <task-id>
pnpm parallax logs --task <task-id>
```
## Dashboard

Commands:
The dashboard is accessible at `http://localhost:9372` (default):

- `parallax start [--server-api-port <port>] [--server-ui-port <port>] [--concurrency <count>]`
- `parallax register <config-file> [--env-file <path>]`
- `parallax unregister <config-file>`
- `parallax stop`
- `parallax preflight`
- `parallax status`
- `parallax pending [--approve <id>] [--reject <id>]`
- `parallax pr-review <task-id>` (experimental)
- `parallax retry <task-id>`
- `parallax cancel <task-id>`
- `parallax logs [--task <id>]`
- **Tasks** — live task list with plan approval and log streaming
- **Projects** — add, edit, and delete project configurations
- **Integrations** — configure GitHub, Linear, Slack, and API keys

## Runtime behavior

1. Pull eligible tasks from provider filters.
2. Generate plan text and persist it.
3. Wait for explicit plan approval from UI or CLI.
3. Wait for explicit plan approval from UI, CLI, or Slack.
4. Execute only approved plan steps.
5. Open/update PR and move task lifecycle state.

## Dashboard behavior

- Pending plans are editable in a textarea and can be approved/rejected in-place.
- Task logs stream in real time.
- File changes are shown as clickable entries with side-panel diff view.

## Development

See [CONTRIBUTING.md](CONTRIBUTING.md).

## Documentation

For full user guides, see [docs/README.md](docs/README.md).

## Publish Global CLI (`parallax-cli`)

Parallax is published as a single global CLI package:
Expand All @@ -163,31 +120,21 @@ Releases are published through the manual GitHub Actions workflow:
- trigger it with `Run workflow`
- the workflow publishes the exact version already set in [`packages/cli/package.json`](packages/cli/package.json)

Repository requirement:

- configure npm trusted publishing for this repository/package in npm
Before triggering the release, update the version in `packages/cli/package.json`.

Before triggering the release, update the version in:
Default runtime locations and ports:

```bash
packages/cli/package.json
```
- runtime state: `~/.parallax`
- API: `http://localhost:9371`
- dashboard: `http://localhost:9372`

Then on Raspberry Pi / any machine:
## Development

```bash
npm i -g parallax-cli
parallax preflight
parallax start --server-api-port 3000 --server-ui-port 8080 --concurrency 2
parallax status
parallax register ./parallax.yml
```
See [CONTRIBUTING.md](CONTRIBUTING.md).

Default runtime locations and ports:
## Documentation

- runtime state: `~/.parallax`
- API: `http://localhost:3000`
- dashboard: `http://localhost:8080`
For full user guides, see [docs/README.md](docs/README.md).

## License

Expand Down
11 changes: 5 additions & 6 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ This documentation is for people trying Parallax for the first time and running

## Documentation map

- [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.
- [Getting Started](./getting-started.md): install Parallax, run the setup wizard, and open the dashboard.
- [Configuration Reference](./configuration.md): how Parallax stores config and what each field means.
- [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.
Expand All @@ -23,8 +23,7 @@ This documentation is for people trying Parallax for the first time and running

1. Install: `npm i -g parallax-cli`
2. Validate dependencies: `parallax preflight`
3. Create `parallax.yml`
3. Run the setup wizard: `parallax init`
4. Start Parallax: `parallax start`
5. Check runtime status: `parallax status`
6. Register config: `parallax register ./parallax.yml`
7. Open dashboard: `http://localhost:8080`
5. Open the dashboard: `parallax open`
6. Check runtime status: `parallax status`
Loading
Loading