Skip to content

Commit 21025d6

Browse files
committed
refactor: rename planning terminology to plan
Rename 'planning' to 'plan' throughout the codebase to match OpenCode's built-in agent naming conventions (plan, build, evaluation). Changes: - planningModel → planModel (config, types, CLI) - --planning-model → --plan-model (CLI flag) - OPENCODER_PLANNING_MODEL → OPENCODER_PLAN_MODEL (env var) - Phase 'planning' → 'plan' (types, state) - generatePlanningPrompt → generatePlanPrompt (plan.ts) - generateIdeaPlanningPrompt → generateIdeaPlanPrompt (plan.ts) - runPlanning → runPlan (builder.ts) - runIdeaPlanning → runIdeaPlan (builder.ts) - runPlanningPhase → runPlanPhase (loop.ts) - Updated all docs, tests, and example config - Updated release.yml workflow for Bun cross-compilation Signed-off-by: leocavalcante <[email protected]>
1 parent 2f0b84e commit 21025d6

File tree

12 files changed

+116
-114
lines changed

12 files changed

+116
-114
lines changed

.github/workflows/release.yml

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,40 +14,41 @@ jobs:
1414
matrix:
1515
include:
1616
- os: ubuntu-latest
17-
target: x86_64-linux
18-
artifact: opencoder-linux-amd64
17+
target: bun-linux-x64
18+
artifact: opencoder-linux-x64
1919
- os: ubuntu-latest
20-
target: aarch64-linux
20+
target: bun-linux-arm64
2121
artifact: opencoder-linux-arm64
2222
- os: macos-latest
23-
target: x86_64-macos
24-
artifact: opencoder-macos-amd64
23+
target: bun-darwin-x64
24+
artifact: opencoder-darwin-x64
2525
- os: macos-latest
26-
target: aarch64-macos
27-
artifact: opencoder-macos-arm64
26+
target: bun-darwin-arm64
27+
artifact: opencoder-darwin-arm64
2828
runs-on: ${{ matrix.os }}
2929

3030
steps:
3131
- uses: actions/checkout@v4
3232

33-
- name: Setup Zig
34-
uses: mlugg/setup-zig@v2
33+
- name: Setup Bun
34+
uses: oven-sh/setup-bun@v2
3535
with:
36-
version: 0.15.2
36+
bun-version: latest
3737

38-
- name: Build release
39-
run: zig build -Doptimize=ReleaseSafe -Dtarget=${{ matrix.target }}
40-
41-
- name: Rename binary
42-
run: mv zig-out/bin/opencoder ${{ matrix.artifact }}
38+
- name: Install dependencies
39+
run: bun install
4340

44-
- name: Strip binary
45-
if: matrix.os == 'ubuntu-latest'
46-
run: strip ${{ matrix.artifact }}
41+
- name: Build release
42+
run: bun build --compile --minify --target=${{ matrix.target }} src/index.ts --outfile ${{ matrix.artifact }}
4743

48-
- name: Calculate checksum
44+
- name: Calculate checksum (Linux)
45+
if: runner.os == 'Linux'
4946
run: sha256sum ${{ matrix.artifact }} > ${{ matrix.artifact }}.sha256
5047

48+
- name: Calculate checksum (macOS)
49+
if: runner.os == 'macOS'
50+
run: shasum -a 256 ${{ matrix.artifact }} > ${{ matrix.artifact }}.sha256
51+
5152
- name: Upload artifact
5253
uses: actions/upload-artifact@v4
5354
with:
@@ -67,15 +68,16 @@ jobs:
6768
merge-multiple: true
6869

6970
- name: Create checksums.txt
71+
working-directory: artifacts
7072
run: cat *.sha256 > checksums.txt
7173

7274
- name: Create release
7375
uses: softprops/action-gh-release@v2
7476
with:
7577
files: |
76-
opencoder-linux-amd64
77-
opencoder-linux-arm64
78-
opencoder-macos-amd64
79-
opencoder-macos-arm64
80-
checksums.txt
78+
artifacts/opencoder-linux-x64
79+
artifacts/opencoder-linux-arm64
80+
artifacts/opencoder-darwin-x64
81+
artifacts/opencoder-darwin-arm64
82+
artifacts/checksums.txt
8183
generate_release_notes: true

AGENTS.md

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ describe("module", () => {
258258
### Environment Variables
259259

260260
```bash
261-
OPENCODER_PLANNING_MODEL=anthropic/claude-sonnet-4
261+
OPENCODER_PLAN_MODEL=anthropic/claude-sonnet-4
262262
OPENCODER_BUILD_MODEL=anthropic/claude-sonnet-4
263263
OPENCODER_VERBOSE=true
264264
OPENCODER_MAX_RETRIES=3
@@ -271,7 +271,7 @@ OPENCODER_TASK_PAUSE_SECONDS=2
271271

272272
```json
273273
{
274-
"planningModel": "anthropic/claude-sonnet-4",
274+
"planModel": "anthropic/claude-sonnet-4",
275275
"buildModel": "anthropic/claude-sonnet-4",
276276
"verbose": false,
277277
"maxRetries": 3,
@@ -288,7 +288,7 @@ opencoder --model anthropic/claude-sonnet-4
288288
# With project directory and hint
289289
opencoder -m anthropic/claude-sonnet-4 -p ./myproject "focus on tests"
290290

291-
# Different models for planning and build
291+
# Different models for plan and build
292292
opencoder -P anthropic/claude-opus-4 -B anthropic/claude-sonnet-4
293293

294294
# Verbose output
@@ -302,19 +302,19 @@ Opencoder includes an **ideas queue system** that allows users to provide specif
302302
### How It Works
303303

304304
1. **Ideas Directory**: `.opencoder/ideas/` - Users place `.md` files here
305-
2. **Planning Integration**: Before each planning cycle, the loop checks for ideas
305+
2. **Plan Integration**: Before each plan cycle, the loop checks for ideas
306306
3. **Selection Logic**:
307307
- **1 idea**: Used directly (no AI selection call)
308308
- **2+ ideas**: AI evaluates all and picks the simplest/quick-win considering dependencies
309309
4. **Build**: Selected idea is deleted, plan is created from idea content
310-
5. **Fallback**: When ideas are exhausted, returns to autonomous planning
310+
5. **Fallback**: When ideas are exhausted, returns to autonomous plan
311311

312312
### Key Modules
313313

314314
- **`ideas.ts`**: Core module with `Idea` interface, `loadAllIdeas()`, `formatIdeasForSelection()`
315-
- **`plan.ts`**: Contains `generateIdeaSelectionPrompt()` and `generateIdeaPlanningPrompt()`
316-
- **`builder.ts`**: Has `runIdeaSelection()` and `runIdeaPlanning()` methods
317-
- **`loop.ts`**: Integrates ideas check before planning phase
315+
- **`plan.ts`**: Contains `generateIdeaSelectionPrompt()` and `generateIdeaPlanPrompt()`
316+
- **`builder.ts`**: Has `runIdeaSelection()` and `runIdeaPlan()` methods
317+
- **`loop.ts`**: Integrates ideas check before plan phase
318318

319319
### Selection Criteria
320320

@@ -351,7 +351,7 @@ bun run dev -- -m anthropic/claude-sonnet-4 -p test-project
351351
### Implementation Notes
352352

353353
- Ideas take **full precedence** over user hints
354-
- Idea files are **deleted before planning** (prevents retry loops)
354+
- Idea files are **deleted before plan** (prevents retry loops)
355355
- Empty/invalid ideas are **automatically cleaned up**
356356
- No naming conventions required - any `.md` file works
357357

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88

99
- **Autonomous Development Loop** - Continuously plans, builds, and evaluates without stopping
1010
- **OpenCode SDK Integration** - Direct SDK integration with real-time event streaming
11-
- **Ideas Queue** - Drop markdown files in `.opencoder/ideas/` to prioritize specific tasks before autonomous planning
12-
- **Two-Model Architecture** - Uses a high-capability model for planning and a faster model for building
11+
- **Ideas Queue** - Drop markdown files in `.opencoder/ideas/` to prioritize specific tasks before autonomous plan
12+
- **Two-Model Architecture** - Uses a high-capability model for plan and a faster model for building
1313
- **Live Output Streaming** - Real-time display of AI thinking, tool calls, and results
1414
- **State Persistence** - Resumes from where it left off after interruptions (JSON format)
1515
- **Exponential Backoff** - Graceful retry logic for transient failures
@@ -57,7 +57,7 @@ Instead of interactive sessions where you guide the AI, OpenCoder creates an *au
5757

5858
### The Philosophy
5959

60-
OpenCoder treats software development as an **infinite game**. There's always another test to write, another edge case to handle, another optimization to make. OpenCoder embraces this by never declaring "done"—it continuously cycles through planning, building, and evaluation until you tell it to stop.
60+
OpenCoder treats software development as an **infinite game**. There's always another test to write, another edge case to handle, another optimization to make. OpenCoder embraces this by never declaring "done"—it continuously cycles through plan, build, and evaluation until you tell it to stop.
6161

6262
## Installation
6363

@@ -111,19 +111,19 @@ opencoder --model anthropic/claude-sonnet-4
111111
opencoder -m anthropic/claude-sonnet-4 -p ./myproject "build a REST API"
112112
```
113113

114-
### With Different Planning and Build Models
114+
### With Different Plan and Build Models
115115

116116
```bash
117-
# Use a more capable model for planning, faster model for building
117+
# Use a more capable model for plan, faster model for building
118118
opencoder -P anthropic/claude-opus-4 -B anthropic/claude-sonnet-4
119119
```
120120

121121
### Options
122122

123123
| Flag | Description |
124124
|------|-------------|
125-
| `-m, --model MODEL` | Model for both planning and build (provider/model format) |
126-
| `-P, --planning-model MODEL` | Model for planning/evaluation phases |
125+
| `-m, --model MODEL` | Model for both plan and build (provider/model format) |
126+
| `-P, --plan-model MODEL` | Model for plan/evaluation phases |
127127
| `-B, --build-model MODEL` | Model for build phase |
128128
| `-p, --project DIR` | Project directory (default: current directory) |
129129
| `-v, --verbose` | Enable verbose logging |
@@ -155,7 +155,7 @@ OpenCoder implements an **agentic development loop** with three phases:
155155
(start new cycle)
156156
```
157157

158-
1. **Planning Phase** - Analyzes the project and creates a markdown checklist with 3-7 actionable tasks
158+
1. **Plan Phase** - Analyzes the project and creates a markdown checklist with 3-7 actionable tasks
159159
2. **Build Phase** - Works through each task sequentially, making code changes
160160
3. **Evaluation Phase** - Reviews completed work and decides whether to start a new cycle (COMPLETE/NEEDS_WORK)
161161

@@ -169,7 +169,7 @@ Create an `opencoder.json` in your project directory:
169169

170170
```json
171171
{
172-
"planningModel": "anthropic/claude-sonnet-4",
172+
"planModel": "anthropic/claude-sonnet-4",
173173
"buildModel": "anthropic/claude-sonnet-4",
174174
"verbose": false,
175175
"maxRetries": 3,
@@ -182,7 +182,7 @@ Create an `opencoder.json` in your project directory:
182182
| Variable | Default | Description |
183183
|----------|---------|-------------|
184184
| `OPENCODER_PROJECT_DIR` | `$PWD` | Default project directory |
185-
| `OPENCODER_PLANNING_MODEL` | - | Model for planning phase |
185+
| `OPENCODER_PLAN_MODEL` | - | Model for plan phase |
186186
| `OPENCODER_BUILD_MODEL` | - | Model for build phase |
187187
| `OPENCODER_VERBOSE` | `false` | Enable verbose logging |
188188
| `OPENCODER_MAX_RETRIES` | `3` | Max retries per operation |
@@ -272,7 +272,7 @@ opencoder -m anthropic/claude-sonnet-4
272272
- **1 idea**: Uses it directly (no extra API call)
273273
- **2+ ideas**: AI evaluates all and picks the simplest/quick-win, considering dependencies
274274
3. **Build** - Selected idea is deleted, plan is created specifically for it
275-
4. **Fallback** - When ideas are exhausted, returns to autonomous planning
275+
4. **Fallback** - When ideas are exhausted, returns to autonomous plan
276276

277277
### Selection Criteria
278278

opencoder.json.example

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"planningModel": "anthropic/claude-sonnet-4",
3-
"executionModel": "anthropic/claude-sonnet-4",
2+
"planModel": "anthropic/claude-sonnet-4",
3+
"buildModel": "anthropic/claude-sonnet-4",
44
"verbose": false,
55
"maxRetries": 3,
66
"backoffBase": 10,

src/builder.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import type { Logger } from "./logger.ts"
88
import {
99
extractPlanFromResponse,
1010
generateEvaluationPrompt,
11-
generateIdeaPlanningPrompt,
11+
generateIdeaPlanPrompt,
1212
generateIdeaSelectionPrompt,
13-
generatePlanningPrompt,
13+
generatePlanPrompt,
1414
generateTaskPrompt,
1515
} from "./plan.ts"
1616
import type { BuildResult, Config } from "./types.ts"
@@ -68,12 +68,12 @@ export class Builder {
6868
}
6969

7070
/**
71-
* Run the planning phase
71+
* Run the plan phase
7272
*/
73-
async runPlanning(cycle: number, hint?: string): Promise<string> {
74-
this.logger.header(`CYCLE ${cycle} - PLANNING PHASE`)
73+
async runPlan(cycle: number, hint?: string): Promise<string> {
74+
this.logger.header(`CYCLE ${cycle} - PLAN PHASE`)
7575

76-
const prompt = generatePlanningPrompt(cycle, hint)
76+
const prompt = generatePlanPrompt(cycle, hint)
7777

7878
// Create a new session for this cycle
7979
const session = await this.client.session.create({
@@ -87,8 +87,8 @@ export class Builder {
8787
this.sessionId = session.data.id
8888
this.logger.logVerbose(`Created session: ${this.sessionId}`)
8989

90-
// Send the planning prompt
91-
const result = await this.sendPrompt(prompt, this.config.planningModel, "Planning")
90+
// Send the plan prompt
91+
const result = await this.sendPrompt(prompt, this.config.planModel, "Planning")
9292

9393
return extractPlanFromResponse(result)
9494
}
@@ -131,7 +131,7 @@ export class Builder {
131131

132132
const prompt = generateEvaluationPrompt(cycle, planContent)
133133

134-
return await this.sendPrompt(prompt, this.config.planningModel, "Evaluating")
134+
return await this.sendPrompt(prompt, this.config.planModel, "Evaluating")
135135
}
136136

137137
/**
@@ -156,7 +156,7 @@ export class Builder {
156156
const result = await this.sendPromptToSession(
157157
tempSessionId,
158158
prompt,
159-
this.config.planningModel,
159+
this.config.planModel,
160160
"Selecting",
161161
)
162162
return result
@@ -171,13 +171,13 @@ export class Builder {
171171
}
172172

173173
/**
174-
* Run planning for a specific idea
174+
* Run plan for a specific idea
175175
*/
176-
async runIdeaPlanning(ideaContent: string, ideaFilename: string, cycle: number): Promise<string> {
177-
this.logger.header(`CYCLE ${cycle} - IDEA PLANNING`)
176+
async runIdeaPlan(ideaContent: string, ideaFilename: string, cycle: number): Promise<string> {
177+
this.logger.header(`CYCLE ${cycle} - IDEA PLAN`)
178178
this.logger.info(`Planning for: ${ideaFilename}`)
179179

180-
const prompt = generateIdeaPlanningPrompt(ideaContent, ideaFilename, cycle)
180+
const prompt = generateIdeaPlanPrompt(ideaContent, ideaFilename, cycle)
181181

182182
// Create a new session for this cycle
183183
const session = await this.client.session.create({
@@ -191,7 +191,7 @@ export class Builder {
191191
this.sessionId = session.data.id
192192
this.logger.logVerbose(`Created session: ${this.sessionId}`)
193193

194-
const result = await this.sendPrompt(prompt, this.config.planningModel, "Planning")
194+
const result = await this.sendPrompt(prompt, this.config.planModel, "Planning")
195195

196196
return extractPlanFromResponse(result)
197197
}

src/cli.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,16 @@ export async function run(): Promise<void> {
2121
.version(VERSION)
2222
.argument("[hint]", "Optional hint/instruction for the AI")
2323
.option("-p, --project <dir>", "Project directory (default: current directory)")
24-
.option("-m, --model <model>", "Model for both planning and build (provider/model format)")
25-
.option("-P, --planning-model <model>", "Model for planning phase (provider/model format)")
24+
.option("-m, --model <model>", "Model for both plan and build (provider/model format)")
25+
.option("-P, --plan-model <model>", "Model for plan phase (provider/model format)")
2626
.option("-B, --build-model <model>", "Model for build phase (provider/model format)")
2727
.option("-v, --verbose", "Enable verbose logging")
2828
.action(async (hint: string | undefined, opts: Record<string, unknown>) => {
2929
try {
3030
const cliOptions: CliOptions = {
3131
project: opts.project as string | undefined,
3232
model: opts.model as string | undefined,
33-
planningModel: opts.planningModel as string | undefined,
33+
planModel: opts.planModel as string | undefined,
3434
buildModel: opts.buildModel as string | undefined,
3535
verbose: opts.verbose as boolean | undefined,
3636
}
@@ -49,33 +49,33 @@ export async function run(): Promise<void> {
4949
`
5050
Examples:
5151
$ opencoder --model anthropic/claude-sonnet-4
52-
Run with Claude Sonnet for both planning and build
52+
Run with Claude Sonnet for both plan and build
5353
5454
$ opencoder -m anthropic/claude-sonnet-4 "build a REST API"
5555
Run with a specific hint/instruction
5656
5757
$ opencoder -P anthropic/claude-opus-4 -B anthropic/claude-sonnet-4
58-
Use different models for planning and build
58+
Use different models for plan and build
5959
6060
$ opencoder -m openai/gpt-4o -p ./myproject -v
6161
Run with verbose logging in a specific directory
6262
6363
Options:
6464
-p, --project <dir> Project directory (default: current directory)
65-
-m, --model <model> Model for both planning and build
66-
-P, --planning-model Model for planning phase
65+
-m, --model <model> Model for both plan and build
66+
-P, --plan-model Model for plan phase
6767
-B, --build-model Model for build phase
6868
-v, --verbose Enable verbose logging
6969
7070
Environment variables:
71-
OPENCODER_PLANNING_MODEL Default planning model
71+
OPENCODER_PLAN_MODEL Default plan model
7272
OPENCODER_BUILD_MODEL Default build model
7373
OPENCODER_VERBOSE Enable verbose logging (true/1)
7474
OPENCODER_PROJECT_DIR Default project directory
7575
7676
Config file (opencoder.json):
7777
{
78-
"planningModel": "anthropic/claude-sonnet-4",
78+
"planModel": "anthropic/claude-sonnet-4",
7979
"buildModel": "anthropic/claude-sonnet-4",
8080
"verbose": false
8181
}

0 commit comments

Comments
 (0)